mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-19 10:39:54 +08:00
arm.c (bad_signed_byte_operand): New predicate function.
* arm.c (bad_signed_byte_operand): New predicate function. * arm.h (PREDICATE_CODES): Add it to the list. * arm.md (*extendqi[sh]i_insn): Split any addresses that ldrsb can't handle. (define_split): Two new splits for above insns. From-SVN: r20057
This commit is contained in:
parent
312a0c9073
commit
4d818c8540
@ -1,3 +1,11 @@
|
||||
Tue May 26 07:31:04 1998 Richard Earnshaw (rearnsha@arm.com)
|
||||
|
||||
* arm.c (bad_signed_byte_operand): New predicate function.
|
||||
* arm.h (PREDICATE_CODES): Add it to the list.
|
||||
* arm.md (*extendqi[sh]i_insn): Split any addresses that ldrsb
|
||||
can't handle.
|
||||
(define_split): Two new splits for above insns.
|
||||
|
||||
Mon May 25 22:49:56 PDT 1998 Jeff Law (law@cygnus.com)
|
||||
|
||||
* version.c: Bump for snapshot.
|
||||
|
@ -1745,6 +1745,33 @@ reload_memory_operand (op, mode)
|
||||
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)));
|
||||
}
|
||||
|
||||
/* Return 1 if OP is a valid memory address, but not valid for a signed byte
|
||||
memory access (architecture V4) */
|
||||
int
|
||||
bad_signed_byte_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
if (! memory_operand (op, mode) || GET_CODE (op) != MEM)
|
||||
return 0;
|
||||
|
||||
op = XEXP (op, 0);
|
||||
|
||||
/* A sum of anything more complex than reg + reg or reg + const is bad */
|
||||
if ((GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
|
||||
&& ! s_register_operand (XEXP (op, 0), VOIDmode))
|
||||
return 1;
|
||||
|
||||
/* Big constants are also bad */
|
||||
if (GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT
|
||||
&& (INTVAL (XEXP (op, 1)) > 0xff
|
||||
|| -INTVAL (XEXP (op, 1)) > 0xff))
|
||||
return 1;
|
||||
|
||||
/* Everything else is good, or can will automatically be made so. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return TRUE for valid operands for the rhs of an ARM instruction. */
|
||||
|
||||
int
|
||||
|
@ -1781,6 +1781,7 @@ extern int arm_compare_fp;
|
||||
{"fpu_rhs_operand", {SUBREG, REG, CONST_DOUBLE}}, \
|
||||
{"arm_not_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"offsettable_memory_operand", {MEM}}, \
|
||||
{"bad_signed_byte_operand", {MEM}}, \
|
||||
{"alignable_memory_operand", {MEM}}, \
|
||||
{"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}}, \
|
||||
{"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \
|
||||
|
@ -2344,16 +2344,52 @@
|
||||
operands[2] = gen_reg_rtx (SImode);
|
||||
}")
|
||||
|
||||
; Rather than restricting all byte accesses to memory addresses that ldrsb
|
||||
; can handle, we fix up the ones that ldrsb can't grok with a split.
|
||||
(define_insn "*extendqihi_insn"
|
||||
[(set (match_operand:HI 0 "s_register_operand" "=r")
|
||||
(sign_extend:HI (match_operand:QI 1 "memory_operand" "o<>")))]
|
||||
(sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
|
||||
"arm_arch4"
|
||||
"ldr%?sb\\t%0, %1"
|
||||
[(set_attr "type" "load")])
|
||||
"*
|
||||
/* If the address is invalid, this will split the instruction into two. */
|
||||
if (bad_signed_byte_operand(operands[1], QImode))
|
||||
return \"#\";
|
||||
return \"ldr%?sb\\t%0, %1\";
|
||||
"
|
||||
[(set_attr "type" "load")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:HI 0 "s_register_operand" "")
|
||||
(sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
|
||||
"arm_arch4 && reload_completed"
|
||||
[(set (match_dup 3) (match_dup 1))
|
||||
(set (match_dup 0) (sign_extend:HI (match_dup 2)))]
|
||||
"
|
||||
{
|
||||
HOST_WIDE_INT offset;
|
||||
|
||||
operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]));
|
||||
operands[2] = gen_rtx (MEM, QImode, operands[3]);
|
||||
MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]);
|
||||
RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
|
||||
operands[1] = XEXP (operands[1], 0);
|
||||
if (GET_CODE (operands[1]) == PLUS
|
||||
&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
|
||||
&& ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
|
||||
|| const_ok_for_arm (-offset)))
|
||||
{
|
||||
HOST_WIDE_INT low = (offset > 0
|
||||
? (offset & 0xff) : -((-offset) & 0xff));
|
||||
XEXP (operands[2], 0) = plus_constant (operands[3], low);
|
||||
operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
|
||||
}
|
||||
}
|
||||
")
|
||||
|
||||
(define_expand "extendqisi2"
|
||||
[(set (match_dup 2)
|
||||
(ashift:SI (match_operand:QI 1 "s_register_operand" "")
|
||||
(ashift:SI (match_operand:QI 1 "general_operand" "")
|
||||
(const_int 24)))
|
||||
(set (match_operand:SI 0 "s_register_operand" "")
|
||||
(ashiftrt:SI (match_dup 2)
|
||||
@ -2373,12 +2409,47 @@
|
||||
operands[2] = gen_reg_rtx (SImode);
|
||||
}")
|
||||
|
||||
; Rather than restricting all byte accesses to memory addresses that ldrsb
|
||||
; can handle, we fix up the ones that ldrsb can't grok with a split.
|
||||
(define_insn "*extendqisi_insn"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "=r")
|
||||
(sign_extend:SI (match_operand:QI 1 "memory_operand" "o<>")))]
|
||||
(sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
|
||||
"arm_arch4"
|
||||
"ldr%?sb\\t%0, %1"
|
||||
[(set_attr "type" "load")])
|
||||
"*
|
||||
/* If the address is invalid, this will split the instruction into two. */
|
||||
if (bad_signed_byte_operand(operands[1], QImode))
|
||||
return \"#\";
|
||||
return \"ldr%?sb\\t%0, %1\";
|
||||
"
|
||||
[(set_attr "type" "load")
|
||||
(set_attr "length" "8")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:SI 0 "s_register_operand" "")
|
||||
(sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
|
||||
"arm_arch4 && reload_completed"
|
||||
[(set (match_dup 0) (match_dup 1))
|
||||
(set (match_dup 0) (sign_extend:SI (match_dup 2)))]
|
||||
"
|
||||
{
|
||||
HOST_WIDE_INT offset;
|
||||
|
||||
operands[2] = gen_rtx (MEM, QImode, operands[0]);
|
||||
MEM_IN_STRUCT_P (operands[2]) = MEM_IN_STRUCT_P (operands[1]);
|
||||
RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
|
||||
operands[1] = XEXP (operands[1], 0);
|
||||
if (GET_CODE (operands[1]) == PLUS
|
||||
&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
|
||||
&& ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
|
||||
|| const_ok_for_arm (-offset)))
|
||||
{
|
||||
HOST_WIDE_INT low = (offset > 0
|
||||
? (offset & 0xff) : -((-offset) & 0xff));
|
||||
XEXP (operands[2], 0) = plus_constant (operands[0], low);
|
||||
operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
|
||||
}
|
||||
}
|
||||
")
|
||||
|
||||
(define_insn "extendsfdf2"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "=f")
|
||||
|
Loading…
Reference in New Issue
Block a user