summaryrefslogtreecommitdiffstats
path: root/gcc/config/xtensa
diff options
context:
space:
mode:
authorbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>2002-06-27 04:33:41 +0000
committerbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>2002-06-27 04:33:41 +0000
commit43326cf7509fd6fff93f61d5c59c4198009b655a (patch)
tree38c67d5efdf712d104945d3513f73941e6148563 /gcc/config/xtensa
parente68f3b9b82bc10b11e13378f28426a13f7975534 (diff)
downloadppe42-gcc-43326cf7509fd6fff93f61d5c59c4198009b655a.tar.gz
ppe42-gcc-43326cf7509fd6fff93f61d5c59c4198009b655a.zip
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@55020 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/xtensa')
-rw-r--r--gcc/config/xtensa/xtensa-protos.h1
-rw-r--r--gcc/config/xtensa/xtensa.c27
-rw-r--r--gcc/config/xtensa/xtensa.h21
-rw-r--r--gcc/config/xtensa/xtensa.md19
4 files changed, 50 insertions, 18 deletions
diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h
index 76cf73cb338..bb640bb4384 100644
--- a/gcc/config/xtensa/xtensa-protos.h
+++ b/gcc/config/xtensa/xtensa-protos.h
@@ -86,6 +86,7 @@ extern void print_operand_address PARAMS ((FILE *, rtx));
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));
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index dd9ad7d8005..bf669da2503 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -2281,6 +2281,33 @@ xtensa_function_epilogue (file, size)
}
+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
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index e98c2c673f8..22fcb79a14d 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -1060,8 +1060,7 @@ typedef struct xtensa_args {
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.
@@ -1085,22 +1084,8 @@ typedef struct xtensa_args {
/* 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. */
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 771edd556e3..cf07ffc25b8 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -34,6 +34,7 @@
(UNSPEC_NSAU 1)
(UNSPEC_NOP 2)
(UNSPEC_PLT 3)
+ (UNSPEC_RET_ADDR 4)
(UNSPECV_SET_FP 1)
])
@@ -1370,6 +1371,7 @@
(set_attr "mode" "SI")
(set_attr "length" "6,6")])
+
;;
;; ....................
;;
@@ -2432,6 +2434,23 @@
(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")])
+
+
;;
;; ....................
;;
OpenPOWER on IntegriCloud