From 3fc2009ee102928c95a09d7ef0187835417598fe Mon Sep 17 00:00:00 2001 From: rearnsha Date: Tue, 26 May 1998 07:37:15 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@20057 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 8 +++++ gcc/config/arm/arm.c | 27 ++++++++++++++++ gcc/config/arm/arm.h | 1 + gcc/config/arm/arm.md | 85 ++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 114 insertions(+), 7 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2efb4ed09d4..13750bda942 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 28614a2d2e9..ab0faa835ad 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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 diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 8f4cb2021ad..c6676da5215 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -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}}, \ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 1920112e5c5..4df608726ed 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -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") -- 2.11.4.GIT