* src/z80/main.c: enabled "critical" keyword
authorepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 4 Aug 2004 21:05:21 +0000 (21:05 +0000)
committerepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 4 Aug 2004 21:05:21 +0000 (21:05 +0000)
* src/z80/mappings.i,
* src/z80/gen.c (genFunction, genEndFunction): support for interrupt
functions (fixes bug #979646)
* doc/sdccman.lyx: added a subsection explaining z80 interrupt support

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3420 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
doc/sdccman.lyx
src/z80/gen.c
src/z80/main.c
src/z80/mappings.i

index 1821e22fc0f01799fb188a9c994e41f2a831ca0c..0fc53ce6e09db7fdeb555bd45dd7e6508dfdee45 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2004-08-04 Erik Petrich <epetrich AT ivorytower.norman.ok.us>
+       * src/z80/main.c: enabled "critical" keyword
+       * src/z80/mappings.i,
+       * src/z80/gen.c (genFunction, genEndFunction): support for interrupt
+       functions (fixes bug #979646)
+       * doc/sdccman.lyx: added a subsection explaining z80 interrupt support
+
 2004-08-04 Jesus Calvino-Fraga <jesusc AT ece.ubc.ca>
 
        * src/mcs51/gen.c (genInline): Add \n for labels, not DOS/WIN dirs
index 75d1494ef8bb49deac8011ad008494bc1f4b2cd2..582b8366792cb3fa72445d7b6ce3c34f1e7b0703 100644 (file)
@@ -10340,6 +10340,41 @@ Since the number of interrupts available is chip specific and the interrupt
 \end_inset 
 
  for details on customizing startup.
+\layout Subsection
+
+Z80 Interrupt Service Routines
+\layout Standard
+
+The Z80 uses several different methods for determining the correct interrupt
+ vector depending on the hardware implementation.
+ Therefore, SDCC ignores the optional interrupt number and does not attempt
+ to generate an interrupt vector table.
+\layout Standard
+
+By default, SDCC generates code for a maskable interrupt, which uses an
+ RETI instruction to return from the interrupt.
+ To write an interrupt handler for the non-maskable interrupt, which needs
+ an RETN instruction instead, add the 
+\emph on 
+critical
+\emph default 
+ keyword:
+\layout Verse
+
+
+\family typewriter 
+void nmi_isr (void) critical interrupt
+\newline 
+{ 
+\newline 
+\SpecialChar ~
+\SpecialChar ~
+\SpecialChar ~
+\SpecialChar ~
+...
+\newline 
+}
 \layout Section
 
 Enabling and Disabling Interrupts
index 127bc13fd2bd32ce5df6cd62ea0eea2b4270d025..2818150f3b63aedbdad12a2ea27e8d9239313ce5 100644 (file)
@@ -3113,14 +3113,21 @@ genFunction (iCode * ic)
 
   ftype = operandType (IC_LEFT (ic));
 
-  /* if critical function then turn interrupts off */
-  if (IFFUNC_ISCRITICAL (ftype))
-    emit2 ("!di");
-
   /* if this is an interrupt service routine then save all potentially used registers. */
   if (IFFUNC_ISISR (sym->type))
     {
-      emit2 ("!pusha");
+      if (!FUNC_ISNAKED( sym->type ))
+        {
+          emit2 ("!pusha");
+       }
+    }
+  else
+    {
+      /* if critical function then turn interrupts off */
+      if (IFFUNC_ISCRITICAL (sym->type))
+        {
+          emit2 ("!di");
+       }
     }
 
   /* PENDING: callee-save etc */
@@ -3218,64 +3225,80 @@ genEndFunction (iCode * ic)
 {
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
 
-  if (IFFUNC_ISISR (sym->type))
+
+  /* PENDING: calleeSave */
+  if (IS_Z80 && _G.omitFramePtr)
     {
-      wassertl (0, "Tried to close an interrupt support function");
+      if (_G.stack.offset)
+        emit2 ("!ldaspsp", _G.stack.offset);
     }
-  else
+  else if (_G.stack.offset && IS_GB && _G.stack.offset > INT8MAX)
     {
-      if (IFFUNC_ISCRITICAL (sym->type))
-       emit2 ("!ei");
-
-      /* PENDING: calleeSave */
-
-      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);
-        }
-      else if (_G.stack.offset)
-        {
-          emit2 ("!leavex", _G.stack.offset);
-        }
-      else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
-        {
-          emit2 ("!leave");
-        }
+      emit2 ("!leavexl", _G.stack.offset);
+    }
+  else if (_G.stack.offset)
+    {
+      emit2 ("!leavex", _G.stack.offset);
+    }
+  else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */
+    {
+      emit2 ("!leave");
+    }
+      
+  if (_G.calleeSaves.pushedDE) 
+    {
+      emit2 ("pop de");
+      _G.calleeSaves.pushedDE = FALSE;
+    }
 
-      if (_G.calleeSaves.pushedDE
-        {
-          emit2 ("pop de");
-          _G.calleeSaves.pushedDE = FALSE;
-        }
+  if (_G.calleeSaves.pushedBC
+    {
+      emit2 ("pop bc");
+      _G.calleeSaves.pushedBC = FALSE;
+    }
 
-      if (_G.calleeSaves.pushedBC) 
-        {
-          emit2 ("pop bc");
-          _G.calleeSaves.pushedBC = FALSE;
-        }
+  if (options.profile) 
+    {
+      emit2 ("!profileexit");
+    }
 
-      if (options.profile) 
+  /* if this is an interrupt service routine then restore all potentially used registers. */
+  if (IFFUNC_ISISR (sym->type))
+    {
+      if (!FUNC_ISNAKED( sym->type ))
         {
-          emit2 ("!profileexit");
+          emit2 ("!popa");
         }
+    }
+  else
+    {
+      /* if critical function then turn interrupts back on */
+      if (IFFUNC_ISCRITICAL (sym->type))
+        emit2 ("!ei");
+    }
 
-
-      if (options.debug && currFunc)
-       {
-         debugFile->writeEndFunction (currFunc, ic, 1);
-       }
+  if (options.debug && currFunc)
+    {
+      debugFile->writeEndFunction (currFunc, ic, 1);
+    }
       
+  if (IFFUNC_ISISR (sym->type))
+    {
+      /* "critical interrupt" is used to imply NMI handler */
+      if (IS_Z80 && IFFUNC_ISCRITICAL (sym->type))
+        emit2 ("retn");
+      else
+        emit2 ("reti");
+    }
+  else
+    {
       /* Both banked and non-banked just ret */
       emit2 ("ret");
-
-      sprintf (buffer, "%s_end", sym->rname);
-      emit2 ("!labeldef", buffer);
     }
+      
+  sprintf (buffer, "%s_end", sym->rname);
+  emit2 ("!labeldef", buffer);
+  
   _G.flushStatics = 1;
   _G.stack.pushed = 0;
   _G.stack.offset = 0;
index de057f8994a202d70c3ab694776bbfae137210df..99a518ddc909d0ad2b1210228885f5360ae00646 100644 (file)
@@ -81,6 +81,7 @@ static char *_keywords[] =
   "banked",
   "at",       //.p.t.20030714 adding support for 'sfr at ADDR' construct
   "_naked",   //.p.t.20030714 adding support for '_naked' functions
+  "critical",
   NULL
 };
 
index 60267bd0c829a4480ba3447c9d5c6b182e3a3f08..d77251244e1899f92edf2c34f373f5c8f814490d 100644 (file)
@@ -35,6 +35,12 @@ static const ASM_MAPPING _asxxxx_gb_mapping[] = {
       "\tpush de\n"
       "\tpush hl"
     },
+    { "popa", 
+      "pop hl\n"
+      "\tpop de\n"
+      "\tpop bc\n"
+      "\tpop af"
+    },
     { "adjustsp", "lda sp,-%d(sp)" },
     { "fileprelude", "" },
     { "profileenter",
@@ -93,7 +99,15 @@ static const ASM_MAPPING _asxxxx_z80_mapping[] = {
                "push af\n"
                "\tpush\tbc\n"
                "\tpush\tde\n"
-               "\tpush\thl"
+               "\tpush\thl\n"
+               "\tpush\tiy"
+    },
+    { "popa",
+               "pop iy\n"
+               "\tpop\thl\n"
+               "\tpop\tde\n"
+               "\tpop\tbc\n"
+               "\tpop\taf"
     },
     { "adjustsp", "lda sp,-%d(sp)" },
     { "profileenter",
@@ -172,6 +186,12 @@ static const ASM_MAPPING _rgbds_gb_mapping[] = {
       "\tpush de\n"
       "\tpush hl"
     },
+    { "popa", 
+      "pop hl\n"
+      "\tpop de\n"
+      "\tpop bc\n"
+      "\tpop af"
+    },
     { "di", "di" },
     { "adjustsp", "add sp,-%d" },
     { "enter", "" },
@@ -257,6 +277,12 @@ static const ASM_MAPPING _isas_gb_mapping[] = {
       "\tpush de\n"
       "\tpush hl"
     },
+    { "popa", 
+      "pop hl\n"
+      "\tpop de\n"
+      "\tpop bc\n"
+      "\tpop af"
+    },
     { "di", "di" },
     { "adjustsp", "add sp,-%d" },
     { "enter", "" },
@@ -370,7 +396,15 @@ static const ASM_MAPPING _z80asm_z80_mapping[] = {
                "push af\n"
                "\tpush\tbc\n"
                "\tpush\tde\n"
-               "\tpush\thl"
+               "\tpush\thl\n"
+               "\tpush\tiy"
+    },
+    { "popa", 
+               "pop\tiy\n"
+               "\tpop\thl\n"
+               "\tpop\tde\n"
+               "\tpop\tbc\n"
+               "\tpop\taf"
     },
     { "adjustsp", "lda sp,(sp%+d)" },
     { "profileenter",