* src/SDCCmain.c (setParseWithComma): fixed bug #816685
[fw/sdcc] / src / z80 / gen.c
index f822996156bc4d626f0533bcbe15ec5f6dccb4cb..e159073147471e29ba0ddeb42a3fbd849b89d443 100644 (file)
@@ -220,7 +220,8 @@ static struct
   bool flushStatics;
   bool in_home;
   const char *lastFunctionName;
-
+  iCode *current_iCode;
+  
   set *sendSet;
 
   struct
@@ -234,6 +235,7 @@ static struct
     lineNode *head;
     lineNode *current;
     int isInline;
+    int isDebug;
     allocTrace trace;
   } lines;
 
@@ -261,7 +263,8 @@ static const char *aopNames[] = {
   "AOP_HLREG",
   "AOP_SIMPLELIT",
   "AOP_EXSTK",
-  "AOP_PAIRPT"
+  "AOP_PAIRPT",
+  "AOP_DUMMY"
 };
 
 static bool
@@ -397,7 +400,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);
 
@@ -407,6 +410,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
@@ -466,6 +471,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);
 }
 
@@ -486,12 +492,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;
@@ -670,6 +690,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                                  */
 /*-----------------------------------------------------------------*/
@@ -1032,13 +1085,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);
+      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;
     }
@@ -1496,6 +1557,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;
       
@@ -1532,6 +1595,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)
@@ -1645,8 +1712,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));
 
@@ -1711,6 +1785,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);
@@ -1861,7 +1939,12 @@ aopPut (asmop * aop, const char *s, int offset)
 
     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:
@@ -2361,7 +2444,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);
@@ -2596,6 +2680,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 */
@@ -2764,12 +2849,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");
@@ -2796,9 +2893,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");
@@ -3051,7 +3145,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);
@@ -3083,6 +3192,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)
@@ -3094,6 +3206,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))))
@@ -3108,7 +3225,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++;
            }
        }
     }
@@ -3357,7 +3475,9 @@ 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))
         {
@@ -3563,7 +3683,7 @@ genPlus (iCode * ic)
           goto release;
         }
     }
-
+  
   setupToPreserveCarry (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)), AOP (IC_RIGHT (ic)));
 
   while (size--)
@@ -6956,7 +7076,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++);
@@ -7013,9 +7133,23 @@ genReceive (iCode * ic)
 static void
 genDummyRead (iCode * ic)
 {
-  emit2 ("; genDummyRead not implemented");
+  operand *right;
+  int size, offset;
 
-  ic = ic;
+  right = IC_RIGHT (ic);
+  aopOp (right, ic, FALSE, FALSE);
+  
+  /* general case */
+  size = AOP_SIZE (right);
+  offset = 0;
+
+  while (size--)
+    {
+      _moveA (aopGet (AOP (right), offset, FALSE));
+      offset++;
+    }
+
+  freeAsmop (right, NULL, ic);
 }
 
 enum
@@ -7554,12 +7688,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));
@@ -7823,6 +7981,7 @@ genZ80Code (iCode * lic)
           break;
 
        case DUMMY_READ_VOLATILE:
+         emitDebug ("; genDummyRead");
          genDummyRead (ic);
          break;