Pre making the rgbds branch
[fw/sdcc] / src / z80 / gen.c
index 0782a420cd41d6de258f8052d67edee9279175fa..cc4a1176a15123fde268a76fc8455533a6548d75 100644 (file)
@@ -16,6 +16,7 @@
   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)
@@ -30,6 +31,7 @@
   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
@@ -59,6 +61,7 @@
    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 ;
@@ -77,6 +80,31 @@ extern int ptrRegReq ;
 extern int nRegs;
 extern FILE *codeOutFile;
 set *sendSet = NULL;
+const char *_shortJP = "jp";
+
+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 )
@@ -94,23 +122,42 @@ unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
 unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
 0x07, 0x03, 0x01, 0x00};
 
-static int _lastStack = 0;
-static int _pushed = 0;
-static int _spoffset;
-
 #define LSB     0
 #define MSB16   1
 #define MSB24   2
 #define MSB32   3
 
 /* Stack frame:
-
    IX+4                param0  LH
    IX+2                ret     LH
    IX+0                ix      LH
    IX-2                temp0   LH
 */
 
+static struct {
+    struct {
+       AOP_TYPE last_type;
+       const char *lit;
+       int offset;
+    } pairs[NUM_PAIRS];
+    struct {
+       int last;
+       int pushed;
+       int offset;
+    } stack;
+    int frameId;
+} _G;
+
+static char *aopGet(asmop *aop, int offset, bool bit16);
+
+static char *_strdup(const char *s)
+{
+    char *ret;
+    ALLOC_ATOMIC(ret, strlen(s)+1);
+    strcpy(ret, s);
+    return ret;
+}
+
 /*-----------------------------------------------------------------*/
 /* emitcode - writes the code into a file : for now it is simple    */
 /*-----------------------------------------------------------------*/
@@ -139,6 +186,178 @@ void emitcode (const char *inst, const char *fmt, ...)
     va_end(ap);
 }
 
+typedef struct {
+    const char *szName;
+    const char *szFormat;
+} TOKEN;
+
+static TOKEN _tokens[] = {
+    { "area", ".area %s" },
+    { "global", ".globl %s" },
+    { "labeldef", "%s::" },
+    { "tlabeldef", "%05d$:" },
+    { "fileprelude", "; Generated using the default tokens." },
+    { "functionheader", 
+      "; ---------------------------------\n"
+      "; Function %s\n"
+      "; ---------------------------------"
+    },
+    { "functionlabeldef", "%s:" },
+    { "pusha", 
+      "\tpush af\n"
+      "\tpush bc\n"
+      "\tpush de\n"
+      "\tpush hl"
+    },
+    { "di", "\tdi" },
+    { "adjustsp", "\tlda sp,-%d(sp)" },
+    { "prelude", "\tpush bc" },
+    { "leave", 
+      "\tpop bc\n"
+      "\tret"
+    },
+    { "leavex", 
+      "\tlda sp,%d(sp)\n"
+      "\tpop bc\n"
+      "\tret"
+    },
+    { "hli", "(hl+) ; 2" },
+    { "*hl", "(hl) ; 1" },
+    { "ldahlsp", "lda hl,%d(sp)" },
+    { "ldaspsp", "lda sp,%d(sp)" },
+};
+
+/* 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");
+    }
+}
+*/
+
+#define NUM_TOKENS (sizeof(_tokens)/sizeof(_tokens[0]))
+
+static const TOKEN *_findToken(const char *szName)
+{
+    int i;
+    for (i=0; i < NUM_TOKENS; i++) {
+       if (!strcmp(_tokens[i].szName, szName))
+           return _tokens + i;
+    }
+    return NULL;
+}
+
+static va_list _iprintf(char *pInto, const char *szFormat, va_list ap)
+{
+    char *pStart = pInto;
+    char *sz = _strdup(szFormat);
+
+    while (*sz) {
+       if (*sz == '%') {
+           switch (*++sz) {
+               /* See if it's a special emitter */
+           case 'r':
+               wassert(0);
+               break;
+           default:
+               {
+                   /* Scan out the arg and pass it on to sprintf */
+                   char *p = sz-1, tmp;
+                   while (isdigit(*sz))
+                       sz++;
+                   /* Skip the format */
+                   tmp = *++sz;
+                   *sz = '\0';
+                   vsprintf(pInto, p, ap);
+                   /* PENDING: Assume that the arg length was an int */
+                   va_arg(ap, int);
+                   *sz = tmp;
+               }
+           }
+           pInto = pStart + strlen(pStart);
+       }
+       else {
+           *pInto++ = *sz++;
+       }
+    }
+    *pInto = '\0';
+
+    return ap;
+}
+
+static void vtprintf(char *buffer, const char *szFormat, va_list ap)
+{
+    char *sz = _strdup(szFormat);
+    char *pInto = buffer, *p;
+
+    buffer[0] = '\0';
+    
+    while (*sz) {
+       if (*sz == '!') {
+           /* Start of a token.  Search until the first
+              [non alplha, *] and call it a token. */
+           char old;
+           const TOKEN *t;
+           p = ++sz;
+           while (isalpha(*sz) || *sz == '*') {
+               sz++;
+           }
+           old = *sz;
+           *sz = '\0';
+           /* Now find the token in the token list */
+           if ((t = _findToken(p))) {
+               ap = _iprintf(pInto, t->szFormat, ap);
+               pInto = buffer + strlen(buffer);
+           }
+           else {
+               printf("Cant find token \"%s\"\n", p);
+               wassert(0);
+           }
+       }
+       else {
+           *pInto++ = *sz++;
+       }
+    }
+    *pInto = '\0';
+}
+
+static void tprintf(char *buffer, const char *szFormat, ...)
+{
+    va_list ap;
+
+    va_start(ap, szFormat);
+    vtprintf(buffer, szFormat, ap);
+}
+
+static void emit2(const char *szFormat, ...)
+{
+    char buffer[256];
+    va_list ap;
+
+    va_start(ap, szFormat);
+
+    vtprintf(buffer, szFormat, ap);
+
+    lineCurr = (lineCurr ?
+               connectLine(lineCurr,newLineNode(buffer)) :
+               (lineHead = newLineNode(buffer)));
+
+    lineCurr->isInline = inLine;
+    lineCurr->isDebug  = debugLine;
+}
+
 const char *getPairName(asmop *aop)
 {
     if (aop->type == AOP_REG) {
@@ -167,46 +386,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                                  */
 /*-----------------------------------------------------------------*/
@@ -235,7 +472,6 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
     if (sym->onStack || sym->iaccess) {
         sym->aop = aop = newAsmop(AOP_STK);
         aop->size = getSize(sym->type);
-
        aop->aopu.aop_stk = sym->stack;
         return aop;
     }
@@ -249,6 +485,7 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
         return aop;
     }
 
+#if 0
     if (IS_GB) {
        /* if it is in direct space */
        if (IN_DIRSPACE(space)) {
@@ -259,12 +496,16 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
            return aop;
        }
     }
+#endif
 
     /* only remaining is far space */
     /* in which case DPTR gets the address */
-    sym->aop = aop = newAsmop(AOP_IY);
-    if (!IS_GB)
-       emitcode ("ld","iy,#%s ; a", sym->rname);
+    if (IS_GB) {
+       sym->aop = aop = newAsmop(AOP_HL);
+    }
+    else {
+       sym->aop = aop = newAsmop(AOP_IY);
+    }
     aop->size = getSize(sym->type);
     aop->aopu.aop_dir = sym->rname;
 
@@ -525,11 +766,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 ) {
@@ -543,23 +779,39 @@ dealloc:
     }
 }
 
-char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
+bool isLitWord(asmop *aop)
+{
+    /*    if (aop->size != 2)
+         return FALSE;*/
+    switch (aop->type) {
+    case AOP_IMMD:
+    case AOP_LIT:
+       return TRUE;
+    default:
+       return FALSE;
+    }
+}
+
+char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
 {
     char *s = buffer ;
     char *rs;
 
-    if (aop->size != 2)
+#if 0
+    if (aop->size != 2 && aop->type != AOP_HL)
        return NULL;
-    assert(offset == 0);
+#endif
+    wassert(offset == 0);
 
     /* depending on type */
     switch (aop->type) {
+    case AOP_HL:
+    case AOP_IY:
     case AOP_IMMD:
        sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
-       
     case AOP_LIT: {
        value * val = aop->aopu.aop_lit;
        /* if it is a float then it gets tricky */
@@ -571,27 +823,176 @@ char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
            ALLOC_ATOMIC(rs,strlen(buffer)+1);
            return strcpy (rs,buffer);
        }
-       assert(0);
+       wassert(0);
        return NULL;
     }
+    default:
+       return NULL;
     }
-    return NULL;
 }
 
 char *aopGetWord(asmop *aop, int offset)
 {
-    return aopGetWordLong(aop, offset, TRUE);
+    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)--;
+    }
+}
+
+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 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].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 = _strdup(l);
+       _G.pairs[pairId].offset = offset;
+    }
+    /* Both a lit on the right and a true symbol on the left */
+    if (offset)
+       emitcode("ld", "%s,#%s + %d", pair, l, offset);
+    else 
+       emitcode("ld", "%s,#%s", 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);
+           emit2("ld a,!hli");
+           emit2("ld h,!*hl");
+           emit2("ld l,a");
+       }
+       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:
+    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;
+       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", aop->aopu.aop_stk+offset + _G.stack.pushed + _G.stack.offset);
+       }
+       _G.pairs[pairId].offset = abso;
+       break;
+    }
+    default:
+       wassert(0);
+    }
+    _G.pairs[pairId].last_type = aop->type;
+}
+
+static void emitLabel(int key)
+{
+    emit2("!tlabeldef yeah?", 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;
@@ -600,10 +1001,10 @@ static char *aopGet (asmop *aop, int offset, bool bit16)
     switch (aop->type) {
     case AOP_IMMD:
        if (bit16) 
-           sprintf (s,"#%s",aop->aopu.aop_immd);
+           sprintf (s,"#%s ; 5",aop->aopu.aop_immd);
        else
            if (offset) {
-               assert(offset == 1);
+               wassert(offset == 1);
                sprintf(s,"#>%s",
                        aop->aopu.aop_immd);
            }
@@ -615,7 +1016,7 @@ static char *aopGet (asmop *aop, int offset, bool bit16)
        return rs;
        
     case AOP_DIR:
-       assert(IS_GB);
+       wassert(IS_GB);
        emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
        sprintf(s, "a");
        ALLOC_ATOMIC(rs,strlen(s)+1);
@@ -625,29 +1026,35 @@ static char *aopGet (asmop *aop, int offset, bool bit16)
     case AOP_REG:
        return aop->aopu.aop_reg[offset]->name;
 
+    case AOP_HL:
+       wassert(IS_GB);
+       emitcode("", ";3");
+       setupPair(PAIR_HL, aop, offset);
+       tprintf(s, "!*hl");
+       return _strdup(s);
+
     case AOP_IY:
-       sprintf(s,"%d(iy)", offset);
+       wassert(IS_Z80);
+       setupPair(PAIR_IY, aop, offset);
+       tprintf(s,"!*iyx", offset);
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
 
     case AOP_STK:
        if (IS_GB) {
-           /* We cant really optimise this as we cant afford to
-              change the flags.
-           */
-           emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
-           sprintf(s, "(hl)");
+           setupPair(PAIR_HL, aop, offset);
+           tprintf(s, "!*hl");
        }
        else {
-           sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+           tprintf(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) {
@@ -661,12 +1068,10 @@ 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);
 }
 
@@ -683,7 +1088,7 @@ bool isRegString(char *s)
     return FALSE;
 }
 
-bool isConstant(char *s)
+bool isConstant(const char *s)
 {
     return  (*s == '#');
 }
@@ -713,7 +1118,7 @@ static void aopPut (asmop *aop, char *s, int offset)
     switch (aop->type) {
     case AOP_DIR:
        /* Direct.  Hmmm. */
-       assert(IS_GB);
+       wassert(IS_GB);
        emitcode("ld", "a,%s", s);
        emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
        break;
@@ -727,7 +1132,8 @@ static void aopPut (asmop *aop, char *s, int offset)
        break;
        
     case AOP_IY:
-       assert(!IS_GB);
+       wassert(!IS_GB);
+       setupPair(PAIR_IY, aop, offset);
        if (!canAssignToPtr(s)) {
            emitcode("ld", "a,%s", s);
            emitcode("ld", "%d(iy),a", offset);
@@ -735,14 +1141,25 @@ static void aopPut (asmop *aop, char *s, int offset)
        else
            emitcode("ld", "%d(iy),%s", offset, s);
        break;
-       
+    
+    case AOP_HL:
+       wassert(IS_GB);
+       if (!strcmp(s, "(hl)")) {
+           emitcode("ld", "a,(hl)");
+           s = "a";
+       }
+       emitcode("", ";2");
+       setupPair(PAIR_HL, aop, offset);
+       emitcode("ld", "(hl),%s", s);
+       break;
+
     case AOP_STK:
        if (IS_GB) {
            if (!strcmp("(hl)", s)) {
                emitcode("ld", "a,(hl)");
                s = "a";
            }
-           emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
+           setupPair(PAIR_HL, aop, offset);
            if (!canAssignToPtr(s)) {
                emitcode("ld", "a,%s", s);
                emitcode("ld", "(hl),a");
@@ -767,7 +1184,7 @@ static void aopPut (asmop *aop, char *s, int offset)
            emitcode("rla", "");
        } else {
            /* In bit space but not in C - cant happen */
-           assert(0);
+           wassert(0);
        }
        break;
        
@@ -813,7 +1230,7 @@ int getDataSize(operand *op)
     size = AOP_SIZE(op);
     if(size == 3) {
         /* pointer */
-       assert(0);
+       wassert(0);
     }
     return size;
 }
@@ -832,7 +1249,7 @@ static void movLeft2Result (operand *left, int offl,
            aopPut(AOP(result),l,offr);
        }
        else {
-           assert(0);
+           wassert(0);
         }
     }
 }
@@ -905,12 +1322,12 @@ static void genNot (iCode *ic)
 
     /* 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));
@@ -944,7 +1361,7 @@ static void genCpl (iCode *ic)
     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));
@@ -976,7 +1393,7 @@ static void genUminus (iCode *ic)
     case */
     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
-       assert(0);
+       wassert(0);
         goto release;
     } 
 
@@ -985,7 +1402,7 @@ static void genUminus (iCode *ic)
 
     /* if float then do float stuff */
     if (IS_FLOAT(optype)) {
-       assert(0);
+       wassert(0);
         goto release;
     }
 
@@ -1015,42 +1432,34 @@ release:
     freeAsmop(IC_RESULT(ic),NULL,ic);
 }
 
-static bool requiresHL(asmop *aop)
-{
-    switch (aop->type) {
-    case AOP_STK:
-       return TRUE;
-    default:
-       return FALSE;
-    }
-}
-
 /*-----------------------------------------------------------------*/
 /* assignResultValue -                                            */
 /*-----------------------------------------------------------------*/
 void assignResultValue(operand * oper)
 {
-    int offset = 0;
     int size = AOP_SIZE(oper);
+    bool topInA = 0;
 
-    assert(size <= 2);
-
-    while (size--) {
-       aopPut(AOP(oper),_fReturn[offset],offset);
-       offset++;
-    }
-}
+    wassert(size <= 4);
+    topInA = requiresHL(AOP(oper));
 
-static void fetchHL(asmop *aop)
-{
-    if (IS_GB && requiresHL(aop)) {
-       emitcode("ld", "a,%s", aopGet(aop, 0, FALSE));
-       emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
-       emitcode("ld", "l,a");
+    if (!IS_GB)
+       wassert(size <= 2);
+    if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
+       /* We do it the hard way here. */
+       emitcode("push", "hl");
+       _G.stack.pushed += 2;
+       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 {
-       emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
-       emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
+       while (size--) {
+           aopPut(AOP(oper), _fReturn[size], size);
+       }
     }
 }
 
@@ -1075,7 +1484,7 @@ static void genIpush (iCode *ic)
         /* push it on the stack */
        if (isPair(AOP(IC_LEFT(ic)))) {
            emitcode("push", getPairName(AOP(IC_LEFT(ic))));
-           _pushed += 2;
+           _G.stack.pushed += 2;
        }
        else {
            offset = size;
@@ -1085,7 +1494,7 @@ static void genIpush (iCode *ic)
                emitcode("ld", "a,%s", l);
                emitcode("push", "af");
                emitcode("inc", "sp");
-               _pushed++;
+               _G.stack.pushed++;
            }
        }
        return ;        
@@ -1100,23 +1509,15 @@ static void genIpush (iCode *ic)
     size = AOP_SIZE(IC_LEFT(ic));
 
     if (isPair(AOP(IC_LEFT(ic)))) {
-       _pushed+=2;
+       _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");
-               _pushed+=2;
-           }
-           else {
-               /* Optimise here - load into HL then push HL */
-               fetchHL(AOP(IC_LEFT(ic)));
-               emitcode("push", "hl");
-               _pushed += 2;
-           }
+           fetchHL(AOP(IC_LEFT(ic)));
+           emitcode("push", "hl ; 2");
+           spillPair(PAIR_HL);
+           _G.stack.pushed += 2;
            goto release;
        }
        offset = size;
@@ -1125,7 +1526,7 @@ static void genIpush (iCode *ic)
            emitcode("ld", "a,%s", l);
            emitcode("push", "af");
            emitcode("inc", "sp");
-           _pushed++;
+           _G.stack.pushed++;
        }       
     }
  release:
@@ -1154,6 +1555,7 @@ static void genIpop (iCode *ic)
        while (size--) {
            emitcode("dec", "sp");
            emitcode("pop", "hl");
+           spillPair(PAIR_HL);
            aopPut(AOP(IC_LEFT(ic)), "l", offset--);
        }
     }
@@ -1165,8 +1567,6 @@ static void genIpop (iCode *ic)
  */
 static void emitCall (iCode *ic, bool ispcall)
 {
-    int isPrintf = 0;
-
     /* if caller saves & we have not saved then */
     if (!ic->regsSaved) {
        /* PENDING */
@@ -1195,18 +1595,25 @@ static void emitCall (iCode *ic, bool ispcall)
     }
 
     if (ispcall) {
-       symbol *rlbl = newiTempLabel(NULL);
-
-       emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
-       emitcode("push", "hl");
-
        aopOp(IC_LEFT(ic),ic,FALSE);
-       emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
-       emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
+
+       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);
+           emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
+           emitcode("push", "hl");
+           _G.stack.pushed += 2;
+           
+           fetchHL(AOP(IC_LEFT(ic)));
+           emitcode("jp", "(hl)");
+           emitcode("","%05d$:",(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 */
@@ -1214,10 +1621,8 @@ static void emitCall (iCode *ic, bool ispcall)
            OP_SYMBOL(IC_LEFT(ic))->rname :
            OP_SYMBOL(IC_LEFT(ic))->name;
        emitcode("call", "%s", name);
-       if (!strcmp(name, "__printf"))
-           isPrintf = 1;
-
     }
+    spillCached();
 
     /* if we need assign a result value */
     if ((IS_ITEMP(IC_RESULT(ic)) && 
@@ -1237,22 +1642,26 @@ 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;
-       emitcode("", ";parmBytes = %u\n", i);
-       if (isPrintf)
-           i+=2;
-       _pushed -= i;
-       if (i>6) {
-           emitcode("ld", "hl,#%d", i);
-           emitcode("add", "hl,sp");
-           emitcode("ld", "sp,hl");
+       _G.stack.pushed -= i;
+       if (IS_GB) {
+           emit2("!ldaspsp", i);
        }
        else {
-           while (i>1) {
-               emitcode("pop", "hl");
-               i-=2;
+           spillCached();
+           if (i>6) {
+               emitcode("ld", "hl,#%d", i);
+               emitcode("add", "hl,sp");
+               emitcode("ld", "sp,hl");
            }
-           if (i) 
-               emitcode("inc", "sp");
+           else {
+               while (i>1) {
+                   emitcode("pop", "hl");
+                   i-=2;
+               }
+               if (i) 
+                   emitcode("inc", "sp");
+           }
+           spillCached();
        }
     }
 
@@ -1296,49 +1705,36 @@ static int resultRemat (iCode *ic)
 /*-----------------------------------------------------------------*/
 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(";","-----------------------------------------");
+    emit2("!functionheader", sym->name);
+    emit2("!functionlabeldef", sym->rname);
 
-    emitcode("","%s:",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");
+       emit2("!pusha");
     }
     /* PENDING: callee-save etc */
 
     /* adjust the stack for the function */
-    emitcode("push", "bc");
-    if (!IS_GB) {
-       emitcode("push", "de");
-       emitcode("push", "ix");
-       emitcode("ld", "ix,#0");
-       emitcode("add", "ix,sp");
-    }
+    emit2("!prelude");
 
-    _lastStack = sym->stack;
+    _G.stack.last = sym->stack;
 
     if (sym->stack) {
-       emitcode("ld", "hl,#-%d", sym->stack);
-       emitcode("add", "hl,sp");
-       emitcode("ld", "sp,hl");
+       emit2("!adjustsp", sym->stack);
     }
-    _spoffset = sym->stack;
+    _G.stack.offset = sym->stack;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1349,11 +1745,11 @@ 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");
        
        /* PENDING: calleeSave */
 
@@ -1369,23 +1765,13 @@ static void genEndFunction (iCode *ic)
                emitcode("","XG$%s$0$0 ==.",currFunc->name);
            debugLine = 0;
        }
-       if (!IS_GB) {
-           emitcode("ld", "sp,ix");
-           emitcode("pop", "ix");
-           emitcode("pop", "de");
-       }
-       else {
-           if (_spoffset) {
-               emitcode("ld", "hl,#%d", _spoffset);
-               emitcode("add", "hl,sp");
-               emitcode("ld", "sp,hl");
-           }
-       }
-       emitcode("pop", "bc");
-       emitcode("ret", "");
+       if (_G.stack.offset)
+           emit2("!leavex");
+       else
+           emit2("!leave");
     }
-    _pushed = 0;
-    _spoffset = 0;
+    _G.stack.pushed = 0;
+    _G.stack.offset = 0;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1409,14 +1795,25 @@ static void genRet (iCode *ic)
     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);
@@ -1439,7 +1836,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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1457,7 +1854,8 @@ 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 */
@@ -1467,55 +1865,54 @@ static bool genPlusIncr (iCode *ic)
     emitcode("", "; genPlusIncr");
 
     icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-
+    
     /* If result is a pair */
-    if (isPair(AOP(IC_RESULT(ic)))) {
-       char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
-       if (left) {
-           /* Both a lit on the right and a true symbol on the left */
-           emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
+    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 ;
+        return FALSE;
 
-    /* Inc a pair */
-    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
-       isPair(AOP(IC_RESULT(ic)))) {
-       while (icount--) {
-           emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
-       }
-       return TRUE;
-    }
     /* if increment 16 bits in register */
     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
         (size > 1) &&
         (icount == 1)) {
         symbol *tlbl = newiTempLabel(NULL);
        emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
-       emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
+       emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
     
        emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
        if(size == 4) {
-           assert(0);
+           wassert(0);
        }
-       emitcode("", LABEL_STR ":",tlbl->key+100);
+       emitLabel(tlbl->key+100);
         return TRUE;
     }
 
-    /* If result is a pair */
-    if (isPair(AOP(IC_RESULT(ic)))) {
-       movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
-       movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
-       while (icount--)
-           emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
-       return TRUE;
-    }
-
     /* if the sizes are greater than 1 then we cannot */
     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
         AOP_SIZE(IC_LEFT(ic)) > 1   )
@@ -1542,12 +1939,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(_shortJP,"z," LABEL_STR ,tlbl->key+100);
         emitcode("ld","a,%s",one);
-        emitcode("", LABEL_STR ":",tlbl->key+100);
+       emitLabel(tlbl->key+100);
         outAcc(result);
     }
 }
@@ -1584,14 +1981,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
@@ -1605,8 +2002,8 @@ static void genPlus (iCode *ic)
     if (isPair(AOP(IC_RESULT(ic)))) {
        char *left, *right;
        
-       left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
-       right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
+       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 */
@@ -1617,6 +2014,14 @@ static void genPlus (iCode *ic)
        }
     }
 
+    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;
+    }
+
     while(size--) {
        if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
            MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
@@ -1642,12 +2047,12 @@ static void genPlus (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);
 
      if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
        AOP_SIZE(IC_RIGHT(ic)) == 3   &&
        !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
-        assert(0);
+        wassert(0);
 
    
 release:
@@ -1688,9 +2093,9 @@ static bool genMinusDec (iCode *ic)
     
        emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
        if(size == 4) {
-           assert(0);
+           wassert(0);
        }
-       emitcode("", LABEL_STR ":",tlbl->key+100);
+       emitLabel(tlbl->key+100);
         return TRUE;
     }
 #endif
@@ -1744,7 +2149,7 @@ static void genMinus (iCode *ic)
     /* 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 ;
     }
 
@@ -1788,7 +2193,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);
@@ -1802,7 +2207,7 @@ release:
 static void genMult (iCode *ic)
 {
     /* Shouldn't occur - all done through function calls */
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1811,7 +2216,7 @@ static void genMult (iCode *ic)
 static void genDiv (iCode *ic)
 {
     /* Shouldn't occur - all done through function calls */
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1820,7 +2225,7 @@ static void genDiv (iCode *ic)
 static void genMod (iCode *ic)
 {
     /* Shouldn't occur - all done through function calls */
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1887,7 +2292,7 @@ static void genCmp (operand *left,operand *right,
     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
@@ -1962,15 +2367,16 @@ static void genCmp (operand *left,operand *right,
            }
             while (size--) {
                /* Do a long subtract */
-               if (!sign || size
+               if (!sign || size ) {
                    MOVA(aopGet(AOP(left),offset,FALSE));
+               }
                 if (sign && size == 0) {
                    emitcode("ld", "a,%s", _fTmp[0]);
                    emitcode("sbc", "a,%s", _fTmp[1]);
                }
                else {
                    /* Subtract through, propagating the carry */
-                   emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
+                   emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
                }
             }
         }
@@ -2070,15 +2476,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 ; 2", aopGet(AOP(left),offset,FALSE));
-           if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
+       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");
-           else 
-               emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
-            emitcode("jp", "nz," LABEL_STR , lbl->key+100);
-            offset++;
-        }
+           }
+           emitcode("jp", "nz," LABEL_STR, 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));
+               emitcode("jp", "nz," LABEL_STR , lbl->key+100);
+               offset++;
+           }
+       }
     }
     /* if the right side is in a register or in direct space or
     if the left is a pointer register & right is not */    
@@ -2101,9 +2523,8 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl)
         /* right is a pointer reg need both a & b */
        /* PENDING: is this required? */
         while(size--) {
-            char *l = aopGet(AOP(left),offset,FALSE);
             MOVA(aopGet(AOP(right),offset,FALSE));
-           emitcode("cp", "%s ; 5", l);
+           emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
            emitcode("jr", "nz," LABEL_STR, lbl->key+100);
             offset++;
         }
@@ -2121,10 +2542,10 @@ static void gencjne(operand *left, operand *right, symbol *lbl)
 
     /* PENDING: ?? */
     emitcode("ld","a,%s",one);
-    emitcode("jp", LABEL_STR ,tlbl->key+100);
-    emitcode("", LABEL_STR ":",lbl->key+100);
+    emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
+    emitLabel(lbl->key+100);
     emitcode("xor","a,a");
-    emitcode("", LABEL_STR ":",tlbl->key+100);
+    emitLabel(tlbl->key+100);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2152,20 +2573,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);                
+               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(_shortJP, LABEL_STR ,lbl->key+100);
+                emitLabel(tlbl->key+100);                
                 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
-                emitcode("", LABEL_STR ":",lbl->key+100);             
+               emitLabel(lbl->key+100);             
             }
         }
         /* mark the icode as generated */
@@ -2176,11 +2597,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");
@@ -2239,13 +2660,13 @@ static void genAndOp (iCode *ic)
     /* 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);
+        emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
         toBoolean(right);
-        emitcode("", LABEL_STR ":",tlbl->key+100);
+       emitLabel(tlbl->key+100);
         outBitAcc(result);
     }
 
@@ -2272,13 +2693,13 @@ static void genOrOp (iCode *ic)
     /* 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);
+        emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
         toBoolean(right);
-        emitcode("", LABEL_STR,tlbl->key+100);
+       emitLabel(tlbl->key+100);
         outBitAcc(result);
     }
 
@@ -2307,6 +2728,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);
+        emitcode("jp", LABEL_STR, nlbl->key+100);                 
+        emitLabel(tlbl->key+100);
+        emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
+        emitLabel(nlbl->key+100);
+    }
+    else{
+        emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
+        emitLabel(tlbl->key+100);
+    }
+    ic->generated = 1;
+}
+
 /*-----------------------------------------------------------------*/
 /* genAnd  - code for and                                          */
 /*-----------------------------------------------------------------*/
@@ -2358,7 +2799,7 @@ static void genAnd (iCode *ic, iCode *ifx)
     size = AOP_SIZE(result);
 
     if (AOP_TYPE(left) == AOP_CRY){
-       assert(0);
+       wassert(0);
         goto release ;
     }
 
@@ -2374,7 +2815,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)
@@ -2384,7 +2825,7 @@ static void genAnd (iCode *ic, iCode *ifx)
                     genIfxJump(ifx, buffer);
                 }
                else {
-                   assert(0);
+                   wassert(0);
                }
                 goto release;
             }
@@ -2392,7 +2833,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--){
@@ -2400,7 +2841,7 @@ 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{
@@ -2420,11 +2861,7 @@ static void genAnd (iCode *ic, iCode *ifx)
             // if(left & literal)
             else{
                 if(ifx)
-#if 0
                     jmpTrueOrFalse(ifx, tlbl);
-#else
-               assert(0);
-#endif
                 goto release ;
             }
         }
@@ -2451,7 +2888,7 @@ static void genAnd (iCode *ic, iCode *ifx)
 
             } else {
                if (AOP_TYPE(left) == AOP_ACC) {
-                   assert(0);
+                   wassert(0);
                }
                else {
                    MOVA(aopGet(AOP(right),offset,FALSE));
@@ -2463,7 +2900,7 @@ static void genAnd (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
@@ -2550,14 +2987,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 ;
     }
 
@@ -2567,10 +3004,12 @@ 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; 5",
-                            aopGet(AOP(left),offset,FALSE),
-                            aopGet(AOP(right),offset,FALSE));
+                else {
+                   MOVA(aopGet(AOP(right),offset,FALSE));
+                   emitcode("or","a,%s; 5",
+                            aopGet(AOP(left),offset,FALSE));
+                   aopPut(AOP(result),"a ; 8", offset);
+               }
             } else {
                if (AOP_TYPE(left) == AOP_ACC) 
                    emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
@@ -2578,14 +3017,14 @@ static void genOr (iCode *ic, iCode *ifx)
                    MOVA(aopGet(AOP(right),offset,FALSE));
                    emitcode("or","a,%s ; 7",
                             aopGet(AOP(left),offset,FALSE));
-                   aopPut(AOP(result),"a ; 8",0);
+                   aopPut(AOP(result),"a ; 8", 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
@@ -2660,14 +3099,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 ;
     }
 
@@ -2697,7 +3136,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
@@ -2769,7 +3208,7 @@ static void genInline (iCode *ic)
 /*-----------------------------------------------------------------*/
 static void genRRC (iCode *ic)
 {
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2777,7 +3216,7 @@ static void genRRC (iCode *ic)
 /*-----------------------------------------------------------------*/
 static void genRLC (iCode *ic)
 {    
-    assert(0);
+    wassert(0);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2789,14 +3228,14 @@ static void shiftR2Left2Result (operand *left, int offl,
 {
     if(sameRegs(AOP(result), AOP(left)) &&
        ((offl + MSB16) == offr)){
-       assert(0);
+       wassert(0);
     } else {
        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) {*/
@@ -2810,8 +3249,8 @@ static void shiftR2Left2Result (operand *left, int offl,
                emitcode("ld","a,#%u+1", shCount);
                tlbl = newiTempLabel(NULL);
                tlbl1 = newiTempLabel(NULL);
-               emitcode("jp", LABEL_STR ,tlbl1->key+100); 
-               emitcode("", LABEL_STR ":",tlbl->key+100);    
+               emitcode(_shortJP, LABEL_STR ,tlbl1->key+100); 
+               emitLabel(tlbl->key+100);    
            }
 
            emitcode("or", "a,a");
@@ -2821,9 +3260,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);
+               emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
            }
     }
 }
@@ -2836,7 +3275,7 @@ 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);
@@ -2855,8 +3294,8 @@ static void shiftL2Left2Result (operand *left, int offl,
            emitcode("ld","a,#%u+1", shCount);
            tlbl = newiTempLabel(NULL);
            tlbl1 = newiTempLabel(NULL);
-           emitcode("jp", LABEL_STR ,tlbl1->key+100); 
-           emitcode("", LABEL_STR ":",tlbl->key+100);    
+           emitcode(_shortJP, LABEL_STR ,tlbl1->key+100); 
+           emitLabel(tlbl->key+100);    
        }
 
        emitcode("or", "a,a");
@@ -2865,9 +3304,9 @@ 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);
+           emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
        }
     }
 }
@@ -2957,7 +3396,7 @@ 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) {
@@ -2979,7 +3418,7 @@ static void genlshTwo (operand *result,operand *left, int shCount)
     /*  1 <= shCount <= 7 */
     else {  
         if(size == 1) {
-           assert(0);
+           wassert(0);
        }
         else {
             shiftL2Left2Result(left, LSB, result, LSB, shCount);
@@ -3020,7 +3459,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))
@@ -3035,10 +3474,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);
@@ -3107,22 +3546,23 @@ static void genLeftShift (iCode *ic)
     offset = 0 ;   
     tlbl1 = newiTempLabel(NULL);
 
-    emitcode("jp", LABEL_STR ,tlbl1->key+100); 
-    emitcode("", LABEL_STR ":",tlbl->key+100);    
+    emitcode(_shortJP, LABEL_STR ,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);
+    emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
 
     freeAsmop(left,NULL,ic);
     freeAsmop(result,NULL,ic);
 }
 
+/*-----------------------------------------------------------------*/
 /* genlshTwo - left shift two bytes by known amount != 0           */
 /*-----------------------------------------------------------------*/
 static void genrshOne (operand *result,operand *left, int shCount)
@@ -3131,8 +3571,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) {
@@ -3177,7 +3617,7 @@ static void shiftR1Left2Result (operand *left, int offl,
 {
     MOVA(aopGet(AOP(left),offl,FALSE));
     if (sign) {
-       assert(0);
+       wassert(0);
     }
     else {
         AccRsh(shCount);
@@ -3195,7 +3635,7 @@ static void genrshTwo (operand *result,operand *left,
     if (shCount >= 8) {
         shCount -= 8 ;
         if (shCount) {
-           assert(0);
+           wassert(0);
             shiftR1Left2Result(left, MSB16, result, LSB,
                                shCount, sign);
        }
@@ -3233,7 +3673,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))
@@ -3249,10 +3689,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);
@@ -3264,7 +3704,26 @@ 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);
@@ -3275,12 +3734,56 @@ static void genRightShift (iCode *ic)
     /* 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);
+    aopOp(result,ic,FALSE);
+
+    /* now move the left to the result if they are not the
+    same */
+    if (!sameRegs(AOP(left),AOP(result)) && 
+        AOP_SIZE(result) > 1) {
+
+        size = AOP_SIZE(result);
+        offset=0;
+        while (size--) {
+            l = aopGet(AOP(left),offset,FALSE);
+           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;
+
+    emitcode(_shortJP, LABEL_STR, tlbl1->key+100);
+    emitcode("", LABEL_STR ":", 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);
     }
+    emitcode("", LABEL_STR ":", tlbl1->key+100);
+    emitcode("dec", "a");
+    emitcode(_shortJP, "nz," LABEL_STR, tlbl->key+100);
+
+    freeAsmop(left,NULL,ic);
+    freeAsmop(result,NULL,ic);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3291,31 +3794,39 @@ static void genGenPointerGet (operand *left,
 {
     int size, offset ;
     link *retype = getSpec(operandType(result));
+    int pair = PAIR_HL;
+
+    if (IS_GB)
+       pair = PAIR_DE;
 
     aopOp(left,ic,FALSE);
     aopOp(result,ic,FALSE);
-
-    if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
+    
+    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))) 
+           {
+               sprintf(buffer, "(%s)", getPairName(AOP(left)));
+               aopPut(AOP(result), buffer, 0);
+           }
+       else {
+           emitcode("ld", "a,(%s)", getPairName(AOP(left)));
+           aopPut(AOP(result),"a", 0);
+       }
        freeAsmop(left,NULL,ic);
        goto release;
     }
 
     /* For now we always load into IY */
     /* if this is remateriazable */
-    if (AOP_TYPE(left) == AOP_IMMD)
-       emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
-    else { /* we need to get it byte by byte */
-       fetchHL(AOP(left));
-    }
+    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);
@@ -3323,15 +3834,15 @@ static void genGenPointerGet (operand *left,
 
         while (size--) {
            /* PENDING: make this better */
-           if (AOP(result)->type == AOP_REG) {
+           if (!IS_GB && AOP(result)->type == AOP_REG) {
                aopPut(AOP(result),"(hl)",offset++);
            }
            else {
-               emitcode("ld", "a,(hl)", offset);
+               emitcode("ld", "a,(%s)", _pairs[pair].name, offset);
                aopPut(AOP(result),"a",offset++);
            }
            if (size) {
-               emitcode("inc", "hl");
+               emitcode("inc", "%s", _pairs[pair].name);
            }
         }
     }
@@ -3374,39 +3885,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);
 
+    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)) {
+           emitcode("ld", "(%s),%s", pair, l);
+       }
+       else {
+           MOVA(l);
+           emitcode("ld", "(%s),a ; 1", 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 */
-           fetchHL(AOP(result));
-        }
+       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);
@@ -3414,16 +3926,15 @@ 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) {
+               emitcode("ld", "(%s),%s ; 2", _pairs[pairId].name, l);
            }
            else {
                MOVA(l);
-               emitcode("ld", "(hl),a", offset);
+               emitcode("ld", "(%s),a ; 3", _pairs[pairId].name, offset);
            }
            if (size) {
-               emitcode("inc", "hl");
+               emitcode("inc", _pairs[pairId].name);
            }
            offset++;
         }
@@ -3498,31 +4009,32 @@ static void genAddrOf (iCode *ic)
     /* if the operand is on the stack then we 
     need to get the stack offset of this
     variable */
-    if (sym->onStack) {
-        /* if it has an offset  then we need to compute it */
-       if (IS_GB) {
-           emitcode("lda", "hl,%d+%d(sp)", sym->stack, _spoffset);
+    if (IS_GB) {
+       if (sym->onStack) {
+           spillCached();
+           emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
            emitcode("ld", "d,h");
            emitcode("ld", "e,l");
-           aopPut(AOP(IC_RESULT(ic)), "e", 0);
-           aopPut(AOP(IC_RESULT(ic)), "d", 1);
-           goto end;
        }
        else {
-           emitcode("push", "de");
-           emitcode("push", "ix");
-           emitcode("pop", "hl");
-           emitcode("ld", "de,#%d", sym->stack);
-           emitcode("add", "hl,de");
-           emitcode("pop", "de");
+           emitcode("ld", "de,#%s", 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);
-end:
     freeAsmop(IC_RESULT(ic),NULL,ic);
 }
 
@@ -3557,7 +4069,7 @@ static void genAssign (iCode *ic)
 
     /* if the result is a bit */
     if (AOP_TYPE(result) == AOP_CRY) {
-       assert(0);
+       wassert(0);
     }
 
     /* general case */
@@ -3566,7 +4078,10 @@ 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)) && AOP_TYPE(right) == AOP_LIT) {
+       emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
+    }
+    else if((size > 1) &&
        (AOP_TYPE(result) != AOP_REG) &&
        (AOP_TYPE(right) == AOP_LIT) &&
        !IS_FLOAT(operandType(right)) &&
@@ -3595,6 +4110,13 @@ static void genAssign (iCode *ic)
                       offset);
            offset++;
        }
+    }
+    else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
+       /* 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),
@@ -3626,14 +4148,16 @@ static void genJumpTab (iCode *ic)
     emitcode("ld", "e,%s", l);
     emitcode("ld", "d,#0");
     jtab = newiTempLabel(NULL);
+    spillCached();
     emitcode("ld", "hl,#" LABEL_STR, 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");
     emitcode("jp", "(hl)");
-    emitcode("","%05d$:",jtab->key+100);
+    emitLabel(jtab->key+100);
     /* now generate the jump labels */
     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
          jtab = setNextItem(IC_JTLABELS(ic)))
@@ -3659,7 +4183,7 @@ static void genCast (iCode *ic)
 
     /* if the result is a bit */
     if (AOP_TYPE(result) == AOP_CRY) {
-       assert(0);
+       wassert(0);
     }
 
     /* if they are the same size : or less */
@@ -3685,7 +4209,7 @@ static void genCast (iCode *ic)
 #if 0
     /* if the result is of type pointer */
     if (IS_PTR(ctype)) {
-       assert(0);
+       wassert(0);
     }
 #endif
     
@@ -3732,7 +4256,7 @@ 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);  
@@ -3755,10 +4279,12 @@ void genZ80Code (iCode *lic)
     if (IS_GB) {
        _fReturn = _gbz80_return;
        _fTmp = _gbz80_return;
+       _shortJP = "jr";
     }
     else {
        _fReturn = _z80_return;
        _fTmp = _z80_return;
+       _shortJP = "jp";
     }
 
     lineHead = lineCurr = NULL;
@@ -3965,7 +4491,7 @@ void genZ80Code (iCode *lic)
            
        case GETHBIT:
            emitcode("", "; genHBIT");
-           assert(0);
+           wassert(0);
            
        case LEFT_OP:
            emitcode("", "; genLeftShift");