OSDN Git Service

Patch to make nested functions and non-local gotos work.
authorwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Apr 1999 23:03:01 +0000 (23:03 +0000)
committerwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 7 Apr 1999 23:03:01 +0000 (23:03 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@26282 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 8fc8a32..d7c4dba 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 3b79d64..535d05e 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 36aa6d9..fdf4199 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 53157e0..0574c57 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