+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.
+
2002-06-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* mips.c (coprocessor_operand, coprocessor2_operand,
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));
}
+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
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 ()
+#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.
/* 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))))
-
+ frame, after the prologue. */
+#define RETURN_ADDR_RTX xtensa_return_addr
/* Addressing modes, and classification of registers for them. */
(UNSPEC_NSAU 1)
(UNSPEC_NOP 2)
(UNSPEC_PLT 3)
+ (UNSPEC_RET_ADDR 4)
(UNSPECV_SET_FP 1)
])
(set_attr "mode" "SI")
(set_attr "length" "6,6")])
+
;;
;; ....................
;;
(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")])
+
+
;;
;; ....................
;;