@@ -230,6 +230,18 @@
(match_test "sh_disp_addr_displacement (op)
<= sh_max_mov_insn_displacement (GET_MODE (op), false)")))
+;; Returns true if OP is a post-increment addressing mode memory reference.
+(define_predicate "post_inc_mem"
+ (and (match_code "mem")
+ (match_code "post_inc" "0")
+ (match_code "reg" "00")))
+
+;; Returns true if OP is a pre-decrement addressing mode memory reference.
+(define_predicate "pre_dec_mem"
+ (and (match_code "mem")
+ (match_code "pre_dec" "0")
+ (match_code "reg" "00")))
+
;; Returns 1 if the operand can be used in an SH2A movu.{b|w} insn.
(define_predicate "zero_extend_movu_operand"
(and (ior (match_operand 0 "displacement_mem_operand")
@@ -224,8 +224,12 @@ sh_find_set_of_reg (rtx reg, rtx_insn* insn, F stepfunc,
}
}
- if (result.set_src != NULL)
- gcc_assert (result.insn != NULL && result.set_rtx != NULL);
+ /* If the searched reg is found inside a (mem (post_inc:SI (reg))), set_of
+ will return NULL and set_rtx will be NULL.
+ In this case report a 'not found'. result.insn will always be non-null
+ at this point, so no need to check it. */
+ if (result.set_src != NULL && result.set_rtx == NULL)
+ result.set_src = NULL;
return result;
}
@@ -1307,12 +1307,10 @@ struct sh_args {
#define HAVE_POST_INCREMENT TARGET_SH1
#define HAVE_PRE_DECREMENT TARGET_SH1
-#define USE_LOAD_POST_INCREMENT(mode) ((mode == SImode || mode == DImode) \
- ? 0 : TARGET_SH1)
-#define USE_LOAD_PRE_DECREMENT(mode) 0
-#define USE_STORE_POST_INCREMENT(mode) 0
-#define USE_STORE_PRE_DECREMENT(mode) ((mode == SImode || mode == DImode) \
- ? 0 : TARGET_SH1)
+#define USE_LOAD_POST_INCREMENT(mode) TARGET_SH1
+#define USE_LOAD_PRE_DECREMENT(mode) TARGET_SH2A
+#define USE_STORE_POST_INCREMENT(mode) TARGET_SH2A
+#define USE_STORE_PRE_DECREMENT(mode) TARGET_SH1
/* If a memory clear move would take CLEAR_RATIO or more simple
move-instruction pairs, we will do a setmem instead. */
@@ -4820,6 +4820,15 @@
[(set_attr "type" "load")
(set_attr "length" "2,2,4")])
+;; The pre-dec and post-inc mems must be captured by the '<' and '>'
+;; constraints, otherwise wrong code might get generated.
+(define_insn "*extend<mode>si2_predec"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=z")
+ (sign_extend:SI (match_operand:QIHI 1 "pre_dec_mem" "<")))]
+ "TARGET_SH2A"
+ "mov.<bw> %1,%0"
+ [(set_attr "type" "load")])
+
;; The *_snd patterns will take care of other QImode/HImode addressing
;; modes than displacement addressing. They must be defined _after_ the
;; displacement addressing patterns. Otherwise the displacement addressing
@@ -5261,6 +5270,22 @@
prepare_move_operands (operands, <MODE>mode);
})
+;; The pre-dec and post-inc mems must be captured by the '<' and '>'
+;; constraints, otherwise wrong code might get generated.
+(define_insn "*mov<mode>_load_predec"
+ [(set (match_operand:QIHISI 0 "arith_reg_dest" "=z")
+ (match_operand:QIHISI 1 "pre_dec_mem" "<"))]
+ "TARGET_SH2A"
+ "mov.<bwl> %1,%0"
+ [(set_attr "type" "load")])
+
+(define_insn "*mov<mode>_store_postinc"
+ [(set (match_operand:QIHISI 0 "post_inc_mem" "=>")
+ (match_operand:QIHISI 1 "arith_reg_operand" "z"))]
+ "TARGET_SH2A"
+ "mov.<bwl> %1,%0"
+ [(set_attr "type" "store")])
+
;; Specifying the displacement addressing load / store patterns separately
;; before the generic movqi / movhi pattern allows controlling the order
;; in which load / store insns are selected in a more fine grained way.