mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-20 01:19:21 +08:00
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
This commit is contained in:
parent
c3c55f8632
commit
f9cc092ab4
@ -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 <ddsinc09@ix.netcom.com>
|
||||
|
||||
* fixincludes:
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user