This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

ia64 varargs hazard


Horay for assembler warnings.  We weren't emitting a stop bit between
the prologue and epilogue for an empty function declared with stdargs.
This resulted in the final varargs spill in the same insn group as
the ar.unat restore.  Oops.

At the same time, fully track affected ar.unat bits from spills/fills.
I'd not generated a failing test case, but it was theoretically possible
for varargs spills and normal gr spills to interfere.



r~


        * config/ia64/ia64.c (do_spill): Pass cfa offset to move expander.
        (do_restore): Likewise.
        (gen_movdi_x, gen_fr_spill_x, gen_fr_restore_x): New.
        (ia64_expand_prologue, ia64_expand_epilogue): Use them.
        (rtx_needs_barrier): Track actual bit manipulation for
        ar.unat moves, gr_spill, and gr_restore.
        (emit_insn_group_barriers): Special case gr_spill/gr_restore.
        (process_set): Don't handle varargs spills.
        * config/ia64/ia64.md (gr_spill): Accept cfa offset.  Emit
        .mem.offset here instead of in process_set.
        (gr_restore): Likewise.

Index: ia64.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.c,v
retrieving revision 1.40
diff -c -p -d -r1.40 ia64.c
*** ia64.c	2000/08/08 10:01:20	1.40
--- ia64.c	2000/08/11 23:00:37
*************** static void ia64_compute_frame_size PARA
*** 103,110 ****
  static void setup_spill_pointers PARAMS ((int, rtx, HOST_WIDE_INT));
  static void finish_spill_pointers PARAMS ((void));
  static rtx spill_restore_mem PARAMS ((rtx, HOST_WIDE_INT));
! static void do_spill PARAMS ((rtx (*)(rtx, rtx), rtx, HOST_WIDE_INT, rtx));
! static void do_restore PARAMS ((rtx (*)(rtx, rtx), rtx, HOST_WIDE_INT));
  
  static enum machine_mode hfa_element_mode PARAMS ((tree, int));
  static void fix_range PARAMS ((const char *));
--- 103,110 ----
  static void setup_spill_pointers PARAMS ((int, rtx, HOST_WIDE_INT));
  static void finish_spill_pointers PARAMS ((void));
  static rtx spill_restore_mem PARAMS ((rtx, HOST_WIDE_INT));
! static void do_spill PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT, rtx));
! static void do_restore PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT));
  
  static enum machine_mode hfa_element_mode PARAMS ((tree, int));
  static void fix_range PARAMS ((const char *));
*************** spill_restore_mem (reg, cfa_off)
*** 1281,1294 ****
  
  static void
  do_spill (move_fn, reg, cfa_off, frame_reg)
!      rtx (*move_fn) PARAMS ((rtx, rtx));
       rtx reg, frame_reg;
       HOST_WIDE_INT cfa_off;
  {
    rtx mem, insn;
  
    mem = spill_restore_mem (reg, cfa_off);
!   insn = emit_insn ((*move_fn) (mem, reg));
  
    if (frame_reg)
      {
--- 1281,1294 ----
  
  static void
  do_spill (move_fn, reg, cfa_off, frame_reg)
!      rtx (*move_fn) PARAMS ((rtx, rtx, rtx));
       rtx reg, frame_reg;
       HOST_WIDE_INT cfa_off;
  {
    rtx mem, insn;
  
    mem = spill_restore_mem (reg, cfa_off);
!   insn = emit_insn ((*move_fn) (mem, reg, GEN_INT (cfa_off)));
  
    if (frame_reg)
      {
*************** do_spill (move_fn, reg, cfa_off, frame_r
*** 1324,1336 ****
  
  static void
  do_restore (move_fn, reg, cfa_off)
!      rtx (*move_fn) PARAMS ((rtx, rtx));
       rtx reg;
       HOST_WIDE_INT cfa_off;
  {
!   emit_insn ((*move_fn) (reg, spill_restore_mem (reg, cfa_off)));
  }
  
  
  /* Called after register allocation to add any instructions needed for the
     prologue.  Using a prologue insn is favored compared to putting all of the
--- 1324,1364 ----
  
  static void
  do_restore (move_fn, reg, cfa_off)
!      rtx (*move_fn) PARAMS ((rtx, rtx, rtx));
       rtx reg;
       HOST_WIDE_INT cfa_off;
  {
!   emit_insn ((*move_fn) (reg, spill_restore_mem (reg, cfa_off),
! 			 GEN_INT (cfa_off)));
! }
! 
! /* Wrapper functions that discards the CONST_INT spill offset.  These
!    exist so that we can give gr_spill/gr_fill the offset they need and
!    use a consistant function interface.  */
! 
! static rtx
! gen_movdi_x (dest, src, offset)
!      rtx dest, src;
!      rtx offset ATTRIBUTE_UNUSED;
! {
!   return gen_movdi (dest, src);
  }
  
+ static rtx
+ gen_fr_spill_x (dest, src, offset)
+      rtx dest, src;
+      rtx offset ATTRIBUTE_UNUSED;
+ {
+   return gen_fr_spill (dest, src);
+ }
+ 
+ static rtx
+ gen_fr_restore_x (dest, src, offset)
+      rtx dest, src;
+      rtx offset ATTRIBUTE_UNUSED;
+ {
+   return gen_fr_restore (dest, src);
+ }
  
  /* Called after register allocation to add any instructions needed for the
     prologue.  Using a prologue insn is favored compared to putting all of the
*************** ia64_expand_prologue ()
*** 1532,1542 ****
    for (regno = GR_ARG_FIRST + 7; n_varargs > 0; --n_varargs, --regno)
      {
        reg = gen_rtx_REG (DImode, regno);
! 
!       /* ??? These aren't really "frame related" in the unwind sense,
! 	 but marking them so gives us the chance to emit .mem.offset
! 	 markers so that we don't get assembler WAW warnings.  */
!       do_spill (gen_gr_spill, reg, cfa_off += 8, reg);
      }
  
    /* Locate the bottom of the register save area.  */
--- 1560,1566 ----
    for (regno = GR_ARG_FIRST + 7; n_varargs > 0; --n_varargs, --regno)
      {
        reg = gen_rtx_REG (DImode, regno);
!       do_spill (gen_gr_spill, reg, cfa_off += 8, NULL_RTX);
      }
  
    /* Locate the bottom of the register save area.  */
*************** ia64_expand_prologue ()
*** 1571,1577 ****
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
  	  insn = emit_move_insn (alt_reg, reg);
! 	  do_spill (gen_movdi, alt_reg, cfa_off, reg);
  	  cfa_off -= 8;
  	}
      }
--- 1595,1601 ----
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
  	  insn = emit_move_insn (alt_reg, reg);
! 	  do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
  	  cfa_off -= 8;
  	}
      }
*************** ia64_expand_prologue ()
*** 1581,1587 ****
        && current_frame_info.reg_save_ar_unat == 0)
      {
        reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
!       do_spill (gen_movdi, ar_unat_save_reg, cfa_off, reg);
        cfa_off -= 8;
      }
  
--- 1605,1611 ----
        && current_frame_info.reg_save_ar_unat == 0)
      {
        reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM);
!       do_spill (gen_movdi_x, ar_unat_save_reg, cfa_off, reg);
        cfa_off -= 8;
      }
  
*************** ia64_expand_prologue ()
*** 1592,1598 ****
        && ! current_function_is_leaf)
      {
        reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
!       do_spill (gen_movdi, ar_pfs_save_reg, cfa_off, reg);
        cfa_off -= 8;
      }
  
--- 1616,1622 ----
        && ! current_function_is_leaf)
      {
        reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
!       do_spill (gen_movdi_x, ar_pfs_save_reg, cfa_off, reg);
        cfa_off -= 8;
      }
  
*************** ia64_expand_prologue ()
*** 1615,1621 ****
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
  	  emit_move_insn (alt_reg, reg);
! 	  do_spill (gen_movdi, alt_reg, cfa_off, reg);
  	  cfa_off -= 8;
  	}
      }
--- 1639,1645 ----
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
  	  emit_move_insn (alt_reg, reg);
! 	  do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
  	  cfa_off -= 8;
  	}
      }
*************** ia64_expand_prologue ()
*** 1655,1661 ****
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
  	  emit_move_insn (alt_reg, reg);
! 	  do_spill (gen_movdi, alt_reg, cfa_off, reg);
  	  cfa_off -= 8;
  	}
      }
--- 1679,1685 ----
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
  	  emit_move_insn (alt_reg, reg);
! 	  do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
  	  cfa_off -= 8;
  	}
      }
*************** ia64_expand_prologue ()
*** 1668,1674 ****
  	alt_reg = gen_rtx_REG (DImode, alt_regno);
  	reg = gen_rtx_REG (DImode, regno);
  	emit_move_insn (alt_reg, reg);
! 	do_spill (gen_movdi, alt_reg, cfa_off, reg);
  	cfa_off -= 8;
        }
  
--- 1692,1698 ----
  	alt_reg = gen_rtx_REG (DImode, alt_regno);
  	reg = gen_rtx_REG (DImode, regno);
  	emit_move_insn (alt_reg, reg);
! 	do_spill (gen_movdi_x, alt_reg, cfa_off, reg);
  	cfa_off -= 8;
        }
  
*************** ia64_expand_prologue ()
*** 1679,1685 ****
          if (cfa_off & 15)
  	  abort ();
  	reg = gen_rtx_REG (XFmode, regno);
! 	do_spill (gen_fr_spill, reg, cfa_off, reg);
  	cfa_off -= 16;
        }
  
--- 1703,1709 ----
          if (cfa_off & 15)
  	  abort ();
  	reg = gen_rtx_REG (XFmode, regno);
! 	do_spill (gen_fr_spill_x, reg, cfa_off, reg);
  	cfa_off -= 16;
        }
  
*************** ia64_expand_epilogue ()
*** 1736,1742 ****
  	{
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
! 	  do_restore (gen_movdi, alt_reg, cfa_off);
  	  cfa_off -= 8;
  	}
        reg = gen_rtx_REG (DImode, PR_REG (0));
--- 1760,1766 ----
  	{
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
! 	  do_restore (gen_movdi_x, alt_reg, cfa_off);
  	  cfa_off -= 8;
  	}
        reg = gen_rtx_REG (DImode, PR_REG (0));
*************** ia64_expand_epilogue ()
*** 1757,1763 ****
  	  alt_regno = next_scratch_gr_reg ();
  	  ar_unat_save_reg = gen_rtx_REG (DImode, alt_regno);
  	  current_frame_info.gr_used_mask |= 1 << alt_regno;
! 	  do_restore (gen_movdi, ar_unat_save_reg, cfa_off);
  	  cfa_off -= 8;
  	}
      }
--- 1781,1787 ----
  	  alt_regno = next_scratch_gr_reg ();
  	  ar_unat_save_reg = gen_rtx_REG (DImode, alt_regno);
  	  current_frame_info.gr_used_mask |= 1 << alt_regno;
! 	  do_restore (gen_movdi_x, ar_unat_save_reg, cfa_off);
  	  cfa_off -= 8;
  	}
      }
*************** ia64_expand_epilogue ()
*** 1774,1780 ****
      {
        alt_regno = next_scratch_gr_reg ();
        alt_reg = gen_rtx_REG (DImode, alt_regno);
!       do_restore (gen_movdi, alt_reg, cfa_off);
        cfa_off -= 8;
        reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
        emit_move_insn (reg, alt_reg);
--- 1798,1804 ----
      {
        alt_regno = next_scratch_gr_reg ();
        alt_reg = gen_rtx_REG (DImode, alt_regno);
!       do_restore (gen_movdi_x, alt_reg, cfa_off);
        cfa_off -= 8;
        reg = gen_rtx_REG (DImode, AR_PFS_REGNUM);
        emit_move_insn (reg, alt_reg);
*************** ia64_expand_epilogue ()
*** 1788,1794 ****
  	{
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
! 	  do_restore (gen_movdi, alt_reg, cfa_off);
  	  cfa_off -= 8;
  	}
        reg = gen_rtx_REG (DImode, AR_LC_REGNUM);
--- 1812,1818 ----
  	{
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
! 	  do_restore (gen_movdi_x, alt_reg, cfa_off);
  	  cfa_off -= 8;
  	}
        reg = gen_rtx_REG (DImode, AR_LC_REGNUM);
*************** ia64_expand_epilogue ()
*** 1819,1825 ****
  	{
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
! 	  do_restore (gen_movdi, alt_reg, cfa_off);
  	  cfa_off -= 8;
  	}
        reg = gen_rtx_REG (DImode, BR_REG (0));
--- 1843,1849 ----
  	{
  	  alt_regno = next_scratch_gr_reg ();
  	  alt_reg = gen_rtx_REG (DImode, alt_regno);
! 	  do_restore (gen_movdi_x, alt_reg, cfa_off);
  	  cfa_off -= 8;
  	}
        reg = gen_rtx_REG (DImode, BR_REG (0));
*************** ia64_expand_epilogue ()
*** 1831,1837 ****
        {
  	alt_regno = next_scratch_gr_reg ();
  	alt_reg = gen_rtx_REG (DImode, alt_regno);
! 	do_restore (gen_movdi, alt_reg, cfa_off);
  	cfa_off -= 8;
  	reg = gen_rtx_REG (DImode, regno);
  	emit_move_insn (reg, alt_reg);
--- 1855,1861 ----
        {
  	alt_regno = next_scratch_gr_reg ();
  	alt_reg = gen_rtx_REG (DImode, alt_regno);
! 	do_restore (gen_movdi_x, alt_reg, cfa_off);
  	cfa_off -= 8;
  	reg = gen_rtx_REG (DImode, regno);
  	emit_move_insn (reg, alt_reg);
*************** ia64_expand_epilogue ()
*** 1844,1850 ****
          if (cfa_off & 15)
  	  abort ();
  	reg = gen_rtx_REG (XFmode, regno);
! 	do_restore (gen_fr_restore, reg, cfa_off);
  	cfa_off -= 16;
        }
  
--- 1868,1874 ----
          if (cfa_off & 15)
  	  abort ();
  	reg = gen_rtx_REG (XFmode, regno);
! 	do_restore (gen_fr_restore_x, reg, cfa_off);
  	cfa_off -= 16;
        }
  
*************** ia64_override_options ()
*** 3172,3178 ****
  /* This is used for volatile asms which may require a stop bit immediately
     before and after them.  */
  #define REG_VOLATILE	(FIRST_PSEUDO_REGISTER + 2)
! #define NUM_REGS	(FIRST_PSEUDO_REGISTER + 3)
  
  /* For each register, we keep track of how many times it has been
     written in the current instruction group.  If a register is written
--- 3196,3203 ----
  /* This is used for volatile asms which may require a stop bit immediately
     before and after them.  */
  #define REG_VOLATILE	(FIRST_PSEUDO_REGISTER + 2)
! #define AR_UNAT_BIT_0	(FIRST_PSEUDO_REGISTER + 3)
! #define NUM_REGS	(AR_UNAT_BIT_0 + 64)
  
  /* For each register, we keep track of how many times it has been
     written in the current instruction group.  If a register is written
*************** rtx_needs_barrier (x, flags, pred)
*** 3545,3551 ****
        x = SUBREG_REG (x);
        /* FALLTHRU */
      case REG:
!       need_barrier = rws_access_reg (x, flags, pred);
        break;
  
      case MEM:
--- 3570,3582 ----
        x = SUBREG_REG (x);
        /* FALLTHRU */
      case REG:
!       if (REGNO (x) == AR_UNAT_REGNUM)
! 	{
! 	  for (i = 0; i < 64; ++i)
! 	    need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + i, flags, pred);
! 	}
!       else
! 	need_barrier = rws_access_reg (x, flags, pred);
        break;
  
      case MEM:
*************** rtx_needs_barrier (x, flags, pred)
*** 3601,3611 ****
      case UNSPEC:
        switch (XINT (x, 1))
  	{
- 	  /* ??? For the st8.spill/ld8.fill instructions, we can ignore unat
- 	     dependencies as long as we don't have both a spill and fill in
- 	     the same instruction group.  We need to check for that.  */
  	case 1: /* st8.spill */
  	case 2: /* ld8.fill */
  	case 3: /* stf.spill */
  	case 4: /* ldf.spill */
  	case 8: /* popcnt */
--- 3632,3650 ----
      case UNSPEC:
        switch (XINT (x, 1))
  	{
  	case 1: /* st8.spill */
  	case 2: /* ld8.fill */
+ 	  {
+ 	    HOST_WIDE_INT offset = INTVAL (XVECEXP (x, 0, 1));
+ 	    HOST_WIDE_INT bit = (offset >> 3) & 63;
+ 
+ 	    need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
+ 	    new_flags.is_write = (XINT (x, 1) == 1);
+ 	    need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + bit,
+ 					      new_flags, pred);
+ 	    break;
+ 	  }
+ 	  
  	case 3: /* stf.spill */
  	case 4: /* ldf.spill */
  	case 8: /* popcnt */
*************** emit_insn_group_barriers (insns)
*** 3773,3789 ****
  	    {
  	      rtx pat = PATTERN (insn);
  
! 	      /* We play dependency tricks with the epilogue in order to
! 		 get proper schedules.  Undo this for dv analysis.  */
! 	      if (INSN_CODE (insn) == CODE_FOR_epilogue_deallocate_stack)
! 		pat = XVECEXP (pat, 0, 0);
  
! 	      /* ??? Similarly, the pattern we use for br.cloop
! 		 confuses the code above.  The second element of the
! 		 vector is representative.  */
! 	      else if (INSN_CODE (insn) == CODE_FOR_doloop_end_internal)
! 		pat = XVECEXP (pat, 0, 1);
  
  	      memset (rws_insn, 0, sizeof (rws_insn));
  	      need_barrier |= rtx_needs_barrier (pat, flags, 0);
  
--- 3812,3848 ----
  	    {
  	      rtx pat = PATTERN (insn);
  
! 	      /* Ug.  Hack hacks hacked elsewhere.  */
! 	      switch (INSN_CODE (insn))
! 		{
! 		  /* We play dependency tricks with the epilogue in order
! 		     to get proper schedules.  Undo this for dv analysis.  */
! 		case CODE_FOR_epilogue_deallocate_stack:
! 		  pat = XVECEXP (pat, 0, 0);
! 		  break;
  
! 		  /* The pattern we use for br.cloop confuses the code above.
! 		     The second element of the vector is representative.  */
! 		case CODE_FOR_doloop_end_internal:
! 		  pat = XVECEXP (pat, 0, 1);
! 		  break;
! 
! 		  /* We include ar.unat in the rtl pattern so that sched2
! 		     does not move the ar.unat save/restore after/before
! 		     a gr spill/fill.  However, we special case these
! 		     insns based on their unspec number so as to model
! 		     their precise ar.unat bit operations.  If we pass on
! 		     the use/clobber of the whole ar.unat register we'll
! 		     waste this effort.  */
! 		case CODE_FOR_gr_spill_internal:
! 		case CODE_FOR_gr_restore_internal:
! 		  pat = XVECEXP (pat, 0, 0);
! 		  break;
  
+ 		default:
+ 		  break;
+ 		}
+ 
  	      memset (rws_insn, 0, sizeof (rws_insn));
  	      need_barrier |= rtx_needs_barrier (pat, flags, 0);
  
*************** process_set (asm_out_file, pat)
*** 4235,4254 ****
  	case GR_REG (7):
  	  fprintf (asm_out_file, "\t.save.g 0x%x\n",
  		   1 << (src_regno - GR_REG (4)));
- 	  /* FALLTHRU */
- 
- 	case GR_ARG_FIRST + 0:
- 	case GR_ARG_FIRST + 1:
- 	case GR_ARG_FIRST + 2:
- 	case GR_ARG_FIRST + 3:
- 	case GR_ARG_FIRST + 4:
- 	case GR_ARG_FIRST + 5:
- 	case GR_ARG_FIRST + 6:
- 	case GR_ARG_FIRST + 7:
- 	  /* ??? These aren't really "frame related" in the unwind sense,
- 	     but marking them so gives us the chance to emit .mem.offset
- 	     markers so that we don't get assembler WAW warnings.  */
- 	  fprintf (asm_out_file, "\t.mem.offset %ld, 0\n", off);
  	  return 1;
  
  	case BR_REG (1):
--- 4294,4299 ----
Index: ia64.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.md,v
retrieving revision 1.30
diff -c -p -d -r1.30 ia64.md
*** ia64.md	2000/08/08 10:01:20	1.30
--- ia64.md	2000/08/11 23:00:37
***************
*** 3435,3470 ****
  
  ;; Modifies ar.unat
  (define_expand "gr_spill"
!   [(parallel
!      [(set (match_operand:DI 0 "memory_operand" "=m")
! 	   (unspec:DI [(match_operand:DI 1 "register_operand" "r")] 1))
!       (clobber (match_dup 2))])]
    ""
!   "operands[2] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
  
! (define_insn "*gr_spill_internal"
    [(set (match_operand:DI 0 "memory_operand" "=m")
! 	(unspec:DI [(match_operand:DI 1 "register_operand" "r")] 1))
!    (clobber (match_operand:DI 2 "register_operand" ""))]
    ""
!   "st8.spill %0 = %1%P0"
    [(set_attr "type" "M")])
  
  ;; Reads ar.unat
  (define_expand "gr_restore"
!   [(parallel
!      [(set (match_operand:DI 0 "register_operand" "=r")
! 	   (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] 2))
!       (use (match_dup 2))])]
    ""
!   "operands[2] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
  
! (define_insn "*gr_restore_internal"
    [(set (match_operand:DI 0 "register_operand" "=r")
! 	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")] 2))
!    (use (match_operand:DI 2 "register_operand" ""))]
    ""
!   "ld8.fill %0 = %1%P1"
    [(set_attr "type" "M")])
  
  (define_insn "fr_spill"
--- 3435,3472 ----
  
  ;; Modifies ar.unat
  (define_expand "gr_spill"
!   [(parallel [(set (match_operand:DI 0 "memory_operand" "=m")
! 		   (unspec:DI [(match_operand:DI 1 "register_operand" "r")
! 			       (match_operand:DI 2 "const_int_operand" "")] 1))
! 	      (clobber (match_dup 3))])]
    ""
!   "operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
  
! (define_insn "gr_spill_internal"
    [(set (match_operand:DI 0 "memory_operand" "=m")
! 	(unspec:DI [(match_operand:DI 1 "register_operand" "r")
! 		    (match_operand:DI 2 "const_int_operand" "")] 1))
!    (clobber (match_operand:DI 3 "register_operand" ""))]
    ""
!   ".mem.offset %2, 0\;st8.spill %0 = %1%P0"
    [(set_attr "type" "M")])
  
  ;; Reads ar.unat
  (define_expand "gr_restore"
!   [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
! 		   (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
! 			       (match_operand:DI 2 "const_int_operand" "")] 2))
! 	      (use (match_dup 3))])]
    ""
!   "operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
  
! (define_insn "gr_restore_internal"
    [(set (match_operand:DI 0 "register_operand" "=r")
! 	(unspec:DI [(match_operand:DI 1 "memory_operand" "m")
! 		    (match_operand:DI 2 "const_int_operand" "")] 2))
!    (use (match_operand:DI 3 "register_operand" ""))]
    ""
!   ".mem.offset %2, 0\;ld8.fill %0 = %1%P1"
    [(set_attr "type" "M")])
  
  (define_insn "fr_spill"

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]