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:
Richard Earnshaw 1998-05-26 07:37:15 +00:00 committed by Richard Earnshaw
parent 312a0c9073
commit 4d818c8540
4 changed files with 114 additions and 7 deletions

View File

@ -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.

View File

@ -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

View File

@ -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}}, \

View File

@ -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")