Got rid of gc_strdup, added prototype for alt lexer
[fw/sdcc] / src / z80 / gen.c
index 41d9cdfc911c1bab9b6219e9c8da608d01ffe1a9..003f59462de5f13ed13cb421e938116baddef41c 100644 (file)
@@ -1,26 +1,46 @@
 /*-------------------------------------------------------------------------
-  SDCCgen51.c - source file for code generation for 8051
+  gen.c - Z80 specific code generator.
+
+  Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
+                                               ticks   dhry    size
+  Base with asm strcpy / strcmp / memcpy:      23198   141     1A14
+  Improved WORD push                           22784   144     19AE
+  With label1 on                               22694   144     197E
+  With label2 on                               22743   144     198A
+  With label3 on                               22776   144     1999
+  With label4 on                               22776   144     1999
+  With all 'label' on                          22661   144     196F
+  With loopInvariant on                                20919   156     19AB
+  With loopInduction on                                Breaks          198B
+  With all working on                          20796   158     196C
+  Slightly better genCmp(signed)               20597   159     195B
+  Better reg packing, first peephole           20038   163     1873
+  With assign packing                          19281   165     1849
+  5/3/00                                       17741   185     17B6
+
+  Michael Hope <michaelh@earthling.net>        2000
+  Based on the mcs51 generator - 
+               Sandeep Dutta . sandeep.dutta@usa.net (1998)
+        and -  Jean-Louis VERN.jlvern@writeme.com (1999)
+        
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
   
-  Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
-         and -  Jean-Louis VERN.jlvern@writeme.com (1999)
+  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.
+
   
-        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!
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+  
+  In other words, you are welcome to use, share and improve this program.
+  You are forbidden to forbid anyone else to use, share and improve
+  what you give them.   Help stamp out software-hoarding!
 
 -------------------------------------------------------------------------*/
 
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include "SDCCglobl.h"
 
 #ifdef HAVE_SYS_ISA_DEFS_H
 #include <sys/isa_defs.h>
 #endif
 
-#include "SDCCast.h"
-#include "SDCCmem.h"
-#include "SDCCy.h"
-#include "SDCChasht.h"
-#include "SDCCbitv.h"
-#include "SDCCset.h"
-#include "SDCCicode.h"
-#include "SDCClabel.h"
-#include "SDCCBBlock.h"
-#include "SDCCloop.h"
-#include "SDCCcse.h"
-#include "SDCCcflow.h"
-#include "SDCCdflow.h"
-#include "SDCClrange.h"
-#include "ralloc.h"
-#include "gen.h"
+#include "z80.h"
 #include "SDCCpeeph.h"
+#include "gen.h"
+#include "SDCCglue.h"
 
 /* this is the down and dirty file with all kinds of kludgy & hacky
    stuff. This is what it is all about CODE GENERATION for a specific MCU.
    Some of the routines may be reusable, will have to see */
 
-static char *zero = "#0x00";
-static char *one  = "#0x01";
 static char *spname ;
-static char *fReturn[] = {"l", "h", "e", "d" };
+static char *_z80_return[] = {"l", "h", "e", "d" };
+static char *_gbz80_return[] = { "e", "d", "l", "h" };
+static char **_fReturn;
+static char **_fTmp;
+
+/* PENDING: messy */
+static char zero[20];
+
 static char *accUse[] = {"a" };
+static char *hlUse[] = { "l", "h" };
 short rbank = -1;
 short accInUse = 0 ;
 short inLine = 0;
@@ -70,6 +82,30 @@ extern int ptrRegReq ;
 extern int nRegs;
 extern FILE *codeOutFile;
 set *sendSet = NULL;
+
+typedef enum {
+    PAIR_INVALID,
+    PAIR_BC,
+    PAIR_DE,
+    PAIR_HL,
+    PAIR_IY,
+    PAIR_IX,
+    NUM_PAIRS
+} PAIR_ID;
+
+static struct {
+    const char *name;
+    const char *l;
+    const char *h;
+} _pairs[NUM_PAIRS] = {
+    { "??", "?", "?" },
+    { "bc", "c", "b" },
+    { "de", "e", "d" },
+    { "hl", "l", "h" },
+    { "iy", "iy.l?", "iy.h?" },
+    { "ix", "ix.l?", "ix.h?" }
+};
+    
 #define RESULTONSTACK(x) \
                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
                          IC_RESULT(x)->aop->type == AOP_STK )
@@ -77,17 +113,13 @@ set *sendSet = NULL;
 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
 #define CLRC    emitcode("xor","a,a");
 
-#define LABEL_STR      "%05d$"
-
 lineNode *lineHead = NULL;
 lineNode *lineCurr = NULL;
 
-unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
-0xE0, 0xC0, 0x80, 0x00};
-unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
-0x07, 0x03, 0x01, 0x00};
-
-static int _lastStack = 0;
+static const unsigned char SLMask[] = 
+{0xFF ,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
+static const unsigned char SRMask[] = 
+{0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
 
 #define LSB     0
 #define MSB16   1
@@ -95,13 +127,70 @@ static int _lastStack = 0;
 #define MSB32   3
 
 /* Stack frame:
-
    IX+4                param0  LH
    IX+2                ret     LH
    IX+0                ix      LH
    IX-2                temp0   LH
 */
 
+static struct {
+    struct {
+       AOP_TYPE last_type;
+       const char *lit;
+       int offset;
+    } pairs[NUM_PAIRS];
+    struct {
+       int last;
+       int pushed;
+       int param_offset;
+       int offset;
+       int pushed_bc;
+       int pushed_de;
+    } stack;
+    int frameId;
+    bool flush_statics;
+    bool in_home;
+} _G;
+
+static char *aopGet(asmop *aop, int offset, bool bit16);
+
+static void _tidyUp(char *buf)
+{
+    /* Clean up the line so that it is 'prettier' */
+    if (strchr(buf, ':')) {
+       /* Is a label - cant do anything */
+       return;
+    }
+    /* Change the first (and probably only) ' ' to a tab so
+       everything lines up.
+    */
+    while (*buf) {
+       if (*buf == ' ') {
+           *buf = '\t';
+           return;
+       }
+       buf++;
+    }
+}
+
+static void emit2(const char *szFormat, ...)
+{
+    char buffer[256];
+    va_list ap;
+
+    va_start(ap, szFormat);
+
+    tvsprintf(buffer, szFormat, ap);
+
+    _tidyUp(buffer);
+    lineCurr = (lineCurr ?
+               connectLine(lineCurr,newLineNode(buffer)) :
+               (lineHead = newLineNode(buffer)));
+
+    lineCurr->isInline = inLine;
+    lineCurr->isDebug  = debugLine;
+}
+
 /*-----------------------------------------------------------------*/
 /* emitcode - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
@@ -130,6 +219,26 @@ void emitcode (const char *inst, const char *fmt, ...)
     va_end(ap);
 }
 
+/* Z80:
+    { "adjustsp", 
+      "\tld hl,#-%d\n"
+      "\tadd hl,sp\n"
+      "\tld sp,hl"
+    }
+    { "prelude",
+       "push bc"
+       "push de"
+       "push ix"
+       "ld ix,#0"
+       "add ix,sp"
+    { "leave" 
+    emitcode("ld", "sp,ix");
+    emitcode("pop", "ix");
+    emitcode("pop", "de");
+    }
+}
+*/
+
 const char *getPairName(asmop *aop)
 {
     if (aop->type == AOP_REG) {
@@ -158,46 +267,64 @@ const char *getPairName(asmop *aop)
            break;
        }
     }
-    assert(0);
+    wassert(0);
     return NULL;
 }
 
-/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
-bool isPair(asmop *aop)
+static PAIR_ID getPairId(asmop *aop)
 {
     if (aop->size == 2) {
        if (aop->type == AOP_REG) {
            if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
-               return TRUE;
+               return PAIR_BC;
            }
            if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
-               return TRUE;
+               return PAIR_DE;
            }
            if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
-               return TRUE;
+               return PAIR_HL;
            }
        }
        if (aop->type == AOP_STR) {
            if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
-               return TRUE;
+               return PAIR_BC;
            }
            if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
-               return TRUE;
+               return PAIR_DE;
            }
            if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
-               return TRUE;
+               return PAIR_HL;
            }
        }
     }
-    return FALSE;
+    return PAIR_INVALID;
 }
 
+/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
+bool isPair(asmop *aop)
+{
+    return (getPairId(aop) != PAIR_INVALID);
+}
+
+bool isPtrPair(asmop *aop)
+{
+    PAIR_ID pairId = getPairId(aop);
+    switch (pairId) {
+    case PAIR_HL:
+    case PAIR_IY:
+    case PAIR_IX:
+       return TRUE;
+    default:
+       return FALSE;
+    }
+}
 /** Push a register pair onto the stack */
 void genPairPush(asmop *aop)
 {
     emitcode("push", "%s", getPairName(aop));
 }
 
+
 /*-----------------------------------------------------------------*/
 /* newAsmop - creates a new asmOp                                  */
 /*-----------------------------------------------------------------*/
@@ -213,10 +340,16 @@ static asmop *newAsmop (short type)
 /*-----------------------------------------------------------------*/
 /* aopForSym - for a true symbol                                   */
 /*-----------------------------------------------------------------*/
-static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
+static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
 {
     asmop *aop;
-    memmap *space= SPEC_OCLS(sym->etype);
+    memmap *space;
+
+    wassert(ic);
+    wassert(sym);
+    wassert(sym->etype);
+
+    space = SPEC_OCLS(sym->etype);
 
     /* if already has one */
     if (sym->aop)
@@ -224,9 +357,9 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
 
     /* Assign depending on the storage class */
     if (sym->onStack || sym->iaccess) {
+       emitcode("", "; AOP_STK for %s", sym->rname);
         sym->aop = aop = newAsmop(AOP_STK);
         aop->size = getSize(sym->type);
-
        aop->aopu.aop_stk = sym->stack;
         return aop;
     }
@@ -240,10 +373,26 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
         return aop;
     }
 
+    if (IS_GB) {
+       /* if it is in direct space */
+       if (IN_REGSP(space) && !requires_a) {
+           sym->aop = aop = newAsmop (AOP_SFR);
+           aop->aopu.aop_dir = sym->rname ;
+           aop->size = getSize(sym->type);
+           emitcode("", "; AOP_SFR for %s", sym->rname);
+           return aop;
+       }
+    }
+
     /* only remaining is far space */
     /* in which case DPTR gets the address */
-    sym->aop = aop = newAsmop(AOP_IY);
-    emitcode ("ld","iy,#%s", sym->rname);
+    if (IS_GB) {
+       emitcode("", "; AOP_HL for %s", sym->rname);
+       sym->aop = aop = newAsmop(AOP_HL);
+    }
+    else {
+       sym->aop = aop = newAsmop(AOP_IY);
+    }
     aop->size = getSize(sym->type);
     aop->aopu.aop_dir = sym->rname;
 
@@ -266,6 +415,7 @@ static asmop *aopForRemat (symbol *sym)
     while (1) {
         /* if plus or minus print the right hand side */
         if (ic->op == '+' || ic->op == '-') {
+           /* PENDING: for re-target */
             sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
                     ic->op );
             s += strlen(s);
@@ -339,10 +489,10 @@ bool operandsEqu ( operand *op1, operand *op2)
 
     /* if they are the same */
     if (sym1 == sym2)
-        return TRUE ;
+        return 1;
 
     if (strcmp(sym1->rname,sym2->rname) == 0)
-        return TRUE;
+        return 2;
 
 
     /* if left is a tmp & right is not */
@@ -350,15 +500,16 @@ bool operandsEqu ( operand *op1, operand *op2)
         !IS_ITEMP(op2) &&
         sym1->isspilt  &&
         (sym1->usl.spillLoc == sym2))
-        return TRUE;
+        return 3;
 
     if (IS_ITEMP(op2)  && 
         !IS_ITEMP(op1) &&
         sym2->isspilt  &&
+       sym1->level > 0 &&
         (sym2->usl.spillLoc == sym1))
-        return TRUE ;
+        return 4;
 
-    return FALSE ;
+    return FALSE;
 }
 
 /*-----------------------------------------------------------------*/
@@ -368,12 +519,16 @@ bool sameRegs (asmop *aop1, asmop *aop2 )
 {
     int i;
 
-    if (aop1 == aop2)
-        return TRUE ;
+    if (aop1->type == AOP_SFR ||
+       aop2->type == AOP_SFR)
+       return FALSE;
+
+    if (aop1 == aop2) 
+        return TRUE;
 
     if (aop1->type != AOP_REG ||
         aop2->type != AOP_REG )
-        return FALSE ;
+        return FALSE;
 
     if (aop1->size != aop2->size)
         return FALSE ;
@@ -389,7 +544,7 @@ bool sameRegs (asmop *aop1, asmop *aop2 )
 /*-----------------------------------------------------------------*/
 /* aopOp - allocates an asmop for an operand  :                    */
 /*-----------------------------------------------------------------*/
-static void aopOp (operand *op, iCode *ic, bool result)
+static void aopOp (operand *op, iCode *ic, bool result, bool requires_a)
 {
     asmop *aop;
     symbol *sym;
@@ -418,7 +573,7 @@ static void aopOp (operand *op, iCode *ic, bool result)
 
     /* if this is a true symbol */
     if (IS_TRUE_SYMOP(op)) {    
-        op->aop = aopForSym(ic,OP_SYMBOL(op),result);
+        op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a);
         return ;
     }
 
@@ -453,11 +608,22 @@ static void aopOp (operand *op, iCode *ic, bool result)
 
        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->accuse == ACCUSE_A) {
+               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];
+           }
+           else if (sym->accuse == ACCUSE_HL) {
+               wassert(!IS_GB);
+               aop = op->aop = sym->aop = newAsmop(AOP_HLREG);
+               aop->size = getSize(sym->type);
+               for ( i = 0 ; i < 2 ; i++ )
+                   aop->aopu.aop_str[i] = hlUse[i];
+           }
+           else
+               wassert(0);
+           return;
        }
 
         if (sym->ruonly ) {
@@ -465,13 +631,13 @@ static void aopOp (operand *op, iCode *ic, bool result)
             aop = op->aop = sym->aop = newAsmop(AOP_STR);
             aop->size = getSize(sym->type);
             for ( i = 0 ; i < 4 ; i++ )
-                aop->aopu.aop_str[i] = fReturn[i];
+                aop->aopu.aop_str[i] = _fReturn[i];
             return;
         }
 
         /* else spill location  */
         sym->aop = op->aop = aop = 
-                                  aopForSym(ic,sym->usl.spillLoc,result);
+                                  aopForSym(ic,sym->usl.spillLoc,result, requires_a);
         aop->size = getSize(sym->type);
         return;
     }
@@ -503,11 +669,6 @@ static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
 
     aop->freed = 1;
 
-    switch (aop->type) {
-    case AOP_STK :
-       break;
-    }
-
 dealloc:
     /* all other cases just dealloc */
     if (op ) {
@@ -521,43 +682,41 @@ dealloc:
     }
 }
 
-/*-----------------------------------------------------------------*/
-/* aopLiteral - string from a literal value                        */
-/*-----------------------------------------------------------------*/
-char *aopLiteral (value *val, int offset)
+bool isLitWord(asmop *aop)
 {
-    char *rs;
-
-    /* if it is a float then it gets tricky */
-    /* otherwise it is fairly simple */
-    if (!IS_FLOAT(val->type)) {
-        unsigned long v = floatFromVal(val);
-
-        v >>= (offset * 8);
-        sprintf(buffer,"#0x%02x",((char) v) & 0xff);
-        ALLOC_ATOMIC(rs,strlen(buffer)+1);
-        return strcpy (rs,buffer);
+    /*    if (aop->size != 2)
+         return FALSE;*/
+    switch (aop->type) {
+    case AOP_IMMD:
+    case AOP_LIT:
+       return TRUE;
+    default:
+       return FALSE;
     }
-
-    assert(0);
 }
 
-char *aopGetWord(asmop *aop, int offset)
+char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
 {
     char *s = buffer ;
     char *rs;
 
-    assert(aop->size == 2);
-    assert(offset == 0);
-
+#if 0
+    if (aop->size != 2 && aop->type != AOP_HL)
+       return NULL;
+#endif
     /* depending on type */
     switch (aop->type) {
+    case AOP_HL:
+    case AOP_IY:
     case AOP_IMMD:
-       sprintf (s,"#%s",aop->aopu.aop_immd);
+       /* PENDING: for re-target */
+       if (with_hash)
+           tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
+       else
+           tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset);
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
-       
     case AOP_LIT: {
        value * val = aop->aopu.aop_lit;
        /* if it is a float then it gets tricky */
@@ -565,26 +724,250 @@ char *aopGetWord(asmop *aop, int offset)
        if (!IS_FLOAT(val->type)) {
            unsigned long v = floatFromVal(val);
 
-           sprintf(buffer,"#0x%04lx", v);
+           if (offset == 2)
+               v >>= 16;
+
+           if (with_hash)
+               tsprintf(buffer, "!immedword", v);
+           else
+               tsprintf(buffer, "!constword", v);
            ALLOC_ATOMIC(rs,strlen(buffer)+1);
            return strcpy (rs,buffer);
        }
-       assert(0);
+       else {
+           /* A float */
+           Z80_FLOAT f;
+           convertFloat(&f, floatFromVal(val));
+           if (with_hash) 
+               tsprintf(buffer, "!immedword", f.w[offset/2]);
+           else
+               tsprintf(buffer, "!constword", f.w[offset/2]);
+           ALLOC_ATOMIC(rs,strlen(buffer)+1);
+           return strcpy (rs,buffer);
+       }
+    }
+    default:
        return NULL;
     }
+}
+
+char *aopGetWord(asmop *aop, int offset)
+{
+    return aopGetLitWordLong(aop, offset, TRUE);
+}
+
+bool isPtr(const char *s) 
+{
+    if (!strcmp(s, "hl"))
+       return TRUE;
+    if (!strcmp(s, "ix"))
+       return TRUE;
+    if (!strcmp(s, "iy"))
+       return TRUE;
+    return FALSE;
+}
+
+static void adjustPair(const char *pair, int *pold, int new)
+{
+    wassert(pair);
+
+    while (*pold < new) {
+       emitcode("inc", "%s", pair);
+       (*pold)++;
+    }
+    while (*pold > new) {
+       emitcode("dec", "%s", pair);
+       (*pold)--;
     }
-    return NULL;
+}
+
+static void spillPair(PAIR_ID pairId)
+{
+    _G.pairs[pairId].last_type = AOP_INVALID;
+    _G.pairs[pairId].lit = NULL;
+}
+
+static void spillCached(void)
+{
+    spillPair(PAIR_HL);
+    spillPair(PAIR_IY);
+}
+
+static bool requiresHL(asmop *aop)
+{
+    switch (aop->type) {
+    case AOP_HL:
+    case AOP_STK:
+       return TRUE;
+    default:
+       return FALSE;
+    }
+}
+
+static char *fetchLitSpecial(asmop *aop, bool negate, bool xor)
+{
+    unsigned long v;
+    value * val = aop->aopu.aop_lit;
+
+    wassert(aop->type == AOP_LIT);
+    wassert(!IS_FLOAT(val->type));
+    
+    v = floatFromVal(val);
+
+    if (xor)
+       v ^= 0x8000;
+    if (negate)
+       v = -v;
+    v &= 0xFFFF;
+
+    tsprintf(buffer, "!immedword", v);
+    return gc_strdup(buffer);
+}
+
+static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
+{
+    const char *l;
+    const char *pair = _pairs[pairId].name;
+    l = aopGetLitWordLong(left, 0, FALSE);
+    wassert(l && pair);
+
+    if (isPtr(pair)) {
+       if (pairId == PAIR_HL || pairId == PAIR_IY) {
+           if (_G.pairs[pairId].last_type == left->type) {
+               if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
+                   if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
+                       adjustPair(pair, &_G.pairs[pairId].offset, offset);
+                       return;
+                   }
+                   if (pairId == PAIR_IY && abs(offset)<127) {
+                       return;
+                   }
+               }
+           }
+       }
+       _G.pairs[pairId].last_type = left->type;
+       _G.pairs[pairId].lit = gc_strdup(l);
+       _G.pairs[pairId].offset = offset;
+    }
+    if (IS_GB && pairId == PAIR_DE && 0) {
+       if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
+           if (abs(_G.pairs[pairId].offset - offset) < 3) {
+               adjustPair(pair, &_G.pairs[pairId].offset, offset);
+               return;
+           }
+       }
+       _G.pairs[pairId].last_type = left->type;
+       _G.pairs[pairId].lit = gc_strdup(l);
+       _G.pairs[pairId].offset = offset;
+    }
+    /* Both a lit on the right and a true symbol on the left */
+    if (offset)
+       emit2("ld %s,!hashedstr + %u", pair, l, offset);
+    else
+       emit2("ld %s,!hashedstr", pair, l);
+}
+
+static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
+{
+    /* if this is remateriazable */
+    if (isLitWord(aop)) {
+       fetchLitPair(pairId, aop, offset);
+    }
+    else { /* we need to get it byte by byte */
+       if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
+           aopGet(aop, offset, FALSE);
+           switch (aop->size) {
+           case 1:
+               emit2("ld l,!*hl");
+               emit2("ld h,!immedbyte", 0);
+               break;
+           case 2:
+               emit2("!ldahli");
+               emit2("ld h,!*hl");
+               emit2("ld l,a");
+               break;
+           default:
+               emit2("; WARNING: mlh woosed out.  This code is invalid.");
+           }
+       }
+       else if (IS_Z80 && aop->type == AOP_IY) {
+           /* Instead of fetching relative to IY, just grab directly
+              from the address IY refers to */
+           char *l = aopGetLitWordLong(aop, offset, FALSE);
+           wassert(l);
+           emit2("ld %s,(%s)", _pairs[pairId].name, l);
+       }
+       else {
+           emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
+           emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
+       }
+       /* PENDING: check? */
+       if (pairId == PAIR_HL)
+           spillPair(PAIR_HL);
+    }
+}
+
+static void fetchPair(PAIR_ID pairId, asmop *aop)
+{
+    fetchPairLong(pairId, aop, 0);
+}
+
+static void fetchHL(asmop *aop)
+{
+    fetchPair(PAIR_HL, aop);
+}
+
+static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
+{
+    assert(pairId == PAIR_HL || pairId == PAIR_IY);
+
+    switch (aop->type) {
+    case AOP_IY:
+       fetchLitPair(pairId, aop, 0);
+       break;
+    case AOP_HL:
+       fetchLitPair(pairId, aop, offset);
+       _G.pairs[pairId].offset = offset;
+       break;
+    case AOP_STK: {
+       /* Doesnt include _G.stack.pushed */
+       int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
+       if (aop->aopu.aop_stk > 0) {
+           abso += _G.stack.param_offset;
+       }
+       assert(pairId == PAIR_HL);
+       /* In some cases we can still inc or dec hl */
+       if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
+           adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
+       }
+       else {
+           emit2("!ldahlsp", abso +_G.stack.pushed);
+       }
+       _G.pairs[pairId].offset = abso;
+       break;
+    }
+    default:
+       wassert(0);
+    }
+    _G.pairs[pairId].last_type = aop->type;
+}
+
+static void emitLabel(int key)
+{
+    emit2("!tlabeldef", key);
+    spillCached();
 }
 
 /*-----------------------------------------------------------------*/
 /* aopGet - for fetching value of the aop                          */
 /*-----------------------------------------------------------------*/
-static char *aopGet (asmop *aop, int offset, bool bit16)
+static char *aopGet(asmop *aop, int offset, bool bit16)
 {
     char *s = buffer ;
     char *rs;
 
     /* offset is greater than size then zero */
+    /* PENDING: this seems a bit screwed in some pointer cases. */
     if (offset > (aop->size - 1) &&
         aop->type != AOP_LIT)
         return zero;
@@ -592,52 +975,84 @@ static char *aopGet (asmop *aop, int offset, bool bit16)
     /* depending on type */
     switch (aop->type) {
     case AOP_IMMD:
+       /* PENDING: re-target */
        if (bit16) 
-           sprintf (s,"#%s",aop->aopu.aop_immd);
+           tsprintf (s,"!immedwords", aop->aopu.aop_immd);
        else
-           if (offset) {
-               assert(offset == 1);
-               sprintf(s,"#>%s",
-                       aop->aopu.aop_immd);
+           switch (offset) {
+           case 2:
+               tsprintf(s, "!bankimmeds", aop->aopu.aop_immd);
+               break;
+           case 1:
+               tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
+               break;
+           case 0:
+               tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
+               break;
+           default:
+               wassert(0);
            }
-           else
-               sprintf(s,"#<%s",
-                       aop->aopu.aop_immd);
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
        
     case AOP_DIR:
-       assert(0);
-       emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
+       wassert(IS_GB);
+       emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
        sprintf(s, "a");
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
        
+    case AOP_SFR:
+       wassert(IS_GB);
+       emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
+       sprintf(s, "a");
+       ALLOC_ATOMIC(rs,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+
     case AOP_REG:
        return aop->aopu.aop_reg[offset]->name;
 
+    case AOP_HL:
+       wassert(IS_GB);
+       setupPair(PAIR_HL, aop, offset);
+       tsprintf(s, "!*hl");
+       return gc_strdup(s);
+
     case AOP_IY:
-       sprintf(s,"%d(iy)", offset);
+       wassert(IS_Z80);
+       setupPair(PAIR_IY, aop, offset);
+       tsprintf(s,"!*iyx", offset);
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
 
     case AOP_STK:
-       sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+       if (IS_GB) {
+           setupPair(PAIR_HL, aop, offset);
+           tsprintf(s, "!*hl");
+       }
+       else {
+           tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
+       }
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
        
     case AOP_CRY:
-       assert(0);
+       wassert(0);
        
     case AOP_ACC:
        if (!offset) {
            return "a";
        }
-       return "#0x00";
+       return "!zero";
+
+    case AOP_HLREG:
+       wassert(offset < 2);
+       return aop->aopu.aop_str[offset];
 
     case AOP_LIT:
        return aopLiteral (aop->aopu.aop_lit,offset);
@@ -645,16 +1060,14 @@ static char *aopGet (asmop *aop, int offset, bool bit16)
     case AOP_STR:
        aop->coff = offset;
        return aop->aopu.aop_str[offset];
+    default:
+       break;
     }
-
-    fprintf(stderr, "Type %u\n", aop->type);
-
-    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
-           "aopget got unsupported aop->type");
+    wassertl(0, "aopget got unsupported aop->type");
     exit(0);
 }
 
-bool isRegString(char *s)
+bool isRegString(const char *s)
 {
     if (!strcmp(s, "b") ||
        !strcmp(s, "c") ||
@@ -667,12 +1080,13 @@ bool isRegString(char *s)
     return FALSE;
 }
 
-bool isConstant(char *s)
+bool isConstant(const char *s)
 {
-    return  (*s == '#');
+    /* This is a bit of a hack... */
+    return  (*s == '#' || *s == '$');
 }
 
-bool canAssignToPtr(char *s)
+bool canAssignToPtr(const char *s)
 {
     if (isRegString(s))
        return TRUE;
@@ -684,10 +1098,8 @@ bool canAssignToPtr(char *s)
 /*-----------------------------------------------------------------*/
 /* aopPut - puts a string for a aop                                */
 /*-----------------------------------------------------------------*/
-static void aopPut (asmop *aop, char *s, int offset)
+static void aopPut (asmop *aop, const char *s, int offset)
 {
-    char *d = buffer ;
-
     if (aop->size && offset > ( aop->size - 1)) {
         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
                "aopPut got offset > aop->size");
@@ -698,46 +1110,84 @@ static void aopPut (asmop *aop, char *s, int offset)
     /* depending on where it is ofcourse */
     switch (aop->type) {
     case AOP_DIR:
-       assert(0);
        /* Direct.  Hmmm. */
-       emitcode("ld", "a,%s", s);
-       emitcode("ld", "(%s+%d),a", d, offset);
+       wassert(IS_GB);
+       if (strcmp(s, "a"))
+           emitcode("ld", "a,%s", s);
+       emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
+       break;
+       
+    case AOP_SFR:
+       wassert(IS_GB);
+       if (strcmp(s, "a"))
+           emitcode("ld", "a,%s", s);
+       emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
        break;
        
     case AOP_REG:
-       /* Dont bother if it's a ld x,x */
-       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
-           emitcode("ld","%s,%s",
-                    aop->aopu.aop_reg[offset]->name,s);
-       }
+       if (!strcmp(s, "!*hl"))
+           emit2("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
+       else
+           emit2("ld %s,%s",
+                 aop->aopu.aop_reg[offset]->name, s);
        break;
        
     case AOP_IY:
+       wassert(!IS_GB);
+       setupPair(PAIR_IY, aop, offset);
        if (!canAssignToPtr(s)) {
-           emitcode("ld", "a,%s", s);
-           emitcode("ld", "%d(iy),a", offset);
+           emit2("ld a,%s", s);
+           emit2("ld !*iyx,a", offset);
        }
        else
-           emitcode("ld", "%d(iy),%s", offset, s);
+           emit2("ld !*iyx,%s", offset, s);
        break;
+    
+    case AOP_HL:
+       wassert(IS_GB);
+       /* PENDING: for re-target */
+       if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
+           emit2("ld a,!*hl");
+           s = "a";
+       }
+       setupPair(PAIR_HL, aop, offset);
        
+       emit2("ld !*hl,%s", s);
+       break;
+
     case AOP_STK:
-       if (!canAssignToPtr(s)) {
-           emitcode("ld", "a,%s", s);
-           emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
+       if (IS_GB) {
+           /* PENDING: re-target */
+           if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
+               emit2("ld a,!*hl");
+               s = "a";
+           }
+           setupPair(PAIR_HL, aop, offset);
+           if (!canAssignToPtr(s)) {
+               emit2("ld a,%s", s);
+               emit2("ld !*hl,a");
+           }
+           else
+               emit2("ld !*hl,%s", s);
+       }
+       else {
+           if (!canAssignToPtr(s)) {
+               emit2("ld a,%s", s);
+               emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
+           }
+           else
+               emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
        }
-       else
-           emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
        break;
        
     case AOP_CRY:
        /* if bit variable */
        if (!aop->aopu.aop_dir) {
-           emitcode("ld", "a,#0");
-           emitcode("rla", "");
+           emit2("ld a,#0");
+           emit2("rla");
        } else {
            /* In bit space but not in C - cant happen */
-           assert(0);
+           wassert(0);
        }
        break;
        
@@ -753,6 +1203,7 @@ static void aopPut (asmop *aop, char *s, int offset)
        if (!offset && (strcmp(s,"acc") == 0))
            break;
        if (offset>0) {
+           
            emitcode("", "; Error aopPut AOP_ACC");
        }
        else {
@@ -761,6 +1212,11 @@ static void aopPut (asmop *aop, char *s, int offset)
        }
        break;
 
+    case AOP_HLREG:
+       wassert(offset < 2);
+       emit2("ld %s,%s", aop->aopu.aop_str[offset], s);
+       break;
+
     default :
        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
               "aopPut got unsupported aop->type");
@@ -773,6 +1229,20 @@ static void aopPut (asmop *aop, char *s, int offset)
 #define AOP_SIZE(op) AOP(op)->size
 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
 
+static void commitPair(asmop *aop, PAIR_ID id)
+{
+    if (id == PAIR_HL && requiresHL(aop)) {
+       emit2("ld a,l");
+       emit2("ld d,h");
+       aopPut(aop, "a", 0);
+       aopPut(aop, "d", 1);
+    }
+    else {
+       aopPut(aop, _pairs[id].l, 0);
+       aopPut(aop, _pairs[id].h, 1);
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* getDataSize - get the operand data size                         */
 /*-----------------------------------------------------------------*/
@@ -782,7 +1252,7 @@ int getDataSize(operand *op)
     size = AOP_SIZE(op);
     if(size == 3) {
         /* pointer */
-       assert(0);
+       wassert(0);
     }
     return size;
 }
@@ -801,7 +1271,7 @@ static void movLeft2Result (operand *left, int offl,
            aopPut(AOP(result),l,offr);
        }
        else {
-           assert(0);
+           wassert(0);
         }
     }
 }
@@ -819,14 +1289,14 @@ void outAcc(operand *result)
         offset = 1;
         /* unsigned or positive */
         while (size--){
-            aopPut(AOP(result),zero,offset++);
+            aopPut(AOP(result), zero, offset++);
         }
     }
 }
 
 /** Take the value in carry and put it into a register
  */
-void outBitC(operand *result)
+void outBitCLong(operand *result, bool swap_sense)
 {
     /* if the result is bit */
     if (AOP_TYPE(result) == AOP_CRY) {
@@ -834,12 +1304,19 @@ void outBitC(operand *result)
         aopPut(AOP(result),"blah",0);
     }
     else {
-       emitcode("ld", "a,#0");
-       emitcode("rla", "");
+       emit2("ld a,!zero");
+       emit2("rla");
+       if (swap_sense)
+           emit2("xor a,!immedbyte", 1);
         outAcc(result);
     }
 }
 
+void outBitC(operand *result)
+{
+    outBitCLong(result, FALSE);
+}
+
 /*-----------------------------------------------------------------*/
 /* toBoolean - emit code for orl a,operator(sizeop)                */
 /*-----------------------------------------------------------------*/
@@ -854,8 +1331,10 @@ void toBoolean(operand *oper)
            emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
     }
     else {
-       CLRC;
-       emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
+       if (AOP(oper)->type != AOP_ACC) {
+           CLRC;
+           emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
+       }
     }
 }
 
@@ -867,17 +1346,17 @@ static void genNot (iCode *ic)
     link *optype = operandType(IC_LEFT(ic));
 
     /* assign asmOps to operand & result */
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+    aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
+    aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
 
     /* if in bit space then a special case */
     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
-       assert(0);
+       wassert(0);
     }
 
     /* if type float then do float */
     if (IS_FLOAT(optype)) {
-       assert(0);
+       wassert(0);
     }
 
     toBoolean(IC_LEFT(ic));
@@ -886,7 +1365,7 @@ static void genNot (iCode *ic)
        If A == 0, !A = 1
        else A = 0
        So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
-    emitcode("sub", "a,#0x01");
+    emit2("sub a,!one");
     outBitC(IC_RESULT(ic));
 
     /* release the aops */
@@ -904,14 +1383,14 @@ static void genCpl (iCode *ic)
 
 
     /* assign asmOps to operand & result */
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+    aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
+    aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
 
     /* if both are in bit space then 
     a special case */
     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
-       assert(0);
+       wassert(0);
     } 
 
     size = AOP_SIZE(IC_RESULT(ic));
@@ -932,7 +1411,66 @@ static void genCpl (iCode *ic)
 /*-----------------------------------------------------------------*/
 static void genUminus (iCode *ic)
 {
-    assert(0);
+    int offset ,size ;
+    link *optype, *rtype;
+
+    /* assign asmops */
+    aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
+    aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
+
+    /* if both in bit space then special
+    case */
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
+        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
+       wassert(0);
+        goto release;
+    } 
+
+    optype = operandType(IC_LEFT(ic));
+    rtype = operandType(IC_RESULT(ic));
+
+    /* if float then do float stuff */
+    if (IS_FLOAT(optype)) {
+       wassert(0);
+        goto release;
+    }
+
+    /* otherwise subtract from zero */
+    size = AOP_SIZE(IC_LEFT(ic));
+    offset = 0 ;
+    CLRC ;
+    while(size--) {
+        char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
+       emit2("ld a,!zero");
+       emit2("sbc a,%s",l);
+        aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+    }
+
+    /* if any remaining bytes in the result */
+    /* we just need to propagate the sign   */
+    if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
+        emit2("rlc a");
+        emit2("sbc a,a");
+        while (size--) 
+            aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+    }       
+
+release:
+    /* release the aops */
+    freeAsmop(IC_LEFT(ic),NULL,ic);
+    freeAsmop(IC_RESULT(ic),NULL,ic);
+}
+
+static void _push(PAIR_ID pairId)
+{
+    emit2("push %s", _pairs[pairId].name);
+    _G.stack.pushed += 2;
+}
+
+static void _pop(PAIR_ID pairId)
+{
+    emit2("pop %s", _pairs[pairId].name);
+    _G.stack.pushed -= 2;
 }
 
 
@@ -941,11 +1479,30 @@ static void genUminus (iCode *ic)
 /*-----------------------------------------------------------------*/
 void assignResultValue(operand * oper)
 {
-    int offset = 0;
     int size = AOP_SIZE(oper);
-    while (size--) {
-       aopPut(AOP(oper),fReturn[offset],offset);
-       offset++;
+    bool topInA = 0;
+
+    wassert(size <= 4);
+    topInA = requiresHL(AOP(oper));
+
+#if 0
+    if (!IS_GB)
+       wassert(size <= 2);
+#endif
+    if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
+       /* We do it the hard way here. */
+       _push(PAIR_HL);
+       aopPut(AOP(oper), _fReturn[0], 0);
+       aopPut(AOP(oper), _fReturn[1], 1);
+       emitcode("pop", "de");
+       _G.stack.pushed -= 2;
+       aopPut(AOP(oper), _fReturn[0], 2);
+       aopPut(AOP(oper), _fReturn[1], 3);
+    }
+    else {
+       while (size--) {
+           aopPut(AOP(oper), _fReturn[size], size);
+       }
     }
 }
 
@@ -957,7 +1514,6 @@ static void genIpush (iCode *ic)
     int size, offset = 0 ;
     char *l;
 
-
     /* if this is not a parm push : ie. it is spill push 
        and spill push is always done on the local stack */
     if (!ic->parmPush) {
@@ -965,20 +1521,29 @@ static void genIpush (iCode *ic)
         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
             return ;
 
-        aopOp(IC_LEFT(ic),ic,FALSE);
+        aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
         size = AOP_SIZE(IC_LEFT(ic));
         /* push it on the stack */
        if (isPair(AOP(IC_LEFT(ic)))) {
            emitcode("push", getPairName(AOP(IC_LEFT(ic))));
+           _G.stack.pushed += 2;
        }
        else {
            offset = size;
            while (size--) {
-               l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
                /* Simple for now - load into A and PUSH AF */
-               emitcode("ld", "a,%s", l);
-               emitcode("push", "af");
-               emitcode("inc", "sp");
+               if (AOP(IC_LEFT(ic))->type == AOP_IY) {
+                   char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
+                   wassert(l);
+                   emit2("ld a,(%s)", l);
+               }
+               else {
+                   l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
+                   emit2("ld a,%s", l);
+               }
+               emit2("push af");
+               emit2("inc sp");
+               _G.stack.pushed++;
            }
        }
        return ;        
@@ -988,28 +1553,47 @@ static void genIpush (iCode *ic)
        at this point? */
 
     /* then do the push */
-    aopOp(IC_LEFT(ic),ic,FALSE);
+    aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
 
     size = AOP_SIZE(IC_LEFT(ic));
 
     if (isPair(AOP(IC_LEFT(ic)))) {
+       _G.stack.pushed+=2;
        emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
     }
     else {
        if (size == 2) {
-           char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
-           if (s) {
-               emitcode("ld", "hl,%s", s);
-               emitcode("push", "hl");
-               goto release;
-           }
+           fetchHL(AOP(IC_LEFT(ic)));
+           emitcode("push", "hl");
+           spillPair(PAIR_HL);
+           _G.stack.pushed += 2;
+           goto release;
+       }
+       if (size == 4) {
+           fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
+           emitcode("push", "hl");
+           spillPair(PAIR_HL);
+           _G.stack.pushed += 2;
+           fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 0);
+           emitcode("push", "hl");
+           spillPair(PAIR_HL);
+           _G.stack.pushed += 2;
+           goto release;
        }
        offset = size;
        while (size--) {
-           l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
-           emitcode("ld", "a,%s", l);
+           if (AOP(IC_LEFT(ic))->type == AOP_IY) {
+               char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
+               wassert(l);
+               emit2("ld a,(%s)", l);
+           }
+           else {
+               l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
+               emit2("ld a,%s", l);
+           }
            emitcode("push", "af");
            emitcode("inc", "sp");
+           _G.stack.pushed++;
        }       
     }
  release:
@@ -1028,7 +1612,7 @@ static void genIpop (iCode *ic)
     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
         return ;
 
-    aopOp(IC_LEFT(ic),ic,FALSE);
+    aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
     size = AOP_SIZE(IC_LEFT(ic));
     offset = (size-1);
     if (isPair(AOP(IC_LEFT(ic)))) {
@@ -1038,6 +1622,7 @@ static void genIpop (iCode *ic)
        while (size--) {
            emitcode("dec", "sp");
            emitcode("pop", "hl");
+           spillPair(PAIR_HL);
            aopPut(AOP(IC_LEFT(ic)), "l", offset--);
        }
     }
@@ -1045,58 +1630,193 @@ static void genIpop (iCode *ic)
     freeAsmop(IC_LEFT(ic),NULL,ic);
 }
 
+static int _isPairUsed(iCode *ic, PAIR_ID pairId)
+{
+    int ret = 0;
+    switch (pairId) {
+    case PAIR_DE:
+       if (bitVectBitValue(ic->rUsed, D_IDX))
+           ret++;
+       if (bitVectBitValue(ic->rUsed, E_IDX))
+           ret++;
+       break;
+    default:
+       wassert(0);
+    }
+    return ret;
+}
+
+static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
+{
+    int ret = 0;
+    asmop *aop;
+    symbol *sym = OP_SYMBOL(op);
+
+    if (sym->isspilt || sym->nRegs == 0)
+       return 0;
+
+    aopOp(op, ic, FALSE, FALSE);
+    
+    aop = AOP(op);
+    if (aop->type == AOP_REG) {
+       int i;
+       for (i=0; i < aop->size; i++) {
+           if (pairId == PAIR_DE) {
+               emit2("; name %s", aop->aopu.aop_reg[i]->name);
+               if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
+                   ret++;
+               if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
+                   ret++;
+           }
+           else {
+               wassert(0);
+           }
+       }
+    }
+
+    freeAsmop(IC_LEFT(ic),NULL,ic);
+    return ret;
+}
+
+/* This is quite unfortunate */
+static void setArea(int inHome)
+{
+    static int lastArea = 0;
+
+    /*    
+    if (_G.in_home != inHome) {
+       if (inHome) {
+           const char *sz = port->mem.code_name;
+           port->mem.code_name = "HOME";
+           emit2("!area", CODE_NAME);
+           port->mem.code_name = sz;
+       }
+       else
+       emit2("!area", CODE_NAME);*/
+       _G.in_home = inHome;
+       //    }
+}
+
+static bool isInHome(void)
+{
+    return _G.in_home;
+}
+
 /** Emit the code for a call statement 
  */
-static void emitCall (iCode *ic, bool ispcall)
+static void emitCall(iCode *ic, bool ispcall)
 {
+    int pushed_de = 0;
+    link *detype = getSpec(operandType(IC_LEFT(ic)));
+
     /* if caller saves & we have not saved then */
     if (!ic->regsSaved) {
        /* PENDING */
     }
-
+    
     /* if send set is not empty then assign */
     if (sendSet) {
-       iCode *sic ;
-
-       for (sic = setFirstItem(sendSet) ; sic ; 
-            sic = setNextItem(sendSet)) {
-           int size, offset = 0;
-           aopOp(IC_LEFT(sic),sic,FALSE);
-           size = AOP_SIZE(IC_LEFT(sic));
-           while (size--) {
-               char *l = aopGet(AOP(IC_LEFT(sic)),offset,
-                               FALSE);
-               if (strcmp(l,fReturn[offset]))
-                   emitcode("ld","%s,%s",
-                            fReturn[offset],
-                            l);
-               offset++;
+       iCode *sic;
+       int send = 0;
+       int n = elementsInSet(sendSet);
+       if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
+           /* Only push de if it is used and if it's not used
+              in the return value */
+           /* Panic if partly used */
+           if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
+               emit2("; Warning: de crossover");
+           }
+           else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
+               /* Store away de */
+               _push(PAIR_DE);
+               pushed_de = 1;
            }
+       }
+       /* PENDING: HACK */
+       if (IS_Z80 && n == 2 ) {
+           /* Want to load HL first, then DE as HL may = DE */
+           sic = setFirstItem(sendSet);
+           sic = setNextItem(sendSet);
+           aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+           fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+           send++;
+           freeAsmop (IC_LEFT(sic),NULL,sic);
+           sic = setFirstItem(sendSet);
+           aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+           fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
+           send++;
            freeAsmop (IC_LEFT(sic),NULL,sic);
        }
+       else {
+           for (sic = setFirstItem(sendSet) ; sic ; 
+                sic = setNextItem(sendSet)) {
+               int size;
+               aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
+               size = AOP_SIZE(IC_LEFT(sic));
+               wassert(size <= 2);
+               /* Always send in pairs */
+               switch (send) {
+               case 0:
+                   if (IS_Z80 && n == 1)
+                       fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+                   else
+                       fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
+                   break;
+               case 1:
+                   fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
+                   break;
+               default:
+                   /* Send set too big */
+                   wassert(0);
+               }
+               send++;
+               freeAsmop (IC_LEFT(sic),NULL,sic);
+           }
+       }
        sendSet = NULL;
+       if (pushed_de) {
+       }
     }
 
     if (ispcall) {
-       symbol *rlbl = newiTempLabel(NULL);
-
-       emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
-       emitcode("push", "hl");
+       if (IS_BANKEDCALL(detype)) {
+           werror(W_INDIR_BANKED);
+       }
+       aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
 
-       aopOp(IC_LEFT(ic),ic,FALSE);
-       emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
-       emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
+       if (isLitWord(AOP(IC_LEFT(ic)))) {
+           emitcode("", "; Special case where the pCall is to a constant");
+           emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
+       }
+       else {
+           symbol *rlbl = newiTempLabel(NULL);
+           spillPair(PAIR_HL);
+           emit2("ld hl,!immed!tlabel", (rlbl->key+100));
+           emitcode("push", "hl");
+           _G.stack.pushed += 2;
+           
+           fetchHL(AOP(IC_LEFT(ic)));
+           emit2("jp !*hl");
+           emit2("!tlabeldef", (rlbl->key+100));
+           _G.stack.pushed -= 2;
+       }
        freeAsmop(IC_LEFT(ic),NULL,ic); 
-       
-       emitcode("jp", "(hl)");
-       emitcode("","%05d$:",(rlbl->key+100));
     }
     else {
-       /* make the call */
-       emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
-                               OP_SYMBOL(IC_LEFT(ic))->rname :
-                               OP_SYMBOL(IC_LEFT(ic))->name));
+       char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
+           OP_SYMBOL(IC_LEFT(ic))->rname :
+           OP_SYMBOL(IC_LEFT(ic))->name;
+       if (IS_BANKEDCALL(detype)) {
+           emit2("call banked_call");
+           emit2("!dws", name);
+           emit2("!dw !bankimmeds", name);
+       }
+       else {
+           /* make the call */
+           emit2("call %s", name);
+       }
     }
+    spillCached();
 
     /* if we need assign a result value */
     if ((IS_ITEMP(IC_RESULT(ic)) && 
@@ -1105,7 +1825,7 @@ static void emitCall (iCode *ic, bool ispcall)
         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
 
         accInUse++;
-        aopOp(IC_RESULT(ic),ic,FALSE);
+        aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
         accInUse--;
 
        assignResultValue(IC_RESULT(ic));
@@ -1116,15 +1836,30 @@ static void emitCall (iCode *ic, bool ispcall)
     /* adjust the stack for parameters if required */
     if (IC_LEFT(ic)->parmBytes) {
        int i = IC_LEFT(ic)->parmBytes;
-       /* PENDING: do better */
-       while (i>1) {
-           emitcode("pop", "hl");
-           i-=2;
+       _G.stack.pushed -= i;
+       if (IS_GB) {
+           emit2("!ldaspsp", i);
+       }
+       else {
+           spillCached();
+           if (i>6) {
+               emitcode("ld", "hl,#%d", i);
+               emitcode("add", "hl,sp");
+               emitcode("ld", "sp,hl");
+           }
+           else {
+               while (i>1) {
+                   emitcode("pop", "hl");
+                   i-=2;
+               }
+               if (i) 
+                   emitcode("inc", "sp");
+           }
+           spillCached();
        }
-       if (i) 
-           emitcode("inc", "sp");
     }
-
+    if (pushed_de)
+       _pop(PAIR_DE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1132,6 +1867,7 @@ static void emitCall (iCode *ic, bool ispcall)
 /*-----------------------------------------------------------------*/
 static void genCall (iCode *ic)
 {
+    link *detype = getSpec(operandType(IC_LEFT(ic)));
     emitCall(ic, FALSE);
 }
 
@@ -1160,59 +1896,82 @@ static int resultRemat (iCode *ic)
     return 0;
 }
 
+extern set *publics;
+
 /*-----------------------------------------------------------------*/
 /* genFunction - generated code for function entry                 */
 /*-----------------------------------------------------------------*/
 static void genFunction (iCode *ic)
 {
-    symbol *sym;
+    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
     link *fetype;
 
     nregssaved = 0;
-    /* create the function header */
-    emitcode(";","-----------------------------------------");
-    emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
-    emitcode(";","-----------------------------------------");
+    setArea(IS_NONBANKED(sym->etype));
 
-    emitcode("","%s:",sym->rname);
-    fetype = getSpec(operandType(IC_LEFT(ic)));
+    /* PENDING: hack */
+    if (!IS_STATIC(sym->etype)) {
+       addSetIfnotP(&publics, sym);
+    }
 
+    /* create the function header */
+    emit2("!functionheader", sym->name);
+    /* PENDING: portability. */
+    emit2("__%s_start:", sym->rname);
+    emit2("!functionlabeldef", sym->rname);
+   
+    fetype = getSpec(operandType(IC_LEFT(ic)));
+    
     /* if critical function then turn interrupts off */
     if (SPEC_CRTCL(fetype))
-        emitcode("di","");
+       emit2("!di");
 
     /* if this is an interrupt service routine then
     save acc, b, dpl, dph  */
     if (IS_ISR(sym->etype)) {
-       emitcode("push", "af");
-       emitcode("push", "bc");
-       emitcode("push", "de");
-       emitcode("push", "hl");
-    } else {
-       /* if callee-save to be used for this function
-          then save the registers being used in this function */
-       if (sym->calleeSave) {
-           /* Handled by ncsv/csv */
+       emit2("!pusha");
+    }
+    /* PENDING: callee-save etc */
+
+    /* If BC or DE are used, then push */
+    _G.stack.pushed_bc = 0;
+    _G.stack.pushed_de = 0;
+    _G.stack.param_offset = 0;
+    if (sym->regsUsed) {
+       int i;
+       for ( i = 0 ; i < sym->regsUsed->size ; i++) {
+           if (bitVectBitValue(sym->regsUsed, i)) {
+               switch (i) {
+               case C_IDX:
+               case B_IDX:
+                   _G.stack.pushed_bc = 1;
+                   break;
+               case D_IDX:
+               case E_IDX:
+                   if (IS_Z80)
+                       _G.stack.pushed_de = 1;
+                   break;
+               }
+           }
        }
-       else {
-           assert(0);
+       if (_G.stack.pushed_bc) {
+           emit2("push bc");
+           _G.stack.param_offset += 2;
+       }
+       if (_G.stack.pushed_de) {
+           emit2("push de");
+           _G.stack.param_offset += 2;
        }
     }
 
     /* adjust the stack for the function */
-    emitcode("push", "de"); 
-    emitcode("push", "bc");
-    emitcode("push", "ix");
-    emitcode("ld", "ix,#0");
-    emitcode("add", "ix,sp");
-
-    _lastStack = sym->stack;
-
-    if (sym->stack) {
-       emitcode("ld", "hl,#-%d", sym->stack);
-       emitcode("add", "hl,sp");
-       emitcode("ld", "sp,hl");
-    }    
+    _G.stack.last = sym->stack;
+
+    if (sym->stack)
+       emit2("!enterx", sym->stack);
+    else
+       emit2("!enter");
+    _G.stack.offset = sym->stack;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1223,18 +1982,13 @@ static void genEndFunction (iCode *ic)
     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
 
     if (IS_ISR(sym->etype)) {
-       assert(0);
+       wassert(0);
     }
     else {
         if (SPEC_CRTCL(sym->etype))
-            emitcode("ei", "");
+           emit2("!ei");
        
-       if (sym->calleeSave) {
-           /* Handled by cret */
-       }
-       else {
-           assert(0);
-       }
+       /* PENDING: calleeSave */
 
        /* if debug then send end of function */
        if (options.debug && currFunc) { 
@@ -1248,13 +2002,24 @@ static void genEndFunction (iCode *ic)
                emitcode("","XG$%s$0$0 ==.",currFunc->name);
            debugLine = 0;
        }
-       emitcode("ld", "sp,ix");
-       emitcode("pop", "ix");
-       emitcode("pop", "bc");
-       emitcode("pop", "de");
-       emitcode("ret", "");
+       if (_G.stack.offset)
+           emit2("!leavex", _G.stack.offset);
+       else
+           emit2("!leave");
+
+       if (_G.stack.pushed_de)
+           emit2("pop de");
+       if (_G.stack.pushed_bc)
+           emit2("pop bc");
+       /* Both baned and non-banked just ret */
+       emit2("ret");
+       
+       /* PENDING: portability. */
+       emit2("__%s_end:", sym->rname);
     }
-
+    _G.flush_statics = 1;
+    _G.stack.pushed = 0;
+    _G.stack.offset = 0;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1274,18 +2039,29 @@ static void genRet (iCode *ic)
     
     /* we have something to return then
        move the return value into place */
-    aopOp(IC_LEFT(ic),ic,FALSE);
+    aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
     size = AOP_SIZE(IC_LEFT(ic));
     
     if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
+       if (IS_GB) {
+           emitcode("ld", "de,%s", l);
+       }
+       else {
            emitcode("ld", "hl,%s", l);
+       }
     }
     else {
-       while (size--) {
-           l = aopGet(AOP(IC_LEFT(ic)),offset,
-                      FALSE);
-           if (strcmp(fReturn[offset],l))
-               emitcode("ld","%s,%s",fReturn[offset++],l);
+       if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
+           fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
+           fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
+       }
+       else {
+           while (size--) {
+               l = aopGet(AOP(IC_LEFT(ic)),offset,
+                          FALSE);
+               if (strcmp(_fReturn[offset],l))
+                   emitcode("ld","%s,%s", _fReturn[offset++],l);
+           }
        }
     }
     freeAsmop (IC_LEFT(ic),NULL,ic);
@@ -1296,7 +2072,7 @@ static void genRet (iCode *ic)
     if (!(ic->next && ic->next->op == LABEL &&
          IC_LABEL(ic->next) == returnLabel))
        
-       emitcode("jp",  LABEL_STR ,(returnLabel->key+100));
+       emit2("jp !tlabel", returnLabel->key+100);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1308,7 +2084,7 @@ static void genLabel (iCode *ic)
     if (IC_LABEL(ic) == entryLabel)
         return ;
 
-    emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
+    emitLabel(IC_LABEL(ic)->key+100);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1316,7 +2092,7 @@ static void genLabel (iCode *ic)
 /*-----------------------------------------------------------------*/
 static void genGoto (iCode *ic)
 {
-    emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
+    emit2("jp !tlabel", IC_LABEL(ic)->key+100);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1326,49 +2102,65 @@ static bool genPlusIncr (iCode *ic)
 {
     unsigned int icount ;
     unsigned int size = getDataSize(IC_RESULT(ic));
-    
+    PAIR_ID resultId = getPairId(AOP(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 ;
+    emitcode("", "; genPlusIncr");
 
-    /* Inc a pair */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
-       isPair(AOP(IC_RESULT(ic)))) {
+    icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+    
+    /* If result is a pair */
+    if (resultId != PAIR_INVALID) {
+       if (isLitWord(AOP(IC_LEFT(ic)))) {
+           fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
+           return TRUE;
+       }
+       if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
+           fetchPair(resultId, AOP(IC_RIGHT(ic)));
+           emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
+           return TRUE;
+       }
+       if (icount > 5)
+           return FALSE;
+       /* Inc a pair */
+       if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+           if (icount > 2)
+               return FALSE;
+           movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
+           movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
+       }
        while (icount--) {
            emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
        }
        return TRUE;
     }
+
+    /* if the literal value of the right hand side
+       is greater than 4 then it is not worth it */
+    if (icount > 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 = newiTempLabel(NULL);
-       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
-       emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
-    
-       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
-       if(size == 4) {
-           assert(0);
+        size > 1 &&
+        icount == 1
+       ) {
+       int offset = 0;
+       symbol *tlbl = NULL;
+       tlbl = newiTempLabel(NULL);
+       while (size--) {
+           emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
+           if (size) {
+               emit2("!shortjp nz,!tlabel", tlbl->key+100);
+           }
        }
-       emitcode("", LABEL_STR ":",tlbl->key+100);
-        return TRUE;
-    }
-
-    /* If result is a pair */
-    if (isPair(AOP(IC_RESULT(ic)))) {
-       movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
-       movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
-       while (icount--)
-           emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
-       return TRUE;
+       emitLabel(tlbl->key+100);
+        return TRUE;
     }
 
     /* if the sizes are greater than 1 then we cannot */
@@ -1382,7 +2174,6 @@ static bool genPlusIncr (iCode *ic)
     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
        while (icount--)
            emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
-       
         return TRUE ;
     }
     
@@ -1397,12 +2188,12 @@ void outBitAcc(operand *result)
     symbol *tlbl = newiTempLabel(NULL);
     /* if the result is a bit */
     if (AOP_TYPE(result) == AOP_CRY){
-       assert(0);
+       wassert(0);
     }
     else {
-        emitcode("jp","z," LABEL_STR ,tlbl->key+100);
-        emitcode("ld","a,%s",one);
-        emitcode("", LABEL_STR ":",tlbl->key+100);
+        emit2("!shortjp z,!tlabel", tlbl->key+100);
+       emit2("ld a,!one");
+       emitLabel(tlbl->key+100);
         outAcc(result);
     }
 }
@@ -1416,9 +2207,9 @@ static void genPlus (iCode *ic)
 
     /* special cases :- */
 
-    aopOp (IC_LEFT(ic),ic,FALSE);
-    aopOp (IC_RIGHT(ic),ic,FALSE);
-    aopOp (IC_RESULT(ic),ic,TRUE);
+    aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
+    aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
+    aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
 
     /* Swap the left and right operands if:
 
@@ -1439,14 +2230,14 @@ static void genPlus (iCode *ic)
     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
        /* Cant happen */
-       assert(0);
+       wassert(0);
     }
 
     /* if left in bit space & right literal */
     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
         AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
        /* Can happen I guess */
-       assert(0);
+       wassert(0);
     }
 
     /* if I can do an increment instead
@@ -1454,40 +2245,114 @@ static void genPlus (iCode *ic)
     if (genPlusIncr (ic) == TRUE)
         goto release;   
 
+    emit2("; genPlusIncr failed");
+
     size = getDataSize(IC_RESULT(ic));
 
+    /* Special case when left and right are constant */
+    if (isPair(AOP(IC_RESULT(ic)))) {
+       char *left, *right;
+       
+       left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
+       right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
+       if (left && right) {
+           /* It's a pair */
+           /* PENDING: fix */
+           char buffer[100];
+           sprintf(buffer, "#(%s + %s)", left, right);
+           emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
+           goto release;
+       }
+    }
+
+    if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
+       /* Fetch into HL then do the add */
+       spillPair(PAIR_HL);
+       fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
+       emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
+       goto release;
+    }
+
+    /* Special case:
+       ld hl,sp+n trashes C so we cant afford to do it during an
+       add with stack based varibles.  Worst case is:
+               ld  hl,sp+left
+       ld  a,(hl)
+       ld  hl,sp+right
+       add (hl)
+       ld  hl,sp+result
+       ld  (hl),a
+       ld  hl,sp+left+1
+       ld  a,(hl)
+       ld  hl,sp+right+1
+       adc (hl)
+       ld  hl,sp+result+1
+       ld  (hl),a
+       So you cant afford to load up hl if either left, right, or result
+       is on the stack (*sigh*)  The alt is:
+       ld  hl,sp+left
+       ld  de,(hl)
+       ld  hl,sp+right
+       ld  hl,(hl)
+       add hl,de
+       ld  hl,sp+result
+       ld  (hl),hl
+       Combinations in here are:
+        * If left or right are in bc then the loss is small - trap later
+        * If the result is in bc then the loss is also small
+    */
+    if (IS_GB) {
+       if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
+           AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
+           AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
+           if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
+               AOP_SIZE(IC_RIGHT(ic)) == 2) &&
+               (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
+                AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
+               if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
+                   /* Swap left and right */
+                   operand *t = IC_RIGHT(ic);
+                   IC_RIGHT(ic) = IC_LEFT(ic);
+                   IC_LEFT(ic) = t;
+               }
+               if (getPairId(AOP(IC_LEFT(ic))) == PAIR_BC) {
+                   fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
+                   emit2("add hl,bc");
+               }
+               else {
+                   fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
+                   fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
+                   emit2("add hl,de");
+               }
+               commitPair(AOP(IC_RESULT(ic)), PAIR_HL);
+               goto release;
+           }
+           else if (size == 4) {
+               emit2("; WARNING: This add is probably broken.\n");
+           }
+       }
+    }
+
     while(size--) {
        if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
            MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
            if(offset == 0)
-               emitcode("add","a,%s",
-                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+               emit2("add a,%s",
+                     aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
            else
-               emitcode("adc","a,%s",
-                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+               emit2("adc a,%s",
+                     aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
        } else {
-           MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+           MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
            if(offset == 0)
-               emitcode("add","a,%s",
-                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
+               emit2("add a,%s",
+                     aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
            else
-               emitcode("adc","a,%s",
-                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
+               emit2("adc a,%s",
+                     aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
        }
-        aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
+       aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
     }
-
-    /* Some kind of pointer arith. */
-    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_LEFT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
-       assert(0);
-
-     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
-       AOP_SIZE(IC_RIGHT(ic)) == 3   &&
-       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
-        assert(0);
-
    
 release:
     freeAsmop(IC_LEFT(ic),NULL,ic);
@@ -1515,6 +2380,25 @@ static bool genMinusDec (iCode *ic)
         return FALSE;
 
     size = getDataSize(IC_RESULT(ic));
+
+#if 0
+    /* if increment 16 bits in register */
+    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
+        (size > 1) &&
+        (icount == 1)) {
+        symbol *tlbl = newiTempLabel(NULL);
+       emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
+       emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
+    
+       emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
+       if(size == 4) {
+           wassert(0);
+       }
+       emitLabel(tlbl->key+100);
+        return TRUE;
+    }
+#endif
+
     /* if decrement 16 bits in register */
     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
         (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
@@ -1556,15 +2440,15 @@ 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);
+    aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
+    aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
+    aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
 
     /* special cases :- */
     /* if both left & right are in bit space */
     if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
         AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
-       assert(0);
+       wassert(0);
         goto release ;
     }
 
@@ -1575,28 +2459,70 @@ static void genMinus (iCode *ic)
     size = getDataSize(IC_RESULT(ic));   
 
     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
-        CLRC;
     }
     else{
         lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
         lit = - (long)lit;
     }
 
-
+    /* Same logic as genPlus */
+    if (IS_GB) {
+       if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
+           AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
+           AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
+           if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
+               AOP_SIZE(IC_RIGHT(ic)) == 2) &&
+               (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
+                AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
+               PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
+               PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
+
+               if (left == PAIR_INVALID && right == PAIR_INVALID) {
+                   left = PAIR_DE;
+                   right = PAIR_HL;
+               }
+               else if (right == PAIR_INVALID)
+                   right = PAIR_DE;
+               else if (left == PAIR_INVALID)
+                   left = PAIR_DE;
+               
+               fetchPair(left, AOP(IC_LEFT(ic)));
+               /* Order is important.  Right may be HL */
+               fetchPair(right, AOP(IC_RIGHT(ic)));
+
+               emit2("ld a,%s", _pairs[left].l);
+               emit2("sub a,%s", _pairs[right].l);
+               emit2("ld e,a");
+               emit2("ld a,%s", _pairs[left].h);
+               emit2("sbc a,%s", _pairs[right].h);
+
+               aopPut(AOP(IC_RESULT(ic)), "a", 1);
+               aopPut(AOP(IC_RESULT(ic)), "e", 0);
+               goto release;
+           }
+           else if (size == 4) {
+               emit2("; WARNING: This sub is probably broken.\n");
+           }
+       }
+    }
+    
     /* if literal, add a,#-lit, else normal subb */
     while (size--) {
        MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));    
-       if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
-           emitcode("sbc","a,%s",
-                    aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+       if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
+           if (!offset)
+               emitcode("sub","a,%s",
+                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+           else
+               emitcode("sbc","a,%s",
+                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+       }
        else{
            /* first add without previous c */
            if (!offset)
-               emitcode("add","a,#0x%02x",
-                        (unsigned int)(lit & 0x0FFL));
+               emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
            else
-               emitcode("adc","a,#0x%02x",
-                        (unsigned int)((lit >> (offset*8)) & 0x0FFL));
+               emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
        }
        aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
     }
@@ -1604,7 +2530,7 @@ static void genMinus (iCode *ic)
     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
        AOP_SIZE(IC_LEFT(ic)) == 3   &&
        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
-       assert(0);
+       wassert(0);
 
 release:
     freeAsmop(IC_LEFT(ic),NULL,ic);
@@ -1618,7 +2544,7 @@ release:
 static void genMult (iCode *ic)
 {
     /* Shouldn't occur - all done through function calls */
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1627,7 +2553,7 @@ static void genMult (iCode *ic)
 static void genDiv (iCode *ic)
 {
     /* Shouldn't occur - all done through function calls */
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1636,7 +2562,7 @@ static void genDiv (iCode *ic)
 static void genMod (iCode *ic)
 {
     /* Shouldn't occur - all done through function calls */
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1649,7 +2575,7 @@ static void genIfxJump (iCode *ic, char *jval)
 
     /* if true label then we jump if condition
     supplied is true */
-    if ( IC_TRUE(ic) ) {
+    if (IC_TRUE(ic)) {
         jlbl = IC_TRUE(ic);
        if (!strcmp(jval, "a")) {
            inst = "nz";
@@ -1657,6 +2583,9 @@ static void genIfxJump (iCode *ic, char *jval)
        else if (!strcmp(jval, "c")) {
            inst = "c";
        }
+       else if (!strcmp(jval, "nc")) {
+           inst = "nc";
+       }
        else {
            /* The buffer contains the bit on A that we should test */
            inst = "nz";
@@ -1671,6 +2600,9 @@ static void genIfxJump (iCode *ic, char *jval)
        else if (!strcmp(jval, "c")) {
            inst = "nc";
        }
+       else if (!strcmp(jval, "nc")) {
+           inst = "c";
+       }
        else {
            /* The buffer contains the bit on A that we should test */
            inst = "z";
@@ -1682,15 +2614,22 @@ static void genIfxJump (iCode *ic, char *jval)
     }
     else if (!strcmp(jval, "c")) {
     }
+    else if (!strcmp(jval, "nc")) {
+    }
     else {
        emitcode("bit", "%s,a", jval);
     }
-    emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
+    emit2("jp %s,!tlabel", inst, jlbl->key+100);
 
     /* mark the icode as generated */
     ic->generated = 1;
 }
 
+const char *getPairIdName(PAIR_ID id)
+{
+    return _pairs[id].name;
+}
+
 /** Generic compare for > or <
  */
 static void genCmp (operand *left,operand *right,
@@ -1698,12 +2637,13 @@ static void genCmp (operand *left,operand *right,
 {
     int size, offset = 0 ;
     unsigned long lit = 0L;
+    bool swap_sense = FALSE;
 
     /* if left & right are bit variables */
     if (AOP_TYPE(left) == AOP_CRY &&
         AOP_TYPE(right) == AOP_CRY ) {
        /* Cant happen on the Z80 */
-       assert(0);
+       wassert(0);
     } else {
         /* subtract right from left if at the
         end the carry flag is set then we know that
@@ -1711,12 +2651,41 @@ static void genCmp (operand *left,operand *right,
         size = max(AOP_SIZE(left),AOP_SIZE(right));
 
         /* if unsigned char cmp with lit, just compare */
-        if((size == 1) && !sign &&
+        if((size == 1) && 
            (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
            emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
-           emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
+           if (sign) {
+               emit2("xor a,!immedbyte", 0x80);
+               emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
+           }
+           else 
+               emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
         } 
        else {
+           /* Special cases:
+              On the GB:
+                 If the left or the right is a lit:
+                       Load -lit into HL, add to right via, check sense.
+           */
+           if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) {
+               asmop *lit = AOP(right);
+               asmop *op = AOP(left);
+               swap_sense = TRUE;
+               if (AOP_TYPE(left) == AOP_LIT) {
+                   swap_sense = FALSE;
+                   lit = AOP(left);
+                   op = AOP(right);
+               }
+               if (sign) {
+                   emit2("ld e,%s", aopGet(op, 0, 0));
+                   emit2("ld a,%s", aopGet(op, 1, 0));
+                   emit2("xor a,!immedbyte", 0x80);
+                   emit2("ld d,a");
+               }
+               emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign));
+               emit2("add hl,de");
+               goto release;
+           }
             if(AOP_TYPE(right) == AOP_LIT) {
                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
                 /* optimize if(x < 0) or if(x >= 0) */
@@ -1729,8 +2698,7 @@ static void genCmp (operand *left,operand *right,
                        /* Just load in the top most bit */
                         MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
                         if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
-                           assert(0);
-                            genIfxJump (ifx,"acc.7");
+                            genIfxJump (ifx,"7");
                             return;
                         }
                         else    
@@ -1739,19 +2707,51 @@ static void genCmp (operand *left,operand *right,
                     goto release;
                 }
             }
+           if (sign) {
+               /* First setup h and l contaning the top most bytes XORed */
+               bool fDidXor = FALSE;
+               if (AOP_TYPE(left) == AOP_LIT){
+                   unsigned long lit = (unsigned long)
+                       floatFromVal(AOP(left)->aopu.aop_lit);
+                   emit2("ld %s,!immedbyte", _fTmp[0],
+                            0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+               }
+               else {
+                   emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
+                   emit2("xor a,!immedbyte", 0x80);
+                   emitcode("ld", "%s,a", _fTmp[0]);
+                   fDidXor = TRUE;
+               }
+               if (AOP_TYPE(right) == AOP_LIT) {
+                   unsigned long lit = (unsigned long)
+                       floatFromVal(AOP(right)->aopu.aop_lit);
+                   emit2("ld %s,!immedbyte", _fTmp[1],
+                            0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+               }
+               else {
+                   emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
+                   emit2("xor a,!immedbyte", 0x80);
+                   emitcode("ld", "%s,a", _fTmp[1]);
+                   fDidXor = TRUE;
+               }
+               if (!fDidXor)
+                   CLRC;
+           }
+           else {
+               CLRC;
+           }
             while (size--) {
                /* Do a long subtract */
-                MOVA(aopGet(AOP(left),offset,FALSE));
+               if (!sign || size ) {
+                   MOVA(aopGet(AOP(left),offset,FALSE));
+               }
                 if (sign && size == 0) {
-                   /* Case where it's signed and we've hit the end */
-                   assert(0);
-                } else {
+                   emitcode("ld", "a,%s", _fTmp[0]);
+                   emitcode("sbc", "a,%s", _fTmp[1]);
+               }
+               else {
                    /* Subtract through, propagating the carry */
-                   if (offset==0) {
-                       emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
-                   }
-                   else
-                       emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
+                   emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
                }
             }
         }
@@ -1759,15 +2759,15 @@ static void genCmp (operand *left,operand *right,
 
 release:
     if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
-        outBitC(result);
+        outBitCLong(result, swap_sense);
     } else {
         /* if the result is used in the next
         ifx conditional branch then generate
         code a little differently */
-        if (ifx )
-            genIfxJump (ifx,"c");
+        if (ifx)
+            genIfxJump(ifx, swap_sense ? "nc" : "c");
         else
-            outBitC(result);
+            outBitCLong(result, swap_sense);
         /* leave the result in acc */
     }
 }
@@ -1789,9 +2789,9 @@ static void genCmpGt (iCode *ic, iCode *ifx)
     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);
+    aopOp (left,ic,FALSE, FALSE);
+    aopOp (right,ic,FALSE, FALSE);
+    aopOp (result,ic,TRUE, FALSE);
 
     genCmp(right, left, result, ifx, sign);
 
@@ -1818,9 +2818,9 @@ static void genCmpLt (iCode *ic, iCode *ifx)
     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
 
     /* assign the amsops */
-    aopOp (left,ic,FALSE);
-    aopOp (right,ic,FALSE);
-    aopOp (result,ic,TRUE);
+    aopOp (left,ic,FALSE, FALSE);
+    aopOp (right,ic,FALSE, FALSE);
+    aopOp (result,ic,TRUE, FALSE);
 
     genCmp(left, right, result, ifx, sign);
 
@@ -1851,12 +2851,31 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl)
     /* if the right side is a literal then anything goes */
     if (AOP_TYPE(right) == AOP_LIT &&
         AOP_TYPE(left) != AOP_DIR ) {
-        while (size--) {
-           emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
-           emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
-            emitcode("jp", "nz," LABEL_STR , lbl->key+100);
-            offset++;
-        }
+       if (lit == 0) {
+           emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
+           if (size > 1) {
+               size--;
+               offset++;
+               while (size--) {
+                   emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
+               }
+           }
+           else {
+               emitcode("or", "a,a");
+           }
+           emit2("jp nz,!tlabel", lbl->key+100);
+       }
+       else {
+           while (size--) {
+               emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
+               if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
+                   emitcode("or", "a,a");
+               else 
+                   emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
+               emit2("jp nz,!tlabel", 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 */    
@@ -1868,15 +2887,22 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl)
             if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
                ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
                /* PENDING */
-                emitcode("jp","nz," LABEL_STR ,lbl->key+100);
+                emit2("jp nz,!tlabel", lbl->key+100);
             else {
-               emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
-               emitcode("jp", "nz," LABEL_STR , lbl->key+100);
+               emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
+               emit2("jp nz,!tlabel", lbl->key+100);
            }
             offset++;
         }
     } else {
-       assert(0);
+        /* right is a pointer reg need both a & b */
+       /* PENDING: is this required? */
+        while(size--) {
+            MOVA(aopGet(AOP(right),offset,FALSE));
+           emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
+           emit2("!shortjp nz,!tlabel", lbl->key+100);
+            offset++;
+        }
     }
 }
 
@@ -1890,11 +2916,11 @@ static void gencjne(operand *left, operand *right, symbol *lbl)
     gencjneshort(left, right, lbl);
 
     /* PENDING: ?? */
-    emitcode("ld","a,%s",one);
-    emitcode("jp", LABEL_STR ,tlbl->key+100);
-    emitcode("", LABEL_STR ":",lbl->key+100);
+    emit2("ld a,!one");
+    emit2("!shortjp !tlabel", tlbl->key+100);
+    emitLabel(lbl->key+100);
     emitcode("xor","a,a");
-    emitcode("", LABEL_STR ":",tlbl->key+100);
+    emitLabel(tlbl->key+100);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1904,9 +2930,9 @@ static void genCmpEq (iCode *ic, iCode *ifx)
 {
     operand *left, *right, *result;
 
-    aopOp((left=IC_LEFT(ic)),ic,FALSE);
-    aopOp((right=IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
+    aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
 
     /* Swap operands if it makes the operation easier. ie if:
        1.  Left is a literal.
@@ -1922,20 +2948,20 @@ static void genCmpEq (iCode *ic, iCode *ifx)
         /* if they are both bit variables */
         if (AOP_TYPE(left) == AOP_CRY &&
             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
-           assert(0);
+           wassert(0);
         } else {
             tlbl = newiTempLabel(NULL);
             gencjneshort(left, right, tlbl);
             if ( IC_TRUE(ifx) ) {
-                emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
-                emitcode("", LABEL_STR ":",tlbl->key+100);                
+               emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
+               emitLabel(tlbl->key+100);
             } else {
                /* PENDING: do this better */
                 symbol *lbl = newiTempLabel(NULL);
-                emitcode("jp", LABEL_STR ,lbl->key+100);
-                emitcode("", LABEL_STR ":",tlbl->key+100);                
-                emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
-                emitcode("", LABEL_STR ":",lbl->key+100);             
+               emit2("!shortjp !tlabel", lbl->key+100);
+                emitLabel(tlbl->key+100);
+                emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
+               emitLabel(lbl->key+100);             
             }
         }
         /* mark the icode as generated */
@@ -1946,11 +2972,11 @@ static void genCmpEq (iCode *ic, iCode *ifx)
     /* if they are both bit variables */
     if (AOP_TYPE(left) == AOP_CRY &&
         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
-       assert(0);
+       wassert(0);
     } else {
         gencjne(left,right,newiTempLabel(NULL));    
         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
-           assert(0);
+           wassert(0);
         }
         if (ifx) {
            genIfxJump(ifx,"a");
@@ -2002,20 +3028,20 @@ static void genAndOp (iCode *ic)
     /* 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);
+    aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
+    aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
+    aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
 
     /* if both are bit variables */
     if (AOP_TYPE(left) == AOP_CRY &&
         AOP_TYPE(right) == AOP_CRY ) {
-       assert(0);
+       wassert(0);
     } else {
         tlbl = newiTempLabel(NULL);
         toBoolean(left);    
-        emitcode("jp","z," LABEL_STR ,tlbl->key+100);
+       emit2("!shortjp z,!tlabel", tlbl->key+100);
         toBoolean(right);
-        emitcode("", LABEL_STR ":",tlbl->key+100);
+       emitLabel(tlbl->key+100);
         outBitAcc(result);
     }
 
@@ -2035,20 +3061,20 @@ static void genOrOp (iCode *ic)
     /* 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);
+    aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
+    aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
+    aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
 
     /* if both are bit variables */
     if (AOP_TYPE(left) == AOP_CRY &&
         AOP_TYPE(right) == AOP_CRY ) {
-       assert(0);
+       wassert(0);
     } else {
         tlbl = newiTempLabel(NULL);
         toBoolean(left);
-        emitcode("jp","nz," LABEL_STR,tlbl->key+100);
+       emit2("!shortjp nz,!tlabel", tlbl->key+100);
         toBoolean(right);
-        emitcode("", LABEL_STR,tlbl->key+100);
+       emitLabel(tlbl->key+100);
         outBitAcc(result);
     }
 
@@ -2077,6 +3103,26 @@ int isLiteralBit(unsigned long lit)
     return 0;
 }
 
+/*-----------------------------------------------------------------*/
+/* jmpTrueOrFalse -                                                */
+/*-----------------------------------------------------------------*/
+static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
+{
+    // ugly but optimized by peephole
+    if(IC_TRUE(ic)){
+        symbol *nlbl = newiTempLabel(NULL);
+       emit2("jp !tlabel", nlbl->key+100);                 
+        emitLabel(tlbl->key+100);
+       emit2("jp !tlabel", IC_TRUE(ic)->key+100);
+        emitLabel(nlbl->key+100);
+    }
+    else{
+       emit2("jp !tlabel", IC_FALSE(ic)->key+100);
+        emitLabel(tlbl->key+100);
+    }
+    ic->generated = 1;
+}
+
 /*-----------------------------------------------------------------*/
 /* genAnd  - code for and                                          */
 /*-----------------------------------------------------------------*/
@@ -2087,9 +3133,9 @@ static void genAnd (iCode *ic, iCode *ifx)
     unsigned long lit = 0L;
     int bytelit = 0;
 
-    aopOp((left = IC_LEFT(ic)),ic,FALSE);
-    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
-    aopOp((result=IC_RESULT(ic)),ic,TRUE);
+    aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
 
 #ifdef DEBUG_TYPE
     emitcode("","; Type res[%d] = l[%d]&r[%d]",
@@ -2128,7 +3174,7 @@ static void genAnd (iCode *ic, iCode *ifx)
     size = AOP_SIZE(result);
 
     if (AOP_TYPE(left) == AOP_CRY){
-       assert(0);
+       wassert(0);
         goto release ;
     }
 
@@ -2144,7 +3190,7 @@ static void genAnd (iCode *ic, iCode *ifx)
             MOVA(aopGet(AOP(left),posbit>>3,FALSE));
             // bit = left & 2^n
             if(size) {
-               assert(0);
+               wassert(0);
                 emitcode("mov","c,acc.%d",posbit&0x07);
            }
             // if(left &  2^n)
@@ -2154,7 +3200,7 @@ static void genAnd (iCode *ic, iCode *ifx)
                     genIfxJump(ifx, buffer);
                 }
                else {
-                   assert(0);
+                   wassert(0);
                }
                 goto release;
             }
@@ -2162,7 +3208,7 @@ static void genAnd (iCode *ic, iCode *ifx)
             symbol *tlbl = newiTempLabel(NULL);
             int sizel = AOP_SIZE(left);
             if(size) {
-               assert(0);
+               wassert(0);
                 emitcode("setb","c");
            }
             while(sizel--){
@@ -2170,14 +3216,17 @@ static void genAnd (iCode *ic, iCode *ifx)
                     MOVA( aopGet(AOP(left),offset,FALSE));
                     // byte ==  2^n ?
                     if((posbit = isLiteralBit(bytelit)) != 0) {
-                       assert(0);
+                       wassert(0);
                         emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
                    }
                     else{
                         if(bytelit != 0x0FFL)
                             emitcode("and","a,%s",
                                      aopGet(AOP(right),offset,FALSE));
-                        emitcode("jr","nz, %05d$",tlbl->key+100);
+                       else
+                           /* For the flags */
+                           emit2("or a,a");
+                        emit2("!shortjp nz,!tlabel", tlbl->key+100);
                     }
                 }
                 offset++;
@@ -2185,16 +3234,12 @@ static void genAnd (iCode *ic, iCode *ifx)
             // bit = left & literal
             if (size){
                 emitcode("clr","c");
-                emitcode("","%05d$:",tlbl->key+100);
+               emit2("!tlabeldef", tlbl->key+100);
             }
             // if(left & literal)
             else{
                 if(ifx)
-#if 0
                     jmpTrueOrFalse(ifx, tlbl);
-#else
-               assert(0);
-#endif
                 goto release ;
             }
         }
@@ -2215,25 +3260,26 @@ static void genAnd (iCode *ic, iCode *ifx)
                        MOVA(aopGet(AOP(left),offset,FALSE));
                        emitcode("and","a,%s",
                                 aopGet(AOP(right),offset,FALSE));
-                       emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
+                       aopPut(AOP(left), "a", offset);
                    }
                }
 
             } else {
                if (AOP_TYPE(left) == AOP_ACC) {
-                   assert(0);
+                   wassert(0);
                }
                else {
-                   MOVA(aopGet(AOP(right),offset,FALSE));
-                   emitcode("and","%s,a",
-                            aopGet(AOP(left),offset,FALSE));
+                   MOVA(aopGet(AOP(left),offset,FALSE));
+                   emitcode("and","a,%s",
+                            aopGet(AOP(right),offset,FALSE));
+                   aopPut(AOP(left), "a", offset);
                }
             }
         }
     } else {
         // left & result in different registers
         if(AOP_TYPE(result) == AOP_CRY){
-           assert(0);
+           wassert(0);
         } else {
            for(;(size--);offset++) {
                // normal case
@@ -2254,9 +3300,9 @@ static void genAnd (iCode *ic, iCode *ifx)
                if (AOP_TYPE(left) == AOP_ACC) 
                    emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
                else {
-                   MOVA(aopGet(AOP(right),offset,FALSE));
+                   MOVA(aopGet(AOP(left),offset,FALSE));
                    emitcode("and","a,%s",
-                            aopGet(AOP(left),offset,FALSE));
+                            aopGet(AOP(right),offset,FALSE));
                }
                aopPut(AOP(result),"a",offset);
            }
@@ -2279,11 +3325,11 @@ static void genOr (iCode *ic, iCode *ifx)
     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);
+    aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
 
-#ifdef DEBUG_TYPE
+#if 1
     emitcode("","; Type res[%d] = l[%d]&r[%d]",
              AOP_TYPE(result),
              AOP_TYPE(left), AOP_TYPE(right));
@@ -2320,14 +3366,14 @@ static void genOr (iCode *ic, iCode *ifx)
     size = AOP_SIZE(result);
 
     if (AOP_TYPE(left) == AOP_CRY){
-       assert(0);
+       wassert(0);
         goto release ;
     }
 
     if((AOP_TYPE(right) == AOP_LIT) &&
        (AOP_TYPE(result) == AOP_CRY) &&
        (AOP_TYPE(left) != AOP_CRY)){
-       assert(0);
+       wassert(0);
         goto release ;
     }
 
@@ -2337,25 +3383,27 @@ static void genOr (iCode *ic, iCode *ifx)
             if(AOP_TYPE(right) == AOP_LIT){
                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
                     continue;
-                else 
-                   emitcode("or","%s,%s",
-                            aopGet(AOP(left),offset,FALSE),
+                else {
+                   MOVA(aopGet(AOP(left),offset,FALSE));
+                   emitcode("or","a,%s",
                             aopGet(AOP(right),offset,FALSE));
+                   aopPut(AOP(result),"a", offset);
+               }
             } else {
                if (AOP_TYPE(left) == AOP_ACC) 
                    emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
                else {              
-                   MOVA(aopGet(AOP(right),offset,FALSE));
+                   MOVA(aopGet(AOP(left),offset,FALSE));
                    emitcode("or","a,%s",
-                            aopGet(AOP(left),offset,FALSE));
-                   aopPut(AOP(result),"a",0);
+                            aopGet(AOP(right),offset,FALSE));
+                   aopPut(AOP(result),"a", offset);
                }
             }
         }
     } else {
         // left & result in different registers
         if(AOP_TYPE(result) == AOP_CRY){
-           assert(0);
+           wassert(0);
         } else for(;(size--);offset++){
             // normal case
             // result = left & right
@@ -2372,12 +3420,14 @@ static void genOr (iCode *ic, iCode *ifx)
            if (AOP_TYPE(left) == AOP_ACC) 
                emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
            else {
-               MOVA(aopGet(AOP(right),offset,FALSE));
+               MOVA(aopGet(AOP(left),offset,FALSE));
                emitcode("or","a,%s",
-                        aopGet(AOP(left),offset,FALSE));
-               aopPut(AOP(result),"a",0);
+                        aopGet(AOP(right),offset,FALSE));
            }
            aopPut(AOP(result),"a",offset);                     
+           /* PENDING: something weird is going on here.  Add exception. */
+           if (AOP_TYPE(result) == AOP_ACC)
+               break;
         }
     }
 
@@ -2396,9 +3446,9 @@ static void genXor (iCode *ic, iCode *ifx)
     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);
+    aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
+    aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
 
     /* if left is a literal & right is not then exchange them */
     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
@@ -2428,14 +3478,14 @@ static void genXor (iCode *ic, iCode *ifx)
     size = AOP_SIZE(result);
 
     if (AOP_TYPE(left) == AOP_CRY){
-       assert(0);
+       wassert(0);
         goto release ;
     }
 
     if((AOP_TYPE(right) == AOP_LIT) &&
        (AOP_TYPE(result) == AOP_CRY) &&
        (AOP_TYPE(left) != AOP_CRY)){
-       assert(0);
+       wassert(0);
         goto release ;
     }
 
@@ -2465,7 +3515,7 @@ static void genXor (iCode *ic, iCode *ifx)
     } else {
         // left & result in different registers
         if(AOP_TYPE(result) == AOP_CRY){
-           assert(0);
+           wassert(0);
         } else for(;(size--);offset++){
             // normal case
             // result = left & right
@@ -2537,7 +3587,7 @@ static void genInline (iCode *ic)
 /*-----------------------------------------------------------------*/
 static void genRRC (iCode *ic)
 {
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2545,7 +3595,7 @@ static void genRRC (iCode *ic)
 /*-----------------------------------------------------------------*/
 static void genRLC (iCode *ic)
 {    
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2555,16 +3605,11 @@ static void shiftR2Left2Result (operand *left, int offl,
                                 operand *result, int offr,
                                 int shCount, int sign)
 {
-    if(sameRegs(AOP(result), AOP(left)) &&
-       ((offl + MSB16) == offr)){
-       assert(0);
-    } else {
-       movLeft2Result(left, offl, result, offr, 0);
-       movLeft2Result(left, offl+1, result, offr+1, 0);
-    }
+    movLeft2Result(left, offl, result, offr, 0);
+    movLeft2Result(left, offl+1, result, offr+1, 0);
 
     if (sign) {
-       assert(0);
+       wassert(0);
     }
     else {
        /*      if (AOP(result)->type == AOP_REG) {*/
@@ -2573,13 +3618,14 @@ static void shiftR2Left2Result (operand *left, int offl,
            symbol *tlbl , *tlbl1;
            char *l;
 
+           tlbl = newiTempLabel(NULL);
+           tlbl1 = newiTempLabel(NULL);
+               
            /* Left is already in result - so now do the shift */
            if (shCount>1) {
-               emitcode("ld","a,#%u+1", shCount);
-               tlbl = newiTempLabel(NULL);
-               tlbl1 = newiTempLabel(NULL);
-               emitcode("jp", LABEL_STR ,tlbl1->key+100); 
-               emitcode("", LABEL_STR ":",tlbl->key+100);    
+               emit2("ld a,!immedbyte+1", shCount);
+               emit2("!shortjp !tlabel", tlbl1->key+100); 
+               emitLabel(tlbl->key+100);    
            }
 
            emitcode("or", "a,a");
@@ -2589,9 +3635,9 @@ static void shiftR2Left2Result (operand *left, int offl,
                emitcode("rr","%s", l);         
            }
            if (shCount>1) {
-               emitcode("", LABEL_STR ":",tlbl1->key+100);
+               emitLabel(tlbl1->key+100);
                emitcode("dec", "a");
-               emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+               emit2("!shortjp nz,!tlabel", tlbl->key+100);
            }
     }
 }
@@ -2604,24 +3650,28 @@ static void shiftL2Left2Result (operand *left, int offl,
 {
     if(sameRegs(AOP(result), AOP(left)) &&
        ((offl + MSB16) == offr)){
-       assert(0);
+       wassert(0);
     } else {
        /* Copy left into result */
-       movLeft2Result(left,offl, result, offr, 0);
+       movLeft2Result(left, offl, result, offr, 0);
+       movLeft2Result(left, offl+1, result, offr+1, 0);
     }
-    if (AOP(result)->type == AOP_REG) {
+    /* PENDING: for now just see if it'll work. */
+    /*if (AOP(result)->type == AOP_REG) { */
+    {
        int size = 2;
        int offset = 0;
        symbol *tlbl , *tlbl1;
        char *l;
 
+       tlbl = newiTempLabel(NULL);
+       tlbl1 = newiTempLabel(NULL);
+
        /* Left is already in result - so now do the shift */
        if (shCount>1) {
-           emitcode("ld","a,#%u+1", shCount);
-           tlbl = newiTempLabel(NULL);
-           tlbl1 = newiTempLabel(NULL);
-           emitcode("jp", LABEL_STR ,tlbl1->key+100); 
-           emitcode("", LABEL_STR ":",tlbl->key+100);    
+           emit2("ld a,!immedbyte+1", shCount);
+           emit2("!shortjp !tlabel", tlbl1->key+100); 
+           emitLabel(tlbl->key+100);    
        }
 
        emitcode("or", "a,a");
@@ -2630,15 +3680,11 @@ static void shiftL2Left2Result (operand *left, int offl,
            emitcode("rl","%s", l);         
        }
        if (shCount>1) {
-           emitcode("", LABEL_STR ":",tlbl1->key+100);
+           emitLabel(tlbl1->key+100);
            emitcode("dec", "a");
-           emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+           emit2("!shortjp nz,!tlabel", tlbl->key+100);
        }
     }
-    else {
-       /* PENDING: do something */
-       assert(0);
-    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -2688,19 +3734,19 @@ static void AccRol (int shCount)
 /*-----------------------------------------------------------------*/
 static void AccLsh (int shCount)
 {
-    if(shCount != 0){
-        if(shCount == 1)
-            emitcode("add","a,a");
-        else 
-           if(shCount == 2) {
+    if(shCount != 0) {
+        if(shCount == 1) {
             emitcode("add","a,a");
-            emitcode("add","a,a");
-        } else {
-            /* rotate left accumulator */
-            AccRol(shCount);
-            /* and kill the lower order bits */
-            emitcode("and","a,#0x%02x", SLMask[shCount]);
-        }
+       }
+        else if(shCount == 2) {
+           emitcode("add","a,a");
+           emitcode("add","a,a");
+       } else {
+           /* rotate left accumulator */
+           AccRol(shCount);
+           /* and kill the lower order bits */
+           emit2("and a,!immedbyte", SLMask[shCount]);
+       }
     }
 }
 
@@ -2726,29 +3772,30 @@ static void genlshTwo (operand *result,operand *left, int shCount)
 {
     int size = AOP_SIZE(result);
 
-    assert(size==2);
+    wassert(size==2);
 
     /* if shCount >= 8 */
     if (shCount >= 8) {
         shCount -= 8 ;
-
         if (size > 1){
             if (shCount) {
                 movLeft2Result(left, LSB, result, MSB16, 0);
                aopPut(AOP(result),zero, 0);   
-               shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
+               shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
            }
             else {
                 movLeft2Result(left, LSB, result, MSB16, 0);
                aopPut(AOP(result),zero, 0);   
            }
         }
-        aopPut(AOP(result),zero,LSB);   
+       else {
+           aopPut(AOP(result),zero,LSB);   
+       }
     }
     /*  1 <= shCount <= 7 */
     else {  
         if(size == 1) {
-           assert(0);
+           wassert(0);
        }
         else {
             shiftL2Left2Result(left, LSB, result, LSB, shCount);
@@ -2777,8 +3824,8 @@ static void genLeftShiftLiteral (operand *left,
 
     freeAsmop(right,NULL,ic);
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, FALSE);
 
     size = getSize(operandType(result));
 
@@ -2789,7 +3836,7 @@ static void genLeftShiftLiteral (operand *left,
 
     /* I suppose that the left size >= result size */
     if (shCount == 0) {
-       assert(0);
+       wassert(0);
     }
 
     else if(shCount >= (size * 8))
@@ -2804,10 +3851,10 @@ static void genLeftShiftLiteral (operand *left,
            genlshTwo (result,left,shCount);
            break;
        case 4:
-           assert(0);
+           wassert(0);
            break;
        default:
-           assert(0);
+           wassert(0);
         }
     }
     freeAsmop(left,NULL,ic);
@@ -2828,7 +3875,7 @@ static void genLeftShift (iCode *ic)
     left  = IC_LEFT(ic);
     result = IC_RESULT(ic);
 
-    aopOp(right,ic,FALSE);
+    aopOp(right,ic,FALSE, FALSE);
 
     /* if the shift count is known then do it 
     as efficiently as possible */
@@ -2844,8 +3891,8 @@ static void genLeftShift (iCode *ic)
     emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
     emitcode("inc","a");
     freeAsmop (right,NULL,ic);
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, FALSE);
 
     /* now move the left to the result if they are not the
        same */
@@ -2876,23 +3923,24 @@ static void genLeftShift (iCode *ic)
     offset = 0 ;   
     tlbl1 = newiTempLabel(NULL);
 
-    emitcode("jp", LABEL_STR ,tlbl1->key+100); 
-    emitcode("", LABEL_STR ":",tlbl->key+100);    
+    emit2("!shortjp !tlabel", tlbl1->key+100); 
+    emitLabel(tlbl->key+100);    
     l = aopGet(AOP(result),offset,FALSE);
     emitcode("or", "a,a");
     while (size--) {
         l = aopGet(AOP(result),offset++,FALSE);
         emitcode("rl","%s", l);         
     }
-    emitcode("", LABEL_STR ":",tlbl1->key+100);
+    emitLabel(tlbl1->key+100);
     emitcode("dec", "a");
-    emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+    emit2("!shortjp nz,!tlabel", tlbl->key+100);
 
     freeAsmop(left,NULL,ic);
     freeAsmop(result,NULL,ic);
 }
 
-/* genlshTwo - left shift two bytes by known amount != 0           */
+/*-----------------------------------------------------------------*/
+/* genrshOne - left shift two bytes by known amount != 0           */
 /*-----------------------------------------------------------------*/
 static void genrshOne (operand *result,operand *left, int shCount)
 {
@@ -2900,8 +3948,8 @@ static void genrshOne (operand *result,operand *left, int shCount)
     int size = AOP_SIZE(result);
     char *l;
 
-    assert(size==1);
-    assert(shCount<8);
+    wassert(size==1);
+    wassert(shCount<8);
 
     l = aopGet(AOP(left),0,FALSE);
     if (AOP(result)->type == AOP_REG) {
@@ -2925,15 +3973,10 @@ static void genrshOne (operand *result,operand *left, int shCount)
 static void AccRsh (int shCount)
 {
     if(shCount != 0){
-        if(shCount == 1){
-            CLRC;
-            emitcode("rr","a");
-        } else {
-            /* rotate right accumulator */
-            AccRol(8 - shCount);
-            /* and kill the higher order bits */
-            emitcode("and","a,#0x%02x", SRMask[shCount]);
-        }
+       /* rotate right accumulator */
+       AccRol(8 - shCount);
+       /* and kill the higher order bits */
+       emit2("and a,!immedbyte", SRMask[shCount]);
     }
 }
 
@@ -2946,7 +3989,7 @@ static void shiftR1Left2Result (operand *left, int offl,
 {
     MOVA(aopGet(AOP(left),offl,FALSE));
     if (sign) {
-       assert(0);
+       wassert(0);
     }
     else {
         AccRsh(shCount);
@@ -2962,16 +4005,15 @@ static void genrshTwo (operand *result,operand *left,
 {
     /* if shCount >= 8 */
     if (shCount >= 8) {
-        shCount -= 8 ;
+        shCount -= 8;
         if (shCount) {
-           assert(0);
             shiftR1Left2Result(left, MSB16, result, LSB,
                                shCount, sign);
        }
         else {
             movLeft2Result(left, MSB16, result, LSB, sign);
-           aopPut(AOP(result),zero,1);
        }
+       aopPut(AOP(result),zero,1);
     }
     /*  1 <= shCount <= 7 */
     else {
@@ -2992,8 +4034,8 @@ static void genRightShiftLiteral (operand *left,
 
     freeAsmop(right,NULL,ic);
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, FALSE);
 
     size = getSize(operandType(result));
 
@@ -3002,7 +4044,7 @@ static void genRightShiftLiteral (operand *left,
 
     /* I suppose that the left size >= result size */
     if (shCount == 0) {
-       assert(0);
+       wassert(0);
     }
 
     else if(shCount >= (size * 8))
@@ -3018,10 +4060,10 @@ static void genRightShiftLiteral (operand *left,
            genrshTwo(result, left, shCount, FALSE);
            break;
        case 4:
-           assert(0);
+           wassert(0);
            break;
        default:
-           assert(0);
+           wassert(0);
         }
     }
     freeAsmop(left,NULL,ic);
@@ -3033,59 +4075,129 @@ static void genRightShiftLiteral (operand *left,
 /*-----------------------------------------------------------------*/
 static void genRightShift (iCode *ic)
 {
-    operand *left,*right, *result;
+    operand *right, *left, *result;
+    link *retype ;
+    int size, offset, first = 1;
+    char *l;
+    bool is_signed;
+
+    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)));
+
+    is_signed = !SPEC_USIGN(retype);
+
+    /* signed & unsigned types are treated the same : i.e. the
+    signed is NOT propagated inwards : quoting from the
+    ANSI - standard : "for E1 >> E2, is equivalent to division
+    by 2**E2 if unsigned or if it has a non-negative value,
+    otherwise the result is implementation defined ", MY definition
+    is that the sign does not get propagated */
 
     right = IC_RIGHT(ic);
     left  = IC_LEFT(ic);
     result = IC_RESULT(ic);
 
-    aopOp(right,ic,FALSE);
+    aopOp(right,ic,FALSE, FALSE);
 
     /* if the shift count is known then do it 
     as efficiently as possible */
     if (AOP_TYPE(right) == AOP_LIT) {
-        genRightShiftLiteral (left,right,result,ic);
-        return ;
+        genRightShiftLiteral(left,right,result,ic);
+        return;
     }
-    else {
-       assert(0);
+
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, 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);
+           aopPut(AOP(result),l,offset);
+            offset++;
+        }
+    }
+
+    emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
+    emitcode("inc","a");
+    freeAsmop (right, NULL, ic);
+
+    tlbl = newiTempLabel(NULL);
+    tlbl1= newiTempLabel(NULL);
+    size = AOP_SIZE(result);
+    offset = size - 1;
+
+    emit2("!shortjp !tlabel", tlbl1->key+100);
+    emitLabel(tlbl->key+100);
+    while (size--) {
+        l = aopGet(AOP(result),offset--,FALSE);
+       if (first) {
+           if (is_signed)
+               emitcode("sra", "%s", l);
+           else
+               emitcode("srl", "%s", l);
+           first = 0;
+       }
+       else
+           emitcode("rr", "%s", l);
     }
+    emitLabel(tlbl1->key+100);
+    emitcode("dec", "a");
+    emit2("!shortjp nz,!tlabel", tlbl->key+100);
+
+    freeAsmop(left,NULL,ic);
+    freeAsmop(result,NULL,ic);
 }
 
 /*-----------------------------------------------------------------*/
-/* genGenPointerGet - gget value from generic pointer space        */
+/* genGenPointerGet -  get value from generic pointer space        */
 /*-----------------------------------------------------------------*/
 static void genGenPointerGet (operand *left,
                               operand *result, iCode *ic)
 {
     int size, offset ;
     link *retype = getSpec(operandType(result));
+    int pair = PAIR_HL;
 
-    aopOp(left,ic,FALSE);
-    aopOp(result,ic,FALSE);
+    if (IS_GB)
+       pair = PAIR_DE;
 
-    if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
+    aopOp(left,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, FALSE);
+    
+    if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
        /* Just do it */
-       emitcode("ld", "a,(%s)", getPairName(AOP(left)));
-       aopPut(AOP(result),"a", 0);
+       if (isPtrPair(AOP(left))) 
+           {
+               tsprintf(buffer, "!*pair", getPairName(AOP(left)));
+               aopPut(AOP(result), buffer, 0);
+           }
+       else {
+           emit2("ld a,!*pair", getPairName(AOP(left)));
+           aopPut(AOP(result),"a", 0);
+       }
        freeAsmop(left,NULL,ic);
        goto release;
     }
 
     /* For now we always load into IY */
     /* if this is remateriazable */
-    if (AOP_TYPE(left) == AOP_IMMD)
-       emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
-    else { /* we need to get it byte by byte */
-       emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
-       emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
-    }
+    fetchPair(pair, AOP(left));
+
     /* so iy now contains the address */
     freeAsmop(left,NULL,ic);
 
     /* if bit then unpack */
     if (IS_BITVAR(retype)) {
-       assert(0);
+       wassert(0);
     }
     else {
         size = AOP_SIZE(result);
@@ -3093,15 +4205,16 @@ static void genGenPointerGet (operand *left,
 
         while (size--) {
            /* PENDING: make this better */
-           if (AOP(result)->type == AOP_REG) {
-               aopPut(AOP(result),"(hl)",offset++);
+           if (!IS_GB && AOP(result)->type == AOP_REG) {
+               aopPut(AOP(result), "!*hl", offset++);
            }
            else {
-               emitcode("ld", "a,(hl)", offset);
+               emit2("ld a,!*pair", _pairs[pair].name);
                aopPut(AOP(result),"a",offset++);
            }
            if (size) {
-               emitcode("inc", "hl");
+               emit2("inc %s", _pairs[pair].name);
+               _G.pairs[pair].offset++;
            }
         }
     }
@@ -3144,40 +4257,40 @@ static void genGenPointerSet (operand *right,
 {    
     int size, offset ;
     link *retype = getSpec(operandType(right));
+    PAIR_ID pairId = PAIR_HL;
 
-    aopOp(result,ic,FALSE);
-    aopOp(right,ic,FALSE);
+    aopOp(result,ic,FALSE, FALSE);
+    aopOp(right,ic,FALSE, FALSE);
+
+    if (IS_GB)
+       pairId = PAIR_DE;
 
     /* Handle the exceptions first */
     if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
        /* Just do it */
        char *l = aopGet(AOP(right), 0, FALSE);
-       MOVA(l);
-       emitcode("ld", "(%s),a", getPairName(AOP(result)));
-       freeAsmop(result,NULL,ic);
+       const char *pair = getPairName(AOP(result));
+       if (canAssignToPtr(l) && isPtr(pair)) {
+           emit2("ld !*pair,%s", pair, l);
+       }
+       else {
+           MOVA(l);
+           emit2("ld !*pair,a", pair);
+       }
        goto release;
     }
        
     /* if the operand is already in dptr 
        then we do nothing else we move the value to dptr */
     if (AOP_TYPE(result) != AOP_STR) {
-        /* if this is remateriazable */
-        if (AOP_TYPE(result) == AOP_IMMD) {
-           emitcode("", "; Error 2");
-           emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
-        }
-        else { /* we need to get it byte by byte */
-           /* PENDING: do this better */
-           emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
-           emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
-        }
+       fetchPair(pairId, AOP(result));
     }
     /* so hl know contains the address */
     freeAsmop(result,NULL,ic);
 
     /* if bit then unpack */
     if (IS_BITVAR(retype)) {
-       assert(0);
+       wassert(0);
     }
     else {
         size = AOP_SIZE(right);
@@ -3185,16 +4298,16 @@ static void genGenPointerSet (operand *right,
 
         while (size--) {
             char *l = aopGet(AOP(right),offset,FALSE);
-
-           if (isRegOrLit(AOP(right))) {
-               emitcode("ld", "(hl),%s", l);
+           if (isRegOrLit(AOP(right)) && !IS_GB) {
+               emit2("ld !*pair,%s", _pairs[pairId].name, l);
            }
            else {
                MOVA(l);
-               emitcode("ld", "(hl),a", offset);
+               emit2("ld !*pair,a", _pairs[pairId].name);
            }
            if (size) {
-               emitcode("inc", "hl");
+               emitcode("inc", _pairs[pairId].name);
+               _G.pairs[pairId].offset++;
            }
            offset++;
         }
@@ -3230,7 +4343,7 @@ static void genIfx (iCode *ic, iCode *popIc)
     operand *cond = IC_COND(ic);
     int isbit =0;
 
-    aopOp(cond,ic,FALSE);
+    aopOp(cond,ic,FALSE, TRUE);
 
     /* get the value into acc */
     if (AOP_TYPE(cond) != AOP_CRY)
@@ -3264,26 +4377,42 @@ static void genAddrOf (iCode *ic)
 {
     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
 
-    aopOp(IC_RESULT(ic),ic,FALSE);
+    aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
 
     /* if the operand is on the stack then we 
     need to get the stack offset of this
     variable */
-    if (sym->onStack) {
-        /* if it has an offset  then we need to compute it */
-       emitcode("push", "de");
-       emitcode("push", "ix");
-       emitcode("pop", "hl");
-       emitcode("ld", "de,#%d", sym->stack);
-       emitcode("add", "hl,de");
-       emitcode("pop", "de");
+    if (IS_GB) {
+       if (sym->onStack) {
+           spillCached();
+           if (sym->stack <= 0) {
+               emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
+           }
+           else {
+               emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
+           }
+           emitcode("ld", "d,h");
+           emitcode("ld", "e,l");
+       }
+       else {
+           emit2("ld de,!hashedstr", sym->rname);
+       }
+       aopPut(AOP(IC_RESULT(ic)), "e", 0);
+       aopPut(AOP(IC_RESULT(ic)), "d", 1);
     }
     else {
-       emitcode("ld", "hl,#%s", sym->rname);
+       spillCached();
+       if (sym->onStack) {
+           /* if it has an offset  then we need to compute it */
+           emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
+           emitcode("add", "hl,sp");
+       }
+       else {
+           emitcode("ld", "hl,#%s", sym->rname);
+       }
+       aopPut(AOP(IC_RESULT(ic)), "l", 0);
+       aopPut(AOP(IC_RESULT(ic)), "h", 1);
     }
-    aopPut(AOP(IC_RESULT(ic)), "l", 0);
-    aopPut(AOP(IC_RESULT(ic)), "h", 1);
-
     freeAsmop(IC_RESULT(ic),NULL,ic);
 }
 
@@ -3299,14 +4428,16 @@ static void genAssign (iCode *ic)
     result = IC_RESULT(ic);
     right  = IC_RIGHT(ic) ;
 
+#if 1
     /* Dont bother assigning if they are the same */
     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
-       emitcode("", "; (operands are equal)");
+       emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
         return;
     }
+#endif
 
-    aopOp(right,ic,FALSE);
-    aopOp(result,ic,TRUE);
+    aopOp(right,ic,FALSE, FALSE);
+    aopOp(result,ic,TRUE, FALSE);
 
     /* if they are the same registers */
     if (sameRegs(AOP(right),AOP(result))) {
@@ -3316,7 +4447,7 @@ static void genAssign (iCode *ic)
 
     /* if the result is a bit */
     if (AOP_TYPE(result) == AOP_CRY) {
-       assert(0);
+       wassert(0);
     }
 
     /* general case */
@@ -3325,28 +4456,56 @@ static void genAssign (iCode *ic)
 
     if(AOP_TYPE(right) == AOP_LIT)
        lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
-    if((size > 1) &&
+    if (isPair(AOP(result))) {
+       fetchPair(getPairId(AOP(result)), AOP(right));
+    }
+    else if((size > 1) &&
        (AOP_TYPE(result) != AOP_REG) &&
        (AOP_TYPE(right) == AOP_LIT) &&
        !IS_FLOAT(operandType(right)) &&
-       (lit < 256L)){
-       emitcode("xor","a,a");
+       (lit < 256L)) {
+       bool fXored = FALSE;
+       offset = 0;
        /* Work from the top down.
           Done this way so that we can use the cached copy of 0
           in A for a fast clear */
        while (size--) {
-           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
-               aopPut(AOP(result),"a",size);
+           if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
+               if (!fXored && size>1) {
+                   emitcode("xor", "a,a");
+                   fXored = TRUE;
+               }
+               if (fXored) {
+                   aopPut(AOP(result),"a",offset);
+               }
+               else {
+                   aopPut(AOP(result), zero, offset);
+               }
+           }
            else
                aopPut(AOP(result),
-                      aopGet(AOP(right),size,FALSE),
-                      size);
+                      aopGet(AOP(right),offset,FALSE),
+                      offset);
+           offset++;
        }
+    }
+    else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result)) && IS_GB) {
+       /* Special case.  Load into a and d, then load out. */
+       MOVA(aopGet(AOP(right), 0, FALSE));
+       emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
+       aopPut(AOP(result), "a", 0);
+       aopPut(AOP(result), "e", 1);
     } else {
        while (size--) {
-           aopPut(AOP(result),
-                  aopGet(AOP(right),offset,FALSE),
-                  offset);
+           /* PENDING: do this check better */
+           if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
+               MOVA(aopGet(AOP(right), offset, FALSE));
+               aopPut(AOP(result), "a", offset);
+           }
+           else 
+               aopPut(AOP(result),
+                      aopGet(AOP(right),offset,FALSE),
+                      offset);
            offset++;
        }
     }
@@ -3361,7 +4520,31 @@ release:
 /*-----------------------------------------------------------------*/
 static void genJumpTab (iCode *ic)
 {
-    assert(0);
+    symbol *jtab;
+    char *l;
+
+    aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
+    /* get the condition into accumulator */
+    l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
+    if (!IS_GB)
+       emitcode("push", "de");
+    emitcode("ld", "e,%s", l);
+    emit2("ld d,!zero");
+    jtab = newiTempLabel(NULL);
+    spillCached();
+    emit2("ld hl,!immed!tlabel", jtab->key+100);
+    emitcode("add", "hl,de");
+    emitcode("add", "hl,de");
+    emitcode("add", "hl,de");
+    freeAsmop(IC_JTCOND(ic),NULL,ic);
+    if (!IS_GB)
+       emitcode("pop", "de");
+    emit2("jp !*hl");
+    emitLabel(jtab->key+100);
+    /* now generate the jump labels */
+    for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
+         jtab = setNextItem(IC_JTLABELS(ic)))
+       emit2("jp !tlabel", jtab->key+100);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3378,12 +4561,12 @@ static void genCast (iCode *ic)
     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
         return ;
 
-    aopOp(right,ic,FALSE;
-    aopOp(result,ic,FALSE);
+    aopOp(right,ic,FALSE, FALSE);
+    aopOp(result,ic,FALSE, FALSE);
 
     /* if the result is a bit */
     if (AOP_TYPE(result) == AOP_CRY) {
-       assert(0);
+       wassert(0);
     }
 
     /* if they are the same size : or less */
@@ -3405,10 +4588,13 @@ static void genCast (iCode *ic)
         goto release;
     }
 
+    /* PENDING: should be OK. */
+#if 0
     /* if the result is of type pointer */
     if (IS_PTR(ctype)) {
-       assert(0);
+       wassert(0);
     }
+#endif
     
     /* so we now know that the size of destination is greater
     than the size of the source */
@@ -3453,10 +4639,10 @@ static void genReceive (iCode *ic)
     if (isOperandInFarSpace(IC_RESULT(ic)) && 
        ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
          IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
-       assert(0);
+       wassert(0);
     } else {
        accInUse++;
-       aopOp(IC_RESULT(ic),ic,FALSE);  
+       aopOp(IC_RESULT(ic),ic,FALSE, FALSE);  
        accInUse--;
        assignResultValue(IC_RESULT(ic));       
     }
@@ -3472,6 +4658,17 @@ void genZ80Code (iCode *lic)
     iCode *ic;
     int cln = 0;
 
+    /* HACK */
+    if (IS_GB) {
+       _fReturn = _gbz80_return;
+       _fTmp = _gbz80_return;
+    }
+    else {
+       _fReturn = _z80_return;
+       _fTmp = _z80_return;
+    }
+    tsprintf(zero, "!zero");
+
     lineHead = lineCurr = NULL;
 
     /* if debug information required */
@@ -3676,7 +4873,7 @@ void genZ80Code (iCode *lic)
            
        case GETHBIT:
            emitcode("", "; genHBIT");
-           assert(0);
+           wassert(0);
            
        case LEFT_OP:
            emitcode("", "; genLeftShift");
@@ -3745,10 +4942,20 @@ void genZ80Code (iCode *lic)
 
     /* now we are ready to call the 
        peep hole optimizer */
-    /*    if (!options.nopeep)
-         peepHole (&lineHead); */
+    if (!options.nopeep)
+       peepHole (&lineHead);
 
+    /* This is unfortunate */
     /* now do the actual printing */
-    printLine (lineHead,codeOutFile);
-    return;
+    {
+       FILE *fp = codeOutFile;
+       if (isInHome() && codeOutFile == code->oFile)
+           codeOutFile = home->oFile;
+       printLine (lineHead, codeOutFile);
+       if (_G.flush_statics) {
+           flushStatics();
+           _G.flush_statics = 0;
+       }
+       codeOutFile = fp;
+    }
 }