]> git.gag.com Git - fw/sdcc/blobdiff - src/z80/gen.c
* src/z80/gen.c (setupPair): Added 'extended stack' support for the z80. Can now...
[fw/sdcc] / src / z80 / gen.c
index c8c6df5cf302e736d0d4445091db587bf5852b40..7421f80070cf69ed65f888c99414c391aeecdd60 100644 (file)
@@ -167,10 +167,6 @@ static struct
 // PENDING
 #define ACC_NAME       _pairs[PAIR_AF].h
 
-#define RESULTONSTACK(x) \
-                         (IC_RESULT(x) && IC_RESULT(x)->aop && \
-                         IC_RESULT(x)->aop->type == AOP_STK )
-
 enum 
   {
     LSB,
@@ -220,8 +216,13 @@ static struct
     lineNode *head;
     lineNode *current;
     int isInline;
+    allocTrace trace;
   } lines;
 
+  struct
+  {
+    allocTrace aops;
+  } trace;
 } _G;
 
 static const char *aopGet (asmop * aop, int offset, bool bit16);
@@ -268,6 +269,17 @@ _tidyUp (char *buf)
     }
 }
 
+static lineNode *
+_newLineNode (char *line)
+{
+  lineNode *pl;
+
+  pl = traceAlloc(&_G.lines.trace, Safe_alloc ( sizeof (lineNode)));
+  pl->line = traceAlloc(&_G.lines.trace, Safe_strdup (line));
+
+  return pl;
+}
+
 static void
 _vemit2 (const char *szFormat, va_list ap)
 {
@@ -277,8 +289,8 @@ _vemit2 (const char *szFormat, va_list ap)
 
   _tidyUp (buffer);
   _G.lines.current = (_G.lines.current ?
-             connectLine (_G.lines.current, newLineNode (buffer)) :
-             (_G.lines.head = newLineNode (buffer)));
+             connectLine (_G.lines.current, _newLineNode (buffer)) :
+             (_G.lines.head = _newLineNode (buffer)));
 
   _G.lines.current->isInline = _G.lines.isInline;
 }
@@ -336,8 +348,8 @@ _emit2 (const char *inst, const char *fmt,...)
   if (lbp && *lbp)
     {
       _G.lines.current = (_G.lines.current ?
-                  connectLine (_G.lines.current, newLineNode (lb)) :
-                  (_G.lines.head = newLineNode (lb)));
+                  connectLine (_G.lines.current, _newLineNode (lb)) :
+                  (_G.lines.head = _newLineNode (lb)));
     }
   _G.lines.current->isInline = _G.lines.isInline;
   va_end (ap);
@@ -496,7 +508,7 @@ newAsmop (short type)
 {
   asmop *aop;
 
-  aop = Safe_calloc (1, sizeof (asmop));
+  aop = traceAlloc(&_G.trace.aops, Safe_alloc (sizeof (asmop)));
   aop->type = type;
   return aop;
 }
@@ -523,8 +535,21 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
   /* Assign depending on the storage class */
   if (sym->onStack || sym->iaccess)
     {
-      emitDebug ("; AOP_STK for %s", sym->rname);
-      sym->aop = aop = newAsmop (AOP_STK);
+      /* The pointer that is used depends on how big the offset is.
+         Normally everything is AOP_STK, but for offsets of < -127 or
+         > 128 on the Z80 an extended stack pointer is used.
+      */
+      if (IS_Z80 && (sym->stack < -127 || sym->stack > (int)(128-getSize (sym->type))))
+        {
+          emitDebug ("; AOP_EXSTK for %s", sym->rname);
+          sym->aop = aop = newAsmop (AOP_EXSTK);
+        }
+      else
+        {
+          emitDebug ("; AOP_STK for %s", sym->rname);
+          sym->aop = aop = newAsmop (AOP_STK);
+        }
+
       aop->size = getSize (sym->type);
       aop->aopu.aop_stk = sym->stack;
       return aop;
@@ -534,8 +559,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a)
   if (IS_FUNC (sym->type))
     {
       sym->aop = aop = newAsmop (AOP_IMMD);
-      aop->aopu.aop_immd = Safe_calloc (1, strlen (sym->rname) + 1);
-      strcpy (aop->aopu.aop_immd, sym->rname);
+      aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup (sym->rname));
       aop->size = 2;
       return aop;
     }
@@ -601,8 +625,7 @@ aopForRemat (symbol * sym)
       break;
     }
 
-  aop->aopu.aop_immd = Safe_calloc (1, strlen (buffer) + 1);
-  strcpy (aop->aopu.aop_immd, buffer);
+  aop->aopu.aop_immd = traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
   return aop;
 }
 
@@ -918,7 +941,7 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
         {
           tsprintf (s, "%s + %d", aop->aopu.aop_immd, offset);
         }
-      return gc_strdup(s);
+      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
 
     case AOP_LIT:
       {
@@ -947,7 +970,7 @@ aopGetLitWordLong (asmop * aop, int offset, bool with_hash)
            else
              tsprintf (buffer, "!constword", v);
 
-            return gc_strdup(buffer);
+            return traceAlloc(&_G.trace.aops, Safe_strdup(buffer));
          }
        else
          {
@@ -1024,6 +1047,7 @@ requiresHL (asmop * aop)
     case AOP_IY:
     case AOP_HL:
     case AOP_STK:
+    case AOP_EXSTK:
       return TRUE;
     default:
       return FALSE;
@@ -1060,7 +1084,7 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
            }
        }
       _G.pairs[pairId].last_type = left->type;
-      _G.pairs[pairId].base = gc_strdup (base);
+      _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
       _G.pairs[pairId].offset = offset;
     }
   /* Both a lit on the right and a true symbol on the left */
@@ -1136,12 +1160,39 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
   switch (aop->type)
     {
     case AOP_IY:
+      wassertl (pairId == PAIR_IY, "AOP_IY must be in IY");
       fetchLitPair (pairId, aop, 0);
       break;
+
     case AOP_HL:
       fetchLitPair (pairId, aop, offset);
       _G.pairs[pairId].offset = offset;
       break;
+
+    case AOP_EXSTK:
+      wassertl (IS_Z80, "Only the Z80 has an extended stack");
+      wassertl (pairId == PAIR_IY, "The Z80 extended stack must be in IY");
+
+      {
+       int offset = aop->aopu.aop_stk + _G.stack.offset;
+
+        if (_G.pairs[pairId].last_type == aop->type &&
+            _G.pairs[pairId].offset == offset)
+          {
+            /* Already setup */
+          }
+        else
+          {
+            /* PENDING: Do this better. */
+            sprintf (buffer, "%d", offset + _G.stack.pushed);
+            emit2 ("ld iy,!hashedstr", buffer);
+            emit2 ("add iy,sp");
+            _G.pairs[pairId].last_type = aop->type;
+            _G.pairs[pairId].offset = offset;
+          }
+      }
+      break;
+
     case AOP_STK:
       {
        /* Doesnt include _G.stack.pushed */
@@ -1190,7 +1241,7 @@ aopGet (asmop * aop, int offset, bool bit16)
       aop->type != AOP_LIT) 
     {
       tsprintf (s, "!zero");
-      return gc_strdup(s);
+      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
     }
 
   /* depending on type */
@@ -1216,21 +1267,21 @@ aopGet (asmop * aop, int offset, bool bit16)
            wassertl (0, "Fetching from beyond the limits of an immediate value.");
          }
 
-      return gc_strdup(s);
+      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
 
     case AOP_DIR:
       wassert (IS_GB);
       emit2 ("ld a,(%s+%d)", aop->aopu.aop_dir, offset);
       sprintf (s, "a");
 
-      return gc_strdup(s);
+      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
 
     case AOP_SFR:
       wassert (IS_GB);
       emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset);
       sprintf (s, "a");
 
-      return gc_strdup(s);
+      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
 
     case AOP_REG:
       return aop->aopu.aop_reg[offset]->name;
@@ -1240,14 +1291,21 @@ aopGet (asmop * aop, int offset, bool bit16)
       setupPair (PAIR_HL, aop, offset);
       tsprintf (s, "!*hl");
 
-      return gc_strdup (s);
+      return traceAlloc(&_G.trace.aops, Safe_strdup (s));
 
     case AOP_IY:
       wassert (IS_Z80);
       setupPair (PAIR_IY, aop, offset);
       tsprintf (s, "!*iyx", offset);
 
-      return gc_strdup(s);
+      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
+
+    case AOP_EXSTK:
+      wassert (IS_Z80);
+      setupPair (PAIR_IY, aop, offset);
+      tsprintf (s, "!*iyx", offset, offset);
+
+      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
 
     case AOP_STK:
       if (IS_GB)
@@ -1262,7 +1320,7 @@ aopGet (asmop * aop, int offset, bool bit16)
          tsprintf (s, "!*ixx", aop->aopu.aop_stk + offset);
        }
 
-      return gc_strdup(s);
+      return traceAlloc(&_G.trace.aops, Safe_strdup(s));
 
     case AOP_CRY:
       wassertl (0, "Tried to fetch from a bit variable");
@@ -1275,7 +1333,7 @@ aopGet (asmop * aop, int offset, bool bit16)
       else
         {
           tsprintf(s, "!zero");
-          return gc_strdup(s);
+          return traceAlloc(&_G.trace.aops, Safe_strdup(s));
         }
 
     case AOP_HLREG:
@@ -1292,7 +1350,7 @@ aopGet (asmop * aop, int offset, bool bit16)
         v >>= (offset * 8);
         tsprintf (s, "!immedbyte", (unsigned int) v & 0xff);
         
-        return gc_strdup(s);
+        return traceAlloc(&_G.trace.aops, Safe_strdup(s));
       }
     case AOP_STR:
       aop->coff = offset;
@@ -1384,14 +1442,17 @@ aopPut (asmop * aop, const char *s, int offset)
 
     case AOP_IY:
       wassert (!IS_GB);
-      setupPair (PAIR_IY, aop, offset);
       if (!canAssignToPtr (s))
        {
          emit2 ("ld a,%s", s);
+          setupPair (PAIR_IY, aop, offset);
          emit2 ("ld !*iyx,a", offset);
        }
       else
-       emit2 ("ld !*iyx,%s", offset, s);
+        {
+          setupPair (PAIR_IY, aop, offset);
+          emit2 ("ld !*iyx,%s", offset, s);
+        }
       break;
 
     case AOP_HL:
@@ -1407,6 +1468,21 @@ aopPut (asmop * aop, const char *s, int offset)
       emit2 ("ld !*hl,%s", s);
       break;
 
+    case AOP_EXSTK:
+      wassert (!IS_GB);
+      if (!canAssignToPtr (s))
+       {
+         emit2 ("ld a,%s", s);
+          setupPair (PAIR_IY, aop, offset);
+         emit2 ("ld !*iyx,a", offset);
+       }
+      else
+        {
+          setupPair (PAIR_IY, aop, offset);
+          emit2 ("ld !*iyx,%s", offset, s);
+        }
+      break;
+
     case AOP_STK:
       if (IS_GB)
        {
@@ -3399,7 +3475,8 @@ genCmp (operand * left, operand * right,
              else
                {
                  /* Subtract through, propagating the carry */
-                 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset++, FALSE));
+                 emit2 ("%s a,%s", offset == 0 ? "sub" : "sbc", aopGet (AOP (right), offset, FALSE));
+                 offset++;
                }
            }
        }
@@ -5914,7 +5991,7 @@ genZ80Code (iCode * lic)
   iCode *ic;
   int cln = 0;
 
-  /* HACK */
+  /* Hack */
   if (IS_GB)
     {
       _fReturn = _gbz80_return;
@@ -6205,6 +6282,9 @@ genZ80Code (iCode * lic)
       }
     codeOutFile = fp;
   }
+
+  freeTrace(&_G.lines.trace);
+  freeTrace(&_G.trace.aops);
 }
 
 /*
@@ -6245,7 +6325,7 @@ fetchLitSpecial (asmop * aop, bool negate, bool xor)
   v &= 0xFFFF;
 
   tsprintf (buffer, "!immedword", v);
-  return gc_strdup (buffer);
+  return traceAlloc(&_G.trace.aops, Safe_strdup (buffer));
 }