* src/SDCCicode.c (getPtrType): avoid unnecessary extra assignments
[fw/sdcc] / src / avr / gen.c
index a182bc99d1116d70c054b039614990ad105c52f8..15955ceedbc5abaa6fc266cb01b79630c149acdb 100644 (file)
@@ -1,31 +1,27 @@
 /*-------------------------------------------------------------------------
-  SDCCgen51.c - source file for code generation for 8051
-  
-  Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
-         and -  Jean-Louis VERN.jlvern@writeme.com (1999)
-  Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
-  
+  gen.c - source file for code generation for ATMEL AVR
+
+  Written By -  Sandeep Dutta . sandeep.dutta@usa.net (2000)
+
   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 <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 "newalloc.h"
 
 #include "common.h"
 #include "SDCCpeeph.h"
 #include "ralloc.h"
 #include "gen.h"
 
-char *aopLiteral (value *val, int offset);
+char *aopLiteral (value * val, int offset);
+extern int allocInfo;
 
-/* this is the down and dirty file with all kinds of 
+/* 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 ;
-
-char *fReturn8051[] = {"dpl","dph","b","a" };
-char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
-unsigned fReturnSize = 4; /* shared with ralloc.c */
-char **fReturn = fReturn8051;
-static char *accUse[] = {"a","b"};
+static char *zero = "0x00";
+static char *one = "0x01";
+static char *spname;
 
-static short rbank = -1;
+char *fReturnAVR[] = { "r16", "r17", "r18", "r19" };
+unsigned fAVRReturnSize = 4;    /* shared with ralloc.c */
+char **fAVRReturn = fReturnAVR;
+static char *larray[4] = { ">", "<", "hlo8", "hhi8" };
 
 static struct {
-    short r0Pushed;
-    short r1Pushed;
-    short accInUse;
-    short inLine;
-    short debugLine;
-    short nRegsSaved;
-    set *sendSet;
+        short xPushed;
+        short zPushed;
+        short accInUse;
+        short inLine;
+        short debugLine;
+        short nRegsSaved;
+        set *sendSet;
 } _G;
 
-extern int mcs51_ptrRegReq ;
-extern int mcs51_nRegs;
-extern FILE *codeOutFile;
-static void saverbank (int, iCode *,bool);
+extern int avr_ptrRegReq;
+extern int avr_nRegs;
+extern struct dbuf_s *codeOutBuf;
 #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 CLRC    emitcode("clr","c");
+#define MOVR0(x) if (strcmp(x,"r0")) emitcode("mov","r0,%s",x);
+#define MOVR24(x) if (strcmp(x,"r24")) emitcode("mov","r24,%s",x);
+#define AOP_ISHIGHREG(a,n) (a->type == AOP_REG && a->aopu.aop_reg[n] && a->aopu.aop_reg[n]->rIdx >= R16_IDX)
+#define CLRC    emitcode("clc","")
+#define SETC    emitcode("stc","")
+#define MOVA(x)
+#define IS_REGIDX(a,r) (a->type == AOP_REG && a->aopu.aop_reg[0]->rIdx == r)
 
 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
 
+#if 0
+// PENDING: Unused.
 /*-----------------------------------------------------------------*/
-/* emitcode - writes the code into a file : for now it is simple    */
+/* reAdjustPreg - points a register back to where it should        */
 /*-----------------------------------------------------------------*/
-static void emitcode (char *inst,char *fmt, ...)
+static void
+reAdjustPreg (asmop * aop)
 {
-    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);
+        int size;
+
+        aop->coff = 0;
+        if ((size = aop->size) <= 1)
+                return;
+        size--;
+        switch (aop->type) {
+        case AOP_X:
+        case AOP_Z:
+                emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name, size);
+                break;
+        }
+
 }
 
 /*-----------------------------------------------------------------*/
-/* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
+/* outBitC - output a bit C                                        */
 /*-----------------------------------------------------------------*/
-static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
+static void
+outBitC (operand * 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 = mcs51_regWithIdx(R0_IDX);
-    }
+        emitcode ("clr", "r0");
+        emitcode ("rol", "r0");
+        outAcc (result);
+}
 
-    /* if no usage of r1 then return it */
-    if (!r1iu && !r1ou) {
-        ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
-        (*aopp)->type = AOP_R1;
+/*-----------------------------------------------------------------*/
+/* inExcludeList - return 1 if the string is in exclude Reg list   */
+/*-----------------------------------------------------------------*/
+static bool
+inExcludeList (char *s)
+{
+        int i = 0;
 
-        return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R1_IDX);
-    }    
+        if (options.excludeRegs[i] &&
+            STRCASECMP (options.excludeRegs[i], "none") == 0)
+                return FALSE;
 
-    /* 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",
-                      mcs51_regWithIdx(R0_IDX)->dname);
-            _G.r0Pushed++ ;
+        for (i = 0; options.excludeRegs[i]; i++) {
+                if (options.excludeRegs[i] &&
+                    STRCASECMP (s, options.excludeRegs[i]) == 0)
+                        return TRUE;
         }
-        
-        ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
-        (*aopp)->type = AOP_R0;
+        return FALSE;
+}
 
-        return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx(R0_IDX);
-    }
+/*-----------------------------------------------------------------*/
+/* 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;
 
-    /* if r1 not used then */
+        while (ic->prev) {
+                ic = ic->prev;
+                count++;
 
-    if (!r1iu) {
-        /* push it if not already pushed */
-        if (!_G.r1Pushed) {
-            emitcode ("push","%s",
-                      mcs51_regWithIdx(R1_IDX)->dname);
-            _G.r1Pushed++ ;
+                if (ic->op == LABEL && IC_LABEL (ic)->key == key) {
+                        /* printf("findLabelBackwards = %d\n", count); */
+                        return count;
+                }
         }
-        
-        ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
-        (*aopp)->type = AOP_R1;
-        return mcs51_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);
+        return 0;
 }
 
 /*-----------------------------------------------------------------*/
-/* newAsmop - creates a new asmOp                                  */
+/* addSign - complete with sign                                    */
 /*-----------------------------------------------------------------*/
-static asmop *newAsmop (short type)
+static void
+addSign (operand * result, int offset, int sign)
 {
-    asmop *aop;
+        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++);
+        }
+}
 
-    ALLOC(aop,sizeof(asmop));
-    aop->type = type;
-    return aop;
+/*-----------------------------------------------------------------*/
+/* 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;
 }
 
 /*-----------------------------------------------------------------*/
-/* pointerCode - returns the code for a pointer type               */
+/* outAcc - output Acc                                             */
 /*-----------------------------------------------------------------*/
-static int pointerCode (link *etype)
-{
-    int p_type;
-
-    return 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 ; */
-/*     return p_type; */
+static void
+outAcc (operand * result)
+{
+        int size, offset;
+        size = getDataSize (result);
+        if (size) {
+                aopPut (AOP (result), "r0", 0);
+                size--;
+                offset = 1;
+                /* unsigned or positive */
+                while (size--) {
+                        aopPut (AOP (result), zero, offset++);
+                }
+        }
 }
 
+#endif  // End Unused code section
+
 /*-----------------------------------------------------------------*/
-/* aopForSym - for a true symbol                                   */
+/* emitcode - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
-static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
+static void
+emitcode (char *inst, char *fmt, ...)
 {
-    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 || 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 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;
-    }
+        va_list ap;
+        char lb[INITIAL_INLINEASM];
+        char *lbp = lb;
 
-    /* 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;
-    }
+        va_start (ap, fmt);
 
-    /* only remaining is far space */
-    /* in which case DPTR gets the address */
-    sym->aop = aop = newAsmop(AOP_DPTR);
-    emitcode ("mov","dptr,#%s", sym->rname);
-    aop->size = getSize(sym->type);
+        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);
 
-    /* if it is in code space */
-    if (IN_CODESPACE(space))
-        aop->code = 1;
+        while (isspace ((unsigned char)*lbp))
+                lbp++;
 
-    return aop;     
+        if (lbp && *lbp)
+                lineCurr = (lineCurr ?
+                            connectLine (lineCurr, newLineNode (lb)) :
+                            (lineHead = newLineNode (lb)));
+        lineCurr->isInline = _G.inLine;
+        lineCurr->isDebug = _G.debugLine;
+        va_end (ap);
 }
 
 /*-----------------------------------------------------------------*/
-/* aopForRemat - rematerialzes an object                           */
+/* avr_emitDebuggerSymbol - associate the current code location  */
+/*   with a debugger symbol                                        */
 /*-----------------------------------------------------------------*/
-static asmop *aopForRemat (symbol *sym)
+void
+avr_emitDebuggerSymbol (char * debugSym)
 {
-    char *s = buffer;   
-    iCode *ic = sym->rematiCode;
-    asmop *aop = newAsmop(AOP_IMMD);
+  _G.debugLine = 1;
+  emitcode ("", "%s ==.", debugSym);
+  _G.debugLine = 0;
+}
 
-    while (1) {
+/*-----------------------------------------------------------------*/
+/* hasInc - operand is incremented before any other use            */
+/*-----------------------------------------------------------------*/
+static iCode *
+hasInc (operand *op, iCode *ic)
+{
+        sym_link *type = operandType(op);
+        sym_link *retype = getSpec (type);
+        iCode *lic = ic->next;
+        int isize ;
 
-        /* if plus or minus print the right hand side */
-        if (ic->op == '+' || ic->op == '-') {
-            sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
-                    ic->op );
-            s += strlen(s);
-            ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
-            continue ;
+        if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
+        if (IS_AGGREGATE(type->next)) return NULL;
+        isize = getSize(type->next);
+        while (lic) {
+                /* if operand of the form op = op + <sizeof *op> */
+                if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
+                    isOperandEqual(IC_RESULT(lic),op) &&
+                    isOperandLiteral(IC_RIGHT(lic)) &&
+                    operandLitValue(IC_RIGHT(lic)) == isize) {
+                        return lic;
+                }
+                /* if the operand used or deffed */
+                if (bitVectBitValue(OP_USES(op),lic->key) || (lic->defKey == op->key)) {
+                        return NULL;
+                }
+                lic = lic->next;
         }
-
-        /* we reached the end */
-        sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
-        break;
-    }
-
-    ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
-    strcpy(aop->aopu.aop_immd,buffer);    
-    return aop;        
+        return NULL;
 }
 
 /*-----------------------------------------------------------------*/
-/* regsInCommon - two operands have some registers in common       */
+/* getFreePtr - returns X or Z whichever is free or can be pushed  */
 /*-----------------------------------------------------------------*/
-static bool regsInCommon (operand *op1, operand *op2)
+static regs *
+getFreePtr (iCode * ic, asmop ** aopp, bool result, bool zonly)
 {
-    symbol *sym1, *sym2;
-    int i;
-
-    /* if they have registers in common */
-    if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
-        return FALSE ;
+        bool xiu = FALSE, ziu = FALSE;
+        bool xou = FALSE, zou = FALSE;
 
-    sym1 = OP_SYMBOL(op1);
-    sym2 = OP_SYMBOL(op2);
+        /* the logic: if x & z used in the instruction
+           then we are in trouble otherwise */
 
-    if (sym1->nRegs == 0 || sym2->nRegs == 0)
-        return FALSE ;
+        /* first check if x & z are used by this
+           instruction, in which case we are in trouble */
+        if ((xiu = bitVectBitValue (ic->rUsed, X_IDX)) &&
+            (ziu = bitVectBitValue (ic->rUsed, Z_IDX))) {
+                goto endOfWorld;
+        }
 
-    for (i = 0 ; i < sym1->nRegs ; i++) {
-        int j;
-        if (!sym1->regs[i])
-            continue ;
+        xou = bitVectBitValue (ic->rMask, X_IDX);
+        zou = bitVectBitValue (ic->rMask, Z_IDX);
 
-        for (j = 0 ; j < sym2->nRegs ;j++ ) {
-            if (!sym2->regs[j])
-                continue ;
+        /* if no usage of Z then return it */
+        if (!ziu && !zou) {
+                ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
+                (*aopp)->type = AOP_Z;
 
-            if (sym2->regs[j] == sym1->regs[i])
-                return TRUE ;
+                (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
+                return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
         }
-    }
 
-    return FALSE ;
-}
+        /* if no usage of X then return it */
+        if (!xiu && !xou && !zonly) {
+                ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
+                (*aopp)->type = AOP_X;
 
-/*-----------------------------------------------------------------*/
-/* operandsEqu - equivalent                                        */
-/*-----------------------------------------------------------------*/
-static bool operandsEqu ( operand *op1, operand *op2)
-{
-    symbol *sym1, *sym2;
+                (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
+                return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
+        }
 
-    /* if they not symbols */
-    if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
-        return FALSE;
+        /* if z not used then */
 
-    sym1 = OP_SYMBOL(op1);
-    sym2 = OP_SYMBOL(op2);
+        if (!ziu) {
+                /* push it if not already pushed */
+                if (!_G.zPushed) {
+                        emitcode ("push", "%s",
+                                  avr_regWithIdx (R30_IDX)->dname);
+                        emitcode ("push", "%s",
+                                  avr_regWithIdx (R31_IDX)->dname);
+                        _G.zPushed++;
+                }
 
-    /* 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 ;
+                ic->rUsed = bitVectSetBit (ic->rUsed, Z_IDX);
+                (*aopp)->type = AOP_Z;
+                (*aopp)->aop_ptr2 = avr_regWithIdx (R31_IDX);
+                return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R30_IDX);
+        }
 
-    /* if they are the same */
-    if (sym1 == sym2)
-        return TRUE ;
+        /* now we know they both have usage */
+        /* if x not used in this instruction */
+        if (!xiu && !zonly) {
+                /* push it if not already pushed */
+                if (!_G.xPushed) {
+                        emitcode ("push", "%s",
+                                  avr_regWithIdx (R26_IDX)->dname);
+                        emitcode ("push", "%s",
+                                  avr_regWithIdx (R27_IDX)->dname);
+                        _G.xPushed++;
+                }
 
-    if (strcmp(sym1->rname,sym2->rname) == 0)
-        return TRUE;
+                ic->rUsed = bitVectSetBit (ic->rUsed, X_IDX);
+                (*aopp)->type = AOP_X;
 
+                (*aopp)->aop_ptr2 = avr_regWithIdx (R27_IDX);
+                return (*aopp)->aopu.aop_ptr = avr_regWithIdx (R26_IDX);
+        }
 
-    /* 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 ;
+      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;
+        }
 
-    return FALSE ;
+        /* other wise this is true end of the world */
+        werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                "getFreePtr should never reach here");
+        exit (0);
 }
 
 /*-----------------------------------------------------------------*/
-/* sameRegs - two asmops have the same registers                   */
+/* newAsmop - creates a new asmOp                                  */
 /*-----------------------------------------------------------------*/
-static bool sameRegs (asmop *aop1, asmop *aop2 )
+static asmop *
+newAsmop (short type)
 {
-    int i;
-
-    if (aop1 == aop2)
-        return TRUE ;
-
-    if (aop1->type != AOP_REG ||
-        aop2->type != AOP_REG )
-        return FALSE ;
-
-    if (aop1->size != aop2->size )
-        return FALSE ;
-
-    for (i = 0 ; i < aop1->size ; i++ )
-        if (aop1->aopu.aop_reg[i] !=
-            aop2->aopu.aop_reg[i] )
-            return FALSE ;
+        asmop *aop;
 
-    return TRUE ;
+        aop = Safe_calloc (1, sizeof (asmop));
+        aop->type = type;
+        return aop;
 }
 
 /*-----------------------------------------------------------------*/
-/* aopOp - allocates an asmop for an operand  :                    */
+/* pointerCode - returns the code for a pointer type               */
 /*-----------------------------------------------------------------*/
-static void aopOp (operand *op, iCode *ic, bool result)
+static int
+pointerCode (sym_link * etype)
 {
-    asmop *aop;
-    symbol *sym;
-    int i;
-
-    if (!op)
-        return ;
-
-    /* if this a literal */
-    if (IS_OP_LITERAL(op)) {
-        op->aop = aop = newAsmop(AOP_LIT);
-        aop->aopu.aop_lit = op->operand.valOperand;
-        aop->size = getSize(operandType(op));
-        return;
-    }
-
-    /* if already has a asmop then continue */
-    if (op->aop)
-        return ;
-
-    /* if the underlying symbol has a aop */
-    if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
-        op->aop = OP_SYMBOL(op)->aop;
-        return;
-    }
-
-    /* if this is a true symbol */
-    if (IS_TRUE_SYMOP(op)) {    
-        op->aop = aopForSym(ic,OP_SYMBOL(op),result);
-        return ;
-    }
-
-    /* this is a temporary : this has
-    only four choices :
-    a) register
-    b) spillocation
-    c) rematerialize 
-    d) conditional   
-    e) can be a return use only */
-
-    sym = OP_SYMBOL(op);
-
-
-    /* if the type is a conditional */
-    if (sym->regType == REG_CND) {
-        aop = op->aop = sym->aop = newAsmop(AOP_CRY);
-        aop->size = 0;
-        return;
-    }
 
-    /* if it is spilt then two situations
-    a) is rematerialize 
-    b) has a spill location */
-    if (sym->isspilt || sym->nRegs == 0) {
-
-        /* rematerialize it NOW */
-        if (sym->remat) {
-            sym->aop = op->aop = aop =
-                                      aopForRemat (sym);
-            aop->size = getSize(sym->type);
-            return;
-        }
-
-       if (sym->accuse) {
-           int i;
-            aop = op->aop = sym->aop = newAsmop(AOP_ACC);
-            aop->size = getSize(sym->type);
-            for ( i = 0 ; i < 2 ; i++ )
-                aop->aopu.aop_str[i] = accUse[i];
-            return;  
-       }
-
-        if (sym->ruonly ) {
-            int i;
-            aop = op->aop = sym->aop = newAsmop(AOP_STR);
-            aop->size = getSize(sym->type);
-            for ( i = 0 ; i < fReturnSize ; i++ )
-                aop->aopu.aop_str[i] = fReturn[i];
-            return;
-        }
-
-        /* else spill location  */
-        sym->aop = op->aop = aop = 
-                                  aopForSym(ic,sym->usl.spillLoc,result);
-        aop->size = getSize(sym->type);
-        return;
-    }
+        return PTR_TYPE (SPEC_OCLS (etype));
 
-    /* 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 ;
+/* aopForSym - for a true symbol                                   */
+/*-----------------------------------------------------------------*/
+static asmop *
+aopForSym (iCode * ic, symbol * sym, bool result)
+{
+        asmop *aop;
+        memmap *space = SPEC_OCLS (sym->etype);
 
-    if (aop->freed)
-        goto dealloc; 
+        /* if already has one */
+        if (sym->aop)
+                return sym->aop;
 
-    aop->freed = 1;
+        /* assign depending on the storage class */
+        /* if it is on the stack */
+        if (sym->onStack) {
+                sym->aop = aop = newAsmop (0);
+                aop->size = getSize (sym->type);
 
-    /* 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--;
+                /* we can use std / ldd instruction */
+                if (sym->stack > 0
+                    && (sym->stack + getSize (sym->type) - 1) <= 63) {
+                        aop->type = AOP_STK_D;
+                        aop->aopu.aop_stk = sym->stack;
+                        return aop;
                 }
-            }
-            bitVectUnSetBit(ic->rUsed,R0_IDX);
-            break;
 
-        case AOP_R1 :
-            if (_G.r1Pushed ) {
-                if (pop) {
-                    emitcode ("pop","ar1");
-                    _G.r1Pushed--;
+                /* otherwise get a free pointer register X/Z */
+                aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, FALSE);
+
+                /* now assign the address of the variable to
+                   the pointer register */
+                if (aop->type != AOP_STK) {
+                        emitcode ("movw", "%s,r28", aop->aopu.aop_ptr->name);
+                        if (sym->stack < 0) {
+                                if ((sym->stack - _G.nRegsSaved) > -63) {
+                                        emitcode ("sbiw", "%s,0x%02x",
+                                                  aop->aopu.aop_ptr->name,
+                                                  (sym->stack -
+                                                   _G.nRegsSaved));
+                                }
+                                else {
+                                        emitcode ("subi", "%s,<(%d)",
+                                                  aop->aopu.aop_ptr->name,
+                                                  sym->stack - _G.nRegsSaved);
+                                        emitcode ("sbci", "%s,>(%d)",
+                                                  aop->aop_ptr2->name,
+                                                  sym->stack - _G.nRegsSaved);
+                                }
+                        }
+                        else {
+                                if (sym->stack <= 63) {
+                                        emitcode ("adiw", "%s,0x%02x",
+                                                  aop->aopu.aop_ptr->name,
+                                                  sym->stack);
+                                }
+                                else {
+                                        emitcode ("subi", "%s,<(-%d)",
+                                                  aop->aopu.aop_ptr->name,
+                                                  sym->stack);
+                                        emitcode ("sbci", "%s,>(-%d)",
+                                                  aop->aop_ptr2->name,
+                                                  sym->stack);
+                                }
+                        }
                 }
-            }
-            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 (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--;
-            }
+                return aop;
+        }
 
-            if (_G.r1Pushed) {
-                emitcode("pop","ar1");
-                _G.r1Pushed--;
-            }       
+        /* 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;
         }
-    }
 
-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;
+        /* special case for a function */
+        if (IS_FUNC (sym->type)) {
+                sym->aop = aop = newAsmop (AOP_IMMD);
+                aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
+                strcpy (aop->aopu.aop_immd, sym->rname);
+                aop->size = FPTRSIZE;
+                return aop;
         }
-    }
+
+        /* only remaining is code / eeprom which will need pointer reg */
+        /* if it is in code space */
+
+        sym->aop = aop = newAsmop (0);
+
+        if (IN_CODESPACE (space))
+                aop->code = 1;
+
+        aop->aopu.aop_ptr = getFreePtr (ic, &aop, result, aop->code);
+        aop->size = getSize (sym->type);
+        emitcode ("ldi", "%s,<(%s)", aop->aopu.aop_ptr->name, sym->rname);
+        emitcode ("ldi", "%s,>(%s)", aop->aop_ptr2);
+
+        return aop;
 }
 
 /*-----------------------------------------------------------------*/
-/* aopGet - for fetching value of the aop                          */
+/* aopForRemat - rematerialzes an object                           */
 /*-----------------------------------------------------------------*/
-static char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
+static asmop *
+aopForRemat (symbol * sym)
 {
-    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:
-       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");
-       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];
-       
-    }
+        iCode *ic = sym->rematiCode;
+        asmop *aop = newAsmop (AOP_IMMD);
+        int val = 0;
+
+        for (;;) {
+                if (ic->op == '+')
+                        val += (int) operandLitValue (IC_RIGHT (ic));
+                else if (ic->op == '-')
+                        val -= (int) 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);
 
-    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-           "aopget got unsupported aop->type");
-    exit(0);
+        aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
+        strcpy (aop->aopu.aop_immd, buffer);
+        return aop;
 }
+
 /*-----------------------------------------------------------------*/
-/* aopPut - puts a string for a aop                                */
+/* regsInCommon - two operands have some registers in common       */
 /*-----------------------------------------------------------------*/
-static void aopPut (asmop *aop, char *s, int offset)
+static bool
+regsInCommon (operand * op1, operand * op2)
 {
-    char *d = buffer ;
-    symbol *lbl ;
+        symbol *sym1, *sym2;
+        int i;
 
-    if (aop->size && offset > ( aop->size - 1)) {
-        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-               "aopPut got offset > aop->size");
-        exit(0);
-    }
+        /* if they have registers in common */
+        if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
+                return FALSE;
 
-    /* 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:
-       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");
-       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);    
-    }    
+        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;
 
-#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;
-    }
+                for (j = 0; j < sym2->nRegs; j++) {
+                        if (!sym2->regs[j])
+                                continue;
+
+                        if (sym2->regs[j] == sym1->regs[i])
+                                return TRUE;
+                }
+        }
 
+        return FALSE;
 }
-#endif
 
 /*-----------------------------------------------------------------*/
-/* reAdjustPreg - points a register back to where it should        */
+/* operandsEqu - equivalent                                        */
 /*-----------------------------------------------------------------*/
-static void reAdjustPreg (asmop *aop)
+static bool
+operandsEqu (operand * op1, operand * op2)
 {
-    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 : 
-            while (size--)
-                emitcode("lcall","__decdptr");
-            break;  
-
-    }   
+        symbol *sym1, *sym2;
 
-}
+        /* if they not symbols */
+        if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
+                return FALSE;
 
-#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))
+        sym1 = OP_SYMBOL (op1);
+        sym2 = OP_SYMBOL (op2);
 
-#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
-                        AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged)) 
+        /* 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;
 
-#define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
-                      (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
-                      x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
+        /* if they are the same */
+        if (sym1 == sym2)
+                return TRUE;
 
-/*-----------------------------------------------------------------*/
-/* genNotFloat - generates not for float operations              */
-/*-----------------------------------------------------------------*/
-static void genNotFloat (operand *op, operand *res)
-{
-    int size, offset;
-    char *l;
-    symbol *tlbl ;
-
-    /* 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++);
-}
+        if (strcmp (sym1->rname, sym2->rname) == 0)
+                return TRUE;
 
-/*-----------------------------------------------------------------*/
-/* 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;
-}
+        /* if left is a tmp & right is not */
+        if (IS_ITEMP (op1) &&
+            !IS_ITEMP (op2) && sym1->isspilt && (sym1->usl.spillLoc == sym2))
+                return TRUE;
 
-/*-----------------------------------------------------------------*/
-/* 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++);
-        }
-    }
-}
+        if (IS_ITEMP (op2) &&
+            !IS_ITEMP (op1) &&
+            sym2->isspilt && sym1->level > 0 && (sym2->usl.spillLoc == sym1))
+                return TRUE;
 
-/*-----------------------------------------------------------------*/
-/* 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);
-    }
+        return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
-/* toBoolean - emit code for orl a,operator(sizeop)                */
+/* sameRegs - two asmops have the same registers                   */
 /*-----------------------------------------------------------------*/
-static void toBoolean(operand *oper)
+static bool
+sameRegs (asmop * aop1, asmop * aop2)
 {
-    int size = AOP_SIZE(oper) - 1;
-    int offset = 1;
-    MOVA(aopGet(AOP(oper),0,FALSE,FALSE));
-    while (size--) 
-        emitcode("orl","a,%s",aopGet(AOP(oper),offset++,FALSE,FALSE));
-}
-
+        int i;
 
-/*-----------------------------------------------------------------*/
-/* genNot - generate code for ! operation                          */
-/*-----------------------------------------------------------------*/
-static void genNot (iCode *ic)
-{
-    symbol *tlbl;
-    link *optype = operandType(IC_LEFT(ic));
-
-    /* assign asmOps to operand & result */
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
-
-    /* if in bit space then a special case */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
-        emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
-        emitcode("cpl","c"); 
-        outBitC(IC_RESULT(ic));
-        goto release;
-    }
+        if (aop1 == aop2)
+                return TRUE;
 
-    /* if type float then do float */
-    if (IS_FLOAT(optype)) {
-        genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
-        goto release;
-    }
+        if (aop1->type != AOP_REG || aop2->type != AOP_REG)
+                return FALSE;
 
-    toBoolean(IC_LEFT(ic));
+        if (aop1->size != aop2->size)
+                return FALSE;
 
-    tlbl = newiTempLabel(NULL);
-    emitcode("cjne","a,#0x01,%05d$",tlbl->key+100);
-    emitcode("","%05d$:",tlbl->key+100);
-    outBitC(IC_RESULT(ic));
+        for (i = 0; i < aop1->size; i++)
+                if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
+                        return FALSE;
 
-release:    
-    /* release the aops */
-    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+        return TRUE;
 }
 
-
 /*-----------------------------------------------------------------*/
-/* genCpl - generate code for complement                           */
+/* isRegPair - for size 2 if this operand has a register pair      */
 /*-----------------------------------------------------------------*/
-static void genCpl (iCode *ic)
+static int
+isRegPair (asmop * aop)
 {
-    int offset = 0;
-    int size ;
-
-
-    /* assign asmOps to operand & result */
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
-
-    /* if both are in bit space then 
-    a special case */
-    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
-
-        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++);
-    }
+        if (!aop || aop->size < 2)
+                return 0;
+        if (aop->type == AOP_X || aop->type == AOP_Z)
+                return 1;
+        if (aop->type != AOP_REG)
+                return 0;
+        if ( ((aop->aopu.aop_reg[1]->rIdx - aop->aopu.aop_reg[0]->rIdx) == 1) &&
+             (aop->aopu.aop_reg[0]->rIdx & 1) == 0)
 
-
-release:
-    /* release the aops */
-    freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+                return 1;
+        return 0;
 }
 
 /*-----------------------------------------------------------------*/
-/* genUminusFloat - unary minus for floating points                */
+/* allHigh - all registers are high registers                      */
 /*-----------------------------------------------------------------*/
-static void genUminusFloat(operand *op,operand *result)
+static int allHigh (asmop * aop)
 {
-    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);
-
-    MOVA(l);    
-
-    emitcode("cpl","acc.7");
-    aopPut(AOP(result),"a",3);    
-
-    while(size--) {
-        aopPut(AOP(result),
-               aopGet(AOP(op),offset,FALSE,FALSE),
-               offset);
-        offset++;
-    }          
+        int i;
+
+        if (aop->type == AOP_X || aop->type == AOP_Z)
+                return 1;
+        if (aop->type != AOP_REG)
+                return 0;
+        for (i=0; i < aop->size ; i++ )
+                if (aop->aopu.aop_reg[i]->rIdx < R16_IDX) return 0;
+        return 1;
 }
 
 /*-----------------------------------------------------------------*/
-/* genUminus - unary minus code generation                         */
+/* aopOp - allocates an asmop for an operand  :                    */
 /*-----------------------------------------------------------------*/
-static void genUminus (iCode *ic)
+static void
+aopOp (operand * op, iCode * ic, bool result)
 {
-    int offset ,size ;
-    link *optype, *rtype;
+        asmop *aop;
+        symbol *sym;
+        int i;
 
+        if (!op)
+                return;
 
-    /* assign asmops */
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    aopOp(IC_RESULT(ic),ic,TRUE);
+        /* 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 both in bit space then special
-    case */
-    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
+        /* if already has a asmop then continue */
+        if (op->aop)
+                return;
 
-        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; 
-    } 
+        /* if the underlying symbol has a aop */
+        if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) {
+                op->aop = OP_SYMBOL (op)->aop;
+                return;
+        }
 
-    optype = operandType(IC_LEFT(ic));
-    rtype = operandType(IC_RESULT(ic));
+        /* if this is a true symbol */
+        if (IS_TRUE_SYMOP (op)) {
+                op->aop = aopForSym (ic, OP_SYMBOL (op), result);
+                return;
+        }
 
-    /* if float then do float stuff */
-    if (IS_FLOAT(optype)) {
-        genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
-        goto release;
-    }
+        /* this is a temporary : this has
+           only four choices :
+           a) register
+           b) spillocation
+           c) rematerialize
+           d) conditional
+           e) can be a return use only */
 
-    /* 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++);
-    }
+        sym = OP_SYMBOL (op);
 
-    /* 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 type is a conditional */
+        if (sym->regType & REG_CND) {
+                aop = op->aop = sym->aop = newAsmop (AOP_CRY);
+                aop->size = 0;
+                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 < mcs51_nRegs ; i++) {
-           if (bitVectBitValue(rsave,i)) {
-               if (i == R0_IDX)
-                   emitcode("mov","a,b");
-               else
-                   emitcode("mov","a,%s",mcs51_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 < mcs51_nRegs ; i++) {
-           if (bitVectBitValue(rsave,i))
-               emitcode("push","%s",mcs51_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);
+        /* if it is spilt then two situations
+           a) is rematerialize
+           b) has a spill location */
+        if (sym->isspilt || sym->nRegs == 0) {
 
-}
-/*-----------------------------------------------------------------*/
-/* 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 =  mcs51_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",mcs51_regWithIdx(i)->name);
-           }       
-
-       }
-       emitcode("mov","%s,r0",spname);
-       if (bitVectBitValue(rsave,R0_IDX))
-           emitcode("mov","r0,b");
-    } else
-       for (i =  mcs51_nRegs ; i >= 0 ; i--) {
-           if (bitVectBitValue(rsave,i))
-               emitcode("pop","%s",mcs51_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);
-       }
+                asmop *oldAsmOp = NULL;
+
+                /* rematerialize it NOW */
+                if (sym->remat) {
+                        sym->aop = op->aop = aop = aopForRemat (sym);
+                        aop->size = getSize (sym->type);
+                        return;
+                }
+
+                if (sym->accuse) {
+                        assert ("ACC_USE cannot happen in AVR\n");
+                }
+
+                if (sym->ruonly) {
+                        int i;
+                        aop = op->aop = sym->aop = newAsmop (AOP_STR);
+                        aop->size = getSize (sym->type);
+                        for (i = 0; i < (int) fAVRReturnSize; i++)
+                                aop->aopu.aop_str[i] = fAVRReturn[i];
+                        return;
+                }
+
+                /* else spill location  */
+                if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
+                    /* force a new aop if sizes differ */
+                    oldAsmOp = sym->usl.spillLoc->aop;
+                    sym->usl.spillLoc->aop = NULL;
+                }
+                sym->aop = op->aop = aop =
+                        aopForSym (ic, sym->usl.spillLoc, result);
+                if (getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
+                        /* Don't reuse the new aop, go with the last one */
+                        sym->usl.spillLoc->aop = oldAsmOp;
+                }
+                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];
 }
 
 /*-----------------------------------------------------------------*/
-/* assignResultValue -                                            */
-/*-----------------------------------------------------------------*/
-static void assignResultValue(operand * oper)
+/* freeAsmop - free up the asmop given to an operand               */
+/*----------------------------------------------------------------*/
+static void
+freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
 {
-       int offset = 0;
-       int size = AOP_SIZE(oper);
-       while (size--) {
-               aopPut(AOP(oper),fReturn[offset],offset);
-               offset++;
-       }
-}
+        asmop *aop;
+
+        if (!op)
+                aop = aaop;
+        else
+                aop = op->aop;
 
+        if (!aop)
+                return;
 
-/*-----------------------------------------------------------------*/
-/* genXpush - pushes onto the external stack                       */
-/*-----------------------------------------------------------------*/
-static void genXpush (iCode *ic)
-{
-    asmop *aop = newAsmop(0);
-    regs *r ;
-    int size,offset = 0;
+        if (aop->freed)
+                goto dealloc;
 
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    r = getFreePtr(ic,&aop,FALSE);
+        aop->freed = 1;
 
-    
-    emitcode("mov","%s,_spx",r->name);
+        /* depending on the asmop type only three cases need work AOP_RO
+           , AOP_R1 && AOP_STK */
+        switch (aop->type) {
+        case AOP_X:
+                if (_G.xPushed) {
+                        if (pop) {
+                                emitcode ("pop", "r26");
+                                emitcode ("pop", "r27");
+                                _G.xPushed--;
+                        }
+                }
+                bitVectUnSetBit (ic->rUsed, X_IDX);
+                break;
 
-    size = AOP_SIZE(IC_LEFT(ic));
-    while(size--) {
+        case AOP_Z:
+                if (_G.zPushed) {
+                        if (pop) {
+                                emitcode ("pop", "r30");
+                                emitcode ("pop", "r31");
+                                _G.zPushed--;
+                        }
+                }
+                bitVectUnSetBit (ic->rUsed, Z_IDX);
+                break;
 
-       char *l = aopGet(AOP(IC_LEFT(ic)),
-                        offset++,FALSE,FALSE); 
-       MOVA(l);            
-       emitcode("movx","@%s,a",r->name);       
-       emitcode("inc","%s",r->name);
+        case AOP_STK:
+                {
+                        int sz = aop->size;
+                        int stk = aop->aopu.aop_stk + aop->size;
+                        bitVectUnSetBit (ic->rUsed, X_IDX);
+                        bitVectUnSetBit (ic->rUsed, Z_IDX);
+
+                        getFreePtr (ic, &aop, FALSE, 0);
+
+                        emitcode ("movw", "%s,r28");
+                        if (stk) {
+                                if (stk <= 63 && stk > 0) {
+                                        emitcode ("adiw", "%s,0x%02x",
+                                                  aop->aopu.aop_ptr->name,
+                                                  stk + 1);
+                                }
+                                else {
+                                        emitcode ("subi", "%s,<(%d)",
+                                                  aop->aopu.aop_ptr->name,
+                                                  -(stk + 1));
+                                        emitcode ("sbci", "%s,>(%d)",
+                                                  aop->aop_ptr2->name,
+                                                  -(stk + 1));
+                                }
+                        }
 
-    }
+                        while (sz--) {
+                                emitcode ("pop", "r24");
+                                emitcode ("st", "-%s,r24",
+                                          aop->type == AOP_X ? "X" : "Z");
+                                if (!sz)
+                                        break;
+                        }
+                        op->aop = aop;
+                        freeAsmop (op, NULL, ic, TRUE);
+                        if (_G.xPushed) {
+                                emitcode ("pop", "r26");
+                                emitcode ("pop", "r27");
+                                _G.xPushed--;
+                        }
 
-       
-    emitcode("mov","_spx,%s",r->name);
+                        if (_G.zPushed) {
+                                emitcode ("pop", "r30");
+                                emitcode ("pop", "r31");
+                                _G.zPushed--;
+                        }
+                }
+        }
 
-    freeAsmop(NULL,aop,ic,TRUE);
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+      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;
+                }
+        }
 }
 
 /*-----------------------------------------------------------------*/
-/* genIpush - genrate code for pushing this gets a little complex  */
+/* aopGet - for fetching value of the aop                          */
 /*-----------------------------------------------------------------*/
-static void genIpush (iCode *ic)
+static char *
+aopGet (asmop * aop, int offset)
 {
-    int size, offset = 0 ;
-    char *l;
-
-
-    /* if this is not a parm push : ie. it is spill push 
-    and spill push is always done on the local stack */
-    if (!ic->parmPush) {
-
-        /* and the item is spilt then do nothing */
-        if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
-            return ;
-
-        aopOp(IC_LEFT(ic),ic,FALSE);
-        size = AOP_SIZE(IC_LEFT(ic));
-        /* push it on the stack */
-        while(size--) {
-            l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
-            if (*l == '#') {
-                MOVA(l);
-                l = "acc";
-            }
-            emitcode("push","%s",l);
-        }
-        return ;        
-    }
+        char *s = buffer;
+        char *rs;
 
-    /* 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);
+        /* offset is greater than
+           size then zero */
+        if (offset > (aop->size - 1) && aop->type != AOP_LIT)
+                return zero;
 
-    /* if use external stack then call the external
-    stack pushing routine */
-    if (options.useXstack) {
-        genXpush(ic);
-        return ;
-    }
+        /* depending on type */
+        switch (aop->type) {
+
+        case AOP_X:
+                if (offset > aop->coff) {
+                        emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
+                                  offset - aop->coff);
+                }
 
-    /* then do the push */
-    aopOp(IC_LEFT(ic),ic,FALSE);
+                if (offset < aop->coff) {
+                        emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
+                                  aop->coff - offset);
+                }
 
+                aop->coff = offset;
+                emitcode ("ld", "%s,x",
+                          (rs = ((offset & 1) ? "r25" : "r24")));
+                return rs;
 
-       // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
-    size = AOP_SIZE(IC_LEFT(ic));
+        case AOP_Z:
+                if (aop->code) {
+                        if (offset > aop->coff) {
+                                emitcode ("adiw", "r30,%d",
+                                          offset - aop->coff);
+                        }
+                        else {
+                                emitcode ("sbiw", "r30,%d",
+                                          aop->coff - offset);
+                        }
+                        emitcode ("lpm", "%s,z",
+                                  (rs = ((offset & 1) ? "r25" : "r24")));
+                }
+                else {
+                        /* we can use lds */
+                        if (offset > aop->coff) {
+                                emitcode ("ldd", "%s,z+%d",
+                                          (rs =
+                                           ((offset & 1) ? "r25" : "r24")),
+                                          offset - aop->coff);
+                        }
+                        else {
+                                emitcode ("sbiw", "%s,%d",
+                                          aop->aopu.aop_ptr->name,
+                                          aop->coff - offset);
+                                aop->coff = offset;
+                                emitcode ("ld", "%s,z",
+                                          (rs =
+                                           ((offset & 1) ? "r25" : "r24")));
+                        }
+                }
+                return rs;
 
-    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);
-    }       
+        case AOP_IMMD:
 
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
-}
+                emitcode ("lds", "%s,(%s)+%d",
+                          (rs = ((offset & 1) ? "r25" : "r24")),
+                          aop->aopu.aop_immd, offset);
+                return rs;
 
-/*-----------------------------------------------------------------*/
-/* genIpop - recover the registers: can happen only for spilling   */
-/*-----------------------------------------------------------------*/
-static void genIpop (iCode *ic)
-{
-    int size,offset ;
+        case AOP_DIR:
+                emitcode ("lds", "%s,(%s)+%d",
+                          (rs = ((offset & 1) ? "r25" : "r24")),
+                          aop->aopu.aop_dir, offset);
+                return rs;
 
+        case AOP_REG:
+                return aop->aopu.aop_reg[offset]->name;
 
-    /* if the temp was not pushed then */
-    if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
-        return ;
+        case AOP_CRY:
+                assert ("cannot be in bit space AOP_CRY\n");
+                break;
 
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    size = AOP_SIZE(IC_LEFT(ic));
-    offset = (size-1);
-    while (size--) 
-        emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
-                                   FALSE,TRUE));
+        case AOP_LIT:
+                s = aopLiteral (aop->aopu.aop_lit, offset);
+                emitcode ("ldi", "%s,<(%s)",
+                          (rs = ((offset & 1) ? "r24" : "r25")), s);
+                return rs;
+
+        case AOP_STR:
+                aop->coff = offset;
+                return aop->aopu.aop_str[offset];
+
+        case AOP_STK_D:
+                emitcode ("ldd", "%s,Y+%d",
+                          (rs = ((offset & 1) ? "r25" : "r24")),
+                          aop->aopu.aop_stk + offset);
+                return rs;
+        }
 
-    freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
+        werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                "aopget got unsupported aop->type");
+        exit (0);
 }
 
 /*-----------------------------------------------------------------*/
-/* unsaverbank - restores the resgister bank from stack            */
+/* aopPut - puts a string for a aop                                */
 /*-----------------------------------------------------------------*/
-static void unsaverbank (int bank,iCode *ic,bool popPsw)
+static void
+aopPut (asmop * aop, char *s, int offset)
 {
-    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 = (mcs51_nRegs - 1) ; i >= 0 ;i--) {
-        if (options.useXstack) {       
-            emitcode("movx","a,@%s",r->name);
-            emitcode("mov","(%s+%d),a",
-                     regs8051[i].base,8*bank+regs8051[i].offset);
-            emitcode("dec","%s",r->name);
-
-        } else 
-            emitcode("pop","(%s+%d)",
-                     regs8051[i].base,8*bank+regs8051[i].offset);
-    }
-
-    if (options.useXstack) {
-
-       emitcode("mov","_spx,%s",r->name);
-       freeAsmop(NULL,aop,ic,TRUE);
+        char *d = buffer;
 
-    } 
-}
+        if (aop->size && offset > (aop->size - 1)) {
+                werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                        "aopPut got offset > aop->size");
+                exit (0);
+        }
 
-/*-----------------------------------------------------------------*/
-/* 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;
+        /* 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 (options.useXstack) {
+                emitcode ("sts", "%s,%s", d, s);
+                break;
 
-       aop = newAsmop(0);
-       r = getFreePtr(ic,&aop,FALSE);  
-       emitcode("mov","%s,_spx",r->name);
+        case AOP_REG:
+                if (toupper ((unsigned char)*s) != 'R') {
+                        if (s == zero) {
+                                emitcode ("clr", "%s",
+                                          aop->aopu.aop_reg[offset]->name);
+                        }
+                        else {
+                                emitcode ("ldi", "r25,%s", s);
+                                emitcode ("mov", "%s,r35",
+                                          aop->aopu.aop_reg[offset]->name);
+                        }
+                }
+                else {
+                        if (strcmp (aop->aopu.aop_reg[offset]->name, s)) {
+                                emitcode ("mov", "%s,%s",
+                                          aop->aopu.aop_reg[offset]->name, s);
+                        }
+                }
+                break;
 
-    }
+        case AOP_X:
+                if (offset > aop->coff) {
+                        emitcode ("adiw", "%s,%d", aop->aopu.aop_ptr->name,
+                                  offset - aop->coff);
+                }
 
-    for (i = 0 ; i < mcs51_nRegs ;i++) {
-        if (options.useXstack) {
-            emitcode("inc","%s",r->name);
-            emitcode("mov","a,(%s+%d)",
-                     regs8051[i].base,8*bank+regs8051[i].offset);
-            emitcode("movx","@%s,a",r->name);           
-        } else 
-            emitcode("push","(%s+%d)",
-                     regs8051[i].base,8*bank+regs8051[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;
+                if (offset < aop->coff) {
+                        emitcode ("sbiw", "%s,%d", aop->aopu.aop_ptr->name,
+                                  aop->coff - offset);
+                }
 
-}
+                aop->coff = offset;
+                emitcode ("st", "x,%s", s);
+                break;
 
-/*-----------------------------------------------------------------*/
-/* genCall - generates a call statement                            */
-/*-----------------------------------------------------------------*/
-static void genCall (iCode *ic)
-{
-    link *detype;   
-
-    /* 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);
-           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)) ) {
-
-        _G.accInUse++;
-        aopOp(IC_RESULT(ic),ic,FALSE);
-        _G.accInUse--;
-
-       assignResultValue(IC_RESULT(ic));
-               
-        freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
-    }
+        case AOP_Z:
+                if (aop->code) {
+                        if (offset > aop->coff) {
+                                emitcode ("adiw", "r30,%d",
+                                          offset - aop->coff);
+                        }
+                        else {
+                                emitcode ("sbiw", "r30,%d",
+                                          aop->coff - offset);
+                        }
+                        emitcode ("lpm", "%s,z", s);
+                }
+                else {
+                        /* we can use lds */
+                        if (offset > aop->coff) {
+                                emitcode ("sdd", "z+%d,%s",
+                                          offset - aop->coff, s);
+                        }
+                        else {
+                                emitcode ("sbiw", "%s,%d",
+                                          aop->aopu.aop_ptr->name,
+                                          aop->coff - offset);
+                                aop->coff = offset;
+                                emitcode ("ld", "%s,z", s);
+                        }
+                }
+                break;
 
-    /* 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);
+        case AOP_STK:
+                emitcode ("push", "%s", s);
+                break;
 
-    }
+        case AOP_CRY:
+                /* if used only for a condition code check */
+                assert (toupper ((unsigned char)*s) == 'R');
+                if (offset == 0) {
+                        emitcode ("xrl", "r0,r0");
+                        emitcode ("cpi", "%s,0", s);
+                }
+                else {
+                        emitcode ("cpc", "r0,%s", s);
+                }
+                break;
 
-    /* if register bank was saved then pop them */
-    if (ic->bankSaved)
-        unsaverbank(SPEC_BANK(detype),ic,TRUE);
+        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;
 
-    /* if we hade saved some registers then unsave them */
-    if (ic->regsSaved && !(OP_SYMBOL(IC_LEFT(ic))->calleeSave))
-        unsaveRegisters (ic);
+        case AOP_STK_D:
+                emitcode ("std", "y+%d,%s", offset, s);
+                break;
 
+        default:
+                werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                        "aopPut got unsupported aop->type");
+                exit (0);
+        }
 
 }
 
+#define AOP(op) op->aop
+#define AOP_TYPE(op) AOP(op)->type
+#define AOP_SIZE(op) AOP(op)->size
+#define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_X || \
+                       AOP_TYPE(x) == AOP_Z))
+#define AOP_INPREG(x) (x && (x->type == AOP_REG &&                      \
+                      ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)) || \
+                       (x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)) )))
+#define AOP_ISX(x) (x && (x->type == AOP_REG &&                      \
+                      ((x->aopu.aop_reg[0] == avr_regWithIdx(R26_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R27_IDX)))))
+#define AOP_ISZ(x) (x && (x->type == AOP_REG &&                      \
+                      ((x->aopu.aop_reg[0] == avr_regWithIdx(R30_IDX) && x->aopu.aop_reg[1] == avr_regWithIdx(R31_IDX)))))
+
 /*-----------------------------------------------------------------*/
-/* genPcall - generates a call by pointer statement                */
+/* genNotFloat - generates not for float operations                */
 /*-----------------------------------------------------------------*/
-static void genPcall (iCode *ic)
+static void
+genNotFloat (operand * op, operand * res)
 {
-    link *detype;
-    symbol *rlbl = newiTempLabel(NULL);
-
-
-    /* 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);
-
-    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);
-           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);
-        _G.accInUse--;
-       
-       assignResultValue(IC_RESULT(ic));
-
-        freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
-    }
+        int size, offset;
+        char *l;
+        symbol *tlbl;
 
-    /* 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);
+        /* 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++);
+        MOVR0 (l);
 
-    /* if register bank was saved then unsave them */
-    if (detype        && 
-        (SPEC_BANK(currFunc->etype) != 
-         SPEC_BANK(detype)))
-        unsaverbank(SPEC_BANK(detype),ic,TRUE);
+        while (size--) {
+                emitcode ("or", "R0,%s", aopGet (op->aop, offset++));
+        }
+        tlbl = newiTempLabel (NULL);
 
-    /* if we hade saved some registers then
-    unsave them */
-    if (ic->regsSaved)
-        unsaveRegisters (ic);
+        tlbl = newiTempLabel (NULL);
+        aopPut (res->aop, zero, 1);
+        emitcode ("cpi", "r0,0");
+        emitcode ("breq", "L%05d", tlbl->key);
+        aopPut (res->aop, one, 1);
+        emitcode ("", "L%05d:", tlbl->key);
 
+        size = res->aop->size - 2;
+        offset = 2;
+        /* put zeros in the rest */
+        while (size--)
+                aopPut (res->aop, zero, offset++);
 }
 
 /*-----------------------------------------------------------------*/
-/* resultRemat - result  is rematerializable                       */
+/* opIsGptr: returns non-zero if the passed operand is       */
+/* a generic pointer type.             */
 /*-----------------------------------------------------------------*/
-static int resultRemat (iCode *ic)
+static int
+opIsGptr (operand * op)
 {
-    if (SKIP_IC(ic) || ic->op == IFX)
-        return 0;
+        sym_link *type = operandType (op);
 
-    if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
-        symbol *sym = OP_SYMBOL(IC_RESULT(ic));
-        if (sym->remat && !POINTER_SET(ic)) 
-            return 1;
-    }
-
-    return 0;
+        if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) {
+                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   */
+/* getDataSize - get the operand data size                         */
 /*-----------------------------------------------------------------*/
-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 ;
+static int
+getDataSize (operand * op)
+{
+        int size;
+        size = AOP_SIZE (op);
+        if (size == GPTRSIZE) {
+                sym_link *type = operandType (op);
+                if (IS_GENPTR (type)) {
+                        /* generic pointer; arithmetic operations
+                         * should ignore the high byte (pointer type).
+                         */
+                        size--;
+                }
+        }
+        return size;
 }
 
 /*-----------------------------------------------------------------*/
-/* genFunction - generated code for function entry                 */
+/* toBoolean - emit code for orl a,operator(sizeop)                */
 /*-----------------------------------------------------------------*/
-static void genFunction (iCode *ic)
+static void
+toBoolean (operand * oper, char *r, bool clr)
 {
-    symbol *sym;
-    link *fetype;
-
-    _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 < mcs51_nRegs ; i++ ) {
-            if (strcmp(regs8051[i].base,"0") == 0)
-                emitcode("","%s = 0x%02x",
-                         regs8051[i].dname,
-                         8*rbank+regs8051[i].offset);
-            else
-                emitcode ("","%s = %s + 0x%02x",
-                          regs8051[i].dname,
-                          regs8051[i].base,
-                          8*rbank+regs8051[i].offset);
+        int size = AOP_SIZE (oper);
+        int offset = 0;
+        if (clr) {
+                emitcode ("clr", "%s", r);
+                while (size--)
+                        emitcode ("or", "%s,%s", r, aopGet (AOP (oper), offset++));
+        } else {
+                size--;
+                emitcode("mov","%s,%s",r,aopGet (AOP (oper), offset++));
+                if (size) while (size--) emitcode ("or", "%s,%s", r, aopGet (AOP (oper), 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");   
-       /* 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) ||
-                          (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                           emitcode("push","%s",mcs51_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) ||
-                      (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
-                       emitcode("push","%s",mcs51_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);   
-    }
+/*-----------------------------------------------------------------*/
+/* genNot - generate code for ! operation                          */
+/*-----------------------------------------------------------------*/
+static void
+genNot (iCode * ic)
+{
+        symbol *tlbl;
+        sym_link *optype = operandType (IC_LEFT (ic));
+        int size, offset = 1;
 
-    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);
-    }
+        /* assign asmOps to operand & result */
+        aopOp (IC_LEFT (ic), ic, FALSE);
+        aopOp (IC_RESULT (ic), ic, TRUE);
 
-    /* adjust the stack for the function */
-    if (sym->stack) {
+        /* if type float then do float */
+        if (IS_FLOAT (optype)) {
+                genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
+                goto release;
+        }
+        emitcode ("clr", "r24");
+        tlbl = newiTempLabel (NULL);
+        size = AOP_SIZE (IC_LEFT (ic));
+        offset = 0;
+        if (size == 1) {
+                emitcode ("cpse", "%s,r24", aopGet (AOP (IC_LEFT (ic)), 0));
+        }
+        else {
+                while (size--) {
+                        if (offset)
+                                emitcode ("cpc", "%s,r24",
+                                          aopGet (AOP (IC_LEFT (ic)),
+                                                  offset));
+                        else
+                                emitcode ("cpi", "%s,0",
+                                          aopGet (AOP (IC_LEFT (ic)),
+                                                  offset));
+                        offset++;
+                }
+                emitcode ("bne", "L%05d", tlbl->key);
+        }
+        emitcode ("ldi", "r24,1");
+        emitcode ("", "L%05d:", tlbl->key);
+        aopPut (AOP (IC_RESULT (ic)), "r24", 0);
+        size = AOP_SIZE (IC_RESULT (ic)) - 1;
+        offset = 1;
+        while (size--)
+                aopPut (AOP (IC_RESULT (ic)), zero, offset++);
 
-       int i = sym->stack;
-       if (i > 256 ) 
-           werror(W_STACK_OVERFLOW,sym->name);
 
-       if (i > 3 && sym->recvSize < 4) {              
+      release:
+        /* release the aops */
+        freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
+        freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+}
 
-           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) {
+/*-----------------------------------------------------------------*/
+/* genCpl - generate code for complement                           */
+/*-----------------------------------------------------------------*/
+static void
+genCpl (iCode * ic)
+{
+        int offset = 0;
+        int size;
+        int samer;
 
-       emitcode ("mov","a,_spx");
-       emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
-       emitcode ("mov","_spx,a");
-    }    
+        /* assign asmOps to operand & result */
+        aopOp (IC_LEFT (ic), ic, FALSE);
+        aopOp (IC_RESULT (ic), ic, TRUE);
+        samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
+        size = AOP_SIZE (IC_RESULT (ic));
+        while (size--) {
+                char *l = aopGet (AOP (IC_LEFT (ic)), offset);
+                if (samer) {
+                        emitcode ("com", "%s", l);
+                }
+                else {
+                        aopPut (AOP (IC_RESULT (ic)), l, offset);
+                        emitcode ("com", "%s",
+                                  aopGet (AOP (IC_RESULT (ic)), offset));
+                }
+                offset++;
+        }
 
+        /* release the aops */
+        freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
+        freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genEndFunction - generates epilogue for functions               */
+/* genUminusFloat - unary minus for floating points                */
 /*-----------------------------------------------------------------*/
-static void genEndFunction (iCode *ic)
+static void
+genUminusFloat (operand * op, operand * result)
 {
-    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
-
-    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) ||
-                          (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                           emitcode("pop","%s",mcs51_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"))
-           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) ||
-                      (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                       emitcode("pop","%s",mcs51_regWithIdx(i)->dname);
-               }
-           }
-           
-       }
-
-       /* 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 ("ret","");
-    }
+        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);
 
+        emitcode ("ldi", "r24,0x80");
+        if (sameRegs (AOP (op), AOP (result))) {
+                emitcode ("eor", "%s,r24", l);
+        }
+        else {
+                aopPut (AOP (result), l, 3);
+                emitcode ("eor", "%s,r24", aopGet (AOP (result), 3));
+        }
+        while (size--) {
+                aopPut (AOP (result), aopGet (AOP (op), offset), offset);
+                offset++;
+        }
 }
 
 /*-----------------------------------------------------------------*/
-/* genRet - generate code for return statement                     */
+/* genUminus - unary minus code generation                         */
 /*-----------------------------------------------------------------*/
-static void genRet (iCode *ic)
+static void
+genUminus (iCode * ic)
 {
-    int size,offset = 0 , pushed = 0;
-    
-    /* if we have no return value then
-       just generate the "ret" */
-    if (!IC_LEFT(ic)) 
-       goto jumpret;       
-    
-    /* we have something to return then
-       move the return value into place */
-    aopOp(IC_LEFT(ic),ic,FALSE);
-    size = AOP_SIZE(IC_LEFT(ic));
-    
-    while (size--) {
-           char *l ;
-           if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
-                   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));
-    
+        int offset, size;
+        sym_link *optype, *rtype;
+        int samer;
+
+        /* assign asmops */
+        aopOp (IC_LEFT (ic), ic, FALSE);
+        aopOp (IC_RESULT (ic), ic, TRUE);
+
+        optype = operandType (IC_LEFT (ic));
+        rtype = operandType (IC_RESULT (ic));
+
+        /* if float then do float stuff */
+        if (IS_FLOAT (optype)) {
+                genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
+                goto release;
+        }
+
+        /* otherwise subtract from zero */
+        size = AOP_SIZE (IC_LEFT (ic));
+        offset = 0;
+        samer = sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)));
+        if (size == 1) {
+                if (samer) {
+                        emitcode ("neg", "%s",
+                                  aopGet (AOP (IC_LEFT (ic)), 0));
+                }
+                else {
+                        aopPut (AOP (IC_RESULT (ic)),
+                                aopGet (AOP (IC_LEFT (ic)), 0), 0);
+                        emitcode ("neg", "%s",
+                                  aopGet (AOP (IC_RESULT (ic)), 0));
+                }
+        }
+        else {
+                offset = size - 1;
+                while (size--) {
+                        char *l = aopGet (AOP (IC_LEFT (ic)), offset);
+                        if (!samer) {
+                                aopPut (AOP (IC_RESULT (ic)), l, offset);
+                                l = aopGet (AOP (IC_RESULT (ic)), offset);
+                        }
+                        if (offset)
+                                emitcode ("com", "%s", l);
+                        else
+                                emitcode ("neg", "%s", l);
+                        offset--;
+                }
+                size = AOP_SIZE (IC_LEFT (ic)) - 1;
+                offset = 1;
+                while (size--) {
+                        emitcode ("sbci", "%s,0xff",
+                                  aopGet (AOP (IC_RESULT (ic)), 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))))) {
+                symbol *tlbl = newiTempLabel (NULL);
+                emitcode ("clr", "r0");
+                emitcode ("brcc", "L%05d", tlbl->key);
+                emitcode ("com", "r0");
+                emitcode ("", "L%05d:", tlbl->key);
+                while (size--)
+                        aopPut (AOP (IC_RESULT (ic)), "r0", offset++);
+        }
+
+      release:
+        /* release the aops */
+        freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
+        freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genLabel - generates a label                                    */
+/* assignResultValue -               */
 /*-----------------------------------------------------------------*/
-static void genLabel (iCode *ic)
+static void
+assignResultValue (operand * oper)
 {
-    /* special case never generate */
-    if (IC_LABEL(ic) == entryLabel)
-        return ;
-
-    emitcode("","%05d$:",(IC_LABEL(ic)->key+100));
+        int offset = 0;
+        int size = AOP_SIZE (oper);
+        while (size--) {
+                aopPut (AOP (oper), fAVRReturn[offset], offset);
+                offset++;
+        }
 }
 
 /*-----------------------------------------------------------------*/
-/* genGoto - generates a ljmp                                      */
+/* saveZreg - if indirect call then save z-pointer register        */
 /*-----------------------------------------------------------------*/
-static void genGoto (iCode *ic)
+static void
+saveZreg (iCode * ic)
 {
-    emitcode ("ljmp","%05d$",(IC_LABEL(ic)->key+100));
+        /* only if live accross this call */
+        if (ic->regsSaved == 0 &&
+            (bitVectBitValue (ic->rMask, R30_IDX) ||
+             bitVectBitValue (ic->rMask, R31_IDX))) {
+                ic->regsSaved = 1;
+                emitcode ("push", "r30");
+                emitcode ("push", "r31");
+        }
 }
 
 /*-----------------------------------------------------------------*/
-/* 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.                               */
+/* popZreg - restore values of zreg                                */
 /*-----------------------------------------------------------------*/
-static int findLabelBackwards(iCode *ic, int key)
+static void
+popZreg (iCode * ic)
 {
-    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;
+        if (ic->regsSaved) {
+                emitcode ("pop", "r31");
+                emitcode ("pop", "r30");
         }
-    }
-    
-    /* printf("findLabelBackwards: not found.\n"); */
-    
-    return 0;
 }
 
 /*-----------------------------------------------------------------*/
-/* genPlusIncr :- does addition with increment if possible         */
+/* genIpush - genrate code for pushing this gets a little complex  */
 /*-----------------------------------------------------------------*/
-static bool genPlusIncr (iCode *ic)
+static void
+genIpush (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 (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;
+        int size, offset = 0;
+        char *l;
+
+
+        if (!ic->parmPush) {
+                /* and the item is spilt then do nothing */
+                if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+                        return;
         }
-        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 (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));
+        else {
+                iCode *lic;
+                for (lic = ic->next; lic; lic = lic->next)
+                        if (lic->op == PCALL)
+                                break;
+                if (lic)
+                        saveZreg (lic);
         }
-       
-        return TRUE ;
-    }
-    
-    return FALSE ;
+
+        /* this is a paramter push */
+        aopOp (IC_LEFT (ic), ic, FALSE);
+        size = AOP_SIZE (IC_LEFT (ic));
+        while (size--) {
+                l = aopGet (AOP (IC_LEFT (ic)), offset++);
+                emitcode ("push", "%s", l);
+        }
+
+        freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* outBitAcc - output a bit in acc                                 */
+/* genIpop - recover the registers: can happen only for spilling   */
 /*-----------------------------------------------------------------*/
-static void outBitAcc(operand *result)
+static void
+genIpop (iCode * ic)
 {
-    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);
-    }
+        int size, offset;
+
+
+        /* if the temp was not pushed then */
+        if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+                return;
+
+        aopOp (IC_LEFT (ic), ic, FALSE);
+        size = AOP_SIZE (IC_LEFT (ic));
+        offset = (size - 1);
+        while (size--)
+                emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--));
+
+        freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPlusBits - generates code for addition of two bits           */
+/* genCall - generates a call statement                            */
 /*-----------------------------------------------------------------*/
-static void genPlusBits (iCode *ic)
-{
-    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));
-    }
+static void
+genCall (iCode * ic)
+{
+
+        /* if send set is not empty then assign */
+        if (_G.sendSet) {
+                iCode *sic;
+                int rnum = 16;
+                for (sic = setFirstItem (_G.sendSet); sic;
+                     sic = setNextItem (_G.sendSet)) {
+                        int size, offset = 0;
+                        aopOp (IC_LEFT (sic), sic, FALSE);
+                        size = AOP_SIZE (IC_LEFT (sic));
+                        while (size--) {
+                                char *l =
+                                        aopGet (AOP (IC_LEFT (sic)), offset);
+                                char *b = buffer;
+                                sprintf (buffer, "r%d", rnum++);
+                                if (strcmp (l, b))
+                                        emitcode ("mov", "%s,%s", b, l);
+                                offset++;
+                        }
+                        freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+                }
+                _G.sendSet = NULL;
+        }
+        /* make the call */
+        emitcode ("call", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
+                                 OP_SYMBOL (IC_LEFT (ic))->rname :
+                                 OP_SYMBOL (IC_LEFT (ic))->name));
+
+        /* if we need assign a result value */
+        if ((IS_ITEMP (IC_RESULT (ic)) &&
+             (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
+              OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
+            IS_TRUE_SYMOP (IC_RESULT (ic))) {
+
+                aopOp (IC_RESULT (ic), ic, FALSE);
+                assignResultValue (IC_RESULT (ic));
+                freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+        }
+
+        /* adjust the stack for parameters if required */
+        if (ic->parmBytes) {
+                if (ic->parmBytes > 63) {
+                        emitcode ("sbiw", "r28,%d", ic->parmBytes);
+                }
+                else {
+                        emitcode ("subi", "r28,<(%d)",
+                                  ic->parmBytes);
+                        emitcode ("sbci", "r29,>(%d)",
+                                  ic->parmBytes);
+                }
+        }
+
 }
 
-#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)
+/*-----------------------------------------------------------------*/
+/* genPcall - generates a call by pointer statement                */
+/*-----------------------------------------------------------------*/
+static void
+genPcall (iCode * ic)
+{
+
+        if (!ic->regsSaved)
+                saveZreg (ic);
+
+        aopOp (IC_LEFT (ic), ic, FALSE);
+        emitcode ("mov", "r30", aopGet (AOP (IC_LEFT (ic)), 0));
+        emitcode ("mov", "r31", aopGet (AOP (IC_RIGHT (ic)), 0));
+        freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+
+        /* if send set is not empty the assign */
+        if (_G.sendSet) {
+                iCode *sic;
+                int rnum = 16;
+                for (sic = setFirstItem (_G.sendSet); sic;
+                     sic = setNextItem (_G.sendSet)) {
+                        int size, offset = 0;
+                        aopOp (IC_LEFT (sic), sic, FALSE);
+                        size = AOP_SIZE (IC_LEFT (sic));
+                        while (size--) {
+                                char *l =
+                                        aopGet (AOP (IC_LEFT (sic)), offset);
+                                char *b = buffer;
+                                sprintf (b, "r%d", rnum++);
+                                if (strcmp (l, b))
+                                        emitcode ("mov", "%s,%s", b, l);
+                                offset++;
+                        }
+                        freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+                }
+                _G.sendSet = NULL;
+        }
+
+        emitcode ("icall", "");
+
+        /* 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))) {
+
+                aopOp (IC_RESULT (ic), ic, FALSE);
+
+                assignResultValue (IC_RESULT (ic));
+                freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+        }
+
+        /* adjust the stack for parameters if
+           required */
+        if (ic->parmBytes) {
+                int i;
+                if (ic->parmBytes > 3) {
+                        emitcode ("mov", "a,%s", spname);
+                        emitcode ("add", "a,#0x%02x",
+                                  (-ic->parmBytes) & 0xff);
+                        emitcode ("mov", "%s,a", spname);
+                }
+                else
+                        for (i = 0; i < ic->parmBytes; i++)
+                                emitcode ("dec", "%s", spname);
+
+        }
+
+        /* adjust the stack for parameters if required */
+        if (ic->parmBytes) {
+                if (ic->parmBytes > 63) {
+                        emitcode ("sbiw", "r28,%d", ic->parmBytes);
+                }
+                else {
+                        emitcode ("subi", "r28,<(%d)",
+                                  ic->parmBytes);
+                        emitcode ("sbci", "r29,>(%d)",
+                                  ic->parmBytes);
+                }
+        }
+        if (ic->regsSaved)
+                popZreg (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* resultRemat - result  is rematerializable                       */
+/*-----------------------------------------------------------------*/
+static int
+resultRemat (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);
-    }
+        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;
 }
-#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)
+
+/*-----------------------------------------------------------------*/
+/* genFunction - generated code for function entry                 */
+/*-----------------------------------------------------------------*/
+static void
+genFunction (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);
-    }
+        symbol *sym;
+        sym_link *ftype;
+        int i = 0;
 
-    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);
-    }
+        _G.nRegsSaved = 0;
+        /* create the function header */
+        emitcode (";", "-----------------------------------------");
+        emitcode (";", " function %s",
+                  (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
+        emitcode (";", "-----------------------------------------");
+
+        emitcode ("", "%s:", sym->rname);
+        ftype = operandType (IC_LEFT (ic));
 
-    if (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);
-     }
+        /* if critical function then turn interrupts off */
+        if (IFFUNC_ISCRITICAL (ftype))
+                emitcode ("cli", "");
+
+        if (IFFUNC_ISISR (sym->type)) {
+        }
+
+        /* save the preserved registers that are used in this function */
+        for (i = R2_IDX; i <= R15_IDX; i++) {
+                if (bitVectBitValue (sym->regsUsed, i)) {
+                        _G.nRegsSaved++;
+                        emitcode ("push", "%s", avr_regWithIdx (i)->name);
+                }
+        }
+        /* now for the pointer registers */
+        if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
+                _G.nRegsSaved++;
+                emitcode ("push", "r26");
+        }
+        if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
+                _G.nRegsSaved++;
+                emitcode ("push", "r27");
+        }
+        if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
+                _G.nRegsSaved++;
+                emitcode ("push", "r30");
+        }
+        if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
+                _G.nRegsSaved++;
+                emitcode ("push", "r31");
+        }
+        /* adjust the stack for the function */
+        if (sym->stack) {
+                emitcode ("push", "r28");
+                emitcode ("push", "r29");
+                emitcode ("in", "r28,__SP_L__");
+                emitcode ("in", "r29,__SP_H__");
+                if (sym->stack <= 63) {
+                        emitcode ("sbiw", "r28,%d", sym->stack);
+                }
+                else {
+                        emitcode ("subi", "r28,<(%d)", sym->stack);
+                        emitcode ("sbci", "r29,>(%d)", sym->stack);
+                }
+                emitcode ("out", "__SP_L__,r28");
+                emitcode ("out", "__SP_H__,r29");
+        }
 }
-#endif
 
 /*-----------------------------------------------------------------*/
-/* genPlus - generates code for addition                           */
+/* genEndFunction - generates epilogue for functions               */
 /*-----------------------------------------------------------------*/
-static void genPlus (iCode *ic)
+static void
+genEndFunction (iCode * ic)
 {
-    int size, offset = 0;
-
-    /* special cases :- */
-
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RIGHT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
-
-    /* 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;
-    }
+        symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+        int i;
 
-    /* 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 ;
-    }
+        /* restore stack pointer */
+        if (sym->stack) {
+                if (sym->stack <= 63) {
+                        emitcode ("adiw", "r28,%d", sym->stack);
+                }
+                else {
+                        emitcode ("subi", "r28,<(-%d)", sym->stack);
+                        emitcode ("sbci", "r29,>(-%d)", sym->stack);
+                }
+                emitcode ("out", "__SP_L__,r28");
+                emitcode ("out", "__SP_H__,r29");
 
-    /* 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++);
-            }
+                /* pop frame pointer */
+                emitcode ("pop", "r29");
+                emitcode ("pop", "r28");
+        }
+        /* restore preserved registers */
+        if (bitVectBitValue (sym->regsUsed, R31_IDX)) {
+                _G.nRegsSaved--;
+                emitcode ("pop", "r31");
+        }
+        if (bitVectBitValue (sym->regsUsed, R30_IDX)) {
+                _G.nRegsSaved--;
+                emitcode ("pop", "r30");
+        }
+        if (bitVectBitValue (sym->regsUsed, R27_IDX)) {
+                _G.nRegsSaved--;
+                emitcode ("pop", "r27");
+        }
+        if (bitVectBitValue (sym->regsUsed, R26_IDX)) {
+                _G.nRegsSaved--;
+                emitcode ("pop", "r26");
+        }
+        for (i = R15_IDX; i >= R2_IDX; i--) {
+                if (bitVectBitValue (sym->regsUsed, i)) {
+                        _G.nRegsSaved--;
+                        emitcode ("pop", "%s", avr_regWithIdx (i)->name);
+                }
         }
-        goto release ;
-    }
 
-    /* if I can do an increment instead
-    of add then GOOD for ME */
-    if (genPlusIncr (ic) == TRUE)
-        goto release;   
-
-    size = getDataSize(IC_RESULT(ic));
-
-    while(size--){
-       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
-           MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE,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));
-       }
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
-    }
+        if (IFFUNC_ISCRITICAL (sym->type))
+                emitcode ("sti", "");
 
-    adjustArithmeticResult(ic);
+        if (options.debug && currFunc) {
+                debugFile->writeEndFunction (currFunc, ic, 1);
+        }
+
+        if (IFFUNC_ISISR (sym->type)) {
+                emitcode ("rti", "");
+        }
+        else {
+                emitcode ("ret", "");
+        }
 
-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     */
+/* genRet - generate code for return statement                     */
 /*-----------------------------------------------------------------*/
-static bool genMinusDec (iCode *ic)
+static void
+genRet (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 (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 ||
-                  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 ||
-                          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 ||
-                          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;
-    }
+        int size, offset = 0;
 
-    /* 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 ;
+        /* if we have no return value then
+           just generate the "ret" */
+        if (!IC_LEFT (ic))
+                goto jumpret;
+
+        /* we have something to return then
+           move the return value into place */
+        aopOp (IC_LEFT (ic), ic, FALSE);
+        size = AOP_SIZE (IC_LEFT (ic));
+
+        while (size--) {
+                if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) {
+                        emitcode ("ldi", "%s,%s(%d)", fAVRReturn[offset],
+                                  larray[offset],
+                                  (int) ulFromVal (AOP (IC_LEFT (ic))->
+                                                      aopu.aop_lit), offset);
+                }
+                else {
+                        char *l;
+                        l = aopGet (AOP (IC_LEFT (ic)), offset);
+                        if (strcmp (fAVRReturn[offset], l))
+                                emitcode ("mov", "%s,%s", fAVRReturn[offset],
+                                          l);
+                }
+                offset++;
+        }
 
-    /* we can if the aops of the left & result match or
-    if they are in registers and the registers are the
-    same */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+        freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
 
-        while (icount--) 
-            emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+      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))
 
-        return TRUE ;
-    }
+                emitcode ("rjmp", "L%05d", returnLabel->key);
 
-    return FALSE ;
 }
 
 /*-----------------------------------------------------------------*/
-/* addSign - complete with sign                                    */
+/* genLabel - generates a label                                    */
 /*-----------------------------------------------------------------*/
-static void addSign(operand *result, int offset, int sign)
+static void
+genLabel (iCode * ic)
 {
-    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++);
-    }
+        /* special case never generate */
+        if (IC_LABEL (ic) == entryLabel)
+                return;
+
+        emitcode ("", "L%05d:", IC_LABEL (ic)->key);
 }
 
 /*-----------------------------------------------------------------*/
-/* genMinusBits - generates code for subtraction  of two bits      */
+/* genGoto - generates a ljmp                                      */
 /*-----------------------------------------------------------------*/
-static void genMinusBits (iCode *ic)
+static void
+genGoto (iCode * ic)
 {
-    symbol *lbl = newiTempLabel(NULL);
-    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)))));
-    }
+        emitcode ("rjmp", "L%05d", (IC_LABEL (ic)->key));
 }
 
 /*-----------------------------------------------------------------*/
-/* genMinus - generates code for subtraction                       */
+/* genPlusIncr :- does addition with increment if possible         */
 /*-----------------------------------------------------------------*/
-static void genMinus (iCode *ic)
-{
-    int size, offset = 0;
-    unsigned long lit = 0L;
-
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RIGHT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
-
-    /* special cases :- */
-    /* if both left & right are in bit space */
-    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-        AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
-        genMinusBits (ic);
-        goto release ;
-    }
+static bool
+genPlusIncr (iCode * ic)
+{
+        unsigned int icount;
+        int offset = 0;
+
+        /* will try to generate an increment */
+        /* if the right side is not a literal
+           we cannot */
+        if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+                return FALSE;
+
+        icount = (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.
+                                             aop_lit);
+
+        /* if the sizes are greater than 2 or they are not the same regs
+           then we cannot */
+        if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+                return FALSE;
+
+        /* so we know LEFT & RESULT in the same registers and add
+           amount <= 63 */
+        /* for short & char types */
+        if (AOP_SIZE (IC_RESULT (ic)) < 2) {
+                if (icount == 1) {
+                        emitcode ("inc", "%s",
+                                  aopGet (AOP (IC_LEFT (ic)), 0));
+                        return TRUE;
+                }
+                if (AOP_ISHIGHREG( AOP (IC_LEFT (ic)),0)) {
+                        emitcode ("subi", "%s,<(%d)",
+                                  aopGet (AOP (IC_LEFT (ic)), 0), 0-icount);
+                        return TRUE;
+                }
+        }
 
-    /* if I can do an decrement instead
-    of subtract then GOOD for ME */
-    if (genMinusDec (ic) == TRUE)
-        goto release;   
+        for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
+                if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
+        }
 
-    size = getDataSize(IC_RESULT(ic));   
+        if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
+                /* if register pair and starts with 26/30 then adiw */
+                if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
+                    && icount < 64
+                    && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
+                        IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
+                        IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
+                        emitcode ("adiw", "%s,%d",
+                                  aopGet (AOP (IC_RESULT (ic)), 0), icount);
+                        return TRUE;
+                }
 
-    if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
-        CLRC;
-    }
-    else{
-        lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-        lit = - (long)lit;
-    }
+                /* use subi */
+                emitcode ("subi", "%s,<(%d)",
+                          aopGet (AOP (IC_RESULT (ic)), 0), 0-icount);
+                emitcode ("sbci", "%s,>(%d)",
+                          aopGet (AOP (IC_RESULT (ic)), 1), 0-icount);
+                return TRUE;
+        }
 
-    /* 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));
-        }
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
-    }
+        /* for 32 bit longs */
+        emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
+                  0-icount);
+        emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
+                  0-icount);
+        emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
+                  0-icount);
+        emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
+                  0-icount);
+        return TRUE;
 
-    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);
 }
 
+/* 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),
+                        GPTRSIZE - 1);
+        }
 
-/*-----------------------------------------------------------------*/
-/* 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);
-}
+        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),
+                        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);
+        }
+}
 
 /*-----------------------------------------------------------------*/
-/* genMultOneByte : 8 bit multiplication & division                */
+/* genPlus - generates code for addition                           */
 /*-----------------------------------------------------------------*/
-static void genMultOneByte (operand *left,
-                            operand *right,
-                            operand *result)
+static void
+genPlus (iCode * ic)
 {
-    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;
-    }
+        int size, offset = 0;
+        int samer;
+        char *l;
 
-    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));
-            }
+        /* special cases :- */
 
-            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");
-            }
+        aopOp (IC_LEFT (ic), ic, FALSE);
+        aopOp (IC_RIGHT (ic), ic, FALSE);
+        aopOp (IC_RESULT (ic), ic, TRUE);
+
+        /* if I can do an increment instead
+           of add then GOOD for ME */
+        if (genPlusIncr (ic) == TRUE)
+                goto release;
+
+        size = getDataSize (IC_RESULT (ic));
+        samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
+
+        while (size--) {
+                if (!samer)
+                        aopPut (AOP (IC_RESULT (ic)),
+                                aopGet (AOP (IC_LEFT (ic)), offset), offset);
+
+                if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
+
+                        if (offset == 0)
+                                l = "add";
+                        else
+                                l = "adc";
+
+                        emitcode (l, "%s,%s",
+                                  aopGet (AOP (IC_RESULT (ic)), offset),
+                                  aopGet (AOP (IC_RIGHT (ic)), offset));
+                }
+                else {
+                        if (AOP_ISHIGHREG( AOP( IC_RESULT(ic)),offset)) {
+                                if (offset == 0)
+                                        l = "subi";
+                                else
+                                        l = "sbci";
+
+                                emitcode (l, "%s,%s(-%d)",
+                                          aopGet (AOP (IC_RESULT (ic)), offset),
+                                          larray[offset],
+                                          (int) ulFromVal (AOP (IC_RIGHT (ic))->
+                                                              aopu.aop_lit));
+                        } else {
+                                if (offset == 0)
+                                        l = "add";
+                                else
+                                        l = "adc";
+
+                                emitcode (l, "%s,%s",
+                                          aopGet (AOP (IC_RESULT (ic)), offset),
+                                          aopGet (AOP (IC_RIGHT (ic)), offset));
+                        }
+                }
+                offset++;
         }
-        size -= 2;   
-        offset = 2;
-        if (size > 0)
-            while (size--)
-                aopPut(AOP(result),"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);
 }
 
 /*-----------------------------------------------------------------*/
-/* genMult - generates code for multiplication                     */
+/* genMinusDec :- does subtraction with deccrement if possible     */
 /*-----------------------------------------------------------------*/
-static void genMult (iCode *ic)
-{
-    operand *left = IC_LEFT(ic);
-    operand *right = IC_RIGHT(ic);
-    operand *result= IC_RESULT(ic);   
-
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
-
-    /* special cases first */
-    /* both are bits */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right)== AOP_CRY) {
-        genMultbits(left,right,result);
-        goto release ;
-    }
+static bool
+genMinusDec (iCode * ic)
+{
+        unsigned int icount;
+        int offset ;
+
+        /* will try to generate an increment */
+        /* if the right side is not a literal
+           we cannot */
+        if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+                return FALSE;
+
+        icount =
+                (unsigned int) ulFromVal (AOP (IC_RIGHT (ic))->aopu.
+                                             aop_lit);
+
+        /* if the sizes are greater than 2 or they are not the same regs
+           then we cannot */
+        if (!sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+                return FALSE;
+
+        /* so we know LEFT & RESULT in the same registers and add
+           amount <= 63 */
+        /* for short & char types */
+        if (AOP_SIZE (IC_RESULT (ic)) < 2) {
+                if (icount == 1) {
+                        emitcode ("dec", "%s",
+                                  aopGet (AOP (IC_LEFT (ic)), 0));
+                        return TRUE;
+                }
+                if (AOP_ISHIGHREG( AOP ( IC_LEFT(ic)),0)) {
+                        emitcode ("subi", "%s,<(%d)",
+                                  aopGet (AOP (IC_LEFT (ic)), 0), icount);
+                        return TRUE;
+                }
+        }
 
-    /* if both are of size == 1 */
-    if (AOP_SIZE(left) == 1 &&
-        AOP_SIZE(right) == 1 ) {
-        genMultOneByte(left,right,result);
-        goto release ;
-    }
+        for (offset = 0 ; offset < AOP_SIZE(IC_RESULT(ic)) ; offset++) {
+                if (!(AOP_ISHIGHREG(AOP(IC_RESULT(ic)),offset))) return FALSE;
+        }
+
+        if (AOP_SIZE (IC_RESULT (ic)) <= 3) {
+                /* if register pair and starts with 26/30 then adiw */
+                if (isRegPair (AOP (IC_RESULT (ic))) && icount > 0
+                    && icount < 64
+                    && (IS_REGIDX (AOP (IC_RESULT (ic)), R26_IDX) ||
+                        IS_REGIDX (AOP (IC_RESULT (ic)), R24_IDX) ||
+                        IS_REGIDX (AOP (IC_RESULT (ic)), R30_IDX))) {
+                        emitcode ("sbiw", "%s,%d",
+                                  aopGet (AOP (IC_RESULT (ic)), 0), icount);
+                        return TRUE;
+                }
 
-    /* should have been converted to function call */       
-    assert(1) ;
+                /* use subi */
+                emitcode ("subi", "%s,<(%d)",
+                          aopGet (AOP (IC_RESULT (ic)), 0), icount);
+                emitcode ("sbci", "%s,>(%d)",
+                          aopGet (AOP (IC_RESULT (ic)), 1), icount);
+                return TRUE;
+        }
+        /* for 32 bit longs */
+        emitcode ("subi", "%s,<(%d)", aopGet (AOP (IC_RESULT (ic)), 0),
+                  icount);
+        emitcode ("sbci", "%s,>(%d)", aopGet (AOP (IC_RESULT (ic)), 1),
+                  icount);
+        emitcode ("sbci", "%s,hlo8(%d)", aopGet (AOP (IC_RESULT (ic)), 2),
+                  icount);
+        emitcode ("sbci", "%s,hhi8(%d)", aopGet (AOP (IC_RESULT (ic)), 3),
+                  icount);
+        return TRUE;
 
-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                                  */
+/* genMinus - generates code for subtraction                       */
 /*-----------------------------------------------------------------*/
-static void genDivbits (operand *left, 
-                        operand *right, 
-                        operand *result)
+static void
+genMinus (iCode * ic)
 {
+        int size, offset = 0, samer;
+        char *l;
 
-    char *l;
+        aopOp (IC_LEFT (ic), ic, FALSE);
+        aopOp (IC_RIGHT (ic), ic, FALSE);
+        aopOp (IC_RESULT (ic), ic, TRUE);
 
-    /* the result must be bit */    
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    l = aopGet(AOP(left),0,FALSE,FALSE);
+        /* if I can do an decrement instead
+           of subtract then GOOD for ME */
+        if (genMinusDec (ic) == TRUE)
+                goto release;
 
-    MOVA(l);    
+        size = getDataSize (IC_RESULT (ic));
+        samer = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
+        while (size--) {
+                if (!samer)
+                        aopPut (AOP (IC_RESULT (ic)),
+                                aopGet (AOP (IC_LEFT (ic)), offset), offset);
 
-    emitcode("div","ab");
-    emitcode("rrc","a");
-    aopPut(AOP(result),"c",0);
-}
+                if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
 
-/*-----------------------------------------------------------------*/
-/* 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 ;
-    }
+                        if (offset == 0)
+                                l = "sub";
+                        else
+                                l = "sbc";
 
-    /* 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++);
+                        emitcode (l, "%s,%s",
+                                  aopGet (AOP (IC_RESULT (ic)), offset),
+                                  aopGet (AOP (IC_RIGHT (ic)), offset));
+                }
+                else {
+                        if (AOP_ISHIGHREG(AOP (IC_RESULT (ic)),offset)) {
+                                if (offset == 0)
+                                        l = "subi";
+                                else
+                                        l = "sbci";
+
+                                emitcode (l, "%s,%s(%d)",
+                                          aopGet (AOP (IC_RESULT (ic)), offset),
+                                          larray[offset],
+                                          (int) ulFromVal (AOP (IC_RIGHT (ic))->
+                                                              aopu.aop_lit));
+                        } else {
+                                if (offset == 0)
+                                        l = "sub";
+                                else
+                                        l = "sbc";
+
+                                emitcode (l, "%s,%s",
+                                          aopGet (AOP (IC_RESULT (ic)), offset),
+                                          aopGet (AOP (IC_RIGHT (ic)), offset));
+                        }
+                }
+                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);
 }
 
 /*-----------------------------------------------------------------*/
-/* genDiv - generates code for division                            */
+/* genMultOneByte : 8 bit multiplication & division                */
 /*-----------------------------------------------------------------*/
-static void genDiv (iCode *ic)
+static void
+genMultOneByte (operand * left, operand * right, operand * result)
 {
-    operand *left = IC_LEFT(ic);
-    operand *right = IC_RIGHT(ic);
-    operand *result= IC_RESULT(ic);   
-
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
-
-    /* special cases first */
-    /* both are bits */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right)== AOP_CRY) {
-        genDivbits(left,right,result);
-        goto release ;
-    }
+        sym_link *opetype = operandType (result);
+        symbol *lbl;
+        int size, offset;
 
-    /* if both are of size == 1 */
-    if (AOP_SIZE(left) == 1 &&
-        AOP_SIZE(right) == 1 ) {
-        genDivOneByte(left,right,result);
-        goto release ;
-    }
+        /* (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;
+        }
 
-    /* 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); 
+        size = AOP_SIZE (result);
+
+        if (SPEC_USIGN (opetype)) {
+                emitcode ("mul", "%s,%s", aopGet (AOP (left), 0),
+                          aopGet (AOP (right), 0));
+        }
+        else {
+                emitcode ("muls", "%s,%s", aopGet (AOP (left), 0),
+                          aopGet (AOP (right), 0));
+        }
+        aopPut (AOP (result), "r0", 0);
+        if (size > 1) {
+                aopPut (AOP (result), "r1", 1);
+                offset = 2;
+                size -= 2;
+                if (SPEC_USIGN (opetype)) {
+                        while (size--) {
+                                aopPut (AOP (result), zero, offset++);
+                        }
+                }
+                else {
+                        if (size) {
+                                lbl = newiTempLabel (NULL);
+                                emitcode ("ldi", "r24,0");
+                                emitcode ("brcc", "L%05d", lbl->key);
+                                emitcode ("ldi", "r24,0xff)");
+                                emitcode ("", "L%05d:", lbl->key);
+                                while (size--)
+                                        aopPut (AOP (result), "r24",
+                                                offset++);
+                        }
+                }
+        }
+        return;
 }
 
 /*-----------------------------------------------------------------*/
-/* genModbits :- modulus of bits                                   */
+/* genMult - generates code for multiplication                     */
 /*-----------------------------------------------------------------*/
-static void genModbits (operand *left, 
-                        operand *right, 
-                        operand *result)
+static void
+genMult (iCode * ic)
 {
+        operand *left = IC_LEFT (ic);
+        operand *right = IC_RIGHT (ic);
+        operand *result = IC_RESULT (ic);
 
-    char *l;
+        /* assign the amsops */
+        aopOp (left, ic, FALSE);
+        aopOp (right, ic, FALSE);
+        aopOp (result, ic, TRUE);
 
-    /* the result must be bit */    
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    l = aopGet(AOP(left),0,FALSE,FALSE);
+        /* if both are of size == 1 */
+        if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1) {
+                genMultOneByte (left, right, result);
+                goto release;
+        }
 
-    MOVA(l);       
+        /* should have been converted to function call */
+        assert (0);
 
-    emitcode("div","ab");
-    emitcode("mov","a,b");
-    emitcode("rrc","a");
-    aopPut(AOP(result),"c",0);
+      release:
+        freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+        freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genModOneByte : 8 bit modulus                                   */
+/* genDiv - generates code for division                            */
 /*-----------------------------------------------------------------*/
-static void genModOneByte (operand *left,
-                           operand *right,
-                           operand *result)
+static void
+genDiv (iCode * ic)
 {
-    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);
-
+        /* should have been converted to function call */
+        assert (0);
 }
 
 /*-----------------------------------------------------------------*/
 /* genMod - generates code for division                            */
 /*-----------------------------------------------------------------*/
-static void genMod (iCode *ic)
+static void
+genMod (iCode * ic)
 {
-    operand *left = IC_LEFT(ic);
-    operand *right = IC_RIGHT(ic);
-    operand *result= IC_RESULT(ic);  
-
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
-
-    /* special cases first */
-    /* both are bits */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right)== AOP_CRY) {
-        genModbits(left,right,result);
-        goto release ;
-    }
+        /* should have been converted to function call */
+        assert (0);
 
-    /* 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);
+enum {
+        AVR_EQ = 0,
+        AVR_NE,
+        AVR_LT,
+        AVR_GE
+};
+
+/*-----------------------------------------------------------------*/
+/* revavrcnd - reverse a conditional for avr                       */
+/*-----------------------------------------------------------------*/
+static int
+revavrcnd (int type)
+{
+        static struct {
+                int type, rtype;
+        } rar[] = {
+                {
+                AVR_EQ, AVR_NE}
+                , {
+                AVR_LT, AVR_GE}
+        };
+        int i;
 
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
+        for (i = 0; i < (sizeof (rar) / sizeof (rar[0])); i++) {
+                if (rar[i].type == type)
+                        return rar[i].rtype;
+                if (rar[i].rtype == type)
+                        return rar[i].type;
+        }
+        assert (0);             /* cannot happen */
+        return 0;               /* makes the compiler happy */
 }
 
+static char *br_name[4] = { "breq", "brne", "brlt", "brge" };
+static char *br_uname[4] = { "breq", "brne", "brlo", "brcc" };
+
 /*-----------------------------------------------------------------*/
-/* genIfxJump :- will create a jump depending on the ifx           */
+/* genBranch - generate the branch instruction                     */
 /*-----------------------------------------------------------------*/
-static void genIfxJump (iCode *ic, char *jval)
+static void
+genBranch (iCode * ifx, int br_type, int sign)
 {
-    symbol *jlbl ;
-    symbol *tlbl = newiTempLabel(NULL);
-    char *inst;
-
-    /* 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;
+        int tj = (IC_TRUE (ifx) ? 1 : 0);
+
+        if (tj) {               /* if true jump */
+                char *nm = (sign ? br_name[br_type] : br_uname[br_type]);
+                emitcode (nm, "L%05d", IC_TRUE (ifx)->key);
+        }
+        else {                  /* if false jump */
+                int rtype = revavrcnd (br_type);
+                char *nm = (sign ? br_name[rtype] : br_uname[rtype]);
+                emitcode (nm, "L%05d", IC_FALSE (ifx)->key);
+        }
+        ifx->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
-/* genCmp :- greater or less than comparison                       */
+/* genCmp - compare & jump                                         */
 /*-----------------------------------------------------------------*/
-static void genCmp (operand *left,operand *right,
-                    operand *result, iCode *ifx, int sign)
+static void
+genCmp (iCode * ic, iCode * ifx, int br_type)
 {
-    int size, offset = 0 ;
-    unsigned long lit = 0L;
-
-    /* if left & right are bit variables */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right) == AOP_CRY ) {
-        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;
+        operand *left, *right, *result;
+        sym_link *letype, *retype;
+        symbol *lbl;
+        int sign, size, offset = 0;
+
+        left = IC_LEFT (ic);
+        right = IC_RIGHT (ic);
+        result = IC_RESULT (ic);
+
+        letype = getSpec (operandType (left));
+        retype = getSpec (operandType (right));
+        sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
+
+        /* assign the amsops */
+        aopOp (left, ic, FALSE);
+        aopOp (right, ic, FALSE);
+        aopOp (result, ic, TRUE);
+        size = AOP_SIZE (left);
+
+        if (ifx) {
+                if (size == 1) {
+                        if (AOP_TYPE (right) == AOP_LIT) {
+                                emitcode ("cpi", "%s,<(%d)",
+                                          aopGet (AOP (left), 0),
+                                          (int) ulFromVal (AOP (IC_RIGHT (ic))->
+                                                        aopu.aop_lit));
+                                genBranch (ifx, br_type, sign);
+                        }
+                        else {  /* right != literal */
+                                emitcode ("cp", "%s,%s",
+                                          aopGet (AOP (left), 0),
+                                          aopGet (AOP (right), 0));
+                                genBranch (ifx, br_type, sign);
                         }
-                        else    
-                            emitcode("rlc","a");
-                    }
-                    goto release;
                 }
-            }
-            CLRC;
-            while (size--) {
-                MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
-                if (sign && size == 0) {
-                    emitcode("xrl","a,#0x80");
-                    if (AOP_TYPE(right) == AOP_LIT){
-                        unsigned long lit = (unsigned long)
-                           floatFromVal(AOP(right)->aopu.aop_lit);
-                        emitcode("subb","a,#0x%02x",
-                                0x80 ^ (unsigned int)((lit >> (offset*8)) & 0x0FFL));                       
-                    } else {
-                        emitcode("mov","b,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
-                        emitcode("xrl","b,#0x80");
-                        emitcode("subb","a,b");
-                    }
-                } else      
-                    emitcode("subb","a,%s",aopGet(AOP(right),offset++,FALSE,FALSE));
-            }
+                else {          /* size != 1 */
+                        while (size--) {
+                                if (offset == 0)
+                                        emitcode ("cp", "%s,%s",
+                                                  aopGet (AOP (left), 0),
+                                                  aopGet (AOP (right), 0));
+                                else
+                                        emitcode ("cpc", "%s,%s",
+                                                  aopGet (AOP (left), offset),
+                                                  aopGet (AOP (right),
+                                                          offset));
+                                offset++;
+                        }
+                        genBranch (ifx, br_type, sign);
+                }
+        }
+        else {                  /* no ifx */
+                emitcode ("clr", "r0");
+                while (size--) {
+                        if (offset == 0)
+                                emitcode ("cp", "%s,%s",
+                                          aopGet (AOP (left), 0),
+                                          aopGet (AOP (right), 0));
+                        else
+                                emitcode ("cpc", "%s,%s",
+                                          aopGet (AOP (left), offset),
+                                          aopGet (AOP (right), offset));
+                        offset++;
+                }
+                lbl = newiTempLabel (NULL);
+                br_type = revavrcnd (br_type);
+                if (sign)
+                        emitcode (br_uname[br_type], "L%05d", lbl->key);
+                else
+                        emitcode (br_name[br_type], "L%05d", lbl->key);
+                emitcode ("inc", "r0");
+                emitcode ("", "L%05d:", lbl->key);
+                aopPut (AOP (result), "r0", 0);
+                size = AOP_SIZE (result) - 1;
+                offset = 1;
+                while (size--)
+                        aopPut (AOP (result), zero, offset++);
         }
-    }
 
-release:
-    if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
-        outBitC(result);
-    } else {
-        /* if the result is used in the next
-        ifx conditional branch then generate
-        code a little differently */
-        if (ifx )
-            genIfxJump (ifx,"c");
-        else
-            outBitC(result);
-        /* leave the result in acc */
-    }
+        freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+        freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* genCmpGt :- greater than comparison                             */
 /*-----------------------------------------------------------------*/
-static void genCmpGt (iCode *ic, iCode *ifx)
+static void
+genCmpGt (iCode * ic, iCode * ifx)
 {
-    operand *left, *right, *result;
-    link *letype , *retype;
-    int sign ;
-
-    left = IC_LEFT(ic);
-    right= IC_RIGHT(ic);
-    result = IC_RESULT(ic);
-
-    letype = getSpec(operandType(left));
-    retype =getSpec(operandType(right));
-    sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
-
-    genCmp(right, left, result, ifx, sign);
-
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE); 
+        /* should have transformed by the parser */
+        assert (0);
 }
 
 /*-----------------------------------------------------------------*/
 /* genCmpLt - less than comparisons                                */
 /*-----------------------------------------------------------------*/
-static void genCmpLt (iCode *ic, iCode *ifx)
+static void
+genCmpLt (iCode * ic, iCode * ifx)
 {
-    operand *left, *right, *result;
-    link *letype , *retype;
-    int sign ;
-
-    left = IC_LEFT(ic);
-    right= IC_RIGHT(ic);
-    result = IC_RESULT(ic);
-
-    letype = getSpec(operandType(left));
-    retype =getSpec(operandType(right));
-    sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
-
-    /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+        genCmp (ic, ifx, AVR_LT);
+}
 
-    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); 
+/*-----------------------------------------------------------------*/
+/* genCmpEq - generates code for equal to                          */
+/*-----------------------------------------------------------------*/
+static void
+genCmpEq (iCode * ic, iCode * ifx)
+{
+        genCmp (ic, ifx, AVR_EQ);
 }
 
 /*-----------------------------------------------------------------*/
-/* gencjneshort - compare and jump if not equal                    */
+/* genCmpNe - generates code for not equal to                      */
 /*-----------------------------------------------------------------*/
-static void gencjneshort(operand *left, operand *right, symbol *lbl)
+static void
+genCmpNe (iCode * ic, iCode * ifx)
 {
-    int size = max(AOP_SIZE(left),AOP_SIZE(right));
-    int offset = 0;
-    unsigned long lit = 0L;
-
-    /* if the left side is a literal or 
-    if the right is in a pointer register and left 
-    is not */
-    if ((AOP_TYPE(left) == AOP_LIT) || 
-        (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--) {
-            emitcode("cjne","%s,%s,%05d$",
-                     aopGet(AOP(left),offset,FALSE,FALSE),
-                     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++;
-        }
-    }
+        genCmp (ic, ifx, AVR_NE);
 }
 
 /*-----------------------------------------------------------------*/
-/* gencjne - compare and jump if not equal                         */
+/* genCmpGe - generates code for greater than equal to             */
 /*-----------------------------------------------------------------*/
-static void gencjne(operand *left, operand *right, symbol *lbl)
+static void
+genCmpGe (iCode * ic, iCode * ifx)
 {
-    symbol *tlbl  = newiTempLabel(NULL);
-
-    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);
+        genCmp (ic, ifx, AVR_GE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genCmpEq - generates code for equal to                          */
+/* genCmpLe - generates code for less than equal to                */
 /*-----------------------------------------------------------------*/
-static void genCmpEq (iCode *ic, iCode *ifx)
+static void
+genCmpLe (iCode * ic, iCode * ifx)
 {
-    operand *left, *right, *result;
-
-    aopOp((left=IC_LEFT(ic)),ic,FALSE);
-    aopOp((right=IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
-
-    /* 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 */
-    }
+        operand *left = IC_LEFT (ic);
+        operand *right = IC_RIGHT (ic);
 
-release:
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);
+        IC_RIGHT (ic) = left;
+        IC_LEFT (ic) = right;
+        genCmp (ic, ifx, AVR_GE);
 }
 
 /*-----------------------------------------------------------------*/
 /* ifxForOp - returns the icode containing the ifx for operand     */
 /*-----------------------------------------------------------------*/
-static iCode *ifxForOp ( operand *op, iCode *ic )
+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;
+        /* 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)
+static void
+genAndOp (iCode * ic)
 {
-    operand *left,*right, *result;
-    symbol *tlbl;
-
-    /* note here that && operations that are in an
-    if statement are taken away by backPatchLabels
-    only those used in arthmetic operations remain */
-    aopOp((left=IC_LEFT(ic)),ic,FALSE);
-    aopOp((right=IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,FALSE);
-
-    /* if both are bit variables */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right) == AOP_CRY ) {
-        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);
-    }
+        operand *left, *right, *result;
+        symbol *tlbl;
+        int size, offset;
+
+        /* note here that && operations that are in an
+           if statement are taken away by backPatchLabels
+           only those used in arthmetic operations remain */
+        aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+        aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+        aopOp ((result = IC_RESULT (ic)), ic, FALSE);
+
+        tlbl = newiTempLabel (NULL);
+        toBoolean (left, "r0", TRUE);
+        toBoolean (right, "r1", TRUE);
+        emitcode ("and", "r0,r1");
+        emitcode ("ldi", "r24,1");
+        emitcode ("breq", "L%05d", tlbl->key);
+        emitcode ("dec", "r24");
+        emitcode ("", "L%05d:", tlbl->key);
+        aopPut (AOP (result), "r24", 0);
+        size = AOP_SIZE (result) - 1;
+        offset = 1;
+        while (size--)
+                aopPut (AOP (result), zero, offset++);
 
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);
+        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)
+static void
+genOrOp (iCode * ic)
 {
-    operand *left,*right, *result;
-    symbol *tlbl;
-
-    /* note here that || operations that are in an
-    if statement are taken away by backPatchLabels
-    only those used in arthmetic operations remain */
-    aopOp((left=IC_LEFT(ic)),ic,FALSE);
-    aopOp((right=IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,FALSE);
-
-    /* if both are bit variables */
-    if (AOP_TYPE(left) == AOP_CRY &&
-        AOP_TYPE(right) == AOP_CRY ) {
-        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);
-    }
+        operand *left, *right, *result;
+        symbol *tlbl;
+        int size, offset;
+
+        /* note here that || operations that are in an
+           if statement are taken away by backPatchLabels
+           only those used in arthmetic operations remain */
+        aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+        aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+        aopOp ((result = IC_RESULT (ic)), ic, FALSE);
+
+        tlbl = newiTempLabel (NULL);
+        toBoolean (left, "r0", TRUE);
+        toBoolean (right, "r0", FALSE);
+        emitcode ("ldi", "r24,1");
+        emitcode ("breq", "L%05d", tlbl->key);
+        emitcode ("dec", "r24");
+        emitcode ("", "L%05d:", tlbl->key);
+        aopPut (AOP (result), "r24", 0);
+        size = AOP_SIZE (result) - 1;
+        offset = 1;
+        while (size--)
+                aopPut (AOP (result), zero, offset++);
+
+        freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+        freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+        freeAsmop (result, NULL, ic, TRUE);
+}
+
+enum {
+        AVR_AND = 0, AVR_OR, AVR_XOR
+};
+static char *bopnames_lit[] = { "andi", "ori" };
+static char *bopnames[] = { "and", "or", "eor" };
+/*-----------------------------------------------------------------*/
+/* genBitWise - generate bitwise operations                        */
+/*-----------------------------------------------------------------*/
+static void
+genBitWise (iCode * ic, iCode * ifx, int bitop)
+{
+        operand *left, *right, *result;
+        int size, offset = 0;
+        char *l;
+        symbol *lbl, *lbl1;
+        int samerl, samerr;
+
+        aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+        aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+        aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+
+        size = AOP_SIZE (left);
+        offset = 0;
+        if (ifx) {              /* used only for jumps */
+                if (AOP_TYPE (right) == AOP_LIT &&
+                    (bitop == AVR_AND || bitop == AVR_OR)) {
+                        int lit =
+                                (int) ulFromVal (AOP (right)->aopu.
+                                                    aop_lit);
+                        int p2 = powof2 (lit);
+                        if (bitop == AVR_AND && (p2 >= 0)) {    /* right side is a power of 2 */
+                                l = aopGet (AOP (left), p2 / 8);
+                                if (IC_TRUE (ifx)) {
+                                        emitcode ("sbrc", "%s,%d", l,
+                                                  (p2 % 8));
+                                        emitcode ("rjmp", "L%05d",
+                                                  IC_TRUE (ifx)->key);
+                                }
+                                else {
+                                        emitcode ("sbrs", "%s,%d", l,
+                                                  (p2 % 8));
+                                        emitcode ("rjmp", "L%05d",
+                                                  IC_FALSE (ifx)->key);
+                                }
+                        }
+                        else {  /* right not power of two */
+                                int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
+                                if (size == 1) {
+                                        if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),0)) {
+                                                emitcode (bopnames_lit[bitop],
+                                                          "%s,<(%d)",
+                                                          aopGet (AOP (IC_LEFT (ic)), 0), lit);
+                                        }
+                                        else {
+                                                MOVR24 (aopGet (AOP (IC_LEFT (ic)), 0));
+                                                emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
+                                        }
+                                        lbl = newiTempLabel (NULL);
+                                        if (IC_TRUE (ifx)) {
+                                                emitcode ("breq", "L%05d", lbl->key);
+                                                emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+                                        }
+                                        else {
+                                                emitcode ("brne", "L%05d", lbl->key);
+                                                emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
+                                        }
+                                        emitcode ("", "L%05d:", lbl->key);
+                                }
+                                else if (size == 2) {
+                                        emitcode ("mov", "r24,%s", aopGet (AOP (IC_LEFT (ic)), 0));
+                                        emitcode ("mov", "r25,%s", aopGet (AOP (IC_LEFT (ic)), 1));
+                                        emitcode (bopnames_lit[bitop], "r24,<(%d)", lit);
+                                        emitcode (bopnames_lit[bitop], "r25,>(%d)", lit);
+                                        emitcode ("sbiw", "r24,0");
+                                        lbl = newiTempLabel (NULL);
+                                        if (IC_TRUE (ifx)) {
+                                                emitcode ("breq", "L%05d", lbl->key);
+                                                emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+                                        }
+                                        else {
+                                                emitcode ("brne", "L%05d", lbl->key);
+                                                emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
+                                        }
+                                        emitcode ("", "L%05d:", lbl->key);
+                                }
+                                else {
+                                        lbl = newiTempLabel (NULL);
+                                        lbl1 = newiTempLabel (NULL);
+                                        while (size--) {
+                                                if (eh && AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset)) {
+                                                        emitcode (bopnames_lit [bitop], "%s,<(%d)",
+                                                                  aopGet (AOP (IC_LEFT (ic)), offset),
+                                                                  lit);
+                                                }
+                                                else {
+                                                        char *l = aopGet (AOP (IC_LEFT (ic)), offset);
+                                                        MOVR24 (l);
+                                                        emitcode ("andi", "r24,<(%d)", lit);
+                                                }
+                                                emitcode ("brne", "L%05d", lbl->key);
+                                                offset++;
+                                        }
+                                        /* all are zero */
+                                        if (IC_FALSE (ifx))
+                                                emitcode ("rjmp", "L%05d", IC_FALSE (ifx)-> key);
+                                        else
+                                                emitcode ("rjmp", "L%05d", lbl1->key);
+                                        emitcode ("", "L%05d:", lbl->key);
+                                        /* not zero */
+                                        if (IC_TRUE (ifx))
+                                                emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+                                        emitcode ("", "L%05d:", lbl1->key);
+
+                                }
+                        }
+                }
+                else {          /* right is not a literal */
+                        int eh = OP_SYMBOL (left)->liveTo <= ic->seq;
+                        int reh = OP_SYMBOL (right)->liveTo <= ic->seq;
+                        if (size == 1) {
+                                if (eh) {
+                                        emitcode (bopnames[bitop], "%s,%s", aopGet (AOP (IC_LEFT (ic)), 0),
+                                                  aopGet (AOP (IC_RIGHT (ic)), 0));
+                                }
+                                else if (reh) {
+                                        emitcode (bopnames[bitop], "%s,%s",
+                                                  aopGet (AOP (IC_RIGHT (ic)), 0),
+                                                  aopGet (AOP (IC_LEFT (ic)), 0));
+                                }
+                                else {
+                                        MOVR0 (aopGet (AOP (IC_LEFT (ic)), 0));
+                                        emitcode (bopnames[bitop], "r0,%s",
+                                                  aopGet (AOP (IC_RIGHT (ic)), 0));
+                                }
+                                lbl = newiTempLabel (NULL);
+                                if (IC_TRUE (ifx)) {
+                                        emitcode ("breq", "L%05d", lbl->key);
+                                        emitcode ("rjmp", "L%05d",
+                                                  IC_TRUE (ifx)->key);
+                                }
+                                else {
+                                        emitcode ("brne", "L%05d", lbl->key);
+                                        emitcode ("rjmp", "L%05d",
+                                                  IC_FALSE (ifx)->key);
+                                }
+                                emitcode ("", "L%05d:", lbl->key);
+                        }
+                        else if (size == 2) {
+                                emitcode ("mov", "r24,%s",
+                                          aopGet (AOP (IC_LEFT (ic)), 0));
+                                emitcode ("mov", "r25,%s",
+                                          aopGet (AOP (IC_LEFT (ic)), 1));
+                                emitcode (bopnames[bitop], "r24,%s",
+                                          aopGet (AOP (IC_RIGHT (ic)), 0));
+                                emitcode (bopnames[bitop], "r25,%s",
+                                          aopGet (AOP (IC_RIGHT (ic)), 1));
+                                emitcode ("sbiw", "r24,0");
+                                lbl = newiTempLabel (NULL);
+                                if (IC_TRUE (ifx)) {
+                                        emitcode ("breq", "L%05d", lbl->key);
+                                        emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+                                }
+                                else {
+                                        emitcode ("brne", "L%05d", lbl->key);
+                                        emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
+                                }
+                                emitcode ("", "L%05d:", lbl->key);
+                        }
+                        else {
+                                lbl = newiTempLabel (NULL);
+                                lbl1 = newiTempLabel (NULL);
+                                while (size--) {
+                                        if (eh) {
+                                                emitcode (bopnames[bitop], "%s,%s",
+                                                          aopGet (AOP (IC_LEFT (ic)), offset),
+                                                          aopGet (AOP (IC_RIGHT (ic)), offset));
+                                        }
+                                        else if (reh) {
+                                                emitcode (bopnames[bitop], "%s,%s",
+                                                          aopGet (AOP (IC_RIGHT (ic)), offset),
+                                                          aopGet (AOP (IC_LEFT (ic)), offset));
+                                        }
+                                        else {
+                                                MOVR0 (aopGet (AOP (IC_LEFT (ic)), offset));
+                                                emitcode (bopnames[bitop], "r0,%s",
+                                                          aopGet (AOP (IC_RIGHT (ic)), offset));
+                                        }
+                                        emitcode ("brne", "L%05d", lbl->key);
+                                        offset++;
+                                }
+                                /* all are zero */
+                                if (IC_FALSE (ifx))
+                                        emitcode ("rjmp", "L%05d", IC_FALSE (ifx)->key);
+                                else
+                                        emitcode ("rjmp", "L%05d", lbl1->key);
+                                emitcode ("", "L%05d:", lbl->key);
+                                /* not zero */
+                                if (IC_TRUE (ifx))
+                                        emitcode ("rjmp", "L%05d", IC_TRUE (ifx)->key);
+                                emitcode ("", "L%05d:", lbl1->key);
 
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);            
-}
+                        }
+                }
+                goto release;
+        }
 
-/*-----------------------------------------------------------------*/
-/* 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;
+        /* result needs to go a register */
+        samerl = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)));
+        samerr = sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)));
+        while (size--) {
+                if (AOP_TYPE (right) == AOP_LIT) {
+                        unsigned int lit =
+                                (int) ulFromVal (AOP (right)->aopu.
+                                                    aop_lit);
+                        if (((lit >> (8 * offset)) & 0xff) == 0) {
+                                if (bitop == AVR_AND) {
+                                        aopPut (AOP (result), zero, offset++);
+                                        continue;
+                                }
+                                else if (bitop == AVR_OR) {
+                                        if (!samerl)
+                                                aopPut (AOP (result),
+                                                        aopGet (AOP (left),
+                                                                offset),
+                                                        offset);
+                                        offset++;
+                                        continue;
+                                }
+                        }
+                }
+                if (samerl) {
+                        if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT &&
+                            AOP_ISHIGHREG(AOP(IC_LEFT(ic)),offset) &&
+                            (bitop == AVR_AND || bitop == AVR_OR)) {
+                                emitcode (bopnames_lit[bitop], "%s,%s(%d)",
+                                          aopGet (AOP (IC_LEFT (ic)), offset),
+                                          larray[offset],
+                                          (int) ulFromVal (AOP (right)-> aopu.aop_lit));
+                        }
+                        else {
+                                emitcode (bopnames[bitop], "%s,%s",
+                                          aopGet (AOP (IC_LEFT (ic)), offset),
+                                          aopGet (AOP (IC_RIGHT (ic)), offset));
+                        }
+                }
+                else if (samerr) {
+                        emitcode (bopnames[bitop], "%s,%s",
+                                  aopGet (AOP (IC_RIGHT (ic)), offset),
+                                  aopGet (AOP (IC_LEFT (ic)), offset));
+                }
+                else {
+                        aopPut (AOP (IC_RESULT (ic)),
+                                aopGet (AOP (IC_LEFT (ic)), offset), offset);
+                        emitcode (bopnames[bitop],
+                                  aopGet (AOP (IC_RESULT (ic)), offset),
+                                  aopGet (AOP (IC_RIGHT (ic)), offset));
+                }
+                offset++;
+        }
+      release:
+        freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+        freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* continueIfTrue -                                                */
+/* genAnd  - code for and                                          */
 /*-----------------------------------------------------------------*/
-static void continueIfTrue (iCode *ic)
+static void
+genAnd (iCode * ic, iCode * ifx)
 {
-    if(IC_TRUE(ic))
-        emitcode("ljmp","%05d$",IC_TRUE(ic)->key+100);
-    ic->generated = 1;
+        genBitWise (ic, ifx, AVR_AND);
 }
 
 /*-----------------------------------------------------------------*/
-/* jmpIfTrue -                                                     */
+/* genOr  - code for or                                            */
 /*-----------------------------------------------------------------*/
-static void jumpIfTrue (iCode *ic)
+static void
+genOr (iCode * ic, iCode * ifx)
 {
-    if(!IC_TRUE(ic))
-        emitcode("ljmp","%05d$",IC_FALSE(ic)->key+100);
-    ic->generated = 1;
+        genBitWise (ic, ifx, AVR_OR);
 }
 
 /*-----------------------------------------------------------------*/
-/* jmpTrueOrFalse -                                                */
+/* genXor - code for xclusive or                                   */
 /*-----------------------------------------------------------------*/
-static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
+static void
+genXor (iCode * ic, iCode * ifx)
 {
-    // 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;
+        genBitWise (ic, ifx, AVR_XOR);
 }
 
 /*-----------------------------------------------------------------*/
-/* genAnd  - code for and                                          */
+/* genInline - write the inline code out                           */
 /*-----------------------------------------------------------------*/
-static void genAnd (iCode *ic, iCode *ifx)
+static void
+genInline (iCode * ic)
 {
-    operand *left, *right, *result;
-    int size, offset=0;  
-    unsigned long lit = 0L;
-    int bytelit = 0;
-    char buffer[10];
-
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
-
-#ifdef DEBUG_TYPE
-    emitcode("","; Type res[%d] = l[%d]&r[%d]",
-             AOP_TYPE(result),
-             AOP_TYPE(left), AOP_TYPE(right));
-    emitcode("","; Size res[%d] = l[%d]&r[%d]",
-             AOP_SIZE(result),
-             AOP_SIZE(left), AOP_SIZE(right));
-#endif
+  char *buffer, *bp, *bp1;
+  bool inComment = FALSE;
 
-    /* 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;
-    }
+  _G.inLine += (!options.asmpeep);
 
-    /* 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 ;
-    }
+  buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
 
-    // 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 ;
+  /* emit each line as a code */
+  while (*bp)
+    {
+      switch (*bp)
+        {
+        case ';':
+          inComment = TRUE;
+          ++bp;
+          break;
+
+        case '\n':
+          inComment = FALSE;
+          *bp++ = '\0';
+          emitcode (bp1, "");
+          bp1 = bp;
+          break;
+
+        default:
+          /* Add \n for labels, not dirs such as c:\mydir */
+          if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
+            {
+              ++bp;
+              *bp = '\0';
+              ++bp;
+              emitcode (bp1, "");
+              bp1 = bp;
             }
+          else
+            ++bp;
+          break;
         }
-        outBitC(result);
-        goto release ;
     }
+    if (bp1 != bp)
+      emitcode (bp1, "");
 
-    /* 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);
-           }
-       }
-    }
+    Safe_free (buffer);
 
-release :
-    freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-    freeAsmop(result,NULL,ic,TRUE);     
+    _G.inLine -= (!options.asmpeep);
 }
 
 /*-----------------------------------------------------------------*/
-/* genOr  - code for or                                            */
+/* genRotC - rotate right/left with carry , lr = 1 rotate right    */
 /*-----------------------------------------------------------------*/
-static void genOr (iCode *ic, iCode *ifx)
+static void
+genRotC (iCode * ic, int lr)
 {
-    operand *left, *right, *result;
-    int size, offset=0;
-    unsigned long lit = 0L;
-
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
-
-#ifdef DEBUG_TYPE
-    emitcode("","; Type res[%d] = l[%d]&r[%d]",
-             AOP_TYPE(result),
-             AOP_TYPE(left), AOP_TYPE(right));
-    emitcode("","; Size res[%d] = l[%d]&r[%d]",
-             AOP_SIZE(result),
-             AOP_SIZE(left), AOP_SIZE(right));
-#endif
-
-    /* if left is a literal & right is not then exchange them */
-    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
-       AOP_NEEDSACC(left)) {
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
+        operand *left, *result;
+        int size, offset = 0;
 
-    /* if result = right then exchange them */
-    if(sameRegs(AOP(result),AOP(right))){
-        operand *tmp = right ;
-        right = left;
-        left = tmp;
-    }
+        /* rotate right with carry */
+        left = IC_LEFT (ic);
+        result = IC_RESULT (ic);
+        aopOp (left, ic, FALSE);
+        aopOp (result, ic, FALSE);
 
-    /* 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);
+        /* move it to the result */
+        size = AOP_SIZE (result);
+        if (!sameRegs (AOP (left), AOP (result))) {
+                offset = 0;
+                while (size--) {
+                        aopPut (AOP (result),
+                                aopGet (AOP (left), offset), offset);
+                        offset++;
                 }
-            }
-        }
-        // 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));
-               }
-            }
+                size = AOP_SIZE (result);
         }
-    } 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;
-
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
-
-#ifdef DEBUG_TYPE
-    emitcode("","; Type res[%d] = l[%d]&r[%d]",
-             AOP_TYPE(result),
-             AOP_TYPE(left), AOP_TYPE(right));
-    emitcode("","; Size res[%d] = l[%d]&r[%d]",
-             AOP_SIZE(result),
-             AOP_SIZE(left), AOP_SIZE(right));
-#endif
-
-    /* if left is a literal & right is not ||
-       if left needs acc & right does not */
-    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
-       (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");
-                    }
-                }
-            }
+        if (lr)
+                offset = size - 1;
+        else
+                offset = 0;
 
-        } 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 ;
-    }
+        CLRC;
+        emitcode ("sbrc", "%s,%d", aopGet (AOP (result), offset),
+                  (lr ? 0 : 7));
+        emitcode ("sec", "");
 
-    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;
+        while (size--) {
+                emitcode ((lr ? "ror" : "rol"), "%s",
+                          aopGet (AOP (result), offset));
+                if (lr)
+                        offset--;
                 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));
-               }
-            }
+                        offset++;
         }
-    } 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;
-    
-    _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);
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
 /* genRRC - rotate right with carry                                */
 /*-----------------------------------------------------------------*/
-static void genRRC (iCode *ic)
+static void
+genRRC (iCode * ic)
 {
-    operand *left , *result ;
-    int size, offset = 0;
-    char *l;    
-
-    /* rotate right with carry */
-    left = IC_LEFT(ic);
-    result=IC_RESULT(ic);
-    aopOp (left,ic,FALSE);
-    aopOp (result,ic,FALSE);
-
-    /* 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);
+        genRotC (ic, 1);
 }
 
 /*-----------------------------------------------------------------*/
 /* genRLC - generate code for rotate left with carry               */
 /*-----------------------------------------------------------------*/
-static void genRLC (iCode *ic)
-{    
-    operand *left , *result ;
-    int size, offset = 0;
-    char *l;    
-
-    /* rotate right with carry */
-    left = IC_LEFT(ic);
-    result=IC_RESULT(ic);
-    aopOp (left,ic,FALSE);
-    aopOp (result,ic,FALSE);
-
-    /* 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);
+static void
+genRLC (iCode * ic)
+{
+        genRotC (ic, 0);
 }
 
 /*-----------------------------------------------------------------*/
 /* genGetHbit - generates code get highest order bit               */
 /*-----------------------------------------------------------------*/
-static void genGetHbit (iCode *ic)
+static void
+genGetHbit (iCode * ic)
 {
-    operand *left, *result;
-    left = IC_LEFT(ic);
-    result=IC_RESULT(ic);
-    aopOp (left,ic,FALSE);
-    aopOp (result,ic,FALSE);
-
-    /* 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);
-    }
-
+        operand *left, *result;
+        int size, offset;
 
-    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;
-    }
-}
+        left = IC_LEFT (ic);
+        result = IC_RESULT (ic);
+        aopOp (left, ic, FALSE);
+        aopOp (result, ic, FALSE);
 
-/*-----------------------------------------------------------------*/
-/* 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]);
+        size = AOP_SIZE (result);
+        if (!sameRegs (AOP (left), AOP (result))) {
+                emitcode ("clr", "%s", aopGet (AOP (result), size - 1));
+                emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
+                emitcode ("subi", "%s,<(-1)",
+                          aopGet (AOP (result), size - 1));
         }
-    }
-}
-
-/*-----------------------------------------------------------------*/
-/* 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]);
+        else {
+                emitcode ("clr", "r0");
+                emitcode ("sbrc", "%s,7", aopGet (AOP (left), size - 1));
+                emitcode ("subi", "r0,<(-1)");
+                aopPut (AOP (result), "r0", 0);
         }
-    }
-}
-
-/*-----------------------------------------------------------------*/
-/* 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);
+        offset = 1;
+        size--;
+        while (size--) {
+                emitcode ("clr", aopGet (AOP (result), offset++));
         }
-    }
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* shiftR1Left2Result - shift right one byte from left to result   */
+/* genShiftLeftLit - shift left by a known amount                  */
 /*-----------------------------------------------------------------*/
-static void shiftR1Left2Result (operand *left, int offl,
-                                operand *result, int offr,
-                                int shCount, int sign)
+static void
+genShiftLeftLit (iCode * ic)
 {
-    MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
-    /* shift right accumulator */
-    if(sign)
-        AccSRsh(shCount);
-    else
-        AccRsh(shCount);
-    aopPut(AOP(result),"a",offr);
-}
+        operand *left, *right, *result;
+        int size, shCount, offset = 0;
+        int lByteZ = 0;
 
-/*-----------------------------------------------------------------*/
-/* 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);
-}
+        right = IC_RIGHT (ic);
+        left = IC_LEFT (ic);
+        result = IC_RESULT (ic);
 
-/*-----------------------------------------------------------------*/
-/* 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);
+        aopOp (left, ic, FALSE);
+        aopOp (result, ic, FALSE);
+        size = AOP_SIZE (result);
+        shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
 
-        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);
+        if (shCount > (size * 8 - 1)) {
+                while (size--)
+                        aopPut (AOP (result), zero, offset++);
+                goto release;
+        }
+        switch (size) {
+        case 1:
+                if (!sameRegs (AOP (left), AOP (result)))
+                        aopPut (AOP (result), aopGet (AOP (left), 0), 0);
+                if (shCount >= 4) {
+                        if (AOP_ISHIGHREG(AOP(result),0)) {
+                                emitcode ("swap", "%s", aopGet (AOP (result), 0));
+                                emitcode ("andi", "%s,0xf0");
+                        } else {
+                                emitcode ("ldi","r24,0xf0");
+                                emitcode ("swap", "%s", aopGet (AOP (result), 0));
+                                emitcode ("and", "%s,r24");
+                        }
+                        shCount -= 4;
+                }
+                if (shCount == 1) {
+                        emitcode ("add", "%s,%s", aopGet (AOP (result), 0),
+                                  aopGet (AOP (result), 0));
+                        shCount--;
+                }
+                while (shCount--)
+                        emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+                break;
+        case 2:
+                if (shCount >= 12) {
+                        aopPut (AOP (result), aopGet (AOP (left), 0), 1);
+                        aopPut (AOP (result), zero, 0);
+                        emitcode ("swap", "%s", aopGet (AOP (result), 1));
+                        if (AOP_ISHIGHREG(AOP(result),1)) {
+                                emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
+                        } else {
+                                emitcode ("ldi","r24,0xf0");
+                                emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
+                        }
+                        shCount -= 12;
+                        lByteZ = 1;
+                }
+                if (shCount >= 8) {
+                        aopPut (AOP (result), aopGet (AOP (left), 0), 1);
+                        aopPut (AOP (result), zero, 0);
+                        shCount -= 8;
+                        lByteZ = 1;
+                }
+                if (shCount >= 4) {
+                        shCount -= 4;
+                        if (!sameRegs (AOP (left), AOP (result))) {
+                                aopPut (AOP (result), aopGet (AOP (left), 0),
+                                        0);
+                                aopPut (AOP (result), aopGet (AOP (left), 1),
+                                        1);
+                        }
+                        emitcode ("mov", "r24,%s", aopGet (AOP (result), 0));
+                        emitcode ("andi", "r24,0x0f");
+                        if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
+                                emitcode("ldi","r25,0xf0");
+                        }
+                        emitcode ("swap", "%s", aopGet (AOP (result), 0));
+                        if (AOP_ISHIGHREG(AOP(result),0)) {
+                                emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 0));
+                        } else {
+                                emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
+                        }
+                        emitcode ("swap", "%s", aopGet (AOP (result), 1));
+                        if (AOP_ISHIGHREG(AOP(result),1)) {
+                                emitcode ("andi", "%s,0xf0", aopGet (AOP (result), 1));
+                        } else {
+                                emitcode ("and", "%s,r25", aopGet (AOP (result), 1));
+                        }
+                        emitcode ("or", "%s,r24", aopGet (AOP (result), 1));
+                        while (shCount--) {
+                                emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+                                emitcode ("rol", "%s", aopGet (AOP (result), 1));
+                        }
+                }
+                if (!lByteZ && !sameRegs (AOP (result), AOP (left))
+                    && shCount) {
+                        offset = 0;
+                        while (size--) {
+                                aopPut (AOP (result),
+                                        aopGet (AOP (left), offset), offset);
+                                offset++;
+                        }
+                }
+                while (shCount--) {
+                        if (lByteZ) {
+                                emitcode ("lsl", "%s", aopGet (AOP (result), 1));
+                        }
+                        else {
+                                emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+                                emitcode ("rol", "%s", aopGet (AOP (result), 1));
+                        }
+                }
+                break;
+        case 3:
+                assert ("shifting generic pointer ?\n");
+                break;
+        case 4:
+                /* 32 bits we do only byte boundaries */
+                if (shCount >= 24) {
+                        aopPut (AOP (result), aopGet (AOP (left), 0), 3);
+                        aopPut (AOP (result), zero, 2);
+                        aopPut (AOP (result), zero, 1);
+                        aopPut (AOP (result), zero, 0);
+                        lByteZ = 3;
+                        shCount -= 24;
+                }
+                if (shCount >= 16) {
+                        aopPut (AOP (result), aopGet (AOP (left), 0), 3);
+                        aopPut (AOP (result), aopGet (AOP (left), 1), 2);
+                        aopPut (AOP (result), zero, 1);
+                        aopPut (AOP (result), zero, 0);
+                        lByteZ = 2;
+                        shCount -= 16;
+                }
+                if (shCount >= 8) {
+                        aopPut (AOP (result), aopGet (AOP (left), 0), 3);
+                        aopPut (AOP (result), aopGet (AOP (left), 1), 2);
+                        aopPut (AOP (result), aopGet (AOP (left), 2), 1);
+                        aopPut (AOP (result), zero, 0);
+                        shCount -= 8;
+                        lByteZ = 1;
+                }
+                if (!lByteZ && !sameRegs (AOP (left), AOP (right))) {
+                        offset = 0;
+                        while (size--) {
+                                aopPut (AOP (result),
+                                        aopGet (AOP (left), offset), offset);
+                                offset++;
+                        }
+                        offset = 0;
+                        size = AOP_SIZE (result);
+                }
+                if (shCount) {
+                        switch (lByteZ) {
+                        case 0:
+                                while (shCount--) {
+                                        emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+                                        emitcode ("rol", "%s", aopGet (AOP (result), 1));
+                                        emitcode ("rol", "%s", aopGet (AOP (result), 2));
+                                        emitcode ("rol", "%s", aopGet (AOP (result), 3));
+                                }
+                                break;
+                        case 1:
+                                while (shCount--) {
+                                        emitcode ("lsl", "%s", aopGet (AOP (result), 1));
+                                        emitcode ("rol", "%s", aopGet (AOP (result), 2));
+                                        emitcode ("rol", "%s", aopGet (AOP (result), 3));
+                                }
+                                break;
+                        case 2:
+                                while (shCount--) {
+                                        emitcode ("lsl", "%s", aopGet (AOP (result), 2));
+                                        emitcode ("rol", "%s", aopGet (AOP (result), 3));
+                                }
+                                break;
+                        case 3:
+                                while (shCount--) {
+                                        emitcode ("lsl", "%s", aopGet (AOP (result), 3));
+                                }
+                                break;
+                        }
                 }
-            }
         }
-    }
-}
 
-/*-----------------------------------------------------------------*/
-/* 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);
+      release:
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (right, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
+/* genLeftShift - generates code for left shifting                 */
 /*-----------------------------------------------------------------*/
-static void AccAXLrl1 (char *x)
+static void
+genLeftShift (iCode * ic)
 {
-    emitcode("xch","a,%s",x);
-    emitcode("rlc","a");
-    emitcode("xch","a,%s",x);
-    emitcode("rlc","a");
-}
+        operand *left, *right, *result;
+        int size, offset;
+        symbol *tlbl;
 
-/*-----------------------------------------------------------------*/
-/* 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");
-}
+        right = IC_RIGHT (ic);
+        left = IC_LEFT (ic);
+        result = IC_RESULT (ic);
 
-/*-----------------------------------------------------------------*/
-/* 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;
-    }
-}
+        aopOp (right, ic, FALSE);
 
-/*-----------------------------------------------------------------*/
-/* 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;
-    }
-}
+        if (AOP_TYPE (right) == AOP_LIT) {
+                genShiftLeftLit (ic);
+                return;
+        }
 
-/*-----------------------------------------------------------------*/
-/* 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;
-    }
+        /* unknown count */
+        aopOp (left, ic, FALSE);
+        aopOp (result, ic, FALSE);
+        size = AOP_SIZE (result);
+        offset = 0;
+        if (AOP_SIZE (right) > 1) {
+                if (isRegPair (AOP (right))) {
+                        emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
+                }
+                else {
+                        emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
+                        emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
+                }
+        }
+        else {
+                emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
+        }
+        if (!sameRegs (AOP (left), AOP (result))) {
+                while (size--) {
+                        aopPut (AOP (result), aopGet (AOP (left), offset),
+                                offset);
+                        offset++;
+                }
+                size = AOP_SIZE (result);
+        }
+        tlbl = newiTempLabel (NULL);
+        emitcode ("", "L%05d:", tlbl->key);
+        offset = 0;
+        while (size--) {
+                if (offset)
+                        emitcode ("rol", "%s", aopGet (AOP (result), offset));
+                else
+                        emitcode ("lsl", "%s", aopGet (AOP (result), 0));
+                offset++;
+        }
+        if (AOP_SIZE (right) > 1)
+                emitcode ("sbiw", "r24,1");
+        else
+                emitcode ("dec", "r24");
+        emitcode ("brne", "L%05d", tlbl->key);
+
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (right, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* shiftL2Left2Result - shift left two bytes from left to result   */
+/* genShiftRightLit - generate for right shift with known count    */
 /*-----------------------------------------------------------------*/
-static void shiftL2Left2Result (operand *left, int offl,
-                                operand *result, int offr, int shCount)
+static void
+genShiftRightLit (iCode * ic)
 {
-    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);
-}
+        operand *left = IC_LEFT (ic)
+        , *right = IC_RIGHT (ic)
+        , *result = IC_RESULT (ic);
+        int size, shCount, offset = 0;
+        int hByteZ = 0;
+        sym_link *letype = getSpec (operandType (left));
+        int sign = !SPEC_USIGN (letype);
 
+        right = IC_RIGHT (ic);
+        left = IC_LEFT (ic);
+        result = IC_RESULT (ic);
 
-/*-----------------------------------------------------------------*/
-/* 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);
-}
+        aopOp (left, ic, FALSE);
+        aopOp (result, ic, FALSE);
+        size = AOP_SIZE (result);
+        shCount = (int) ulFromVal (AOP (right)->aopu.aop_lit);
 
-/*-----------------------------------------------------------------*/
-/* 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);
+        /* if signed then give up and use a loop to shift */
+        if (sign) {
+                symbol *tlbl;
+                if (!sameRegs (AOP (left), AOP (result))) {
+                        while (size--) {
+                                aopPut (AOP (result),
+                                        aopGet (AOP (left), offset), offset);
+                                offset++;
+                        }
+                        size = AOP_SIZE (result);
+                        offset = 0;
+                }
+                /* be as economical as possible */
+                if (shCount <= 4) {
+                        while (shCount--) {
+                                size = AOP_SIZE (result);
+                                offset = size - 1;
+                                while (size--) {
+                                        /* highest order byte */
+                                        if (offset == (AOP_SIZE(result)-1))
+                                                emitcode ("asr", "%s", aopGet (AOP (result), offset));
+                                        else
+                                                emitcode ("ror", "%s", aopGet (AOP (result), offset));
+                                        offset--;
+                                }
+                        }
+                }
+                else {
+                        emitcode ("ldi", "r24,<(%d)", shCount);
+                        tlbl = newiTempLabel (NULL);
+                        emitcode ("", "L%05d:", tlbl->key);
+                        offset = size - 1;
+                        while (size--) {
+                                if (offset == (AOP_SIZE(result) - 1))
+                                        emitcode ("asr", "%s", aopGet (AOP (result), offset));
+                                else
+                                        emitcode ("ror", "%s", aopGet (AOP (result), offset));
+                                offset--;
+                        }
+                        emitcode ("dec", "r24");
+                        emitcode ("brne", "L%05d", tlbl->key);
+                }
+                goto release;
+        }
+        if (shCount > (size * 8 - 1)) {
+                while (size--)
+                        aopPut (AOP (result), zero, offset++);
+                goto release;
+        }
+        /* for unsigned we can much more efficient */
+        switch (size) {
+        case 1:
+                if (!sameRegs (AOP (left), AOP (result)))
+                        aopPut (AOP (result), aopGet (AOP (left), 0), 0);
+                if (shCount >= 4) {
+                        emitcode ("swap", "%s", aopGet (AOP (result), 0));
+                        if (AOP_ISHIGHREG(AOP(result),0)) {
+                                emitcode ("andi", "%s,0x0f",aopGet(AOP(result),0));
+                        } else {
+                                emitcode ("ldi","r24,0x0f");
+                                emitcode ("and", "%s,r24",aopGet(AOP(result),0));
+                        }
+                        shCount -= 4;
+                }
+                while (shCount--)
+                        emitcode ("lsr", "%s", aopGet (AOP (result), 0));
+                break;
+        case 2:
+                if (shCount >= 12) {
+                        aopPut (AOP (result), aopGet (AOP (left), 1), 0);
+                        aopPut (AOP (result), zero, 1);
+                        emitcode ("swap", "%s", aopGet (AOP (result), 0));
+                        if (AOP_ISHIGHREG(AOP(result),0)) {
+                                emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
+                        } else {
+                                emitcode ("ldi","r24,0x0f");
+                                emitcode ("and", "%s,r24",aopGet(AOP(result),0));
+                        }
+                        shCount -= 12;
+                        hByteZ = 1;
+                }
+                if (shCount >= 8) {
+                        aopPut (AOP (result), aopGet (AOP (left), 1), 0);
+                        aopPut (AOP (result), zero, 1);
+                        shCount -= 8;
+                        hByteZ = 1;
+                }
+                if (shCount >= 4) {
+                        shCount -= 4;
+                        if (!sameRegs (AOP (left), AOP (result))) {
+                                aopPut (AOP (result), aopGet (AOP (left), 0), 0);
+                                aopPut (AOP (result), aopGet (AOP (left), 1), 1);
+                        }
+                        if (!(AOP_ISHIGHREG(AOP(result),0) && AOP_ISHIGHREG(AOP(result),1))) {
+                                emitcode("ldi","r25,0x0f");
+                        }
+                        emitcode ("mov", "r24,%s", aopGet (AOP (result), 1));
+                        emitcode ("andi", "r24,0xf0");
+                        emitcode ("swap", "%s", aopGet (AOP (result), 0));
+                        if (AOP_ISHIGHREG(AOP(result),0)) {
+                                emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 0));
+                        } else {
+                                emitcode ("and", "%s,r25", aopGet (AOP (result), 0));
+                        }
+                        emitcode ("or", "%s,r24", aopGet (AOP (result), 0));
+                        emitcode ("swap", "%s", aopGet (AOP (result), 1));
+                        if (AOP_ISHIGHREG(AOP(result),1)) {
+                                emitcode ("andi", "%s,0x0f", aopGet (AOP (result), 1));
+                        } else {
+                                emitcode ("and", "%s,r24", aopGet (AOP (result), 1));
+                        }
+                        while (shCount--) {
+                                emitcode ("lsr", "%s", aopGet (AOP (result), 1));
+                                emitcode ("ror", "%s", aopGet (AOP (result), 0));
+                        }
+
+                }
+                if (!hByteZ && !sameRegs (AOP (result), AOP (left))
+                    && shCount) {
+                        offset = 0;
+                        while (size--) {
+                                aopPut (AOP (result), aopGet (AOP (left), offset), offset);
+                                offset++;
+                        }
+                }
+                while (shCount--) {
+                        if (hByteZ) {
+                                emitcode ("lsr", "%s", aopGet (AOP (result), 0));
+                        }
+                        else {
+                                emitcode ("lsr", "%s", aopGet (AOP (result), 1));
+                                emitcode ("ror", "%s", aopGet (AOP (result), 0));
+                        }
+                }
+                break;
+
+        case 3:
+                assert ("shifting generic pointer ?\n");
+                break;
+        case 4:
+                /* 32 bits we do only byte boundaries */
+                if (shCount >= 24) {
+                        aopPut (AOP (result), aopGet (AOP (left), 3), 0);
+                        aopPut (AOP (result), zero, 1);
+                        aopPut (AOP (result), zero, 2);
+                        aopPut (AOP (result), zero, 3);
+                        hByteZ = 3;
+                        shCount -= 24;
+                }
+                if (shCount >= 16) {
+                        aopPut (AOP (result), aopGet (AOP (left), 3), 1);
+                        aopPut (AOP (result), aopGet (AOP (left), 2), 0);
+                        aopPut (AOP (result), zero, 2);
+                        aopPut (AOP (result), zero, 3);
+                        hByteZ = 2;
+                        shCount -= 16;
+                }
+                if (shCount >= 8) {
+                        aopPut (AOP (result), aopGet (AOP (left), 1), 0);
+                        aopPut (AOP (result), aopGet (AOP (left), 2), 1);
+                        aopPut (AOP (result), aopGet (AOP (left), 3), 2);
+                        aopPut (AOP (result), zero, 3);
+                        shCount -= 8;
+                        hByteZ = 1;
+                }
+                if (!hByteZ && !sameRegs (AOP (left), AOP (right))) {
+                        offset = 0;
+                        while (size--) {
+                                aopPut (AOP (result),
+                                        aopGet (AOP (left), offset), offset);
+                                offset++;
+                        }
+                        offset = 0;
+                        size = AOP_SIZE (result);
+                }
+                if (shCount) {
+                        switch (hByteZ) {
+                        case 0:
+                                while (shCount--) {
+                                        emitcode ("lsr", "%s", aopGet (AOP (result), 3));
+                                        emitcode ("ror", "%s", aopGet (AOP (result), 2));
+                                        emitcode ("ror", "%s", aopGet (AOP (result), 1));
+                                        emitcode ("ror", "%s", aopGet (AOP (result), 0));
+                                }
+                                break;
+                        case 1:
+                                while (shCount--) {
+                                        emitcode ("lsr", "%s", aopGet (AOP (result), 2));
+                                        emitcode ("ror", "%s", aopGet (AOP (result), 1));
+                                        emitcode ("ror", "%s", aopGet (AOP (result), 0));
+                                }
+                                break;
+                        case 2:
+                                while (shCount--) {
+                                        emitcode ("lsr", "%s", aopGet (AOP (result), 1));
+                                        emitcode ("ror", "%s", aopGet (AOP (result), 0));
+                                }
+                                break;
+                        case 3:
+                                while (shCount--) {
+                                        emitcode ("lsr", "%s", aopGet (AOP (result), 0));
+                                }
+                                break;
+                        }
+                }
+        }
+      release:
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (right, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* shiftRLeftOrResult - shift right one byte from left,or to result*/
+/* genRightShift - generate code for right shifting                */
 /*-----------------------------------------------------------------*/
-static void shiftRLeftOrResult (operand *left, int offl,
-                                operand *result, int offr, int shCount)
+static void
+genRightShift (iCode * ic)
 {
-    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);
-}
+        operand *right, *left, *result;
+        sym_link *letype;
+        int size, offset;
+        int sign = 0, first = 1;
+        symbol *tlbl;
 
-/*-----------------------------------------------------------------*/
-/* genlshOne - left shift a one byte quantity by known count       */
-/*-----------------------------------------------------------------*/
-static void genlshOne (operand *result, operand *left, int shCount)
-{       
-    shiftL1Left2Result(left, LSB, result, LSB, shCount);
+        aopOp (right = IC_RIGHT (ic), ic, FALSE);
+
+        if (AOP_TYPE (right) == AOP_LIT) {
+                genShiftRightLit (ic);
+                return;
+        }
+        /* unknown count */
+        if (AOP_SIZE (right) > 1) {
+                if (isRegPair (AOP (right))) {
+                        emitcode ("movw", "r24,%s", aopGet (AOP (right), 0));
+                }
+                else {
+                        emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
+                        emitcode ("mov", "r25,%s", aopGet (AOP (right), 1));
+                }
+        }
+        else {
+                emitcode ("mov", "r24,%s", aopGet (AOP (right), 0));
+        }
+        aopOp (left = IC_LEFT (ic), ic, FALSE);
+        aopOp (result = IC_RESULT (ic), ic, FALSE);
+        size = AOP_SIZE (result);
+        tlbl = newiTempLabel (NULL);
+        emitcode ("", "L%05d:", tlbl->key);
+        offset = size - 1;
+        letype = getSpec (operandType (left));
+        sign = !SPEC_USIGN (letype);
+        if (!sameRegs (AOP (left), AOP (result))) {
+                while (size--) {
+                        aopPut (AOP (result), aopGet (AOP (left), offset), offset);
+                        offset++;
+                }
+                size = AOP_SIZE (result);
+        }
+        size = AOP_SIZE (result);
+        while (size--) {
+                if (first) {
+                        if (sign)
+                                emitcode ("asr", "%s", aopGet (AOP (result), offset));
+                        else
+                                emitcode ("lsr", "%s", aopGet (AOP (result), offset));
+                        first = 0;
+                }
+                else
+                        emitcode ("ror", "%s", aopGet (AOP (result), offset));
+                offset--;
+        }
+        if (AOP_SIZE (right) > 1)
+                emitcode ("sbiw", "r24,1");
+        else
+                emitcode ("dec", "r24");
+        emitcode ("brne", "L%05d", tlbl->key);
+
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genlshTwo - left shift two bytes by known amount != 0           */
+/* RRsh - shift right rn by known count                            */
 /*-----------------------------------------------------------------*/
-static void genlshTwo (operand *result,operand *left, int shCount)
+static void
+RRsh (int shCount,int reg)
 {
-    int size;
-    
-    size = getDataSize(result);
-
-    /* if shCount >= 8 */
-    if (shCount >= 8) {
-        shCount -= 8 ;
+        shCount &= 0x0007;      // shCount : 0..7
 
-        if (size > 1){
-            if (shCount)
-                shiftL1Left2Result(left, LSB, result, MSB16, shCount);
-            else 
-                movLeft2Result(left, LSB, result, MSB16, 0);
+        switch (shCount) {
+        case 0:
+                break;
+        case 1:
+                emitcode ("lsr", "r%d",reg);
+                break;
+        case 2:
+                emitcode ("lsr", "r%d",reg);
+                emitcode ("lsr", "r%d",reg);
+                break;
+        case 3:
+                emitcode ("swap", "r%d",reg);
+                emitcode ("lsl", "r%d",reg);
+                break;
+        case 4:
+                emitcode ("swap", "r%d",reg);
+                break;
+        case 5:
+                emitcode ("swap", "r%d",reg);
+                emitcode ("lsr", "r%d",reg);
+                break;
+        case 6:
+                emitcode ("swap","r%d",reg);
+                emitcode ("lsr", "r%d",reg);
+                emitcode ("lsr", "r%d",reg);
+                break;
+        case 7:
+                emitcode ("swap","r%d",reg);
+                emitcode ("lsr", "r%d",reg);
+                emitcode ("lsr", "r%d",reg);
+                emitcode ("lsr", "r%d",reg);
+                break;
         }
-        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                                             */
+/* RLsh - shift left rn by known count                             */
 /*-----------------------------------------------------------------*/
-static void shiftLLong (operand *left, operand *result, int offr )
+static void
+RLsh (int shCount, int reg)
 {
-    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);
-    }
+        shCount &= 0x0007;      // shCount : 0..7
 
-    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);       
+        switch (shCount) {
+        case 0:
+                break;
+        case 1:
+                emitcode ("lsl", "r%d",reg);
+                break;
+        case 2:
+                emitcode ("lsl", "r%d",reg);
+                emitcode ("lsl", "r%d",reg);
+                break;
+        case 3:
+                emitcode ("swap","r%d",reg);
+                emitcode ("lsr", "r%d",reg);
+                break;
+        case 4:
+                emitcode ("swap", "r%d",reg);
+                break;
+        case 5:
+                emitcode ("swap","r%d",reg);
+                emitcode ("lsl", "r%d",reg);
+                break;
+        case 6:
+                emitcode ("swap","r%d",reg);
+                emitcode ("lsl", "r%d",reg);
+                emitcode ("lsl", "r%d",reg);
+                break;
+        case 7:
+                emitcode ("swap","r%d",reg);
+                emitcode ("lsl", "r%d",reg);
+                emitcode ("lsl", "r%d",reg);
+                emitcode ("lsl", "r%d",reg);
+                break;
+        }
 }
 
 /*-----------------------------------------------------------------*/
-/* genlshFour - shift four byte by a known amount != 0             */
+/* genUnpackBits - generates code for unpacking bits               */
 /*-----------------------------------------------------------------*/
-static void genlshFour (operand *result, operand *left, int shCount)
+static void
+genUnpackBits (operand * result, char *rname, int ptype)
 {
-    int size;
+        int shCnt;
+        int rlen = 0;
+        sym_link *etype;
+        int offset = 0;
+        int rsize;
 
-    size = AOP_SIZE(result);
+        etype = getSpec (operandType (result));
+        rsize = getSize (operandType (result));
+        /* read the first byte  */
+        switch (ptype) {
 
-    /* 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;
-    }
+        case POINTER:
+        case IPOINTER:
+        case PPOINTER:
+        case FPOINTER:
+                emitcode ("ld", "r24,%s+", rname);
+                break;
 
-    /* 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);
-            }
+        case CPOINTER:
+                emitcode ("lpm", "r24,%s+", rname);
+                break;
+
+        case GPOINTER:
+                emitcode ("call","__gptrget_pi");
+                emitcode ("mov","r24,r0");
+                break;
         }
-    }
 
-    /* 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);
-    }
-}
+        rlen = SPEC_BLEN (etype);
 
-/*-----------------------------------------------------------------*/
-/* 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;
+        /* 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)) {
 
-    freeAsmop(right,NULL,ic,TRUE);
+                /* shift right acc */
+                RRsh (shCnt,24);
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+                emitcode ("andi", "r24,lo(0x%x)",
+                          ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
+                aopPut (AOP (result), "r24", offset++);
+                goto finish;
+        }
 
-    size = getSize(operandType(result));
+        /* bit field did not fit in a byte  */
+        aopPut (AOP (result), "r24", offset++);
 
-#if VIEW_SIZE
-    emitcode("; shift left ","result %d, left %d",size,
-             AOP_SIZE(left));
-#endif
+        while (1) {
 
-    /* I suppose that the left size >= result size */
-    if(shCount == 0){
-        while(size--){
-            movLeft2Result(left, size, result, size, 0);
-        }
-    }
+                switch (ptype) {
 
-    else if(shCount >= (size * 8))
-        while(size--)
-            aopPut(AOP(result),zero,size);
-    else{
-        switch (size) {
-            case 1:
-                genlshOne (result,left,shCount);
-                break;
+                case POINTER:
+                case IPOINTER:
+                case PPOINTER:
+                case FPOINTER:
+                        emitcode ("ld", "r24,%s+");
+                        break;
 
-            case 2:
-            case 3:
-                genlshTwo (result,left,shCount);
-                break;
+                case CPOINTER:
+                        emitcode ("lpm", "r24,%s+");
+                        break;
 
-            case 4:
-                genlshFour (result,left,shCount);
-                break;
-        }
-    }
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-}
+                case GPOINTER:
+                        emitcode ("call", "__gptrget_pi");
+                        break;
+                }
 
-/*-----------------------------------------------------------------*/
-/* genLeftShift - generates code for left shifting                 */
-/*-----------------------------------------------------------------*/
-static void genLeftShift (iCode *ic)
-{
-    operand *left,*right, *result;
-    int size, offset;
-    char *l;
-    symbol *tlbl , *tlbl1;
-
-    right = IC_RIGHT(ic);
-    left  = IC_LEFT(ic);
-    result = IC_RESULT(ic);
-
-    aopOp(right,ic,FALSE);
-
-    /* if the shift count is known then do it 
-    as efficiently as possible */
-    if (AOP_TYPE(right) == AOP_LIT) {
-        genLeftShiftLiteral (left,right,result,ic);
-        return ;
-    }
+                rlen -= 8;
+                /* if we are done */
+                if (rlen < 8)
+                        break;
 
-    /* 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);
-    aopOp(result,ic,FALSE);
-
-    /* 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))) {
+                aopPut (AOP (result), "r24", offset++);
 
-                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));
+        if (rlen) {
+                aopPut (AOP (result), "r24", offset++);
+        }
 
-    emitcode("","%05d$:",tlbl1->key+100);
-    emitcode("djnz","b,%05d$",tlbl->key+100);
-release:
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+      finish:
+        if (offset < rsize) {
+                rsize -= offset;
+                while (rsize--)
+                        aopPut (AOP (result), zero, offset++);
+        }
+        return;
 }
 
 /*-----------------------------------------------------------------*/
-/* genrshOne - right shift a one byte quantity by known count      */
+/* genDataPointerGet - generates code when ptr offset is known     */
 /*-----------------------------------------------------------------*/
-static void genrshOne (operand *result, operand *left,
-                       int shCount, int sign)
+static void
+genDataPointerGet (operand * left, operand * result, iCode * ic)
 {
-    shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
-}
+        char *l;
+        char buffer[256];
+        int size, offset = 0;
+        aopOp (result, ic, TRUE);
 
-/*-----------------------------------------------------------------*/
-/* genrshTwo - right shift two bytes by known amount != 0          */
-/*-----------------------------------------------------------------*/
-static void genrshTwo (operand *result,operand *left,
-                       int shCount, int sign)
-{
-    /* if shCount >= 8 */
-    if (shCount >= 8) {
-        shCount -= 8 ;
-        if (shCount)
-            shiftR1Left2Result(left, MSB16, result, LSB,
-                               shCount, sign);
-        else 
-            movLeft2Result(left, MSB16, result, LSB, sign);
-        addSign(result, MSB16, sign);
-    }
+        /* get the string representation of the name */
+        l = aopGet (AOP (left), 0);
+        size = AOP_SIZE (result);
+        while (size--) {
+                if (offset)
+                        sprintf (buffer, "(%s + %d)", l, offset);
+                else
+                        sprintf (buffer, "%s", l);
+                emitcode ("lds", "%s,%s", aopGet (AOP (result), offset++),
+                          buffer);
+        }
 
-    /*  1 <= shCount <= 7 */
-    else
-        shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* shiftRLong - shift right one long from left to result           */
-/* offl = LSB or MSB16                                             */
+/* genNearPointerGet - emitcode for near pointer fetch             */
 /*-----------------------------------------------------------------*/
-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);
-    }
-}
+static void
+genMemPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
+{
+        asmop *aop = NULL;
+        regs *preg = NULL;
+        int gotFreePtr = 0;
+        char *rname, *frname = NULL;
+        sym_link *rtype, *retype;
+        sym_link *ltype = operandType (left);
+
+        rtype = operandType (result);
+        retype = getSpec (rtype);
+
+        aopOp (left, ic, FALSE);
+
+        /* if left is rematerialisable and
+           result is not bit variable type and
+           the left is pointer to data space i.e
+           lower 128 bytes of space */
+        if (AOP_TYPE (left) == AOP_IMMD &&
+            !IS_BITVAR (retype) && DCL_TYPE (ltype) == POINTER) {
+                genDataPointerGet (left, result, ic);
+                return;
+        }
 
-/*-----------------------------------------------------------------*/
-/* genrshFour - shift four byte by a known amount != 0             */
-/*-----------------------------------------------------------------*/
-static void genrshFour (operand *result, operand *left,
-                        int shCount, int sign)
-{
-    /* 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);
+        /* 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, 0);
+                if (isRegPair (AOP (left) )) {
+                        emitcode ("movw", "%s,%s",
+                                  aop->aopu.aop_ptr->name,
+                                  aopGet(AOP(left),0));
+                } else {
+                        emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
+                                  aopGet (AOP (left), 0));
+                        emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
+                                  aopGet (AOP (left), 1));
+                }
+                gotFreePtr = 1;
         }
-    }
-    else{   /* 1 <= shCount <= 7 */
-        if(shCount <= 2){
-            shiftRLong(left, LSB, result, sign);
-            if(shCount == 2)
-                shiftRLong(result, LSB, result, sign);
+        else {
+                aop = AOP(left);
+                frname = aopGet(aop,0);
         }
-        else{
-            shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
-            shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
-            shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
+        if (AOP_ISX(aop)) {
+                rname = "X";
+        } else if (AOP_ISZ(aop)) {
+                rname = "Z";
+        } else {
+                werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                        "pointer not in correct register");
+                exit (0);
         }
-    }
-}
-
-/*-----------------------------------------------------------------*/
-/* 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;
-
-    freeAsmop(right,NULL,ic,TRUE);
-
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
-
-#if VIEW_SIZE
-    emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
-             AOP_SIZE(left));
-#endif
-
-    size = getDataSize(left);
-    /* test the LEFT size !!! */
 
-    /* I suppose that the left size >= result size */
-    if(shCount == 0){
-        size = getDataSize(result);
-        while(size--)
-            movLeft2Result(left, size, result, size, 0);
-    }
+        aopOp (result, ic, FALSE);
 
-    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;
+        /* 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 (size || pi) {
+                                emitcode ("ld","%s,%s+",aopGet(AOP(result),offset), rname);
+                        } else {
+                                emitcode ("ld","%s,%s",aopGet(AOP(result),offset), rname);
+                        }
+                }
+        }
 
-            case 2:
-                genrshTwo (result,left,shCount,sign);
-                break;
+        /* now some housekeeping stuff */
+        if (gotFreePtr) {
+                /* we had to allocate for this iCode */
+                if (pi) {
+                        if (isRegPair (AOP (left) )) {
+                                emitcode ("movw", "%s,%s",
+                                          aopGet (AOP(left),0),
+                                          aop->aopu.aop_ptr->name);
+                        } else {
+                                emitcode ("mov", "%s,%s",
+                                          aopGet (AOP (left), 0),
+                                          aop->aopu.aop_ptr->name);
+                                emitcode ("mov", "%s,%s",
+                                          aopGet (AOP (left), 1),
+                                          aop->aop_ptr2->name);
+                        }
+                }
+                freeAsmop (NULL, aop, ic, TRUE);
+        } else {
 
-            case 4:
-                genrshFour (result,left,shCount,sign);
-                break;
-            default :
-                break;
+                /* 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)) && !pi) {
+                        int size = AOP_SIZE (result) - 1;
+                        emitcode ("sbiw", "%s,%d",frname,size);
+                }
         }
 
-        freeAsmop(left,NULL,ic,TRUE);
-        freeAsmop(result,NULL,ic,TRUE);
-    }
+        /* done */
+        if (pi) pi->generated = 1;
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
+
 }
 
 /*-----------------------------------------------------------------*/
-/* genSignedRightShift - right shift of signed number              */
+/* genCodePointerGet - gget value from code space                  */
 /*-----------------------------------------------------------------*/
-static void genSignedRightShift (iCode *ic)
+static void
+genCodePointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
 {
-    operand *right, *left, *result;
-    int size, offset;
-    char *l;
-    symbol *tlbl, *tlbl1 ;
+        int size, offset;
+        sym_link *retype = getSpec (operandType (result));
+        asmop *aop = NULL;
+        int gotFreePtr = 0;
 
-    /* we do it the hard way put the shift count in b
-    and loop thru preserving the sign */
+        aopOp (left, ic, FALSE);
 
-    right = IC_RIGHT(ic);
-    left  = IC_LEFT(ic);
-    result = IC_RESULT(ic);
+        /* if the operand is already in Z register
+           then we do nothing else we move the value to Z register */
+        if (AOP_ISZ(AOP(left))) {
+                aop = AOP (left);
+        } else {
+                aop = newAsmop(0);
+                getFreePtr(ic,&aop,FALSE,TRUE);
+                if (isRegPair(AOP (left))) {
+                        emitcode ("movw","r30,%s",aopGet (AOP (left), 0));
+                } else {
+                        emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
+                        emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
+                }
+                gotFreePtr = 1;
+        }
 
-    aopOp(right,ic,FALSE);  
+        aopOp (result, ic, FALSE);
 
+        /* if bit then unpack */
+        if (IS_BITVAR (retype))
+                genUnpackBits (result, "Z", CPOINTER);
+        else {
+                size = AOP_SIZE (result);
+                offset = 0;
+
+                while (size--) {
+                        if (size || pi) {
+                                emitcode ("lpm","%s,Z+",aopGet(AOP(result),offset++));
+                        } else {
+                                emitcode ("lpm","%s,Z",aopGet(AOP(result),offset++));
+                        }
+                }
+        }
 
-    if ( AOP_TYPE(right) == AOP_LIT) {
-       genRightShiftLiteral (left,right,result,ic,1);
-       return ;
-    }
-        /* shift count is unknown then we have to form 
-       a loop get the loop count in B : Note: we take
-       only the lower order byte since shifting
-       more that 32 bits make no sense anyway, ( the
-       largest size of an object can be only 32 bits ) */  
-
-    emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-    emitcode("inc","b");
-    freeAsmop (right,NULL,ic,TRUE);
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
-
-    /* now move the left to the result if they are not the
-    same */
-    if (!sameRegs(AOP(left),AOP(result)) && 
-        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)) {
+        /* now some housekeeping stuff */
+        if (gotFreePtr) {
+                /* we had to allocate for this iCode */
+                if (pi) {
+                        if (isRegPair(AOP (left))) {
+                                emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
+                        } else {
+                                emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
+                                emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
+                        }
+                }
+                freeAsmop (NULL, aop, ic, TRUE);
+        } else {
 
-                emitcode("mov","a,%s",l);
-                aopPut(AOP(result),"a",offset);
-            } else
-                aopPut(AOP(result),l,offset);
-            offset++;
+                /* 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)) &&
+                    !pi) {
+                        int size = AOP_SIZE (result) - 1;
+                        emitcode ("sbiw", "r30,%d",size);
+                }
         }
-    }
-
-    /* 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);
+        /* done */
+        if (pi) pi->generated=1;
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 
-release:
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genRightShift - generate code for right shifting                */
+/* genGenPointerGet - gget value from generic pointer space        */
 /*-----------------------------------------------------------------*/
-static void genRightShift (iCode *ic)
+static void
+genGenPointerGet (operand * left, operand * result, iCode * ic, iCode *pi)
 {
-    operand *right, *left, *result;
-    link *retype ;
-    int size, offset;
-    char *l;
-    symbol *tlbl, *tlbl1 ;
-
-    /* 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 */
+        int size, offset;
+        int gotFreePtr = 0;
+        sym_link *retype = getSpec (operandType (result));
+        asmop *aop = NULL;
 
-    right = IC_RIGHT(ic);
-    left  = IC_LEFT(ic);
-    result = IC_RESULT(ic);
+        aopOp (left, ic, FALSE);
 
-    aopOp(right,ic,FALSE);
+        /* if the operand is already in dptr
+           then we do nothing else we move the value to dptr */
+        if (AOP_ISZ(AOP(left))) {
+                aop = AOP(left);
+        } else {
+                aop = newAsmop(0);
+                getFreePtr(ic,&aop,FALSE,TRUE);
+                if (isRegPair(AOP(left))) {
+                        emitcode ("movw", "r30,%s", aopGet (AOP (left), 0));
+                } else {
+                        emitcode ("mov", "r30,%s", aopGet (AOP (left), 0));
+                        emitcode ("mov", "r31,%s", aopGet (AOP (left), 1));
+                }
+                emitcode ("mov", "r24,%s", aopGet (AOP (left), 2));
+                gotFreePtr=1;
+        }
 
-    /* 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 ;
-    }
+        /* so Z register now contains the address */
 
-    /* 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);
-    aopOp(result,ic,FALSE);
-
-    /* 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)) {
+        aopOp (result, ic, FALSE);
 
-                emitcode("mov","a,%s",l);
-                aopPut(AOP(result),"a",offset);
-            } else
-                aopPut(AOP(result),l,offset);
-            offset++;
+        /* if bit then unpack */
+        if (IS_BITVAR (retype))
+                genUnpackBits (result, "Z", GPOINTER);
+        else {
+                size = AOP_SIZE (result);
+                offset = 0;
+
+                while (size--) {
+                        if (size || pi)
+                                emitcode ("call", "__gptrget_pi");
+                        else
+                                emitcode ("call", "__gptrget");
+                        aopPut (AOP (result), "r0", 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);
+        /* now some housekeeping stuff */
+        if (gotFreePtr) {
+                /* we had to allocate for this iCode */
+                if (pi) {
+                        if (isRegPair(AOP (left))) {
+                                emitcode ("movw","%s,r30",aopGet (AOP (left), 0));
+                        } else {
+                                emitcode ("mov", "%s,r30", aopGet (AOP (left), 0));
+                                emitcode ("mov", "%s,r31", aopGet (AOP (left), 1));
+                        }
+                }
+                freeAsmop (NULL, aop, ic, TRUE);
+        } else {
 
-release:
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+                /* 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)) &&
+                    !pi) {
+                        int size = AOP_SIZE (result) - 1;
+                        emitcode ("sbiw", "r30,%d",size);
+                }
+        }
+        if (pi) pi->generated=1;
+        freeAsmop (left, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genUnpackBits - generates code for unpacking bits               */
+/* genPointerGet - generate code for pointer get                   */
 /*-----------------------------------------------------------------*/
-static void genUnpackBits (operand *result, char *rname, int ptype)
-{    
-    int shCnt ;
-    int rlen = 0 ;
-    link *etype;
-    int offset = 0 ;
-
-    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))  {
+static void
+genPointerGet (iCode * ic, iCode *pi)
+{
+        operand *left, *result;
+        sym_link *type, *etype;
+        int p_type;
 
-        /* shift right acc */
-        AccRsh(shCnt);
+        left = IC_LEFT (ic);
+        result = IC_RESULT (ic);
 
-        emitcode("anl","a,#0x%02x",
-                 ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
-        aopPut(AOP(result),"a",offset);
-        return ;
-    }
+        /* 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));
 
-    /* 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);
-
-    /* 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++);
-    }
+        /* now that we have the pointer type we assign
+           the pointer values */
+        switch (p_type) {
 
-    freeAsmop(left,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
-}
+        case POINTER:
+        case IPOINTER:
+        case PPOINTER:
+        case FPOINTER:
+                genMemPointerGet (left, result, ic, pi);
+                break;
 
-/*-----------------------------------------------------------------*/
-/* 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);
-    
-    /* 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);
-    
-      /* 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);
-       }
-    }
+        case CPOINTER:
+                genCodePointerGet (left, result, ic, pi);
+                break;
 
-    /* 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);
-       }
-    }
+        case GPOINTER:
+                genGenPointerGet (left, result, ic, pi);
+                break;
+        }
 
-    /* done */
-    freeAsmop(result,NULL,ic,TRUE);
-     
 }
 
 /*-----------------------------------------------------------------*/
-/* genPagedPointerGet - emitcode for paged pointer fetch           */
+/* genPackBits - generates code for packed bit storage             */
 /*-----------------------------------------------------------------*/
-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);
-
-  /* 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);
-
-    /* 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);
-       }
-    }
+static void
+genPackBits (sym_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++);
+        MOVR24 (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 */
+                RLsh (shCount,24);
+
+                if (SPEC_BLEN (etype) < 8) {                    /* if smaller than a byte */
+
+                        switch (p_type) {
+                        case POINTER:
+                        case IPOINTER:
+                        case PPOINTER:
+                        case FPOINTER:
+                                emitcode ("ld", "r1,%s",rname);
+                                break;
+
+                        case GPOINTER:
+                                emitcode ("push", "r1");
+                                emitcode ("push", "r24");
+                                emitcode ("call", "__gptrget");
+                                emitcode ("pop", "r1");
+                                emitcode ("mov","r24,r0");
+                                break;
+                        }
 
-    /* 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);
-       }
-    }
+                        emitcode ("andi", "r24,#0x%02x", (unsigned char)
+                                  ((unsigned char) (0xFF << (blen + bstr)) |
+                                   (unsigned char) (0xFF >> (8 - bstr))));
+                        emitcode ("or", "r24,r1");
+                        if (p_type == GPOINTER)
+                                emitcode ("pop", "r1");
+                }
+        }
 
-    /* done */
-    freeAsmop(result,NULL,ic,TRUE);
-    
-       
-}
+        switch (p_type) {
+        case POINTER:
+        case IPOINTER:
+        case PPOINTER:
+        case FPOINTER:
+                emitcode("st","%s+,r24");
+                break;
 
-/*-----------------------------------------------------------------*/
-/* genFarPointerGet - gget value from far space                    */
-/*-----------------------------------------------------------------*/
-static void genFarPointerGet (operand *left,
-                              operand *result, iCode *ic)
-{
-    int size, offset ;
-    link *retype = getSpec(operandType(result));
-
-    aopOp(left,ic,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));
-            }
+        case GPOINTER:
+                emitcode("mov","r0,r24");
+                emitcode ("call", "__gptrput_pi");
+                break;
         }
-    }
-    /* so dptr know contains the address */
-    freeAsmop(left,NULL,ic,TRUE);
-    aopOp(result,ic,FALSE);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genUnpackBits(result,"dptr",FPOINTER);
-    else {
-        size = AOP_SIZE(result);
-        offset = 0 ;
+        /* if we r done */
+        if (SPEC_BLEN (etype) <= 8)
+                return;
 
-        while (size--) {
-            emitcode("movx","a,@dptr");
-            aopPut(AOP(result),"a",offset++);
-            if (size)
-                emitcode("inc","dptr");
-        }
-    }
+        rLen = SPEC_BLEN (etype);
 
-    freeAsmop(result,NULL,ic,TRUE);
-}
+        /* now generate for lengths greater than one byte */
+        while (1) {
 
-/*-----------------------------------------------------------------*/
-/* 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);
-
-    /* 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));
-            }
+                l = aopGet (AOP (right), offset++);
+
+                rLen -= 8;
+                if (rLen < 8)
+                        break;
+
+                switch (p_type) {
+                case POINTER:
+                case IPOINTER:
+                case PPOINTER:
+                case FPOINTER:
+                        emitcode ("st", "%s+,%s",rname,l);
+                        break;
+
+                case GPOINTER:
+                        MOVR0 (l);
+                        emitcode ("lcall", "__gptrput_pi");
+                        break;
+                }
         }
-    }
-    /* so dptr know contains the address */
-    freeAsmop(left,NULL,ic,TRUE);
-    aopOp(result,ic,FALSE);
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genUnpackBits(result,"dptr",CPOINTER);
-    else {
-        size = AOP_SIZE(result);
-        offset = 0 ;
+        MOVR24 (l);
 
-        while (size--) {
-            emitcode("clr","a");
-            emitcode("movc","a,@a+dptr");
-            aopPut(AOP(result),"a",offset++);
-            if (size)
-                emitcode("inc","dptr");
+        /* last last was not complete */
+        if (rLen) {
+                /* save the byte & read byte */
+                switch (p_type) {
+                case POINTER:
+                case IPOINTER:
+                case PPOINTER:
+                case FPOINTER:
+                        emitcode ("st","%s+,r24",rname);
+                        break;
+                case GPOINTER:
+                        emitcode ("push", "r1");
+                        emitcode ("push", "r24");
+                        emitcode ("lcall", "__gptrget");
+                        emitcode ("mov","r24,r0");
+                        emitcode ("pop", "r1");
+                        break;
+                }
+
+                emitcode ("andi", "r24,0x%02x", (((unsigned char) -1 << rLen) & 0xff));
+                emitcode ("or", "r24,r1");
         }
-    }
 
-    freeAsmop(result,NULL,ic,TRUE);
+        if (p_type == GPOINTER)
+                emitcode ("pop", "r1");
+
+        switch (p_type) {
+
+        case POINTER:
+        case IPOINTER:
+        case PPOINTER:
+        case FPOINTER:
+                emitcode ("st", "%s,r24", rname);
+                break;
+
+        case GPOINTER:
+                emitcode ("mov","r0,r24");
+                emitcode ("call", "__gptrput");
+                break;
+        }
 }
 
 /*-----------------------------------------------------------------*/
-/* genGenPointerGet - gget value from generic pointer space        */
+/* genDataPointerSet - remat pointer to data space                 */
 /*-----------------------------------------------------------------*/
-static void genGenPointerGet (operand *left,
-                              operand *result, iCode *ic)
+static void
+genDataPointerSet (operand * right, operand * result, iCode * ic)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(result));
-
-    aopOp(left,ic,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));
-           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);
+        int size, offset = 0;
+        char *l, buffer[256];
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genUnpackBits(result,"dptr",GPOINTER);
-    else {
-        size = AOP_SIZE(result);
-        offset = 0 ;
+        aopOp (right, ic, FALSE);
 
+        l = aopGet (AOP (result), 0);
+        size = AOP_SIZE (right);
         while (size--) {
-            emitcode("lcall","__gptrget");
-            aopPut(AOP(result),"a",offset++);
-            if (size)
-                emitcode("inc","dptr");
+                if (offset)
+                        sprintf (buffer, "(%s + %d)", l, offset);
+                else
+                        sprintf (buffer, "%s", l);
+                emitcode ("sts", "%s,%s", buffer,
+                          aopGet (AOP (right), offset++));
         }
-    }
 
-    freeAsmop(result,NULL,ic,TRUE);
+        freeAsmop (right, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPointerGet - generate code for pointer get                   */
+/* genNearPointerSet - emitcode for near pointer put               */
 /*-----------------------------------------------------------------*/
-static void genPointerGet (iCode *ic)
+static void
+genMemPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
 {
-    operand *left, *result ;
-    link *type, *etype;
-    int p_type;
-
-    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 ; */
-    }
+        asmop *aop = NULL;
+        char *frname = NULL, *rname, *l;
+        int gotFreePtr = 0;
+        sym_link *retype;
+        sym_link *ptype = operandType (result);
 
-    /* now that we have the pointer type we assign
-    the pointer values */
-    switch (p_type) {
+        retype = getSpec (operandType (right));
 
-    case POINTER:      
-    case IPOINTER:
-       genNearPointerGet (left,result,ic);
-       break;
+        aopOp (result, ic, FALSE);
 
-    case PPOINTER:
-       genPagedPointerGet(left,result,ic);
-       break;
+        /* 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 (!AOP_INPREG(AOP(result))) {
+                /* otherwise get a free pointer register */
+                aop = newAsmop (0);
+                getFreePtr (ic, &aop, FALSE, 0);
+                if (isRegPair (AOP (result) )) {
+                        emitcode ("movw", "%s,%s",aop->aopu.aop_ptr->name,
+                                  aopGet(AOP (result), 0));
+                } else {
+                        emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
+                                  aopGet (AOP (result), 0));
+                        emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
+                                  aopGet (AOP (result), 1));
+                }
+                gotFreePtr = 1;
+        } else {
+                aop = AOP(result);
+                frname = aopGet(aop,0);
+        }
 
-    case FPOINTER:
-       genFarPointerGet (left,result,ic);
-       break;
+        aopOp (right, ic, FALSE);
+        if (AOP_ISX(aop)) {
+                rname = "X";
+        } else if (AOP_ISZ(aop)) {
+                rname = "Z";
+        } else {
+                werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                        "pointer not in correct register");
+                exit (0);
+        }
+        /* 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);
+                        if (size || pi)
+                                emitcode ("st", "%s+,%s", rname,l);
+                        else
+                                emitcode ("st", "%s,%s", rname,l);
+                        offset++;
+                }
+        }
 
-    case CPOINTER:
-       emitcodePointerGet (left,result,ic);
-       break;
+        /* now some housekeeping stuff */
+        if (gotFreePtr) {
+                /* we had to allocate for this iCode */
+                if (pi) {
+                        if (isRegPair (AOP (result) )) {
+                                emitcode ("movw", "%s,%s",
+                                          aopGet(AOP(result),0),
+                                          aop->aopu.aop_ptr->name);
+                        } else {
+                                emitcode ("mov", "%s,%s", aop->aopu.aop_ptr->name,
+                                          aopGet (AOP (result), 0));
+                                emitcode ("mov", "%s,%s", aop->aop_ptr2->name,
+                                          aopGet (AOP (result), 1));
+                        }
+                }
+                freeAsmop (NULL, aop, ic, TRUE);
+        } else {
 
-    case GPOINTER:
-       genGenPointerGet (left,result,ic);
-       break;
-    }
+                /* 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 (right)->liveTo > ic->seq || ic->depth)) && !pi) {
+                        int size = AOP_SIZE (right) - 1;
+                        emitcode ("sbiw", "%s,%d",frname,size);
+                }
+        }
 
+        /* done */
+        if (pi) pi->generated = 1;
+        freeAsmop (result, NULL, ic, TRUE);
+        freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genPackBits - generates code for packed bit storage             */
+/* genGenPointerSet - set value from generic pointer space         */
 /*-----------------------------------------------------------------*/
-static void genPackBits (link    *etype ,
-                         operand *right ,
-                         char *rname, int p_type)
+static void
+genGenPointerSet (operand * right, operand * result, iCode * ic, iCode *pi)
 {
-    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);
+        int size, offset;
+        int gotFreePtr = 0;
+        sym_link *retype = getSpec (operandType (right));
+        asmop *aop = NULL;
 
-        if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
+        aopOp (result, ic, FALSE);
 
+        /* if the operand is already in dptr
+           then we do nothing else we move the value to dptr */
+        if (AOP_ISZ(AOP(result))) {
+                aop = AOP(right);
+        } else {
+                aop = newAsmop(0);
+                getFreePtr(ic,&aop,FALSE,TRUE);
+                if (isRegPair(AOP(result))) {
+                        emitcode ("movw", "r30,%s", aopGet (AOP (result), 0));
+                } else {
+                        emitcode ("mov", "r30,%s", aopGet (AOP (result), 0));
+                        emitcode ("mov", "r31,%s", aopGet (AOP (result), 1));
+                }
+                emitcode ("mov", "r24,%s",  aopGet (AOP (result), 2));
+                gotFreePtr=1;
+        }
 
-            switch (p_type) {
-                case POINTER:
-                    emitcode ("mov","b,a");
-                    emitcode("mov","a,@%s",rname);
-                    break;
+        /* so Z register now contains the address */
+        aopOp (right, ic, FALSE);
 
-                case FPOINTER:
-                    emitcode ("mov","b,a");
-                    emitcode("movx","a,@dptr");
-                    break;
+        /* if bit then unpack */
+        if (IS_BITVAR (retype))
+                genUnpackBits (result, "Z", GPOINTER);
+        else {
+                size = AOP_SIZE (right);
+                offset = 0;
 
-                case GPOINTER:
-                    emitcode ("push","b");
-                    emitcode ("push","acc");
-                    emitcode ("lcall","__gptrget");
-                    emitcode ("pop","b");
-                    break;
-            }
+                while (size--) {
+                        char *l = aopGet(AOP (right), offset++);
+                        MOVR0(l);
 
-            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");
+                        if (size || pi)
+                                emitcode ("call", "__gptrput_pi");
+                        else
+                                emitcode ("call", "__gptrput");
+                }
         }
-    }
-
-    switch (p_type) {
-        case POINTER:
-            emitcode("mov","@%s,a",rname);
-            break;
-
-        case FPOINTER:
-            emitcode("movx","@dptr,a");
-            break;
 
-        case GPOINTER:
-            emitcode("lcall","__gptrput");
-            break;
-    }
+        /* now some housekeeping stuff */
+        if (gotFreePtr) {
+                /* we had to allocate for this iCode */
+                if (pi) {
+                        if (isRegPair(AOP(result))) {
+                                emitcode ("movw", "%s,r30", aopGet (AOP (result), 0));
+                        } else {
+                                emitcode ("mov", "%s,r30", aopGet (AOP (result), 0));
+                                emitcode ("mov", "%s,r31", aopGet (AOP (result), 1));
+                        }
+                }
+                freeAsmop (NULL, aop, ic, TRUE);
+        } else {
 
-    /* if we r done */
-    if ( SPEC_BLEN(etype) <= 8 )
-        return ;
+                /* 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)) && !pi) {
+                        int size = AOP_SIZE (right) - 1;
+                        emitcode ("sbiw", "r30,%d",size);
+                }
+        }
+        if (pi) pi->generated = 1;
+        freeAsmop (right, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
+}
 
-    emitcode("inc","%s",rname);
-    rLen = SPEC_BLEN(etype) ;     
+/*-----------------------------------------------------------------*/
+/* genPointerSet - stores the value into a pointer location        */
+/*-----------------------------------------------------------------*/
+static void
+genPointerSet (iCode * ic, iCode *pi)
+{
+        operand *right, *result;
+        sym_link *type, *etype;
+        int p_type;
 
-    /* now generate for lengths greater than one byte */
-    while (1) {
+        right = IC_RIGHT (ic);
+        result = IC_RESULT (ic);
 
-        l = aopGet(AOP(right),offset++,FALSE,TRUE);
+        /* 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));
 
-        rLen -= 8 ;
-        if (rLen <= 0 )
-            break ;
+        }
 
+        /* now that we have the pointer type we assign
+           the pointer values */
         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);
+        case POINTER:
+        case IPOINTER:
+        case PPOINTER:
+        case FPOINTER:
+                genMemPointerSet (right, result, ic, pi);
                 break;
 
-            case FPOINTER:
-                emitcode ("mov","b,a");
-                emitcode("movx","a,@dptr");
+        case GPOINTER:
+                genGenPointerSet (right, result, ic, pi);
                 break;
 
-            case GPOINTER:
-                emitcode ("push","b");
-                emitcode ("push","acc");
-                emitcode ("lcall","__gptrget");
-                emitcode ("pop","b");
-                break;
+        default:
+          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                  "genPointerSet: illegal pointer type");
         }
 
-        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                 */
+/* genIfx - generate code for Ifx statement                        */
 /*-----------------------------------------------------------------*/
-static void genDataPointerSet(operand *right,
-                             operand *result,
-                             iCode *ic)
+static void
+genIfx (iCode * ic, iCode * popIc)
 {
-    int size, offset = 0 ;
-    char *l, buffer[256];
-
-    aopOp(right,ic,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));
-    }
+        operand *cond = IC_COND (ic);
+        char *cname ;
+        symbol *lbl;
+        int tob = 0;
 
-    freeAsmop(right,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+        aopOp (cond, ic, FALSE);
+
+        /* get the value into acc */
+        if (AOP_SIZE(cond) == 1 && AOP_ISHIGHREG(AOP(cond),0)) {
+                cname = aopGet(AOP(cond),0);
+        } else {
+                toBoolean (cond, "r24", 0);
+                tob = 1;
+                cname = "r24";
+        }
+        /* 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);
+                emitcode("cpi","%s,0",cname);
+        } else if (!tob) emitcode("cpi","%s,0",cname);
+
+        lbl = newiTempLabel(NULL);
+        if (IC_TRUE(ic)) {
+                emitcode ("breq","L%05d",lbl->key);
+                emitcode ("jmp","L%05d",IC_TRUE(ic)->key);
+                emitcode ("","L%05d:",lbl->key);
+        } else {
+                emitcode ("brne","L%05d",lbl->key);
+                emitcode ("jmp","L%05d",IC_FALSE(ic)->key);
+                emitcode ("","L%05d:",lbl->key);
+        }
+        ic->generated = 1;
 }
 
 /*-----------------------------------------------------------------*/
-/* genNearPointerSet - emitcode for near pointer put                */
+/* genAddrOf - generates code for address of                       */
 /*-----------------------------------------------------------------*/
-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);
-    
-    /* 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);
-
-    /* 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 ;    
+static void
+genAddrOf (iCode * ic)
+{
+        symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+        int size, offset;
+
+        aopOp (IC_RESULT (ic), ic, FALSE);
+        assert(AOP_SIZE(IC_RESULT(ic)) >= 2);
+        /* 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) {
+                        if (allHigh(AOP(IC_RESULT(ic)))) {
+                                if (isRegPair (AOP(IC_RESULT(ic)))) {
+                                        emitcode ("movw","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
+                                } else {
+                                        emitcode ("mov","%s,r28",aopGet(AOP(IC_RESULT(ic)),0));
+                                        emitcode ("mov","%s,r29",aopGet(AOP(IC_RESULT(ic)),1));
+                                }
+                                if (sym->stack < 0) {
+                                        emitcode("subi","%s,<(%d)",aopGet(AOP(IC_RESULT(ic)),0),-sym->stack);
+                                        emitcode("sbci","%s,>(%d)",aopGet(AOP(IC_RESULT(ic)),1),-sym->stack);
+                                } else {
+                                        emitcode("subi","%s,<(-%d)",aopGet(AOP(IC_RESULT(ic)),0),sym->stack);
+                                        emitcode("sbci","%s,>(-%d)",aopGet(AOP(IC_RESULT(ic)),1),sym->stack);
+                                }
+                        } else {
+                                emitcode("movw","r24,r28");
+                                if (sym->stack > -63 && sym->stack < 63) {
+                                        if (sym->stack < 0)
+                                                emitcode("sbiw","r24,%d",-sym->stack);
+                                        else
+                                                emitcode("sbiw","r24,%d",sym->stack);
+                                } else {
+                                        if (sym->stack < 0) {
+                                                emitcode("subi","r24,<(%d)",-sym->stack);
+                                                emitcode("sbci","r25,>(%d)",-sym->stack);
+                                        } else {
+                                                emitcode("subi","r24,<(-%d)",sym->stack);
+                                                emitcode("sbci","r25,>(-%d)",sym->stack);
+                                        }
+                                }
+
+                                aopPut(AOP(IC_RESULT(ic)),"r24",0);
+                                aopPut(AOP(IC_RESULT(ic)),"r25",1);
+                        }
+                }
+                else {
+                        aopPut(AOP(IC_RESULT(ic)),"r28",0);
+                        aopPut(AOP(IC_RESULT(ic)),"r29",1);
+                }
+                /* fill the result with zero */
+                size = AOP_SIZE (IC_RESULT (ic)) - 2;
+                offset = 2;
+                while (size--) {
+                        aopPut (AOP (IC_RESULT (ic)), zero, offset++);
+                }
 
-        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++;
+                goto release;
         }
-    }
 
-    /* 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);
+        /* object not on stack then we need the name */
+        size = AOP_SIZE (IC_RESULT (ic));
+        offset = 0;
+        assert(size<=2);
+        while (size--) {
+                char s[SDCC_NAME_MAX];
+                if (offset)
+                        sprintf (s, ">(%s)", sym->rname);
+                else
+                        sprintf (s, "<(%s)", sym->rname);
+                aopPut (AOP (IC_RESULT (ic)), s, offset++);
         }
-    }
-
-    /* done */
-    freeAsmop(right,NULL,ic,TRUE);
 
+      release:
+        freeAsmop (IC_RESULT (ic), 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);
-    
-    /* 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);
-
-    /* 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                     */
+/* genFarFarAssign - assignment when both are in far space         */
 /*-----------------------------------------------------------------*/
-static void genFarPointerSet (operand *right,
-                              operand *result, iCode *ic)
+static void
+genFarFarAssign (operand * result, operand * right, iCode * ic)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(right));
-
-    aopOp(result,ic,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));
-            }
+        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++);
+                MOVA (l);
+                emitcode ("push", "acc");
         }
-    }
-    /* so dptr know contains the address */
-    freeAsmop(result,NULL,ic,TRUE);
-    aopOp(right,ic,FALSE);
-
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genPackBits(retype,right,"dptr",FPOINTER);
-    else {
-        size = AOP_SIZE(right);
-        offset = 0 ;
 
+        freeAsmop (right, NULL, ic, FALSE);
+        /* now assign DPTR to result */
+        aopOp (result, ic, FALSE);
+        size = AOP_SIZE (result);
         while (size--) {
-            char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
-            MOVA(l);
-            emitcode("movx","@dptr,a");
-            if (size)
-                emitcode("inc","dptr");
+                emitcode ("pop", "acc");
+                aopPut (AOP (result), "a", --offset);
         }
-    }
+        freeAsmop (result, NULL, ic, FALSE);
 
-    freeAsmop(right,NULL,ic,TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genGenPointerSet - set value from generic pointer space         */
+/* genAssign - generate code for assignment                        */
 /*-----------------------------------------------------------------*/
-static void genGenPointerSet (operand *right,
-                              operand *result, iCode *ic)
+static void
+genAssign (iCode * ic)
 {
-    int size, offset ;
-    link *retype = getSpec(operandType(right));
-
-    aopOp(result,ic,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));
-            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);
+        operand *result, *right;
+        int size, offset;
+        unsigned long lit = 0L;
 
-    /* if bit then unpack */
-    if (IS_BITVAR(retype)) 
-        genPackBits(retype,right,"dptr",GPOINTER);
-    else {
-        size = AOP_SIZE(right);
-        offset = 0 ;
+        result = IC_RESULT (ic);
+        right = IC_RIGHT (ic);
 
-        while (size--) {
-            char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
-            MOVA(l);
-            emitcode("lcall","__gptrput");
-            if (size)
-                emitcode("inc","dptr");
+        /* if they are the same */
+        if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
+                return;
+
+        aopOp (right, ic, FALSE);
+
+        /* special case both in far space */
+        if (AOP_TYPE (right) == AOP_DPTR &&
+            IS_TRUE_SYMOP (result) && isOperandInFarSpace (result)) {
+
+                genFarFarAssign (result, right, ic);
+                return;
         }
-    }
 
-    freeAsmop(right,NULL,ic,TRUE);
-}
+        aopOp (result, ic, TRUE);
 
-/*-----------------------------------------------------------------*/
-/* genPointerSet - stores the value into a pointer location        */
-/*-----------------------------------------------------------------*/
-static void genPointerSet (iCode *ic)
-{    
-    operand *right, *result ;
-    link *type, *etype;
-    int p_type;
-
-    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 ; */
-    }
+        /* if they are the same registers */
+        if (sameRegs (AOP (right), AOP (result)))
+                goto release;
 
-    /* now that we have the pointer type we assign
-    the pointer values */
-    switch (p_type) {
+        /* if the result is a bit */
+        if (AOP_TYPE (result) == AOP_CRY) {
 
-    case POINTER:
-    case IPOINTER:
-       genNearPointerSet (right,result,ic);
-       break;
+                /* 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;
+                }
 
-    case PPOINTER:
-       genPagedPointerSet (right,result,ic);
-       break;
+                /* 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;
+                }
 
-    case FPOINTER:
-       genFarPointerSet (right,result,ic);
-       break;
+                /* we need to or */
+                toBoolean (right, "", 0);
+                aopPut (AOP (result), "a", 0);
+                goto release;
+        }
 
-    case GPOINTER:
-       genGenPointerSet (right,result,ic);
-       break;
-    }
+        /* bit variables done */
+        /* general case */
+        size = AOP_SIZE (result);
+        offset = 0;
+        if (AOP_TYPE (right) == AOP_LIT)
+                lit = ulFromVal (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), size);
+                }
+        }
+        else {
+                while (size--) {
+                        aopPut (AOP (result),
+                                aopGet (AOP (right), offset), offset);
+                        offset++;
+                }
+        }
 
+      release:
+        freeAsmop (right, NULL, ic, FALSE);
+        freeAsmop (result, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genIfx - generate code for Ifx statement                        */
+/* genJumpTab - genrates code for jump table                       */
 /*-----------------------------------------------------------------*/
-static void genIfx (iCode *ic, iCode *popIc)
+static void
+genJumpTab (iCode * ic)
 {
-    operand *cond = IC_COND(ic);
-    int isbit =0;
-
-    aopOp(cond,ic,FALSE);
-
-    /* get the value into acc */
-    if (AOP_TYPE(cond) != AOP_CRY)
-        toBoolean(cond);
-    else
-        isbit = 1;
-    /* the result is now in the accumulator */
-    freeAsmop(cond,NULL,ic,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;
+        symbol *jtab;
+        char *l;
+
+        aopOp (IC_JTCOND (ic), ic, FALSE);
+        /* get the condition into accumulator */
+        l = aopGet (AOP (IC_JTCOND (ic)), 0);
+        MOVA (l);
+        /* multiply by three */
+        emitcode ("add", "a,acc");
+        emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0));
+        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);
+
 }
 
 /*-----------------------------------------------------------------*/
-/* genAddrOf - generates code for address of                       */
+/* genCast - gen code for casting                                  */
 /*-----------------------------------------------------------------*/
-static void genAddrOf (iCode *ic)
+static void
+genCast (iCode * ic)
 {
-    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
-    int size, offset ;
+        operand *result = IC_RESULT (ic);
+        sym_link *ctype = operandType (IC_LEFT (ic));
+        sym_link *rtype = operandType (IC_RIGHT (ic));
+        operand *right = IC_RIGHT (ic);
+        int size, offset;
 
-    aopOp(IC_RESULT(ic),ic,FALSE);
+        /* if they are equivalent then do nothing */
+        if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
+                return;
 
-    /* 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;
-        offset = 1;
-        while (size--) 
-            aopPut(AOP(IC_RESULT(ic)),zero,offset++);
+        aopOp (right, ic, FALSE);
+        aopOp (result, ic, FALSE);
 
-        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);
 
-    /* object not on stack then we need the name */
-    size = AOP_SIZE(IC_RESULT(ic));
-    offset = 0;
+                        goto release;
+                }
 
-    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++);
-    }
+                /* 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;
+                }
 
-release:
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+                /* we need to or */
+                toBoolean (right, "", 0);
+                aopPut (AOP (result), "a", 0);
+                goto release;
+        }
 
-}
+        /* if they are the same size : or less */
+        if (AOP_SIZE (result) <= AOP_SIZE (right)) {
 
-/*-----------------------------------------------------------------*/
-/* 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");
-    }
-    
-    freeAsmop(right,NULL,ic,FALSE);
-    /* now assign DPTR to result */
-    aopOp(result,ic,FALSE);
-    size = AOP_SIZE(result);
-    while (size--) {
-       emitcode ("pop","acc");
-       aopPut(AOP(result),"a",--offset);
-    }
-    freeAsmop(result,NULL,ic,FALSE);
-       
-}
+                /* if they are in the same place */
+                if (sameRegs (AOP (right), AOP (result)))
+                        goto release;
 
-/*-----------------------------------------------------------------*/
-/* genAssign - generate code for assignment                        */
-/*-----------------------------------------------------------------*/
-static void genAssign (iCode *ic)
-{
-    operand *result, *right;
-    int size, offset ;
-       unsigned long lit = 0L;
-
-    result = IC_RESULT(ic);
-    right  = IC_RIGHT(ic) ;
-
-    /* if they are the same */
-    if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
-        return ;
-
-    aopOp(right,ic,FALSE);
-    
-    /* special case both in far space */
-    if (AOP_TYPE(right) == AOP_DPTR &&
-       IS_TRUE_SYMOP(result)       &&
-       isOperandInFarSpace(result)) {
-
-       genFarFarAssign (result,right,ic);
-        return ;
-    }
+                /* if they in different places then copy */
+                size = AOP_SIZE (result);
+                offset = 0;
+                while (size--) {
+                        aopPut (AOP (result),
+                                aopGet (AOP (right), offset), offset);
+                        offset++;
+                }
+                goto release;
+        }
+
+
+        /* if the result is of type pointer */
+        if (IS_PTR (ctype)) {
 
-    aopOp(result,ic,TRUE);
+                int p_type;
+                sym_link *type = operandType (right);
+                sym_link *etype = getSpec (type);
 
-    /* if they are the same registers */
-    if (sameRegs(AOP(right),AOP(result)))
-        goto release;
+                /* pointer to generic pointer */
+                if (IS_GENPTR (ctype)) {
+                        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), offset);
+                                offset++;
+                        }
+
+                    /* the last byte depending on type */
+                    {
+                        int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
+                        char gpValStr[10];
 
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY) {
+                        if (gpVal == -1)
+                        {
+                            // pointerTypeToGPByte will have bitched.
+                            exit(1);
+                        }
+
+                        sprintf(gpValStr, "#0x%x", gpVal);
+                        aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
+                    }
+                    goto release;
+                }
 
-        /* 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;
+                /* just copy the pointers */
+                size = AOP_SIZE (result);
+                offset = 0;
+                while (size--) {
+                        aopPut (AOP (result),
+                                aopGet (AOP (right), offset), offset);
+                        offset++;
+                }
+                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 ;
+        /* 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), offset);
+                offset++;
         }
 
-        /* we need to or */
-        toBoolean(right);
-        aopPut(AOP(result),"a",0);
-        goto release ;
-    }
+        /* 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 :{ */
+                // PENDING: Does nothing on avr
+#if 0
+                char *l = aopGet (AOP (right), AOP_SIZE (right) - 1);
+                MOVA (l);
+#endif
+                emitcode ("rlc", "a");
+                emitcode ("subb", "a,acc");
+                while (size--)
+                        aopPut (AOP (result), "a", offset++);
+        }
 
-    /* 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);
-}   
+        /* we are done hurray !!!! */
 
-/*-----------------------------------------------------------------*/
-/* genJumpTab - genrates code for jump table                       */
-/*-----------------------------------------------------------------*/
-static void genJumpTab (iCode *ic)
-{
-    symbol *jtab;
-    char *l;
-
-    aopOp(IC_JTCOND(ic),ic,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);
+      release:
+        freeAsmop (right, NULL, ic, TRUE);
+        freeAsmop (result, NULL, ic, TRUE);
 
 }
 
 /*-----------------------------------------------------------------*/
-/* genCast - gen code for casting                                  */
+/* genDjnz - generate decrement & jump if not zero instrucion      */
 /*-----------------------------------------------------------------*/
-static void genCast (iCode *ic)
+static int
+genDjnz (iCode * ic, iCode * ifx)
 {
-    operand *result = IC_RESULT(ic);
-    link *ctype = operandType(IC_LEFT(ic));
-    operand *right = IC_RIGHT(ic);
-    int size, offset ;
-
-    /* if they are equivalent then do nothing */
-    if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
-        return ;
-
-    aopOp(right,ic,FALSE) ;
-    aopOp(result,ic,FALSE);
-
-    /* if the result is a bit */
-    if (AOP_TYPE(result) == AOP_CRY) {
-        /* 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)) {
+        symbol *lbl, *lbl1;
+        if (!ifx)
+                return 0;
 
-        /* if they are in the same place */
-        if (sameRegs(AOP(right),AOP(result)))
-            goto release;
+        /* if the if condition has a false label
+           then we cannot save */
+        if (IC_FALSE (ifx))
+                return 0;
 
-        /* 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 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 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));
-
-/*             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 ; */
-           }
-               
-           /* 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++;
-    }
+        /* if the size of this greater than one then no
+           saving */
+        if (getSize (operandType (IC_RESULT (ic))) > 1)
+                return 0;
 
-    /* now depending on the sign of the destination */
-    size = AOP_SIZE(result) - AOP_SIZE(right);
-    /* if unsigned or not an integral type */
-    if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
-        while (size--)
-            aopPut(AOP(result),zero,offset++);
-    } else {
-        /* we need to extend the sign :{ */
-        char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
-                         FALSE,FALSE);
-        MOVA(l);
-        emitcode("rlc","a");
-        emitcode("subb","a,acc");
-        while (size--)
-            aopPut(AOP(result),"a",offset++);   
-    }
+        /* otherwise we can save BIG */
+        lbl = newiTempLabel (NULL);
+        lbl1 = newiTempLabel (NULL);
 
-    /* we are done hurray !!!! */
+        aopOp (IC_RESULT (ic), ic, FALSE);
 
-release:
-    freeAsmop(right,NULL,ic,TRUE);
-    freeAsmop(result,NULL,ic,TRUE);
+        if (IS_AOP_PREG (IC_RESULT (ic))) {
+                emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0));
+                emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0));
+                emitcode ("jnz", "%05d$", lbl->key + 100);
+        }
+        else {
+                emitcode ("djnz", "%s,%05d$",
+                          aopGet (AOP (IC_RESULT (ic)), 0), 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;
 }
 
+static char *recvregs[8] = {
+        "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23"
+};
+
+static int recvCnt = 0;
+
 /*-----------------------------------------------------------------*/
-/* genDjnz - generate decrement & jump if not zero instrucion      */
+/* genReceive - generate code for a receive iCode                  */
 /*-----------------------------------------------------------------*/
-static int genDjnz (iCode *ic, iCode *ifx)
+static void
+genReceive (iCode * ic)
 {
-    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);
-    
-    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;
+        int size, offset = 0;
+        aopOp (IC_RESULT (ic), ic, FALSE);
+        size = AOP_SIZE (IC_RESULT (ic));
+        while (size--) {
+                aopPut (AOP (IC_RESULT (ic)), recvregs[recvCnt++], offset);
+                offset++;
+        }
+        freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
-/* genReceive - generate code for a receive iCode                  */
+/* genDummyRead - generate code for dummy read of volatiles        */
 /*-----------------------------------------------------------------*/
-static void genReceive (iCode *ic)
-{    
-    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 - size;
-       while (size--) {
-           emitcode ("push","%s", (strcmp(fReturn[fReturnSize - offset - 1],"a") ?
-                                   fReturn[fReturnSize - offset - 1] : "acc"));
-           offset++;
-       }
-       aopOp(IC_RESULT(ic),ic,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);  
-       _G.accInUse--;
-       assignResultValue(IC_RESULT(ic));       
-    }
+static void
+genDummyRead (iCode * ic)
+{
+  emitcode (";     genDummyRead","");
+  emitcode (";     not implemented","");
 
-    freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
+  ic = ic;
 }
 
 /*-----------------------------------------------------------------*/
 /* gen51Code - generate code for 8051 based controllers            */
 /*-----------------------------------------------------------------*/
-void gen51Code (iCode *lic)
+void
+genAVRCode (iCode * lic)
 {
-    iCode *ic;
-    int cln = 0;
-
-    lineHead = lineCurr = NULL;
-
-    /* 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); */
-           
+        iCode *ic;
+        int cln = 0;
+
+        lineHead = lineCurr = NULL;
+        recvCnt = 0;
+        /* print the allocation information */
+        if (allocInfo)
+                printAllocInfo (currFunc, codeOutBuf);
+        /* if debug information required */
+        if (options.debug && currFunc) {
+                debugFile->writeFunction (currFunc, lic);
         }
-    }
-    
+        /* stack pointer name */
+        spname = "sp";
+
 
-    /* now we are ready to call the 
-       peep hole optimizer */
-    if (!options.nopeep)
-       peepHole (&lineHead);
+        for (ic = lic; ic; ic = ic->next) {
 
-    /* now do the actual printing */
-    printLine (lineHead,codeOutFile);
-    return;
+                if (cln != ic->lineno) {
+                        if (options.debug) {
+                                debugFile->writeCLine (ic);
+                        }
+                        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:
+                        genCmpLe (ic, ifxForOp (IC_RESULT (ic), ic));
+                        break;
+
+                case GE_OP:
+                        genCmpGe (ic, ifxForOp (IC_RESULT (ic), ic));
+                        break;
+
+                case NE_OP:
+                        genCmpNe (ic, ifxForOp (IC_RESULT (ic), ic));
+                        break;
+
+                case EQ_OP:
+                        genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
+                        break;
+
+                case AND_OP:
+                        genAndOp (ic);
+                        break;
+
+                case OR_OP:
+                        genOrOp (ic);
+                        break;
+
+                case '^':
+                        genXor (ic, ifxForOp (IC_RESULT (ic), ic));
+                        break;
+
+                case '|':
+                        genOr (ic, ifxForOp (IC_RESULT (ic), ic));
+                        break;
+
+                case BITWISEAND:
+                        genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
+                        break;
+
+                case INLINEASM:
+                        genInline (ic);
+                        break;
+
+                case RRC:
+                        genRRC (ic);
+                        break;
+
+                case RLC:
+                        genRLC (ic);
+                        break;
+
+                case GETHBIT:
+                        genGetHbit (ic);
+                        break;
+
+                case LEFT_OP:
+                        genLeftShift (ic);
+                        break;
+
+                case RIGHT_OP:
+                        genRightShift (ic);
+                        break;
+
+                case GET_VALUE_AT_ADDRESS:
+                        genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
+                        break;
+
+                case '=':
+                        if (POINTER_SET (ic))
+                                genPointerSet (ic, hasInc(IC_RESULT(ic),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;
+
+                case DUMMY_READ_VOLATILE:
+                        genDummyRead (ic);
+                        break;
+
+                default:
+                        ic = ic;
+                }
+        }
+
+
+        /* now we are ready to call the
+           peep hole optimizer */
+        if (!options.nopeep)
+                peepHole (&lineHead);
+
+        /* now do the actual printing */
+        printLine (lineHead, codeOutBuf);
+        return;
 }