diff options
author | Jeffrey A Law <law@cygnus.com> | 1997-11-03 02:26:49 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1997-11-02 19:26:49 -0700 |
commit | 566368181653e0f7240d0240b9567cc5950f8720 (patch) | |
tree | a9c7da63cf4771fcd2d7c4e2c3a91803695e6bee /gcc | |
parent | b9ddcfac31ed5b5b495931e5a8660bc63166dc09 (diff) | |
download | gcc-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/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 183 |
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 |