]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Patch to make nested functions and non-local gotos work.
authorJim Wilson <wilson@cygnus.com>
Wed, 7 Apr 1999 23:03:01 +0000 (23:03 +0000)
committerJim Wilson <wilson@gcc.gnu.org>
Wed, 7 Apr 1999 23:03:01 +0000 (16:03 -0700)
* i960/i960.c (i960_function_prologue): Don't save static chain
pointer.
* i960/i960.h (STACK_CHAIN_REGNUM): Change from r3 to g12.
(TRAMPOLINE_TEMPLATE): Likewise.
(FRAME_POINTER_REQUIRED): Check current_function_has_nonlocal_goto.
* i960/i960.md (nonlocal_goto): Rewrite.

From-SVN: r26282

gcc/ChangeLog
gcc/config/i960/i960.c
gcc/config/i960/i960.h
gcc/config/i960/i960.md

index 8fc8a328a35329c530ba4b92dc0d8980ab55341e..d7c4dba6b4e2ee7df6dd0cb55642cf891194e3d5 100644 (file)
@@ -1,3 +1,12 @@
+Wed Apr  7 22:40:19 1999  Jim Wilson  <wilson@cygnus.com>
+
+       * i960/i960.c (i960_function_prologue): Don't save static chain
+       pointer.
+       * i960/i960.h (STACK_CHAIN_REGNUM): Change from r3 to g12.
+       (TRAMPOLINE_TEMPLATE): Likewise.
+       (FRAME_POINTER_REQUIRED): Check current_function_has_nonlocal_goto.
+       * i960/i960.md (nonlocal_goto): Rewrite.
+       
 Tue Apr  6 17:49:49 1999  Philip Blundell  <pb@nexus.co.uk>
 
        * config/arm/lib1funcs.asm: Test for __ELF__ not __elf__.
index 3b79d644bdc47de44e3c770ae5a0b550703f8be4..535d05e80d17eca634e62d278dbbe4a233e97c1f 100644 (file)
@@ -1349,7 +1349,9 @@ i960_function_prologue (file, size)
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     if (regs_ever_live[i]
-       && ((! call_used_regs[i]) || (i > 7 && i < 12)))
+       && ((! call_used_regs[i]) || (i > 7 && i < 12))
+       /* No need to save the static chain pointer.  */
+       && ! (i == STATIC_CHAIN_REGNUM && current_function_needs_context))
       {
        regs[i] = -1;
         /* Count global registers that need saving.  */
index 36aa6d9757b1b8cfc5dae8b2cb9aab64288f4cf8..fdf419903ccbfbfdc40af33bb5b7c3df789cc936 100644 (file)
@@ -528,7 +528,7 @@ extern int target_flags;
        g0..g3 are used for return values,
        g0..g7 may always be used for parameters,
        g8..g11 may be used for parameters, but are preserved if they aren't,
-       g12 is always preserved, but otherwise unused,
+       g12 is the static chain if needed, otherwise is preserved
        g13 is the struct return ptr if used, or temp, but may be trashed,
        g14 is the leaf return ptr or the arg block ptr otherwise zero,
                must be reset to zero before returning if it was used,
@@ -606,7 +606,12 @@ extern int hard_regno_mode_ok ();
 /* ??? It isn't clear to me why this is here.  Perhaps because of a bug (since
    fixed) in the definition of INITIAL_FRAME_POINTER_OFFSET which would have
    caused this to fail.  */
-#define FRAME_POINTER_REQUIRED (! leaf_function_p ())
+/* ??? Must check current_function_has_nonlocal_goto, otherwise frame pointer
+   elimination messes up nonlocal goto sequences.  I think this works for other
+   targets because they use indirect jumps for the return which disables fp
+   elimination.  */
+#define FRAME_POINTER_REQUIRED \
+  (! leaf_function_p () || current_function_has_nonlocal_goto)
 
 /* C statement to store the difference between the frame pointer
    and the stack pointer values immediately after the function prologue.
@@ -622,8 +627,9 @@ extern int hard_regno_mode_ok ();
 #define ARG_POINTER_REGNUM 14
 
 /* Register in which static-chain is passed to a function.
-   On i960, we use r3.  */
-#define STATIC_CHAIN_REGNUM 19
+   On i960, we use g12.  We can't use any local register, because we need
+   a register that can be set before a call or before a jump.  */
+#define STATIC_CHAIN_REGNUM 12
  
 /* Functions which return large structures get the address
    to place the wanted value at in g13.  */
@@ -1543,14 +1549,14 @@ extern struct rtx_def *gen_compare_reg ();
 
 /* On the i960, the trampoline contains three instructions:
      ldconst _function, r4
-     ldconst static addr, r3
+     ldconst static addr, g12
      jump (r4)  */
 
 #define TRAMPOLINE_TEMPLATE(FILE)                                      \
 {                                                                      \
   ASM_OUTPUT_INT (FILE, GEN_INT (0x8C203000)); \
   ASM_OUTPUT_INT (FILE, GEN_INT (0x00000000)); \
-  ASM_OUTPUT_INT (FILE, GEN_INT (0x8C183000)); \
+  ASM_OUTPUT_INT (FILE, GEN_INT (0x8CE03000)); \
   ASM_OUTPUT_INT (FILE, GEN_INT (0x00000000)); \
   ASM_OUTPUT_INT (FILE, GEN_INT (0x84212000)); \
 }
index 53157e09c2fff02e184248b9f5c428dbc413ae41..0574c57680b61a65e002eb716c7d8d896ea7d2b2 100644 (file)
   ""
   "
 {
-  rtx fp = operands[1];
-  rtx new_pc = operands[3];
+  rtx chain = operands[0];
+  rtx handler = operands[1];
   rtx stack = operands[2];
-  rtx val = operands[0];
-
-  /* This code isn't sufficient to make nonlocal_gotos for nested
-     functions to work fully.  Here we assume that the passed frame
-     pointer is a real hard frame pointer, not a
-     virtual_stack_vars_rtx type of frame.  */
+  rtx label = operands[3];
 
   /* We must restore the stack pointer, frame pointer, previous frame
      pointer and the return instruction pointer.  Since the ret
      instruction does all this for us with one instruction, we arrange
      everything so that ret will do everything we need done.  */
 
-  if (GET_CODE (fp) != REG)
-    fp = force_reg (Pmode, fp);
-  if (GET_CODE (val) != REG)
-    val = force_reg (Pmode, val);
-  if (GET_CODE (new_pc) != REG)
-    new_pc = force_reg (Pmode, new_pc);
-
-
   /* First, we must flush the register windows, so that we can modify
      the saved local registers on the stack directly and because we
      are going to change the previous frame pointer.  */
 
   emit_insn (gen_flush_register_windows ());
 
+  /* Load the static chain value for the containing fn into fp.  This is needed
+     because STACK refers to fp.  */
+  emit_move_insn (hard_frame_pointer_rtx, chain);
+
+  /* Now move the adjusted value into the pfp register for the following return
+     instruction.  */
+  emit_move_insn (gen_rtx (REG, SImode, 16),
+                 plus_constant (hard_frame_pointer_rtx, -64));
+
   /* Next, we put the address that we want to transfer to, into the
-     saved $rip value on the stack.  Once we ret below, that value
+     saved $rip value in the frame.  Once we ret below, that value
      will be loaded into the pc (IP).  */
 
   emit_move_insn (gen_rtx (MEM, SImode,
-                          plus_constant (fp, 8)),
-                 new_pc);
-
-#if 0
-  /* Next, we put the value into the static chain register's save
-     area on the stack.  After the ret below, this will be loaded into
-     r3 (the static chain).  */
-     
-  emit_move_insn (gen_rtx (MEM, SImode,
-                          plus_constant (fp, 12)),
-                 val);
-#endif
+                          plus_constant (hard_frame_pointer_rtx, -56)),
+                 replace_rtx (copy_rtx (handler), virtual_stack_vars_rtx,
+                              hard_frame_pointer_rtx));
 
-  /* We now load pfp (the previous frame pointer) with the value that
-     we want fp to be.  */
-
-  emit_move_insn (gen_rtx (REG, SImode, 16), fp);
+  /* Next, we put stack into the saved $sp value in the frame.  */
+  emit_move_insn (gen_rtx (MEM, SImode,
+                          plus_constant (hard_frame_pointer_rtx, -60)),
+                 replace_rtx (copy_rtx (stack), virtual_stack_vars_rtx,
+                              hard_frame_pointer_rtx));
 
   /* And finally, we can now just ret to get all the values saved
      above into all the right registers, and also, all the local