* Runs dhrystone. 68.83d/s with terrible code.
[fw/sdcc] / src / z80 / gen.c
index 926012163818ee1d4d6b83e7b233a5c584f415f0..4ac569f5c854b5975cfc933e590af94d14c4a17d 100644 (file)
 #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 "SDCCglue.h" /* drdani Jan 30 2000 */
+#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 ;
@@ -106,6 +95,8 @@ 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
@@ -258,10 +249,27 @@ 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);
+    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;
 
@@ -484,7 +492,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;
         }
 
@@ -612,8 +620,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);   
@@ -622,6 +630,13 @@ static char *aopGet (asmop *aop, int offset, bool bit16)
     case AOP_REG:
        return aop->aopu.aop_reg[offset]->name;
 
+    case AOP_HL:
+       emitcode("ld", "hl,#%s+%d", aop->aopu.aop_dir, 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);
@@ -629,7 +644,16 @@ 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) {
+           /* 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)");
+       }
+       else {
+           sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+       }
        ALLOC_ATOMIC(rs,strlen(s)+1);
        strcpy(rs,s);   
        return rs;
@@ -690,8 +714,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");
@@ -702,10 +724,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:
@@ -717,6 +739,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);
@@ -724,14 +747,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";
+       }
+       emitcode("ld", "hl,#%s+%d", aop->aopu.aop_dir, 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";
+           }
+           emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
+           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:
@@ -859,8 +907,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));
+       }
     }
 }
 
@@ -987,6 +1037,17 @@ release:
     freeAsmop(IC_RESULT(ic),NULL,ic);
 }
 
+static bool requiresHL(asmop *aop)
+{
+    switch (aop->type) {
+    case AOP_DIR:
+    case AOP_HL:
+    case AOP_STK:
+       return TRUE;
+    default:
+       return FALSE;
+    }
+}
 
 /*-----------------------------------------------------------------*/
 /* assignResultValue -                                            */
@@ -995,12 +1056,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  */
 /*-----------------------------------------------------------------*/
@@ -1022,6 +1100,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;
@@ -1031,6 +1110,7 @@ static void genIpush (iCode *ic)
                emitcode("ld", "a,%s", l);
                emitcode("push", "af");
                emitcode("inc", "sp");
+               _pushed++;
            }
        }
        return ;        
@@ -1045,6 +1125,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 {
@@ -1053,12 +1134,13 @@ static void genIpush (iCode *ic)
            if (s) {
                emitcode("ld", "hl,%s", s);
                emitcode("push", "hl");
+               _pushed+=2;
            }
            else {
                /* Optimise here - load into HL then push HL */
-               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)));
                emitcode("push", "hl");
+               _pushed += 2;
            }
            goto release;
        }
@@ -1068,6 +1150,7 @@ static void genIpush (iCode *ic)
            emitcode("ld", "a,%s", l);
            emitcode("push", "af");
            emitcode("inc", "sp");
+           _pushed++;
        }       
     }
  release:
@@ -1115,7 +1198,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;
@@ -1124,9 +1206,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++;
            }
@@ -1140,20 +1222,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 */
@@ -1174,6 +1258,7 @@ 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;
+       _pushed -= i;
        if (i>6) {
            emitcode("ld", "hl,#%d", i);
            emitcode("add", "hl,sp");
@@ -1256,11 +1341,13 @@ 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;
 
@@ -1268,7 +1355,8 @@ static void genFunction (iCode *ic)
        emitcode("ld", "hl,#-%d", sym->stack);
        emitcode("add", "hl,sp");
        emitcode("ld", "sp,hl");
-    }    
+    }
+    _spoffset = sym->stack;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1299,13 +1387,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;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1329,14 +1427,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);
@@ -1407,7 +1510,7 @@ static bool genPlusIncr (iCode *ic)
     if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
        isPair(AOP(IC_RESULT(ic)))) {
        while (icount--) {
-           emitcode("inc", "%s ; 1", getPairName(AOP(IC_RESULT(ic))));
+           emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
        }
        return TRUE;
     }
@@ -1596,6 +1699,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)))) {
@@ -1804,7 +1926,7 @@ static void genCmp (operand *left,operand *right,
                emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
            }
            else 
-               emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
+               emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
         } 
        else {
             if(AOP_TYPE(right) == AOP_LIT) {
@@ -1834,25 +1956,25 @@ static void genCmp (operand *left,operand *right,
                if (AOP_TYPE(left) == AOP_LIT){
                    unsigned long lit = (unsigned long)
                        floatFromVal(AOP(left)->aopu.aop_lit);
-                   emitcode("ld", "l,#0x%02x",
+                   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", "l,a");
+                   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", "h,#0x%02x",
+                   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", "h,a");
+                   emitcode("ld", "%s,a", _fTmp[1]);
                    fDidXor = TRUE;
                }
                if (!fDidXor)
@@ -1866,8 +1988,8 @@ static void genCmp (operand *left,operand *right,
                if (!sign || size) 
                    MOVA(aopGet(AOP(left),offset,FALSE));
                 if (sign && size == 0) {
-                   emitcode("ld", "a,l");
-                   emitcode("sbc", "a,h");
+                   emitcode("ld", "a,%s", _fTmp[0]);
+                   emitcode("sbc", "a,%s", _fTmp[1]);
                }
                else {
                    /* Subtract through, propagating the carry */
@@ -1972,8 +2094,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++;
         }
@@ -1990,7 +2115,7 @@ 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++;
@@ -2001,7 +2126,7 @@ static void gencjneshort(operand *left, operand *right, symbol *lbl)
         while(size--) {
             char *l = aopGet(AOP(left),offset,FALSE);
             MOVA(aopGet(AOP(right),offset,FALSE));
-           emitcode("cp", "%s", l);
+           emitcode("cp", "%s ; 5", l);
            emitcode("jr", "nz," LABEL_STR, lbl->key+100);
             offset++;
         }
@@ -2476,7 +2601,7 @@ 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);
                }
             }
         }
@@ -3189,6 +3314,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);
@@ -3204,11 +3333,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);
@@ -3223,15 +3355,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);
            }
         }
     }
@@ -3274,10 +3406,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 */
@@ -3294,12 +3430,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 */
@@ -3315,16 +3456,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", l);
            }
            else {
                MOVA(l);
-               emitcode("ld", "(hl),a", offset);
+               emitcode("ld", "(%s),a", ptr, offset);
            }
            if (size) {
-               emitcode("inc", "hl");
+               emitcode("inc", ptr);
            }
            offset++;
         }
@@ -3401,19 +3541,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);
 }
 
@@ -3512,7 +3662,8 @@ static void genJumpTab (iCode *ic)
     /* get the condition into accumulator */
     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
     MOVA(l);
-    emitcode("push", "de");
+    if (!IS_GB)
+       emitcode("push", "de");
     emitcode("ld", "e,%s", l);
     emitcode("ld", "d,#0");
     jtab = newiTempLabel(NULL);
@@ -3520,7 +3671,8 @@ static void genJumpTab (iCode *ic)
     emitcode("add", "hl,de");
     emitcode("add", "hl,de");
     freeAsmop(IC_JTCOND(ic),NULL,ic);
-    emitcode("pop", "de");
+    if (!IS_GB)
+       emitcode("pop", "de");
     emitcode("jp", "(hl)");
     emitcode("","%05d$:",jtab->key+100);
     /* now generate the jump labels */
@@ -3570,10 +3722,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 */
@@ -3637,6 +3792,16 @@ void genZ80Code (iCode *lic)
     iCode *ic;
     int cln = 0;
 
+    /* HACK */
+    if (IS_GB) {
+       _fReturn = _gbz80_return;
+       _fTmp = _gbz80_return;
+    }
+    else {
+       _fReturn = _z80_return;
+       _fTmp = _z80_return;
+    }
+
     lineHead = lineCurr = NULL;
 
     /* if debug information required */