Commit 4d818c85 by Richard Earnshaw Committed by Richard Earnshaw

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
parent 312a0c90
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) Mon May 25 22:49:56 PDT 1998 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot. * version.c: Bump for snapshot.
......
...@@ -1745,6 +1745,33 @@ reload_memory_operand (op, mode) ...@@ -1745,6 +1745,33 @@ reload_memory_operand (op, mode)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER))); && 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. */ /* Return TRUE for valid operands for the rhs of an ARM instruction. */
int int
......
...@@ -1781,6 +1781,7 @@ extern int arm_compare_fp; ...@@ -1781,6 +1781,7 @@ extern int arm_compare_fp;
{"fpu_rhs_operand", {SUBREG, REG, CONST_DOUBLE}}, \ {"fpu_rhs_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"arm_not_operand", {SUBREG, REG, CONST_INT}}, \ {"arm_not_operand", {SUBREG, REG, CONST_INT}}, \
{"offsettable_memory_operand", {MEM}}, \ {"offsettable_memory_operand", {MEM}}, \
{"bad_signed_byte_operand", {MEM}}, \
{"alignable_memory_operand", {MEM}}, \ {"alignable_memory_operand", {MEM}}, \
{"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}}, \ {"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}}, \
{"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \ {"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \
......
...@@ -2344,16 +2344,52 @@ ...@@ -2344,16 +2344,52 @@
operands[2] = gen_reg_rtx (SImode); 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" (define_insn "*extendqihi_insn"
[(set (match_operand:HI 0 "s_register_operand" "=r") [(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" "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" (define_expand "extendqisi2"
[(set (match_dup 2) [(set (match_dup 2)
(ashift:SI (match_operand:QI 1 "s_register_operand" "") (ashift:SI (match_operand:QI 1 "general_operand" "")
(const_int 24))) (const_int 24)))
(set (match_operand:SI 0 "s_register_operand" "") (set (match_operand:SI 0 "s_register_operand" "")
(ashiftrt:SI (match_dup 2) (ashiftrt:SI (match_dup 2)
...@@ -2373,12 +2409,47 @@ ...@@ -2373,12 +2409,47 @@
operands[2] = gen_reg_rtx (SImode); 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" (define_insn "*extendqisi_insn"
[(set (match_operand:SI 0 "s_register_operand" "=r") [(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" "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" (define_insn "extendsfdf2"
[(set (match_operand:DF 0 "s_register_operand" "=f") [(set (match_operand:DF 0 "s_register_operand" "=f")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment