summaryrefslogtreecommitdiff
path: root/gcc/config/xtensa
diff options
context:
space:
mode:
authorbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>2004-01-27 20:24:59 +0000
committerbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>2004-01-27 20:24:59 +0000
commit2aac53ce24f34bc47c49ae2ad7bb4b8726aeaf69 (patch)
tree9036f0138122ff2a661af2ca521b93759da00ac7 /gcc/config/xtensa
parent3f18719cda960d9d45c9343acb33e7d71ec8d689 (diff)
downloadgcc-2aac53ce24f34bc47c49ae2ad7bb4b8726aeaf69.tar.gz
* config/xtensa/xtensa.c (xtensa_copy_incoming_a7): Remove SUBREG
on CQImode and CHImode incoming arguments in register a7. (function_arg): Wrap BLKmode argument in register a7 in a PARALLEL. * config/xtensa/xtensa.h (BLOCK_REG_PADDING): Define. * config/xtensa/xtensa.md (movdi, movdf): Only call force_reg or xtensa_copy_incoming_a7 before reload. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@76742 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/xtensa')
-rw-r--r--gcc/config/xtensa/xtensa.c36
-rw-r--r--gcc/config/xtensa/xtensa.h6
-rw-r--r--gcc/config/xtensa/xtensa.md28
3 files changed, 53 insertions, 17 deletions
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index d5087285766..7e7b03acadd 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -1327,7 +1327,27 @@ xtensa_copy_incoming_a7 (rtx *operands, enum machine_mode mode)
if (a7_overlap_mentioned_p (operands[1])
&& !cfun->machine->incoming_a7_copied)
{
- rtx mov;
+ rtx mov, src;
+
+ /* Despite defining SPLIT_COMPLEX_ARGS, complex function
+ arguments may still appear if they are wrapped in a struct.
+ For CQImode and CHImode arguments, this results in a move
+ with a source operand of the form: "(subreg:SI (reg:CHI a7)
+ 0)". The subreg is later removed by the reload pass,
+ resulting in the RTL for a7 being regenerated using
+ hard_frame_pointer_rtx, and making it impossible for us to
+ distinguish the function argument. Detect this here when
+ generating the RTL and remove the subreg immediately so that
+ reload won't mess it up. */
+ src = operands[1];
+ if (GET_CODE (src) == SUBREG
+ && GET_CODE (SUBREG_REG (src)) == REG
+ && REGNO (SUBREG_REG (src)) == A7_REG
+ && SUBREG_BYTE (src) == 0
+ && (GET_MODE (SUBREG_REG (src)) == CHImode
+ || GET_MODE (SUBREG_REG (src)) == CQImode))
+ operands[1] = gen_raw_REG (mode, A7_REG);
+
switch (mode)
{
case DFmode:
@@ -1773,11 +1793,15 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
rtx that is not equal to hard_frame_pointer_rtx. For multi-word
modes for which we don't define move patterns, we can't control
the expansion unless we explicitly list the individual registers
- in a PARALLEL. */
-
- if (mode != DImode && mode != DFmode
- && regno < A7_REG
- && regno + words > A7_REG)
+ in a PARALLEL. Likewise, a single-word BLKmode argument passed
+ in a7 must be wrapped in a PARALLEL to avoid code that takes the
+ register number and builds a new REG. This is extremely fragile
+ but seems to be the best solution for now. */
+
+ if ((mode != DImode && mode != DFmode
+ && regno < A7_REG
+ && regno + words > A7_REG)
+ || (mode == BLKmode && regno == A7_REG))
{
rtx result;
int n;
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index f650bcd7ad9..677a5268285 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -799,6 +799,12 @@ typedef struct xtensa_args {
/* Pass complex arguments independently. */
#define SPLIT_COMPLEX_ARGS 1
+/* Because Xtensa's function_arg() wraps BLKmode arguments passed in
+ a7 inside a PARALLEL, BLOCK_REG_PADDING needs to be defined
+ to get emit_group_store to do the right thing. */
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+ FUNCTION_ARG_PADDING (MODE, TYPE)
+
/* Profiling Xtensa code is typically done with the built-in profiling
feature of Tensilica's instruction set simulator, which does not
require any compiler support. Profiling code on a real (i.e.,
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 01ec40d63a7..d0c4474cb60 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1,5 +1,5 @@
;; GCC machine description for Tensilica's Xtensa architecture.
-;; Copyright (C) 2001 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
;; Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
;; This file is part of GCC.
@@ -803,12 +803,15 @@
if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
operands[1] = force_const_mem (DImode, operands[1]);
- if (!register_operand (operands[0], DImode)
- && !register_operand (operands[1], DImode))
- operands[1] = force_reg (DImode, operands[1]);
+ if (!(reload_in_progress | reload_completed))
+ {
+ if (!register_operand (operands[0], DImode)
+ && !register_operand (operands[1], DImode))
+ operands[1] = force_reg (DImode, operands[1]);
- if (xtensa_copy_incoming_a7 (operands, DImode))
- DONE;
+ if (xtensa_copy_incoming_a7 (operands, DImode))
+ DONE;
+ }
})
(define_insn_and_split "movdi_internal"
@@ -1012,12 +1015,15 @@
if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
operands[1] = force_const_mem (DFmode, operands[1]);
- if (!register_operand (operands[0], DFmode)
- && !register_operand (operands[1], DFmode))
- operands[1] = force_reg (DFmode, operands[1]);
+ if (!(reload_in_progress | reload_completed))
+ {
+ if (!register_operand (operands[0], DFmode)
+ && !register_operand (operands[1], DFmode))
+ operands[1] = force_reg (DFmode, operands[1]);
- if (xtensa_copy_incoming_a7 (operands, DFmode))
- DONE;
+ if (xtensa_copy_incoming_a7 (operands, DFmode))
+ DONE;
+ }
})
(define_insn_and_split "movdf_internal"