Lots.
[fw/sdcc] / src / z80 / gen.c
index 3f5075bd183dc55ba4dc0e5975924080447b69fb..a46c959d975a03c6b3332235feb6aacfeaacefcc 100644 (file)
@@ -1,26 +1,43 @@
 /*-------------------------------------------------------------------------
-  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
+
+  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.
 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;
+
 static char *accUse[] = {"a" };
 short rbank = -1;
 short accInUse = 0 ;
@@ -70,6 +77,8 @@ extern int ptrRegReq ;
 extern int nRegs;
 extern FILE *codeOutFile;
 set *sendSet = NULL;
+const char *_shortJP = "jp";
+
 #define RESULTONSTACK(x) \
                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
                          IC_RESULT(x)->aop->type == AOP_STK )
@@ -88,6 +97,10 @@ unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
 0x07, 0x03, 0x01, 0x00};
 
 static int _lastStack = 0;
+static int _pushed = 0;
+static int _spoffset;
+static int _lastHLOff = 0;
+static asmop *_lastHL;
 
 #define LSB     0
 #define MSB16   1
@@ -226,7 +239,7 @@ 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);
-
+       _lastHL = NULL;
        aop->aopu.aop_stk = sym->stack;
         return aop;
     }
@@ -240,10 +253,29 @@ 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)) {
+           sym->aop = aop = newAsmop (AOP_DIR);
+           aop->aopu.aop_dir = sym->rname ;
+           aop->size = getSize(sym->type);
+           emitcode("", "; AOP_DIR for %s", sym->rname);
+           return aop;
+       }
+    }
+#endif
+
     /* 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) {
+       sym->aop = aop = newAsmop(AOP_HL);
+       _lastHL = NULL;
+    }
+    else {
+       sym->aop = aop = newAsmop(AOP_IY);
+       emitcode ("ld","iy,#%s ; a", sym->rname);
+    }
     aop->size = getSize(sym->type);
     aop->aopu.aop_dir = sym->rname;
 
@@ -339,10 +371,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 +382,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;
 }
 
 /*-----------------------------------------------------------------*/
@@ -465,7 +498,7 @@ 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;
         }
 
@@ -521,18 +554,19 @@ dealloc:
     }
 }
 
-char *aopGetWord(asmop *aop, int offset)
+char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
 {
     char *s = buffer ;
     char *rs;
 
-    assert(aop->size == 2);
+    if (aop->size != 2)
+       return NULL;
     assert(offset == 0);
 
     /* depending on type */
     switch (aop->type) {
     case AOP_IMMD:
-       sprintf (s,"#%s",aop->aopu.aop_immd);
+       sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
@@ -544,7 +578,7 @@ char *aopGetWord(asmop *aop, int offset)
        if (!IS_FLOAT(val->type)) {
            unsigned long v = floatFromVal(val);
 
-           sprintf(buffer,"#0x%04lx", v);
+           sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
            ALLOC_ATOMIC(rs,strlen(buffer)+1);
            return strcpy (rs,buffer);
        }
@@ -555,6 +589,40 @@ char *aopGetWord(asmop *aop, int offset)
     return NULL;
 }
 
+char *aopGetWord(asmop *aop, int offset)
+{
+    return aopGetWordLong(aop, offset, TRUE);
+}
+
+static void setupHL(asmop *aop, int offset)
+{
+    if (_lastHL != aop) {
+       switch (aop->type) {
+       case AOP_HL:
+           emitcode("ld", "hl,#%s+%d", aop->aopu.aop_dir, offset);
+           break;
+       case AOP_STK:
+           /* In some cases we can still inc or dec hl */
+           emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
+           break;
+       default:
+           assert(0);
+       }
+       _lastHL = aop;
+       _lastHLOff = offset;
+    }
+    else {
+       while (offset < _lastHLOff) {
+           emitcode("dec", "hl");
+           _lastHLOff--;
+       }
+       while (offset > _lastHLOff) {
+           emitcode("inc", "hl");
+           _lastHLOff++;
+       }
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* aopGet - for fetching value of the aop                          */
 /*-----------------------------------------------------------------*/
@@ -587,8 +655,8 @@ static char *aopGet (asmop *aop, int offset, bool bit16)
        return rs;
        
     case AOP_DIR:
-       assert(0);
-       emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
+       assert(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);   
@@ -597,6 +665,14 @@ static char *aopGet (asmop *aop, int offset, bool bit16)
     case AOP_REG:
        return aop->aopu.aop_reg[offset]->name;
 
+    case AOP_HL:
+       assert(IS_GB);
+       setupHL(aop, offset);
+       sprintf(s, "(hl)");
+       ALLOC_ATOMIC(rs, strlen(s)+1);
+       strcpy(rs,s);
+       return rs;
+
     case AOP_IY:
        sprintf(s,"%d(iy)", offset);
        ALLOC_ATOMIC(rs,strlen(s)+1);
@@ -604,7 +680,13 @@ static char *aopGet (asmop *aop, int offset, bool bit16)
        return rs;
 
     case AOP_STK:
-       sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+       if (IS_GB) {
+           setupHL(aop, offset);
+           sprintf(s, "(hl)");
+       }
+       else {
+           sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+       }
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
@@ -665,8 +747,6 @@ bool canAssignToPtr(char *s)
 /*-----------------------------------------------------------------*/
 static void aopPut (asmop *aop, char *s, int offset)
 {
-    char *d = buffer ;
-
     if (aop->size && offset > ( aop->size - 1)) {
         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
                "aopPut got offset > aop->size");
@@ -677,10 +757,10 @@ 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. */
+       assert(IS_GB);
        emitcode("ld", "a,%s", s);
-       emitcode("ld", "(%s+%d),a", d, offset);
+       emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
        break;
        
     case AOP_REG:
@@ -692,6 +772,7 @@ static void aopPut (asmop *aop, char *s, int offset)
        break;
        
     case AOP_IY:
+       assert(!IS_GB);
        if (!canAssignToPtr(s)) {
            emitcode("ld", "a,%s", s);
            emitcode("ld", "%d(iy),a", offset);
@@ -699,14 +780,39 @@ static void aopPut (asmop *aop, char *s, int offset)
        else
            emitcode("ld", "%d(iy),%s", offset, s);
        break;
-       
+    
+    case AOP_HL:
+       assert(IS_GB);
+       if (!strcmp(s, "(hl)")) {
+           emitcode("ld", "a,(hl)");
+           s = "a";
+       }
+       setupHL(aop, offset);
+       emitcode("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) {
+           if (!strcmp("(hl)", s)) {
+               emitcode("ld", "a,(hl)");
+               s = "a";
+           }
+           setupHL(aop, offset);
+           if (!canAssignToPtr(s)) {
+               emitcode("ld", "a,%s", s);
+               emitcode("ld", "(hl),a");
+           }
+           else
+               emitcode("ld", "(hl),%s", s);
+       }
+       else {
+           if (!canAssignToPtr(s)) {
+               emitcode("ld", "a,%s", s);
+               emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
+           }
+           else
+               emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
        }
-       else
-           emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
        break;
        
     case AOP_CRY:
@@ -732,6 +838,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 {
@@ -833,8 +940,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));
+       }
     }
 }
 
@@ -911,9 +1020,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);
+    aopOp(IC_RESULT(ic),ic,TRUE);
+
+    /* if both in bit space then special
+    case */
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
+        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
+       assert(0);
+        goto release;
+    } 
+
+    optype = operandType(IC_LEFT(ic));
+    rtype = operandType(IC_RESULT(ic));
+
+    /* if float then do float stuff */
+    if (IS_FLOAT(optype)) {
+       assert(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);
+       emitcode("ld", "a,#0");
+       emitcode("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))))) {
+        emitcode("rlc","a");
+        emitcode("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 bool requiresHL(asmop *aop)
+{
+    switch (aop->type) {
+    case AOP_HL:
+    case AOP_STK:
+       return TRUE;
+    default:
+       return FALSE;
+    }
+}
 
 /*-----------------------------------------------------------------*/
 /* assignResultValue -                                            */
@@ -922,12 +1088,29 @@ void assignResultValue(operand * oper)
 {
     int offset = 0;
     int size = AOP_SIZE(oper);
+
+    assert(size <= 2);
+
     while (size--) {
-       aopPut(AOP(oper),fReturn[offset],offset);
+       aopPut(AOP(oper),_fReturn[offset],offset);
        offset++;
     }
 }
 
+static void fetchHL(asmop *aop)
+{
+    if (IS_GB && requiresHL(aop)) {
+       aopGet(aop, 0, FALSE);
+       emitcode("ld", "a,(hl+)");
+       emitcode("ld", "h,(hl)");
+       emitcode("ld", "l,a");
+    }
+    else {
+       emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
+       emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* genIpush - genrate code for pushing this gets a little complex  */
 /*-----------------------------------------------------------------*/
@@ -949,6 +1132,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;
        }
        else {
            offset = size;
@@ -958,6 +1142,7 @@ static void genIpush (iCode *ic)
                emitcode("ld", "a,%s", l);
                emitcode("push", "af");
                emitcode("inc", "sp");
+               _pushed++;
            }
        }
        return ;        
@@ -972,6 +1157,7 @@ static void genIpush (iCode *ic)
     size = AOP_SIZE(IC_LEFT(ic));
 
     if (isPair(AOP(IC_LEFT(ic)))) {
+       _pushed+=2;
        emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
     }
     else {
@@ -980,8 +1166,15 @@ static void genIpush (iCode *ic)
            if (s) {
                emitcode("ld", "hl,%s", s);
                emitcode("push", "hl");
-               goto release;
+               _pushed+=2;
+           }
+           else {
+               /* Optimise here - load into HL then push HL */
+               fetchHL(AOP(IC_LEFT(ic)));
+               emitcode("push", "hl");
+               _pushed += 2;
            }
+           goto release;
        }
        offset = size;
        while (size--) {
@@ -989,6 +1182,7 @@ static void genIpush (iCode *ic)
            emitcode("ld", "a,%s", l);
            emitcode("push", "af");
            emitcode("inc", "sp");
+           _pushed++;
        }       
     }
  release:
@@ -1036,7 +1230,6 @@ static void emitCall (iCode *ic, bool ispcall)
     /* if send set is not empty then assign */
     if (sendSet) {
        iCode *sic ;
-
        for (sic = setFirstItem(sendSet) ; sic ; 
             sic = setNextItem(sendSet)) {
            int size, offset = 0;
@@ -1045,9 +1238,9 @@ static void emitCall (iCode *ic, bool ispcall)
            while (size--) {
                char *l = aopGet(AOP(IC_LEFT(sic)),offset,
                                FALSE);
-               if (strcmp(l,fReturn[offset]))
+               if (strcmp(l, _fReturn[offset]))
                    emitcode("ld","%s,%s",
-                            fReturn[offset],
+                            _fReturn[offset],
                             l);
                offset++;
            }
@@ -1061,20 +1254,22 @@ static void emitCall (iCode *ic, bool ispcall)
 
        emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
        emitcode("push", "hl");
+       _pushed += 2;
 
        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));
+       fetchHL(AOP(IC_LEFT(ic)));
        freeAsmop(IC_LEFT(ic),NULL,ic); 
        
        emitcode("jp", "(hl)");
        emitcode("","%05d$:",(rlbl->key+100));
+       _pushed -= 2;
     }
     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;
+       emitcode("call", "%s", name);
     }
 
     /* if we need assign a result value */
@@ -1095,13 +1290,25 @@ 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;
+       _pushed -= i;
+       if (IS_GB) {
+           emitcode("lda", "sp,%d(sp)", i);
+       }
+       else {
+           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");
+           }
        }
-       if (i) 
-           emitcode("inc", "sp");
     }
 
 }
@@ -1171,19 +1378,27 @@ static void genFunction (iCode *ic)
     /* PENDING: callee-save etc */
 
     /* adjust the stack for the function */
-    emitcode("push", "de"); 
     emitcode("push", "bc");
-    emitcode("push", "ix");
-    emitcode("ld", "ix,#0");
-    emitcode("add", "ix,sp");
+    if (!IS_GB) {
+       emitcode("push", "de");
+       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");
-    }    
+       if (IS_GB) {
+           emitcode("lda", "sp,-%d(sp)", sym->stack);
+       }
+       else {
+           emitcode("ld", "hl,#-%d", sym->stack);
+           emitcode("add", "hl,sp");
+           emitcode("ld", "sp,hl");
+       }
+    }
+    _spoffset = sym->stack;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1214,13 +1429,23 @@ static void genEndFunction (iCode *ic)
                emitcode("","XG$%s$0$0 ==.",currFunc->name);
            debugLine = 0;
        }
-       emitcode("ld", "sp,ix");
-       emitcode("pop", "ix");
+       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("pop", "de");
        emitcode("ret", "");
     }
-
+    _pushed = 0;
+    _spoffset = 0;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1244,14 +1469,19 @@ 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 (strcmp(_fReturn[offset],l))
+               emitcode("ld","%s,%s", _fReturn[offset++],l);
        }
     }
     freeAsmop (IC_LEFT(ic),NULL,ic);
@@ -1299,9 +1529,23 @@ static bool genPlusIncr (iCode *ic)
     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
         return FALSE;
     
+    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);
+           return TRUE;
+       }
+    }
+
     /* 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)
+    if (icount > 4)
         return FALSE ;
 
     /* Inc a pair */
@@ -1318,7 +1562,7 @@ static bool genPlusIncr (iCode *ic)
         (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) {
@@ -1366,7 +1610,7 @@ void outBitAcc(operand *result)
        assert(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);
         outAcc(result);
@@ -1422,6 +1666,22 @@ static void genPlus (iCode *ic)
 
     size = getDataSize(IC_RESULT(ic));
 
+    /* Special case when left and right are constant */
+    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);
+       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;
+       }
+    }
+
     while(size--) {
        if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
            MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
@@ -1481,6 +1741,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) {
+           assert(0);
+       }
+       emitcode("", LABEL_STR ":",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)))) {
@@ -1541,7 +1820,6 @@ 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);
@@ -1552,9 +1830,14 @@ static void genMinus (iCode *ic)
     /* 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)
@@ -1677,10 +1960,15 @@ 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) {
+               emitcode("xor", "a,#0x80");
+               emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
+           }
+           else 
+               emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
         } 
        else {
             if(AOP_TYPE(right) == AOP_LIT) {
@@ -1695,8 +1983,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    
@@ -1705,19 +1992,50 @@ 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);
+                   emitcode("ld", "%s,#0x%02x", _fTmp[0],
+                            0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+               }
+               else {
+                   emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
+                   emitcode("xor", "a,#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);
+                   emitcode("ld", "%s,#0x%02x", _fTmp[1],
+                            0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
+               }
+               else {
+                   emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
+                   emitcode("xor", "a,#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",aopGet(AOP(right),offset++,FALSE));
                }
             }
         }
@@ -1818,8 +2136,11 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl)
     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("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++;
         }
@@ -1836,13 +2157,21 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl)
                /* PENDING */
                 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
             else {
-               emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
+               emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
                emitcode("jp", "nz," LABEL_STR , lbl->key+100);
            }
             offset++;
         }
     } else {
-       assert(0);
+        /* 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("jr", "nz," LABEL_STR, lbl->key+100);
+            offset++;
+        }
     }
 }
 
@@ -1857,7 +2186,7 @@ static void gencjne(operand *left, operand *right, symbol *lbl)
 
     /* PENDING: ?? */
     emitcode("ld","a,%s",one);
-    emitcode("jp", LABEL_STR ,tlbl->key+100);
+    emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
     emitcode("", LABEL_STR ":",lbl->key+100);
     emitcode("xor","a,a");
     emitcode("", LABEL_STR ":",tlbl->key+100);
@@ -1898,7 +2227,7 @@ static void genCmpEq (iCode *ic, iCode *ifx)
             } else {
                /* PENDING: do this better */
                 symbol *lbl = newiTempLabel(NULL);
-                emitcode("jp", LABEL_STR ,lbl->key+100);
+                emitcode(_shortJP, 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);             
@@ -1979,7 +2308,7 @@ static void genAndOp (iCode *ic)
     } 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);
         outBitAcc(result);
@@ -2012,9 +2341,9 @@ static void genOrOp (iCode *ic)
     } 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);
+        emitcode("", LABEL_STR ":",tlbl->key+100);
         outBitAcc(result);
     }
 
@@ -2043,6 +2372,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);                 
+        emitcode("", LABEL_STR ":",tlbl->key+100);
+        emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
+        emitcode("", LABEL_STR ":",nlbl->key+100);
+    }
+    else{
+        emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
+        emitcode("", LABEL_STR ":",tlbl->key+100);
+    }
+    ic->generated = 1;
+}
+
 /*-----------------------------------------------------------------*/
 /* genAnd  - code for and                                          */
 /*-----------------------------------------------------------------*/
@@ -2156,11 +2505,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 ;
             }
         }
@@ -2249,7 +2594,7 @@ static void genOr (iCode *ic, iCode *ifx)
     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
     aopOp((result=IC_RESULT(ic)),ic,TRUE);
 
-#ifdef DEBUG_TYPE
+#if 1
     emitcode("","; Type res[%d] = l[%d]&r[%d]",
              AOP_TYPE(result),
              AOP_TYPE(left), AOP_TYPE(right));
@@ -2304,17 +2649,17 @@ static void genOr (iCode *ic, iCode *ifx)
                 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
                     continue;
                 else 
-                   emitcode("or","%s,%s",
+                   emitcode("or","%s,%s; 5",
                             aopGet(AOP(left),offset,FALSE),
                             aopGet(AOP(right),offset,FALSE));
             } else {
                if (AOP_TYPE(left) == AOP_ACC) 
-                   emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
+                   emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
                else {              
                    MOVA(aopGet(AOP(right),offset,FALSE));
-                   emitcode("or","a,%s",
+                   emitcode("or","a,%s ; 7",
                             aopGet(AOP(left),offset,FALSE));
-                   aopPut(AOP(result),"a",0);
+                   aopPut(AOP(result),"a ; 8", offset);
                }
             }
         }
@@ -2341,9 +2686,11 @@ static void genOr (iCode *ic, iCode *ifx)
                MOVA(aopGet(AOP(right),offset,FALSE));
                emitcode("or","a,%s",
                         aopGet(AOP(left),offset,FALSE));
-               aopPut(AOP(result),"a",0);
            }
            aopPut(AOP(result),"a",offset);                     
+           /* PENDING: something weird is going on here.  Add exception. */
+           if (AOP_TYPE(result) == AOP_ACC)
+               break;
         }
     }
 
@@ -2544,7 +2891,7 @@ 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(_shortJP, LABEL_STR ,tlbl1->key+100); 
                emitcode("", LABEL_STR ":",tlbl->key+100);    
            }
 
@@ -2557,7 +2904,7 @@ static void shiftR2Left2Result (operand *left, int offl,
            if (shCount>1) {
                emitcode("", LABEL_STR ":",tlbl1->key+100);
                emitcode("dec", "a");
-               emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+               emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
            }
     }
 }
@@ -2573,9 +2920,12 @@ static void shiftL2Left2Result (operand *left, int offl,
        assert(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;
@@ -2586,7 +2936,7 @@ 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(_shortJP, LABEL_STR ,tlbl1->key+100); 
            emitcode("", LABEL_STR ":",tlbl->key+100);    
        }
 
@@ -2598,13 +2948,9 @@ static void shiftL2Left2Result (operand *left, int offl,
        if (shCount>1) {
            emitcode("", LABEL_STR ":",tlbl1->key+100);
            emitcode("dec", "a");
-           emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+           emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
        }
     }
-    else {
-       /* PENDING: do something */
-       assert(0);
-    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -2842,7 +3188,7 @@ static void genLeftShift (iCode *ic)
     offset = 0 ;   
     tlbl1 = newiTempLabel(NULL);
 
-    emitcode("jp", LABEL_STR ,tlbl1->key+100); 
+    emitcode(_shortJP, LABEL_STR ,tlbl1->key+100); 
     emitcode("", LABEL_STR ":",tlbl->key+100);    
     l = aopGet(AOP(result),offset,FALSE);
     emitcode("or", "a,a");
@@ -2852,7 +3198,7 @@ static void genLeftShift (iCode *ic)
     }
     emitcode("", LABEL_STR ":",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);
@@ -3026,6 +3372,10 @@ static void genGenPointerGet (operand *left,
 {
     int size, offset ;
     link *retype = getSpec(operandType(result));
+    const char *ptr = "hl";
+
+    if (IS_GB)
+       ptr = "de";
 
     aopOp(left,ic,FALSE);
     aopOp(result,ic,FALSE);
@@ -3041,10 +3391,14 @@ static void genGenPointerGet (operand *left,
     /* 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));
+       emitcode("ld","%s,%s", ptr, 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));
+       if (IS_GB) {
+           emitcode("ld", "e,%s", aopGet(AOP(left), 0, FALSE));
+           emitcode("ld", "d,%s", aopGet(AOP(left), 1, FALSE));
+       }
+       else
+           fetchHL(AOP(left));
     }
     /* so iy now contains the address */
     freeAsmop(left,NULL,ic);
@@ -3059,15 +3413,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)", ptr, offset);
                aopPut(AOP(result),"a",offset++);
            }
            if (size) {
-               emitcode("inc", "hl");
+               emitcode("inc", "%s", ptr);
            }
         }
     }
@@ -3110,10 +3464,14 @@ static void genGenPointerSet (operand *right,
 {    
     int size, offset ;
     link *retype = getSpec(operandType(right));
+    const char *ptr = "hl";
 
     aopOp(result,ic,FALSE);
     aopOp(right,ic,FALSE);
 
+    if (IS_GB)
+       ptr = "de";
+
     /* Handle the exceptions first */
     if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
        /* Just do it */
@@ -3130,12 +3488,17 @@ static void genGenPointerSet (operand *right,
         /* if this is remateriazable */
         if (AOP_TYPE(result) == AOP_IMMD) {
            emitcode("", "; Error 2");
-           emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
+           emitcode("ld", "%s,%s", ptr, 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));
+           if (IS_GB) {
+               emitcode("ld", "e,%s", aopGet(AOP(result), 0, TRUE));
+               emitcode("ld", "d,%s", aopGet(AOP(result), 1, TRUE));
+           }
+           else {
+               /* PENDING: do this better */
+               fetchHL(AOP(result));
+           }
         }
     }
     /* so hl know contains the address */
@@ -3151,16 +3514,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", ptr, l);
            }
            else {
                MOVA(l);
-               emitcode("ld", "(hl),a", offset);
+               emitcode("ld", "(%s),a", ptr, offset);
            }
            if (size) {
-               emitcode("inc", "hl");
+               emitcode("inc", ptr);
            }
            offset++;
         }
@@ -3237,19 +3599,29 @@ static void genAddrOf (iCode *ic)
     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) {
+           emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _pushed, _spoffset);
+           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");
+       }
     }
     else {
        emitcode("ld", "hl,#%s", sym->rname);
     }
     aopPut(AOP(IC_RESULT(ic)), "l", 0);
     aopPut(AOP(IC_RESULT(ic)), "h", 1);
-
+end:
     freeAsmop(IC_RESULT(ic),NULL,ic);
 }
 
@@ -3265,11 +3637,13 @@ 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);
@@ -3295,19 +3669,38 @@ static void genAssign (iCode *ic)
        (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), "#0", 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))) {
+       /* 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),
@@ -3327,7 +3720,31 @@ release:
 /*-----------------------------------------------------------------*/
 static void genJumpTab (iCode *ic)
 {
-    assert(0);
+    symbol *jtab;
+    char *l;
+
+    aopOp(IC_JTCOND(ic),ic,FALSE);
+    /* get the condition into accumulator */
+    l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
+    MOVA(l);
+    if (!IS_GB)
+       emitcode("push", "de");
+    emitcode("ld", "e,%s", l);
+    emitcode("ld", "d,#0");
+    jtab = newiTempLabel(NULL);
+    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);
+    /* now generate the jump labels */
+    for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
+         jtab = setNextItem(IC_JTLABELS(ic)))
+        emitcode("jp", LABEL_STR, jtab->key+100);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3371,10 +3788,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);
     }
+#endif
     
     /* so we now know that the size of destination is greater
     than the size of the source */
@@ -3438,6 +3858,18 @@ void genZ80Code (iCode *lic)
     iCode *ic;
     int cln = 0;
 
+    /* HACK */
+    if (IS_GB) {
+       _fReturn = _gbz80_return;
+       _fTmp = _gbz80_return;
+       _shortJP = "jr";
+    }
+    else {
+       _fReturn = _z80_return;
+       _fTmp = _z80_return;
+       _shortJP = "jp";
+    }
+
     lineHead = lineCurr = NULL;
 
     /* if debug information required */
@@ -3711,8 +4143,8 @@ void genZ80Code (iCode *lic)
 
     /* now we are ready to call the 
        peep hole optimizer */
-    /*    if (!options.nopeep)
-         peepHole (&lineHead); */
+    if (!options.nopeep)
+       peepHole (&lineHead);
 
     /* now do the actual printing */
     printLine (lineHead,codeOutFile);