From f9cc092ab43c9ff54821bb04fe704d817b7e613a Mon Sep 17 00:00:00 2001 From: Richard Earnshaw Date: Mon, 12 Apr 1999 09:43:37 +0000 Subject: [PATCH] arm.h (target_fp_name, [...]): Const-ify. * arm.h (target_fp_name, structure_size_string, arm_cpu_select): Const-ify. * arm.c (target_fp_name, structure_size_string): Const-ify. * arm.md (reload_inhi, reload_outhi): Make the scratch DImode. * arm.c (arm_reload_in_hi): Handle cases when the input is still a pseudo, make use of scratch registers for reloading the address as appropriate. (arm_reload_outhi): Similarly for when the output is still a pseudo. * riscix.h (SUBTARGET_SWITCHES): Document. From-SVN: r26368 --- gcc/ChangeLog | 14 +++ gcc/config/arm/arm.c | 257 ++++++++++++++++++++++++++++++++++++---- gcc/config/arm/arm.h | 10 +- gcc/config/arm/arm.md | 8 +- gcc/config/arm/riscix.h | 8 +- 5 files changed, 264 insertions(+), 33 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6d992cf9153d..8f086b63474a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +Mon Apr 12 09:30:03 1999 Richard Earnshaw (rearnsha@arm.com) + + * arm.h (target_fp_name, structure_size_string, arm_cpu_select): + Const-ify. + * arm.c (target_fp_name, structure_size_string): Const-ify. + + * arm.md (reload_inhi, reload_outhi): Make the scratch DImode. + * arm.c (arm_reload_in_hi): Handle cases when the input is still + a pseudo, make use of scratch registers for reloading the address + as appropriate. + (arm_reload_outhi): Similarly for when the output is still a pseudo. + + * riscix.h (SUBTARGET_SWITCHES): Document. + 1999-04-12 Bruce Korb * fixincludes: diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index d84efe7ce1cb..dc33088a073f 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -84,10 +84,10 @@ enum floating_point_type arm_fpu_arch; enum prog_mode_type arm_prgmode; /* Set by the -mfp=... option */ -char * target_fp_name = NULL; +const char * target_fp_name = NULL; /* Used to parse -mstructure_size_boundary command line option. */ -char * structure_size_string = NULL; +const char * structure_size_string = NULL; int arm_structure_size_boundary = 32; /* Used to be 8 */ /* Bit values used to identify processor capabilities. */ @@ -3609,22 +3609,95 @@ void arm_reload_in_hi (operands) rtx *operands; { - rtx base = find_replacement (&XEXP (operands[1], 0)); + rtx ref = operands[1]; + rtx base, scratch; + HOST_WIDE_INT offset = 0; + + if (GET_CODE (ref) == SUBREG) + { + offset = SUBREG_WORD (ref) * UNITS_PER_WORD; + if (BYTES_BIG_ENDIAN) + offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref))) + - MIN (UNITS_PER_WORD, + GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref))))); + ref = SUBREG_REG (ref); + } + + if (GET_CODE (ref) == REG) + { + /* We have a pseudo which has been spilt onto the stack; there + are two cases here: the first where there is a simple + stack-slot replacement and a second where the stack-slot is + out of range, or is used as a subreg. */ + if (reg_equiv_mem[REGNO (ref)]) + { + ref = reg_equiv_mem[REGNO (ref)]; + base = find_replacement (&XEXP (ref, 0)); + } + else + /* The slot is out of range, or was dressed up in a SUBREG */ + base = reg_equiv_address[REGNO (ref)]; + } + else + base = find_replacement (&XEXP (ref, 0)); - emit_insn (gen_zero_extendqisi2 (operands[2], gen_rtx_MEM (QImode, base))); /* Handle the case where the address is too complex to be offset by 1. */ if (GET_CODE (base) == MINUS || (GET_CODE (base) == PLUS && GET_CODE (XEXP (base, 1)) != CONST_INT)) { - rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[0])); + rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); emit_insn (gen_rtx_SET (VOIDmode, base_plus, base)); base = base_plus; } + else if (GET_CODE (base) == PLUS) + { + /* The addend must be CONST_INT, or we would have dealt with it above */ + HOST_WIDE_INT hi, lo; + offset += INTVAL (XEXP (base, 1)); + base = XEXP (base, 0); + + /* Rework the address into a legal sequence of insns */ + /* Valid range for lo is -4095 -> 4095 */ + lo = (offset >= 0 + ? (offset & 0xfff) + : -((-offset) & 0xfff)); + + /* Corner case, if lo is the max offset then we would be out of range + once we have added the additional 1 below, so bump the msb into the + pre-loading insn(s). */ + if (lo == 4095) + lo &= 0x7ff; + + hi = ((((offset - lo) & (HOST_WIDE_INT) 0xFFFFFFFF) + ^ (HOST_WIDE_INT) 0x80000000) + - (HOST_WIDE_INT) 0x80000000); + + if (hi + lo != offset) + abort (); + + if (hi != 0) + { + rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); + + /* Get the base address; addsi3 knows how to handle constants + that require more than one insn */ + emit_insn (gen_addsi3 (base_plus, base, GEN_INT (hi))); + base = base_plus; + offset = lo; + } + } + + scratch = gen_rtx_REG (SImode, REGNO (operands[2])); + emit_insn (gen_zero_extendqisi2 (scratch, + gen_rtx_MEM (QImode, + plus_constant (base, + offset)))); emit_insn (gen_zero_extendqisi2 (gen_rtx_SUBREG (SImode, operands[0], 0), gen_rtx_MEM (QImode, - plus_constant (base, 1)))); + plus_constant (base, + offset + 1)))); if (BYTES_BIG_ENDIAN) emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], 0), gen_rtx_IOR (SImode, @@ -3632,41 +3705,183 @@ arm_reload_in_hi (operands) (SImode, gen_rtx_SUBREG (SImode, operands[0], 0), GEN_INT (8)), - operands[2]))); + scratch))); else emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], 0), gen_rtx_IOR (SImode, - gen_rtx_ASHIFT (SImode, operands[2], + gen_rtx_ASHIFT (SImode, scratch, GEN_INT (8)), gen_rtx_SUBREG (SImode, operands[0], 0)))); } +/* Handle storing a half-word to memory during reload by synthesising as two + byte stores. Take care not to clobber the input values until after we + have moved them somewhere safe. This code assumes that if the DImode + scratch in operands[2] overlaps either the input value or output address + in some way, then that value must die in this insn (we absolutely need + two scratch registers for some corner cases). */ void arm_reload_out_hi (operands) rtx *operands; { - rtx base = find_replacement (&XEXP (operands[0], 0)); + rtx ref = operands[0]; + rtx outval = operands[1]; + rtx base, scratch; + HOST_WIDE_INT offset = 0; + + if (GET_CODE (ref) == SUBREG) + { + offset = SUBREG_WORD (ref) * UNITS_PER_WORD; + if (BYTES_BIG_ENDIAN) + offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (ref))) + - MIN (UNITS_PER_WORD, + GET_MODE_SIZE (GET_MODE (SUBREG_REG (ref))))); + ref = SUBREG_REG (ref); + } + + + if (GET_CODE (ref) == REG) + { + /* We have a pseudo which has been spilt onto the stack; there + are two cases here: the first where there is a simple + stack-slot replacement and a second where the stack-slot is + out of range, or is used as a subreg. */ + if (reg_equiv_mem[REGNO (ref)]) + { + ref = reg_equiv_mem[REGNO (ref)]; + base = find_replacement (&XEXP (ref, 0)); + } + else + /* The slot is out of range, or was dressed up in a SUBREG */ + base = reg_equiv_address[REGNO (ref)]; + } + else + base = find_replacement (&XEXP (ref, 0)); + + scratch = gen_rtx_REG (SImode, REGNO (operands[2])); + + /* Handle the case where the address is too complex to be offset by 1. */ + if (GET_CODE (base) == MINUS + || (GET_CODE (base) == PLUS && GET_CODE (XEXP (base, 1)) != CONST_INT)) + { + rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); + + /* Be careful not to destroy OUTVAL. */ + if (reg_overlap_mentioned_p (base_plus, outval)) + { + /* Updating base_plus might destroy outval, see if we can + swap the scratch and base_plus. */ + if (! reg_overlap_mentioned_p (scratch, outval)) + { + rtx tmp = scratch; + scratch = base_plus; + base_plus = tmp; + } + else + { + rtx scratch_hi = gen_rtx_REG (HImode, REGNO (operands[2])); + + /* Be conservative and copy OUTVAL into the scratch now, + this should only be necessary if outval is a subreg + of something larger than a word. */ + /* XXX Might this clobber base? I can't see how it can, + since scratch is known to overlap with OUTVAL, and + must be wider than a word. */ + emit_insn (gen_movhi (scratch_hi, outval)); + outval = scratch_hi; + } + } + + emit_insn (gen_rtx_SET (VOIDmode, base_plus, base)); + base = base_plus; + } + else if (GET_CODE (base) == PLUS) + { + /* The addend must be CONST_INT, or we would have dealt with it above */ + HOST_WIDE_INT hi, lo; + + offset += INTVAL (XEXP (base, 1)); + base = XEXP (base, 0); + + /* Rework the address into a legal sequence of insns */ + /* Valid range for lo is -4095 -> 4095 */ + lo = (offset >= 0 + ? (offset & 0xfff) + : -((-offset) & 0xfff)); + + /* Corner case, if lo is the max offset then we would be out of range + once we have added the additional 1 below, so bump the msb into the + pre-loading insn(s). */ + if (lo == 4095) + lo &= 0x7ff; + + hi = ((((offset - lo) & (HOST_WIDE_INT) 0xFFFFFFFF) + ^ (HOST_WIDE_INT) 0x80000000) + - (HOST_WIDE_INT) 0x80000000); + + if (hi + lo != offset) + abort (); + + if (hi != 0) + { + rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1); + + /* Be careful not to destroy OUTVAL. */ + if (reg_overlap_mentioned_p (base_plus, outval)) + { + /* Updating base_plus might destroy outval, see if we + can swap the scratch and base_plus. */ + if (! reg_overlap_mentioned_p (scratch, outval)) + { + rtx tmp = scratch; + scratch = base_plus; + base_plus = tmp; + } + else + { + rtx scratch_hi = gen_rtx_REG (HImode, REGNO (operands[2])); + + /* Be conservative and copy outval into scratch now, + this should only be necessary if outval is a + subreg of something larger than a word. */ + /* XXX Might this clobber base? I can't see how it + can, since scratch is known to overlap with + outval. */ + emit_insn (gen_movhi (scratch_hi, outval)); + outval = scratch_hi; + } + } + + /* Get the base address; addsi3 knows how to handle constants + that require more than one insn */ + emit_insn (gen_addsi3 (base_plus, base, GEN_INT (hi))); + base = base_plus; + offset = lo; + } + } if (BYTES_BIG_ENDIAN) { - emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, 1)), - gen_rtx_SUBREG (QImode, operands[1], 0))); - emit_insn (gen_lshrsi3 (operands[2], - gen_rtx_SUBREG (SImode, operands[1], 0), + emit_insn (gen_movqi (gen_rtx_MEM (QImode, + plus_constant (base, offset + 1)), + gen_rtx_SUBREG (QImode, outval, 0))); + emit_insn (gen_lshrsi3 (scratch, + gen_rtx_SUBREG (SImode, outval, 0), GEN_INT (8))); - emit_insn (gen_movqi (gen_rtx_MEM (QImode, base), - gen_rtx_SUBREG (QImode, operands[2], 0))); + emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset)), + gen_rtx_SUBREG (QImode, scratch, 0))); } else { - emit_insn (gen_movqi (gen_rtx_MEM (QImode, base), - gen_rtx_SUBREG (QImode, operands[1], 0))); - emit_insn (gen_lshrsi3 (operands[2], - gen_rtx_SUBREG (SImode, operands[1], 0), + emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, offset)), + gen_rtx_SUBREG (QImode, outval, 0))); + emit_insn (gen_lshrsi3 (scratch, + gen_rtx_SUBREG (SImode, outval, 0), GEN_INT (8))); - emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (base, 1)), - gen_rtx_SUBREG (QImode, operands[2], 0))); + emit_insn (gen_movqi (gen_rtx_MEM (QImode, + plus_constant (base, offset + 1)), + gen_rtx_SUBREG (QImode, scratch, 0))); } } diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 6be5c0119b39..86fe2481e1e5 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -248,7 +248,7 @@ Unrecognized value in TARGET_CPU_DEFAULT. extern int target_flags; /* The floating point instruction architecture, can be 2 or 3 */ -extern char * target_fp_name; +extern const char * target_fp_name; /* Nonzero if the function prologue (and epilogue) should obey the ARM Procedure Call Standard. */ @@ -404,9 +404,9 @@ function tries to return. */ struct arm_cpu_select { - char * string; - char * name; - struct processors * processors; + const char * string; + const char * name; + const struct processors * processors; }; /* This is a magic array. If the user specifies a command line switch @@ -585,7 +585,7 @@ extern int arm_is_6_or_7; #endif /* Used when parsing command line option -mstructure_size_boundary. */ -extern char * structure_size_string; +extern const char * structure_size_string; /* Non-zero if move instructions will actually fail to work when given unaligned data. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 71cb167f57e8..2c2d48b7e7ff 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -3128,11 +3128,13 @@ mov%?\\t%0, %1\\t%@ movhi mvn%?\\t%0, #%B1\\t%@ movhi") - +;; We use a DImode scratch because we may occasionally need an additional +;; temporary if the address isn't offsettable -- push_reload doesn't seem +;; to take any notice of the "o" constraints on reload_memory_operand operand. (define_expand "reload_outhi" [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o") (match_operand:HI 1 "s_register_operand" "r") - (match_operand:SI 2 "s_register_operand" "=&r")])] + (match_operand:DI 2 "s_register_operand" "=&r")])] "" " arm_reload_out_hi (operands); @@ -3142,7 +3144,7 @@ (define_expand "reload_inhi" [(parallel [(match_operand:HI 0 "s_register_operand" "=r") (match_operand:HI 1 "reload_memory_operand" "o") - (match_operand:SI 2 "s_register_operand" "=&r")])] + (match_operand:DI 2 "s_register_operand" "=&r")])] "TARGET_SHORT_BY_BYTES" " arm_reload_in_hi (operands); diff --git a/gcc/config/arm/riscix.h b/gcc/config/arm/riscix.h index 07bdb0f70819..fad0293337a6 100644 --- a/gcc/config/arm/riscix.h +++ b/gcc/config/arm/riscix.h @@ -79,10 +79,10 @@ Boston, MA 02111-1307, USA. */ /* None of these is actually used in cc1. If we don't define them in target switches cc1 complains about them. For the sake of argument lets allocate bit 31 of target flags for such options. */ -#define SUBTARGET_SWITCHES \ -{"bsd", 0x80000000, ""}, \ -{"xopen", 0x80000000, ""}, \ -{"no-symrename", 0x80000000, ""}, +#define SUBTARGET_SWITCHES \ + {"bsd", 0x80000000, "Do symbol renaming for BSD"}, \ + {"xopen", 0x80000000, "Do symbol renaming for X/OPEN"}, \ + {"no-symrename", 0x80000000, "Don't do symbol renaming"}, /* Run-time Target Specification. */