This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Xtensa: fix builtin_return_addr
- From: Bob Wilson <bwilson at tensilica dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 26 Jun 2002 21:44:16 -0700
- Subject: Xtensa: fix builtin_return_addr
- Organization: Tensilica, Inc.
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.
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")])
+
;;
;; ....................