Xtensa: fix builtin_return_addr

Bob Wilson bwilson@tensilica.com
Wed Jun 26 21:52:00 GMT 2002


The builtin_return_addr function for Xtensa was previously only
partially implemented because the high bits of the result were
incorrect.  This patch fixes the problem.
-------------- next part --------------
2002-06-26  Bob Wilson  <bob.wilson@acm.org>

	* config/xtensa/xtensa-protos.h (xtensa_return_addr): Declare.
	config/xtensa/xtensa.c (xtensa_return_addr): New function.
	config/xtensa/xtensa.h (RETURN_ADDR_RTX): Use xtensa_return_addr.
	config/xtensa/xtensa.md (fix_return_addr): New pattern.

Index: xtensa-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa-protos.h,v
retrieving revision 1.2
diff -c -r1.2 xtensa-protos.h
*** xtensa-protos.h	22 Mar 2002 22:57:53 -0000	1.2
--- xtensa-protos.h	26 Jun 2002 21:18:32 -0000
***************
*** 86,91 ****
--- 86,92 ----
  extern void xtensa_output_literal
    PARAMS ((FILE *, rtx, enum machine_mode, int labelno));
  extern void xtensa_reorg PARAMS ((rtx));
+ extern rtx xtensa_return_addr PARAMS ((int, rtx));
  extern rtx xtensa_builtin_saveregs PARAMS ((void));
  extern enum reg_class xtensa_preferred_reload_class
    PARAMS ((rtx, enum reg_class));
Index: xtensa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.c,v
retrieving revision 1.15
diff -c -r1.15 xtensa.c
*** xtensa.c	11 Jun 2002 03:50:59 -0000	1.15
--- xtensa.c	26 Jun 2002 21:18:32 -0000
***************
*** 2281,2286 ****
--- 2281,2313 ----
  }
  
  
+ rtx
+ xtensa_return_addr (count, frame)
+      int count;
+      rtx frame;
+ {
+   rtx result, retaddr;
+ 
+   if (count == -1)
+     retaddr = gen_rtx_REG (Pmode, 0);
+   else
+     {
+       rtx addr = plus_constant (frame, -4 * UNITS_PER_WORD);
+       addr = memory_address (Pmode, addr);
+       retaddr = gen_reg_rtx (Pmode);
+       emit_move_insn (retaddr, gen_rtx_MEM (Pmode, addr));
+     }
+ 
+   /* The 2 most-significant bits of the return address on Xtensa hold
+      the register window size.  To get the real return address, these
+      bits must be replaced with the high bits from the current PC.  */
+ 
+   result = gen_reg_rtx (Pmode);
+   emit_insn (gen_fix_return_addr (result, retaddr));
+   return result;
+ }
+ 
+ 
  /* Create the va_list data type.
     This structure is set up by __builtin_saveregs.  The __va_reg
     field points to a stack-allocated region holding the contents of the
Index: xtensa.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.h,v
retrieving revision 1.14
diff -c -r1.14 xtensa.h
*** xtensa.h	18 Jun 2002 21:18:46 -0000	1.14
--- xtensa.h	26 Jun 2002 21:18:32 -0000
***************
*** 1060,1067 ****
     we currently need to ensure that there is a frame pointer when these
     builtin functions are used. */
  
! #define SETUP_FRAME_ADDRESSES() \
!   xtensa_setup_frame_addresses ()
  
  /* A C expression whose value is RTL representing the address in a
     stack frame where the pointer to the caller's frame is stored.
--- 1060,1066 ----
     we currently need to ensure that there is a frame pointer when these
     builtin functions are used. */
  
! #define SETUP_FRAME_ADDRESSES  xtensa_setup_frame_addresses
  
  /* A C expression whose value is RTL representing the address in a
     stack frame where the pointer to the caller's frame is stored.
***************
*** 1085,1106 ****
  
  /* A C expression whose value is RTL representing the value of the
     return address for the frame COUNT steps up from the current
!    frame, after the prologue.  FRAMEADDR is the frame pointer of the
!    COUNT frame, or the frame pointer of the COUNT - 1 frame if
!    'RETURN_ADDR_IN_PREVIOUS_FRAME' is defined.
! 
!    The 2 most-significant bits of the return address on Xtensa hold
!    the register window size.  To get the real return address, these bits
!    must be masked off and replaced with the high bits from the current
!    PC.  Since it is unclear how the __builtin_return_address function
!    is used, the current code does not do this masking and simply returns
!    the raw return address from the a0 register. */
! #define RETURN_ADDR_RTX(count, frame)					\
!   ((count) == -1							\
!    ? gen_rtx_REG (Pmode, 0)						\
!    : gen_rtx_MEM (Pmode, memory_address					\
! 		  (Pmode, plus_constant (frame, -4 * UNITS_PER_WORD))))
! 
  
  /* Addressing modes, and classification of registers for them.  */
  
--- 1084,1091 ----
  
  /* A C expression whose value is RTL representing the value of the
     return address for the frame COUNT steps up from the current
!    frame, after the prologue.  */
! #define RETURN_ADDR_RTX  xtensa_return_addr
  
  /* Addressing modes, and classification of registers for them.  */
  
Index: xtensa.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/xtensa/xtensa.md,v
retrieving revision 1.4
diff -c -r1.4 xtensa.md
*** xtensa.md	22 Mar 2002 22:57:53 -0000	1.4
--- xtensa.md	26 Jun 2002 21:18:32 -0000
***************
*** 34,39 ****
--- 34,40 ----
    (UNSPEC_NSAU		1)
    (UNSPEC_NOP		2)
    (UNSPEC_PLT		3)
+   (UNSPEC_RET_ADDR	4)
    (UNSPECV_SET_FP	1)
  ])
  
***************
*** 1370,1375 ****
--- 1371,1377 ----
     (set_attr "mode"	"SI")
     (set_attr "length"	"6,6")])
  
+ 
  ;;
  ;;  ....................
  ;;
***************
*** 2431,2436 ****
--- 2433,2455 ----
    [(set_attr "type"	"nop")
     (set_attr "mode"	"none")
     (set_attr "length"	"0")])
+ 
+ ;; The fix_return_addr pattern sets the high 2 bits of an address in a
+ ;; register to match the high bits of the current PC.
+ 
+ (define_insn "fix_return_addr"
+   [(set (match_operand:SI 0 "register_operand" "=a")
+ 	(unspec:SI [(match_operand:SI 1 "register_operand" "r")]
+ 		   UNSPEC_RET_ADDR))
+    (clobber (match_scratch:SI 2 "=r"))
+    (clobber (match_scratch:SI 3 "=r"))]
+   ""
+   "mov\\t%2, a0\;call0\\t0f\;.align\\t4\;0:\;mov\\t%3, a0\;mov\\ta0, %2\;\
+ srli\\t%3, %3, 30\;slli\\t%0, %1, 2\;ssai\\t2\;src\\t%0, %3, %0"
+   [(set_attr "type"	"multi")
+    (set_attr "mode"	"SI")
+    (set_attr "length"	"24")])
+ 
  
  ;;
  ;;  ....................


More information about the Gcc-patches mailing list