Break DS80C390 support into seperate port (ds390); first pass at spilling temporaries...
authorkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Fri, 18 Aug 2000 20:15:05 +0000 (20:15 +0000)
committerkvigor <kvigor@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Fri, 18 Aug 2000 20:15:05 +0000 (20:15 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@318 4a8a32a2-be11-0410-ad9d-d568d2c75423

14 files changed:
src/SDCCcse.c
src/SDCCicode.c
src/SDCCmain.c
src/SDCCsymt.c
src/ds390/Makefile [new file with mode: 0644]
src/ds390/Makefile.bcc [new file with mode: 0644]
src/ds390/clean.mk [new file with mode: 0644]
src/ds390/gen.c [new file with mode: 0644]
src/ds390/gen.h [new file with mode: 0644]
src/ds390/main.c [new file with mode: 0644]
src/ds390/main.h [new file with mode: 0644]
src/ds390/peeph.def [new file with mode: 0644]
src/ds390/ralloc.c [new file with mode: 0644]
src/ds390/ralloc.h [new file with mode: 0644]

index f1f91676390e9b37b5464ace1984b9c06fde63b6..72129a291e2a34ff0a73cce002c24b3b20d77534 100644 (file)
@@ -1114,6 +1114,15 @@ DEFSETFUNC(delGetPointerSucc)
 static void fixUpTypes(iCode *ic)
 {
        link *t1 = operandType(IC_LEFT(ic)) ,*t2;
+       
+       extern PORT ds390_port;
+       
+       if (port == &ds390_port)
+       {
+           /* hack-o-matic! */
+           return;
+       }
+       
        /* for pointer_gets if the types of result & left r the
           same then change it type of result to next */
        if (IS_PTR(t1) &&
index 287379af13c31ca8229cfcd88c749fabd4bf61ab..2704b942ec9e9630f20e828ce24f75276b8ae070 100644 (file)
@@ -751,8 +751,10 @@ bool isOperandInFarSpace (operand *op)
        else            
            return FALSE;
     }
-
-    etype = getSpec(operandType(op));
+    else
+    {
+       etype = getSpec(operandType(op));
+    }
     return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
 }
 
@@ -2339,8 +2341,9 @@ static void geniCodeParms ( ast *parms , int *stack, link *fetype)
     }
 
     /* if register parm then make it a send */
-    if ((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
-       IS_REGPARM(parms->etype)) {
+    if (((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
+       IS_REGPARM(parms->etype)) && 
+       !IS_RENT(fetype)) {
        ic = newiCode(SEND,pval,NULL);
        ADDTOCHAIN(ic);
     } else {
index 4e32a37eb710193db9e0f0e15dc0971b6c79809e..3becb08b915e34005430c518b5f8cc8ec6f91b7f 100644 (file)
@@ -143,6 +143,10 @@ extern PORT z80_port;
 #if !OPT_DISABLE_AVR
 extern PORT avr_port;
 #endif
+#if !OPT_DISABLE_DS390
+extern PORT ds390_port;
+#endif
+
 
 PORT *port;
 
@@ -159,6 +163,9 @@ static PORT *_ports[] = {
 #if !OPT_DISABLE_AVR
     &avr_port,
 #endif
+#if !OPT_DISABLE_DS390
+    &ds390_port,
+#endif
 };
 
 #define NUM_PORTS (sizeof(_ports)/sizeof(_ports[0]))
index 33585fddb57f580bbc1a9bee09354c91d9dd0614..02fad1ff6f0940058bf71e62b7c4c5b672624ee2 100644 (file)
@@ -1019,8 +1019,8 @@ static void  checkSClass ( symbol *sym )
            SPEC_SCLS(sym->etype) = (options.useXstack  ?
                                     S_XSTACK : S_STACK ) ;
        else
-           SPEC_SCLS(sym->etype) = (options.useXstack  ?
-                                    S_XDATA :S_DATA ) ;
+           SPEC_SCLS(sym->etype) = (options.model  ?
+                                    S_XDATA : S_DATA ) ;
     }
 }
 
diff --git a/src/ds390/Makefile b/src/ds390/Makefile
new file mode 100644 (file)
index 0000000..41682ed
--- /dev/null
@@ -0,0 +1,23 @@
+PRJDIR = ../..
+
+include $(PRJDIR)/Makefile.common
+
+OBJ = gen.o ralloc.o main.o
+LIB = port.a
+
+CFLAGS = -g -Wall -O2
+CFLAGS += -I.. -I. -I../..
+
+all: $(LIB)
+
+main.o: main.c peeph.rul
+
+$(LIB): peeph.rul $(OBJ)
+       rm -f $(LIB)
+       ar r $(LIB) $(OBJ)
+       $(RANLIB) $(LIB)
+
+peeph.rul: peeph.def
+       $(AWK) -f ../SDCCpeeph.awk peeph.def > peeph.rul
+
+include clean.mk
diff --git a/src/ds390/Makefile.bcc b/src/ds390/Makefile.bcc
new file mode 100644 (file)
index 0000000..4b17a92
--- /dev/null
@@ -0,0 +1,22 @@
+PRJDIR = ../..
+
+# !include $(PRJDIR)/Makefile.common
+
+OBJ = gen.obj ralloc.obj main.obj
+LIB = port.lib
+
+!include ..\..\Bcc.inc
+CFLAGS  = -I.. -I. -I..\.. -I..\..\support
+
+all: $(LIB)
+
+main.obj: main.c peeph.rul
+
+$(LIB): peeph.rul $(OBJ)
+       del $(LIB)
+       tlib /a $(LIB) +gen.obj +ralloc.obj +main.obj
+       
+peeph.rul: peeph.def
+        gawk -f ../SDCCpeeph.awk peeph.def > peeph.rul
+
+# include clean.mk
diff --git a/src/ds390/clean.mk b/src/ds390/clean.mk
new file mode 100644 (file)
index 0000000..07f3ca4
--- /dev/null
@@ -0,0 +1,6 @@
+#
+
+clean:
+       rm -f $(LIB) *.o *~ port.a
+
+# End of src/mcs51/clean.mk
diff --git a/src/ds390/gen.c b/src/ds390/gen.c
new file mode 100644 (file)
index 0000000..4386eb0
--- /dev/null
@@ -0,0 +1,8089 @@
+/*-------------------------------------------------------------------------
+  gen.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)
+  Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
+  
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+  
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  
+  In other words, you are welcome to use, share and improve this program.
+  You are forbidden to forbid anyone else to use, share and improve
+  what you give them.   Help stamp out software-hoarding!
+  
+  Notes:
+  000123 mlh   Moved aopLiteral to SDCCglue.c to help the split
+               Made everything static
+-------------------------------------------------------------------------*/
+
+#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>
+#else
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#else
+#ifndef __BORLANDC__
+#warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
+#warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
+#endif
+#endif
+#endif
+
+#include "common.h"
+#include "SDCCpeeph.h"
+#include "ralloc.h"
+#include "gen.h"
+
+char *aopLiteral (value *val, int offset);
+extern int allocInfo;
+
+/* 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 ;
+
+#define D(x) x
+
+unsigned fReturnSize_390 = 5; /* shared with ralloc.c */
+static char *fReturn[] = {"dpl","dph","dpx", "b","a" };
+static char *accUse[] = {"a","b"};
+
+static short rbank = -1;
+
+static struct {
+    short r0Pushed;
+    short r1Pushed;
+    short accInUse;
+    short inLine;
+    short debugLine;
+    short nRegsSaved;
+    set *sendSet;
+} _G;
+
+extern int ds390_ptrRegReq ;
+extern int ds390_nRegs;
+extern FILE *codeOutFile;
+static void saverbank (int, iCode *,bool);
+#define RESULTONSTACK(x) \
+                         (IC_RESULT(x) && IC_RESULT(x)->aop && \
+                         IC_RESULT(x)->aop->type == AOP_STK )
+
+/* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */
+#define MOVA(x) { char *_mova_tmp = strdup(x); \
+                 if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \
+                 { \
+                    emitcode("mov","a,%s",_mova_tmp); \
+                 } \
+                 free(_mova_tmp); \
+                }
+#define CLRC    emitcode("clr","c");
+
+static lineNode *lineHead = NULL;
+static lineNode *lineCurr = NULL;
+
+static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
+0xE0, 0xC0, 0x80, 0x00};
+static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
+0x07, 0x03, 0x01, 0x00};
+
+#define LSB     0
+#define MSB16   1
+#define MSB24   2
+#define MSB32   3
+
+/*-----------------------------------------------------------------*/
+/* emitcode - writes the code into a file : for now it is simple    */
+/*-----------------------------------------------------------------*/
+static void emitcode (char *inst,char *fmt, ...)
+{
+    va_list ap;
+    char lb[MAX_INLINEASM];  
+    char *lbp = lb;
+
+    va_start(ap,fmt);   
+
+    if (inst && *inst) {
+       if (fmt && *fmt)
+           sprintf(lb,"%s\t",inst);
+       else
+           sprintf(lb,"%s",inst);
+        vsprintf(lb+(strlen(lb)),fmt,ap);
+    }  else
+        vsprintf(lb,fmt,ap);
+
+    while (isspace(*lbp)) lbp++;
+
+    if (lbp && *lbp) 
+        lineCurr = (lineCurr ?
+                    connectLine(lineCurr,newLineNode(lb)) :
+                    (lineHead = newLineNode(lb)));
+    lineCurr->isInline = _G.inLine;
+    lineCurr->isDebug  = _G.debugLine;
+    va_end(ap);
+}
+
+/*-----------------------------------------------------------------*/
+/* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
+/*-----------------------------------------------------------------*/
+static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
+{
+    bool r0iu = FALSE , r1iu = FALSE;
+    bool r0ou = FALSE , r1ou = FALSE;
+
+    /* the logic: if r0 & r1 used in the instruction
+    then we are in trouble otherwise */
+
+    /* first check if r0 & r1 are used by this
+    instruction, in which case we are in trouble */
+    if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
+        (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
+    {
+        goto endOfWorld;      
+    }
+
+    r0ou = bitVectBitValue(ic->rMask,R0_IDX);
+    r1ou = bitVectBitValue(ic->rMask,R1_IDX);
+
+    /* if no usage of r0 then return it */
+    if (!r0iu && !r0ou) {
+        ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
+        (*aopp)->type = AOP_R0;
+        
+        return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
+    }
+
+    /* if no usage of r1 then return it */
+    if (!r1iu && !r1ou) {
+        ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
+        (*aopp)->type = AOP_R1;
+
+        return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R1_IDX);
+    }    
+
+    /* now we know they both have usage */
+    /* if r0 not used in this instruction */
+    if (!r0iu) {
+        /* push it if not already pushed */
+        if (!_G.r0Pushed) {
+            emitcode ("push","%s",
+                      ds390_regWithIdx(R0_IDX)->dname);
+            _G.r0Pushed++ ;
+        }
+        
+        ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
+        (*aopp)->type = AOP_R0;
+
+        return (*aopp)->aopu.aop_ptr = ds390_regWithIdx(R0_IDX);
+    }
+
+    /* if r1 not used then */
+
+    if (!r1iu) {
+        /* push it if not already pushed */
+        if (!_G.r1Pushed) {
+            emitcode ("push","%s",
+                      ds390_regWithIdx(R1_IDX)->dname);
+            _G.r1Pushed++ ;
+        }
+        
+        ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
+        (*aopp)->type = AOP_R1;
+        return ds390_regWithIdx(R1_IDX);
+    }
+
+endOfWorld :
+    /* I said end of world but not quite end of world yet */
+    /* if this is a result then we can push it on the stack*/
+    if (result) {
+        (*aopp)->type = AOP_STK;    
+        return NULL;
+    }
+
+    piCode(ic,stdout);
+    /* other wise this is true end of the world */
+    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+           "getFreePtr should never reach here");
+    exit(0);
+}
+
+/*-----------------------------------------------------------------*/
+/* newAsmop - creates a new asmOp                                  */
+/*-----------------------------------------------------------------*/
+static asmop *newAsmop (short type)
+{
+    asmop *aop;
+
+    ALLOC(aop,sizeof(asmop));
+    aop->type = type;
+    return aop;
+}
+
+static void genSetDPTR(int n)
+{
+    if (!n)
+    {
+        emitcode(";", "Select standard DPTR");
+        emitcode("mov", "dps, #0x00");
+    }
+    else
+    {
+        emitcode(";", "Select alternate DPTR");
+        emitcode("mov", "dps, #0x01");
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* pointerCode - returns the code for a pointer type               */
+/*-----------------------------------------------------------------*/
+static int pointerCode (link *etype)
+{
+
+    return PTR_TYPE(SPEC_OCLS(etype));
+
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForSym - for a true symbol                                   */
+/*-----------------------------------------------------------------*/
+static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool useDP2)
+{
+    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 it is on the stack or indirectly addressable */
+    /* space we need to assign either r0 or r1 to it   */    
+    if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
+        sym->aop = aop = newAsmop(0);
+        aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
+        aop->size = getSize(sym->type);
+
+        /* now assign the address of the variable to 
+        the pointer register */
+        if (aop->type != AOP_STK) {
+
+            if (sym->onStack) {
+                    if ( _G.accInUse )
+                        emitcode("push","acc");
+
+                    emitcode("mov","a,_bp");
+                    emitcode("add","a,#0x%02x",
+                             ((sym->stack < 0) ?
+                             ((char)(sym->stack - _G.nRegsSaved )) :
+                             ((char)sym->stack)) & 0xff);
+                    emitcode("mov","%s,a",
+                             aop->aopu.aop_ptr->name);
+
+                    if ( _G.accInUse )
+                        emitcode("pop","acc");
+            } else
+                emitcode("mov","%s,#%s",
+                         aop->aopu.aop_ptr->name,
+                         sym->rname);
+            aop->paged = space->paged;
+        } else
+            aop->aopu.aop_stk = sym->stack;
+        return aop;
+    }
+    
+    if (sym->onStack && options.stack10bit)
+    {
+        /* It's on the 10 bit stack, which is located in
+         * far data space.
+         */
+         
+        if ( _G.accInUse )
+               emitcode("push","acc");
+
+        emitcode("mov","a,_bp");
+        emitcode("add","a,#0x%02x",
+                 ((sym->stack < 0) ?
+                   ((char)(sym->stack - _G.nRegsSaved )) :
+                   ((char)sym->stack)) & 0xff);
+        
+       if (useDP2)
+       {        
+        genSetDPTR(1);
+        emitcode ("mov","dpx1,#0x40");
+        emitcode ("mov","dph1,#0x00");
+        emitcode ("mov","dpl1, a");
+        genSetDPTR(0);
+        }
+        else
+        {
+           emitcode ("mov","dpx,#0x40");
+            emitcode ("mov","dph,#0x00");
+            emitcode ("mov","dpl, a");           
+        }
+       
+        if ( _G.accInUse )
+            emitcode("pop","acc");
+            
+        sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
+       aop->size = getSize(sym->type); 
+       return aop;
+    }
+
+    /* if in bit space */
+    if (IN_BITSPACE(space)) {
+        sym->aop = aop = newAsmop (AOP_CRY);
+        aop->aopu.aop_dir = sym->rname ;
+        aop->size = getSize(sym->type);
+        return aop;
+    }
+    /* if it is in direct space */
+    if (IN_DIRSPACE(space)) {
+        sym->aop = aop = newAsmop (AOP_DIR);
+        aop->aopu.aop_dir = sym->rname ;
+        aop->size = getSize(sym->type);
+        return aop;
+    }
+
+    /* 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 = FPTRSIZE; 
+        return aop;
+    }
+
+    /* only remaining is far space */
+    /* in which case DPTR gets the address */
+    sym->aop = aop = newAsmop(useDP2 ? AOP_DPTR2 : AOP_DPTR);
+    if (useDP2)
+    {        
+        genSetDPTR(1);
+    emitcode ("mov","dptr,#%s", sym->rname);
+        genSetDPTR(0);
+    }    
+    else
+    {
+       emitcode ("mov","dptr,#%s", sym->rname);
+    }
+    aop->size = getSize(sym->type);
+
+    /* if it is in code space */
+    if (IN_CODESPACE(space))
+        aop->code = 1;
+
+    return aop;     
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForRemat - rematerialzes an object                           */
+/*-----------------------------------------------------------------*/
+static asmop *aopForRemat (symbol *sym)
+{
+    iCode *ic = sym->rematiCode;
+    asmop *aop = newAsmop(AOP_IMMD);
+
+    int val = 0;
+
+    for (;;) {
+       if (ic->op == '+')
+           val += operandLitValue(IC_RIGHT(ic));
+       else if (ic->op == '-')
+           val -= operandLitValue(IC_RIGHT(ic));
+       else
+           break;
+       
+       ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
+    }
+
+    if (val)
+       sprintf(buffer,"(%s %c 0x%04x)",
+               OP_SYMBOL(IC_LEFT(ic))->rname, 
+               val >= 0 ? '+' : '-',
+               abs(val) & 0xffff);
+    else
+       strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
+
+    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       */
+/*-----------------------------------------------------------------*/
+static bool regsInCommon (operand *op1, operand *op2)
+{
+    symbol *sym1, *sym2;
+    int i;
+
+    /* if they have registers in common */
+    if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
+        return FALSE ;
+
+    sym1 = OP_SYMBOL(op1);
+    sym2 = OP_SYMBOL(op2);
+
+    if (sym1->nRegs == 0 || sym2->nRegs == 0)
+        return FALSE ;
+
+    for (i = 0 ; i < sym1->nRegs ; i++) {
+        int j;
+        if (!sym1->regs[i])
+            continue ;
+
+        for (j = 0 ; j < sym2->nRegs ;j++ ) {
+            if (!sym2->regs[j])
+                continue ;
+
+            if (sym2->regs[j] == sym1->regs[i])
+                return TRUE ;
+        }
+    }
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* operandsEqu - equivalent                                        */
+/*-----------------------------------------------------------------*/
+static bool operandsEqu ( operand *op1, operand *op2)
+{
+    symbol *sym1, *sym2;
+
+    /* if they not symbols */
+    if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
+        return FALSE;
+
+    sym1 = OP_SYMBOL(op1);
+    sym2 = OP_SYMBOL(op2);
+
+    /* if both are itemps & one is spilt
+       and the other is not then false */
+    if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
+       sym1->isspilt != sym2->isspilt )
+       return FALSE ;
+
+    /* if they are the same */
+    if (sym1 == sym2)
+        return TRUE ;
+
+    if (strcmp(sym1->rname,sym2->rname) == 0)
+        return TRUE;
+
+
+    /* if left is a tmp & right is not */
+    if (IS_ITEMP(op1)  && 
+        !IS_ITEMP(op2) &&
+        sym1->isspilt  &&
+        (sym1->usl.spillLoc == sym2))
+        return TRUE;
+
+    if (IS_ITEMP(op2)  && 
+        !IS_ITEMP(op1) &&
+        sym2->isspilt  &&
+       sym1->level > 0 &&
+        (sym2->usl.spillLoc == sym1))
+        return TRUE ;
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* sameRegs - two asmops have the same registers                   */
+/*-----------------------------------------------------------------*/
+static bool sameRegs (asmop *aop1, asmop *aop2 )
+{
+    int i;
+
+    if (aop1 == aop2)
+    {
+        if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
+        {
+            return FALSE;
+        }
+        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, bool useDP2)
+{
+    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, useDP2);
+        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 < fReturnSize_390 ; i++ )
+                aop->aopu.aop_str[i] = fReturn[i];
+            return;
+        }
+
+        /* else spill location  */
+        sym->aop = op->aop = aop = 
+               aopForSym(ic,sym->usl.spillLoc,result, useDP2);
+        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, bool pop)
+{   
+    asmop *aop ;
+
+    if (!op)
+        aop = aaop;
+    else 
+        aop = op->aop;
+
+    if (!aop)
+        return ;
+
+    if (aop->freed)
+        goto dealloc; 
+
+    aop->freed = 1;
+
+    /* depending on the asmop type only three cases need work AOP_RO
+       , AOP_R1 && AOP_STK */
+    switch (aop->type) {
+        case AOP_R0 :
+            if (_G.r0Pushed ) {
+                if (pop) {
+                    emitcode ("pop","ar0");     
+                    _G.r0Pushed--;
+                }
+            }
+            bitVectUnSetBit(ic->rUsed,R0_IDX);
+            break;
+
+        case AOP_R1 :
+            if (_G.r1Pushed ) {
+                if (pop) {
+                    emitcode ("pop","ar1");
+                    _G.r1Pushed--;
+                }
+            }
+            bitVectUnSetBit(ic->rUsed,R1_IDX);          
+            break;
+
+        case AOP_STK :
+        {
+            int sz = aop->size;    
+            int stk = aop->aopu.aop_stk + aop->size;
+            bitVectUnSetBit(ic->rUsed,R0_IDX);
+            bitVectUnSetBit(ic->rUsed,R1_IDX);          
+
+            getFreePtr(ic,&aop,FALSE);
+            
+            if (options.stack10bit)
+            {
+                /* I'm not sure what to do here yet... */
+                /* #STUB */
+               fprintf(stderr, 
+                       "*** Warning: probably generating bad code for "
+                       "10 bit stack mode.\n");
+            }
+            
+            if (stk) {
+                emitcode ("mov","a,_bp");
+                emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
+                emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
+            } else {
+                emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
+            }
+
+            while (sz--) {
+                emitcode("pop","acc");
+                emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
+                if (!sz) break;
+                emitcode("dec","%s",aop->aopu.aop_ptr->name);
+            }
+            op->aop = aop;
+            freeAsmop(op,NULL,ic,TRUE);
+            if (_G.r0Pushed) {
+                emitcode("pop","ar0");
+                _G.r0Pushed--;
+            }
+
+            if (_G.r1Pushed) {
+                emitcode("pop","ar1");
+                _G.r1Pushed--;
+            }       
+        }
+    }
+
+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;
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* aopGet - for fetching value of the aop                          */
+/*-----------------------------------------------------------------*/
+static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
+{
+    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_R0:
+    case AOP_R1:
+       /* if we need to increment it */       
+       while (offset > aop->coff) {        
+           emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
+           aop->coff++;
+       }
+       
+       while (offset < aop->coff) {
+           emitcode("dec","%s",aop->aopu.aop_ptr->name);
+           aop->coff--;
+       }
+       
+       aop->coff = offset ;
+       if (aop->paged) {
+           emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
+           return (dname ? "acc" : "a");
+       }       
+       sprintf(s,"@%s",aop->aopu.aop_ptr->name);
+       ALLOC_ATOMIC(rs,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_DPTR:
+    case AOP_DPTR2:
+    
+    if (aop->type == AOP_DPTR2)
+    {
+        genSetDPTR(1);
+        emitcode("xch", "a, ap");
+    }
+    
+       while (offset > aop->coff) {
+           emitcode ("inc","dptr");
+           aop->coff++;
+       }
+       
+       while (offset < aop->coff) {        
+           emitcode("lcall","__decdptr");
+           aop->coff--;
+       }
+       
+       aop->coff = offset;
+       if (aop->code) {
+           emitcode("clr","a");
+           emitcode("movc","a,@a+dptr");
+        }
+    else {
+           emitcode("movx","a,@dptr");
+    }
+           
+    if (aop->type == AOP_DPTR2)
+    {
+        emitcode("xch", "a, ap");
+        genSetDPTR(0);
+        return "ap";
+    }
+           
+    return (dname ? "acc" : "a");
+       
+       
+    case AOP_IMMD:
+       if (bit16) 
+           sprintf (s,"#%s",aop->aopu.aop_immd);
+       else
+           if (offset) 
+               sprintf(s,"#(%s >> %d)",
+                       aop->aopu.aop_immd,
+                       offset*8);
+           else
+               sprintf(s,"#%s",
+                       aop->aopu.aop_immd);
+       ALLOC_ATOMIC(rs,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_DIR:
+       if (offset)
+           sprintf(s,"(%s + %d)",
+                   aop->aopu.aop_dir,
+                   offset);
+       else
+           sprintf(s,"%s",aop->aopu.aop_dir);
+       ALLOC_ATOMIC(rs,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_REG:
+       if (dname) 
+           return aop->aopu.aop_reg[offset]->dname;
+       else
+           return aop->aopu.aop_reg[offset]->name;
+       
+    case AOP_CRY:
+       emitcode("clr","a");
+       emitcode("mov","c,%s",aop->aopu.aop_dir);
+       emitcode("rlc","a") ;
+       return (dname ? "acc" : "a");
+       
+    case AOP_ACC:
+       if (!offset && dname)
+           return "acc";
+       return aop->aopu.aop_str[offset];
+
+    case AOP_LIT:
+       return aopLiteral (aop->aopu.aop_lit,offset);
+       
+    case AOP_STR:
+       aop->coff = offset ;
+       if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
+           dname)
+           return "acc";
+       
+       return aop->aopu.aop_str[offset];
+       
+    }
+
+    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+           "aopget got unsupported aop->type");
+    exit(0);
+}
+/*-----------------------------------------------------------------*/
+/* aopPut - puts a string for a aop                                */
+/*-----------------------------------------------------------------*/
+static void aopPut (asmop *aop, char *s, int offset)
+{
+    char *d = buffer ;
+    symbol *lbl ;
+
+    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:
+       if (offset)
+           sprintf(d,"(%s + %d)",
+                   aop->aopu.aop_dir,offset);
+       else
+           sprintf(d,"%s",aop->aopu.aop_dir);
+       
+       if (strcmp(d,s))
+           emitcode("mov","%s,%s",d,s);
+       
+       break;
+       
+    case AOP_REG:
+       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0 &&
+           strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
+           if (*s == '@'           ||
+               strcmp(s,"r0") == 0 ||
+               strcmp(s,"r1") == 0 ||
+               strcmp(s,"r2") == 0 ||
+               strcmp(s,"r3") == 0 ||
+               strcmp(s,"r4") == 0 ||
+               strcmp(s,"r5") == 0 ||
+               strcmp(s,"r6") == 0 || 
+               strcmp(s,"r7") == 0 )
+               emitcode("mov","%s,%s",
+                        aop->aopu.aop_reg[offset]->dname,s);
+           else
+               emitcode("mov","%s,%s",
+                        aop->aopu.aop_reg[offset]->name,s);
+       }
+       break;
+       
+    case AOP_DPTR:
+    case AOP_DPTR2:
+    
+    if (aop->type == AOP_DPTR2)
+    {
+        genSetDPTR(1);
+    }
+    
+       if (aop->code) {
+           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+                  "aopPut writting to code space");
+           exit(0);
+       }
+       
+       while (offset > aop->coff) {
+           aop->coff++;
+           emitcode ("inc","dptr");
+       }
+       
+       while (offset < aop->coff) {
+           aop->coff-- ;
+           emitcode("lcall","__decdptr");
+       }
+       
+       aop->coff = offset;
+       
+       /* if not in accumulater */
+       MOVA(s);        
+       
+       emitcode ("movx","@dptr,a");
+       
+    if (aop->type == AOP_DPTR2)
+    {
+        genSetDPTR(0);
+    }
+       break;
+       
+    case AOP_R0:
+    case AOP_R1:
+       while (offset > aop->coff) {
+           aop->coff++;
+           emitcode("inc","%s",aop->aopu.aop_ptr->name);
+       }
+       while (offset < aop->coff) {
+           aop->coff-- ;
+           emitcode ("dec","%s",aop->aopu.aop_ptr->name);
+       }
+       aop->coff = offset;
+       
+       if (aop->paged) {
+           MOVA(s);           
+           emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
+           
+       } else
+           if (*s == '@') {
+               MOVA(s);
+               emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
+           } else
+               if (strcmp(s,"r0") == 0 ||
+                   strcmp(s,"r1") == 0 ||
+                   strcmp(s,"r2") == 0 ||
+                   strcmp(s,"r3") == 0 ||
+                   strcmp(s,"r4") == 0 ||
+                   strcmp(s,"r5") == 0 ||
+                   strcmp(s,"r6") == 0 || 
+                   strcmp(s,"r7") == 0 ) {
+                   char buffer[10];
+                   sprintf(buffer,"a%s",s);
+                   emitcode("mov","@%s,%s",
+                            aop->aopu.aop_ptr->name,buffer);
+               } else
+                   emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
+       
+       break;
+       
+    case AOP_STK:
+       if (strcmp(s,"a") == 0)
+           emitcode("push","acc");
+       else
+           emitcode("push","%s",s);
+       
+       break;
+       
+    case AOP_CRY:
+       /* if bit variable */
+       if (!aop->aopu.aop_dir) {
+           emitcode("clr","a");
+           emitcode("rlc","a");
+       } else {
+           if (s == zero) 
+               emitcode("clr","%s",aop->aopu.aop_dir);
+           else
+               if (s == one)
+                   emitcode("setb","%s",aop->aopu.aop_dir);
+               else
+                   if (!strcmp(s,"c"))
+                       emitcode("mov","%s,c",aop->aopu.aop_dir);
+                   else {
+                       lbl = newiTempLabel(NULL);
+                       
+                       if (strcmp(s,"a")) {
+                           MOVA(s);
+                       }
+                       emitcode("clr","c");
+                       emitcode("jz","%05d$",lbl->key+100);
+                       emitcode("cpl","c");
+                       emitcode("","%05d$:",lbl->key+100);
+                       emitcode("mov","%s,c",aop->aopu.aop_dir);
+                   }
+       }
+       break;
+       
+    case AOP_STR:
+       aop->coff = offset;
+       if (strcmp(aop->aopu.aop_str[offset],s))
+           emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
+       break;
+       
+    case AOP_ACC:
+       aop->coff = offset;
+       if (!offset && (strcmp(s,"acc") == 0))
+           break;
+       
+       if (strcmp(aop->aopu.aop_str[offset],s))
+           emitcode ("mov","%s,%s",aop->aopu.aop_str[offset],s);
+       break;
+
+    default :
+       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+              "aopPut got unsupported aop->type");
+       exit(0);    
+    }    
+
+}
+
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* pointToEnd :- points to the last byte of the operand            */
+/*-----------------------------------------------------------------*/
+static void pointToEnd (asmop *aop)
+{
+    int count ;
+    if (!aop)
+        return ;
+
+    aop->coff = count = (aop->size - 1);
+    switch (aop->type) {
+        case AOP_R0 :
+        case AOP_R1 :
+            while (count--)
+                emitcode("inc","%s",aop->aopu.aop_ptr->name);
+            break;
+        case AOP_DPTR :
+            while (count--)
+                emitcode("inc","dptr");
+            break;
+    }
+
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* reAdjustPreg - points a register back to where it should        */
+/*-----------------------------------------------------------------*/
+static void reAdjustPreg (asmop *aop)
+{
+    int size ;
+
+    aop->coff = 0;
+    if ((size = aop->size) <= 1)
+        return ;
+    size-- ;
+    switch (aop->type) {
+        case AOP_R0 :
+        case AOP_R1 :
+            while (size--)
+                emitcode("dec","%s",aop->aopu.aop_ptr->name);
+            break;          
+        case AOP_DPTR :
+        case AOP_DPTR2:
+            if (aop->type == AOP_DPTR2)
+           {
+                genSetDPTR(1);
+           } 
+            while (size--)
+            {
+                emitcode("lcall","__decdptr");
+            }
+                
+           if (aop->type == AOP_DPTR2)
+           {
+                genSetDPTR(0);
+           }                
+            break;  
+
+    }   
+
+}
+
+#define AOP(op) op->aop
+#define AOP_TYPE(op) AOP(op)->type
+#define AOP_SIZE(op) AOP(op)->size
+#define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
+                       AOP_TYPE(x) == AOP_R0))
+
+#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
+                        AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
+                         AOP(x)->paged)) 
+
+#define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
+                      (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
+                      x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
+
+/*-----------------------------------------------------------------*/
+/* genNotFloat - generates not for float operations              */
+/*-----------------------------------------------------------------*/
+static void genNotFloat (operand *op, operand *res)
+{
+    int size, offset;
+    char *l;
+    symbol *tlbl ;
+
+    D(emitcode(";", "genNotFloat "););
+
+    /* we will put 127 in the first byte of 
+    the result */
+    aopPut(AOP(res),"#127",0);
+    size = AOP_SIZE(op) - 1;
+    offset = 1;
+
+    l = aopGet(op->aop,offset++,FALSE,FALSE);
+    MOVA(l);    
+
+    while(size--) {
+        emitcode("orl","a,%s",
+                 aopGet(op->aop,
+                        offset++,FALSE,FALSE));
+    }
+    tlbl = newiTempLabel(NULL);
+
+    tlbl = newiTempLabel(NULL);
+    aopPut(res->aop,one,1);
+    emitcode("jz","%05d$",(tlbl->key+100));
+    aopPut(res->aop,zero,1);
+    emitcode("","%05d$:",(tlbl->key+100));
+
+    size = res->aop->size - 2;
+    offset = 2;    
+    /* put zeros in the rest */
+    while (size--) 
+        aopPut(res->aop,zero,offset++);
+}
+
+/*-----------------------------------------------------------------*/
+/* opIsGptr: returns non-zero if the passed operand is            */   
+/* a generic pointer type.                                        */
+/*-----------------------------------------------------------------*/ 
+static int opIsGptr(operand *op)
+{
+    link *type = operandType(op);
+    
+    if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
+    {
+        return 1;
+    }
+    return 0;        
+}
+
+/*-----------------------------------------------------------------*/
+/* getDataSize - get the operand data size                         */
+/*-----------------------------------------------------------------*/
+static int getDataSize(operand *op)
+{
+    int size;
+    size = AOP_SIZE(op);
+    if (size == GPTRSIZE)
+    {
+        link *type = operandType(op);
+        if (IS_GENPTR(type))
+        {
+            /* generic pointer; arithmetic operations
+             * should ignore the high byte (pointer type).
+             */
+            size--;
+        }
+    }
+    return size;
+}
+
+/*-----------------------------------------------------------------*/
+/* outAcc - output Acc                                             */
+/*-----------------------------------------------------------------*/
+static 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++);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* outBitC - output a bit C                                        */
+/*-----------------------------------------------------------------*/
+static void outBitC(operand *result)
+{
+    /* if the result is bit */
+    if (AOP_TYPE(result) == AOP_CRY) 
+        aopPut(AOP(result),"c",0);
+    else {
+        emitcode("clr","a");
+        emitcode("rlc","a");
+        outAcc(result);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* toBoolean - emit code for orl a,operator(sizeop)                */
+/*-----------------------------------------------------------------*/
+static void toBoolean(operand *oper)
+{
+    int size = AOP_SIZE(oper) - 1;
+    int offset = 1;
+
+    if (AOP_NEEDSACC(oper))
+    {
+        emitcode("push", "b");
+        emitcode("mov", "b, %s", aopGet(AOP(oper),0,FALSE,FALSE));
+    }
+    else
+    {
+    MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
+    }
+    while (size--) 
+    {
+       if (AOP_NEEDSACC(oper))
+       {
+           emitcode("orl","b,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
+       }
+       else
+       {
+        emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
+}
+    }
+    
+    if (AOP_NEEDSACC(oper))
+    {
+        emitcode("mov", "a,b");
+        emitcode("pop", "b");
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genNot - generate code for ! operation                          */
+/*-----------------------------------------------------------------*/
+static void genNot (iCode *ic)
+{
+    symbol *tlbl;
+    link *optype = operandType(IC_LEFT(ic));
+
+    D(emitcode(";", "genNot "););
+
+    /* assign asmOps to operand & result */
+    aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
+    aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
+
+    /* if in bit space then a special case */
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
+        emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
+        emitcode("cpl","c"); 
+        outBitC(IC_RESULT(ic));
+        goto release;
+    }
+
+    /* if type float then do float */
+    if (IS_FLOAT(optype)) {
+        genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
+        goto release;
+    }
+
+    toBoolean(IC_LEFT(ic));
+
+    tlbl = newiTempLabel(NULL);
+    emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
+    emitcode("","%05d$:",tlbl->key+100);
+    outBitC(IC_RESULT(ic));
+
+release:    
+    /* release the aops */
+    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
+    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genCpl - generate code for complement                           */
+/*-----------------------------------------------------------------*/
+static void genCpl (iCode *ic)
+{
+    int offset = 0;
+    int size ;
+
+    D(emitcode(";", "genCpl "););
+
+
+    /* assign asmOps to operand & result */
+    aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
+    aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
+
+    /* 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 ) { 
+
+        emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
+        emitcode("cpl","c"); 
+        emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
+        goto release; 
+    } 
+
+    size = AOP_SIZE(IC_RESULT(ic));
+    while (size--) {
+        char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
+        MOVA(l);       
+        emitcode("cpl","a");
+        aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+    }
+
+
+release:
+    /* release the aops */
+    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
+    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genUminusFloat - unary minus for floating points                */
+/*-----------------------------------------------------------------*/
+static void genUminusFloat(operand *op,operand *result)
+{
+    int size ,offset =0 ;
+    char *l;
+    /* for this we just need to flip the 
+    first it then copy the rest in place */
+    size = AOP_SIZE(op) - 1;
+    l = aopGet(AOP(op),3,FALSE,FALSE);
+
+    D(emitcode(";", "genUminusFloat"););
+
+    MOVA(l);    
+
+    emitcode("cpl","acc.7");
+    aopPut(AOP(result),"a",3);    
+
+    while(size--) {
+        aopPut(AOP(result),
+               aopGet(AOP(op),offset,FALSE,FALSE),
+               offset);
+        offset++;
+    }          
+}
+
+/*-----------------------------------------------------------------*/
+/* genUminus - unary minus code generation                         */
+/*-----------------------------------------------------------------*/
+static void genUminus (iCode *ic)
+{
+    int offset ,size ;
+    link *optype, *rtype;
+
+    D(emitcode(";", "genUminus "););
+
+
+    /* assign asmops */
+    aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
+    aopOp(IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
+
+    /* if both in bit space then special
+    case */
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
+        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
+
+        emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
+        emitcode("cpl","c"); 
+        emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
+        goto release; 
+    } 
+
+    optype = operandType(IC_LEFT(ic));
+    rtype = operandType(IC_RESULT(ic));
+
+    /* if float then do float stuff */
+    if (IS_FLOAT(optype)) {
+        genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
+        goto release;
+    }
+
+    /* otherwise subtract from zero */
+    size = AOP_SIZE(IC_LEFT(ic));
+    offset = 0 ;
+    CLRC ;
+    while(size--) {
+        char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
+        if (!strcmp(l,"a")) {
+            emitcode("cpl","a");
+            emitcode("inc","a");
+        } else {
+            emitcode("clr","a");
+            emitcode("subb","a,%s",l);
+        }       
+        aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+    }
+
+    /* if any remaining bytes in the result */
+    /* we just need to propagate the sign   */
+    if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
+        emitcode("rlc","a");
+        emitcode("subb","a,acc");
+        while (size--) 
+            aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+    }       
+
+release:
+    /* release the aops */
+    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
+    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
+}
+
+/*-----------------------------------------------------------------*/
+/* saveRegisters - will look for a call and save the registers     */
+/*-----------------------------------------------------------------*/
+static void saveRegisters(iCode *lic) 
+{
+    int i;
+    iCode *ic;
+    bitVect *rsave;
+    link *detype;
+
+    /* look for call */
+    for (ic = lic ; ic ; ic = ic->next) 
+        if (ic->op == CALL || ic->op == PCALL)
+            break;
+
+    if (!ic) {
+        fprintf(stderr,"found parameter push with no function call\n");
+        return ;
+    }
+
+    /* if the registers have been saved already then
+    do nothing */
+    if (ic->regsSaved || (OP_SYMBOL(IC_LEFT(ic))->calleeSave))
+        return ;
+
+    /* find the registers in use at this time 
+    and push them away to safety */
+    rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
+                          ic->rUsed);
+
+    ic->regsSaved = 1;
+    if (options.useXstack) {
+       if (bitVectBitValue(rsave,R0_IDX))
+           emitcode("mov","b,r0");
+       emitcode("mov","r0,%s",spname);
+       for (i = 0 ; i < ds390_nRegs ; i++) {
+           if (bitVectBitValue(rsave,i)) {
+               if (i == R0_IDX)
+                   emitcode("mov","a,b");
+               else
+                   emitcode("mov","a,%s",ds390_regWithIdx(i)->name);
+               emitcode("movx","@r0,a");
+               emitcode("inc","r0");
+           }
+       }
+       emitcode("mov","%s,r0",spname);
+       if (bitVectBitValue(rsave,R0_IDX))
+           emitcode("mov","r0,b");         
+    } else
+       for (i = 0 ; i < ds390_nRegs ; i++) {
+           if (bitVectBitValue(rsave,i))
+               emitcode("push","%s",ds390_regWithIdx(i)->dname);
+       }
+
+    detype = getSpec(operandType(IC_LEFT(ic)));
+    if (detype        && 
+        (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
+       IS_ISR(currFunc->etype) &&
+        !ic->bankSaved) 
+
+        saverbank(SPEC_BANK(detype),ic,TRUE);
+
+}
+/*-----------------------------------------------------------------*/
+/* unsaveRegisters - pop the pushed registers                      */
+/*-----------------------------------------------------------------*/
+static void unsaveRegisters (iCode *ic)
+{
+    int i;
+    bitVect *rsave;
+    /* find the registers in use at this time 
+    and push them away to safety */
+    rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
+                          ic->rUsed);
+    
+    if (options.useXstack) {
+       emitcode("mov","r0,%s",spname); 
+       for (i =  ds390_nRegs ; i >= 0 ; i--) {
+           if (bitVectBitValue(rsave,i)) {
+               emitcode("dec","r0");
+               emitcode("movx","a,@r0");
+               if (i == R0_IDX)
+                   emitcode("mov","b,a");
+               else
+                   emitcode("mov","%s,a",ds390_regWithIdx(i)->name);
+           }       
+
+       }
+       emitcode("mov","%s,r0",spname);
+       if (bitVectBitValue(rsave,R0_IDX))
+           emitcode("mov","r0,b");
+    } else
+       for (i =  ds390_nRegs ; i >= 0 ; i--) {
+           if (bitVectBitValue(rsave,i))
+               emitcode("pop","%s",ds390_regWithIdx(i)->dname);
+       }
+
+}  
+
+
+/*-----------------------------------------------------------------*/
+/* pushSide -                                                     */
+/*-----------------------------------------------------------------*/
+static void pushSide(operand * oper, int size)
+{
+       int offset = 0;
+       while (size--) {
+               char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
+               if (AOP_TYPE(oper) != AOP_REG &&
+                   AOP_TYPE(oper) != AOP_DIR &&
+                   strcmp(l,"a") ) {
+                       emitcode("mov","a,%s",l);
+                       emitcode("push","acc");
+               } else
+                       emitcode("push","%s",l);
+       }
+}
+
+/*-----------------------------------------------------------------*/
+/* assignResultValue -                                            */
+/*-----------------------------------------------------------------*/
+static void assignResultValue(operand * oper)
+{
+       int offset = 0;
+       int size = AOP_SIZE(oper);
+       while (size--) {
+               aopPut(AOP(oper),fReturn[offset],offset);
+               offset++;
+       }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genXpush - pushes onto the external stack                       */
+/*-----------------------------------------------------------------*/
+static void genXpush (iCode *ic)
+{
+    asmop *aop = newAsmop(0);
+    regs *r ;
+    int size,offset = 0;
+
+    D(emitcode(";", "genXpush "););
+
+    aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
+    r = getFreePtr(ic,&aop,FALSE);
+
+    
+    emitcode("mov","%s,_spx",r->name);
+
+    size = AOP_SIZE(IC_LEFT(ic));
+    while(size--) {
+
+       char *l = aopGet(AOP(IC_LEFT(ic)),
+                        offset++,FALSE,FALSE); 
+       MOVA(l);            
+       emitcode("movx","@%s,a",r->name);       
+       emitcode("inc","%s",r->name);
+
+    }
+
+       
+    emitcode("mov","_spx,%s",r->name);
+
+    freeAsmop(NULL,aop,ic,TRUE);
+    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpush - genrate code for pushing this gets a little complex  */
+/*-----------------------------------------------------------------*/
+static void genIpush (iCode *ic)
+{
+    int size, offset = 0 ;
+    char *l;
+
+    D(emitcode(";", "genIpush "););
+
+
+    /* if this is not a parm push : ie. it is spill push 
+    and spill push is always done on the local stack */
+    if (!ic->parmPush) {
+
+        /* and the item is spilt then do nothing */
+        if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
+            return ;
+
+        aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
+        size = AOP_SIZE(IC_LEFT(ic));
+        /* push it on the stack */
+        while(size--) {
+            l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
+            if (*l == '#') {
+                MOVA(l);
+                l = "acc";
+            }
+            emitcode("push","%s",l);
+        }
+        return ;        
+    }
+
+    /* this is a paramter push: in this case we call
+    the routine to find the call and save those
+    registers that need to be saved */   
+    saveRegisters(ic);
+
+    /* if use external stack then call the external
+    stack pushing routine */
+    if (options.useXstack) {
+        genXpush(ic);
+        return ;
+    }
+
+    /* then do the push */
+    aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
+
+
+       // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
+    size = AOP_SIZE(IC_LEFT(ic));
+
+    while (size--) {
+        l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
+        if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
+            AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
+            strcmp(l,"a") ) {
+            emitcode("mov","a,%s",l);
+            emitcode("push","acc");
+        } else
+            emitcode("push","%s",l);
+    }       
+
+    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpop - recover the registers: can happen only for spilling   */
+/*-----------------------------------------------------------------*/
+static void genIpop (iCode *ic)
+{
+    int size,offset ;
+
+    D(emitcode(";", "genIpop "););
+
+
+    /* if the temp was not pushed then */
+    if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
+        return ;
+
+    aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
+    size = AOP_SIZE(IC_LEFT(ic));
+    offset = (size-1);
+    while (size--) 
+        emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
+                                   FALSE,TRUE));
+
+    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* unsaverbank - restores the resgister bank from stack            */
+/*-----------------------------------------------------------------*/
+static void unsaverbank (int bank,iCode *ic,bool popPsw)
+{
+    int i;
+    asmop *aop ;
+    regs *r = NULL;
+
+    if (popPsw) {
+       if (options.useXstack) {
+           aop = newAsmop(0);
+           r = getFreePtr(ic,&aop,FALSE);
+           
+           
+           emitcode("mov","%s,_spx",r->name);
+           emitcode("movx","a,@%s",r->name);
+           emitcode("mov","psw,a");
+           emitcode("dec","%s",r->name);
+           
+       }else
+           emitcode ("pop","psw");
+    }
+
+    for (i = (ds390_nRegs - 1) ; i >= 0 ;i--) {
+        if (options.useXstack) {       
+            emitcode("movx","a,@%s",r->name);
+            emitcode("mov","(%s+%d),a",
+                     regs390[i].base,8*bank+regs390[i].offset);
+            emitcode("dec","%s",r->name);
+
+        } else 
+            emitcode("pop","(%s+%d)",
+                     regs390[i].base,8*bank+regs390[i].offset);
+    }
+
+    if (options.useXstack) {
+
+       emitcode("mov","_spx,%s",r->name);
+       freeAsmop(NULL,aop,ic,TRUE);
+
+    } 
+}
+
+/*-----------------------------------------------------------------*/
+/* saverbank - saves an entire register bank on the stack          */
+/*-----------------------------------------------------------------*/
+static void saverbank (int bank, iCode *ic, bool pushPsw)
+{
+    int i;
+    asmop *aop ;
+    regs *r = NULL;
+
+    if (options.useXstack) {
+
+       aop = newAsmop(0);
+       r = getFreePtr(ic,&aop,FALSE);  
+       emitcode("mov","%s,_spx",r->name);
+
+    }
+
+    for (i = 0 ; i < ds390_nRegs ;i++) {
+        if (options.useXstack) {
+            emitcode("inc","%s",r->name);
+            emitcode("mov","a,(%s+%d)",
+                     regs390[i].base,8*bank+regs390[i].offset);
+            emitcode("movx","@%s,a",r->name);           
+        } else 
+            emitcode("push","(%s+%d)",
+                     regs390[i].base,8*bank+regs390[i].offset);
+    }
+    
+    if (pushPsw) {
+       if (options.useXstack) {
+           emitcode("mov","a,psw");
+           emitcode("movx","@%s,a",r->name);   
+           emitcode("inc","%s",r->name);
+           emitcode("mov","_spx,%s",r->name);       
+           freeAsmop (NULL,aop,ic,TRUE);
+           
+       } else
+           emitcode("push","psw");
+       
+       emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
+    }
+    ic->bankSaved = 1;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genCall - generates a call statement                            */
+/*-----------------------------------------------------------------*/
+static void genCall (iCode *ic)
+{
+    link *detype;   
+
+    D(emitcode(";", "genCall "););
+
+    /* if caller saves & we have not saved then */
+    if (!ic->regsSaved)
+        saveRegisters(ic);
+
+    /* if we are calling a function that is not using
+    the same register bank then we need to save the
+    destination registers on the stack */
+    detype = getSpec(operandType(IC_LEFT(ic)));
+    if (detype        && 
+        (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)) &&
+       IS_ISR(currFunc->etype) &&
+        !ic->bankSaved) 
+
+        saverbank(SPEC_BANK(detype),ic,TRUE);
+
+    /* if send set is not empty the assign */
+    if (_G.sendSet) {
+       iCode *sic ;
+
+       for (sic = setFirstItem(_G.sendSet) ; sic ; 
+            sic = setNextItem(_G.sendSet)) {
+           int size, offset = 0;
+        aopOp(IC_LEFT(sic),sic,FALSE, TRUE);
+           size = AOP_SIZE(IC_LEFT(sic));
+           while (size--) {
+               char *l = aopGet(AOP(IC_LEFT(sic)),offset,
+                               FALSE, FALSE);
+               if (strcmp(l,fReturn[offset]))
+                   emitcode("mov","%s,%s",
+                            fReturn[offset],
+                            l);
+               offset++;
+           }
+           freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
+       }
+       _G.sendSet = NULL;
+    }
+    /* make the call */
+    emitcode("lcall","%s",(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
+                           OP_SYMBOL(IC_LEFT(ic))->rname :
+                           OP_SYMBOL(IC_LEFT(ic))->name));
+
+    /* if 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)) ) {
+
+       if (!isOperandInFarSpace(IC_RESULT(ic)))
+       {
+        _G.accInUse++;
+            aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
+        _G.accInUse--;
+
+       assignResultValue(IC_RESULT(ic));
+               
+        freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
+    }
+        else
+        {
+            /* Result is in far space, and requires DPTR to access
+             * it. Push the result onto the stack and restore from
+             * there.
+             */
+            int size = getSize(operandType(IC_RESULT(ic)));
+            int offset = size - 1;
+            char *l;
+           
+           emitcode(";", "Kevin function call abuse #1");
+
+           /* first push the right side on to the stack */
+           /* NB: this relies on the fact that "a" is the last
+            * register in fReturn. If it were not, the MOVA
+            * would potentially clobber a returned byte in A.
+            */
+           while (size--) {
+               l = fReturn[offset--];
+               MOVA(l);
+               emitcode ("push","acc");
+           }
+    
+           /* now assign DPTR to result */
+           aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
+           size = AOP_SIZE(IC_RESULT(ic));
+           aopOp(IC_RESULT(ic),ic,FALSE, FALSE); /* bug? */
+           while (size--) {
+               emitcode ("pop","acc");
+               aopPut(AOP(IC_RESULT(ic)),"a",++offset);
+           }
+           freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+        }
+    }
+
+    /* adjust the stack for parameters if 
+    required */
+    if (IC_LEFT(ic)->parmBytes) {
+        int i;
+        if (IC_LEFT(ic)->parmBytes > 3) {
+            emitcode("mov","a,%s",spname);
+            emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
+            emitcode("mov","%s,a",spname);
+        } else 
+            for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
+                emitcode("dec","%s",spname);
+
+    }
+
+    /* if register bank was saved then pop them */
+    if (ic->bankSaved)
+        unsaverbank(SPEC_BANK(detype),ic,TRUE);
+
+    /* if we hade saved some registers then unsave them */
+    if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
+        unsaveRegisters (ic);
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genPcall - generates a call by pointer statement                */
+/*-----------------------------------------------------------------*/
+static void genPcall (iCode *ic)
+{
+    link *detype;
+    symbol *rlbl = newiTempLabel(NULL);
+
+    D(emitcode(";", "genPcall "););
+
+
+    /* if caller saves & we have not saved then */
+    if (!ic->regsSaved)
+        saveRegisters(ic);
+
+    /* if we are calling a function that is not using
+    the same register bank then we need to save the
+    destination registers on the stack */
+    detype = getSpec(operandType(IC_LEFT(ic)));
+    if (detype        && 
+       IS_ISR(currFunc->etype) &&
+        (SPEC_BANK(currFunc->etype) != SPEC_BANK(detype)))
+        saverbank(SPEC_BANK(detype),ic,TRUE);
+
+
+    /* push the return address on to the stack */
+    emitcode("mov","a,#%05d$",(rlbl->key+100));
+    emitcode("push","acc");    
+    emitcode("mov","a,#(%05d$ >> 8)",(rlbl->key+100));
+    emitcode("push","acc");
+    
+    if (options.model == MODEL_FLAT24)
+    {
+       emitcode("mov","a,#(%05d$ >> 16)",(rlbl->key+100));
+       emitcode("push","acc");    
+    }
+
+    /* now push the calling address */
+    aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
+
+    pushSide(IC_LEFT(ic), FPTRSIZE);
+
+    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
+
+    /* if send set is not empty the assign */
+    if (_G.sendSet) {
+       iCode *sic ;
+
+       for (sic = setFirstItem(_G.sendSet) ; sic ; 
+            sic = setNextItem(_G.sendSet)) {
+           int size, offset = 0;
+           aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+           size = AOP_SIZE(IC_LEFT(sic));
+           while (size--) {
+               char *l = aopGet(AOP(IC_LEFT(sic)),offset,
+                               FALSE,FALSE);
+               if (strcmp(l,fReturn[offset]))
+                   emitcode("mov","%s,%s",
+                            fReturn[offset],
+                            l);
+               offset++;
+           }
+           freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
+       }
+       _G.sendSet = NULL;
+    }
+
+    emitcode("ret","");
+    emitcode("","%05d$:",(rlbl->key+100));
+
+
+    /* if we need assign a result value */
+    if ((IS_ITEMP(IC_RESULT(ic)) &&
+         (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
+          OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
+        IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
+
+        _G.accInUse++;
+        aopOp(IC_RESULT(ic),ic,FALSE, TRUE);
+        _G.accInUse--;
+       
+       assignResultValue(IC_RESULT(ic));
+
+        freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+    }
+
+    /* adjust the stack for parameters if 
+    required */
+    if (IC_LEFT(ic)->parmBytes) {
+        int i;
+        if (IC_LEFT(ic)->parmBytes > 3) {
+            emitcode("mov","a,%s",spname);
+            emitcode("add","a,#0x%02x", (- IC_LEFT(ic)->parmBytes) & 0xff);
+            emitcode("mov","%s,a",spname);
+        } else 
+            for ( i = 0 ; i <  IC_LEFT(ic)->parmBytes ;i++)
+                emitcode("dec","%s",spname);
+
+    }
+
+    /* if register bank was saved then unsave them */
+    if (detype        && 
+        (SPEC_BANK(currFunc->etype) != 
+         SPEC_BANK(detype)))
+        unsaverbank(SPEC_BANK(detype),ic,TRUE);
+
+    /* if we hade saved some registers then
+    unsave them */
+    if (ic->regsSaved)
+        unsaveRegisters (ic);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* resultRemat - result  is rematerializable                       */
+/*-----------------------------------------------------------------*/
+static int resultRemat (iCode *ic)
+{
+    if (SKIP_IC(ic) || ic->op == IFX)
+        return 0;
+
+    if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
+        symbol *sym = OP_SYMBOL(IC_RESULT(ic));
+        if (sym->remat && !POINTER_SET(ic)) 
+            return 1;
+    }
+
+    return 0;
+}
+
+#ifdef __BORLANDC__
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+/*-----------------------------------------------------------------*/
+/* inExcludeList - return 1 if the string is in exclude Reg list   */
+/*-----------------------------------------------------------------*/
+static bool inExcludeList(char *s)
+{
+    int i =0;
+    
+    if (options.excludeRegs[i] &&
+    STRCASECMP(options.excludeRegs[i],"none") == 0)
+       return FALSE ;
+
+    for ( i = 0 ; options.excludeRegs[i]; i++) {
+       if (options.excludeRegs[i] &&
+        STRCASECMP(s,options.excludeRegs[i]) == 0)
+           return TRUE;
+    }
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* genFunction - generated code for function entry                 */
+/*-----------------------------------------------------------------*/
+static void genFunction (iCode *ic)
+{
+    symbol *sym;
+    link *fetype;
+
+    D(emitcode(";", "genFunction "););
+
+    _G.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("clr","ea");
+
+    /* here we need to generate the equates for the
+       register bank if required */
+    if (SPEC_BANK(fetype) != rbank) {
+        int i ;
+
+        rbank = SPEC_BANK(fetype);
+        for ( i = 0 ; i < ds390_nRegs ; i++ ) {
+            if (strcmp(regs390[i].base,"0") == 0)
+                emitcode("","%s = 0x%02x",
+                         regs390[i].dname,
+                         8*rbank+regs390[i].offset);
+            else
+                emitcode ("","%s = %s + 0x%02x",
+                          regs390[i].dname,
+                          regs390[i].base,
+                          8*rbank+regs390[i].offset);
+        }
+    }
+
+    /* if this is an interrupt service routine then
+    save acc, b, dpl, dph  */
+    if (IS_ISR(sym->etype)) {
+        
+       if (!inExcludeList("acc"))          
+           emitcode ("push","acc");    
+       if (!inExcludeList("b"))
+           emitcode ("push","b");
+       if (!inExcludeList("dpl"))
+           emitcode ("push","dpl");
+       if (!inExcludeList("dph"))
+           emitcode ("push","dph");
+       if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
+       {
+           emitcode ("push", "dpx");
+           /* Make sure we're using standard DPTR */
+           emitcode ("push", "dps");
+           emitcode ("mov", "dps, #0x00");
+           if (options.stack10bit)
+           {   
+               /* This ISR could conceivably use DPTR2. Better save it. */
+               emitcode ("push", "dpl1");
+               emitcode ("push", "dph1");
+               emitcode ("push", "dpx1");
+            emitcode ("push", "ap");
+           }
+       }
+       /* if this isr has no bank i.e. is going to
+          run with bank 0 , then we need to save more
+          registers :-) */
+       if (!SPEC_BANK(sym->etype)) {
+
+           /* if this function does not call any other
+              function then we can be economical and
+              save only those registers that are used */
+           if (! sym->hasFcall) {
+               int i;
+
+               /* if any registers used */
+               if (sym->regsUsed) {
+                   /* save the registers used */
+                   for ( i = 0 ; i < sym->regsUsed->size ; i++) {
+                       if (bitVectBitValue(sym->regsUsed,i) ||
+                          (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
+                           emitcode("push","%s",ds390_regWithIdx(i)->dname);                       
+                   }
+               }
+               
+           } else {
+               /* this function has  a function call cannot
+                  determines register usage so we will have the
+                  entire bank */
+               saverbank(0,ic,FALSE);
+           }       
+       }
+    } else {
+       /* if callee-save to be used for this function
+          then save the registers being used in this function */
+       if (sym->calleeSave) {
+           int i;
+           
+           /* if any registers used */
+           if (sym->regsUsed) {
+               /* save the registers used */
+               for ( i = 0 ; i < sym->regsUsed->size ; i++) {
+                   if (bitVectBitValue(sym->regsUsed,i) ||
+                      (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
+                       emitcode("push","%s",ds390_regWithIdx(i)->dname);
+                       _G.nRegsSaved++;
+                   }
+               }
+           }
+       }
+    }
+
+    /* set the register bank to the desired value */
+    if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype)) {
+        emitcode("push","psw");
+        emitcode("mov","psw,#0x%02x",(SPEC_BANK(sym->etype) << 3)&0x00ff);   
+    }
+
+    if (IS_RENT(sym->etype) || options.stackAuto) {
+
+       if (options.useXstack) {
+           emitcode("mov","r0,%s",spname);
+           emitcode("mov","a,_bp");
+           emitcode("movx","@r0,a");
+           emitcode("inc","%s",spname);
+       }
+       else
+       {
+           /* set up the stack */
+           emitcode ("push","_bp");     /* save the callers stack  */
+       }
+       emitcode ("mov","_bp,%s",spname);
+    }
+
+    /* adjust the stack for the function */
+    if (sym->stack) {
+
+       int i = sym->stack;
+       if (i > 256 ) 
+           werror(W_STACK_OVERFLOW,sym->name);
+
+       if (i > 3 && sym->recvSize < 4) {              
+
+           emitcode ("mov","a,sp");
+           emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
+           emitcode ("mov","sp,a");
+          
+       }
+       else
+           while(i--)
+               emitcode("inc","sp");
+    }
+
+     if (sym->xstack) {
+
+       emitcode ("mov","a,_spx");
+       emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
+       emitcode ("mov","_spx,a");
+    }    
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndFunction - generates epilogue for functions               */
+/*-----------------------------------------------------------------*/
+static void genEndFunction (iCode *ic)
+{
+    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+
+    D(emitcode(";", "genEndFunction "););
+
+    if (IS_RENT(sym->etype) || options.stackAuto)
+    {
+        emitcode ("mov","%s,_bp",spname);
+    }
+
+    /* if use external stack but some variables were
+    added to the local stack then decrement the
+    local stack */
+    if (options.useXstack && sym->stack) {      
+        emitcode("mov","a,sp");
+        emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
+        emitcode("mov","sp,a");
+    }
+
+
+    if ((IS_RENT(sym->etype) || options.stackAuto)) {
+       if (options.useXstack) {
+           emitcode("mov","r0,%s",spname);
+           emitcode("movx","a,@r0");
+           emitcode("mov","_bp,a");
+           emitcode("dec","%s",spname);
+       }
+       else
+       {
+           emitcode ("pop","_bp");
+       }
+    }
+
+    /* restore the register bank  */    
+    if (SPEC_BANK(sym->etype) || IS_ISR(sym->etype))
+        emitcode ("pop","psw");
+
+    if (IS_ISR(sym->etype)) {
+
+       /* now we need to restore the registers */
+       /* if this isr has no bank i.e. is going to
+          run with bank 0 , then we need to save more
+          registers :-) */
+       if (!SPEC_BANK(sym->etype)) {
+           
+           /* if this function does not call any other
+              function then we can be economical and
+              save only those registers that are used */
+           if (! sym->hasFcall) {
+               int i;
+               
+               /* if any registers used */
+               if (sym->regsUsed) {
+                   /* save the registers used */
+                   for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
+                       if (bitVectBitValue(sym->regsUsed,i) ||
+                          (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
+                           emitcode("pop","%s",ds390_regWithIdx(i)->dname);
+                   }
+               }
+               
+           } else {
+               /* this function has  a function call cannot
+                  determines register usage so we will have the
+                  entire bank */
+               unsaverbank(0,ic,FALSE);
+           }       
+       }
+
+       if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
+       {
+           if (options.stack10bit)
+           {
+            emitcode ("pop", "ap");
+               emitcode ("pop", "dpx1");
+               emitcode ("pop", "dph1");
+               emitcode ("pop", "dpl1");
+           }   
+           emitcode ("pop", "dps");
+           emitcode ("pop", "dpx");
+       }
+       if (!inExcludeList("dph"))
+           emitcode ("pop","dph");
+       if (!inExcludeList("dpl"))
+           emitcode ("pop","dpl");
+       if (!inExcludeList("b"))
+           emitcode ("pop","b");
+       if (!inExcludeList("acc"))
+           emitcode ("pop","acc");
+
+        if (SPEC_CRTCL(sym->etype))
+            emitcode("setb","ea");
+
+       /* if debug then send end of function */
+/*     if (options.debug && currFunc) { */
+       if (currFunc) {
+           _G.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);
+           _G.debugLine = 0;
+       }
+       
+        emitcode ("reti","");
+    }
+    else {
+        if (SPEC_CRTCL(sym->etype))
+            emitcode("setb","ea");
+       
+       if (sym->calleeSave) {
+           int i;
+           
+           /* if any registers used */
+           if (sym->regsUsed) {
+               /* save the registers used */
+               for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
+                   if (bitVectBitValue(sym->regsUsed,i) ||
+                      (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
+                       emitcode("pop","%s",ds390_regWithIdx(i)->dname);
+               }
+           }
+           
+       }
+
+       /* if debug then send end of function */
+       if (currFunc) {
+           _G.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);
+           _G.debugLine = 0;
+       }
+
+        emitcode ("ret","");
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genRet - generate code for return statement                     */
+/*-----------------------------------------------------------------*/
+static void genRet (iCode *ic)
+{
+    int size,offset = 0 , pushed = 0;
+    
+    D(emitcode(";", "genRet "););
+
+    /* if we have no return value then
+       just generate the "ret" */
+    if (!IC_LEFT(ic)) 
+       goto jumpret;       
+    
+    /* we have something to return then
+       move the return value into place */
+    aopOp(IC_LEFT(ic),ic,FALSE, TRUE);
+    size = AOP_SIZE(IC_LEFT(ic));
+    
+    while (size--) {
+           char *l ;
+           if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
+                   /* #NOCHANGE */
+                   l = aopGet(AOP(IC_LEFT(ic)),offset++,
+                          FALSE,TRUE);
+                   emitcode("push","%s",l);
+                   pushed++;
+           } else {
+                   l = aopGet(AOP(IC_LEFT(ic)),offset,
+                              FALSE,FALSE);
+                   if (strcmp(fReturn[offset],l))
+                           emitcode("mov","%s,%s",fReturn[offset++],l);
+           }
+    }    
+
+    if (pushed) {
+       while(pushed) {
+           pushed--;
+           if (strcmp(fReturn[pushed],"a"))
+               emitcode("pop",fReturn[pushed]);
+           else
+               emitcode("pop","acc");
+       }
+    }
+    freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
+    
+ jumpret:
+       /* generate a jump to the return label
+          if the next is not the return statement */
+    if (!(ic->next && ic->next->op == LABEL &&
+         IC_LABEL(ic->next) == returnLabel))
+       
+       emitcode("ljmp","%05d$",(returnLabel->key+100));
+    
+}
+
+/*-----------------------------------------------------------------*/
+/* genLabel - generates a label                                    */
+/*-----------------------------------------------------------------*/
+static void genLabel (iCode *ic)
+{
+    /* special case never generate */
+    if (IC_LABEL(ic) == entryLabel)
+        return ;
+
+    D(emitcode(";", "genLabel "););
+
+    emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
+}
+
+/*-----------------------------------------------------------------*/
+/* genGoto - generates a ljmp                                      */
+/*-----------------------------------------------------------------*/
+static void genGoto (iCode *ic)
+{
+    D(emitcode(";", "genGoto "););
+    emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
+}
+
+/*-----------------------------------------------------------------*/
+/* findLabelBackwards: walks back through the iCode chain looking  */
+/* for the given label. Returns number of iCode instructions      */
+/* between that label and given ic.                               */
+/* Returns zero if label not found.                               */
+/*-----------------------------------------------------------------*/
+static int findLabelBackwards(iCode *ic, int key)
+{
+    int count = 0;
+    
+    while (ic->prev)
+    {
+        ic = ic->prev;
+        count++;
+        
+        if (ic->op == LABEL && IC_LABEL(ic)->key == key)
+        {
+            /* printf("findLabelBackwards = %d\n", count); */
+            return count;
+        }
+    }
+    
+    return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* 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 ;
+    
+    /* if increment 16 bits in register */
+    if (
+        AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
+        AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
+       sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
+        (size > 1) &&
+        (icount == 1)) {
+        symbol *tlbl;
+        int emitTlbl;
+        int labelRange;
+
+       /* If the next instruction is a goto and the goto target
+        * is < 10 instructions previous to this, we can generate
+        * jumps straight to that target.
+        */
+        if (ic->next && ic->next->op == GOTO
+            && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
+            && labelRange <= 10 )
+        {
+           emitcode(";", "tail increment optimized");
+           tlbl = IC_LABEL(ic->next);
+           emitTlbl = 0;
+        }
+        else
+        {
+            tlbl = newiTempLabel(NULL);
+            emitTlbl = 1;
+        }
+       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
+       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
+          IS_AOP_PREG(IC_RESULT(ic)))
+           emitcode("cjne","%s,#0x00,%05d$"
+                    ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
+                    ,tlbl->key+100);
+       else {
+           emitcode("clr","a");
+           emitcode("cjne","a,%s,%05d$"
+                    ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
+                    ,tlbl->key+100);
+       }
+    
+       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
+       if (size > 2)
+       {
+           if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
+              IS_AOP_PREG(IC_RESULT(ic)))
+               emitcode("cjne","%s,#0x00,%05d$"
+                        ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
+                        ,tlbl->key+100);
+           else
+               emitcode("cjne","a,%s,%05d$"
+                        ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
+                        ,tlbl->key+100);
+           
+           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
+       }
+       if (size > 3)
+       {
+           if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
+              IS_AOP_PREG(IC_RESULT(ic)))
+               emitcode("cjne","%s,#0x00,%05d$"
+                        ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
+                        ,tlbl->key+100);
+           else{
+               emitcode("cjne","a,%s,%05d$"
+                        ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
+                        ,tlbl->key+100);
+           }
+           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
+       }
+       
+       if (emitTlbl)
+       {
+           emitcode("","%05d$:",tlbl->key+100);
+       }
+        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 (
+        AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
+        AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
+        sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+       
+        if (icount > 3) {
+            MOVA(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));       
+            emitcode("add","a,#0x%02x",((char) icount) & 0xff);
+            aopPut(AOP(IC_RESULT(ic)),"a",0);
+        } else {
+           
+            while (icount--) 
+                emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+        }
+       
+        return TRUE ;
+    }
+    
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* outBitAcc - output a bit in acc                                 */
+/*-----------------------------------------------------------------*/
+static void outBitAcc(operand *result)
+{
+    symbol *tlbl = newiTempLabel(NULL);
+    /* if the result is a bit */
+    if (AOP_TYPE(result) == AOP_CRY){
+        aopPut(AOP(result),"a",0);
+    }
+    else {
+        emitcode("jz","%05d$",tlbl->key+100);
+        emitcode("mov","a,%s",one);
+        emitcode("","%05d$:",tlbl->key+100);
+        outAcc(result);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genPlusBits - generates code for addition of two bits           */
+/*-----------------------------------------------------------------*/
+static void genPlusBits (iCode *ic)
+{
+    D(emitcode(";", "genPlusBits "););
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
+        symbol *lbl = newiTempLabel(NULL);
+        emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
+        emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
+        emitcode("cpl","c");
+        emitcode("","%05d$:",(lbl->key+100));
+        outBitC(IC_RESULT(ic));
+    }
+    else{
+        emitcode("clr","a");
+        emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
+        emitcode("rlc","a");
+        emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
+        emitcode("addc","a,#0x00");
+        outAcc(IC_RESULT(ic));
+    }
+}
+
+
+
+#if 0
+/* This is the original version of this code.
+ *
+ * This is being kept around for reference, 
+ * because I am not entirely sure I got it right...
+ */
+static void adjustArithmeticResult(iCode *ic)
+{
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
+       AOP_SIZE(IC_LEFT(ic)) == 3   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
+       aopPut(AOP(IC_RESULT(ic)),
+              aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
+              2);
+
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
+       AOP_SIZE(IC_RIGHT(ic)) == 3   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
+       aopPut(AOP(IC_RESULT(ic)),
+              aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
+              2);
+    
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
+       AOP_SIZE(IC_LEFT(ic)) < 3    &&
+       AOP_SIZE(IC_RIGHT(ic)) < 3   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
+       char buffer[5];
+       sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
+       aopPut(AOP(IC_RESULT(ic)),buffer,2);
+    }
+}
+#else
+/* This is the pure and virtuous version of this code.
+ * I'm pretty certain it's right, but not enough to toss the old 
+ * code just yet...
+ */
+static void adjustArithmeticResult(iCode *ic)
+{
+    if (opIsGptr(IC_RESULT(ic)) &&
+       opIsGptr(IC_LEFT(ic))   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
+    {
+       aopPut(AOP(IC_RESULT(ic)),
+              aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
+              GPTRSIZE - 1);
+    }
+
+    if (opIsGptr(IC_RESULT(ic)) &&
+        opIsGptr(IC_RIGHT(ic))   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
+    {
+       aopPut(AOP(IC_RESULT(ic)),
+              aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
+              GPTRSIZE - 1);
+    }
+
+    if (opIsGptr(IC_RESULT(ic))           &&
+        AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
+        AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
+        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
+        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
+        char buffer[5];
+        sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
+        aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
+     }
+}
+#endif
+
+#define AOP_OP_3(ic) \
+    aopOp (IC_LEFT(ic),ic,FALSE, FALSE); \
+    aopOp (IC_RIGHT(ic),ic,FALSE, TRUE); \
+    aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR); \
+    if (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2 && \
+        AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \
+    { \
+        /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \
+        fprintf(stderr,                                  \
+               "Ack: three operands in far space!\n");   \
+    }
+
+#define AOP_SET_LOCALS(ic) \
+    left = IC_LEFT(ic); \
+    right = IC_RIGHT(ic); \
+    result = IC_RESULT(ic);
+
+/*-----------------------------------------------------------------*/
+/* genPlus - generates code for addition                           */
+/*-----------------------------------------------------------------*/
+static void genPlus (iCode *ic)
+{
+    int size, offset = 0;
+    bool pushResult = FALSE;
+
+    D(emitcode(";", "genPlus "););
+
+    /* special cases :- */
+
+    aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
+    aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
+    if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2) &&
+        (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR))
+    {
+        pushResult = TRUE;
+    }
+    else
+    {
+        aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR);
+
+    /* 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) {
+        genPlusBits (ic);
+        goto release ;
+    }
+
+    /* if left in bit space & right literal */
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
+        AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
+        emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
+        /* if result in bit space */
+        if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
+            if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L)
+                emitcode("cpl","c");
+            outBitC(IC_RESULT(ic));
+        } else {
+            size = getDataSize(IC_RESULT(ic));
+            while (size--) {
+                MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
+                emitcode("addc","a,#00");
+                aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+            }
+        }
+        goto release ;
+    }
+
+    /* if I can do an increment instead
+    of add then GOOD for ME */
+    if (genPlusIncr (ic) == TRUE)
+        goto release;   
+
+    }
+    size = getDataSize(pushResult ? IC_LEFT(ic) : IC_RESULT(ic));
+
+    while(size--){
+       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
+           MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
+           if(offset == 0)
+               emitcode("add","a,%s",
+                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
+           else
+               emitcode("addc","a,%s",
+                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
+       } else {
+           MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
+           if(offset == 0)
+               emitcode("add","a,%s",
+                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
+           else
+               emitcode("addc","a,%s",
+                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
+       }
+        if (!pushResult)
+        {
+            aopPut(AOP(IC_RESULT(ic)),"a",offset);
+        }
+        else
+        {
+            emitcode("push", "acc");
+        }
+        offset++;
+    }
+
+    if (pushResult)
+    {
+        aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
+
+        size = getDataSize(IC_LEFT(ic));
+
+        while(size--)
+        {
+            emitcode("pop", "acc");
+            aopPut(AOP(IC_RESULT(ic)), "a", --offset);
+        }
+    }
+
+    adjustArithmeticResult(ic);
+
+release:
+    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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)) > 4)
+        return FALSE ;
+
+    /* if decrement 16 bits in register */
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
+        AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
+        sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
+        (size > 1) &&
+        (icount == 1)) {
+            symbol *tlbl;
+            int emitTlbl;
+            int labelRange;
+
+           /* If the next instruction is a goto and the goto target
+            * is <= 10 instructions previous to this, we can generate
+            * jumps straight to that target.
+            */
+            if (ic->next && ic->next->op == GOTO
+                && (labelRange = findLabelBackwards(ic, IC_LABEL(ic->next)->key)) != 0
+                && labelRange <= 10 )
+            {        
+               emitcode(";", "tail decrement optimized");
+               tlbl = IC_LABEL(ic->next);
+               emitTlbl = 0;
+            }
+            else
+            {
+                tlbl = newiTempLabel(NULL);
+                emitTlbl = 1;
+            }
+        
+               emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
+               if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
+                  AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
+                  IS_AOP_PREG(IC_RESULT(ic)))
+                       emitcode("cjne","%s,#0xff,%05d$"
+                                        ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
+                                        ,tlbl->key+100);
+               else{
+                       emitcode("mov","a,#0xff");
+                       emitcode("cjne","a,%s,%05d$"
+                                        ,aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)
+                                        ,tlbl->key+100);
+               }
+               emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
+               if (size > 2)
+               {
+                       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
+                          AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
+                          IS_AOP_PREG(IC_RESULT(ic)))
+                               emitcode("cjne","%s,#0xff,%05d$"
+                                                ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
+                                                ,tlbl->key+100);
+                       else{
+                               emitcode("cjne","a,%s,%05d$"
+                                                ,aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)
+                                                ,tlbl->key+100);
+                       }
+                       emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
+               }
+               if (size > 3)
+               {
+                       if(AOP_TYPE(IC_RESULT(ic)) == AOP_REG ||
+                          AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR ||
+                          IS_AOP_PREG(IC_RESULT(ic)))
+                               emitcode("cjne","%s,#0xff,%05d$"
+                                                ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
+                                                ,tlbl->key+100);
+                       else{
+                               emitcode("cjne","a,%s,%05d$"
+                                                ,aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)
+                                                ,tlbl->key+100);
+                       }
+                       emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
+               }
+               if (emitTlbl)
+               {
+                   emitcode("","%05d$:",tlbl->key+100);
+               }
+        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 (
+        AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
+        AOP_TYPE(IC_RESULT(ic)) == AOP_REG &&
+        sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+
+        while (icount--) 
+            emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+        return TRUE ;
+    }
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* addSign - complete with sign                                    */
+/*-----------------------------------------------------------------*/
+static void addSign(operand *result, int offset, int sign)
+{
+    int size = (getDataSize(result) - offset);
+    if(size > 0){
+        if(sign){
+            emitcode("rlc","a");
+            emitcode("subb","a,acc");
+            while(size--)
+                aopPut(AOP(result),"a",offset++); 
+        } else
+            while(size--)
+                aopPut(AOP(result),zero,offset++);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genMinusBits - generates code for subtraction  of two bits      */
+/*-----------------------------------------------------------------*/
+static void genMinusBits (iCode *ic)
+{
+    symbol *lbl = newiTempLabel(NULL);
+    
+    D(emitcode(";", "genMinusBits "););    
+
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
+        emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
+        emitcode("jnb","%s,%05d$",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
+        emitcode("cpl","c");
+        emitcode("","%05d$:",(lbl->key+100));
+        outBitC(IC_RESULT(ic));
+    }
+    else{
+        emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
+        emitcode("subb","a,acc");
+        emitcode("jnb","%s,%05d$",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
+        emitcode("inc","a");
+        emitcode("","%05d$:",(lbl->key+100));
+        aopPut(AOP(IC_RESULT(ic)),"a",0);
+        addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genMinus - generates code for subtraction                       */
+/*-----------------------------------------------------------------*/
+static void genMinus (iCode *ic)
+{
+    int size, offset = 0;
+    unsigned long lit = 0L;
+    bool pushResult = FALSE;
+
+    D(emitcode(";", "genMinus "););
+
+    aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
+    aopOp (IC_RIGHT(ic),ic,FALSE, TRUE);
+    if ((AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) &&
+        (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR2))
+    {
+        pushResult = TRUE;
+    }
+    else
+    {
+        aopOp (IC_RESULT(ic),ic,TRUE, AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR);
+
+    /* 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) {
+        genMinusBits (ic);
+        goto release ;
+    }
+
+    /* if I can do an decrement instead
+    of subtract then GOOD for ME */
+    if (genMinusDec (ic) == TRUE)
+        goto release;
+
+    }
+
+    size = getDataSize(pushResult ? IC_LEFT(ic) : 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,FALSE));    
+        if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
+            emitcode("subb","a,%s",
+                     aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
+        else{
+            /* first add without previous c */
+            if(!offset)
+                emitcode("add","a,#0x%02x",
+                         (unsigned int)(lit & 0x0FFL));
+            else
+                emitcode("addc","a,#0x%02x",
+                         (unsigned int)((lit >> (offset*8)) & 0x0FFL));
+        }
+
+        if (pushResult)
+        {
+            emitcode("push", "acc");
+        }
+        else
+        {
+            aopPut(AOP(IC_RESULT(ic)),"a",offset);
+        }
+        offset++;
+    }
+
+    if (pushResult)
+    {
+        aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
+
+        size = getDataSize(IC_LEFT(ic));
+
+        while(size--)
+        {
+            emitcode("pop", "acc");
+            aopPut(AOP(IC_RESULT(ic)), "a", --offset);
+        }
+    }
+
+    adjustArithmeticResult(ic);
+        
+release:
+    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genMultbits :- multiplication of bits                           */
+/*-----------------------------------------------------------------*/
+static void genMultbits (operand *left, 
+                         operand *right, 
+                         operand *result)
+{
+    emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+    emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
+    outBitC(result);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genMultOneByte : 8 bit multiplication & division                */
+/*-----------------------------------------------------------------*/
+static void genMultOneByte (operand *left,
+                            operand *right,
+                            operand *result)
+{
+    link *opetype = operandType(result);
+    char *l ;
+    symbol *lbl ;
+    int size,offset;
+
+    /* (if two literals, the value is computed before) */
+    /* if one literal, literal on the right */
+    if (AOP_TYPE(left) == AOP_LIT){
+        operand *t = right;
+        right = left;
+        left = t;
+    }
+
+    size = AOP_SIZE(result);
+    /* signed or unsigned */
+    emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
+    l = aopGet(AOP(left),0,FALSE,FALSE);
+    MOVA(l);       
+    emitcode("mul","ab");
+    /* if result size = 1, mul signed = mul unsigned */
+    aopPut(AOP(result),"a",0);
+    if (size > 1){
+        if (SPEC_USIGN(opetype)){
+            aopPut(AOP(result),"b",1);
+            if (size > 2)
+                /* for filling the MSBs */
+                emitcode("clr","a");
+        }
+        else{
+            emitcode("mov","a,b");
+
+            /* adjust the MSB if left or right neg */
+
+            /* if one literal */
+            if (AOP_TYPE(right) == AOP_LIT){
+                /* AND literal negative */
+                if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
+                    /* adjust MSB (c==0 after mul) */
+                    emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
+                }
+            }
+            else{
+                lbl = newiTempLabel(NULL);
+                emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
+                emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
+                emitcode("","%05d$:",(lbl->key+100));
+                emitcode("xch","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
+                lbl = newiTempLabel(NULL);      
+                emitcode("jc","%05d$",(lbl->key+100));          
+                emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
+                emitcode("","%05d$:",(lbl->key+100));
+            }
+
+            lbl = newiTempLabel(NULL);
+            emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
+            emitcode("cjne","a,#0x80,%05d$", (lbl->key+100));
+            emitcode("","%05d$:",(lbl->key+100));
+            emitcode("xch","a,%s",aopGet(AOP(left),0,FALSE,FALSE));
+            lbl = newiTempLabel(NULL);      
+            emitcode("jc","%05d$",(lbl->key+100));          
+            emitcode("subb","a,%s", aopGet(AOP(right),0,FALSE,FALSE));
+            emitcode("","%05d$:",(lbl->key+100));
+
+            aopPut(AOP(result),"a",1);
+            if(size > 2){
+                /* get the sign */
+                emitcode("rlc","a");
+                emitcode("subb","a,acc");
+            }
+        }
+        size -= 2;   
+        offset = 2;
+        if (size > 0)
+            while (size--)
+                aopPut(AOP(result),"a",offset++);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genMult - generates code for multiplication                     */
+/*-----------------------------------------------------------------*/
+static void genMult (iCode *ic)
+{
+    operand *left = IC_LEFT(ic);
+    operand *right = IC_RIGHT(ic);
+    operand *result= IC_RESULT(ic);   
+
+    D(emitcode(";", "genMult "););
+
+    /* assign the amsops */
+    AOP_OP_3(ic);
+#if 0
+    aopOp (left,ic,FALSE, FALSE);
+    aopOp (right,ic,FALSE, TRUE);
+    aopOp (result,ic,TRUE, FALSE);
+#endif
+
+    /* special cases first */
+    /* both are bits */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right)== AOP_CRY) {
+        genMultbits(left,right,result);
+        goto release ;
+    }
+
+    /* if both are of size == 1 */
+    if (AOP_SIZE(left) == 1 &&
+        AOP_SIZE(right) == 1 ) {
+        genMultOneByte(left,right,result);
+        goto release ;
+    }
+
+    /* should have been converted to function call */       
+    assert(1) ;
+
+release :
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* genDivbits :- division of bits                                  */
+/*-----------------------------------------------------------------*/
+static void genDivbits (operand *left, 
+                        operand *right, 
+                        operand *result)
+{
+
+    char *l;
+
+    /* the result must be bit */    
+    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
+    l = aopGet(AOP(left),0,FALSE,FALSE);
+
+    MOVA(l);    
+
+    emitcode("div","ab");
+    emitcode("rrc","a");
+    aopPut(AOP(result),"c",0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDivOneByte : 8 bit division                                  */
+/*-----------------------------------------------------------------*/
+static void genDivOneByte (operand *left,
+                           operand *right,
+                           operand *result)
+{
+    link *opetype = operandType(result);
+    char *l ;
+    symbol *lbl ;
+    int size,offset;
+
+    size = AOP_SIZE(result) - 1;
+    offset = 1;
+    /* signed or unsigned */
+    if (SPEC_USIGN(opetype)) {
+        /* unsigned is easy */
+        emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
+        l = aopGet(AOP(left),0,FALSE,FALSE);
+        MOVA(l);        
+        emitcode("div","ab");
+        aopPut(AOP(result),"a",0);
+        while (size--)
+            aopPut(AOP(result),zero,offset++);
+        return ;
+    }
+
+    /* signed is a little bit more difficult */
+
+    /* save the signs of the operands */
+    l = aopGet(AOP(left),0,FALSE,FALSE);    
+    MOVA(l);    
+    emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
+    emitcode("push","acc"); /* save it on the stack */
+
+    /* now sign adjust for both left & right */
+    l =  aopGet(AOP(right),0,FALSE,FALSE);    
+    MOVA(l);       
+    lbl = newiTempLabel(NULL);
+    emitcode("jnb","acc.7,%05d$",(lbl->key+100));   
+    emitcode("cpl","a");   
+    emitcode("inc","a");
+    emitcode("","%05d$:",(lbl->key+100));
+    emitcode("mov","b,a");
+
+    /* sign adjust left side */
+    l =  aopGet(AOP(left),0,FALSE,FALSE);    
+    MOVA(l);
+
+    lbl = newiTempLabel(NULL);
+    emitcode("jnb","acc.7,%05d$",(lbl->key+100));
+    emitcode("cpl","a");
+    emitcode("inc","a");
+    emitcode("","%05d$:",(lbl->key+100));
+
+    /* now the division */
+    emitcode("div","ab");
+    /* we are interested in the lower order
+    only */
+    emitcode("mov","b,a");
+    lbl = newiTempLabel(NULL);
+    emitcode("pop","acc");   
+    /* if there was an over flow we don't 
+    adjust the sign of the result */
+    emitcode("jb","ov,%05d$",(lbl->key+100));
+    emitcode("jnb","acc.7,%05d$",(lbl->key+100));
+    CLRC;
+    emitcode("clr","a");
+    emitcode("subb","a,b");
+    emitcode("mov","b,a");
+    emitcode("","%05d$:",(lbl->key+100));
+
+    /* now we are done */
+    aopPut(AOP(result),"b",0);
+    if(size > 0){
+        emitcode("mov","c,b.7");
+        emitcode("subb","a,acc");   
+    }
+    while (size--)
+        aopPut(AOP(result),"a",offset++);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genDiv - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void genDiv (iCode *ic)
+{
+    operand *left = IC_LEFT(ic);
+    operand *right = IC_RIGHT(ic);
+    operand *result= IC_RESULT(ic);   
+
+    D(emitcode(";", "genDiv "););
+
+    /* assign the amsops */
+    AOP_OP_3(ic);
+#if 0
+    aopOp (left,ic,FALSE, FALSE);
+    aopOp (right,ic,FALSE, TRUE);
+    aopOp (result,ic,TRUE, FALSE);
+#endif
+
+    /* special cases first */
+    /* both are bits */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right)== AOP_CRY) {
+        genDivbits(left,right,result);
+        goto release ;
+    }
+
+    /* if both are of size == 1 */
+    if (AOP_SIZE(left) == 1 &&
+        AOP_SIZE(right) == 1 ) {
+        genDivOneByte(left,right,result);
+        goto release ;
+    }
+
+    /* should have been converted to function call */
+    assert(1);
+release :
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* genModbits :- modulus of bits                                   */
+/*-----------------------------------------------------------------*/
+static void genModbits (operand *left, 
+                        operand *right, 
+                        operand *result)
+{
+
+    char *l;
+
+    /* the result must be bit */    
+    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
+    l = aopGet(AOP(left),0,FALSE,FALSE);
+
+    MOVA(l);       
+
+    emitcode("div","ab");
+    emitcode("mov","a,b");
+    emitcode("rrc","a");
+    aopPut(AOP(result),"c",0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genModOneByte : 8 bit modulus                                   */
+/*-----------------------------------------------------------------*/
+static void genModOneByte (operand *left,
+                           operand *right,
+                           operand *result)
+{
+    link *opetype = operandType(result);
+    char *l ;
+    symbol *lbl ;
+
+    /* signed or unsigned */
+    if (SPEC_USIGN(opetype)) {
+        /* unsigned is easy */
+        emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
+        l = aopGet(AOP(left),0,FALSE,FALSE);
+        MOVA(l);    
+        emitcode("div","ab");
+        aopPut(AOP(result),"b",0);
+        return ;
+    }
+
+    /* signed is a little bit more difficult */
+
+    /* save the signs of the operands */
+    l = aopGet(AOP(left),0,FALSE,FALSE);    
+    MOVA(l);
+
+    emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
+    emitcode("push","acc"); /* save it on the stack */
+
+    /* now sign adjust for both left & right */
+    l =  aopGet(AOP(right),0,FALSE,FALSE);    
+    MOVA(l);
+
+    lbl = newiTempLabel(NULL);
+    emitcode("jnb","acc.7,%05d$",(lbl->key+100));  
+    emitcode("cpl","a");   
+    emitcode("inc","a");
+    emitcode("","%05d$:",(lbl->key+100));
+    emitcode("mov","b,a"); 
+
+    /* sign adjust left side */
+    l =  aopGet(AOP(left),0,FALSE,FALSE);    
+    MOVA(l);
+
+    lbl = newiTempLabel(NULL);
+    emitcode("jnb","acc.7,%05d$",(lbl->key+100));
+    emitcode("cpl","a");   
+    emitcode("inc","a");
+    emitcode("","%05d$:",(lbl->key+100));
+
+    /* now the multiplication */
+    emitcode("div","ab");
+    /* we are interested in the lower order
+    only */
+    lbl = newiTempLabel(NULL);
+    emitcode("pop","acc");   
+    /* if there was an over flow we don't 
+    adjust the sign of the result */
+    emitcode("jb","ov,%05d$",(lbl->key+100));
+    emitcode("jnb","acc.7,%05d$",(lbl->key+100));
+    CLRC ;
+    emitcode("clr","a");
+    emitcode("subb","a,b");
+    emitcode("mov","b,a");
+    emitcode("","%05d$:",(lbl->key+100));
+
+    /* now we are done */
+    aopPut(AOP(result),"b",0);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genMod - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void genMod (iCode *ic)
+{
+    operand *left = IC_LEFT(ic);
+    operand *right = IC_RIGHT(ic);
+    operand *result= IC_RESULT(ic);  
+
+    D(emitcode(";", "genMod "););
+
+    /* assign the amsops */
+    AOP_OP_3(ic);
+#if 0
+    aopOp (left,ic,FALSE, FALSE);
+    aopOp (right,ic,FALSE, TRUE);
+    aopOp (result,ic,TRUE, FALSE);
+#endif
+
+    /* special cases first */
+    /* both are bits */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right)== AOP_CRY) {
+        genModbits(left,right,result);
+        goto release ;
+    }
+
+    /* if both are of size == 1 */
+    if (AOP_SIZE(left) == 1 &&
+        AOP_SIZE(right) == 1 ) {
+        genModOneByte(left,right,result);
+        goto release ;
+    }
+
+    /* should have been converted to function call */
+    assert(1);
+
+release :
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfxJump :- will create a jump depending on the ifx           */
+/*-----------------------------------------------------------------*/
+static void genIfxJump (iCode *ic, char *jval)
+{
+    symbol *jlbl ;
+    symbol *tlbl = newiTempLabel(NULL);
+    char *inst;
+
+    D(emitcode(";", "genIfxJump "););
+
+    /* if true label then we jump if condition
+    supplied is true */
+    if ( IC_TRUE(ic) ) {
+        jlbl = IC_TRUE(ic);
+        inst = ((strcmp(jval,"a") == 0 ? "jz" :
+                 (strcmp(jval,"c") == 0 ? "jnc" : "jnb" )));
+    }
+    else {
+        /* false label is present */
+        jlbl = IC_FALSE(ic) ;
+        inst = ((strcmp(jval,"a") == 0 ? "jnz" :
+                 (strcmp(jval,"c") == 0 ? "jc" : "jb" )));              
+    }
+    if (strcmp(inst,"jb") == 0 || strcmp(inst,"jnb") == 0) 
+        emitcode(inst,"%s,%05d$",jval,(tlbl->key+100));
+    else
+        emitcode(inst,"%05d$",tlbl->key+100);
+    emitcode("ljmp","%05d$",jlbl->key+100);
+    emitcode("","%05d$:",tlbl->key+100);                
+
+    /* mark the icode as generated */
+    ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmp :- greater or less than comparison                       */
+/*-----------------------------------------------------------------*/
+static void genCmp (operand *left,operand *right,
+                    operand *result, iCode *ifx, int sign)
+{
+    int size, offset = 0 ;
+    unsigned long lit = 0L;
+    bool swappedOps = FALSE;
+
+    D(emitcode(";", "genCmp"););
+
+#if 0
+    /* If left if lit and right isn't, swap 'em. */
+    if (AOP_TYPE(left) == AOP_LIT &&
+        AOP_TYPE(right) != AOP_LIT)
+    {
+        operand *tmp = left;
+        left = right;
+        right = tmp;
+        D(emitcode(";", "kevin literal hack"););
+        swappedOps = !swappedOps;
+    }
+
+    if (AOP_NEEDSACC(right))
+    {
+        if (AOP_NEEDSACC(left))
+        {
+            werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+                   "both CMP operands need ACC!");
+            exit(-1);
+        }
+        else
+        {
+            operand *tmp = left;
+            left = right;
+            right = tmp;
+            D(emitcode(";", "kevin ACC hack"););
+            swappedOps = !swappedOps;
+        }
+    }
+#endif
+
+    /* if left & right are bit variables */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right) == AOP_CRY ) {
+        emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+        emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
+    } 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, do cjne left,#right,zz */
+        if((size == 1) && !sign &&
+           (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
+            symbol *lbl  = newiTempLabel(NULL);
+            emitcode("cjne","%s,%s,%05d$",
+                     aopGet(AOP(left),offset,FALSE,FALSE),
+                     aopGet(AOP(right),offset,FALSE,FALSE),
+                     lbl->key+100);
+            emitcode("","%05d$:",lbl->key+100);
+        } 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){
+                        CLRC;
+                    }
+                    else{
+                        MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE));
+                        if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx){
+                            genIfxJump (ifx,"acc.7");
+                            return;
+                        }
+                        else    
+                            emitcode("rlc","a");
+                    }
+                    goto release;
+                }
+            }
+            CLRC;
+            while (size--)
+            {
+                emitcode(";", "genCmp #1: %d/%d/%d", size, sign, offset);
+                MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
+                emitcode(";", "genCmp #2");
+                if (sign && (size == 0))
+                {
+                    emitcode(";", "genCmp #3");
+                    emitcode("xrl","a,#0x80");
+                    if (AOP_TYPE(right) == AOP_LIT)
+                    {
+                        unsigned long lit = (unsigned long)
+                            floatFromVal(AOP(right)->aopu.aop_lit);
+                        emitcode(";", "genCmp #3.1");
+                        emitcode("subb","a,#0x%02x",
+                            0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));
+                    }
+                    else
+                    {
+                        emitcode(";", "genCmp #3.2");
+                        if (AOP_NEEDSACC(right))
+                        {
+                            emitcode("push", "acc");
+                        }
+                        emitcode("mov","b,%s",aopGet(AOP(right),offset++,
+                                  FALSE,FALSE));
+                        emitcode("xrl","b,#0x80");
+                        if (AOP_NEEDSACC(right))
+                        {
+                            emitcode("pop", "acc");
+                        }
+                        emitcode("subb","a,b");
+                    }
+                }
+                else
+                {
+                    const char *s;
+
+                    emitcode(";", "genCmp #4");
+                    if (AOP_NEEDSACC(right))
+                    {
+                        /* Yuck!! */
+                        emitcode(";", "genCmp #4.1");
+                        emitcode("xch", "a, b");
+                        MOVA(aopGet(AOP(right),offset++,FALSE,FALSE));
+                        emitcode("xch", "a, b");
+                        s = "b";
+                    }
+                    else
+                    {
+                        emitcode(";", "genCmp #4.2");
+                        s = aopGet(AOP(right),offset++,FALSE,FALSE);
+                    }
+
+                    emitcode("subb","a,%s",s);
+                }
+            }
+        }
+    }
+
+release:
+    if (swappedOps)
+    {
+        D(emitcode(";","kevHack: flip carry."););
+        emitcode("cpl", "c");
+    }
+
+    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 ;
+
+    D(emitcode(";", "genCmpGt "););
+
+    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 */
+    AOP_OP_3(ic);
+#if 0
+    aopOp (left,ic,FALSE, TRUE);
+    aopOp (right,ic,FALSE, FALSE);
+    aopOp (result,ic,TRUE, FALSE);
+#endif
+
+    genCmp(right, left, result, ifx, sign);
+
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpLt - less than comparisons                                */
+/*-----------------------------------------------------------------*/
+static void genCmpLt (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    link *letype , *retype;
+    int sign ;
+
+    D(emitcode(";", "genCmpLt "););
+
+    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 */
+    AOP_OP_3(ic);
+#if 0
+    aopOp (left,ic,FALSE, FALSE);
+    aopOp (right,ic,FALSE, TRUE);
+    aopOp (result,ic,TRUE, FALSE);
+#endif
+
+    genCmp(left, right, result, ifx, sign);
+
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE); 
+}
+
+/*-----------------------------------------------------------------*/
+/* 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;
+
+    D(emitcode(";", "gencjneshort"););
+
+    /* if the left side is a literal or 
+    if the right is in a pointer register and left 
+    is not */
+    if ((AOP_TYPE(left) == AOP_LIT) || 
+        (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
+        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--) {
+            char *l = aopGet(AOP(left), offset, FALSE, FALSE);
+            MOVA(l);
+            emitcode("cjne","a,%s,%05d$",
+                     aopGet(AOP(right),offset,FALSE,FALSE),
+                     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) ||
+             (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
+        while (size--) {
+            MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
+            if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
+               ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
+                emitcode("jnz","%05d$",lbl->key+100);
+            else
+                emitcode("cjne","a,%s,%05d$",
+                         aopGet(AOP(right),offset,FALSE,TRUE),
+                         lbl->key+100);
+            offset++;
+        }
+    } else {
+        /* right is a pointer reg need both a & b */
+        while(size--) {
+            char *l = aopGet(AOP(left),offset,FALSE,FALSE);
+            if(strcmp(l,"b"))
+                emitcode("mov","b,%s",l);
+            MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+            emitcode("cjne","a,b,%05d$",lbl->key+100);    
+            offset++;
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* gencjne - compare and jump if not equal                         */
+/*-----------------------------------------------------------------*/
+static void gencjne(operand *left, operand *right, symbol *lbl)
+{
+    symbol *tlbl  = newiTempLabel(NULL);
+
+    D(emitcode(";", "gencjne"););
+
+    gencjneshort(left, right, lbl);
+
+    emitcode("mov","a,%s",one);
+    emitcode("sjmp","%05d$",tlbl->key+100);
+    emitcode("","%05d$:",lbl->key+100);
+    emitcode("clr","a");
+    emitcode("","%05d$:",tlbl->key+100);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpEq - generates code for equal to                          */
+/*-----------------------------------------------------------------*/
+static void genCmpEq (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+
+    D(emitcode(";", "genCmpEq "););
+
+    AOP_OP_3(ic);
+    AOP_SET_LOCALS(ic);
+#if 0
+    aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
+#endif
+
+    /* if literal, literal on the right or 
+    if the right is in a pointer register and left 
+    is not */
+    if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
+        (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
+        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))) {
+            if(AOP_TYPE(right) == AOP_LIT){
+                unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+                if(lit == 0L){
+                    emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                    emitcode("cpl","c");
+                } else if(lit == 1L) {
+                    emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                } else {
+                    emitcode("clr","c");
+                }
+                /* AOP_TYPE(right) == AOP_CRY */
+            } else {
+                symbol *lbl = newiTempLabel(NULL);
+                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
+                emitcode("cpl","c");
+                emitcode("","%05d$:",(lbl->key+100));
+            }
+            /* if true label then we jump if condition
+            supplied is true */
+            tlbl = newiTempLabel(NULL);
+            if ( IC_TRUE(ifx) ) {
+                emitcode("jnc","%05d$",tlbl->key+100);
+                emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
+            } else {
+                emitcode("jc","%05d$",tlbl->key+100);
+                emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
+            }
+            emitcode("","%05d$:",tlbl->key+100);                
+        } else {
+            tlbl = newiTempLabel(NULL);
+            gencjneshort(left, right, tlbl);
+            if ( IC_TRUE(ifx) ) {
+                emitcode("ljmp","%05d$",IC_TRUE(ifx)->key+100);
+                emitcode("","%05d$:",tlbl->key+100);                
+            } else {
+                symbol *lbl = newiTempLabel(NULL);
+                emitcode("sjmp","%05d$",lbl->key+100);
+                emitcode("","%05d$:",tlbl->key+100);                
+                emitcode("ljmp","%05d$",IC_FALSE(ifx)->key+100);
+                emitcode("","%05d$:",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))) {
+        if(AOP_TYPE(right) == AOP_LIT){
+            unsigned long lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+            if(lit == 0L){
+                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                emitcode("cpl","c");
+            } else if(lit == 1L) {
+                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+            } else {
+                emitcode("clr","c");
+            }
+            /* AOP_TYPE(right) == AOP_CRY */
+        } else {
+            symbol *lbl = newiTempLabel(NULL);
+            emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+            emitcode("jb","%s,%05d$",AOP(right)->aopu.aop_dir,(lbl->key+100));
+            emitcode("cpl","c");
+            emitcode("","%05d$:",(lbl->key+100));
+        }
+        /* c = 1 if egal */
+        if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
+            outBitC(result);
+            goto release ;
+        }
+        if (ifx) {
+            genIfxJump (ifx,"c");
+            goto release ;
+        }
+        /* if the result is used in an arithmetic operation
+        then put the result in place */
+        outBitC(result);
+    } else {
+        gencjne(left,right,newiTempLabel(NULL));    
+        if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
+            aopPut(AOP(result),"a",0);
+            goto release ;
+        }
+        if (ifx) {
+            genIfxJump (ifx,"a");
+            goto release ;
+        }
+        /* if the result is used in an arithmetic operation
+        then put the result in place */
+        if (AOP_TYPE(result) != AOP_CRY) 
+            outAcc(result);
+        /* leave the result in acc */
+    }
+
+release:
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* ifxForOp - returns the icode containing the ifx for operand     */
+/*-----------------------------------------------------------------*/
+static iCode *ifxForOp ( operand *op, iCode *ic )
+{
+    /* if true symbol then needs to be assigned */
+    if (IS_TRUE_SYMOP(op))
+        return NULL ;
+
+    /* if this has register type condition and
+    the next instruction is ifx with the same operand
+    and live to of the operand is upto the ifx only then */
+    if (ic->next &&
+        ic->next->op == IFX &&
+        IC_COND(ic->next)->key == op->key &&
+        OP_SYMBOL(op)->liveTo <= ic->next->seq )
+        return ic->next;
+
+    return NULL;
+}
+/*-----------------------------------------------------------------*/
+/* genAndOp - for && operation                                     */
+/*-----------------------------------------------------------------*/
+static void genAndOp (iCode *ic)
+{
+    operand *left,*right, *result;
+    symbol *tlbl;
+
+    D(emitcode(";", "genAndOp "););
+
+    /* note here that && operations that are in an
+    if statement are taken away by backPatchLabels
+    only those used in arthmetic operations remain */
+    AOP_OP_3(ic);
+    AOP_SET_LOCALS(ic);
+#if 0
+    aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
+    aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
+#endif
+
+    /* if both are bit variables */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right) == AOP_CRY ) {
+        emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+        emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
+        outBitC(result);
+    } else {
+        tlbl = newiTempLabel(NULL);
+        toBoolean(left);    
+        emitcode("jz","%05d$",tlbl->key+100);
+        toBoolean(right);
+        emitcode("","%05d$:",tlbl->key+100);
+        outBitAcc(result);
+    }
+
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genOrOp - for || operation                                      */
+/*-----------------------------------------------------------------*/
+static void genOrOp (iCode *ic)
+{
+    operand *left,*right, *result;
+    symbol *tlbl;
+
+    D(emitcode(";", "genOrOp "););
+
+    /* note here that || operations that are in an
+    if statement are taken away by backPatchLabels
+    only those used in arthmetic operations remain */
+    AOP_OP_3(ic);
+    AOP_SET_LOCALS(ic);
+#if 0
+    aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
+    aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
+#endif
+
+    /* if both are bit variables */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right) == AOP_CRY ) {
+        emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+        emitcode("orl","c,%s",AOP(right)->aopu.aop_dir);
+        outBitC(result);
+    } else {
+        tlbl = newiTempLabel(NULL);
+        toBoolean(left);
+        emitcode("jnz","%05d$",tlbl->key+100);
+        toBoolean(right);
+        emitcode("","%05d$:",tlbl->key+100);
+        outBitAcc(result);
+    }
+
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE);            
+}
+
+/*-----------------------------------------------------------------*/
+/* isLiteralBit - test if lit == 2^n                               */
+/*-----------------------------------------------------------------*/
+static int isLiteralBit(unsigned long lit)
+{
+    unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
+    0x100L,0x200L,0x400L,0x800L,
+    0x1000L,0x2000L,0x4000L,0x8000L,
+    0x10000L,0x20000L,0x40000L,0x80000L,
+    0x100000L,0x200000L,0x400000L,0x800000L,
+    0x1000000L,0x2000000L,0x4000000L,0x8000000L,
+    0x10000000L,0x20000000L,0x40000000L,0x80000000L};
+    int idx;
+    
+    for(idx = 0; idx < 32; idx++)
+        if(lit == pw[idx])
+            return idx+1;
+    return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* continueIfTrue -                                                */
+/*-----------------------------------------------------------------*/
+static void continueIfTrue (iCode *ic)
+{
+    if(IC_TRUE(ic))
+        emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
+    ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* jmpIfTrue -                                                     */
+/*-----------------------------------------------------------------*/
+static void jumpIfTrue (iCode *ic)
+{
+    if(!IC_TRUE(ic))
+        emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
+    ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* jmpTrueOrFalse -                                                */
+/*-----------------------------------------------------------------*/
+static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
+{
+    // ugly but optimized by peephole
+    if(IC_TRUE(ic)){
+        symbol *nlbl = newiTempLabel(NULL);
+        emitcode("sjmp","%05d$",nlbl->key+100);                 
+        emitcode("","%05d$:",tlbl->key+100);
+        emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
+        emitcode("","%05d$:",nlbl->key+100);
+    }
+    else{
+        emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
+        emitcode("","%05d$:",tlbl->key+100);
+    }
+    ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* 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;
+    char buffer[10];
+
+    D(emitcode(";", "genAnd "););
+
+    AOP_OP_3(ic);
+    AOP_SET_LOCALS(ic);
+#if 0
+    aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
+#endif
+
+#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(bit & yy)
+    // result = bit & yy;
+    if (AOP_TYPE(left) == AOP_CRY){
+        // c = bit & literal;
+        if(AOP_TYPE(right) == AOP_LIT){
+            if(lit & 1) {
+                if(size && sameRegs(AOP(result),AOP(left)))
+                    // no change
+                    goto release;
+                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+            } else {
+                // bit(result) = 0;
+                if(size && (AOP_TYPE(result) == AOP_CRY)){
+                    emitcode("clr","%s",AOP(result)->aopu.aop_dir);
+                    goto release;
+                }
+                if((AOP_TYPE(result) == AOP_CRY) && ifx){
+                    jumpIfTrue(ifx);
+                    goto release;
+                }
+                emitcode("clr","c");
+            }
+        } else {
+            if (AOP_TYPE(right) == AOP_CRY){
+                // c = bit & bit;
+                emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+                emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
+            } else {
+                // c = bit & val;
+                MOVA(aopGet(AOP(right),0,FALSE,FALSE));
+                // c = lsb
+                emitcode("rrc","a");
+                emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
+            }
+        }
+        // bit = c
+        // val = c
+        if(size)
+            outBitC(result);
+        // if(bit & ...)
+        else if((AOP_TYPE(result) == AOP_CRY) && ifx)
+            genIfxJump(ifx, "c");           
+        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,FALSE));
+            // bit = left & 2^n
+            if(size)
+                emitcode("mov","c,acc.%d",posbit&0x07);
+            // if(left &  2^n)
+            else{
+                if(ifx){
+                    sprintf(buffer,"acc.%d",posbit&0x07);
+                    genIfxJump(ifx, buffer);
+                }
+                goto release;
+            }
+        } else {
+            symbol *tlbl = newiTempLabel(NULL);
+            int sizel = AOP_SIZE(left);
+            if(size)
+                emitcode("setb","c");
+            while(sizel--){
+                if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
+                    MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
+                    // byte ==  2^n ?
+                    if((posbit = isLiteralBit(bytelit)) != 0)
+                        emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
+                    else{
+                        if(bytelit != 0x0FFL)
+                            emitcode("anl","a,%s",
+                                     aopGet(AOP(right),offset,FALSE,TRUE));
+                        emitcode("jnz","%05d$",tlbl->key+100);
+                    }
+                }
+                offset++;
+            }
+            // bit = left & literal
+            if(size){
+                emitcode("clr","c");
+                emitcode("","%05d$:",tlbl->key+100);
+            }
+            // if(left & literal)
+            else{
+                if(ifx)
+                    jmpTrueOrFalse(ifx, tlbl);
+                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 
+                       if (IS_AOP_PREG(result)) {
+                           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                           emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
+                           aopPut(AOP(result),"a",offset);
+                       } else
+                           emitcode("anl","%s,%s",
+                                    aopGet(AOP(left),offset,FALSE,TRUE),
+                                    aopGet(AOP(right),offset,FALSE,FALSE));
+            } else {
+               if (AOP_TYPE(left) == AOP_ACC)
+                   emitcode("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
+               else {
+                   MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                   if (IS_AOP_PREG(result)) {
+                       emitcode("anl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
+                       aopPut(AOP(result),"a",offset);
+
+                   } else
+                       emitcode("anl","%s,a",
+                                aopGet(AOP(left),offset,FALSE,TRUE));
+               }
+            }
+        }
+    } else {
+        // left & result in different registers
+        if(AOP_TYPE(result) == AOP_CRY){
+            // result = bit
+            // if(size), result in bit
+            // if(!size && ifx), conditional oper: if(left & right)
+            symbol *tlbl = newiTempLabel(NULL);
+            int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
+            if(size)
+                emitcode("setb","c");
+            while(sizer--){
+                MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                emitcode("anl","a,%s",
+                         aopGet(AOP(left),offset,FALSE,FALSE));
+                emitcode("jnz","%05d$",tlbl->key+100);
+                offset++;
+            }
+            if(size){
+                CLRC;
+                emitcode("","%05d$:",tlbl->key+100);
+                outBitC(result);
+            } else if(ifx)
+                jmpTrueOrFalse(ifx, tlbl);
+        } 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,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("anl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
+               else {
+                   MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                   emitcode("anl","a,%s",
+                            aopGet(AOP(left),offset,FALSE,FALSE));
+               }
+               aopPut(AOP(result),"a",offset);
+           }
+       }
+    }
+
+release :
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE);     
+}
+
+/*-----------------------------------------------------------------*/
+/* genOr  - code for or                                            */
+/*-----------------------------------------------------------------*/
+static void genOr (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    int size, offset=0;
+    unsigned long lit = 0L;
+
+    D(emitcode(";", "genOr "););
+
+    AOP_OP_3(ic);
+    AOP_SET_LOCALS(ic);
+    #if 0
+    aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
+    #endif
+
+#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(bit | yy)
+    // xx = bit | yy;
+    if (AOP_TYPE(left) == AOP_CRY){
+        if(AOP_TYPE(right) == AOP_LIT){
+            // c = bit & literal;
+            if(lit){
+                // lit != 0 => result = 1
+                if(AOP_TYPE(result) == AOP_CRY){
+                    if(size)
+                        emitcode("setb","%s",AOP(result)->aopu.aop_dir);
+                    else if(ifx)
+                        continueIfTrue(ifx);
+                    goto release;
+                }
+                emitcode("setb","c");
+            } else {
+                // lit == 0 => result = left
+                if(size && sameRegs(AOP(result),AOP(left)))
+                    goto release;
+                emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+            }
+        } else {
+            if (AOP_TYPE(right) == AOP_CRY){
+                // c = bit | bit;
+                emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+                emitcode("orl","c,%s",AOP(left)->aopu.aop_dir);
+            }
+            else{
+                // c = bit | val;
+                symbol *tlbl = newiTempLabel(NULL);
+                if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
+                    emitcode("setb","c");
+                emitcode("jb","%s,%05d$",
+                         AOP(left)->aopu.aop_dir,tlbl->key+100);
+                toBoolean(right);
+                emitcode("jnz","%05d$",tlbl->key+100);
+                if((AOP_TYPE(result) == AOP_CRY) && ifx){
+                    jmpTrueOrFalse(ifx, tlbl);
+                    goto release;
+                } else {
+                    CLRC;
+                    emitcode("","%05d$:",tlbl->key+100);
+                }
+            }
+        }
+        // bit = c
+        // val = c
+        if(size)
+            outBitC(result);
+        // if(bit | ...)
+        else if((AOP_TYPE(result) == AOP_CRY) && ifx)
+            genIfxJump(ifx, "c");           
+        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)){
+        if(lit){
+            // result = 1
+            if(size)
+                emitcode("setb","%s",AOP(result)->aopu.aop_dir);
+            else 
+                continueIfTrue(ifx);
+            goto release;
+        } else {
+            // lit = 0, result = boolean(left)
+            if(size)
+                emitcode("setb","c");
+            toBoolean(right);
+            if(size){
+                symbol *tlbl = newiTempLabel(NULL);
+                emitcode("jnz","%05d$",tlbl->key+100);
+                CLRC;
+                emitcode("","%05d$:",tlbl->key+100);
+            } else {
+                genIfxJump (ifx,"a");
+                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(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
+                    continue;
+                else 
+                   if (IS_AOP_PREG(left)) {
+                       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                       emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
+                       aopPut(AOP(result),"a",offset);
+                   } else
+                       emitcode("orl","%s,%s",
+                                aopGet(AOP(left),offset,FALSE,TRUE),
+                                aopGet(AOP(right),offset,FALSE,FALSE));
+            } else {
+               if (AOP_TYPE(left) == AOP_ACC) 
+                   emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
+               else {              
+                   MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                   if (IS_AOP_PREG(left)) {
+                       emitcode("orl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
+                       aopPut(AOP(result),"a",offset);
+                   } else
+                       emitcode("orl","%s,a",
+                                aopGet(AOP(left),offset,FALSE,TRUE));
+               }
+            }
+        }
+    } else {
+        // left & result in different registers
+        if(AOP_TYPE(result) == AOP_CRY){
+            // result = bit
+            // if(size), result in bit
+            // if(!size && ifx), conditional oper: if(left | right)
+            symbol *tlbl = newiTempLabel(NULL);
+            int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
+            if(size)
+                emitcode("setb","c");
+            while(sizer--){
+                MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                emitcode("orl","a,%s",
+                         aopGet(AOP(left),offset,FALSE,FALSE));
+                emitcode("jnz","%05d$",tlbl->key+100);
+                offset++;
+            }
+            if(size){
+                CLRC;
+                emitcode("","%05d$:",tlbl->key+100);
+                outBitC(result);
+            } else if(ifx)
+                jmpTrueOrFalse(ifx, tlbl);
+        } 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,FALSE),
+                           offset);
+                    continue;
+                }
+            }
+            // faster than result <- left, anl result,right
+            // and better if result is SFR
+           if (AOP_TYPE(left) == AOP_ACC) 
+               emitcode("orl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
+           else {
+               MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+               emitcode("orl","a,%s",
+                        aopGet(AOP(left),offset,FALSE,FALSE));
+           }
+           aopPut(AOP(result),"a",offset);                     
+        }
+    }
+
+release :
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE);     
+}
+
+/*-----------------------------------------------------------------*/
+/* genXor - code for xclusive or                                   */
+/*-----------------------------------------------------------------*/
+static void genXor (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    int size, offset=0;
+    unsigned long lit = 0L;
+
+    D(emitcode(";", "genXor "););
+
+    AOP_OP_3(ic);
+    AOP_SET_LOCALS(ic);
+#if 0
+    aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right= IC_RIGHT(ic)),ic,FALSE, TRUE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
+#endif
+
+#ifdef DEBUG_TYPE
+    emitcode("","; Type res[%d] = l[%d]&r[%d]",
+             AOP_TYPE(result),
+             AOP_TYPE(left), AOP_TYPE(right));
+    emitcode("","; Size res[%d] = l[%d]&r[%d]",
+             AOP_SIZE(result),
+             AOP_SIZE(left), AOP_SIZE(right));
+#endif
+
+    /* if left is a literal & right is not ||
+       if left needs acc & right does not */
+    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
+       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
+        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(bit ^ yy)
+    // xx = bit ^ yy;
+    if (AOP_TYPE(left) == AOP_CRY){
+        if(AOP_TYPE(right) == AOP_LIT){
+            // c = bit & literal;
+            if(lit>>1){
+                // lit>>1  != 0 => result = 1
+                if(AOP_TYPE(result) == AOP_CRY){
+                    if(size)
+                        emitcode("setb","%s",AOP(result)->aopu.aop_dir);
+                    else if(ifx)
+                        continueIfTrue(ifx);
+                    goto release;
+                }
+                emitcode("setb","c");
+            } else{
+                // lit == (0 or 1)
+                if(lit == 0){
+                    // lit == 0, result = left
+                    if(size && sameRegs(AOP(result),AOP(left)))
+                        goto release;
+                    emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                } else{
+                    // lit == 1, result = not(left)
+                    if(size && sameRegs(AOP(result),AOP(left))){
+                        emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
+                        goto release;
+                    } else {
+                        emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
+                        emitcode("cpl","c");
+                    }
+                }
+            }
+
+        } else {
+            // right != literal
+            symbol *tlbl = newiTempLabel(NULL);
+            if (AOP_TYPE(right) == AOP_CRY){
+                // c = bit ^ bit;
+                emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+            }
+            else{
+                int sizer = AOP_SIZE(right);
+                // c = bit ^ val
+                // if val>>1 != 0, result = 1
+                emitcode("setb","c");
+                while(sizer){
+                    MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
+                    if(sizer == 1)
+                        // test the msb of the lsb
+                        emitcode("anl","a,#0xfe");
+                    emitcode("jnz","%05d$",tlbl->key+100);
+                   sizer--;
+                }
+                // val = (0,1)
+                emitcode("rrc","a");
+            }
+            emitcode("jnb","%s,%05d$",AOP(left)->aopu.aop_dir,(tlbl->key+100));
+            emitcode("cpl","c");
+            emitcode("","%05d$:",(tlbl->key+100));
+        }
+        // bit = c
+        // val = c
+        if(size)
+            outBitC(result);
+        // if(bit | ...)
+        else if((AOP_TYPE(result) == AOP_CRY) && ifx)
+            genIfxJump(ifx, "c");           
+        goto release ;
+    }
+
+    if(sameRegs(AOP(result),AOP(left))){
+        /* if left is same as result */
+        for(;size--; offset++) {
+            if(AOP_TYPE(right) == AOP_LIT){
+                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
+                    continue;
+                else
+                   if (IS_AOP_PREG(left)) {
+                       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                       emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
+                       aopPut(AOP(result),"a",offset);
+                   } else 
+                       emitcode("xrl","%s,%s",
+                                aopGet(AOP(left),offset,FALSE,TRUE),
+                                aopGet(AOP(right),offset,FALSE,FALSE));
+            } else {
+               if (AOP_TYPE(left) == AOP_ACC)
+                   emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
+               else {
+                   MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                   if (IS_AOP_PREG(left)) {
+                       emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
+                       aopPut(AOP(result),"a",offset);
+                   } else
+                       emitcode("xrl","%s,a",
+                                aopGet(AOP(left),offset,FALSE,TRUE));
+               }
+            }
+        }
+    } else {
+        // left & result in different registers
+        if(AOP_TYPE(result) == AOP_CRY){
+            // result = bit
+            // if(size), result in bit
+            // if(!size && ifx), conditional oper: if(left ^ right)
+            symbol *tlbl = newiTempLabel(NULL);
+            int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
+            if(size)
+                emitcode("setb","c");
+            while(sizer--){
+                if((AOP_TYPE(right) == AOP_LIT) &&
+                   (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
+                    MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
+                } else {
+                    MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+                    emitcode("xrl","a,%s",
+                             aopGet(AOP(left),offset,FALSE,FALSE));
+                }
+                emitcode("jnz","%05d$",tlbl->key+100);
+                offset++;
+            }
+            if(size){
+                CLRC;
+                emitcode("","%05d$:",tlbl->key+100);
+                outBitC(result);
+            } else if(ifx)
+                jmpTrueOrFalse(ifx, tlbl);
+        } 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,FALSE),
+                           offset);
+                    continue;
+                }
+            }
+            // faster than result <- left, anl result,right
+            // and better if result is SFR
+           if (AOP_TYPE(left) == AOP_ACC)
+               emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
+           else {
+               MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
+               emitcode("xrl","a,%s",
+                        aopGet(AOP(left),offset,FALSE,TRUE));
+           }
+           aopPut(AOP(result),"a",offset);
+        }
+    }
+
+release :
+    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+    freeAsmop(result,NULL,ic,TRUE);     
+}
+
+/*-----------------------------------------------------------------*/
+/* genInline - write the inline code out                           */
+/*-----------------------------------------------------------------*/
+static void genInline (iCode *ic)
+{
+    char buffer[MAX_INLINEASM];
+    char *bp = buffer;
+    char *bp1= buffer;
+    
+    D(emitcode(";", "genInline "););
+
+    _G.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); */
+    _G.inLine -= (!options.asmpeep);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRRC - rotate right with carry                                */
+/*-----------------------------------------------------------------*/
+static void genRRC (iCode *ic)
+{
+    operand *left , *result ;
+    int size, offset = 0;
+    char *l;    
+
+    D(emitcode(";", "genRRC "););
+
+    /* rotate right with carry */
+    left = IC_LEFT(ic);
+    result=IC_RESULT(ic);
+    aopOp (left,ic,FALSE, FALSE);
+    aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
+
+    /* move it to the result */
+    size = AOP_SIZE(result);    
+    offset = size - 1 ;
+    CLRC;
+    while (size--) {
+        l = aopGet(AOP(left),offset,FALSE,FALSE);
+        MOVA(l);
+        emitcode("rrc","a");
+        if (AOP_SIZE(result) > 1)
+            aopPut(AOP(result),"a",offset--);
+    }
+    /* now we need to put the carry into the
+    highest order byte of the result */
+    if (AOP_SIZE(result) > 1) {
+        l = aopGet(AOP(result),AOP_SIZE(result)-1,FALSE,FALSE);
+        MOVA(l);
+    }
+    emitcode("mov","acc.7,c");
+    aopPut(AOP(result),"a",AOP_SIZE(result)-1);
+    freeAsmop(left,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRLC - generate code for rotate left with carry               */
+/*-----------------------------------------------------------------*/
+static void genRLC (iCode *ic)
+{    
+    operand *left , *result ;
+    int size, offset = 0;
+    char *l;    
+
+    D(emitcode(";", "genRLC "););
+
+    /* rotate right with carry */
+    left = IC_LEFT(ic);
+    result=IC_RESULT(ic);
+    aopOp (left,ic,FALSE, FALSE);
+    aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
+
+    /* move it to the result */
+    size = AOP_SIZE(result);    
+    offset = 0 ;
+    if (size--) {
+        l = aopGet(AOP(left),offset,FALSE,FALSE);
+        MOVA(l);
+        emitcode("add","a,acc");
+        if (AOP_SIZE(result) > 1)
+            aopPut(AOP(result),"a",offset++);
+        while (size--) {
+            l = aopGet(AOP(left),offset,FALSE,FALSE);
+            MOVA(l);
+            emitcode("rlc","a");
+            if (AOP_SIZE(result) > 1)
+                aopPut(AOP(result),"a",offset++);
+        }
+    }
+    /* now we need to put the carry into the
+    highest order byte of the result */
+    if (AOP_SIZE(result) > 1) {
+        l = aopGet(AOP(result),0,FALSE,FALSE);
+        MOVA(l);
+    }
+    emitcode("mov","acc.0,c");
+    aopPut(AOP(result),"a",0);
+    freeAsmop(left,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGetHbit - generates code get highest order bit               */
+/*-----------------------------------------------------------------*/
+static void genGetHbit (iCode *ic)
+{
+    operand *left, *result;
+    left = IC_LEFT(ic);
+    result=IC_RESULT(ic);
+    aopOp (left,ic,FALSE, FALSE);
+    aopOp (result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
+
+    D(emitcode(";", "genGetHbit "););
+
+    /* get the highest order byte into a */
+    MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
+    if(AOP_TYPE(result) == AOP_CRY){
+        emitcode("rlc","a");
+        outBitC(result);
+    }
+    else{
+        emitcode("rl","a");
+        emitcode("anl","a,#0x01");
+        outAcc(result);
+    }
+
+
+    freeAsmop(left,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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("swap","a");
+            emitcode("rr","a");
+            break;
+        case 4 :
+            emitcode("swap","a");
+            break;
+        case 5 :
+            emitcode("swap","a");
+            emitcode("rl","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,acc");
+        else 
+           if(shCount == 2) {
+            emitcode("add","a,acc");
+            emitcode("add","a,acc");
+        } else {
+            /* rotate left accumulator */
+            AccRol(shCount);
+            /* and kill the lower order bits */
+            emitcode("anl","a,#0x%02x", SLMask[shCount]);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccRsh - right shift accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void AccRsh (int shCount)
+{
+    if(shCount != 0){
+        if(shCount == 1){
+            CLRC;
+            emitcode("rrc","a");
+        } else {
+            /* rotate right accumulator */
+            AccRol(8 - shCount);
+            /* and kill the higher order bits */
+            emitcode("anl","a,#0x%02x", SRMask[shCount]);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccSRsh - signed right shift accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void AccSRsh (int shCount)
+{
+    symbol *tlbl ;
+    if(shCount != 0){
+        if(shCount == 1){
+            emitcode("mov","c,acc.7");
+            emitcode("rrc","a");
+        } else if(shCount == 2){
+            emitcode("mov","c,acc.7");
+            emitcode("rrc","a");
+            emitcode("mov","c,acc.7");
+            emitcode("rrc","a");
+        } else {
+            tlbl = newiTempLabel(NULL);
+            /* rotate right accumulator */
+            AccRol(8 - shCount);
+            /* and kill the higher order bits */
+            emitcode("anl","a,#0x%02x", SRMask[shCount]);
+            emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100);
+            emitcode("orl","a,#0x%02x",
+                     (unsigned char)~SRMask[shCount]);
+            emitcode("","%05d$:",tlbl->key+100);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* 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,FALSE));
+    /* shift right accumulator */
+    if(sign)
+        AccSRsh(shCount);
+    else
+        AccRsh(shCount);
+    aopPut(AOP(result),"a",offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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,FALSE);
+    MOVA(l);
+    /* shift left accumulator */
+    AccLsh(shCount);
+    aopPut(AOP(result),"a",offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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,FALSE);
+
+        if (*l == '@' && (IS_AOP_PREG(result))) {
+            emitcode("mov","a,%s",l);
+            aopPut(AOP(result),"a",offr);
+        } else {
+            if(!sign)
+                aopPut(AOP(result),l,offr);
+            else{
+                /* MSB sign in acc.7 ! */
+                if(getDataSize(left) == offl+1){
+                    emitcode("mov","a,%s",l);
+                    aopPut(AOP(result),"a",offr);
+                }
+            }
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXRrl1 - right rotate c->a:x->c by 1                         */
+/*-----------------------------------------------------------------*/
+static void AccAXRrl1 (char *x)
+{
+    emitcode("rrc","a");
+    emitcode("xch","a,%s", x);
+    emitcode("rrc","a");
+    emitcode("xch","a,%s", x);
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
+/*-----------------------------------------------------------------*/
+static void AccAXLrl1 (char *x)
+{
+    emitcode("xch","a,%s",x);
+    emitcode("rlc","a");
+    emitcode("xch","a,%s",x);
+    emitcode("rlc","a");
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXLsh1 - left shift a:x<-0 by 1                              */
+/*-----------------------------------------------------------------*/
+static void AccAXLsh1 (char *x)
+{
+    emitcode("xch","a,%s",x);
+    emitcode("add","a,acc");
+    emitcode("xch","a,%s",x);
+    emitcode("rlc","a");
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXLsh - left shift a:x by known count (0..7)                 */
+/*-----------------------------------------------------------------*/
+static void AccAXLsh (char *x, int shCount)
+{
+    switch(shCount){
+        case 0 :
+            break;
+        case 1 :
+            AccAXLsh1(x);
+            break;
+        case 2 :
+            AccAXLsh1(x);
+            AccAXLsh1(x);
+            break;
+        case 3 :
+        case 4 :
+        case 5 :                        // AAAAABBB:CCCCCDDD
+            AccRol(shCount);            // BBBAAAAA:CCCCCDDD
+            emitcode("anl","a,#0x%02x",
+                     SLMask[shCount]);  // BBB00000:CCCCCDDD
+            emitcode("xch","a,%s",x);   // CCCCCDDD:BBB00000
+            AccRol(shCount);            // DDDCCCCC:BBB00000
+            emitcode("xch","a,%s",x);   // BBB00000:DDDCCCCC
+            emitcode("xrl","a,%s",x);   // (BBB^DDD)CCCCC:DDDCCCCC
+            emitcode("xch","a,%s",x);   // DDDCCCCC:(BBB^DDD)CCCCC
+            emitcode("anl","a,#0x%02x",
+                     SLMask[shCount]);  // DDD00000:(BBB^DDD)CCCCC
+            emitcode("xch","a,%s",x);   // (BBB^DDD)CCCCC:DDD00000
+            emitcode("xrl","a,%s",x);   // BBBCCCCC:DDD00000            
+            break;
+        case 6 :                        // AAAAAABB:CCCCCCDD
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 000000BB:CCCCCCDD
+            emitcode("mov","c,acc.0");  // c = B
+            emitcode("xch","a,%s",x);   // CCCCCCDD:000000BB
+            AccAXRrl1(x);               // BCCCCCCD:D000000B
+            AccAXRrl1(x);               // BBCCCCCC:DD000000
+            break;
+        case 7 :                        // a:x <<= 7
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 0000000B:CCCCCCCD
+            emitcode("mov","c,acc.0");  // c = B
+            emitcode("xch","a,%s",x);   // CCCCCCCD:0000000B
+            AccAXRrl1(x);               // BCCCCCCC:D0000000
+            break;
+        default :
+            break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXRsh - right shift a:x known count (0..7)                   */
+/*-----------------------------------------------------------------*/
+static void AccAXRsh (char *x, int shCount)
+{   
+    switch(shCount){
+        case 0 :
+            break;
+        case 1 :
+            CLRC;
+            AccAXRrl1(x);               // 0->a:x
+            break;
+        case 2 :
+            CLRC;
+            AccAXRrl1(x);               // 0->a:x
+            CLRC;
+            AccAXRrl1(x);               // 0->a:x
+            break;
+        case 3 :
+        case 4 :
+        case 5 :                        // AAAAABBB:CCCCCDDD = a:x
+            AccRol(8 - shCount);        // BBBAAAAA:DDDCCCCC
+            emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
+            AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 000CCCCC:BBBAAAAA
+            emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
+            emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
+            emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
+            emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
+            emitcode("xch","a,%s",x);   // 000AAAAA:BBBCCCCC
+            break;
+        case 6 :                        // AABBBBBB:CCDDDDDD
+            emitcode("mov","c,acc.7");
+            AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
+            AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
+            emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 000000AA:BBBBBBCC
+            break;
+        case 7 :                        // ABBBBBBB:CDDDDDDD
+            emitcode("mov","c,acc.7");  // c = A
+            AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
+            emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 0000000A:BBBBBBBC
+            break;
+        default :
+            break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXRshS - right shift signed a:x known count (0..7)           */
+/*-----------------------------------------------------------------*/
+static void AccAXRshS (char *x, int shCount)
+{   
+    symbol *tlbl ;
+    switch(shCount){
+        case 0 :
+            break;
+        case 1 :
+            emitcode("mov","c,acc.7");
+            AccAXRrl1(x);               // s->a:x
+            break;
+        case 2 :
+            emitcode("mov","c,acc.7");
+            AccAXRrl1(x);               // s->a:x
+            emitcode("mov","c,acc.7");
+            AccAXRrl1(x);               // s->a:x
+            break;
+        case 3 :
+        case 4 :
+        case 5 :                        // AAAAABBB:CCCCCDDD = a:x
+            tlbl = newiTempLabel(NULL);
+            AccRol(8 - shCount);        // BBBAAAAA:CCCCCDDD
+            emitcode("xch","a,%s",x);   // CCCCCDDD:BBBAAAAA
+            AccRol(8 - shCount);        // DDDCCCCC:BBBAAAAA
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 000CCCCC:BBBAAAAA
+            emitcode("xrl","a,%s",x);   // BBB(CCCCC^AAAAA):BBBAAAAA
+            emitcode("xch","a,%s",x);   // BBBAAAAA:BBB(CCCCC^AAAAA)
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 000AAAAA:BBB(CCCCC^AAAAA)
+            emitcode("xch","a,%s",x);   // BBB(CCCCC^AAAAA):000AAAAA
+            emitcode("xrl","a,%s",x);   // BBBCCCCC:000AAAAA
+            emitcode("xch","a,%s",x);   // 000SAAAA:BBBCCCCC
+            emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
+            emitcode("orl","a,#0x%02x",
+                     (unsigned char)~SRMask[shCount]);  // 111AAAAA:BBBCCCCC
+            emitcode("","%05d$:",tlbl->key+100);
+            break;                      // SSSSAAAA:BBBCCCCC
+        case 6 :                        // AABBBBBB:CCDDDDDD
+            tlbl = newiTempLabel(NULL);
+            emitcode("mov","c,acc.7");
+            AccAXLrl1(x);               // ABBBBBBC:CDDDDDDA
+            AccAXLrl1(x);               // BBBBBBCC:DDDDDDAA
+            emitcode("xch","a,%s",x);   // DDDDDDAA:BBBBBBCC
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 000000AA:BBBBBBCC
+            emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
+            emitcode("orl","a,#0x%02x",
+                     (unsigned char)~SRMask[shCount]);  // 111111AA:BBBBBBCC
+            emitcode("","%05d$:",tlbl->key+100);
+            break;
+        case 7 :                        // ABBBBBBB:CDDDDDDD
+            tlbl = newiTempLabel(NULL);
+            emitcode("mov","c,acc.7");  // c = A
+            AccAXLrl1(x);               // BBBBBBBC:DDDDDDDA
+            emitcode("xch","a,%s",x);   // DDDDDDDA:BBBBBBCC
+            emitcode("anl","a,#0x%02x",
+                     SRMask[shCount]);  // 0000000A:BBBBBBBC
+            emitcode("jnb","acc.%d,%05d$",7-shCount,tlbl->key+100); 
+            emitcode("orl","a,#0x%02x",
+                     (unsigned char)~SRMask[shCount]);  // 1111111A:BBBBBBBC
+            emitcode("","%05d$:",tlbl->key+100);
+            break;
+        default :
+            break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* 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)){
+       /* don't crash result[offr] */
+       MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
+       emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
+    } else {
+       movLeft2Result(left,offl, result, offr, 0);
+       MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
+    }
+    /* ax << shCount (x = lsb(result))*/
+    AccAXLsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
+    aopPut(AOP(result),"a",offr+MSB16);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* 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)){
+       /* don't crash result[offr] */
+       MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
+       emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
+    } else {
+       movLeft2Result(left,offl, result, offr, 0);
+       MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
+    }
+    /* a:x >> shCount (x = lsb(result))*/
+    if(sign)
+        AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
+    else
+        AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
+    if(getDataSize(result) > 1)
+        aopPut(AOP(result),"a",offr+MSB16);
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftLLeftOrResult - shift left one byte from left, or to result*/
+/*-----------------------------------------------------------------*/
+static void shiftLLeftOrResult (operand *left, int offl,
+                                operand *result, int offr, int shCount)
+{
+    MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
+    /* shift left accumulator */
+    AccLsh(shCount);
+    /* or with result */
+    emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
+    /* back to result */
+    aopPut(AOP(result),"a",offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftRLeftOrResult - shift right one byte from left,or to result*/
+/*-----------------------------------------------------------------*/
+static void shiftRLeftOrResult (operand *left, int offl,
+                                operand *result, int offr, int shCount)
+{
+    MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
+    /* shift right accumulator */
+    AccRsh(shCount);
+    /* or with result */
+    emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
+    /* back to result */
+    aopPut(AOP(result),"a",offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshOne - left shift a one byte quantity by known count       */
+/*-----------------------------------------------------------------*/
+static void genlshOne (operand *result, operand *left, int shCount)
+{       
+    D(emitcode(";", "genlshOne "););
+    shiftL1Left2Result(left, LSB, result, LSB, shCount);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshTwo - left shift two bytes by known amount != 0           */
+/*-----------------------------------------------------------------*/
+static void genlshTwo (operand *result,operand *left, int shCount)
+{
+    int size;
+    
+    D(emitcode(";", "genlshTwo "););
+
+    size = getDataSize(result);
+
+    /* if shCount >= 8 */
+    if (shCount >= 8) {
+        shCount -= 8 ;
+
+        if (size > 1){
+            if (shCount)
+                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
+            else 
+                movLeft2Result(left, LSB, result, MSB16, 0);
+        }
+        aopPut(AOP(result),zero,LSB);   
+    }
+
+    /*  1 <= shCount <= 7 */
+    else {  
+        if(size == 1)
+            shiftL1Left2Result(left, LSB, result, LSB, shCount); 
+        else 
+            shiftL2Left2Result(left, LSB, result, LSB, shCount);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftLLong - shift left one long from left to result            */
+/* offl = LSB or MSB16                                             */
+/*-----------------------------------------------------------------*/
+static void shiftLLong (operand *left, operand *result, int offr )
+{
+    char *l;
+    int size = AOP_SIZE(result);
+
+    if(size >= LSB+offr){
+        l = aopGet(AOP(left),LSB,FALSE,FALSE);
+        MOVA(l);
+        emitcode("add","a,acc");
+       if (sameRegs(AOP(left),AOP(result)) && 
+           size >= MSB16+offr && offr != LSB )
+           emitcode("xch","a,%s",
+                    aopGet(AOP(left),LSB+offr,FALSE,FALSE));
+       else        
+           aopPut(AOP(result),"a",LSB+offr);
+    }
+
+    if(size >= MSB16+offr){
+       if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
+           l = aopGet(AOP(left),MSB16,FALSE,FALSE);
+           MOVA(l);
+       }
+        emitcode("rlc","a");
+       if (sameRegs(AOP(left),AOP(result)) && 
+           size >= MSB24+offr && offr != LSB)
+           emitcode("xch","a,%s",
+                    aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
+       else        
+           aopPut(AOP(result),"a",MSB16+offr);
+    }
+
+    if(size >= MSB24+offr){
+       if (!(sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
+           l = aopGet(AOP(left),MSB24,FALSE,FALSE);
+           MOVA(l);
+       }
+        emitcode("rlc","a");
+       if (sameRegs(AOP(left),AOP(result)) && 
+           size >= MSB32+offr && offr != LSB )
+           emitcode("xch","a,%s",
+                    aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
+       else        
+           aopPut(AOP(result),"a",MSB24+offr);
+    }
+
+    if(size > MSB32+offr){
+       if (!(sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
+           l = aopGet(AOP(left),MSB32,FALSE,FALSE);
+           MOVA(l);    
+       }
+        emitcode("rlc","a");
+        aopPut(AOP(result),"a",MSB32+offr);
+    }
+    if(offr != LSB)
+        aopPut(AOP(result),zero,LSB);       
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshFour - shift four byte by a known amount != 0             */
+/*-----------------------------------------------------------------*/
+static void genlshFour (operand *result, operand *left, int shCount)
+{
+    int size;
+
+    D(emitcode(";", "genlshFour "););
+
+    size = AOP_SIZE(result);
+
+    /* if shifting more that 3 bytes */
+    if (shCount >= 24 ) {
+        shCount -= 24;
+        if (shCount)
+            /* lowest order of left goes to the highest
+            order of the destination */
+            shiftL1Left2Result(left, LSB, result, MSB32, shCount);
+        else
+            movLeft2Result(left, LSB, result, MSB32, 0);
+        aopPut(AOP(result),zero,LSB);
+        aopPut(AOP(result),zero,MSB16);
+        aopPut(AOP(result),zero,MSB32);
+        return;
+    }
+
+    /* more than two bytes */
+    else if ( shCount >= 16 ) {
+        /* lower order two bytes goes to higher order two bytes */
+        shCount -= 16;
+        /* if some more remaining */
+        if (shCount)
+            shiftL2Left2Result(left, LSB, result, MSB24, shCount);
+        else {
+            movLeft2Result(left, MSB16, result, MSB32, 0);
+            movLeft2Result(left, LSB, result, MSB24, 0);
+        }
+        aopPut(AOP(result),zero,MSB16);
+        aopPut(AOP(result),zero,LSB);
+        return;
+    }    
+
+    /* if more than 1 byte */
+    else if ( shCount >= 8 ) {
+        /* lower order three bytes goes to higher order  three bytes */
+        shCount -= 8;
+        if(size == 2){
+            if(shCount)
+                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
+            else
+                movLeft2Result(left, LSB, result, MSB16, 0);
+        }
+        else{   /* size = 4 */
+            if(shCount == 0){
+                movLeft2Result(left, MSB24, result, MSB32, 0);
+                movLeft2Result(left, MSB16, result, MSB24, 0);
+                movLeft2Result(left, LSB, result, MSB16, 0);
+                aopPut(AOP(result),zero,LSB);
+            }
+            else if(shCount == 1)
+                shiftLLong(left, result, MSB16);
+            else{
+                shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
+                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
+                shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
+                aopPut(AOP(result),zero,LSB);
+            }
+        }
+    }
+
+    /* 1 <= shCount <= 7 */
+    else if(shCount <= 2){
+        shiftLLong(left, result, LSB);
+        if(shCount == 2)
+            shiftLLong(result, result, LSB);
+    }
+    /* 3 <= shCount <= 7, optimize */
+    else{
+        shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
+        shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
+        shiftL2Left2Result(left, LSB, result, LSB, shCount);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShiftLiteral - left shifting by known count              */
+/*-----------------------------------------------------------------*/
+static void genLeftShiftLiteral (operand *left,
+                                 operand *right,
+                                 operand *result,
+                                 iCode *ic)
+{    
+    int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
+    int size;
+
+    D(emitcode(";","genLeftShiftLiteral (%d)", shCount););
+
+    freeAsmop(right,NULL,ic,TRUE);
+
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, TRUE);
+
+    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){
+        while(size--){
+            movLeft2Result(left, size, result, size, 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:
+            case 3: /* bug: this is for generic pointers, I bet. */
+                genlshTwo (result,left,shCount);
+                break;
+
+            case 4:
+                genlshFour (result,left,shCount);
+                break;
+        }
+    }
+    freeAsmop(left,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShift - generates code for left shifting                 */
+/*-----------------------------------------------------------------*/
+static void genLeftShift (iCode *ic)
+{
+    operand *left,*right, *result;
+    int size, offset;
+    char *l;
+    symbol *tlbl , *tlbl1;
+
+    D(emitcode(";", "genLeftShift "););
+
+    right = IC_RIGHT(ic);
+    left  = IC_LEFT(ic);
+    result = IC_RESULT(ic);
+
+    aopOp(right,ic,FALSE, FALSE);
+
+    #if 0
+    /* 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 ;
+    }
+    #endif
+
+    /* 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("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
+    emitcode("inc","b");
+    freeAsmop (right,NULL,ic,TRUE);
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
+
+    /* now move the left to the result if they are not the
+    same */
+    if (!sameRegs(AOP(left),AOP(result)) && 
+        AOP_SIZE(result) > 1) {
+
+        size = AOP_SIZE(result);
+        offset=0;
+        while (size--) {
+            l = aopGet(AOP(left),offset,FALSE,TRUE);
+            if (*l == '@' && (IS_AOP_PREG(result))) {
+
+                emitcode("mov","a,%s",l);
+                aopPut(AOP(result),"a",offset);
+            } else
+                aopPut(AOP(result),l,offset);
+            offset++;
+        }
+    }
+
+    tlbl = newiTempLabel(NULL);
+    size = AOP_SIZE(result);
+    offset = 0 ;   
+    tlbl1 = newiTempLabel(NULL);
+
+    /* if it is only one byte then */
+    if (size == 1) {
+       symbol *tlbl1 = newiTempLabel(NULL);
+
+        l = aopGet(AOP(left),0,FALSE,FALSE);
+        MOVA(l);
+       emitcode("sjmp","%05d$",tlbl1->key+100); 
+        emitcode("","%05d$:",tlbl->key+100);
+        emitcode("add","a,acc");
+       emitcode("","%05d$:",tlbl1->key+100);
+        emitcode("djnz","b,%05d$",tlbl->key+100);      
+        aopPut(AOP(result),"a",0);
+        goto release ;
+    }
+    
+    reAdjustPreg(AOP(result));    
+    
+    emitcode("sjmp","%05d$",tlbl1->key+100); 
+    emitcode("","%05d$:",tlbl->key+100);    
+    l = aopGet(AOP(result),offset,FALSE,FALSE);
+    MOVA(l);
+    emitcode("add","a,acc");         
+    aopPut(AOP(result),"a",offset++);
+    while (--size) {
+        l = aopGet(AOP(result),offset,FALSE,FALSE);
+        MOVA(l);
+        emitcode("rlc","a");         
+        aopPut(AOP(result),"a",offset++);
+    }
+    reAdjustPreg(AOP(result));
+
+    emitcode("","%05d$:",tlbl1->key+100);
+    emitcode("djnz","b,%05d$",tlbl->key+100);
+release:
+    freeAsmop(left,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshOne - right shift a one byte quantity by known count      */
+/*-----------------------------------------------------------------*/
+static void genrshOne (operand *result, operand *left,
+                       int shCount, int sign)
+{
+    D(emitcode(";", "genrshOne"););
+    shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshTwo - right shift two bytes by known amount != 0          */
+/*-----------------------------------------------------------------*/
+static void genrshTwo (operand *result,operand *left,
+                       int shCount, int sign)
+{
+    D(emitcode(";", "genrshTwo"););
+
+    /* if shCount >= 8 */
+    if (shCount >= 8) {
+        shCount -= 8 ;
+        if (shCount)
+            shiftR1Left2Result(left, MSB16, result, LSB,
+                               shCount, sign);
+        else 
+            movLeft2Result(left, MSB16, result, LSB, sign);
+        addSign(result, MSB16, sign);
+    }
+
+    /*  1 <= shCount <= 7 */
+    else
+        shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftRLong - shift right one long from left to result           */
+/* offl = LSB or MSB16                                             */
+/*-----------------------------------------------------------------*/
+static void shiftRLong (operand *left, int offl,
+                        operand *result, int sign)
+{
+    if(!sign)
+        emitcode("clr","c");
+    MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
+    if(sign)
+        emitcode("mov","c,acc.7");
+    emitcode("rrc","a");
+    aopPut(AOP(result),"a",MSB32-offl);
+    if(offl == MSB16)
+        /* add sign of "a" */
+        addSign(result, MSB32, sign);
+
+    MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
+    emitcode("rrc","a");
+    aopPut(AOP(result),"a",MSB24-offl);
+
+    MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
+    emitcode("rrc","a");
+    aopPut(AOP(result),"a",MSB16-offl);
+
+    if(offl == LSB){
+        MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
+        emitcode("rrc","a");
+        aopPut(AOP(result),"a",LSB);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshFour - shift four byte by a known amount != 0             */
+/*-----------------------------------------------------------------*/
+static void genrshFour (operand *result, operand *left,
+                        int shCount, int sign)
+{
+    D(emitcode(";", "genrshFour"););
+    
+    /* if shifting more that 3 bytes */
+    if(shCount >= 24 ) {
+        shCount -= 24;
+        if(shCount)
+            shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
+        else
+            movLeft2Result(left, MSB32, result, LSB, sign);
+        addSign(result, MSB16, sign);
+    }
+    else if(shCount >= 16){
+        shCount -= 16;
+        if(shCount)
+            shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
+        else{
+            movLeft2Result(left, MSB24, result, LSB, 0);
+            movLeft2Result(left, MSB32, result, MSB16, sign);
+        }
+        addSign(result, MSB24, sign);
+    }
+    else if(shCount >= 8){
+        shCount -= 8;
+        if(shCount == 1)
+            shiftRLong(left, MSB16, result, sign);
+        else if(shCount == 0){
+            movLeft2Result(left, MSB16, result, LSB, 0);
+            movLeft2Result(left, MSB24, result, MSB16, 0);
+            movLeft2Result(left, MSB32, result, MSB24, sign);
+            addSign(result, MSB32, sign);
+        }
+        else{
+            shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
+            shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
+            /* the last shift is signed */
+            shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
+            addSign(result, MSB32, sign);
+        }
+    }
+    else{   /* 1 <= shCount <= 7 */
+        if(shCount <= 2){
+            shiftRLong(left, LSB, result, sign);
+            if(shCount == 2)
+                shiftRLong(result, LSB, result, sign);
+        }
+        else{
+            shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
+            shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
+            shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShiftLiteral - right shifting by known count            */
+/*-----------------------------------------------------------------*/
+static void genRightShiftLiteral (operand *left,
+                                  operand *right,
+                                  operand *result,
+                                  iCode *ic,
+                                  int sign)
+{    
+    int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
+    int size;
+
+    D(emitcode(";", "genRightShiftLiteral"););
+
+    freeAsmop(right,NULL,ic,TRUE);
+
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
+
+#if VIEW_SIZE
+    emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
+             AOP_SIZE(left));
+#endif
+
+    size = getDataSize(left);
+    /* test the LEFT size !!! */
+
+    /* I suppose that the left size >= result size */
+    if(shCount == 0){
+        size = getDataSize(result);
+        while(size--)
+            movLeft2Result(left, size, result, size, 0);
+    }
+
+    else if(shCount >= (size * 8)){
+        if(sign)
+            /* get sign in acc.7 */
+            MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
+        addSign(result, LSB, sign);
+    } else{
+        switch (size) {
+            case 1:
+                genrshOne (result,left,shCount,sign);
+                break;
+
+            case 2:
+                genrshTwo (result,left,shCount,sign);
+                break;
+
+            case 4:
+                genrshFour (result,left,shCount,sign);
+                break;
+            default :
+                break;
+        }
+
+        freeAsmop(left,NULL,ic,TRUE);
+        freeAsmop(result,NULL,ic,TRUE);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genSignedRightShift - right shift of signed number              */
+/*-----------------------------------------------------------------*/
+static void genSignedRightShift (iCode *ic)
+{
+    operand *right, *left, *result;
+    int size, offset;
+    char *l;
+    symbol *tlbl, *tlbl1 ;
+
+    D(emitcode(";", "genSignedRightShift "););
+
+    /* we do it the hard way put the shift count in b
+    and loop thru preserving the sign */
+
+    right = IC_RIGHT(ic);
+    left  = IC_LEFT(ic);
+    result = IC_RESULT(ic);
+
+    aopOp(right,ic,FALSE, FALSE);
+
+    #if 0
+    if ( AOP_TYPE(right) == AOP_LIT) {
+       genRightShiftLiteral (left,right,result,ic,1);
+       return ;
+    }
+    #endif
+        /* 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("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
+    emitcode("inc","b");
+    freeAsmop (right,NULL,ic,TRUE);
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
+
+    /* now move the left to the result if they are not the
+    same */
+    if (!sameRegs(AOP(left),AOP(result)) && 
+        AOP_SIZE(result) > 1) {
+
+        size = AOP_SIZE(result);
+        offset=0;
+        while (size--) {
+            l = aopGet(AOP(left),offset,FALSE,TRUE);
+            if (*l == '@' && IS_AOP_PREG(result)) {
+
+                emitcode("mov","a,%s",l);
+                aopPut(AOP(result),"a",offset);
+            } else
+                aopPut(AOP(result),l,offset);
+            offset++;
+        }
+    }
+
+    /* mov the highest order bit to OVR */    
+    tlbl = newiTempLabel(NULL);
+    tlbl1= newiTempLabel(NULL);
+
+    size = AOP_SIZE(result);
+    offset = size - 1;
+    emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
+    emitcode("rlc","a");
+    emitcode("mov","ov,c");
+    /* if it is only one byte then */
+    if (size == 1) {
+        l = aopGet(AOP(left),0,FALSE,FALSE);
+        MOVA(l);
+       emitcode("sjmp","%05d$",tlbl1->key+100);
+        emitcode("","%05d$:",tlbl->key+100);
+        emitcode("mov","c,ov");
+        emitcode("rrc","a");
+       emitcode("","%05d$:",tlbl1->key+100);
+        emitcode("djnz","b,%05d$",tlbl->key+100);
+        aopPut(AOP(result),"a",0);
+        goto release ;
+    }
+
+    reAdjustPreg(AOP(result));
+    emitcode("sjmp","%05d$",tlbl1->key+100);
+    emitcode("","%05d$:",tlbl->key+100);    
+    emitcode("mov","c,ov");
+    while (size--) {
+        l = aopGet(AOP(result),offset,FALSE,FALSE);
+        MOVA(l);
+        emitcode("rrc","a");         
+        aopPut(AOP(result),"a",offset--);
+    }
+    reAdjustPreg(AOP(result));
+    emitcode("","%05d$:",tlbl1->key+100);
+    emitcode("djnz","b,%05d$",tlbl->key+100);
+
+release:
+    freeAsmop(left,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShift - generate code for right shifting                */
+/*-----------------------------------------------------------------*/
+static void genRightShift (iCode *ic)
+{
+    operand *right, *left, *result;
+    link *retype ;
+    int size, offset;
+    char *l;
+    symbol *tlbl, *tlbl1 ;
+
+    D(emitcode(";", "genRightShift "););
+
+    /* if signed then we do it the hard way preserve the
+    sign bit moving it inwards */
+    retype = getSpec(operandType(IC_RESULT(ic)));
+
+    if (!SPEC_USIGN(retype)) {
+        genSignedRightShift (ic);
+        return ;
+    }
+
+    /* signed & unsigned types are treated the same : i.e. the
+    signed is NOT propagated inwards : quoting from the
+    ANSI - standard : "for E1 >> E2, is equivalent to division
+    by 2**E2 if unsigned or if it has a non-negative value,
+    otherwise the result is implementation defined ", MY definition
+    is that the sign does not get propagated */
+
+    right = IC_RIGHT(ic);
+    left  = IC_LEFT(ic);
+    result = IC_RESULT(ic);
+
+    aopOp(right,ic,FALSE, FALSE);
+
+    #if 0
+    /* if the shift count is known then do it 
+    as efficiently as possible */
+    if (AOP_TYPE(right) == AOP_LIT) {
+        genRightShiftLiteral (left,right,result,ic, 0);
+        return ;
+    }
+    #endif
+
+    /* 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("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
+    emitcode("inc","b");
+    freeAsmop (right,NULL,ic,TRUE);
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, AOP_TYPE(left) == AOP_DPTR);
+
+    /* now move the left to the result if they are not the
+    same */
+    if (!sameRegs(AOP(left),AOP(result)) && 
+        AOP_SIZE(result) > 1) {
+
+        size = AOP_SIZE(result);
+        offset=0;
+        while (size--) {
+            l = aopGet(AOP(left),offset,FALSE,TRUE);
+            if (*l == '@' && IS_AOP_PREG(result)) {
+
+                emitcode("mov","a,%s",l);
+                aopPut(AOP(result),"a",offset);
+            } else
+                aopPut(AOP(result),l,offset);
+            offset++;
+        }
+    }
+
+    tlbl = newiTempLabel(NULL);
+    tlbl1= newiTempLabel(NULL);
+    size = AOP_SIZE(result);
+    offset = size - 1;
+
+    /* if it is only one byte then */
+    if (size == 1) {
+        l = aopGet(AOP(left),0,FALSE,FALSE);
+        MOVA(l);
+       emitcode("sjmp","%05d$",tlbl1->key+100);
+        emitcode("","%05d$:",tlbl->key+100);
+        CLRC;
+        emitcode("rrc","a");
+       emitcode("","%05d$:",tlbl1->key+100);
+        emitcode("djnz","b,%05d$",tlbl->key+100);
+        aopPut(AOP(result),"a",0);
+        goto release ;
+    }
+
+    reAdjustPreg(AOP(result));
+    emitcode("sjmp","%05d$",tlbl1->key+100);
+    emitcode("","%05d$:",tlbl->key+100);    
+    CLRC;
+    while (size--) {
+        l = aopGet(AOP(result),offset,FALSE,FALSE);
+        MOVA(l);
+        emitcode("rrc","a");         
+        aopPut(AOP(result),"a",offset--);
+    }
+    reAdjustPreg(AOP(result));
+
+    emitcode("","%05d$:",tlbl1->key+100);
+    emitcode("djnz","b,%05d$",tlbl->key+100);
+
+release:
+    freeAsmop(left,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genUnpackBits - generates code for unpacking bits               */
+/*-----------------------------------------------------------------*/
+static void genUnpackBits (operand *result, char *rname, int ptype)
+{    
+    int shCnt ;
+    int rlen = 0 ;
+    link *etype;
+    int offset = 0 ;
+
+    D(emitcode(";", "genUnpackBits "););
+
+    etype = getSpec(operandType(result));
+
+    /* read the first byte  */
+    switch (ptype) {
+
+    case POINTER:
+    case IPOINTER:
+       emitcode("mov","a,@%s",rname);
+       break;
+       
+    case PPOINTER:
+       emitcode("movx","a,@%s",rname);
+       break;
+       
+    case FPOINTER:
+       emitcode("movx","a,@dptr");
+       break;
+
+    case CPOINTER:
+       emitcode("clr","a");
+       emitcode("movc","a","@a+dptr");
+       break;
+
+    case GPOINTER:
+       emitcode("lcall","__gptrget");
+       break;
+    }
+
+    /* if we have bitdisplacement then it fits   */
+    /* into this byte completely or if length is */
+    /* less than a byte                          */
+    if ((shCnt = SPEC_BSTR(etype)) || 
+        (SPEC_BLEN(etype) <= 8))  {
+
+        /* shift right acc */
+        AccRsh(shCnt);
+
+        emitcode("anl","a,#0x%02x",
+                 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
+        aopPut(AOP(result),"a",offset);
+        return ;
+    }
+
+    /* bit field did not fit in a byte  */
+    rlen = SPEC_BLEN(etype) - 8;
+    aopPut(AOP(result),"a",offset++);
+
+    while (1)  {
+
+       switch (ptype) {
+       case POINTER:
+       case IPOINTER:
+           emitcode("inc","%s",rname);
+           emitcode("mov","a,@%s",rname);
+           break;
+           
+       case PPOINTER:
+           emitcode("inc","%s",rname);
+           emitcode("movx","a,@%s",rname);
+           break;
+
+       case FPOINTER:
+           emitcode("inc","dptr");
+           emitcode("movx","a,@dptr");
+           break;
+           
+       case CPOINTER:
+           emitcode("clr","a");
+           emitcode("inc","dptr");
+           emitcode("movc","a","@a+dptr");
+           break;
+           
+       case GPOINTER:
+           emitcode("inc","dptr");
+           emitcode("lcall","__gptrget");
+           break;
+       }
+
+       rlen -= 8;            
+       /* if we are done */
+       if ( rlen <= 0 )
+           break ;
+       
+       aopPut(AOP(result),"a",offset++);
+                                     
+    }
+    
+    if (rlen) {
+       emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
+       aopPut(AOP(result),"a",offset);        
+    }
+    
+    return ;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genDataPointerGet - generates code when ptr offset is known     */
+/*-----------------------------------------------------------------*/
+static void genDataPointerGet (operand *left, 
+                              operand *result, 
+                              iCode *ic)
+{
+    char *l;
+    char buffer[256];
+    int size , offset = 0;
+    aopOp(result,ic,TRUE, FALSE);
+
+    /* get the string representation of the name */
+    l = aopGet(AOP(left),0,FALSE,TRUE);
+    size = AOP_SIZE(result);
+    while (size--) {
+       if (offset)
+           sprintf(buffer,"(%s + %d)",l+1,offset);
+       else
+           sprintf(buffer,"%s",l+1);
+       aopPut(AOP(result),buffer,offset++);
+    }
+
+    freeAsmop(left,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genNearPointerGet - emitcode for near pointer fetch             */
+/*-----------------------------------------------------------------*/
+static void genNearPointerGet (operand *left, 
+                              operand *result, 
+                              iCode *ic)
+{
+    asmop *aop = NULL;
+    regs *preg = NULL ;
+    char *rname ;
+    link *rtype, *retype;
+    link *ltype = operandType(left);    
+    char buffer[80];
+
+    rtype = operandType(result);
+    retype= getSpec(rtype);
+    
+    aopOp(left,ic,FALSE, FALSE);
+    
+    /* if left is rematerialisable and
+       result is not bit variable type and
+       the left is pointer to data space i.e
+       lower 128 bytes of space */
+    if (AOP_TYPE(left) == AOP_IMMD &&
+       !IS_BITVAR(retype)         &&
+       DCL_TYPE(ltype) == POINTER) {
+       genDataPointerGet (left,result,ic);
+       return ;
+    }
+    
+       /* if the value is already in a pointer register
+       then don't need anything more */
+    if (!AOP_INPREG(AOP(left))) {
+       /* otherwise get a free pointer register */
+       aop = newAsmop(0);
+       preg = getFreePtr(ic,&aop,FALSE);
+       emitcode("mov","%s,%s",
+               preg->name,
+               aopGet(AOP(left),0,FALSE,TRUE));
+       rname = preg->name ;
+    } else
+       rname = aopGet(AOP(left),0,FALSE,FALSE);
+    
+    freeAsmop(left,NULL,ic,TRUE);
+    aopOp (result,ic,FALSE, FALSE);
+    
+      /* if bitfield then unpack the bits */
+    if (IS_BITVAR(retype)) 
+       genUnpackBits (result,rname,POINTER);
+    else {
+       /* we have can just get the values */
+       int size = AOP_SIZE(result);
+       int offset = 0 ;        
+       
+       while (size--) {
+           if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
+
+               emitcode("mov","a,@%s",rname);
+               aopPut(AOP(result),"a",offset);
+           } else {
+               sprintf(buffer,"@%s",rname);
+               aopPut(AOP(result),buffer,offset);
+           }
+           offset++ ;
+           if (size)
+               emitcode("inc","%s",rname);
+       }
+    }
+
+    /* now some housekeeping stuff */
+    if (aop) {
+       /* we had to allocate for this iCode */
+       freeAsmop(NULL,aop,ic,TRUE);
+    } else { 
+       /* we did not allocate which means left
+          already in a pointer register, then
+          if size > 0 && this could be used again
+          we have to point it back to where it 
+          belongs */
+       if (AOP_SIZE(result) > 1 &&
+           !OP_SYMBOL(left)->remat &&
+           ( OP_SYMBOL(left)->liveTo > ic->seq ||
+             ic->depth )) {
+           int size = AOP_SIZE(result) - 1;
+           while (size--)
+               emitcode("dec","%s",rname);
+       }
+    }
+
+    /* done */
+    freeAsmop(result,NULL,ic,TRUE);
+     
+}
+
+/*-----------------------------------------------------------------*/
+/* genPagedPointerGet - emitcode for paged pointer fetch           */
+/*-----------------------------------------------------------------*/
+static void genPagedPointerGet (operand *left, 
+                              operand *result, 
+                              iCode *ic)
+{
+    asmop *aop = NULL;
+    regs *preg = NULL ;
+    char *rname ;
+    link *rtype, *retype;    
+
+    rtype = operandType(result);
+    retype= getSpec(rtype);
+    
+    aopOp(left,ic,FALSE, FALSE);
+
+  /* if the value is already in a pointer register
+       then don't need anything more */
+    if (!AOP_INPREG(AOP(left))) {
+       /* otherwise get a free pointer register */
+       aop = newAsmop(0);
+       preg = getFreePtr(ic,&aop,FALSE);
+       emitcode("mov","%s,%s",
+               preg->name,
+               aopGet(AOP(left),0,FALSE,TRUE));
+       rname = preg->name ;
+    } else
+       rname = aopGet(AOP(left),0,FALSE,FALSE);
+    
+    freeAsmop(left,NULL,ic,TRUE);
+    aopOp (result,ic,FALSE, FALSE);
+
+    /* if bitfield then unpack the bits */
+    if (IS_BITVAR(retype)) 
+       genUnpackBits (result,rname,PPOINTER);
+    else {
+       /* we have can just get the values */
+       int size = AOP_SIZE(result);
+       int offset = 0 ;        
+       
+       while (size--) {
+           
+           emitcode("movx","a,@%s",rname);
+           aopPut(AOP(result),"a",offset);
+           
+           offset++ ;
+           
+           if (size)
+               emitcode("inc","%s",rname);
+       }
+    }
+
+    /* now some housekeeping stuff */
+    if (aop) {
+       /* we had to allocate for this iCode */
+       freeAsmop(NULL,aop,ic,TRUE);
+    } else { 
+       /* we did not allocate which means left
+          already in a pointer register, then
+          if size > 0 && this could be used again
+          we have to point it back to where it 
+          belongs */
+       if (AOP_SIZE(result) > 1 &&
+           !OP_SYMBOL(left)->remat &&
+           ( OP_SYMBOL(left)->liveTo > ic->seq ||
+             ic->depth )) {
+           int size = AOP_SIZE(result) - 1;
+           while (size--)
+               emitcode("dec","%s",rname);
+       }
+    }
+
+    /* done */
+    freeAsmop(result,NULL,ic,TRUE);
+    
+       
+}
+
+/*-----------------------------------------------------------------*/
+/* genFarPointerGet - gget value from far space                    */
+/*-----------------------------------------------------------------*/
+static void genFarPointerGet (operand *left,
+                              operand *result, iCode *ic)
+{
+    int size, offset ;
+    link *retype = getSpec(operandType(result));
+
+    D(emitcode(";", "genFarPointerGet"););
+
+    aopOp(left,ic,FALSE, FALSE);
+
+    /* if the operand is already in dptr 
+    then we do nothing else we move the value to dptr */
+    if (AOP_TYPE(left) != AOP_STR) {
+        /* if this is remateriazable */
+        if (AOP_TYPE(left) == AOP_IMMD)
+            emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
+        else { /* we need to get it byte by byte */
+            emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
+            emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
+            }
+        }
+    }
+    /* so dptr know contains the address */
+    freeAsmop(left,NULL,ic,TRUE);
+    aopOp(result,ic,FALSE, TRUE);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) 
+        genUnpackBits(result,"dptr",FPOINTER);
+    else {
+        size = AOP_SIZE(result);
+        offset = 0 ;
+
+        while (size--) {
+            emitcode("movx","a,@dptr");
+            aopPut(AOP(result),"a",offset++);
+            if (size)
+                emitcode("inc","dptr");
+        }
+    }
+
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* emitcodePointerGet - gget value from code space                  */
+/*-----------------------------------------------------------------*/
+static void emitcodePointerGet (operand *left,
+                                operand *result, iCode *ic)
+{
+    int size, offset ;
+    link *retype = getSpec(operandType(result));
+
+    aopOp(left,ic,FALSE, FALSE);
+
+    /* if the operand is already in dptr 
+    then we do nothing else we move the value to dptr */
+    if (AOP_TYPE(left) != AOP_STR) {
+        /* if this is remateriazable */
+        if (AOP_TYPE(left) == AOP_IMMD)
+            emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
+        else { /* we need to get it byte by byte */
+            emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
+            emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
+            }
+        }
+    }
+    /* so dptr know contains the address */
+    freeAsmop(left,NULL,ic,TRUE);
+    aopOp(result,ic,FALSE, FALSE);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) 
+        genUnpackBits(result,"dptr",CPOINTER);
+    else {
+        size = AOP_SIZE(result);
+        offset = 0 ;
+
+        while (size--) {
+            emitcode("clr","a");
+            emitcode("movc","a,@a+dptr");
+            aopPut(AOP(result),"a",offset++);
+            if (size)
+                emitcode("inc","dptr");
+        }
+    }
+
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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, TRUE);
+
+    /* if the operand is already in dptr 
+    then we do nothing else we move the value to dptr */
+    if (AOP_TYPE(left) != AOP_STR) {
+        /* if this is remateriazable */
+        if (AOP_TYPE(left) == AOP_IMMD) {
+            emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
+           emitcode("mov","b,#%d",pointerCode(retype));
+       }
+        else { /* we need to get it byte by byte */
+            emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
+            emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
+               emitcode("mov","b,%s",aopGet(AOP(left),3,FALSE,FALSE));
+            }
+            else
+            {
+               emitcode("mov","b,%s",aopGet(AOP(left),2,FALSE,FALSE));
+            }
+        }
+    }
+    /* so dptr know contains the address */
+    freeAsmop(left,NULL,ic,TRUE);
+    aopOp(result,ic,FALSE, TRUE);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) 
+        genUnpackBits(result,"dptr",GPOINTER);
+    else {
+        size = AOP_SIZE(result);
+        offset = 0 ;
+
+        while (size--) {
+            emitcode("lcall","__gptrget");
+            aopPut(AOP(result),"a",offset++);
+            if (size)
+                emitcode("inc","dptr");
+        }
+    }
+
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerGet - generate code for pointer get                   */
+/*-----------------------------------------------------------------*/
+static void genPointerGet (iCode *ic)
+{
+    operand *left, *result ;
+    link *type, *etype;
+    int p_type;
+
+    D(emitcode(";", "genPointerGet "););
+
+    left = IC_LEFT(ic);
+    result = IC_RESULT(ic) ;
+
+    /* depending on the type of pointer we need to
+    move it to the correct pointer register */
+    type = operandType(left);
+    etype = getSpec(type);
+    /* if left is of type of pointer then it is simple */
+    if (IS_PTR(type) && !IS_FUNC(type->next)) 
+        p_type = DCL_TYPE(type);
+    else {
+       /* we have to go by the storage class */
+       p_type = PTR_TYPE(SPEC_OCLS(etype));
+
+/*     if (SPEC_OCLS(etype)->codesp ) { */
+/*         p_type = CPOINTER ;  */
+/*     } */
+/*     else */
+/*         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
+/*             p_type = FPOINTER ; */
+/*         else */
+/*             if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
+/*                 p_type = PPOINTER; */
+/*             else */
+/*                 if (SPEC_OCLS(etype) == idata ) */
+/*                     p_type = IPOINTER; */
+/*                 else */
+/*                     p_type = POINTER ; */
+    }
+
+    /* now that we have the pointer type we assign
+    the pointer values */
+    switch (p_type) {
+
+    case POINTER:      
+    case IPOINTER:
+       genNearPointerGet (left,result,ic);
+       break;
+
+    case PPOINTER:
+       genPagedPointerGet(left,result,ic);
+       break;
+
+    case FPOINTER:
+       genFarPointerGet (left,result,ic);
+       break;
+
+    case CPOINTER:
+       emitcodePointerGet (left,result,ic);
+       break;
+
+    case GPOINTER:
+       genGenPointerGet (left,result,ic);
+       break;
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genPackBits - generates code for packed bit storage             */
+/*-----------------------------------------------------------------*/
+static void genPackBits (link    *etype ,
+                         operand *right ,
+                         char *rname, int p_type)
+{
+    int shCount = 0 ;
+    int offset = 0  ;
+    int rLen = 0 ;
+    int blen, bstr ;   
+    char *l ;
+
+    blen = SPEC_BLEN(etype);
+    bstr = SPEC_BSTR(etype);
+
+    l = aopGet(AOP(right),offset++,FALSE,FALSE);
+    MOVA(l);   
+
+    /* if the bit lenth is less than or    */
+    /* it exactly fits a byte then         */
+    if (SPEC_BLEN(etype) <= 8 )  {
+        shCount = SPEC_BSTR(etype) ;
+
+        /* shift left acc */
+        AccLsh(shCount);
+
+        if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
+
+
+            switch (p_type) {
+                case POINTER:
+                    emitcode ("mov","b,a");
+                    emitcode("mov","a,@%s",rname);
+                    break;
+
+                case FPOINTER:
+                    emitcode ("mov","b,a");
+                    emitcode("movx","a,@dptr");
+                    break;
+
+                case GPOINTER:
+                    emitcode ("push","b");
+                    emitcode ("push","acc");
+                    emitcode ("lcall","__gptrget");
+                    emitcode ("pop","b");
+                    break;
+            }
+
+            emitcode ("anl","a,#0x%02x",(unsigned char)
+                      ((unsigned char)(0xFF << (blen+bstr)) | 
+                       (unsigned char)(0xFF >> (8-bstr)) ) );
+            emitcode ("orl","a,b");
+            if (p_type == GPOINTER)
+                emitcode("pop","b");
+        }
+    }
+
+    switch (p_type) {
+        case POINTER:
+            emitcode("mov","@%s,a",rname);
+            break;
+
+        case FPOINTER:
+            emitcode("movx","@dptr,a");
+            break;
+
+        case GPOINTER:
+            emitcode("lcall","__gptrput");
+            break;
+    }
+
+    /* if we r done */
+    if ( SPEC_BLEN(etype) <= 8 )
+        return ;
+
+    emitcode("inc","%s",rname);
+    rLen = SPEC_BLEN(etype) ;     
+
+    /* now generate for lengths greater than one byte */
+    while (1) {
+
+        l = aopGet(AOP(right),offset++,FALSE,TRUE);
+
+        rLen -= 8 ;
+        if (rLen <= 0 )
+            break ;
+
+        switch (p_type) {
+            case POINTER:
+                if (*l == '@') {
+                    MOVA(l);
+                    emitcode("mov","@%s,a",rname);
+                } else
+                    emitcode("mov","@%s,%s",rname,l);
+                break;
+
+            case FPOINTER:
+                MOVA(l);
+                emitcode("movx","@dptr,a");
+                break;
+
+            case GPOINTER:
+                MOVA(l);
+                emitcode("lcall","__gptrput");
+                break;  
+        }   
+        emitcode ("inc","%s",rname);
+    }
+
+    MOVA(l);
+
+    /* last last was not complete */
+    if (rLen)   {
+        /* save the byte & read byte */
+        switch (p_type) {
+            case POINTER:
+                emitcode ("mov","b,a");
+                emitcode("mov","a,@%s",rname);
+                break;
+
+            case FPOINTER:
+                emitcode ("mov","b,a");
+                emitcode("movx","a,@dptr");
+                break;
+
+            case GPOINTER:
+                emitcode ("push","b");
+                emitcode ("push","acc");
+                emitcode ("lcall","__gptrget");
+                emitcode ("pop","b");
+                break;
+        }
+
+        emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
+        emitcode ("orl","a,b");
+    }
+
+    if (p_type == GPOINTER)
+        emitcode("pop","b");
+
+    switch (p_type) {
+
+    case POINTER:
+       emitcode("mov","@%s,a",rname);
+       break;
+       
+    case FPOINTER:
+       emitcode("movx","@dptr,a");
+       break;
+       
+    case GPOINTER:
+       emitcode("lcall","__gptrput");
+       break;                  
+    }
+}
+/*-----------------------------------------------------------------*/
+/* genDataPointerSet - remat pointer to data space                 */
+/*-----------------------------------------------------------------*/
+static void genDataPointerSet(operand *right,
+                             operand *result,
+                             iCode *ic)
+{
+    int size, offset = 0 ;
+    char *l, buffer[256];
+
+    aopOp(right,ic,FALSE, FALSE);
+    
+    l = aopGet(AOP(result),0,FALSE,TRUE);
+    size = AOP_SIZE(right);
+    while (size--) {
+       if (offset)
+           sprintf(buffer,"(%s + %d)",l+1,offset);
+       else
+           sprintf(buffer,"%s",l+1);
+       emitcode("mov","%s,%s",buffer,
+                aopGet(AOP(right),offset++,FALSE,FALSE));
+    }
+
+    freeAsmop(right,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genNearPointerSet - emitcode for near pointer put                */
+/*-----------------------------------------------------------------*/
+static void genNearPointerSet (operand *right,
+                               operand *result, 
+                               iCode *ic)
+{
+    asmop *aop = NULL;
+    regs *preg = NULL ;
+    char *rname , *l;
+    link *retype;
+    link *ptype = operandType(result);
+    
+    retype= getSpec(operandType(right));
+
+    aopOp(result,ic,FALSE, FALSE);
+    
+    /* if the result is rematerializable &
+       in data space & not a bit variable */
+    if (AOP_TYPE(result) == AOP_IMMD &&
+       DCL_TYPE(ptype) == POINTER   &&
+       !IS_BITVAR(retype)) {
+       genDataPointerSet (right,result,ic);
+       return;
+    }
+
+    /* if the value is already in a pointer register
+    then don't need anything more */
+    if (!AOP_INPREG(AOP(result))) {
+        /* otherwise get a free pointer register */
+        aop = newAsmop(0);
+        preg = getFreePtr(ic,&aop,FALSE);
+        emitcode("mov","%s,%s",
+                 preg->name,
+                 aopGet(AOP(result),0,FALSE,TRUE));
+        rname = preg->name ;
+    } else
+        rname = aopGet(AOP(result),0,FALSE,FALSE);
+
+    freeAsmop(result,NULL,ic,TRUE);
+    aopOp (right,ic,FALSE, FALSE);
+
+    /* if bitfield then unpack the bits */
+    if (IS_BITVAR(retype)) 
+        genPackBits (retype,right,rname,POINTER);
+    else {
+        /* we have can just get the values */
+        int size = AOP_SIZE(right);
+        int offset = 0 ;    
+
+        while (size--) {
+            l = aopGet(AOP(right),offset,FALSE,TRUE);
+            if (*l == '@' ) {
+                MOVA(l);
+                emitcode("mov","@%s,a",rname);
+            } else
+                emitcode("mov","@%s,%s",rname,l);
+            if (size)
+                emitcode("inc","%s",rname);
+            offset++;
+        }
+    }
+
+    /* now some housekeeping stuff */
+    if (aop) {
+        /* we had to allocate for this iCode */
+        freeAsmop(NULL,aop,ic,TRUE);
+    } else { 
+        /* we did not allocate which means left
+        already in a pointer register, then
+        if size > 0 && this could be used again
+        we have to point it back to where it 
+        belongs */
+        if (AOP_SIZE(right) > 1 &&
+            !OP_SYMBOL(result)->remat &&
+            ( OP_SYMBOL(result)->liveTo > ic->seq ||
+              ic->depth )) {
+            int size = AOP_SIZE(right) - 1;
+            while (size--)
+                emitcode("dec","%s",rname);
+        }
+    }
+
+    /* done */
+    freeAsmop(right,NULL,ic,TRUE);
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genPagedPointerSet - emitcode for Paged pointer put             */
+/*-----------------------------------------------------------------*/
+static void genPagedPointerSet (operand *right,
+                              operand *result, 
+                              iCode *ic)
+{
+    asmop *aop = NULL;
+    regs *preg = NULL ;
+    char *rname , *l;
+    link *retype;
+       
+    retype= getSpec(operandType(right));
+    
+    aopOp(result,ic,FALSE, FALSE);
+    
+    /* if the value is already in a pointer register
+       then don't need anything more */
+    if (!AOP_INPREG(AOP(result))) {
+       /* otherwise get a free pointer register */
+       aop = newAsmop(0);
+       preg = getFreePtr(ic,&aop,FALSE);
+       emitcode("mov","%s,%s",
+               preg->name,
+               aopGet(AOP(result),0,FALSE,TRUE));
+       rname = preg->name ;
+    } else
+       rname = aopGet(AOP(result),0,FALSE,FALSE);
+    
+    freeAsmop(result,NULL,ic,TRUE);
+    aopOp (right,ic,FALSE, FALSE);
+
+    /* if bitfield then unpack the bits */
+    if (IS_BITVAR(retype)) 
+       genPackBits (retype,right,rname,PPOINTER);
+    else {
+       /* we have can just get the values */
+       int size = AOP_SIZE(right);
+       int offset = 0 ;        
+       
+       while (size--) {
+           l = aopGet(AOP(right),offset,FALSE,TRUE);
+           
+           MOVA(l);
+           emitcode("movx","@%s,a",rname);
+
+           if (size)
+               emitcode("inc","%s",rname);
+
+           offset++;
+       }
+    }
+    
+    /* now some housekeeping stuff */
+    if (aop) {
+       /* we had to allocate for this iCode */
+       freeAsmop(NULL,aop,ic,TRUE);
+    } else { 
+       /* we did not allocate which means left
+          already in a pointer register, then
+          if size > 0 && this could be used again
+          we have to point it back to where it 
+          belongs */
+       if (AOP_SIZE(right) > 1 &&
+           !OP_SYMBOL(result)->remat &&
+           ( OP_SYMBOL(result)->liveTo > ic->seq ||
+             ic->depth )) {
+           int size = AOP_SIZE(right) - 1;
+           while (size--)
+               emitcode("dec","%s",rname);
+       }
+    }
+
+    /* done */
+    freeAsmop(right,NULL,ic,TRUE);
+    
+       
+}
+
+/*-----------------------------------------------------------------*/
+/* genFarPointerSet - set value from far space                     */
+/*-----------------------------------------------------------------*/
+static void genFarPointerSet (operand *right,
+                              operand *result, iCode *ic)
+{
+    int size, offset ;
+    link *retype = getSpec(operandType(right));
+
+    aopOp(result,ic,FALSE, FALSE);
+
+    /* 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("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
+        else { /* we need to get it byte by byte */
+            emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
+            emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
+            }
+        }
+    }
+    /* so dptr know contains the address */
+    freeAsmop(result,NULL,ic,TRUE);
+    aopOp(right,ic,FALSE, FALSE);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) 
+        genPackBits(retype,right,"dptr",FPOINTER);
+    else {
+        size = AOP_SIZE(right);
+        offset = 0 ;
+
+        while (size--) {
+            char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
+            MOVA(l);
+            emitcode("movx","@dptr,a");
+            if (size)
+                emitcode("inc","dptr");
+        }
+    }
+
+    freeAsmop(right,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGenPointerSet - set value from generic pointer space         */
+/*-----------------------------------------------------------------*/
+static void genGenPointerSet (operand *right,
+                              operand *result, iCode *ic)
+{
+    int size, offset ;
+    link *retype = getSpec(operandType(right));
+
+    aopOp(result,ic,FALSE, TRUE);
+
+    /* 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("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
+            emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
+        }
+        else { /* we need to get it byte by byte */
+            emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
+            emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
+            if (options.model == MODEL_FLAT24)
+            {
+               emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
+               emitcode("mov","b,%s",aopGet(AOP(result),3,FALSE,FALSE));
+            }
+            else
+            {
+               emitcode("mov","b,%s",aopGet(AOP(result),2,FALSE,FALSE));
+            }
+        }
+    }
+    /* so dptr know contains the address */
+    freeAsmop(result,NULL,ic,TRUE);
+    aopOp(right,ic,FALSE, TRUE);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) 
+        genPackBits(retype,right,"dptr",GPOINTER);
+    else {
+        size = AOP_SIZE(right);
+        offset = 0 ;
+
+        while (size--) {
+            char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
+            MOVA(l);
+            emitcode("lcall","__gptrput");
+            if (size)
+                emitcode("inc","dptr");
+        }
+    }
+
+    freeAsmop(right,NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerSet - stores the value into a pointer location        */
+/*-----------------------------------------------------------------*/
+static void genPointerSet (iCode *ic)
+{    
+    operand *right, *result ;
+    link *type, *etype;
+    int p_type;
+
+    D(emitcode(";", "genPointerSet "););
+
+    right = IC_RIGHT(ic);
+    result = IC_RESULT(ic) ;
+
+    /* depending on the type of pointer we need to
+    move it to the correct pointer register */
+    type = operandType(result);
+    etype = getSpec(type);
+    /* if left is of type of pointer then it is simple */
+    if (IS_PTR(type) && !IS_FUNC(type->next)) {
+        p_type = DCL_TYPE(type);
+    }
+    else {
+       /* we have to go by the storage class */
+       p_type = PTR_TYPE(SPEC_OCLS(etype));
+
+/*     if (SPEC_OCLS(etype)->codesp ) { */
+/*         p_type = CPOINTER ;  */
+/*     } */
+/*     else */
+/*         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
+/*             p_type = FPOINTER ; */
+/*         else */
+/*             if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
+/*                 p_type = PPOINTER ; */
+/*             else */
+/*                 if (SPEC_OCLS(etype) == idata ) */
+/*                     p_type = IPOINTER ; */
+/*                 else */
+/*                     p_type = POINTER ; */
+    }
+
+    /* now that we have the pointer type we assign
+    the pointer values */
+    switch (p_type) {
+
+    case POINTER:
+    case IPOINTER:
+       genNearPointerSet (right,result,ic);
+       break;
+
+    case PPOINTER:
+       genPagedPointerSet (right,result,ic);
+       break;
+
+    case FPOINTER:
+       genFarPointerSet (right,result,ic);
+       break;
+
+    case GPOINTER:
+       genGenPointerSet (right,result,ic);
+       break;
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfx - generate code for Ifx statement                        */
+/*-----------------------------------------------------------------*/
+static void genIfx (iCode *ic, iCode *popIc)
+{
+    operand *cond = IC_COND(ic);
+    int isbit =0;
+
+    D(emitcode(";", "genIfx "););
+
+    aopOp(cond,ic,FALSE, 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,TRUE);
+
+    /* if there was something to be popped then do it */
+    if (popIc)
+        genIpop(popIc);
+
+    /* if the condition is  a bit variable */
+    if (isbit && IS_ITEMP(cond) && 
+       SPIL_LOC(cond))
+       genIfxJump(ic,SPIL_LOC(cond)->rname);
+    else
+       if (isbit && !IS_ITEMP(cond))
+           genIfxJump(ic,OP_SYMBOL(cond)->rname);
+       else
+           genIfxJump(ic,"a");
+
+    ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAddrOf - generates code for address of                       */
+/*-----------------------------------------------------------------*/
+static void genAddrOf (iCode *ic)
+{
+    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+    int size, offset ;
+
+    D(emitcode(";", "genAddrOf "););
+
+    aopOp(IC_RESULT(ic),ic,FALSE, 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 */
+        if (sym->stack) {
+            emitcode("mov","a,_bp");
+            emitcode("add","a,#0x%02x",((char) sym->stack & 0xff));
+            aopPut(AOP(IC_RESULT(ic)),"a",0);       
+        } else {
+            /* we can just move _bp */
+            aopPut(AOP(IC_RESULT(ic)),"_bp",0);
+        }
+        /* fill the result with zero */
+        size = AOP_SIZE(IC_RESULT(ic)) - 1;
+        
+        
+        if (options.stack10bit && size < (FPTRSIZE - 1))
+        {
+            fprintf(stderr, 
+                   "*** warning: pointer to stack var truncated.\n");
+        }
+        
+        offset = 1;
+        while (size--)
+        {
+            /* Yuck! */
+            if (options.stack10bit && offset == 2)
+            {
+                aopPut(AOP(IC_RESULT(ic)),"#0x40", offset++);
+            }
+            else
+            {
+               aopPut(AOP(IC_RESULT(ic)),zero,offset++);
+            }
+        }
+
+        goto release;
+    }
+
+    /* object not on stack then we need the name */
+    size = AOP_SIZE(IC_RESULT(ic));
+    offset = 0;
+
+    while (size--) {
+        char s[SDCC_NAME_MAX];
+        if (offset) 
+            sprintf(s,"#(%s >> %d)",
+                    sym->rname,
+                    offset*8);
+        else
+            sprintf(s,"#%s",sym->rname);
+        aopPut(AOP(IC_RESULT(ic)),s,offset++);
+    }
+
+release:
+    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genFarFarAssign - assignment when both are in far space         */
+/*-----------------------------------------------------------------*/
+static void genFarFarAssign (operand *result, operand *right, iCode *ic)
+{
+    int size = AOP_SIZE(right);
+    int offset = 0;
+    char *l ;
+    /* first push the right side on to the stack */
+    while (size--) {
+       l = aopGet(AOP(right),offset++,FALSE,FALSE);
+       MOVA(l);
+       emitcode ("push","acc");
+    }
+    
+    D(emitcode(";", "genFarFarAssign "););
+
+    freeAsmop(right,NULL,ic,FALSE);
+    /* now assign DPTR to result */
+    aopOp(result,ic,FALSE, FALSE);
+    size = AOP_SIZE(result);
+    while (size--) {
+       emitcode ("pop","acc");
+       aopPut(AOP(result),"a",--offset);
+    }
+    freeAsmop(result,NULL,ic,FALSE);
+       
+}
+
+/*-----------------------------------------------------------------*/
+/* genAssign - generate code for assignment                        */
+/*-----------------------------------------------------------------*/
+static void genAssign (iCode *ic)
+{
+    operand *result, *right;
+    int size, offset ;
+       unsigned long lit = 0L;
+
+    D(emitcode(";", "genAssign "););
+
+    result = IC_RESULT(ic);
+    right  = IC_RIGHT(ic) ;
+
+    /* if they are the same */
+    if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
+        return ;
+
+    aopOp(right,ic,FALSE, FALSE);
+    
+    emitcode(";", "genAssign: resultIsFar = %s",
+             isOperandInFarSpace(result) ?
+             "TRUE" : "FALSE");
+
+    /* special case both in far space */
+    if ((AOP_TYPE(right) == AOP_DPTR ||
+         AOP_TYPE(right) == AOP_DPTR2) &&
+    /* IS_TRUE_SYMOP(result)       && */
+    isOperandInFarSpace(result)) {
+       
+       genFarFarAssign (result,right,ic);
+       return ;
+    }
+
+    aopOp(result,ic,TRUE, FALSE);
+
+    /* if they are the same registers */
+    if (sameRegs(AOP(right),AOP(result)))
+        goto release;
+
+    /* if the result is a bit */
+    if (AOP_TYPE(result) == AOP_CRY) {
+
+        /* if the right size is a literal then
+        we know what the value is */
+        if (AOP_TYPE(right) == AOP_LIT) {
+            if (((int) operandLitValue(right))) 
+                aopPut(AOP(result),one,0);
+            else
+                aopPut(AOP(result),zero,0);
+            goto release;
+        }
+
+        /* the right is also a bit variable */
+        if (AOP_TYPE(right) == AOP_CRY) {
+            emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+            aopPut(AOP(result),"c",0);
+            goto release ;
+        }
+
+        /* we need to or */
+        toBoolean(right);
+        aopPut(AOP(result),"a",0);
+        goto release ;
+    }
+
+    /* bit variables done */
+    /* 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("clr","a");
+       while (size--) {
+           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
+               aopPut(AOP(result),"a",size);
+           else
+               aopPut(AOP(result),
+                      aopGet(AOP(right),size,FALSE,FALSE),
+                      size);
+       }
+    } else {
+       while (size--) {
+           aopPut(AOP(result),
+                  aopGet(AOP(right),offset,FALSE,FALSE),
+                  offset);
+           offset++;
+       }
+    }
+    
+release:
+    freeAsmop (right,NULL,ic,FALSE);
+    freeAsmop (result,NULL,ic,TRUE);
+}   
+
+/*-----------------------------------------------------------------*/
+/* genJumpTab - genrates code for jump table                       */
+/*-----------------------------------------------------------------*/
+static void genJumpTab (iCode *ic)
+{
+    symbol *jtab;
+    char *l;
+
+    D(emitcode(";", "genJumpTab "););
+
+    aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
+    /* get the condition into accumulator */
+    l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
+    MOVA(l);
+    /* multiply by three */
+    emitcode("add","a,acc");
+    emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
+    freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
+
+    jtab = newiTempLabel(NULL);
+    emitcode("mov","dptr,#%05d$",jtab->key+100);
+    emitcode("jmp","@a+dptr");
+    emitcode("","%05d$:",jtab->key+100);
+    /* now generate the jump labels */
+    for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
+         jtab = setNextItem(IC_JTLABELS(ic)))
+        emitcode("ljmp","%05d$",jtab->key+100);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genCast - gen code for casting                                  */
+/*-----------------------------------------------------------------*/
+static void genCast (iCode *ic)
+{
+    operand *result = IC_RESULT(ic);
+    link *ctype = operandType(IC_LEFT(ic));
+    link *rtype = operandType(IC_RIGHT(ic));
+    operand *right = IC_RIGHT(ic);
+    int size, offset ;
+
+    D(emitcode(";", "genCast "););
+
+    /* if they are equivalent then do nothing */
+    if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
+        return ;
+
+    aopOp(right,ic,FALSE, FALSE) ;
+    aopOp(result,ic,FALSE, AOP_TYPE(right) == AOP_DPTR);
+
+    /* if the result is a bit */
+    if (AOP_TYPE(result) == AOP_CRY) {
+        /* if the right size is a literal then
+        we know what the value is */
+        if (AOP_TYPE(right) == AOP_LIT) {
+            if (((int) operandLitValue(right))) 
+                aopPut(AOP(result),one,0);
+            else
+                aopPut(AOP(result),zero,0);
+
+            goto release;
+        }
+
+        /* the right is also a bit variable */
+        if (AOP_TYPE(right) == AOP_CRY) {
+            emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
+            aopPut(AOP(result),"c",0);
+            goto release ;
+        }
+
+        /* we need to or */
+        toBoolean(right);
+        aopPut(AOP(result),"a",0);
+        goto release ;
+    }
+
+    /* 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,FALSE),
+                   offset);
+            offset++;
+        }
+        goto release;
+    }
+
+
+    /* if the result is of type pointer */
+    if (IS_PTR(ctype)) {
+
+       int p_type;
+       link *type = operandType(right);
+       link *etype = getSpec(type);
+
+       /* pointer to generic pointer */
+       if (IS_GENPTR(ctype)) {
+           char *l = zero;
+           
+           if (IS_PTR(type)) 
+               p_type = DCL_TYPE(type);
+           else {
+               /* we have to go by the storage class */
+               p_type = PTR_TYPE(SPEC_OCLS(etype));
+           }
+               
+           /* the first two bytes are known */
+           size = GPTRSIZE - 1; 
+           offset = 0 ;
+           while (size--) {
+               aopPut(AOP(result),
+                      aopGet(AOP(right),offset,FALSE,FALSE),
+                      offset);
+               offset++;
+           }
+           /* the last byte depending on type */
+           switch (p_type) {
+           case IPOINTER:
+           case POINTER:
+               l = zero;
+               break;
+           case FPOINTER:
+               l = one;
+               break;
+           case CPOINTER:
+               l = "#0x02";
+               break;                          
+           case PPOINTER:
+               l = "#0x03";
+               break;
+               
+           default:
+               /* this should never happen */
+        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+                      "got unknown pointer type");
+               exit(1);
+           }
+           aopPut(AOP(result),l, GPTRSIZE - 1);            
+           goto release ;
+       }
+       
+       /* just copy the pointers */
+       size = AOP_SIZE(result);
+       offset = 0 ;
+       while (size--) {
+           aopPut(AOP(result),
+                  aopGet(AOP(right),offset,FALSE,FALSE),
+                  offset);
+           offset++;
+       }
+       goto release ;
+    }
+    
+    /* so we now know that the size of destination is greater
+    than the size of the source */
+    /* we move to result for the size of source */
+    size = AOP_SIZE(right);
+    offset = 0 ;
+    while (size--) {
+        aopPut(AOP(result),
+               aopGet(AOP(right),offset,FALSE,FALSE),
+               offset);
+        offset++;
+    }
+
+    /* now depending on the sign of the source && destination */
+    size = AOP_SIZE(result) - AOP_SIZE(right);
+    /* if unsigned or not an integral type */
+    if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
+        while (size--)
+            aopPut(AOP(result),zero,offset++);
+    } else {
+        /* we need to extend the sign :{ */
+        char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
+                         FALSE,FALSE);
+        MOVA(l);
+        emitcode("rlc","a");
+        emitcode("subb","a,acc");
+        while (size--)
+            aopPut(AOP(result),"a",offset++);   
+    }
+
+    /* we are done hurray !!!! */
+
+release:
+    freeAsmop(right,NULL,ic,TRUE);
+    freeAsmop(result,NULL,ic,TRUE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genDjnz - generate decrement & jump if not zero instrucion      */
+/*-----------------------------------------------------------------*/
+static int genDjnz (iCode *ic, iCode *ifx)
+{
+    symbol *lbl, *lbl1;
+    if (!ifx)
+       return 0;
+    
+    /* if the if condition has a false label
+       then we cannot save */
+    if (IC_FALSE(ifx))
+       return 0;
+
+    /* if the minus is not of the form 
+       a = a - 1 */
+    if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
+       !IS_OP_LITERAL(IC_RIGHT(ic)))
+       return 0;
+
+    if (operandLitValue(IC_RIGHT(ic)) != 1)
+       return 0;
+
+    /* if the size of this greater than one then no
+       saving */
+    if (getSize(operandType(IC_RESULT(ic))) > 1)
+       return 0;
+
+    /* otherwise we can save BIG */
+    lbl = newiTempLabel(NULL);
+    lbl1= newiTempLabel(NULL);
+
+    aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
+    
+    if (IS_AOP_PREG(IC_RESULT(ic))) {
+       emitcode("dec","%s",
+                aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+       emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+       emitcode("jnz","%05d$",lbl->key+100);
+    } else {   
+       emitcode ("djnz","%s,%05d$",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
+                 lbl->key+100);
+    }
+    emitcode ("sjmp","%05d$",lbl1->key+100);
+    emitcode ("","%05d$:",lbl->key+100);
+    emitcode ("ljmp","%05d$",IC_TRUE(ifx)->key+100);
+    emitcode ("","%05d$:",lbl1->key+100);
+    
+    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+    ifx->generated = 1;
+    return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genReceive - generate code for a receive iCode                  */
+/*-----------------------------------------------------------------*/
+static void genReceive (iCode *ic)
+{    
+
+    D(emitcode(";", "genReceive "););
+
+    if (isOperandInFarSpace(IC_RESULT(ic)) && 
+       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
+         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
+       int size = getSize(operandType(IC_RESULT(ic)));
+       int offset =  fReturnSize_390 - size;
+       while (size--) {
+           emitcode ("push","%s", (strcmp(fReturn[fReturnSize_390 - offset - 1],"a") ?
+                                   fReturn[fReturnSize_390 - offset - 1] : "acc"));
+           offset++;
+       }
+       aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
+       size = AOP_SIZE(IC_RESULT(ic));
+       offset = 0;
+       while (size--) {
+           emitcode ("pop","acc");
+           aopPut (AOP(IC_RESULT(ic)),"a",offset++);
+       }
+       
+    } else {
+       _G.accInUse++;
+       aopOp(IC_RESULT(ic),ic,FALSE, FALSE);  
+       _G.accInUse--;
+       assignResultValue(IC_RESULT(ic));       
+    }
+
+    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* gen390Code - generate code for 8051 based controllers            */
+/*-----------------------------------------------------------------*/
+void gen390Code (iCode *lic)
+{
+    iCode *ic;
+    int cln = 0;
+
+    lineHead = lineCurr = NULL;
+
+    /* print the allocation information */
+    if (allocInfo)
+       printAllocInfo( currFunc, codeOutFile);
+    /* if debug information required */
+/*     if (options.debug && currFunc) { */
+    if (currFunc) {
+       cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
+       _G.debugLine = 1;
+       if (IS_STATIC(currFunc->etype))
+           emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
+       else
+           emitcode("","G$%s$0$0 ==.",currFunc->name);
+       _G.debugLine = 0;
+    }
+    /* stack pointer name */
+    if (options.useXstack)
+       spname = "_spx";
+    else
+       spname = "sp";
+    
+    for (ic = lic ; ic ; ic = ic->next ) {
+       
+       if ( cln != ic->lineno ) {
+           if ( options.debug ) {
+               _G.debugLine = 1;
+               emitcode("","C$%s$%d$%d$%d ==.",
+                        ic->filename,ic->lineno,
+                        ic->level,ic->block);
+               _G.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 '!' :
+           genNot(ic);
+           break;
+           
+       case '~' :
+           genCpl(ic);
+           break;
+           
+       case UNARYMINUS:
+           genUminus (ic);
+           break;
+           
+       case IPUSH:
+           genIpush (ic);
+           break;
+           
+       case IPOP:
+           /* IPOP happens only when trying to restore a 
+              spilt live range, if there is an ifx statement
+              following this pop then the if statement might
+              be using some of the registers being popped which
+              would destory the contents of the register so
+              we need to check for this condition and handle it */
+           if (ic->next            && 
+               ic->next->op == IFX &&
+               regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
+               genIfx (ic->next,ic);
+           else
+               genIpop (ic);
+           break; 
+           
+       case CALL:
+           genCall (ic);
+           break;
+           
+       case PCALL:
+           genPcall (ic);
+           break;
+           
+       case FUNCTION:
+           genFunction (ic);
+           break;
+           
+       case ENDFUNCTION:
+           genEndFunction (ic);
+           break;
+           
+       case RETURN:
+           genRet (ic);
+           break;
+           
+       case LABEL:
+           genLabel (ic);
+           break;
+           
+       case GOTO:
+           genGoto (ic);
+           break;
+           
+       case '+' :
+           genPlus (ic) ;
+           break;
+           
+       case '-' :
+           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
+               genMinus (ic);
+           break;
+           
+       case '*' :
+           genMult (ic);
+           break;
+           
+       case '/' :
+           genDiv (ic) ;
+           break;
+           
+       case '%' :
+           genMod (ic);
+           break;
+           
+       case '>' :
+           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
+           break;
+           
+       case '<' :
+           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case LE_OP:
+       case GE_OP:
+       case NE_OP:
+           
+           /* note these two are xlated by algebraic equivalence
+              during parsing SDCC.y */
+           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+                  "got '>=' or '<=' shouldn't have come here");
+           break;      
+           
+       case EQ_OP:
+           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;          
+           
+       case AND_OP:
+           genAndOp (ic);
+           break;
+           
+       case OR_OP:
+           genOrOp (ic);
+           break;
+           
+       case '^' :
+           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case '|' :
+               genOr (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case BITWISEAND:
+            genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case INLINEASM:
+           genInline (ic);
+           break;
+           
+       case RRC:
+           genRRC (ic);
+           break;
+           
+       case RLC:
+           genRLC (ic);
+           break;
+           
+       case GETHBIT:
+           genGetHbit (ic);
+           break;
+           
+       case LEFT_OP:
+           genLeftShift (ic);
+           break;
+           
+       case RIGHT_OP:
+           genRightShift (ic);
+           break;
+           
+       case GET_VALUE_AT_ADDRESS:
+           genPointerGet(ic);
+           break;
+           
+       case '=' :
+           if (POINTER_SET(ic))
+               genPointerSet(ic);
+           else
+               genAssign(ic);
+           break;
+           
+       case IFX:
+           genIfx (ic,NULL);
+           break;
+           
+       case ADDRESS_OF:
+           genAddrOf (ic);
+           break;
+           
+       case JUMPTABLE:
+           genJumpTab (ic);
+           break;
+           
+       case CAST:
+           genCast (ic);
+           break;
+           
+       case RECEIVE:
+           genReceive(ic);
+           break;
+           
+       case SEND:
+           addSet(&_G.sendSet,ic);
+           break;
+
+       default :
+           ic = ic;
+           /*      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/ds390/gen.h b/src/ds390/gen.h
new file mode 100644 (file)
index 0000000..d641b57
--- /dev/null
@@ -0,0 +1,74 @@
+/*-------------------------------------------------------------------------
+  SDCCgen51.h - header file for code generation for 8051
+
+             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+
+#ifndef SDCCGEN51_H
+#define SDCCGEN51_H
+
+enum {
+    AOP_LIT = 1,
+    AOP_REG, AOP_DIR, 
+    AOP_DPTR, AOP_DPTR2, AOP_R0,AOP_R1,
+    AOP_STK ,AOP_IMMD, AOP_STR,
+    AOP_CRY, 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_DPTR2  -  dptr2 contains address of operand (DS80C390 only).
+                    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  */
+       regs  *aop_ptr ;       /* either -> to r0 or r1 */
+       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 gen390Code (iCode *);
+
+extern unsigned fReturnSize_390;
+
+#endif
diff --git a/src/ds390/main.c b/src/ds390/main.c
new file mode 100644 (file)
index 0000000..8920d73
--- /dev/null
@@ -0,0 +1,262 @@
+/** @file main.c
+    ds390 specific general functions.
+
+    Note that mlh prepended _ds390_ on the static functions.  Makes
+    it easier to set a breakpoint using the debugger.
+*/
+#include "common.h"
+#include "main.h"
+#include "ralloc.h"
+#include "gen.h"
+
+static char _defaultRules[] =
+{
+#include "peeph.rul"
+};
+
+/* list of key words used by msc51 */
+static char *_ds390_keywords[] =     {
+    "at",
+    "bit",
+    "code",
+    "critical",
+    "data",
+    "far",
+    "idata",
+    "interrupt",
+    "near",
+    "pdata",
+    "reentrant",
+    "sfr",
+    "sbit",
+    "using",
+    "xdata",
+    "_data",
+    "_code",
+    "_generic",
+    "_near",
+    "_xdata",
+    "_pdata",
+    "_idata",
+    NULL
+};
+
+
+void ds390_assignRegisters (eBBlock **ebbs, int count);
+
+static int regParmFlg = 0; /* determine if we can register a parameter */
+
+static void _ds390_init(void)
+{
+    asm_addTree(&asm_asxxxx_mapping);
+}
+
+static void _ds390_reset_regparm()
+{
+    regParmFlg = 0;
+}
+
+static int _ds390_regparm( link *l)
+{
+    /* for this processor it is simple
+       can pass only the first parameter in a register */
+    if (regParmFlg)
+       return 0;
+
+    regParmFlg = 1;
+    return 1;
+}
+
+static bool _ds390_parseOptions(int *pargc, char **argv, int *i)
+{
+    /* TODO: allow port-specific command line options to specify
+     * segment names here.
+     */
+    return FALSE;
+}
+
+static void _ds390_finaliseOptions(void)
+{
+    /* Hack-o-matic: if we are using the flat24 model,
+     * adjust pointer sizes.
+     */
+    if (options.model != MODEL_FLAT24)
+    {
+       fprintf(stderr, 
+               "*** warning: ds390 port only supports the flat24 model.\n");    
+       options.model = MODEL_FLAT24;
+    }
+    port->s.fptr_size = 3;
+    port->s.gptr_size = 4;
+    port->stack.isr_overhead++;   /* Will save dpx on ISR entry. */
+#if 1
+    port->stack.call_overhead++;          /* This acounts for the extra byte 
+                                           * of return addres on the stack.
+                                           * but is ugly. There must be a 
+                                           * better way.
+                                           */
+#endif
+
+    if (options.model) {
+       port->mem.default_local_map = xdata;
+       port->mem.default_globl_map = xdata;
+    } else {
+       port->mem.default_local_map = data;
+       port->mem.default_globl_map = data;
+    }
+    
+    if (options.stack10bit)
+    {
+       if (options.model != MODEL_FLAT24)
+       {
+            fprintf(stderr, 
+                   "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
+            fprintf(stderr, "\t10 bit stack mode disabled.\n");
+            options.stack10bit = 0;
+        }
+        else
+        {
+            /* Fixup the memory map for the stack; it is now in
+             * far space and requires a FPOINTER to access it.
+             */
+            istack->fmap = 1;
+            istack->ptrType = FPOINTER; 
+        }
+    }
+}
+
+static void _ds390_setDefaultOptions(void)
+{
+}
+
+static const char *_ds390_getRegName(struct regs *reg)
+{
+    if (reg)
+       return reg->name;
+    return "err";
+}
+
+static void _ds390_genAssemblerPreamble(FILE *of)
+{
+   if (options.model == MODEL_FLAT24)
+   {
+       fputs(".flat24 on\t\t; 24 bit flat addressing\n", of);
+       fputs("dpx = 0x93\t\t; dpx register unknown to assembler\n", of);
+       fputs("dps = 0x86\t\t; dps register unknown to assembler\n", of);
+       fputs("dpl1 = 0x84\t\t; dpl1 register unknown to assembler\n", of);
+       fputs("dph1 = 0x85\t\t; dph1 register unknown to assembler\n", of);
+       fputs("dpx1 = 0x95\t\t; dpx1 register unknown to assembler\n", of);
+       fputs("ap = 0x9C\t\t; ap register unknown to assembler\n", of);       
+   }
+}
+
+/* Generate interrupt vector table. */
+static int _ds390_genIVT(FILE *of, symbol **interrupts, int maxInterrupts)
+{
+    int i;
+    
+    if (options.model != MODEL_FLAT24)
+    {
+        /* Let the default code handle it. */
+       return FALSE;
+    }
+    
+    fprintf (of, "\tajmp\t__sdcc_gsinit_startup\n");
+    
+    /* now for the other interrupts */
+    for (i = 0; i < maxInterrupts; i++) 
+    {
+       if (interrupts[i])
+       {
+           fprintf(of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
+       }
+       else
+       {
+           fprintf(of, "\treti\n\t.ds\t7\n");
+       }
+    }
+    
+    return TRUE;
+}
+
+/** $1 is always the basename.
+    $2 is always the output file.
+    $3 varies
+    $l is the list of extra options that should be there somewhere...
+    MUST be terminated with a NULL.
+*/
+static const char *_linkCmd[] = {
+    "aslink", "-nf", "$1", NULL
+};
+
+static const char *_asmCmd[] = {
+    "asx8051", "-plosgffc", "$1.asm", NULL
+};
+
+/* Globals */
+PORT ds390_port = {
+    "ds390",
+    "DS80C390",                        /* Target name */
+    {
+       TRUE,                   /* Emit glue around main */
+       MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
+       MODEL_SMALL
+    },
+    {  
+       _asmCmd,
+       "-plosgffc",            /* Options with debug */
+       "-plosgff",             /* Options without debug */
+       0
+    },
+    {
+       _linkCmd,
+       NULL,
+       ".rel"
+    },
+    {
+       _defaultRules
+    },
+    {
+       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+       1, 1, 2, 4, 1, 2, 3, 1, 4, 4
+    },
+    {
+       "XSEG    (XDATA)",
+       "STACK   (DATA)",
+       "CSEG    (CODE)",
+       "DSEG    (DATA)",
+       "ISEG    (DATA)",
+       "XSEG    (XDATA)",
+       "BSEG    (BIT)",
+       "RSEG    (DATA)",
+       "GSINIT  (CODE)",
+       "OSEG    (OVR,DATA)",
+       "GSFINAL (CODE)",
+       "HOME    (CODE)",
+       NULL,
+       NULL,
+       1
+    },
+    { 
+       +1, 1, 4, 1, 1, 0
+    },
+    /* ds390 has an 8 bit mul */
+    {
+       1
+    },
+    "_",
+    _ds390_init,
+    _ds390_parseOptions,
+    _ds390_finaliseOptions,
+    _ds390_setDefaultOptions,
+    ds390_assignRegisters,
+    _ds390_getRegName ,
+    _ds390_keywords,
+    _ds390_genAssemblerPreamble,
+    _ds390_genIVT ,
+    _ds390_reset_regparm,
+    _ds390_regparm,
+    NULL,
+    FALSE
+};
+
diff --git a/src/ds390/main.h b/src/ds390/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/ds390/peeph.def b/src/ds390/peeph.def
new file mode 100644 (file)
index 0000000..630a6e6
--- /dev/null
@@ -0,0 +1,1796 @@
+//replace restart {
+//        pop  %1
+//        push %1
+//} by {
+//        ; Peephole 1     removed pop %1 push %1 (not push pop)
+//}
+
+//replace restart {
+//        pop  %1
+//        mov  %2,%3
+//        push %1
+//} by {
+//        ; Peephole 2     removed pop %1 push %1 (not push pop)
+//        mov  %2,%3 
+//}
+
+//
+// added by Jean Louis VERN for
+// his shift stuff
+replace restart {
+        xch  a,%1
+        xch  a,%1
+} by {
+        ; Peephole 2.a   removed redundant xch xch
+}
+
+replace restart {
+// saving 2 byte
+        mov  %1,#0x00
+        mov  a,#0x00
+} by {
+        ; Peephole 3.a   changed mov to clr
+        clr  a
+        mov  %1,a
+}
+
+replace restart {
+// saving 1 byte
+        mov  %1,#0x00
+        clr  a
+} by {
+        ; Peephole 3.b   changed mov to clr
+        clr  a
+        mov  %1,a
+}
+
+replace restart {
+// saving 1 byte, loosing 1 cycle but maybe allowing peephole 3.b to start
+        mov  %1,#0x00
+        mov  %2,#0x00
+        mov  a,%3
+} by {
+        ; Peephole 3.c   changed mov to clr
+        clr  a
+        mov  %1,a
+        mov  %2,a
+        mov  a,%3
+}
+
+
+
+replace {
+        mov  %1,a
+        mov  dptr,#%2
+        mov  a,%1
+        movx @dptr,a
+} by {
+        ; Peephole 100   removed redundant mov
+        mov  %1,a
+        mov  dptr,#%2
+        movx @dptr,a
+}
+
+replace {
+       mov  a,acc
+} by {
+       ;  Peephole 100.a   removed redundant mov
+}
+
+replace {
+        mov  a,%1
+        movx @dptr,a
+        inc  dptr
+        mov  a,%1
+        movx @dptr,a
+} by {
+        ; Peephole 101   removed redundant mov
+        mov  a,%1
+        movx @dptr,a
+        inc  dptr
+        movx @dptr,a
+}
+
+replace {
+        mov  %1,%2
+        ljmp %3
+%4:
+        mov  %1,%5
+%3:
+        mov  dpl,%1
+%7:
+        mov  sp,bp
+        pop  bp
+} by {
+        ; Peephole 102   removed redundant mov
+        mov  dpl,%2
+        ljmp %3
+%4:
+        mov  dpl,%5
+%3:
+%7:
+        mov  sp,bp
+        pop  bp
+}
+
+replace {
+        mov  %1,%2
+        ljmp %3
+%4:
+        mov  a%1,%5
+%3:
+        mov  dpl,%1
+%7:
+        mov  sp,bp
+        pop  bp
+} by {
+        ; Peephole 103   removed redundant mov
+        mov  dpl,%2
+        ljmp %3
+%4:
+        mov  dpl,%5
+%3:
+%7:
+        mov  sp,bp
+        pop  bp
+}
+
+replace {
+        mov  a,bp
+        clr  c
+        add  a,#0x01
+        mov  r%1,a
+} by {
+        ; Peephole 104   optimized increment (acc not set to r%1, flags undefined)
+        mov  r%1,bp
+        inc  r%1
+}
+
+replace {
+        mov  %1,a
+        mov  a,%1
+} by {
+        ; Peephole 105   removed redundant mov
+        mov  %1,a
+}
+
+replace {
+        mov  %1,a
+        clr  c
+        mov  a,%1
+} by {
+        ; Peephole 106   removed redundant mov 
+        mov  %1,a
+        clr  c
+}
+
+replace {
+        ljmp %1
+%1:
+} by {
+        ; Peephole 107   removed redundant ljmp
+%1:
+}
+
+replace {
+        jc   %1
+        ljmp %5
+%1:
+} by {
+        ; Peephole 108   removed ljmp by inverse jump logic
+        jnc  %5
+%1:
+} if labelInRange
+
+replace {
+        jz   %1
+        ljmp %5
+%1:
+} by {
+        ; Peephole 109   removed ljmp by inverse jump logic
+        jnz  %5
+%1:
+} if labelInRange
+
+replace {
+        jnz  %1
+        ljmp %5
+%1:
+} by {
+        ; Peephole 110   removed ljmp by inverse jump logic
+        jz  %5
+%1:
+} if labelInRange
+
+replace {
+        jb   %1,%2
+        ljmp %5
+%2:
+} by {
+        ; Peephole 111   removed ljmp by inverse jump logic
+        jnb  %1,%5
+%2:
+} if labelInRange
+
+replace {
+        jnb  %1,%2
+        ljmp %5
+%2:
+} by {
+       ; Peephole 112   removed ljmp by inverse jump logic
+        jb   %1,%5
+%2:
+} if labelInRange
+
+replace {
+        ljmp %5
+%1:
+} by {
+        ; Peephole 132   changed ljmp to sjmp
+        sjmp %5
+%1:
+} if labelInRange
+
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cpl  a
+%3:
+        rrc  a
+        mov  %4,c
+} by {
+        ; Peephole 113   optimized misc sequence
+        clr  %4
+        cjne %1,%2,%3
+        setb %4
+%3:
+}
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        cpl  a
+%3:
+        rrc  a
+        mov  %4,c
+} by {
+        ; Peephole 114   optimized misc sequence
+        clr  %4
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        setb %4
+%3:
+}
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cpl  a
+%3:
+        jnz  %4
+} by {
+        ; Peephole 115   jump optimization 
+        cjne %1,%2,%3
+        sjmp %4
+%3:
+}
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cjne %9,%10,%3
+        cpl  a
+%3:
+        jnz  %4
+} by {
+        ; Peephole 116   jump optimization
+        cjne %1,%2,%3
+        cjne %9,%10,%3
+        sjmp %4
+%3:
+}
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cjne %9,%10,%3
+        cjne %11,%12,%3
+        cpl  a
+%3:
+        jnz %4
+} by {
+        ; Peephole 117   jump optimization
+        cjne %1,%2,%3
+        cjne %9,%10,%3
+        cjne %11,%12,%3
+        sjmp %4
+%3:
+}
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cjne %9,%10,%3
+        cjne %11,%12,%3
+        cjne %13,%14,%3
+        cpl  a
+%3:
+        jnz %4
+} by {
+        ; Peephole 118   jump optimization
+        cjne %1,%2,%3
+        cjne %9,%10,%3
+        cjne %11,%12,%3
+        cjne %13,%14,%3
+        sjmp %4
+%3:
+}
+replace {
+        mov  a,#0x01
+        cjne %1,%2,%3
+        clr  a
+%3:
+        jnz  %4
+} by {
+        ; Peephole 119   jump optimization
+        cjne %1,%2,%4
+%3:
+}
+
+replace {
+        mov  a,#0x01
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        clr  a
+%3:
+        jnz  %4
+} by {
+        ; Peephole 120   jump optimization
+        cjne %1,%2,%4
+        cjne %10,%11,%4
+%3:
+}
+replace {
+        mov  a,#0x01
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        cjne %12,%13,%3
+        clr  a
+%3:
+        jnz  %4
+} by {
+        ; Peephole 121   jump optimization
+        cjne %1,%2,%4
+        cjne %10,%11,%4
+        cjne %12,%13,%4
+%3:
+}
+
+replace {
+        mov  a,#0x01
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        cjne %12,%13,%3
+        cjne %14,%15,%3
+        clr  a
+%3:
+        jnz  %4
+} by {
+        ; Peephole 122   jump optimization
+        cjne %1,%2,%4
+        cjne %10,%11,%4
+        cjne %12,%13,%4
+        cjne %14,%15,%4
+%3:
+}
+
+replace {
+        mov  a,#0x01
+        cjne %1,%2,%3
+        clr  a
+%3:
+        jz   %4
+} by {
+        ; Peephole 123   jump optimization
+        cjne %1,%2,%3
+        smp  %4
+%3:
+}
+replace {
+        mov  a,#0x01
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        clr  a
+%3:
+        jz   %4
+} by {
+        ; Peephole 124   jump optimization
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        smp  %4
+%3:
+}
+
+replace {
+        mov  a,#0x01
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        cjne %12,%13,%3
+        clr  a
+%3:
+        jz   %4
+} by {
+        ; Peephole 125   jump optimization
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        cjne %12,%13,%3
+        sjmp %4
+%3:
+}
+
+replace {
+        mov  a,#0x01
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        cjne %12,%13,%3
+        cjne %14,%15,%3
+        clr  a
+%3:
+        jz   %4
+} by {
+        ; Peephole 126   jump optimization
+        cjne %1,%2,%3
+        cjne %10,%11,%3
+        cjne %12,%13,%3
+        cjne %14,%15,%3
+        sjmp %4
+%3:
+}
+
+replace {
+        push psw
+        mov  psw,%1
+        push bp
+        mov  bp,%2
+%3:
+        mov  %2,bp
+        pop  bp
+        pop  psw
+        ret
+} by {
+        ; Peephole 127   removed misc sequence
+        ret
+}
+
+replace {
+        clr  a
+        rlc  a
+        jz   %1
+} by {
+        ; Peephole 128   jump optimization
+        jnc  %1
+}
+
+replace {
+        clr  a
+        rlc  a
+        jnz  %1
+} by {
+        ; Peephole 129   jump optimization
+        jc   %1
+}
+
+replace { 
+        mov  r%1,@r%2
+} by {
+        ; Peephole 130   changed target address mode r%1 to ar%1
+        mov  ar%1,@r%2
+}
+
+replace { 
+        mov  a,%1
+        subb a,#0x01
+        mov  %2,a
+        mov  %1,%2
+} by {
+        ; Peephole 131   optimized decrement (not caring for c)
+        dec  %1         
+        mov  %2,%1      
+}
+
+replace {
+        mov  r%1,%2
+        mov  ar%3,@r%1
+        inc  r%3
+        mov  r%4,%2
+        mov  @r%4,ar%3
+} by {
+        ; Peephole 133   removed redundant moves
+        mov  r%1,%2
+        inc  @r%1
+        mov  ar%3,@r%1
+}
+
+replace {
+        mov  r%1,%2
+        mov  ar%3,@r%1
+        dec  r%3
+        mov  r%4,%2
+        mov  @r%4,ar%3
+} by {
+        ; Peephole 134   removed redundant moves
+        mov  r%1,%2
+        dec  @r%1
+        mov  ar%3,@r%1
+}
+
+replace {
+        mov  r%1,a
+        mov  a,r%2
+        orl  a,r%1
+} by {
+        ; Peephole 135   removed redundant mov
+        mov  r%1,a
+        orl  a,r%2
+}
+
+replace {
+        mov  %1,a
+        mov  dpl,%2
+        mov  dph,%3
+       mov  dpx,%4
+        mov  a,%1
+} by {
+        ; Peephole 136a   removed redundant moves
+        mov  %1,a
+        mov  dpl,%2
+        mov  dph,%3
+       mov  dpx,%4
+} if 24bitMode
+
+replace {
+        mov  %1,a
+        mov  dpl,%2
+        mov  dph,%3
+        mov  a,%1
+} by {
+        ; Peephole 136   removed redundant moves
+        mov  %1,a
+        mov  dpl,%2
+        mov  dph,%3
+}
+
+replace {
+        mov  b,#0x00
+        mov  a,%1
+        cjne %2,%3,%4
+        mov  b,#0x01
+%4:
+        mov  a,b
+        jz   %5
+} by {
+        ; Peephole 137   optimized misc jump sequence
+        mov  a,%1
+        cjne %2,%3,%5
+%4:
+}
+
+replace {
+        mov  b,#0x00
+        mov  a,%1
+        cjne %2,%3,%4
+        mov  b,#0x01
+%4:
+        mov  a,b
+        jnz  %5
+} by {
+        ; Peephole 138   optimized misc jump sequence
+        mov  a,%1
+        cjne %2,%3,%4
+        sjmp %5
+%4:
+}
+
+replace {
+        mov  r%1,a
+        anl  ar%1,%2
+        mov  a,r%1
+} by {
+        ; Peephole 139   removed redundant mov
+        anl  a,%2
+        mov  r%1,a
+}
+
+replace {
+        mov  r%1,a
+        orl  ar%1,%2
+        mov  a,r%1
+} by {
+        ; Peephole 140   removed redundant mov
+        orl  a,%2
+        mov  r%1,a }
+
+replace {
+        mov  r%1,a
+        xrl  ar%1,%2
+        mov  a,r%1
+} by {
+        ; Peephole 141   removed redundant mov
+        xrl  a,%2
+        mov  r%1,a
+}
+
+replace {
+        mov  r%1,a
+        mov  r%2,ar%1
+        mov  ar%1,@r%2
+} by {
+        ; Peephole 142   removed redundant moves
+        mov  r%2,a
+        mov  ar%1,@r%2
+}
+
+replace {
+        rlc  a
+        mov  acc.0,c
+} by {
+        ; Peephole 143   converted rlc to rl
+        rl   a
+}
+
+replace {
+        rrc  a
+        mov  acc.7,c
+} by {
+        ; Peephole 144   converted rrc to rc
+        rr   a
+}
+
+replace {
+        clr  c
+        addc a,%1
+} by {
+        ; Peephole 145   changed to add without carry  
+        add  a,%1
+}
+
+replace {
+        clr  c
+        mov  a,%1
+        addc a,%2
+} by {
+        ; Peephole 146   changed to add without carry
+        mov  a,%1
+        add  a,%2
+}
+
+replace {
+        orl  r%1,a
+} by {
+        ; Peephole 147   changed target address mode r%1 to ar%1
+        orl  ar%1,a
+}
+
+replace {
+        anl  r%1,a
+} by {
+        ; Peephole 148   changed target address mode r%1 to ar%1
+        anl  ar%1,a
+}
+
+replace {
+        xrl  r%1,a
+} by {
+        ; Peephole 149   changed target address mode r%1 to ar%1
+        xrl  ar%1,a
+}
+
+replace {
+        mov  %1,dpl
+        mov  dpl,%1
+%9:
+        ret
+} by {
+        ; Peephole 150   removed misc moves via dpl before return
+%9:
+        ret
+}
+
+replace {
+        mov  %1,dpl
+        mov  %2,dph
+        mov  dpl,%1
+        mov  dph,%2
+%9:
+        ret
+} by {
+        ; Peephole 151   removed misc moves via dph, dpl before return
+%9:
+        ret
+}
+
+replace {
+        mov  %1,dpl
+        mov  %2,dph
+        mov  dpl,%1
+%9:
+        ret
+} by {
+        ; Peephole 152   removed misc moves via dph, dpl before return
+%9:
+        ret
+}
+
+replace {
+        mov  %1,dpl
+        mov  %2,dph
+        mov  %3,b
+        mov  dpl,%1
+        mov  dph,%2
+        mov  b,%3
+%9:
+        ret
+} by {
+        ; Peephole 153   removed misc moves via dph, dpl, b before return
+%9:
+        ret
+}
+
+replace {
+        mov  %1,dpl
+        mov  %2,dph
+        mov  %3,b
+        mov  dpl,%1
+%9:
+        ret
+} by {
+        ; Peephole 154   removed misc moves via dph, dpl, b before return
+%9:
+        ret
+}
+
+replace {
+        mov  %1,dpl
+        mov  %2,dph
+        mov  %3,b
+        mov  dpl,%1
+        mov  dph,%2
+%9:
+        ret
+} by {
+        ; Peephole 155   removed misc moves via dph, dpl, b before return
+%9:
+        ret
+}
+
+replace {
+        mov  %1,dpl
+        mov  %2,dph
+        mov  %3,b
+        mov  %4,a
+        mov  dpl,%1
+        mov  dph,%2
+        mov  b,%3
+        mov  a,%4
+%9:
+        ret
+} by {
+        ; Peephole 156   removed misc moves via dph, dpl, b, a before return
+%9:
+        ret
+}
+
+replace {
+        mov  %1,dpl
+        mov  %2,dph
+        mov  %3,b
+        mov  %4,a
+        mov  dpl,%1
+        mov  dph,%2
+%9:
+        ret
+} by {
+        ; Peephole 157   removed misc moves via dph, dpl, b, a before return
+%9:
+        ret
+}
+
+replace {
+        mov  %1,dpl
+        mov  %2,dph
+        mov  %3,b
+        mov  %4,a
+        mov  dpl,%1
+%9:
+        ret } by {
+        ; Peephole 158   removed misc moves via dph, dpl, b, a before return
+%9:
+        ret }
+
+replace {
+        mov  %1,#%2
+        xrl  %1,#0x80
+} by {
+        ; Peephole 159   avoided xrl during execution
+        mov  %1,#(%2 ^ 0x80)
+}
+
+replace {
+        jnc  %1
+        sjmp %2
+%1:
+} by {
+        ; Peephole 160   removed sjmp by inverse jump logic
+        jc   %2
+%1:}
+
+replace {
+        jc   %1
+        sjmp %2
+%1:
+} by {
+        ; Peephole 161   removed sjmp by inverse jump logic
+        jnc  %2
+%1:}
+
+replace {
+        jnz  %1
+        sjmp %2
+%1:
+} by {
+        ; Peephole 162   removed sjmp by inverse jump logic
+        jz   %2
+%1:}
+
+replace {
+        jz   %1
+        sjmp %2
+%1:
+} by {
+        ; Peephole 163   removed sjmp by inverse jump logic
+        jnz  %2
+%1:}
+
+replace {
+        jnb  %3,%1
+        sjmp %2
+%1:
+} by {
+        ; Peephole 164   removed sjmp by inverse jump logic
+        jb   %3,%2
+%1:
+}
+
+replace {
+        jb   %3,%1
+        sjmp %2
+%1:
+} by {
+        ; Peephole 165   removed sjmp by inverse jump logic
+        jnb  %3,%2
+%1:
+}
+
+replace {
+        mov  %1,%2
+        mov  %3,%1
+        mov  %2,%1
+} by {
+        ; Peephole 166   removed redundant mov
+        mov  %1,%2
+        mov  %3,%1 }
+
+replace {
+        mov  c,%1
+        cpl  c
+        mov  %1,c
+} by {
+        ; Peephole 167   removed redundant bit moves (c not set to %1)
+        cpl  %1 }
+
+replace {
+        jnb  %1,%2
+        sjmp %3
+%2:} by {
+        ; Peephole 168   jump optimization
+        jb   %1,%3
+%2:}
+
+replace {
+        jb   %1,%2
+        sjmp %3
+%2:} by {
+        ; Peephole 169   jump optimization
+        jnb  %1,%3
+%2:}
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cpl  a
+%3:
+        jz   %4
+} by {
+        ; Peephole 170   jump optimization
+        cjne %1,%2,%4
+%3:}
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cjne %9,%10,%3
+        cpl  a
+%3:
+        jz   %4
+} by {
+        ; Peephole 171   jump optimization
+        cjne %1,%2,%4
+        cjne %9,%10,%4
+%3:}
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cjne %9,%10,%3
+        cjne %11,%12,%3
+        cpl  a
+%3:
+        jz   %4
+} by {
+        ; Peephole 172   jump optimization
+        cjne %1,%2,%4
+        cjne %9,%10,%4
+        cjne %11,%12,%4
+%3:}
+
+replace {
+        clr  a
+        cjne %1,%2,%3
+        cjne %9,%10,%3
+        cjne %11,%12,%3
+        cjne %13,%14,%3
+        cpl  a
+%3:
+        jz   %4
+} by {
+        ; Peephole 173   jump optimization
+        cjne %1,%2,%4
+        cjne %9,%10,%4
+        cjne %11,%12,%4
+        cjne %13,%14,%4
+%3:}
+
+replace {
+        mov  r%1,%2
+        clr  c
+        mov  a,r%1
+        subb a,#0x01
+        mov  %2,a
+} by {
+        ; Peephole 174   optimized decrement (acc not set to %2, flags undefined)
+        mov  r%1,%2
+        dec  %2
+}
+
+
+replace {
+        mov  r%1,%2
+        mov  a,r%1
+        add  a,#0x01
+        mov  %2,a
+} by {
+        ; Peephole 175   optimized increment (acc not set to %2, flags undefined)
+        mov  r%1,%2
+        inc  %2
+}
+
+replace {
+        mov  %1,@r%2
+        inc  %1
+        mov  @r%2,%1
+} by {
+        ; Peephole 176   optimized increment, removed redundant mov
+        inc  @r%2
+        mov  %1,@r%2
+}
+
+replace {
+        mov  %1,%2
+        mov  %2,%1
+} by {
+        ; Peephole 177   removed redundant mov
+        mov  %1,%2
+}
+
+replace {
+        mov  a,%1
+        mov  b,a
+        mov  a,%2
+} by {
+        ; Peephole 178   removed redundant mov
+        mov  b,%1
+        mov  a,%2
+}
+
+// rules 179-182 provided by : Frieder <fe@lake.iup.uni-heidelberg.de>
+// saving 2 byte, 1 cycle
+replace {
+        mov  b,#0x00
+        mov  a,#0x00
+} by {
+        ; Peephole 179   changed mov to clr
+        clr  a
+        mov  b,a
+}
+
+// saving 1 byte, 0 cycles
+replace {
+        mov  a,#0x00
+} by {
+        ; Peephole 180   changed mov to clr
+        clr  a
+}
+
+replace {
+        mov  dpl,#0x00
+        mov  dph,#0x00
+       mov  dpx,#0x00
+} by {
+        ; Peephole 181a   used 24 bit load of dptr
+        mov  dptr,#0x0000
+} if 24bitMode
+
+// saving 3 byte, 2 cycles, return(NULL) profits here
+replace {
+        mov  dpl,#0x00
+        mov  dph,#0x00
+} by {
+        ; Peephole 181   used 16 bit load of dptr
+        mov  dptr,#0x0000
+}
+
+// saves 2 bytes, ?? cycles.
+replace {
+        mov  dpl,#%1
+        mov  dph,#(%1 >> 8)
+       mov  dpx,#(%1 >> 16)
+} by {
+        ; Peephole 182a   used 24 bit load of dptr
+        mov  dptr,#%1
+} if 24bitMode
+
+// saving 3 byte, 2 cycles, return(float_constant) profits here
+replace {
+        mov  dpl,#%1
+        mov  dph,#%2
+} by {
+        ; Peephole 182   used 16 bit load of dptr
+        mov  dptr,#(((%2)<<8) + %1)
+}
+
+replace {
+        anl  %1,#%2
+        anl  %1,#%3
+} by {
+        ; Peephole 183   avoided anl during execution
+        anl  %1,#(%2 & %3)
+}
+
+replace {
+        mov  %1,a
+        cpl  a
+        mov  %1,a
+} by {
+        ; Peephole 184   removed redundant mov
+        cpl  a
+        mov  %1,a
+}
+
+replace {
+// acc being incremented might cause problems
+        mov  %1,a
+        inc  %1
+} by {
+        ; Peephole 185   changed order of increment (acc incremented also!)
+        inc  a
+        mov  %1,a
+}
+
+replace {
+        add  a,#%1
+        mov  dpl,a
+        clr  a
+        addc a,#(%1 >> 8)
+        mov  dph,a
+        clr  a
+        movc a,@a+dptr
+       mov  %2,a
+       inc  dptr
+       clr  a
+       movc a,@a+dptr
+       mov  %3,a
+       inc  dptr
+       clr  a
+       movc a,@a+dptr
+       mov  %4,a
+       inc  dptr
+       clr  a  
+} by {
+        ; Peephole 186.a   optimized movc sequence
+        mov  dptr,#%1
+       mov  b,acc
+        movc a,@a+dptr
+       mov  %2,a
+       mov  acc,b
+       inc  dptr       
+       movc a,@a+dptr
+       mov  %3,a
+       mov  acc,b
+       inc  dptr
+       mov  %4,a
+       mov  acc,b
+       inc  dptr
+}
+
+replace {
+        add  a,#%1
+        mov  dpl,a
+        clr  a
+        addc a,#(%1 >> 8)
+        mov  dph,a
+        clr  a
+        movc a,@a+dptr
+       mov  %2,a
+       inc  dptr
+       clr  a
+       movc a,@a+dptr
+       mov  %3,a
+       inc  dptr
+       clr  a
+} by {
+        ; Peephole 186.b   optimized movc sequence
+        mov  dptr,#%1
+       mov  b,acc
+        movc a,@a+dptr
+       mov  %2,a
+       mov  acc,b
+       inc  dptr       
+       movc a,@a+dptr
+       mov  %3,a
+       mov  acc,b
+       inc  dptr       
+}
+
+replace {
+        add  a,#%1
+        mov  dpl,a
+        clr  a
+        addc a,#(%1 >> 8)
+        mov  dph,a
+        clr  a
+        movc a,@a+dptr
+       mov  %2,a
+       inc  dptr
+       clr  a
+} by {
+        ; Peephole 186.c   optimized movc sequence
+        mov  dptr,#%1
+       mov  b,acc
+        movc a,@a+dptr
+       mov  %2,a
+       mov  acc,b
+       inc  dptr
+}
+
+replace {
+        add  a,#%1
+        mov  dpl,a
+        clr  a
+        addc a,#(%1 >> 8)
+        mov  dph,a
+        clr  a
+        movc a,@a+dptr
+} by {
+        ; Peephole 186   optimized movc sequence
+        mov  dptr,#%1
+        movc a,@a+dptr
+}
+
+replace {
+        mov  r%1,%2
+        anl  ar%1,#%3
+        mov  a,r%1
+} by {
+        ; Peephole 187   used a instead of ar%1 for anl
+        mov  a,%2
+        anl  a,#%3
+        mov  r%1,a
+}
+
+replace {
+        mov  %1,a
+        mov  dptr,%2
+        movc a,@a+dptr
+        mov  %1,a
+} by {
+        ; Peephole 188   removed redundant mov
+        mov  dptr,%2
+        movc a,@a+dptr
+        mov  %1,a
+}
+
+replace {
+        anl  a,#0x0f
+        mov  %1,a
+        mov  a,#0x0f
+        anl  a,%1
+} by {
+        ; Peephole 189   removed redundant mov and anl
+        anl  a,#0x0f
+        mov  %1,a
+}
+
+// rules 190 & 191 need to be in order
+replace {
+        mov  a,%1
+        lcall __gptrput
+        mov  a,%1
+} by {
+        ; Peephole 190   removed redundant mov
+        mov  a,%1
+        lcall __gptrput
+}
+
+replace {
+        mov  %1,a
+        mov  dpl,%2
+        mov  dph,%3
+        mov  b,%4
+        mov  a,%1
+} by {
+        ; Peephole 191   removed redundant mov
+        mov  %1,a
+        mov  dpl,%2
+        mov  dph,%3
+        mov  b,%4
+}
+
+replace {
+        mov  r%1,a
+        mov  @r%2,ar%1
+} by {
+        ; Peephole 192   used a instead of ar%1 as source
+        mov  r%1,a
+        mov  @r%2,a
+}
+
+replace {
+        jnz  %3
+        mov  a,%4
+        jnz  %3
+        mov  a,%9
+        jnz  %3
+        mov  a,%12
+        cjne %13,%14,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 193.a optimized misc jump sequence
+        jnz  %8
+        mov  a,%4
+        jnz  %8
+        mov  a,%9
+        jnz  %8
+        mov  a,%12
+        cjne %13,%14,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        cjne %1,%2,%3
+        mov  a,%4
+        cjne %5,%6,%3
+        mov  a,%9
+        cjne %10,%11,%3
+        mov  a,%12
+        cjne %13,%14,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 193   optimized misc jump sequence
+        cjne %1,%2,%8
+        mov  a,%4
+        cjne %5,%6,%8
+        mov  a,%9
+        cjne %10,%11,%8
+        mov  a,%12
+        cjne %13,%14,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        cjne @%1,%2,%3
+        inc  %1
+        cjne @%1,%6,%3
+        inc  %1
+        cjne @%1,%11,%3
+               inc  %1
+        cjne @%1,%14,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 193.a   optimized misc jump sequence
+        cjne @%1,%2,%8
+        inc  %1
+        cjne @%1,%6,%8
+        inc  %1
+        cjne @%1,%11,%8
+        inc  %1
+        cjne @%1,%14,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        cjne %1,%2,%3
+        cjne %5,%6,%3
+        cjne %10,%11,%3
+        cjne %13,%14,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 194   optimized misc jump sequence
+        cjne %1,%2,%8
+        cjne %5,%6,%8
+        cjne %10,%11,%8
+        cjne %13,%14,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        jnz  %3
+        mov  a,%4
+        jnz  %3
+        mov  a,%9
+        cjne %10,%11,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 195.a optimized misc jump sequence
+        jnz  %8
+        mov  a,%4
+        jnz  %8
+        mov  a,%9
+        cjne %10,%11,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        cjne %1,%2,%3
+        mov  a,%4
+        cjne %5,%6,%3
+        mov  a,%9
+        cjne %10,%11,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 195   optimized misc jump sequence
+        cjne %1,%2,%8
+        mov  a,%4
+        cjne %5,%6,%8
+        mov  a,%9
+        cjne %10,%11,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        cjne @%1,%2,%3
+        inc  %1
+        cjne @%1,%6,%3
+        inc  %1
+        cjne @%1,%11,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 195.a   optimized misc jump sequence
+        cjne @%1,%2,%8
+        inc  %1
+        cjne @%1,%6,%8
+        inc  %1
+        cjne @%1,%11,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        cjne %1,%2,%3
+        cjne %5,%6,%3
+        cjne %10,%11,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 196   optimized misc jump sequence
+        cjne %1,%2,%8
+        cjne %5,%6,%8
+        cjne %10,%11,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        jnz  %3
+        mov  a,%4
+        cjne %5,%6,%3
+        sjmp %7
+%3:
+        sjmp %8 
+} by {
+        ; Peephole 197.a optimized misc jump sequence
+        jnz  %8
+        mov  a,%4
+        cjne %5,%6,%8
+        sjmp %7
+%3:     
+}
+
+replace {
+        cjne %1,%2,%3
+        mov  a,%4
+        cjne %5,%6,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 197   optimized misc jump sequence
+        cjne %1,%2,%8
+        mov  a,%4
+        cjne %5,%6,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        cjne @%1,%2,%3
+        inc  %1
+        cjne @%1,%6,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 197.a   optimized misc jump sequence
+        cjne @%1,%2,%8
+        inc   %1
+        cjne @%1,%6,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        cjne %1,%2,%3
+        cjne %5,%6,%3
+        sjmp %7
+%3:
+        sjmp %8
+} by {
+        ; Peephole 198   optimized misc jump sequence
+        cjne %1,%2,%8
+        cjne %5,%6,%8
+        sjmp %7
+%3:
+}
+
+replace {
+        cjne %1,%2,%3
+        sjmp %4
+%3:
+        sjmp %5
+} by {
+        ; Peephole 199   optimized misc jump sequence
+        cjne %1,%2,%5
+        sjmp %4
+%3:
+}
+
+replace {
+        sjmp %1
+%1:
+} by {
+        ; Peephole 200   removed redundant sjmp
+%1:
+}
+
+replace {
+        sjmp %1
+%2:
+%1:
+} by {
+        ; Peephole 201   removed redundant sjmp
+%2:
+%1:
+}
+
+replace {
+        push  acc
+        mov   dptr,%1
+        pop   acc
+} by {
+        ; Peephole 202   removed redundant push pop
+        mov   dptr,%1
+}
+
+replace {
+        mov  r%1,_spx
+        lcall %2
+        mov  r%1,_spx
+} by {
+        ; Peephole 203   removed mov  r%1,_spx
+        lcall %2
+}
+
+replace {
+        mov  %1,a
+        add  a,acc
+        mov  %1,a
+} by {
+        ; Peephole 204   removed redundant mov
+        add  a,acc
+        mov  %1,a
+}
+
+replace {
+        djnz %1,%2
+        sjmp  %3
+%2:
+        sjmp  %4
+%3:
+} by {
+        ; Peephole 205   optimized misc jump sequence
+        djnz %1,%4
+%2:
+%3:
+}
+
+replace {
+        mov  %1,%1
+} by {
+        ; Peephole 206   removed redundant mov %1,%1
+}
+
+replace {
+        mov  a,_bp
+        add  a,#0x00
+        mov  %1,a
+} by {
+        ; Peephole 207   removed zero add (acc not set to %1, flags undefined)
+        mov  %1,_bp
+}
+
+replace {
+        push  acc
+        mov   r%1,_bp
+        pop   acc
+} by {
+        ; Peephole 208   removed redundant push pop
+        mov   r%1,_bp
+}
+
+replace {
+        mov  a,_bp
+        add  a,#0x00
+        inc  a
+        mov  %1,a
+} by {
+        ; Peephole 209   optimized increment (acc not set to %1, flags undefined)
+        mov  %1,_bp
+        inc  %1
+}
+
+replace {
+        mov  dptr,#((((%1 >> 16)) <<16) + (((%1 >> 8)) <<8) + %1)
+} by {
+        ; Peephole 210a   simplified expression
+        mov  dptr,#%1
+} if 24bitMode
+
+replace {
+        mov  dptr,#((((%1 >> 8)) <<8) + %1)
+} by {
+        ; Peephole 210   simplified expression
+        mov  dptr,#%1
+}
+
+replace {
+        push %1
+        pop  %1
+} by {
+        ; Peephole 211   removed redundant push %1 pop %1  
+} 
+
+replace {
+       mov  a,_bp
+       add  a,#0x01
+       mov  r%1,a
+} by {
+       ; Peephole 212  reduced add sequence to inc
+       mov  r%1,_bp
+       inc  r%1
+}
+
+replace {
+       mov  %1,#(( %2 >> 8 ) ^ 0x80)
+} by { 
+       mov  %1,#(%2 >> 8)
+       xrl  %1,#0x80
+}
+
+replace {
+       mov  %1,#(( %2 + %3 >> 8 ) ^ 0x80)
+} by { 
+       mov  %1,#((%2 + %3) >> 8)
+       xrl  %1,#0x80
+}
+
+replace  {
+       mov  %1,a
+       mov  a,%2
+       add  a,%1
+} by {
+       ; Peephole 214 reduced some extra movs
+       mov  %1,a
+       add  a,%2       
+} if operandsNotSame
+
+replace {
+       mov  %1,a
+       add  a,%2
+       mov  %1,a
+} by {
+       ; Peephole 215 removed some movs
+       add  a,%2
+       mov  %1,a
+} if operandsNotSame
+
+replace {
+       mov   r%1,%2
+       clr   a
+       inc   r%1
+       mov   @r%1,a
+       dec   r%1
+       mov   @r%1,a
+} by {
+       ; Peephole 216 simplified clear (2bytes)
+       mov   r%1,%2
+       clr   a
+       mov   @r%1,a
+       inc   r%1
+       mov   @r%1,a
+}
+
+replace {
+       mov   r%1,%2
+       clr   a
+       inc   r%1
+       inc   r%1
+       mov   @r%1,a
+       dec   r%1
+       mov   @r%1,a
+       dec   r%1
+       mov   @r%1,a
+} by {
+       ; Peephole 217 simplified clear (3bytes)
+       mov   r%1,%2
+       clr   a
+       mov   @r%1,a
+       inc   r%1
+       mov   @r%1,a
+       inc   r%1
+       mov   @r%1,a
+}
+
+replace {
+       mov   r%1,%2
+       clr   a
+       inc   r%1
+       inc   r%1
+       inc   r%1
+       mov   @r%1,a
+       dec   r%1
+       mov   @r%1,a
+       dec   r%1
+       mov   @r%1,a
+       dec   r%1
+       mov   @r%1,a
+} by {
+       ; Peephole 218 simplified clear (4bytes)
+       mov   r%1,%2
+       clr   a
+       mov   @r%1,a
+       inc   r%1
+       mov   @r%1,a
+       inc   r%1
+       mov   @r%1,a
+       inc   r%1
+       mov   @r%1,a
+}
+
+replace {
+       clr   a
+       movx  @dptr,a
+       mov   dptr,%1
+       clr   a
+       movx  @dptr,a
+} by {
+       ; Peephole 219 removed redundant clear
+       clr   a
+       movx  @dptr,a
+       mov   dptr,%1
+       movx  @dptr,a
+}
+
+replace {
+       clr   a
+       movx  @dptr,a
+       mov   dptr,%1
+       movx  @dptr,a
+       mov   dptr,%2
+       clr   a
+       movx  @dptr,a
+} by {
+       ; Peephole 219a removed redundant clear
+       clr   a
+       movx  @dptr,a
+       mov   dptr,%1
+       movx  @dptr,a
+       mov   dptr,%2
+       movx  @dptr,a
+}
+
+replace {
+        mov     dps, #0x00
+        mov     dps, #0x01
+} by {
+        ; Peephole 220a removed bogus DPS set
+        mov     dps, #0x01
+}
+
+replace {
+        mov     dps, #0x01
+        mov     dps, #0x00
+} by {
+        ; Peephole 220b removed bogus DPS set
+        mov     dps, #0x00
+}
+
+replace {
+       mov     %1 + %2,(%2 + %1)
+} by {
+       ; Peephole 221a remove redundant move
+}
+
+replace {
+       mov     (%1 + %2 + %3),((%2 + %1) + %3)
+} by {
+       ; Peephole 221b remove redundant move
+}
+
+replace {
+       dec     r%1
+       inc     r%1
+} by {
+       ; removed dec/inc pair
+}
\ No newline at end of file
diff --git a/src/ds390/ralloc.c b/src/ds390/ralloc.c
new file mode 100644 (file)
index 0000000..1e6e8dc
--- /dev/null
@@ -0,0 +1,2329 @@
+/*------------------------------------------------------------------------
+
+  SDCCralloc.c - source file for register allocation. (8051) specific
+
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+
+#include "common.h"
+#include "ralloc.h"
+#include "gen.h"
+
+/*-----------------------------------------------------------------*/
+/* At this point we start getting processor specific although      */
+/* some routines are non-processor specific & can be reused when   */
+/* targetting other processors. The decision for this will have    */
+/* to be made on a routine by routine basis                        */
+/* routines used to pack registers are most definitely not reusable*/
+/* since the pack the registers depending strictly on the MCU      */
+/*-----------------------------------------------------------------*/
+
+extern void gen390Code(iCode *);
+
+/* Global data */
+static struct {
+    bitVect *spiltSet;
+    set *stackSpil;
+    bitVect *regAssigned;
+    short blockSpil;
+    int slocNum;
+    bitVect *funcrUsed; /* registers used in a function */
+    int stackExtend;
+    int dataExtend;
+} _G;
+
+/* Shared with gen.c */
+int ds390_ptrRegReq; /* one byte pointer register required */
+
+/* 8051 registers */
+regs regs390[] = 
+{
+
+    { REG_GPR  ,R2_IDX , REG_GPR , "r2",  "ar2", "0", 2, 1 },
+    { REG_GPR  ,R3_IDX , REG_GPR , "r3",  "ar3", "0", 3, 1 },
+    { REG_GPR  ,R4_IDX , REG_GPR , "r4",  "ar4", "0", 4, 1 },
+    { REG_GPR  ,R5_IDX , REG_GPR , "r5",  "ar5", "0", 5, 1 },
+    { REG_GPR  ,R6_IDX , REG_GPR , "r6",  "ar6", "0", 6, 1 },
+    { REG_GPR  ,R7_IDX , REG_GPR , "r7",  "ar7", "0", 7, 1 },
+    { REG_PTR  ,R0_IDX , REG_PTR , "r0" , "ar0", "0", 0, 1 },
+    { REG_PTR  ,R1_IDX , REG_PTR , "r1" , "ar1", "0", 1, 1 },    
+    { REG_GPR  ,X8_IDX , REG_GPR , "x8",  "x8" , "xreg", 0, 1 },
+    { REG_GPR  ,X9_IDX , REG_GPR , "x9",  "x9" , "xreg", 1, 1 },
+    { REG_GPR  ,X10_IDX,REG_GPR , "x10", "x10",  "xreg", 2, 1 },
+    { REG_GPR  ,X11_IDX,REG_GPR , "x11", "x11",  "xreg", 3, 1 },
+    { REG_GPR  ,X12_IDX,REG_GPR , "x12", "x12",  "xreg", 4, 1 },
+    { REG_CND  ,CND_IDX,REG_CND , "C"  , "C"  ,  "xreg", 0, 1 },  
+};
+int ds390_nRegs = 13;
+static void spillThis (symbol *);
+
+/*-----------------------------------------------------------------*/
+/* allocReg - allocates register of given type                     */
+/*-----------------------------------------------------------------*/
+static regs *allocReg (short type)
+{
+    int i;
+
+    for ( i = 0 ; i < ds390_nRegs ; i++ ) {
+
+       /* if type is given as 0 then any
+          free register will do */
+       if (!type &&
+           regs390[i].isFree ) {
+           regs390[i].isFree = 0;
+           if (currFunc)
+               currFunc->regsUsed = 
+                   bitVectSetBit(currFunc->regsUsed,i);
+           return &regs390[i];
+       }
+       /* other wise look for specific type
+          of register */
+       if (regs390[i].isFree && 
+           regs390[i].type == type) {
+           regs390[i].isFree = 0;
+           if (currFunc)
+               currFunc->regsUsed = 
+                   bitVectSetBit(currFunc->regsUsed,i);
+           return &regs390[i];
+       }
+    }
+    return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* ds390_regWithIdx - returns pointer to register wit index number       */
+/*-----------------------------------------------------------------*/
+regs *ds390_regWithIdx (int idx)
+{
+    int i ;
+    
+    for (i=0;i < ds390_nRegs;i++)
+       if (regs390[i].rIdx == idx)
+           return &regs390[i];
+
+    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+          "regWithIdx not found");
+    exit(1);
+}
+
+/*-----------------------------------------------------------------*/
+/* freeReg - frees a register                                      */
+/*-----------------------------------------------------------------*/
+static void freeReg (regs *reg)
+{
+    reg->isFree = 1;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* nFreeRegs - returns number of free registers                    */
+/*-----------------------------------------------------------------*/
+static int nFreeRegs (int type)
+{
+    int i;
+    int nfr=0;
+    
+    for (i = 0 ; i < ds390_nRegs; i++ )
+       if (regs390[i].isFree && regs390[i].type == type)
+           nfr++;
+    return nfr;
+}
+
+/*-----------------------------------------------------------------*/
+/* nfreeRegsType - free registers with type                         */
+/*-----------------------------------------------------------------*/
+static int nfreeRegsType (int type)
+{
+    int nfr ;
+    if (type == REG_PTR) {
+       if ((nfr = nFreeRegs(type)) == 0)
+           return nFreeRegs(REG_GPR);
+    } 
+    
+    return nFreeRegs(type);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* allDefsOutOfRange - all definitions are out of a range          */
+/*-----------------------------------------------------------------*/
+static 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 */
+/*-----------------------------------------------------------------*/
+static bitVect *computeSpillable (iCode *ic)
+{
+    bitVect *spillable ;
+
+    /* spillable live ranges are those that are live at this 
+       point . the following categories need to be subtracted
+       from this set. 
+       a) - those that are already spilt
+       b) - if being used by this one
+       c) - defined by this one */
+    
+    spillable = bitVectCopy(ic->rlive);
+    spillable = 
+       bitVectCplAnd(spillable,_G.spiltSet); /* those already spilt */
+    spillable = 
+       bitVectCplAnd(spillable,ic->uses); /* used in this one */    
+    bitVectUnSetBit(spillable,ic->defKey);
+    spillable = bitVectIntersect(spillable,_G.regAssigned);
+    return spillable;
+    
+}
+
+/*-----------------------------------------------------------------*/
+/* noSpilLoc - return true if a variable has no spil location      */
+/*-----------------------------------------------------------------*/
+static int noSpilLoc (symbol *sym, eBBlock *ebp,iCode *ic)
+{
+    return (sym->usl.spillLoc ? 0 : 1);
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLoc - will return 1 if the symbol has spil location      */
+/*-----------------------------------------------------------------*/
+static int hasSpilLoc (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    return (sym->usl.spillLoc ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* directSpilLoc - will return 1 if the splilocation is in direct  */
+/*-----------------------------------------------------------------*/
+static int directSpilLoc (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    if ( sym->usl.spillLoc &&
+        (IN_DIRSPACE(SPEC_OCLS(sym->usl.spillLoc->etype))))
+       return 1;
+    else
+       return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLocnoUptr - will return 1 if the symbol has spil location*/
+/*                    but is not used as a pointer                 */
+/*-----------------------------------------------------------------*/
+static int hasSpilLocnoUptr (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* rematable - will return 1 if the remat flag is set              */
+/*-----------------------------------------------------------------*/
+static int rematable (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    return sym->remat;
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInBlock - not used in this block                         */
+/*-----------------------------------------------------------------*/
+static 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 */
+/*-----------------------------------------------------------------*/
+static int notUsedInRemaining (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    return ((usedInRemaining (operandFromSymbol(sym),ic) ? 0 : 1) &&
+           allDefsOutOfRange (sym->defs,ebp->fSeq,ebp->lSeq));
+}
+
+/*-----------------------------------------------------------------*/
+/* allLRs - return true for all                                    */
+/*-----------------------------------------------------------------*/
+static int allLRs (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* liveRangesWith - applies function to a given set of live range  */
+/*-----------------------------------------------------------------*/
+static set *liveRangesWith (bitVect *lrs, int (func)(symbol *,eBBlock *, iCode *),
+                    eBBlock *ebp, iCode *ic)
+{
+    set *rset = NULL;
+    int i;
+
+    if (!lrs || !lrs->size)
+       return NULL;
+
+    for ( i = 1 ; i < lrs->size ; i++ ) {
+       symbol *sym;
+       if (!bitVectBitValue(lrs,i))
+           continue ;
+
+       /* if we don't find it in the live range 
+          hash table we are in serious trouble */
+       if (!(sym = hTabItemWithKey(liveRanges,i))) {
+           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+                  "liveRangesWith could not find liveRange");
+           exit(1);
+       }
+       
+       if (func(sym,ebp,ic) && bitVectBitValue(_G.regAssigned,sym->key))
+           addSetHead(&rset,sym);
+    }
+
+    return rset;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* leastUsedLR - given a set determines which is the least used    */
+/*-----------------------------------------------------------------*/
+static symbol *leastUsedLR (set *sset)
+{
+    symbol *sym = NULL, *lsym = NULL ;
+    
+    sym = lsym = setFirstItem(sset);
+
+    if (!lsym)
+       return NULL;
+
+    for (; lsym; lsym = setNextItem(sset)) {
+       
+       /* if usage is the same then prefer
+          the spill the smaller of the two */
+       if ( lsym->used == sym->used )
+           if (getSize(lsym->type) < getSize(sym->type))
+               sym = lsym;
+
+       /* if less usage */
+       if (lsym->used < sym->used )
+           sym = lsym;
+       
+   }
+
+    setToNull((void **)&sset);
+    sym->blockSpil = 0;
+    return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* noOverLap - will iterate through the list looking for over lap  */
+/*-----------------------------------------------------------------*/
+static int noOverLap (set *itmpStack, symbol *fsym)
+{
+    symbol *sym;
+   
+
+    for (sym = setFirstItem(itmpStack); sym;
+        sym = setNextItem(itmpStack)) {
+       if (sym->liveTo > fsym->liveFrom )
+           return 0;
+           
+    }
+
+    return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* isFree - will return 1 if the a free spil location is found     */
+/*-----------------------------------------------------------------*/
+static DEFSETFUNC(isFree)
+{
+    symbol *sym = item;
+    V_ARG(symbol **,sloc);
+    V_ARG(symbol *,fsym);
+
+    /* if already found */
+    if (*sloc)
+       return 0;
+
+    /* if it is free && and the itmp assigned to
+       this does not have any overlapping live ranges
+       with the one currently being assigned and
+       the size can be accomodated  */
+    if (sym->isFree                        && 
+       noOverLap(sym->usl.itmpStack,fsym) &&
+       getSize(sym->type) >= getSize(fsym->type)) {
+       *sloc = sym;
+       return 1;
+    }
+
+    return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* spillLRWithPtrReg :- will spil those live ranges which use PTR  */
+/*-----------------------------------------------------------------*/
+static void spillLRWithPtrReg (symbol *forSym)
+{
+    symbol *lrsym;
+    regs *r0,*r1;
+    int k;
+
+    if (!_G.regAssigned ||
+       bitVectIsZero(_G.regAssigned))
+       return;
+
+    r0 = ds390_regWithIdx(R0_IDX);
+    r1 = ds390_regWithIdx(R1_IDX);
+
+    /* for all live ranges */
+    for (lrsym = hTabFirstItem(liveRanges,&k) ; lrsym ; 
+        lrsym = hTabNextItem(liveRanges,&k) ) {
+       int j;       
+
+       /* if no registers assigned to it or
+          spilt */
+       /* if it does not overlap with this then 
+          not need to spill it */
+
+       if (lrsym->isspilt || !lrsym->nRegs ||
+           (lrsym->liveTo < forSym->liveFrom))
+           continue ;
+
+       /* go thru the registers : if it is either
+          r0 or r1 then spil it */
+       for (j = 0 ; j < lrsym->nRegs ; j++ ) 
+           if (lrsym->regs[j] == r0 ||
+               lrsym->regs[j] == r1 ) {
+               spillThis (lrsym);
+               break;
+           }
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* createStackSpil - create a location on the stack to spil        */
+/*-----------------------------------------------------------------*/
+static symbol *createStackSpil (symbol *sym)
+{
+    symbol *sloc= NULL;
+    int useXstack, model, noOverlay;
+
+    char slocBuffer[30];
+
+    /* first go try and find a free one that is already 
+       existing on the stack */
+    if (applyToSet(_G.stackSpil,isFree,&sloc, sym)) {
+       /* found a free one : just update & return */
+       sym->usl.spillLoc = sloc;
+       sym->stackSpil= 1;
+       sloc->isFree = 0;
+       addSetHead(&sloc->usl.itmpStack,sym);
+       return sym;
+    }
+
+    /* could not then have to create one , this is the hard part
+       we need to allocate this on the stack : this is really a
+       hack!! but cannot think of anything better at this time */
+       
+    if (sprintf(slocBuffer,"sloc%d",_G.slocNum++) >= sizeof(slocBuffer))
+    {
+       fprintf(stderr, "***Internal error: slocBuffer overflowed: %s:%d\n",
+               __FILE__, __LINE__);
+       exit(1);        
+    }
+
+    sloc = newiTemp(slocBuffer);
+
+    /* set the type to the spilling symbol */
+    sloc->type = copyLinkChain(sym->type);
+    sloc->etype = getSpec(sloc->type);
+    SPEC_SCLS(sloc->etype) = options.model ? S_XDATA : S_DATA;
+    SPEC_EXTR(sloc->etype) = 0;
+
+    /* we don't allow it to be allocated`
+       onto the external stack since : so we
+       temporarily turn it off ; we also
+       turn off memory model to prevent
+       the spil from going to the external storage
+       and turn off overlaying 
+    */
+    
+    useXstack = options.useXstack;
+    model = options.model;
+    noOverlay = options.noOverlay;
+    options.noOverlay = 1;
+    
+    /* options.model = options.useXstack = 0; */
+
+    allocLocal(sloc);
+
+    options.useXstack = useXstack;
+    options.model     = model;
+    options.noOverlay = noOverlay;
+    sloc->isref = 1; /* to prevent compiler warning */
+    
+    /* if it is on the stack then update the stack */
+    if (IN_STACK(sloc->etype)) {
+       currFunc->stack += getSize(sloc->type);
+       _G.stackExtend += getSize(sloc->type);
+    } else
+       _G.dataExtend += getSize(sloc->type);
+
+    /* add it to the _G.stackSpil set */
+    addSetHead(&_G.stackSpil,sloc);
+    sym->usl.spillLoc = sloc;
+    sym->stackSpil = 1;
+    
+    /* add it to the set of itempStack set 
+       of the spill location */
+    addSetHead(&sloc->usl.itmpStack,sym);
+    return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* isSpiltOnStack - returns true if the spil location is on stack  */
+/*-----------------------------------------------------------------*/
+static bool isSpiltOnStack (symbol *sym)
+{
+    link *etype;
+
+    if (!sym)
+       return FALSE ;
+    
+    if (!sym->isspilt)
+       return FALSE ;
+
+/*     if (sym->_G.stackSpil) */
+/*     return TRUE; */
+    
+    if (!sym->usl.spillLoc)
+       return FALSE;
+
+    etype = getSpec(sym->usl.spillLoc->type);
+    if (IN_STACK(etype))
+       return TRUE;
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* spillThis - spils a specific operand                            */
+/*-----------------------------------------------------------------*/
+static void spillThis (symbol *sym)
+{
+    int i;
+    /* if this is rematerializable or has a spillLocation
+       we are okay, else we need to create a spillLocation
+       for it */
+    if (!(sym->remat || sym->usl.spillLoc)) 
+       createStackSpil (sym);
+    
+
+    /* mark it has spilt & put it in the spilt set */
+    sym->isspilt = 1;
+    _G.spiltSet = bitVectSetBit(_G.spiltSet,sym->key);
+       
+    bitVectUnSetBit(_G.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 (!ds390_ptrRegReq && isSpiltOnStack(sym)) {
+       ds390_ptrRegReq++ ;
+       spillLRWithPtrReg(sym);
+    }
+
+    if (sym->usl.spillLoc && !sym->remat)
+       sym->usl.spillLoc->allocreq = 1;
+    return;
+}
+
+/*-----------------------------------------------------------------*/
+/* selectSpil - select a iTemp to spil : rather a simple procedure */
+/*-----------------------------------------------------------------*/
+static symbol *selectSpil (iCode *ic, eBBlock *ebp, symbol *forSym)
+{
+    bitVect *lrcs= NULL ; 
+    set *selectS ;
+    symbol *sym;
+
+    /* get the spillable live ranges */
+    lrcs = computeSpillable (ic);
+
+    /* get all live ranges that are rematerizable */
+    if ((selectS = liveRangesWith(lrcs,rematable,ebp,ic))) {
+
+       /* return the least used of these */
+       return leastUsedLR(selectS);
+    }
+
+    /* get live ranges with spillLocations in direct space */
+    if ((selectS = liveRangesWith(lrcs,directSpilLoc,ebp,ic))) {
+       sym = leastUsedLR(selectS);
+       strcpy(sym->rname,(sym->usl.spillLoc->rname[0] ? 
+                          sym->usl.spillLoc->rname : 
+                          sym->usl.spillLoc->name)); 
+       sym->spildir = 1;
+       /* mark it as allocation required */
+       sym->usl.spillLoc->allocreq = 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 (!_G.blockSpil && (selectS = liveRangesWith(lrcs,notUsedInBlock,ebp,ic))) {
+           sym = leastUsedLR(selectS);
+           /* if this is not rematerializable */
+           if (!sym->remat) {
+               _G.blockSpil++;
+               sym->blockSpil = 1;
+           }
+           return sym;
+       } 
+
+       /* check if there are any live ranges that not
+          used in the remainder of the block */
+       if (!_G.blockSpil && (selectS = liveRangesWith(lrcs,notUsedInRemaining,ebp,ic))) {
+           sym = leastUsedLR (selectS);
+           if (!sym->remat) {
+               sym->remainSpil = 1;
+               _G.blockSpil++;
+           }
+           return sym;
+       }
+    }   
+
+    /* find live ranges with spillocation && not used as pointers */
+    if ((selectS = liveRangesWith(lrcs,hasSpilLocnoUptr,ebp,ic))) {
+       
+       sym =  leastUsedLR(selectS);
+       /* mark this as allocation required */
+       sym->usl.spillLoc->allocreq = 1;
+       return sym;
+    }
+
+    /* 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 ;
+   
+}
+
+/*-----------------------------------------------------------------*/
+/* spilSomething - spil some variable & mark registers as free     */
+/*-----------------------------------------------------------------*/
+static bool spilSomething (iCode *ic, eBBlock *ebp, symbol *forSym)
+{
+    symbol *ssym;
+    int i ;
+
+    /* get something we can spil */
+    ssym = selectSpil(ic,ebp,forSym);
+    
+    /* mark it as spilt */
+    ssym->isspilt = 1;
+    _G.spiltSet = bitVectSetBit(_G.spiltSet,ssym->key);
+    
+    /* mark it as not register assigned &
+       take it away from the set */   
+    bitVectUnSetBit(_G.regAssigned,ssym->key);
+    /* mark the registers as free */    
+    for (i = 0 ; i < ssym->nRegs ;i++ )
+       if (ssym->regs[i])
+           freeReg(ssym->regs[i]);
+     
+    /* if spilt on stack then free up r0 & r1 
+       if they could have been assigned to as gprs */
+    if (!ds390_ptrRegReq && isSpiltOnStack(ssym) ) {
+       ds390_ptrRegReq++ ;
+       spillLRWithPtrReg(ssym);
+    }
+
+    /* if this was a block level spil then insert push & pop 
+       at the start & end of block respectively */
+    if (ssym->blockSpil) {
+       iCode *nic = newiCode(IPUSH,operandFromSymbol(ssym),NULL);
+       /* add push to the start of the block */
+       addiCodeToeBBlock(ebp,nic,( ebp->sch->op == LABEL ? 
+                                   ebp->sch->next : ebp->sch));
+       nic = newiCode(IPOP,operandFromSymbol(ssym),NULL);
+       /* add pop to the end of the block */
+       addiCodeToeBBlock(ebp,nic,NULL);
+    }       
+
+    /* if spilt because not used in the remainder of the
+       block then add a push before this instruction and
+       a pop at the end of the block */
+    if (ssym->remainSpil) {
+
+       iCode *nic = newiCode(IPUSH,operandFromSymbol(ssym),NULL);
+       /* add push just before this instruction */
+       addiCodeToeBBlock(ebp,nic,ic);
+                                   
+       nic = newiCode(IPOP,operandFromSymbol(ssym),NULL);
+       /* add pop to the end of the block */
+       addiCodeToeBBlock(ebp,nic,NULL);    
+    }
+
+    if (ssym == forSym )
+       return FALSE ;
+    else
+       return TRUE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegPtr - will try for PTR if not a GPR type if not spil      */
+/*-----------------------------------------------------------------*/
+static regs *getRegPtr (iCode *ic, eBBlock *ebp, symbol *sym)
+{
+    regs *reg;
+
+ tryAgain:
+    /* try for a ptr type */
+    if ((reg = allocReg(REG_PTR))) 
+       return reg;    
+
+    /* try for gpr type */
+    if ((reg = allocReg(REG_GPR)))        
+       return reg;    
+
+    /* we have to spil */
+    if (!spilSomething (ic,ebp,sym))
+       return NULL ;
+
+    /* this looks like an infinite loop but 
+       in really selectSpil will abort  */
+    goto tryAgain ;    
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegGpr - will try for GPR if not spil                        */
+/*-----------------------------------------------------------------*/
+static regs *getRegGpr (iCode *ic, eBBlock *ebp,symbol *sym)
+{
+    regs *reg;
+
+ tryAgain:
+    /* try for gpr type */
+    if ((reg = allocReg(REG_GPR)))        
+       return reg;    
+
+    if (!ds390_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 ;    
+}
+
+/*-----------------------------------------------------------------*/
+/* symHasReg - symbol has a given register                         */
+/*-----------------------------------------------------------------*/
+static bool symHasReg(symbol *sym,regs *reg)
+{
+    int i;
+
+    for ( i = 0 ; i < sym->nRegs ; i++)
+       if (sym->regs[i] == reg)
+           return TRUE;
+           
+    return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* deassignLRs - check the live to and if they have registers & are*/
+/*               not spilt then free up the registers              */
+/*-----------------------------------------------------------------*/
+static void deassignLRs (iCode *ic, eBBlock *ebp)
+{
+    symbol *sym;
+    int k;
+    symbol *result;
+
+    for (sym = hTabFirstItem(liveRanges,&k); sym;
+        sym = hTabNextItem(liveRanges,&k)) {
+       
+       symbol *psym= NULL;
+       /* if it does not end here */
+       if (sym->liveTo > ic->seq )
+           continue ;
+
+       /* if it was spilt on stack then we can 
+          mark the stack spil location as free */
+       if (sym->isspilt ) {
+           if (sym->stackSpil) {
+               sym->usl.spillLoc->isFree = 1;
+               sym->stackSpil = 0;
+           }
+           continue ;
+       }
+       
+       if (!bitVectBitValue(_G.regAssigned,sym->key))
+           continue;
+       
+       /* special case check if this is an IFX &
+          the privious one was a pop and the 
+          previous one was not spilt then keep track
+          of the symbol */     
+       if (ic->op == IFX && ic->prev &&
+           ic->prev->op == IPOP && 
+           !ic->prev->parmPush  &&
+           !OP_SYMBOL(IC_LEFT(ic->prev))->isspilt) 
+           psym = OP_SYMBOL(IC_LEFT(ic->prev));
+
+       if (sym->nRegs) {
+           int i = 0;
+           
+           bitVectUnSetBit(_G.regAssigned,sym->key);
+
+           /* if the result of this one needs registers
+              and does not have it then assign it right
+              away */
+           if (IC_RESULT(ic) &&
+               !  (SKIP_IC2(ic) ||               /* not a special icode */
+                   ic->op == JUMPTABLE ||
+                   ic->op == IFX ||
+                   ic->op == IPUSH ||
+                   ic->op == IPOP ||
+                   ic->op == RETURN ||
+                   POINTER_SET(ic))     &&             
+               (result = OP_SYMBOL(IC_RESULT(ic))) && /* has a result */
+               result->liveTo > ic->seq &&            /* and will live beyond this */
+               result->liveTo <= ebp->lSeq &&         /* does not go beyond this block */
+               result->regType == sym->regType &&     /* same register types */
+               result->nRegs            &&            /* which needs registers */
+               ! result->isspilt        &&            /* and does not already have them */
+               ! result->remat          &&
+               ! bitVectBitValue(_G.regAssigned,result->key) &&
+               /* the number of free regs + number of regs in this LR
+                  can accomodate the what result Needs */
+               ((nfreeRegsType(result->regType) +
+                 sym->nRegs) >= result->nRegs)
+               ) {
+               
+               for (i = 0 ; i < max(sym->nRegs,result->nRegs) ; i++)
+                   if (i < sym->nRegs )
+                       result->regs[i] = sym->regs[i] ;
+                   else
+                       result->regs[i] = getRegGpr (ic,ebp,result);
+
+               _G.regAssigned = bitVectSetBit(_G.regAssigned,result->key);
+               
+           }                   
+           
+           /* 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]);
+           }
+       }
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* reassignLR - reassign this to registers                         */
+/*-----------------------------------------------------------------*/
+static void reassignLR (operand *op)
+{
+    symbol *sym = OP_SYMBOL(op);
+    int i;
+
+    /* not spilt any more */     
+    sym->isspilt = sym->blockSpil  = sym->remainSpil = 0;
+    bitVectUnSetBit(_G.spiltSet,sym->key);
+      
+    _G.regAssigned = bitVectSetBit(_G.regAssigned,sym->key);
+
+    _G.blockSpil--;
+
+    for (i=0;i<sym->nRegs;i++)
+       sym->regs[i]->isFree = 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* willCauseSpill - determines if allocating will cause a spill    */
+/*-----------------------------------------------------------------*/
+static int willCauseSpill ( int nr, int rt)
+{
+    /* first check if there are any avlb registers
+       of te type required */
+    if (rt == REG_PTR) {
+       /* special case for pointer type 
+          if pointer type not avlb then 
+          check for type gpr */
+       if (nFreeRegs(rt) >= nr)
+           return 0;
+       if (nFreeRegs(REG_GPR) >= nr)
+           return 0;
+    } else {
+       if (ds390_ptrRegReq) {
+           if (nFreeRegs(rt) >= nr)
+               return 0;
+       } else {
+           if (nFreeRegs(REG_PTR) +
+               nFreeRegs(REG_GPR) >= nr)
+               return 0;
+       }
+    }
+
+    /* it will cause a spil */
+    return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* positionRegs - the allocator can allocate same registers to res-*/
+/* ult and operand, if this happens make sure they are in the same */
+/* position as the operand otherwise chaos results                 */
+/*-----------------------------------------------------------------*/
+static 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;
+       }
+}
+
+/*-----------------------------------------------------------------*/
+/* serialRegAssign - serially allocate registers to the variables  */
+/*-----------------------------------------------------------------*/
+static void serialRegAssign (eBBlock **ebbs, int count)
+{
+    int i;
+
+    /* for all blocks */
+    for (i = 0; i < count ; i++ ) {
+       
+       iCode *ic;
+       
+       if (ebbs[i]->noPath &&
+           (ebbs[i]->entryLabel != entryLabel &&
+            ebbs[i]->entryLabel != returnLabel ))
+           continue ;
+
+       /* of all instructions do */
+       for (ic = ebbs[i]->sch ; ic ; ic = ic->next) {
+        
+           /* if 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 */
+           if (SKIP_IC2(ic) ||
+               ic->op == JUMPTABLE ||
+               ic->op == IFX ||
+               ic->op == IPUSH ||
+               ic->op == IPOP ||
+               (IC_RESULT(ic) &&POINTER_SET(ic)) )
+               continue;   
+           
+           /* now we need to allocate registers
+              only for the result */
+           if (IC_RESULT(ic)) {
+               symbol *sym = OP_SYMBOL(IC_RESULT(ic));
+               bitVect *spillable;
+               int willCS ;
+               int j;
+               int ptrRegSet = 0;
+                              
+               /* if it does not need or is spilt 
+                  or is already assigned to registers
+                  or will not live beyond this instructions */
+               if (!sym->nRegs      || 
+                   sym->isspilt     || 
+                   bitVectBitValue(_G.regAssigned,sym->key) ||
+                   sym->liveTo <= ic->seq)
+                   continue ;
+
+               /* if some liverange has been spilt at the block level
+                  and this one live beyond this block then spil this
+                  to be safe */
+               if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) {
+                   spillThis (sym);
+                   continue ;
+               }
+               /* if trying to allocate this will cause
+                  a spill and there is nothing to spill 
+                  or this one is rematerializable then
+                  spill this one */
+               willCS = willCauseSpill(sym->nRegs,sym->regType);
+               spillable = computeSpillable(ic);
+               if ( sym->remat ||                  
+                   (willCS  && bitVectIsZero(spillable) ) ) {
+
+                   spillThis (sym) ;
+                   continue ;
+
+               }
+
+               /* if it has a spillocation & is used less than
+                  all other live ranges then spill this */
+               if ( willCS && sym->usl.spillLoc ) {
+
+                   symbol *leastUsed = 
+                       leastUsedLR(liveRangesWith (spillable ,
+                                                   allLRs,
+                                                   ebbs[i],
+                                                   ic));
+                   if (leastUsed && 
+                       leastUsed->used > sym->used) {
+                       spillThis (sym);
+                       continue;
+                   }
+               }               
+               
+               /* if we need ptr regs for the right side
+                  then mark it */
+               if (POINTER_GET(ic) && getSize(OP_SYMBOL(IC_LEFT(ic))->type) 
+                   <= PTRSIZE) 
+               {
+                   ds390_ptrRegReq++;
+                   ptrRegSet = 1;
+               }
+               /* else we assign registers to it */            
+               _G.regAssigned = bitVectSetBit(_G.regAssigned,sym->key);
+
+               for (j = 0 ; j < sym->nRegs ;j++ ) {
+                   if (sym->regType == REG_PTR)
+                       sym->regs[j] = getRegPtr(ic,ebbs[i],sym);
+                   else
+                       sym->regs[j] = getRegGpr(ic,ebbs[i],sym);
+
+                   /* if the allocation 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)
+                       positionRegs(OP_SYMBOL(IC_RESULT(ic)),
+                                    OP_SYMBOL(IC_RIGHT(ic)),ic->lineno);
+               
+               if (ptrRegSet) {
+                   ds390_ptrRegReq--;
+                   ptrRegSet = 0;
+               }
+                               
+           }       
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand             */
+/*-----------------------------------------------------------------*/
+static 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(ds390_nRegs);
+
+    for (j = 0; j < sym->nRegs; j++) { 
+       rumask = bitVectSetBit(rumask,
+                              sym->regs[j]->rIdx);
+    }
+
+    return rumask;
+}
+
+/*-----------------------------------------------------------------*/
+/* regsUsedIniCode :- returns bit vector of registers used in iCode*/
+/*-----------------------------------------------------------------*/
+static bitVect *regsUsedIniCode (iCode *ic)
+{
+    bitVect *rmask = newBitVect(ds390_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;
+}
+
+/*-----------------------------------------------------------------*/
+/* createRegMask - for each instruction will determine the regsUsed*/
+/*-----------------------------------------------------------------*/
+static void createRegMask (eBBlock **ebbs, int count)
+{
+    int i;
+
+    /* for all blocks */
+    for (i = 0; i < count ; i++ ) {
+       iCode *ic ;
+
+       if ( ebbs[i]->noPath &&
+            ( ebbs[i]->entryLabel != entryLabel &&
+              ebbs[i]->entryLabel != returnLabel ))
+           continue ;
+
+       /* for all instructions */
+       for ( ic = ebbs[i]->sch ; ic ; ic = ic->next ) {
+           
+           int j;
+
+           if (SKIP_IC2(ic) || !ic->rlive)
+               continue ;
+           
+           /* first mark the registers used in this
+              instruction */
+           ic->rUsed = regsUsedIniCode(ic);
+           _G.funcrUsed = bitVectUnion(_G.funcrUsed,ic->rUsed);
+
+           /* now create the register mask for those 
+              registers that are in use : this is a
+              super set of ic->rUsed */
+           ic->rMask = newBitVect(ds390_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);
+           }
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* rematStr - returns the rematerialized string for a remat var    */
+/*-----------------------------------------------------------------*/
+static 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   */
+/*-----------------------------------------------------------------*/
+static void regTypeNum ()
+{
+    symbol *sym;
+    int k;
+    iCode *ic;
+
+    /* for each live range do */
+    for ( sym = hTabFirstItem(liveRanges,&k); sym ;
+         sym = hTabNextItem(liveRanges,&k)) {
+
+       /* if used zero times then no registers needed */
+       if ((sym->liveTo - sym->liveFrom) == 0)
+           continue ;
+
+
+       /* if the live range is a temporary */
+       if (sym->isitmp) {
+
+           /* if the type is marked as a conditional */
+           if (sym->regType == REG_CND)
+               continue ;
+
+           /* if used in return only then we don't 
+              need registers */
+           if (sym->ruonly || sym->accuse) {
+               if (IS_AGGREGATE(sym->type) || sym->isptr)
+                   sym->type = aggrToPtr(sym->type,FALSE);
+               continue ;
+           }
+           
+           /* if the symbol has only one definition &
+              that definition is a get_pointer and the
+              pointer we are getting is rematerializable and
+              in "data" space */
+              
+           if (bitVectnBitsOn(sym->defs) == 1 &&
+               (ic = hTabItemWithKey(iCodehTab,
+                                     bitVectFirstBit(sym->defs))) &&
+               POINTER_GET(ic) && 
+               !IS_BITVAR(sym->etype)) {
+               
+                               
+               /* if remat in data space */
+               if (OP_SYMBOL(IC_LEFT(ic))->remat &&
+                   // sym->type &&
+                   DCL_TYPE(aggrToPtr(sym->type,FALSE)) == POINTER) {
+               
+                   /* create a psuedo symbol & force a spil */
+                   symbol *psym = newSymbol(rematStr(OP_SYMBOL(IC_LEFT(ic))),1);
+                   psym->type = sym->type;
+                   psym->etype = sym->etype;
+                   strcpy(psym->rname,psym->name);
+                   sym->isspilt = 1;
+                   sym->usl.spillLoc = psym;
+                   continue ;
+               }
+
+               /* if in data space or idata space then try to
+                  allocate pointer register */
+                  
+           }
+               
+           /* if not then we require registers */
+           sym->nRegs = ((IS_AGGREGATE(sym->type) || sym->isptr ) ?
+                         getSize(sym->type = aggrToPtr(sym->type,FALSE)) :
+                         getSize(sym->type));
+
+           if (sym->nRegs > 4) {
+               fprintf(stderr,"allocated more than 4 or 0 registers for type ");
+               printTypeChain(sym->type,stderr);fprintf(stderr,"\n");
+            }
+           
+           /* determine the type of register required */
+           if (sym->nRegs == 1   && 
+               IS_PTR(sym->type) && 
+               sym->uptr) 
+               sym->regType = REG_PTR ;            
+           else 
+               sym->regType = REG_GPR ;
+           
+       } else 
+           /* for the first run we don't provide */
+           /* registers for true symbols we will */
+           /* see how things go                  */
+           sym->nRegs = 0 ;    
+    }
+    
+}
+
+/*-----------------------------------------------------------------*/
+/* freeAllRegs - mark all registers as free                        */
+/*-----------------------------------------------------------------*/
+static void freeAllRegs()
+{
+    int i;
+
+    for (i=0;i< ds390_nRegs;i++ )
+       regs390[i].isFree = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* deallocStackSpil - this will set the stack pointer back         */
+/*-----------------------------------------------------------------*/
+static DEFSETFUNC(deallocStackSpil)
+{
+    symbol *sym = item;
+
+    deallocLocal(sym);
+    return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* farSpacePackable - returns the packable icode for far variables */
+/*-----------------------------------------------------------------*/
+static iCode *farSpacePackable (iCode *ic)
+{
+    iCode *dic ;
+
+    /* go thru till we find a definition for the
+       symbol on the right */
+    for ( dic = ic->prev ; dic ; dic = dic->prev) {
+               
+       /* if the definition is a call then no */
+       if ((dic->op == CALL || dic->op == PCALL) &&
+           IC_RESULT(dic)->key == IC_RIGHT(ic)->key) {
+           return NULL;
+       }
+       
+       /* if shift by unknown amount then not */
+       if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
+           IC_RESULT(dic)->key == IC_RIGHT(ic)->key)
+           return NULL;
+
+       /* if pointer get and size > 1 */
+       if (POINTER_GET(dic) &&
+           getSize(aggrToPtr(operandType(IC_LEFT(dic)),FALSE)) > 1)
+           return NULL ;
+
+       if (POINTER_SET(dic) &&
+           getSize(aggrToPtr(operandType(IC_RESULT(dic)),FALSE)) > 1)
+           return NULL ;
+
+       /* if any three is a true symbol in far space */
+       if (IC_RESULT(dic) &&
+           IS_TRUE_SYMOP(IC_RESULT(dic)) &&
+           isOperandInFarSpace(IC_RESULT(dic)))         
+           return NULL;
+
+       if (IC_RIGHT(dic) &&
+           IS_TRUE_SYMOP(IC_RIGHT(dic)) &&
+           isOperandInFarSpace(IC_RIGHT(dic)) &&
+           !isOperandEqual(IC_RIGHT(dic),IC_RESULT(ic)))
+           return NULL;
+
+       if (IC_LEFT(dic) &&
+           IS_TRUE_SYMOP(IC_LEFT(dic)) &&
+           isOperandInFarSpace(IC_LEFT(dic)) &&
+           !isOperandEqual(IC_LEFT(dic),IC_RESULT(ic)))
+           return NULL;
+       
+       if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(dic))) {
+           if ( (dic->op == LEFT_OP  ||
+                 dic->op == RIGHT_OP ||
+                 dic->op == '-') &&
+                IS_OP_LITERAL(IC_RIGHT(dic)))
+               return NULL;
+           else
+               return dic;
+       }
+    }
+
+    return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForAssign - register reduction for assignment           */
+/*-----------------------------------------------------------------*/
+static int packRegsForAssign (iCode *ic,eBBlock *ebp)
+{
+    iCode *dic, *sic;
+    
+    if (!IS_ITEMP(IC_RIGHT(ic))       ||       
+       OP_SYMBOL(IC_RIGHT(ic))->isind ||
+       OP_LIVETO(IC_RIGHT(ic)) > ic->seq) {
+       return 0;
+    }
+       
+    /* if the true symbol is defined in far space or on stack
+       then we should not since this will increase register pressure */
+    if (isOperandInFarSpace(IC_RESULT(ic))) {
+       if ((dic = farSpacePackable(ic)))
+           goto pack;
+       else
+           return 0;
+       
+    }
+    /* 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 (IS_TRUE_SYMOP(IC_RESULT(dic)) &&
+           IS_OP_VOLATILE(IC_RESULT(dic))) {
+               dic = NULL;
+               break;
+       }
+
+       if (IS_SYMOP(IC_RESULT(dic)) &&
+           IC_RESULT(dic)->key == IC_RIGHT(ic)->key) {
+           if (POINTER_SET(dic))
+               dic = NULL;
+
+           break;          
+       }
+
+       if (IS_SYMOP(IC_RIGHT(dic)) && 
+           (IC_RIGHT(dic)->key == IC_RESULT(ic)->key ||
+            IC_RIGHT(dic)->key == IC_RIGHT(ic)->key)) {
+           dic = NULL;
+           break;
+       }
+       
+       if (IS_SYMOP(IC_LEFT(dic)) && 
+           (IC_LEFT(dic)->key == IC_RESULT(ic)->key ||
+            IC_LEFT(dic)->key == IC_RIGHT(ic)->key)) {
+           dic = NULL;
+           break;
+       }
+
+       if (POINTER_SET(dic) && 
+           IC_RESULT(dic)->key == IC_RESULT(ic)->key ) {
+           dic = NULL ;
+           break;
+       }
+    }
+    
+    if (!dic)
+       return 0 ; /* did not find */
+           
+    /* if 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);
+    hTabDeleteItem (&iCodehTab,ic->key,ic,DELETE_ITEM,NULL);
+    OP_DEFS(IC_RESULT(dic)) = bitVectSetBit(OP_DEFS(IC_RESULT(dic)),dic->key);
+    return 1;
+    
+}
+
+/*-----------------------------------------------------------------*/
+/* findAssignToSym : scanning backwards looks for first assig found*/
+/*-----------------------------------------------------------------*/
+static iCode *findAssignToSym (operand *op,iCode *ic)
+{
+    iCode *dic;
+
+    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   */
+/*-----------------------------------------------------------------*/
+static 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);
+       hTabDeleteItem (&iCodehTab,dic->key,dic,DELETE_ITEM,NULL);
+       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 ;
+
+       /* if this is a subtraction & the result
+          is a true symbol in far space then don't pack */
+       if (ic->op == '-' && IS_TRUE_SYMOP(IC_RESULT(dic))) {
+           link *etype =getSpec(operandType(IC_RESULT(dic)));
+           if (IN_FARSPACE(SPEC_OCLS(etype)))
+               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);
+       hTabDeleteItem (&iCodehTab,dic->key,dic,DELETE_ITEM,NULL);
+       change ++;
+    }
+   
+    return change ;
+}
+
+#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
+
+
+/*-----------------------------------------------------------------*/
+/* packRegsForOneuse : - will reduce some registers for single Use */ 
+/*-----------------------------------------------------------------*/
+static iCode *packRegsForOneuse (iCode *ic, operand *op , eBBlock *ebp)
+{
+    bitVect *uses ;
+    iCode *dic, *sic;
+
+    /* if returning a literal then do nothing */
+    if (!IS_SYMOP(op))
+       return NULL;
+    
+    /* only upto 2 bytes since we cannot predict
+       the usage of b, & acc */
+    if (getSize(operandType(op)) >  (fReturnSize_390 - 2) &&
+       ic->op != RETURN             &&
+       ic->op != SEND               &&
+       !POINTER_SET(ic)             &&
+       !POINTER_GET(ic))
+       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) && 
+       !IS_DATA_PTR(aggrToPtr(operandType(IC_RESULT(dic)),FALSE)))
+       return NULL ;
+
+    if (POINTER_GET(dic) && 
+       !IS_DATA_PTR(aggrToPtr(operandType(IC_LEFT(dic)),FALSE)))
+       return NULL ;
+    
+    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) && 
+           !IS_DATA_PTR(aggrToPtr(operandType(IC_RESULT(dic)),FALSE)))
+           return NULL ;
+       
+       if (POINTER_GET(dic) && 
+           !IS_DATA_PTR(aggrToPtr(operandType(IC_LEFT(dic)),FALSE)))
+           return NULL ;
+
+       /* if address of & the result is remat the okay */
+       if (dic->op == ADDRESS_OF &&
+           OP_SYMBOL(IC_RESULT(dic))->remat)
+           continue ;
+          
+       /* if operand has size of three or more & this
+          operation is a '*','/' or '%' then 'b' may
+          cause a problem */
+       if (( dic->op == '%' || dic->op == '/' || dic->op == '*') &&
+           getSize(operandType(op)) >= 3)
+               return NULL;
+
+       /* 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 *ltype = getSpec(operandType(IC_LEFT(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) ||
+        (IS_BITVAR(ltype) && IN_BITSPACE(SPEC_OCLS(ltype))))
+       return TRUE ;
+    else
+       return FALSE ;    
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForAccUse - pack registers for acc use                  */
+/*-----------------------------------------------------------------*/
+static 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 ;
+       
+    if (IS_BITWISE_OP(ic) &&
+       getSize(operandType(IC_RESULT(ic))) > 1)
+       return ;
+           
+       
+    /* has only one definition */
+    if (bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) > 1)
+       return ;
+
+    /* has only one use */
+    if (bitVectnBitsOn(OP_USES(IC_RESULT(ic))) > 1)
+       return ;
+
+    /* and the usage immediately follows this iCode */
+    if (!(uic = hTabItemWithKey(iCodehTab,
+                               bitVectFirstBit(OP_USES(IC_RESULT(ic))))))
+       return ;
+
+    if (ic->next != uic)
+       return ;
+    
+    /* if it is a conditional branch then we definitely can */
+    if (uic->op == IFX  ) 
+       goto accuse;
+
+    if ( uic->op == JUMPTABLE )
+       return ;
+
+    /* if 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;
+
+    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 ;
+           
+    /* 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 ;
+
+    /* 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 ;
+
+    /* 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 ;
+    }
+
+    /* if the other one is not on stack then we can */
+    if (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
+       (IS_ITEMP(IC_RIGHT(uic)) ||
+        (IS_TRUE_SYMOP(IC_RIGHT(uic)) &&
+         !OP_SYMBOL(IC_RIGHT(uic))->onStack))) 
+       goto accuse;
+    
+    if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
+       (IS_ITEMP(IC_LEFT(uic)) ||
+        (IS_TRUE_SYMOP(IC_LEFT(uic)) &&
+         !OP_SYMBOL(IC_LEFT(uic))->onStack))) 
+       goto accuse ;
+
+    return ;
+
+ accuse:
+    OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
+    
+        
+}
+
+/*-----------------------------------------------------------------*/
+/* packForPush - hueristics to reduce iCode for pushing            */
+/*-----------------------------------------------------------------*/
+static void packForPush(iCode *ic, eBBlock *ebp)
+{
+    iCode *dic;
+
+    if (ic->op != IPUSH || !IS_ITEMP(IC_LEFT(ic)))
+       return ;
+
+    /* must have only definition & one usage */
+    if (bitVectnBitsOn(OP_DEFS(IC_LEFT(ic))) != 1 ||
+       bitVectnBitsOn(OP_USES(IC_LEFT(ic))) != 1 )     
+       return ;
+    
+    /* find the definition */
+    if (!(dic = hTabItemWithKey(iCodehTab,
+                               bitVectFirstBit(OP_DEFS(IC_LEFT(ic))))))
+       return ;
+
+    if (dic->op != '=' || POINTER_SET(dic))
+       return;
+
+    /* we now we know that it has one & only one def & use
+       and the that the definition is an assignment */
+    IC_LEFT(ic) = IC_RIGHT(dic);
+
+    remiCodeFromeBBlock(ebp,dic);
+    hTabDeleteItem (&iCodehTab,dic->key,dic,DELETE_ITEM,NULL);
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegisters - does some transformations to reduce register    */
+/*                   pressure                                      */
+/*-----------------------------------------------------------------*/
+static void packRegisters (eBBlock *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 ) {
+               
+       /* 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;
+
+       }
+       
+       /* 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 this is a +/- operation with a rematerizable 
+          then mark this as rematerializable as well */
+       if ((ic->op == '+' || ic->op == '-') &&
+           (IS_SYMOP(IC_LEFT(ic)) && 
+            IS_ITEMP(IC_RESULT(ic)) &&
+            OP_SYMBOL(IC_LEFT(ic))->remat &&
+             bitVectnBitsOn(OP_DEFS(IC_RESULT(ic))) == 1 &&
+            IS_OP_LITERAL(IC_RIGHT(ic))) ) {
+
+           int i = operandLitValue(IC_RIGHT(ic));
+           OP_SYMBOL(IC_RESULT(ic))->remat = 1;
+           OP_SYMBOL(IC_RESULT(ic))->rematiCode = ic;
+           OP_SYMBOL(IC_RESULT(ic))->usl.spillLoc = NULL;
+       }
+
+       /* mark the pointer usages */
+       if (POINTER_SET(ic))
+           OP_SYMBOL(IC_RESULT(ic))->uptr = 1;
+
+       if (POINTER_GET(ic))
+           OP_SYMBOL(IC_LEFT(ic))->uptr = 1;
+       
+       if (!SKIP_IC2(ic)) {
+           /* if we are using a symbol on the stack
+              then we should say ds390_ptrRegReq */
+           if (ic->op == IFX && IS_SYMOP(IC_COND(ic)))
+               ds390_ptrRegReq += ((OP_SYMBOL(IC_COND(ic))->onStack ||
+                              OP_SYMBOL(IC_COND(ic))->iaccess) ? 1 : 0);
+           else
+               if (ic->op == JUMPTABLE && IS_SYMOP(IC_JTCOND(ic)))
+                   ds390_ptrRegReq += ((OP_SYMBOL(IC_JTCOND(ic))->onStack ||
+                                  OP_SYMBOL(IC_JTCOND(ic))->iaccess) ? 1 : 0);
+               else {
+                   if (IS_SYMOP(IC_LEFT(ic)))
+                       ds390_ptrRegReq += ((OP_SYMBOL(IC_LEFT(ic))->onStack ||
+                                      OP_SYMBOL(IC_LEFT(ic))->iaccess) ? 1 : 0);
+                   if (IS_SYMOP(IC_RIGHT(ic)))
+                       ds390_ptrRegReq += ((OP_SYMBOL(IC_RIGHT(ic))->onStack ||
+                                      OP_SYMBOL(IC_RIGHT(ic))->iaccess) ? 1 : 0);
+                   if (IS_SYMOP(IC_RESULT(ic)))
+                       ds390_ptrRegReq += ((OP_SYMBOL(IC_RESULT(ic))->onStack ||
+                                      OP_SYMBOL(IC_RESULT(ic))->iaccess) ? 1 : 0);    
+               }
+       }
+
+       /* 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 ;
+       }
+       
+       /* reduce for support function calls */
+       if (ic->supportRtn || ic->op == '+' || ic->op == '-' )
+           packRegsForSupport (ic,ebp);        
+       
+       /* 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);     
+
+       /* if pointer set & left has a size more than
+          one and right is not in far space */
+       if (POINTER_SET(ic)                    &&
+           !isOperandInFarSpace(IC_RIGHT(ic)) &&
+           !OP_SYMBOL(IC_RESULT(ic))->remat   &&
+           !IS_OP_RUONLY(IC_RIGHT(ic))        &&
+           getSize(aggrToPtr(operandType(IC_RESULT(ic)),FALSE)) > 1 )
+
+           packRegsForOneuse (ic,IC_RESULT(ic),ebp);
+
+       /* if pointer get */
+       if (POINTER_GET(ic)                    &&
+           !isOperandInFarSpace(IC_RESULT(ic))&&
+           !OP_SYMBOL(IC_LEFT(ic))->remat     &&
+           !IS_OP_RUONLY(IC_RESULT(ic))         &&
+           getSize(aggrToPtr(operandType(IC_LEFT(ic)),FALSE)) > 1 )
+
+           packRegsForOneuse (ic,IC_LEFT(ic),ebp);
+
+
+       /* if this is cast for intergral promotion then
+          check if only use of  the definition of the 
+          operand being casted/ if yes then replace
+          the result of that arithmetic operation with 
+          this result and get rid of the cast */
+       if (ic->op == CAST) {
+           link *fromType = operandType(IC_RIGHT(ic));
+           link *toType = operandType(IC_LEFT(ic));
+
+           if (IS_INTEGRAL(fromType) && IS_INTEGRAL(toType) &&
+               getSize(fromType) != getSize(toType) ) {
+
+               iCode *dic = packRegsForOneuse(ic,IC_RIGHT(ic),ebp);
+               if (dic) {
+                   if (IS_ARITHMETIC_OP(dic)) {
+                       IC_RESULT(dic) = IC_RESULT(ic);
+                       remiCodeFromeBBlock(ebp,ic);
+                       hTabDeleteItem (&iCodehTab,ic->key,ic,DELETE_ITEM,NULL);
+                       OP_DEFS(IC_RESULT(dic)) = bitVectSetBit(OP_DEFS(IC_RESULT(dic)),dic->key);
+                       ic = ic->prev;
+                   } else
+                       OP_SYMBOL(IC_RIGHT(ic))->ruonly =  0;
+               }               
+           } else {
+               
+               /* if the type from and type to are the same
+                  then if this is the only use then packit */
+               if (checkType(operandType(IC_RIGHT(ic)),
+                             operandType(IC_LEFT(ic))) == 1) {
+                   iCode *dic = packRegsForOneuse (ic,IC_RIGHT(ic),ebp);
+                   if (dic) {
+                       IC_RESULT(dic) = IC_RESULT(ic);
+                       remiCodeFromeBBlock(ebp,ic);
+                       hTabDeleteItem (&iCodehTab,ic->key,ic,DELETE_ITEM,NULL);
+                       OP_DEFS(IC_RESULT(dic)) = bitVectSetBit(OP_DEFS(IC_RESULT(dic)),dic->key);
+                       ic = ic->prev;
+                   }
+               }
+           }
+       }
+       
+       /* pack for PUSH 
+          iTempNN := (some variable in farspace) V1
+          push iTempNN ;
+          -------------
+          push V1
+       */
+       if (ic->op == IPUSH ) {
+           packForPush(ic,ebp);
+       }
+         
+       
+       /* 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 ds390_assignRegisters (eBBlock **ebbs, int count)
+{
+    iCode *ic;
+    int i ;
+
+    setToNull((void *)&_G.funcrUsed);
+    ds390_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
+    /* if not register extentions then reduce number
+       of registers */
+    if (options.regExtend)
+       ds390_nRegs = 13;
+    else
+       ds390_nRegs = 8;
+
+    /* 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 (_G.stackExtend) {
+/*     werror(W_TOOMANY_SPILS,"stack", */
+/*            _G.stackExtend,currFunc->name,""); */
+       _G.stackExtend = 0 ;
+    }
+
+    if (_G.dataExtend) {
+/*     werror(W_TOOMANY_SPILS,"data space", */
+/*            _G.dataExtend,currFunc->name,""); */
+       _G.dataExtend = 0 ;
+    }  
+
+    /* after that create the register mask
+       for each of the instruction */
+    createRegMask (ebbs,count);
+
+    /* redo that offsets for stacked automatic variables */
+    redoStackOffsets ();
+
+    if (options.dump_rassgn)
+       dumpEbbsToFileExt(".dumprassgn",ebbs,count);
+
+    /* now get back the chain */
+    ic = iCodeLabelOptimize(iCodeFromeBBlock (ebbs,count));
+
+
+    gen390Code(ic);
+
+    /* free up any _G.stackSpil locations allocated */   
+    applyToSet(_G.stackSpil,deallocStackSpil);
+    _G.slocNum = 0;
+    setToNull((void **)&_G.stackSpil);
+    setToNull((void **)&_G.spiltSet);
+    /* mark all registers as free */
+    freeAllRegs();
+
+    return ;
+}
diff --git a/src/ds390/ralloc.h b/src/ds390/ralloc.h
new file mode 100644 (file)
index 0000000..6b3a754
--- /dev/null
@@ -0,0 +1,57 @@
+/*-------------------------------------------------------------------------
+
+  SDCCralloc.h - header file register allocation
+
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+#include "SDCCicode.h"
+#include "SDCCBBlock.h"
+#ifndef SDCCRALLOC_H
+#define SDCCRALLOC_H 1
+
+enum { R2_IDX = 0, R3_IDX , R4_IDX  ,
+       R5_IDX   ,R6_IDX   , R7_IDX  ,
+       R0_IDX   ,R1_IDX   , X8_IDX  ,
+       X9_IDX   ,X10_IDX  , X11_IDX ,
+       X12_IDX  ,CND_IDX };
+
+
+#define REG_PTR 0x01
+#define REG_GPR 0x02
+#define REG_CND 0x04
+/* definition for the registers */
+typedef struct regs
+{
+    short type;          /* can have value 
+                           REG_GPR, REG_PTR or REG_CND */
+    short rIdx ;         /* index into register table */
+    short otype;        
+    char *name ;         /* name */
+    char *dname;         /* name when direct access needed */
+    char *base ;         /* base address */
+    short offset;        /* offset from the base */
+    unsigned isFree :1;  /* is currently unassigned  */    
+} regs;
+extern regs regs390[];
+
+regs  *ds390_regWithIdx (int);
+
+#endif