* src/z80/peeph-z80.def: removed some peephole rules that don't
[fw/sdcc] / src / z80 / gen.c
index 9df933375c825dcb4c6b9d69b87fb7ef731c0971..281dc7baf33604390278b63dfe7b4cc5a983d4eb 100644 (file)
@@ -214,12 +214,15 @@ static struct
     int pushedDE;
   } calleeSaves;
 
+  bool omitFramePtr;
   int frameId;
   int receiveOffset;
   bool flushStatics;
   bool in_home;
   const char *lastFunctionName;
-
+  iCode *current_iCode;
+  bool preserveCarry;
+  
   set *sendSet;
 
   struct
@@ -233,6 +236,7 @@ static struct
     lineNode *head;
     lineNode *current;
     int isInline;
+    int isDebug;
     allocTrace trace;
   } lines;
 
@@ -260,7 +264,8 @@ static const char *aopNames[] = {
   "AOP_HLREG",
   "AOP_SIMPLELIT",
   "AOP_EXSTK",
-  "AOP_PAIRPT"
+  "AOP_PAIRPT",
+  "AOP_DUMMY"
 };
 
 static bool
@@ -396,7 +401,7 @@ _newLineNode (char *line)
 static void
 _vemit2 (const char *szFormat, va_list ap)
 {
-  char buffer[256];
+  char buffer[INITIAL_INLINEASM];
 
   tvsprintf (buffer, sizeof(buffer), szFormat, ap);
 
@@ -406,6 +411,8 @@ _vemit2 (const char *szFormat, va_list ap)
              (_G.lines.head = _newLineNode (buffer)));
 
   _G.lines.current->isInline = _G.lines.isInline;
+  _G.lines.current->isDebug = _G.lines.isDebug;
+  _G.lines.current->ic = _G.current_iCode;
 }
 
 static void
@@ -465,6 +472,7 @@ _emit2 (const char *inst, const char *fmt,...)
                   (_G.lines.head = _newLineNode (lb)));
     }
   _G.lines.current->isInline = _G.lines.isInline;
+  _G.lines.current->ic = _G.current_iCode;
   va_end (ap);
 }
 
@@ -485,12 +493,26 @@ _emitMove(const char *to, const char *from)
 void
 aopDump(const char *plabel, asmop *aop)
 {
+  int i;
+  char regbuf[9];
+  char *rbp = regbuf;
+  
   emitDebug("; Dump of %s: type %s size %u", plabel, aopNames[aop->type], aop->size);
   switch (aop->type)
     {
+    case AOP_EXSTK:
     case AOP_STK:
       emitDebug(";  aop_stk %d", aop->aopu.aop_stk);
       break;
+    case AOP_REG:
+      for (i=aop->size-1;i>=0;i--)
+        *rbp++ = *(aop->aopu.aop_reg[i]->name);
+      *rbp = '\0';
+      emitDebug(";  reg = %s", regbuf);
+      break;
+    case AOP_PAIRPTR:
+      emitDebug(";  pairptr = (%s)", _pairs[aop->aopu.aop_pairId].name);
+        
     default:
       /* No information. */
       break;
@@ -623,6 +645,30 @@ spillPair (PAIR_ID pairId)
   _G.pairs[pairId].base = NULL;
 }
 
+/* Given a register name, spill the pair (if any) the register is part of */
+static void
+spillPairReg (const char *regname)
+{      
+  if (strlen(regname)==1)
+    {
+      switch (*regname)
+        {
+        case 'h':
+        case 'l':
+          spillPair(PAIR_HL);
+          break;
+        case 'd':
+        case 'e':
+          spillPair(PAIR_DE);
+          break;
+        case 'b':
+        case 'c':
+          spillPair(PAIR_BC);
+          break;
+        }
+    }
+}
+
 /** Push a register pair onto the stack */
 void
 genPairPush (asmop * aop)
@@ -645,6 +691,39 @@ _pop (PAIR_ID pairId)
   spillPair (pairId);
 }
 
+void
+genMovePairPair (PAIR_ID srcPair, PAIR_ID dstPair)
+{
+  switch (dstPair)
+    {
+    case PAIR_IX:
+    case PAIR_IY:
+    case PAIR_AF:
+      _push(srcPair);
+      _pop(dstPair);
+      break;
+    case PAIR_BC:
+    case PAIR_DE:
+    case PAIR_HL:
+      if (srcPair == PAIR_IX || srcPair == PAIR_IY)
+        {
+          _push(srcPair);
+          _pop(dstPair);
+        }
+      else
+        {
+          emit2("ld %s,%s",_pairs[dstPair].l,_pairs[srcPair].l);
+          emit2("ld %s,%s",_pairs[dstPair].h,_pairs[srcPair].h);
+        }
+     default:
+       wassertl (0, "Tried to move a nonphysical pair");
+    }
+  _G.pairs[dstPair].last_type = _G.pairs[srcPair].last_type;
+  _G.pairs[dstPair].base = _G.pairs[srcPair].base;
+  _G.pairs[dstPair].offset = _G.pairs[srcPair].offset;
+}
+
+
 /*-----------------------------------------------------------------*/
 /* newAsmop - creates a new asmOp                                  */
 /*-----------------------------------------------------------------*/
@@ -686,7 +765,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
          Normally everything is AOP_STK, but for offsets of < -128 or
          > 127 on the Z80 an extended stack pointer is used.
       */
-      if (IS_Z80 && (options.ommitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
+      if (IS_Z80 && (_G.omitFramePtr || sym->stack < INT8MIN || sym->stack > (int)(INT8MAX-getSize (sym->type))))
         {
           emitDebug ("; AOP_EXSTK for %s", sym->rname);
           sym->aop = aop = newAsmop (AOP_EXSTK);
@@ -711,18 +790,34 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
       return aop;
     }
 
-  if (IS_GB)
+  if( IN_REGSP( space ))
+  { /*.p.t.20030716 minor restructure to add SFR support to the Z80 */
+    if (IS_GB)
     {
       /* if it is in direct space */
-      if (IN_REGSP (space) && !requires_a)
-       {
-         sym->aop = aop = newAsmop (AOP_SFR);
-         aop->aopu.aop_dir = sym->rname;
-         aop->size = getSize (sym->type);
+      if( !requires_a )
+      {
+        sym->aop = aop = newAsmop (AOP_SFR);
+        aop->aopu.aop_dir = sym->rname;
+        aop->size = getSize (sym->type);
          emitDebug ("; AOP_SFR for %s", sym->rname);
-         return aop;
-       }
+        return aop;
+      }
+    }
+    else
+    { /*.p.t.20030716 adding SFR support to the Z80 port */
+      aop = newAsmop (AOP_SFR);
+      sym->aop          = aop;
+      aop->aopu.aop_dir = sym->rname;
+      aop->size         = getSize( sym->type );
+      aop->paged        = FUNC_REGBANK(sym->type);
+      aop->bcInUse      = isPairInUse( PAIR_BC, ic );
+      aop->deInUse      = isPairInUse( PAIR_DE, ic );
+      emitDebug( ";Z80 AOP_SFR for %s banked:%d bc:%d de:%d", sym->rname, FUNC_REGBANK(sym->type), aop->bcInUse, aop->deInUse );
+
+      return( aop );
     }
+  }
 
   /* only remaining is far space */
   /* in which case DPTR gets the address */
@@ -915,6 +1010,11 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
   /* if already has a asmop then continue */
   if (op->aop)
     {
+      if (op->aop->type == AOP_SFR)
+        {
+          op->aop->bcInUse = isPairInUse( PAIR_BC, ic );
+          op->aop->deInUse = isPairInUse( PAIR_DE, ic );
+        }
       return;
     }
 
@@ -922,6 +1022,11 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
   if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
     {
       op->aop = OP_SYMBOL (op)->aop;
+      if (op->aop->type == AOP_SFR)
+        {
+          op->aop->bcInUse = isPairInUse( PAIR_BC, ic );
+          op->aop->deInUse = isPairInUse( PAIR_DE, ic );
+        }
       return;
     }
 
@@ -1007,14 +1112,21 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a)
          return;
        }
 
-      /* else spill location  */
-      if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
-         /* force a new aop if sizes differ */
-         sym->usl.spillLoc->aop = NULL;
-      }
-      sym->aop = op->aop = aop =
-       aopForSym (ic, sym->usl.spillLoc, result, requires_a);
-      wassertl (aop->size >= getSize (sym->type), "Operand doesn't fit in the spill location");
+      if (sym->usl.spillLoc)
+        {
+         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
+            {
+             /* force a new aop if sizes differ */
+             sym->usl.spillLoc->aop = NULL;
+           }
+         sym->aop = op->aop = aop =
+                    aopForSym (ic, sym->usl.spillLoc, result, requires_a);
+         aop->size = getSize (sym->type);
+         return;
+        }
+      
+      /* else must be a dummy iTemp */
+      sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
       aop->size = getSize (sym->type);
       return;
     }
@@ -1396,6 +1508,12 @@ setupPairFromSP (PAIR_ID id, int offset)
 {
   wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL");
 
+  if (_G.preserveCarry)
+    {
+      _push (PAIR_AF);
+      offset += 2;
+    }
+  
   if (offset < INT8MIN || offset > INT8MAX)
     {
       emit2 ("ld hl,!immedword", offset);
@@ -1403,7 +1521,13 @@ setupPairFromSP (PAIR_ID id, int offset)
     }
   else
     {
-      emit2 ("!ldahlsp", offset);
+          emit2 ("!ldahlsp", offset);
+    }
+
+  if (_G.preserveCarry)
+    {
+      _pop (PAIR_AF);
+      offset -= 2;
     }
 }
 
@@ -1439,11 +1563,15 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
         else
           {
             /* PENDING: Do this better. */
+            if (_G.preserveCarry)
+              _push (PAIR_AF);
             sprintf (buffer, "%d", offset + _G.stack.pushed);
             emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer);
             emit2 ("add %s,sp", _pairs[pairId].name);
             _G.pairs[pairId].last_type = aop->type;
             _G.pairs[pairId].offset = offset;
+            if (_G.preserveCarry)
+              _pop (PAIR_AF);
           }
       }
       break;
@@ -1472,6 +1600,8 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
       }
 
     case AOP_PAIRPTR:
+      if (pairId != aop->aopu.aop_pairId)
+        genMovePairPair(aop->aopu.aop_pairId, pairId);
       adjustPair (_pairs[pairId].name, &_G.pairs[pairId].offset, offset);
       break;
       
@@ -1508,6 +1638,10 @@ aopGet (asmop * aop, int offset, bool bit16)
   /* depending on type */
   switch (aop->type)
     {
+    case AOP_DUMMY:
+      tsprintf (buffer, sizeof(buffer), "!zero");
+      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+    
     case AOP_IMMD:
       /* PENDING: re-target */
       if (bit16)
@@ -1538,11 +1672,35 @@ aopGet (asmop * aop, int offset, bool bit16)
       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
     case AOP_SFR:
-      wassert (IS_GB);
-      emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
-      SNPRINTF (buffer, sizeof(buffer), "a");
+      if( IS_GB )
+      {
+        // wassert (IS_GB);
+        emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
+        SNPRINTF (buffer, sizeof(buffer), "a");
 
-      return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+        return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+      }
+      else
+      { /*.p.t.20030716 handling for i/o port read access for Z80 */
+        if( aop->paged )
+        { /* banked mode */
+         /* reg A goes to address bits 15-8 during "in a,(x)" instruction */
+         emit2( "ld a,!msbimmeds", aop->aopu.aop_dir);
+         emit2( "in a,(!lsbimmeds)", aop->aopu.aop_dir);
+        }
+        else if( z80_opts.port_mode == 180 )
+        { /* z180 in0/out0 mode */
+          emit2( "in0 a,(%s)", aop->aopu.aop_dir );
+        }
+        else
+        { /* 8 bit mode */
+          emit2( "in a,(%s)", aop->aopu.aop_dir );
+        }
+        
+        SNPRINTF (buffer, sizeof(buffer), "a");
+
+        return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
+      }
 
     case AOP_REG:
       return aop->aopu.aop_reg[offset]->name;
@@ -1621,8 +1779,15 @@ aopGet (asmop * aop, int offset, bool bit16)
 
     case AOP_PAIRPTR:
       setupPair (aop->aopu.aop_pairId, aop, offset);
-      SNPRINTF (buffer, sizeof(buffer), 
-               "(%s)", _pairs[aop->aopu.aop_pairId].name);
+      if (aop->aopu.aop_pairId==PAIR_IX)
+        SNPRINTF (buffer, sizeof(buffer), 
+                 "!*ixx", 0);
+      else if (aop->aopu.aop_pairId==PAIR_IY)
+        SNPRINTF (buffer, sizeof(buffer), 
+                 "!*iyx", 0);
+      else
+        SNPRINTF (buffer, sizeof(buffer), 
+                 "(%s)", _pairs[aop->aopu.aop_pairId].name);
 
       return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
 
@@ -1687,6 +1852,10 @@ aopPut (asmop * aop, const char *s, int offset)
   /* depending on where it is ofcourse */
   switch (aop->type)
     {
+    case AOP_DUMMY:
+      _moveA (s);  /* in case s is volatile */
+      break;
+      
     case AOP_DIR:
       /* Direct.  Hmmm. */
       wassert (IS_GB);
@@ -1696,10 +1865,49 @@ aopPut (asmop * aop, const char *s, int offset)
       break;
 
     case AOP_SFR:
-      wassert (IS_GB);
-      if (strcmp (s, "a"))
-       emit2 ("ld a,%s", s);
-      emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
+      if( IS_GB )
+      {
+        //  wassert (IS_GB);
+        if (strcmp (s, "a"))
+          emit2 ("ld a,%s", s);
+        emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset);
+      }
+      else
+      { /*.p.t.20030716 handling for i/o port read access for Z80 */
+        if( aop->paged )
+        { /* banked mode */
+          if( aop->bcInUse )  emit2( "push bc" );
+
+          emit2( "ld bc,#%s", aop->aopu.aop_dir );
+
+          if(( s[0] == '#'    ) /* immediate number */
+           ||( s[0] == '('    ) /* indirect register (ix or iy ??)*/
+           ||( isdigit( s[0] )))/* indirect register with offset (ix or iy ??)*/
+          {
+            emit2( "ld a,%s", s );
+            emit2( "out (c),a"  );
+          }
+          else
+          {
+            emit2( "out (c),%s", s );
+          }
+        
+          if( aop->bcInUse )
+            emit2( "pop bc"    );
+          else
+            spillPair (PAIR_BC);
+        }
+        else if( z80_opts.port_mode == 180 )
+        { /* z180 in0/out0 mode */
+          emit2( "ld a,%s", s );
+          emit2( "out0 (%s),a", aop->aopu.aop_dir );
+        }
+        else
+        { /* 8 bit mode */
+          emit2( "ld a,%s", s );
+          emit2( "out (%s),a", aop->aopu.aop_dir );
+        }
+      }
       break;
 
     case AOP_REG:
@@ -1708,6 +1916,7 @@ aopPut (asmop * aop, const char *s, int offset)
       else
        emit2 ("ld %s,%s",
               aop->aopu.aop_reg[offset]->name, s);
+      spillPairReg(aop->aopu.aop_reg[offset]->name);
       break;
 
     case AOP_IY:
@@ -1807,6 +2016,7 @@ aopPut (asmop * aop, const char *s, int offset)
        {
          emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
        }
+      spillPairReg(aop->aopu.aop_str[offset]);
       break;
 
     case AOP_ACC:
@@ -1820,18 +2030,27 @@ aopPut (asmop * aop, const char *s, int offset)
       else
        {
          if (strcmp (aop->aopu.aop_str[offset], s))
-           emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+           {
+             emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+             spillPairReg(aop->aopu.aop_str[offset]);
+           }
        }
       break;
 
     case AOP_HLREG:
       wassert (offset < 2);
       emit2 ("ld %s,%s", aop->aopu.aop_str[offset], s);
+      spillPairReg(aop->aopu.aop_str[offset]);
       break;
 
     case AOP_PAIRPTR:
       setupPair (aop->aopu.aop_pairId, aop, offset);
-      emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
+      if (aop->aopu.aop_pairId==PAIR_IX)
+        emit2 ("ld !*ixx,%s", 0, s);
+      else if (aop->aopu.aop_pairId==PAIR_IY)
+        emit2 ("ld !*ixy,%s", 0, s);
+      else
+        emit2 ("ld (%s),%s", _pairs[aop->aopu.aop_pairId].name, s);
       break;
 
     default:
@@ -1844,7 +2063,7 @@ aopPut (asmop * aop, const char *s, int offset)
 #define AOP(op) op->aop
 #define AOP_TYPE(op) AOP(op)->type
 #define AOP_SIZE(op) AOP(op)->size
-#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
+#define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR)))
 
 static void
 commitPair (asmop * aop, PAIR_ID id)
@@ -2033,43 +2252,6 @@ _toBoolean (operand * oper)
     }
 }
 
-/*-----------------------------------------------------------------*/
-/* genNotFloat - generates not for float operations              */
-/*-----------------------------------------------------------------*/
-static void
-genNotFloat (operand * op, operand * res)
-{
-  int size, offset;
-  symbol *tlbl;
-
-  emitDebug ("; genNotFloat");
-
-  /* we will put 127 in the first byte of
-     the result */
-  aopPut (AOP (res), "!immedbyte", 0x7F);
-  size = AOP_SIZE (op) - 1;
-  offset = 1;
-
-  _moveA (aopGet (op->aop, offset++, FALSE));
-
-  while (size--)
-    {
-      emit2 ("or a,%s", aopGet (op->aop, offset++, FALSE));
-    }
-
-  tlbl = newiTempLabel (NULL);
-  aopPut (res->aop, "!one", 1);
-  emit2 ("!shortjp z !tlabel", tlbl->key + 100);
-  aopPut (res->aop, "!zero", 1);
-
-  emitLabel(tlbl->key + 100);
-
-  size = res->aop->size - 2;
-  offset = 2;
-  /* put zeros in the rest */
-  while (size--)
-    aopPut (res->aop, "!zero", offset++);
-}
 
 /*-----------------------------------------------------------------*/
 /* genNot - generate code for ! operation                          */
@@ -2077,7 +2259,6 @@ genNotFloat (operand * op, operand * res)
 static void
 genNot (iCode * ic)
 {
-  sym_link *optype = operandType (IC_LEFT (ic));
 
   /* assign asmOps to operand & result */
   aopOp (IC_LEFT (ic), ic, FALSE, TRUE);
@@ -2089,13 +2270,6 @@ genNot (iCode * ic)
       wassertl (0, "Tried to negate a bit");
     }
 
-  /* if type float then do float */
-  if (IS_FLOAT (optype))
-    {
-      genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
-      goto release;
-    }
-
   _toBoolean (IC_LEFT (ic));
 
   /* Not of A:
@@ -2105,7 +2279,6 @@ genNot (iCode * ic)
   emit2 ("sub a,!one");
   outBitC (IC_RESULT (ic));
 
- release:
   /* release the aops */
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
@@ -2377,7 +2550,8 @@ _saveRegsForCall(iCode *ic, int sendSetSize)
     bool bcInRet = FALSE, deInRet = FALSE;
     bitVect *rInUse;
 
-    rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), ic->rUsed);
+    rInUse = bitVectCplAnd (bitVectCopy (ic->rMask), 
+                            z80_rUmaskForOp (IC_RESULT(ic)));
 
     deInUse = bitVectBitValue (rInUse, D_IDX) || bitVectBitValue(rInUse, E_IDX);
     bcInUse = bitVectBitValue (rInUse, B_IDX) || bitVectBitValue(rInUse, C_IDX);
@@ -2612,6 +2786,7 @@ _opUsesPair (operand * op, iCode * ic, PAIR_ID pairId)
 static void
 emitCall (iCode * ic, bool ispcall)
 {
+  bool bInRet, cInRet, dInRet, eInRet;
   sym_link *dtype = operandType (IC_LEFT (ic));
 
   /* if caller saves & we have not saved then */
@@ -2780,12 +2955,24 @@ emitCall (iCode * ic, bool ispcall)
     }
 
   spillCached ();
+  if (IC_RESULT (ic))
+    {
+      bitVect *result = z80_rUmaskForOp (IC_RESULT (ic));
+      bInRet = bitVectBitValue(result, B_IDX);
+      cInRet = bitVectBitValue(result, C_IDX);
+      dInRet = bitVectBitValue(result, D_IDX);
+      eInRet = bitVectBitValue(result, E_IDX);
+    }
+  else
+    {
+      bInRet = FALSE;
+      cInRet = FALSE;
+      dInRet = FALSE;
+      eInRet = FALSE;
+    }
 
   if (_G.stack.pushedDE) 
     {
-      bool dInRet = bitVectBitValue(ic->rUsed, D_IDX);
-      bool eInRet = bitVectBitValue(ic->rUsed, E_IDX);
-
       if (dInRet && eInRet)
         {
           wassertl (0, "Shouldn't push DE if it's wiped out by the return");
@@ -2812,9 +2999,6 @@ emitCall (iCode * ic, bool ispcall)
   
   if (_G.stack.pushedBC) 
     {
-      bool bInRet = bitVectBitValue(ic->rUsed, B_IDX);
-      bool cInRet = bitVectBitValue(ic->rUsed, C_IDX);
-
       if (bInRet && cInRet)
         {
           wassertl (0, "Shouldn't push BC if it's wiped out by the return");
@@ -2885,6 +3069,8 @@ extern set *publics;
 static void
 genFunction (iCode * ic)
 {
+  bool stackParm;
+  
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
   sym_link *ftype;
 
@@ -2979,13 +3165,35 @@ genFunction (iCode * ic)
 
   /* adjust the stack for the function */
   _G.stack.last = sym->stack;
-
-  if (sym->stack && IS_GB && sym->stack > -INT8MIN)
+  
+  stackParm = FALSE;
+  for (sym = setFirstItem (istack->syms); sym;
+       sym = setNextItem (istack->syms))
+    {
+      if (sym->_isparm && !IS_REGPARM (sym->etype))
+        {
+          stackParm = TRUE;
+          break;
+        }
+    }
+  sym = OP_SYMBOL (IC_LEFT (ic));
+  
+  _G.omitFramePtr = options.ommitFramePtr;
+  if (IS_Z80 && !stackParm && !sym->stack)
+    {
+      /* When the conflicts between AOP_EXSTK && AOP_HLREG are fixed, */
+      /* the above !sym->stack condition can be removed. -- EEP       */
+      if (sym->stack)
+        emit2 ("!ldaspsp", -sym->stack);
+      _G.omitFramePtr = TRUE;
+    }
+  else if (sym->stack && IS_GB && sym->stack > -INT8MIN)
     emit2 ("!enterxl", sym->stack);
   else if (sym->stack)
     emit2 ("!enterx", sym->stack);
-  else
+  else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
     emit2 ("!enter");
+
   _G.stack.offset = sym->stack;
 }
 
@@ -3008,7 +3216,12 @@ genEndFunction (iCode * ic)
 
       /* PENDING: calleeSave */
 
-      if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
+      if (IS_Z80 && _G.omitFramePtr)
+        {
+          if (_G.stack.offset)
+            emit2 ("!ldaspsp", _G.stack.offset);
+        }
+      else if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
         {
           emit2 ("!leavexl", _G.stack.offset);
         }
@@ -3016,7 +3229,7 @@ genEndFunction (iCode * ic)
         {
           emit2 ("!leavex", _G.stack.offset);
         }
-      else
+      else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
         {
           emit2 ("!leave");
         }
@@ -3039,7 +3252,22 @@ genEndFunction (iCode * ic)
         }
 
 
-      /* Both baned and non-banked just ret */
+      if (options.debug && currFunc)
+       {
+         _G.lines.isDebug = 1;
+         sprintf (buffer, "C$%s$%d$%d$%d",
+                   FileBaseName (ic->filename), currFunc->lastLine,
+                   ic->level, ic->block);
+          emit2 ("!labeldef", buffer);
+         if (IS_STATIC (currFunc->etype))
+           sprintf (buffer, "XF%s$%s$0$0", moduleName, currFunc->name);
+         else
+           sprintf (buffer, "XG$%s$0$0", currFunc->name);
+          emit2 ("!labeldef", buffer);
+         _G.lines.isDebug = 0;
+       }
+      
+      /* Both banked and non-banked just ret */
       emit2 ("ret");
 
       sprintf (buffer, "%s_end", sym->rname);
@@ -3071,6 +3299,9 @@ genRet (iCode * ic)
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
   size = AOP_SIZE (IC_LEFT (ic));
 
+  aopDump("IC_LEFT", AOP(IC_LEFT(ic)));
+
+  #if 0  
   if ((size == 2) && ((l = aopGetWord (AOP (IC_LEFT (ic)), 0))))
     {
       if (IS_GB)
@@ -3082,6 +3313,11 @@ genRet (iCode * ic)
          emit2 ("ld hl,%s", l);
        }
     }
+  #endif
+  if (size==2)
+    {
+      fetchPair(IS_GB ? PAIR_DE : PAIR_HL, AOP (IC_LEFT (ic)));
+    }
   else
     {
       if (IS_GB && size == 4 && requiresHL (AOP (IC_LEFT (ic))))
@@ -3096,7 +3332,8 @@ genRet (iCode * ic)
              l = aopGet (AOP (IC_LEFT (ic)), offset,
                          FALSE);
              if (strcmp (_fReturn[offset], l))
-               emit2 ("ld %s,%s", _fReturn[offset++], l);
+               emit2 ("ld %s,%s", _fReturn[offset], l);
+              offset++;
            }
        }
     }
@@ -3345,11 +3582,16 @@ setupToPreserveCarry (asmop *result, asmop *left, asmop *right)
       if (couldDestroyCarry (right) && couldDestroyCarry (result))
         {
           shiftIntoPair (0, right);
-          shiftIntoPair (1, result);
+          /* check result again, in case right == result */
+          if (couldDestroyCarry (result))
+            shiftIntoPair (1, result);
         }
       else if (couldDestroyCarry (right))
         {
-          shiftIntoPair (0, right);
+          if (getPairId (result) == PAIR_HL)
+            _G.preserveCarry = TRUE;
+          else
+            shiftIntoPair (0, right);
         }
       else if (couldDestroyCarry (result))
         {
@@ -3383,7 +3625,7 @@ genPlus (iCode * ic)
      in ACC */
 
   if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
-      (AOP_NEEDSACC (IC_LEFT (ic))) ||
+      (AOP_NEEDSACC (IC_RIGHT (ic))) ||
       AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
     {
       operand *t = IC_RIGHT (ic);
@@ -3551,7 +3793,7 @@ genPlus (iCode * ic)
           goto release;
         }
     }
-
+  
   setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
 
   while (size--)
@@ -3580,6 +3822,7 @@ genPlus (iCode * ic)
     }
 
 release:
+  _G.preserveCarry = FALSE;
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
@@ -3783,6 +4026,7 @@ genMinus (iCode * ic)
     }
 
 release:
+  _G.preserveCarry = FALSE;
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
   freeAsmop (IC_RESULT (ic), NULL, ic);
@@ -3798,11 +4042,14 @@ genMult (iCode * ic)
   int count, i;
   /* If true then the final operation should be a subtract */
   bool active = FALSE;
+  bool byteResult;
 
   /* Shouldn't occur - all done through function calls */
   aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
   aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
   aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
+  
+  byteResult =  (AOP_SIZE (IC_RESULT (ic)) == 1);
 
   if (AOP_SIZE (IC_LEFT (ic)) > 2 ||
       AOP_SIZE (IC_RIGHT (ic)) > 2 ||
@@ -3833,10 +4080,13 @@ genMult (iCode * ic)
   if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic)))))
     {
       emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE));
-      emit2 ("ld a,e");
-      emit2 ("rlc a");
-      emit2 ("sbc a,a");
-      emit2 ("ld d,a");
+      if (!byteResult)
+        {
+          emit2 ("ld a,e");
+          emit2 ("rlc a");
+          emit2 ("sbc a,a");
+          emit2 ("ld d,a");
+       }
     }
   else
     {
@@ -3858,7 +4108,8 @@ genMult (iCode * ic)
           if (active == FALSE)
             {
               emit2 ("ld l,e");
-              emit2 ("ld h,d");
+              if (!byteResult)
+               emit2 ("ld h,d");
             }
           else
             {
@@ -3877,7 +4128,10 @@ genMult (iCode * ic)
       _G.stack.pushedDE = FALSE;
     }
 
-  commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
+  if (byteResult)
+    aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0);
+  else
+    commitPair ( AOP (IC_RESULT (ic)), PAIR_HL);
 
   freeAsmop (IC_LEFT (ic), NULL, ic);
   freeAsmop (IC_RIGHT (ic), NULL, ic);
@@ -4747,7 +5001,7 @@ genAnd (iCode * ic, iCode * ifx)
 
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+      (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
     {
       operand *tmp = right;
       right = left;
@@ -4937,7 +5191,7 @@ genOr (iCode * ic, iCode * ifx)
 
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+      (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
     {
       operand *tmp = right;
       right = left;
@@ -5095,7 +5349,7 @@ genXor (iCode * ic, iCode * ifx)
 
   /* if left is a literal & right is not then exchange them */
   if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+      (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left)))
     {
       operand *tmp = right;
       right = left;
@@ -5172,9 +5426,9 @@ genXor (iCode * ic, iCode * ifx)
                continue;
              else
                {
-                 _moveA (aopGet (AOP (right), offset, FALSE));
+                 _moveA (aopGet (AOP (left), offset, FALSE));
                  emit2 ("xor a,%s",
-                           aopGet (AOP (left), offset, FALSE));
+                           aopGet (AOP (right), offset, FALSE));
                  aopPut (AOP (result), "a", offset);
                }
            }
@@ -5186,10 +5440,10 @@ genXor (iCode * ic, iCode * ifx)
                 }
              else
                {
-                 _moveA (aopGet (AOP (right), offset, FALSE));
+                 _moveA (aopGet (AOP (left), offset, FALSE));
                  emit2 ("xor a,%s",
-                           aopGet (AOP (left), offset, FALSE));
-                 aopPut (AOP (result), "a", 0);
+                           aopGet (AOP (right), offset, FALSE));
+                 aopPut (AOP (result), "a", offset);
                }
            }
        }
@@ -5224,9 +5478,9 @@ genXor (iCode * ic, iCode * ifx)
               }
            else
              {
-               _moveA (aopGet (AOP (right), offset, FALSE));
+               _moveA (aopGet (AOP (left), offset, FALSE));
                emit2 ("xor a,%s",
-                         aopGet (AOP (left), offset, FALSE));
+                         aopGet (AOP (right), offset, FALSE));
              }
            aopPut (AOP (result), "a", offset);
          }
@@ -6944,7 +7198,7 @@ genCast (iCode * ic)
   /* now depending on the sign of the destination */
   size = AOP_SIZE (result) - AOP_SIZE (right);
   /* Unsigned or not an integral type - right fill with zeros */
-  if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
+  if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
     {
       while (size--)
        aopPut (AOP (result), "!zero", offset++);
@@ -7001,9 +7255,44 @@ genReceive (iCode * ic)
 static void
 genDummyRead (iCode * ic)
 {
-  emit2 ("; genDummyRead not implemented");
+  operand *op;
+  int size, offset;
 
-  ic = ic;
+  op = IC_RIGHT (ic);
+  if (op && IS_SYMOP (op))
+    {
+      aopOp (op, ic, FALSE, FALSE);
+  
+      /* general case */
+      size = AOP_SIZE (op);
+      offset = 0;
+
+      while (size--)
+       {
+         _moveA (aopGet (AOP (op), offset, FALSE));
+         offset++;
+       }
+
+      freeAsmop (op, NULL, ic);
+    }
+  
+  op = IC_LEFT (ic);
+  if (op && IS_SYMOP (op))
+    {
+      aopOp (op, ic, FALSE, FALSE);
+  
+      /* general case */
+      size = AOP_SIZE (op);
+      offset = 0;
+
+      while (size--)
+       {
+         _moveA (aopGet (AOP (op), offset, FALSE));
+         offset++;
+       }
+
+      freeAsmop (op, NULL, ic);
+    }
 }
 
 enum
@@ -7542,12 +7831,36 @@ genZ80Code (iCode * lic)
     }
 
   _G.lines.head = _G.lines.current = NULL;
+  
+  /* if debug information required */
+  if (options.debug && currFunc)
+    {
+      debugFile->writeFunction(currFunc);
+      _G.lines.isDebug = 1;
+      if (IS_STATIC (currFunc->etype))
+       sprintf (buffer, "F%s$%s$0$0", moduleName, currFunc->name);
+      else
+       sprintf (buffer, "G$%s$0$0", currFunc->name);
+      emit2 ("!labeldef", buffer);
+      _G.lines.isDebug = 0;
+    }
 
   for (ic = lic; ic; ic = ic->next)
     {
+      _G.current_iCode = ic;
 
-      if (cln != ic->lineno)
+      if (ic->lineno && cln != ic->lineno)
        {
+         if (options.debug)
+           {
+             _G.lines.isDebug = 1;
+             sprintf (buffer, "C$%s$%d$%d$%d",
+                       FileBaseName (ic->filename), ic->lineno,
+                       ic->level, ic->block);
+              emit2 ("%s !equ .", buffer);
+              emit2 ("!global", buffer);
+             _G.lines.isDebug = 0;
+           }
          if (!options.noCcodeInAsm) {
            emit2 (";%s:%d: %s", ic->filename, ic->lineno,
                   printCLine(ic->filename, ic->lineno));
@@ -7811,6 +8124,7 @@ genZ80Code (iCode * lic)
           break;
 
        case DUMMY_READ_VOLATILE:
+         emitDebug ("; genDummyRead");
          genDummyRead (ic);
          break;