aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeffrey A Law <law@cygnus.com>1997-11-03 02:26:49 +0000
committerJeff Law <law@gcc.gnu.org>1997-11-02 19:26:49 -0700
commit566368181653e0f7240d0240b9567cc5950f8720 (patch)
treea9c7da63cf4771fcd2d7c4e2c3a91803695e6bee /gcc
parentb9ddcfac31ed5b5b495931e5a8660bc63166dc09 (diff)
downloadgcc-566368181653e0f7240d0240b9567cc5950f8720.zip
gcc-566368181653e0f7240d0240b9567cc5950f8720.tar.gz
gcc-566368181653e0f7240d0240b9567cc5950f8720.tar.bz2
* arm.c (output_move_double): Allocate 3 entries in otherops array.
From-SVN: r16281
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/config/arm/arm.c183
2 files changed, 124 insertions, 63 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 265182f..28bc348 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+Sun Nov 2 19:27:21 1997 Jeffrey A Law (law@cygnus.com)
+
+ * arm.c (output_move_double): Allocate 3 entries in otherops array.
+
Sat Nov 1 21:43:00 1997 Mike Stump (mrs@wrs.com)
* except.c (expand_ex_region_start_for_decl): Emit EH_REGION_BEG
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index fe263ba..ac43337 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -21,10 +21,10 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#include "config.h"
#include <stdio.h>
#include <string.h>
#include "assert.h"
-#include "config.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -376,7 +376,8 @@ use_return_insn ()
if (!reload_completed ||current_function_pretend_args_size
|| current_function_anonymous_args
- || (get_frame_size () && !(TARGET_APCS || frame_pointer_needed)))
+ || ((get_frame_size () + current_function_outgoing_args_size != 0)
+ && !(TARGET_APCS || frame_pointer_needed)))
return 0;
/* Can't be done if interworking with Thumb, and any registers have been
@@ -407,6 +408,13 @@ const_ok_for_arm (i)
{
unsigned HOST_WIDE_INT mask = ~0xFF;
+ /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must
+ be all zero, or all one. */
+ if ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0
+ && ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff)
+ != (((HOST_WIDE_INT) -1) & ~(unsigned HOST_WIDE_INT) 0xffffffff)))
+ return FALSE;
+
/* Fast return for 0 and powers of 2 */
if ((i & (i - 1)) == 0)
return TRUE;
@@ -1501,6 +1509,17 @@ arm_rtx_costs (x, code, outer_code)
+ (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
+ (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4));
+ case TRUNCATE:
+ if (arm_fast_multiply && mode == SImode
+ && GET_CODE (XEXP (x, 0)) == LSHIFTRT
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+ && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
+ == GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)))
+ && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
+ || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))
+ return 8;
+ return 99;
+
case NEG:
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6);
@@ -2352,6 +2371,10 @@ load_multiple_sequence (operands, nops, regs, base, load_offset)
rtx reg;
rtx offset;
+ /* Convert a subreg of a mem into the mem itself. */
+ if (GET_CODE (operands[nops + i]) == SUBREG)
+ operands[nops + i] = alter_subreg(operands[nops + i]);
+
if (GET_CODE (operands[nops + i]) != MEM)
abort ();
@@ -2551,6 +2574,10 @@ store_multiple_sequence (operands, nops, regs, base, load_offset)
rtx reg;
rtx offset;
+ /* Convert a subreg of a mem into the mem itself. */
+ if (GET_CODE (operands[nops + i]) == SUBREG)
+ operands[nops + i] = alter_subreg(operands[nops + i]);
+
if (GET_CODE (operands[nops + i]) != MEM)
abort ();
@@ -2761,16 +2788,20 @@ arm_naked_function_p (func)
/* Routines for use in generating RTL */
rtx
-arm_gen_load_multiple (base_regno, count, from, up, write_back)
+arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
+ in_struct_p)
int base_regno;
int count;
rtx from;
int up;
int write_back;
+ int unchanging_p;
+ int in_struct_p;
{
int i = 0, j;
rtx result;
int sign = up ? 1 : -1;
+ rtx mem;
result = gen_rtx (PARALLEL, VOIDmode,
rtvec_alloc (count + (write_back ? 2 : 0)));
@@ -2785,10 +2816,13 @@ arm_gen_load_multiple (base_regno, count, from, up, write_back)
for (j = 0; i < count; i++, j++)
{
- XVECEXP (result, 0, i)
- = gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, base_regno + j),
- gen_rtx (MEM, SImode,
- plus_constant (from, j * 4 * sign)));
+ mem = gen_rtx (MEM, SImode, plus_constant (from, j * 4 * sign));
+ RTX_UNCHANGING_P (mem) = unchanging_p;
+ MEM_IN_STRUCT_P (mem) = in_struct_p;
+
+ XVECEXP (result, 0, i) = gen_rtx (SET, VOIDmode,
+ gen_rtx (REG, SImode, base_regno + j),
+ mem);
}
if (write_back)
@@ -2798,16 +2832,20 @@ arm_gen_load_multiple (base_regno, count, from, up, write_back)
}
rtx
-arm_gen_store_multiple (base_regno, count, to, up, write_back)
+arm_gen_store_multiple (base_regno, count, to, up, write_back, unchanging_p,
+ in_struct_p)
int base_regno;
int count;
rtx to;
int up;
int write_back;
+ int unchanging_p;
+ int in_struct_p;
{
int i = 0, j;
rtx result;
int sign = up ? 1 : -1;
+ rtx mem;
result = gen_rtx (PARALLEL, VOIDmode,
rtvec_alloc (count + (write_back ? 2 : 0)));
@@ -2822,10 +2860,12 @@ arm_gen_store_multiple (base_regno, count, to, up, write_back)
for (j = 0; i < count; i++, j++)
{
- XVECEXP (result, 0, i)
- = gen_rtx (SET, VOIDmode,
- gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign)),
- gen_rtx (REG, SImode, base_regno + j));
+ mem = gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign));
+ RTX_UNCHANGING_P (mem) = unchanging_p;
+ MEM_IN_STRUCT_P (mem) = in_struct_p;
+
+ XVECEXP (result, 0, i) = gen_rtx (SET, VOIDmode, mem,
+ gen_rtx (REG, SImode, base_regno + j));
}
if (write_back)
@@ -2843,6 +2883,8 @@ arm_gen_movstrqi (operands)
rtx src, dst;
rtx st_src, st_dst, end_src, end_dst, fin_src, fin_dst;
rtx part_bytes_reg = NULL;
+ rtx mem;
+ int dst_unchanging_p, dst_in_struct_p, src_unchanging_p, src_in_struct_p;
extern int optimize;
if (GET_CODE (operands[2]) != CONST_INT
@@ -2853,6 +2895,12 @@ arm_gen_movstrqi (operands)
st_dst = XEXP (operands[0], 0);
st_src = XEXP (operands[1], 0);
+
+ dst_unchanging_p = RTX_UNCHANGING_P (operands[0]);
+ dst_in_struct_p = MEM_IN_STRUCT_P (operands[0]);
+ src_unchanging_p = RTX_UNCHANGING_P (operands[1]);
+ src_in_struct_p = MEM_IN_STRUCT_P (operands[1]);
+
fin_dst = dst = copy_to_mode_reg (SImode, st_dst);
fin_src = src = copy_to_mode_reg (SImode, st_src);
@@ -2866,24 +2914,32 @@ arm_gen_movstrqi (operands)
for (i = 0; in_words_to_go >= 2; i+=4)
{
if (in_words_to_go > 4)
- emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE));
+ emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
+ src_unchanging_p, src_in_struct_p));
else
emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
- FALSE));
+ FALSE, src_unchanging_p,
+ src_in_struct_p));
if (out_words_to_go)
{
if (out_words_to_go > 4)
- emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE));
+ emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
+ dst_unchanging_p,
+ dst_in_struct_p));
else if (out_words_to_go != 1)
emit_insn (arm_gen_store_multiple (0, out_words_to_go,
dst, TRUE,
(last_bytes == 0
- ? FALSE : TRUE)));
+ ? FALSE : TRUE),
+ dst_unchanging_p,
+ dst_in_struct_p));
else
{
- emit_move_insn (gen_rtx (MEM, SImode, dst),
- gen_rtx (REG, SImode, 0));
+ mem = gen_rtx (MEM, SImode, dst);
+ RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ emit_move_insn (mem, gen_rtx (REG, SImode, 0));
if (last_bytes != 0)
emit_insn (gen_addsi3 (dst, dst, GEN_INT (4)));
}
@@ -2898,9 +2954,16 @@ arm_gen_movstrqi (operands)
{
rtx sreg;
- emit_move_insn (sreg = gen_reg_rtx (SImode), gen_rtx (MEM, SImode, src));
+ mem = gen_rtx (MEM, SImode, src);
+ RTX_UNCHANGING_P (mem) = src_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = src_in_struct_p;
+ emit_move_insn (sreg = gen_reg_rtx (SImode), mem);
emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
- emit_move_insn (gen_rtx (MEM, SImode, dst), sreg);
+
+ mem = gen_rtx (MEM, SImode, dst);
+ RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ emit_move_insn (mem, sreg);
emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
in_words_to_go--;
@@ -2913,7 +2976,10 @@ arm_gen_movstrqi (operands)
if (in_words_to_go < 0)
abort ();
- part_bytes_reg = copy_to_mode_reg (SImode, gen_rtx (MEM, SImode, src));
+ mem = gen_rtx (MEM, SImode, src);
+ RTX_UNCHANGING_P (mem) = src_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = src_in_struct_p;
+ part_bytes_reg = copy_to_mode_reg (SImode, mem);
}
if (BYTES_BIG_ENDIAN && last_bytes)
@@ -2930,9 +2996,10 @@ arm_gen_movstrqi (operands)
while (last_bytes)
{
- emit_move_insn (gen_rtx (MEM, QImode,
- plus_constant (dst, last_bytes - 1)),
- gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
+ mem = gen_rtx (MEM, QImode, plus_constant (dst, last_bytes - 1));
+ RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ emit_move_insn (mem, gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
if (--last_bytes)
{
tmp = gen_reg_rtx (SImode);
@@ -2949,8 +3016,10 @@ arm_gen_movstrqi (operands)
if (part_bytes_reg == NULL)
abort ();
- emit_move_insn (gen_rtx (MEM, QImode, dst),
- gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
+ mem = gen_rtx (MEM, QImode, dst);
+ RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ emit_move_insn (mem, gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
if (--last_bytes)
{
rtx tmp = gen_reg_rtx (SImode);
@@ -3913,7 +3982,7 @@ output_move_double (operands)
{
enum rtx_code code0 = GET_CODE (operands[0]);
enum rtx_code code1 = GET_CODE (operands[1]);
- rtx otherops[2];
+ rtx otherops[3];
if (code0 == REG)
{
@@ -3964,7 +4033,21 @@ output_move_double (operands)
}
else if (code1 == CONST_INT)
{
- /* sign extend the intval into the high-order word */
+#if HOST_BITS_PER_WIDE_INT > 32
+ /* If HOST_WIDE_INT is more than 32 bits, the intval tells us
+ what the upper word is. */
+ if (WORDS_BIG_ENDIAN)
+ {
+ otherops[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
+ operands[1] = GEN_INT (INTVAL (operands[1]) >> 32);
+ }
+ else
+ {
+ otherops[1] = GEN_INT (INTVAL (operands[1]) >> 32);
+ operands[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
+ }
+#else
+ /* Sign extend the intval into the high-order word */
if (WORDS_BIG_ENDIAN)
{
otherops[1] = operands[1];
@@ -3973,6 +4056,7 @@ output_move_double (operands)
}
else
otherops[1] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx;
+#endif
output_mov_immediate (otherops);
output_mov_immediate (operands);
}
@@ -4762,10 +4846,9 @@ output_func_epilogue (f, frame_size)
if (use_return_insn() && return_used_this_function)
{
- if (frame_size && !(frame_pointer_needed || TARGET_APCS))
- {
- abort ();
- }
+ if ((frame_size + current_function_outgoing_args_size) != 0
+ && !(frame_pointer_needed || TARGET_APCS))
+ abort ();
goto epilogue_done;
}
@@ -4853,10 +4936,11 @@ output_func_epilogue (f, frame_size)
else
{
/* Restore stack pointer if necessary. */
- if (frame_size)
+ if (frame_size + current_function_outgoing_args_size != 0)
{
operands[0] = operands[1] = stack_pointer_rtx;
- operands[2] = gen_rtx (CONST_INT, VOIDmode, frame_size);
+ operands[2] = GEN_INT (frame_size
+ + current_function_outgoing_args_size);
output_add_immediate (operands);
}
@@ -5028,7 +5112,8 @@ void
arm_expand_prologue ()
{
int reg;
- rtx amount = GEN_INT (- get_frame_size ());
+ rtx amount = GEN_INT (-(get_frame_size ()
+ + current_function_outgoing_args_size));
rtx push_insn;
int num_regs;
int live_regs_mask = 0;
@@ -5295,34 +5380,6 @@ arm_print_operand (stream, x, code)
}
}
-/* Output a label definition. */
-
-void
-arm_asm_output_label (stream, name)
- FILE *stream;
- char *name;
-{
- ARM_OUTPUT_LABEL (stream, name);
-}
-
-/* Output code resembling an .lcomm directive. /bin/as doesn't have this
- directive hence this hack, which works by reserving some `.space' in the
- bss segment directly.
-
- XXX This is a severe hack, which is guaranteed NOT to work since it doesn't
- define STATIC COMMON space but merely STATIC BSS space. */
-
-void
-output_lcomm_directive (stream, name, size, align)
- FILE *stream;
- char *name;
- int size, align;
-{
- bss_section ();
- ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
- ARM_OUTPUT_LABEL (stream, name);
- fprintf (stream, "\t.space\t%d\n", size);
-}
/* A finite state machine takes care of noticing whether or not instructions
can be conditionally executed, and thus decrease execution time and code