diff options
author | bwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-01-27 20:24:59 +0000 |
---|---|---|
committer | bwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-01-27 20:24:59 +0000 |
commit | 2aac53ce24f34bc47c49ae2ad7bb4b8726aeaf69 (patch) | |
tree | 9036f0138122ff2a661af2ca521b93759da00ac7 /gcc/config/xtensa | |
parent | 3f18719cda960d9d45c9343acb33e7d71ec8d689 (diff) | |
download | gcc-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.c | 36 | ||||
-rw-r--r-- | gcc/config/xtensa/xtensa.h | 6 | ||||
-rw-r--r-- | gcc/config/xtensa/xtensa.md | 28 |
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" |