Commit 56636818 by Jeffrey A Law Committed by Jeff Law

* arm.c (output_move_double): Allocate 3 entries in otherops array.

From-SVN: r16281
parent b9ddcfac
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
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment