@@ -101,6 +101,7 @@ extern int h8300_regs_ok_for_stm (int, rtx[]);
extern int h8300_hard_regno_rename_ok (unsigned int, unsigned int);
extern int h8300_hard_regno_nregs (int, enum machine_mode);
extern int h8300_hard_regno_mode_ok (int, enum machine_mode);
+extern bool h8300_move_ok (rtx, rtx);
struct cpp_reader;
extern void h8300_pr_interrupt (struct cpp_reader *);
@@ -5813,6 +5813,40 @@ h8300_hard_regno_mode_ok (int regno, enum machine_mode mode)
goes. */
return regno == MAC_REG ? mode == SImode : 1;
}
+
+/* Helper function for the move patterns. Make sure a move is legitimate. */
+
+bool
+h8300_move_ok (rtx dest, rtx src)
+{
+ rtx addr, other;
+
+ /* Validate that at least one operand is a register. */
+ if (MEM_P (dest))
+ {
+ if (MEM_P (src) || CONSTANT_P (src))
+ return false;
+ addr = XEXP (dest, 0);
+ other = src;
+ }
+ else if (MEM_P (src))
+ {
+ addr = XEXP (src, 0);
+ other = dest;
+ }
+ else
+ return true;
+
+ /* Validate that auto-inc doesn't affect OTHER. */
+ if (GET_RTX_CLASS (GET_CODE (addr)) != RTX_AUTOINC)
+ return true;
+ addr = XEXP (addr, 0);
+
+ if (addr == stack_pointer_rtx)
+ return register_no_sp_elim_operand (other, VOIDmode);
+ else
+ return !reg_overlap_mentioned_p(other, addr);
+}
/* Perform target dependent optabs initialization. */
static void
@@ -180,6 +180,15 @@
(include "constraints.md")
;; ----------------------------------------------------------------------
+;; MACRO DEFINITIONS
+;; ----------------------------------------------------------------------
+
+;; This mode iterator allows :P to be used for patterns that operate on
+;; pointer-sized quantities. Exactly one of the two alternatives will match.
+(define_mode_iterator P [(HI "Pmode == HImode") (SI "Pmode == SImode")])
+
+
+;; ----------------------------------------------------------------------
;; MOVE INSTRUCTIONS
;; ----------------------------------------------------------------------
@@ -189,8 +198,7 @@
[(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m")
(match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))]
"TARGET_H8300
- && (register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode))"
+ && h8300_move_ok (operands[0], operands[1])"
"@
sub.b %X0,%X0
mov.b %R1,%X0
@@ -205,8 +213,7 @@
[(set (match_operand:QI 0 "general_operand_dst" "=r,r ,<,r,r,m")
(match_operand:QI 1 "general_operand_src" " I,r>,r,n,m,r"))]
"(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX
- && (register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode))"
+ && h8300_move_ok (operands[0], operands[1])"
"@
sub.b %X0,%X0
mov.b %R1,%X0
@@ -232,16 +239,11 @@
[(set (match_operand:QI 0 "general_operand_dst" "")
(match_operand:QI 1 "general_operand_src" ""))]
""
- "
{
/* One of the ops has to be in a register. */
- if (!TARGET_H8300SX
- && !register_operand (operand0, QImode)
- && !register_operand (operand1, QImode))
- {
- operands[1] = copy_to_mode_reg (QImode, operand1);
- }
-}")
+ if (!TARGET_H8300SX && !h8300_move_ok (operands[0], operands[1]))
+ operands[1] = copy_to_mode_reg (QImode, operands[1]);
+})
(define_insn "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "+r,r"))
@@ -260,13 +262,7 @@
[(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m")
(match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))]
"TARGET_H8300
- && (register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode))
- && !(GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
- && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG
- && GET_CODE (operands[1]) == REG
- && REGNO (XEXP (XEXP (operands[0], 0), 0)) == REGNO (operands[1]))"
+ && h8300_move_ok (operands[0], operands[1])"
"@
sub.w %T0,%T0
mov.w %T1,%T0
@@ -282,8 +278,7 @@
[(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m")
(match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))]
"(TARGET_H8300H || TARGET_H8300S) && !TARGET_H8300SX
- && (register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode))"
+ && h8300_move_ok (operands[0], operands[1])"
"@
sub.w %T0,%T0
mov.w %T1,%T0
@@ -313,15 +308,11 @@
[(set (match_operand:HI 0 "general_operand_dst" "")
(match_operand:HI 1 "general_operand_src" ""))]
""
- "
{
/* One of the ops has to be in a register. */
- if (!register_operand (operand1, HImode)
- && !register_operand (operand0, HImode))
- {
- operands[1] = copy_to_mode_reg (HImode, operand1);
- }
-}")
+ if (!h8300_move_ok (operands[0], operands[1]))
+ operands[1] = copy_to_mode_reg (HImode, operand1);
+})
(define_insn "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "+r,r,r"))
@@ -341,7 +332,6 @@
[(set (match_operand:SI 0 "general_operand_dst" "")
(match_operand:SI 1 "general_operand_src" ""))]
""
- "
{
if (TARGET_H8300)
{
@@ -351,20 +341,16 @@
else if (!TARGET_H8300SX)
{
/* One of the ops has to be in a register. */
- if (!register_operand (operand1, SImode)
- && !register_operand (operand0, SImode))
- {
- operands[1] = copy_to_mode_reg (SImode, operand1);
- }
+ if (!h8300_move_ok (operands[0], operands[1]))
+ operands[1] = copy_to_mode_reg (SImode, operand1);
}
-}")
+})
(define_insn "*movsi_h8300"
[(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,o,<,r")
(match_operand:SI 1 "general_operand_src" "I,r,io,r,r,>"))]
"TARGET_H8300
- && (register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode))"
+ && h8300_move_ok (operands[0], operands[1])"
"*
{
unsigned int rn = -1;
@@ -434,13 +420,7 @@
[(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,<,r,r,m,*a,*a,r")
(match_operand:SI 1 "general_operand_src" "I,r,i,r,>,m,r,I,r,*a"))]
"(TARGET_H8300S || TARGET_H8300H) && !TARGET_H8300SX
- && (register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode))
- && !(GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
- && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG
- && GET_CODE (operands[1]) == REG
- && REGNO (XEXP (XEXP (operands[0], 0), 0)) == REGNO (operands[1]))"
+ && h8300_move_ok (operands[0], operands[1])"
"*
{
switch (which_alternative)
@@ -872,90 +852,35 @@
;; PUSH INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "pushqi1_h8300"
- [(set (reg:HI SP_REG)
- (plus:HI (reg:HI SP_REG) (const_int -2)))
- (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -1)))
- (match_operand:QI 0 "register_operand" "r"))]
- "TARGET_H8300
- && operands[0] != stack_pointer_rtx"
+(define_insn "*pushqi1_h8300"
+ [(set (mem:QI
+ (pre_modify:HI
+ (reg:HI SP_REG)
+ (plus:HI (reg:HI SP_REG) (const_int -2))))
+ (match_operand:QI 0 "register_no_sp_elim_operand" "r"))]
+ "TARGET_H8300"
"mov.w\\t%T0,@-r7"
[(set_attr "length" "2")])
-(define_insn "pushqi1_h8300hs_advanced"
- [(set (reg:SI SP_REG)
- (plus:SI (reg:SI SP_REG) (const_int -4)))
- (set (mem:QI (plus:SI (reg:SI SP_REG) (const_int -3)))
- (match_operand:QI 0 "register_operand" "r"))]
- "(TARGET_H8300H || TARGET_H8300S)
- && operands[0] != stack_pointer_rtx"
- "mov.l\\t%S0,@-er7"
- [(set_attr "length" "4")])
-
-(define_insn "pushqi1_h8300hs_normal"
- [(set (reg:HI SP_REG)
- (plus:HI (reg:HI SP_REG) (const_int -4)))
- (set (mem:QI (plus:HI (reg:HI SP_REG) (const_int -3)))
- (match_operand:QI 0 "register_operand" "r"))]
- "(TARGET_H8300H || TARGET_H8300S)
- && operands[0] != stack_pointer_rtx"
- "mov.l\\t%S0,@-er7"
- [(set_attr "length" "4")])
-
-(define_expand "pushqi1"
- [(match_operand:QI 0 "register_operand" "")]
- ""
- "
-{
- if (TARGET_H8300)
- emit_insn (gen_pushqi1_h8300 (operands[0]));
- else if (!TARGET_NORMAL_MODE)
- emit_insn (gen_pushqi1_h8300hs_advanced (operands[0]));
- else
- emit_insn (gen_pushqi1_h8300hs_normal (operands[0]));
- DONE;
-}")
-
-(define_expand "pushhi1_h8300"
- [(set (mem:HI (pre_dec:HI (reg:HI SP_REG)))
- (match_operand:HI 0 "register_operand" ""))]
- "TARGET_H8300
- && operands[0] != stack_pointer_rtx"
- "")
-
-(define_insn "pushhi1_h8300hs_advanced"
- [(set (reg:SI SP_REG)
- (plus:SI (reg:SI SP_REG) (const_int -4)))
- (set (mem:HI (plus:SI (reg:SI SP_REG) (const_int -2)))
- (match_operand:HI 0 "register_operand" "r"))]
- "(TARGET_H8300H || TARGET_H8300S)
- && operands[0] != stack_pointer_rtx"
+(define_insn "*pushqi1_h8300hs_<mode>"
+ [(set (mem:QI
+ (pre_modify:P
+ (reg:P SP_REG)
+ (plus:P (reg:P SP_REG) (const_int -4))))
+ (match_operand:QI 0 "register_no_sp_elim_operand" "r"))]
+ "TARGET_H8300H || TARGET_H8300S"
"mov.l\\t%S0,@-er7"
[(set_attr "length" "4")])
-(define_insn "pushhi1_h8300hs_normal"
- [(set (reg:HI SP_REG)
- (plus:HI (reg:HI SP_REG) (const_int -4)))
- (set (mem:HI (plus:HI (reg:HI SP_REG) (const_int -2)))
- (match_operand:HI 0 "register_operand" "r"))]
- "(TARGET_H8300H || TARGET_H8300S)
- && operands[0] != stack_pointer_rtx"
+(define_insn "*pushhi1_h8300hs_<mode>"
+ [(set (mem:HI
+ (pre_modify:P
+ (reg:P SP_REG)
+ (plus:P (reg:P SP_REG) (const_int -4))))
+ (match_operand:HI 0 "register_no_sp_elim_operand" "r"))]
+ "TARGET_H8300H || TARGET_H8300S"
"mov.l\\t%S0,@-er7"
[(set_attr "length" "4")])
-
-(define_expand "pushhi1"
- [(match_operand:HI 0 "register_operand" "")]
- ""
- "
-{
- if (TARGET_H8300)
- emit_insn (gen_pushhi1_h8300 (operands[0]));
- else if (!TARGET_NORMAL_MODE)
- emit_insn (gen_pushhi1_h8300hs_advanced (operands[0]));
- else
- emit_insn (gen_pushhi1_h8300hs_normal (operands[0]));
- DONE;
-}")
;; ----------------------------------------------------------------------
;; TEST INSTRUCTIONS
@@ -375,6 +375,20 @@
return op == stack_pointer_rtx;
})
+;; False if X is anything that might eliminate to the stack pointer.
+
+(define_predicate "register_no_sp_elim_operand"
+ (match_operand 0 "register_operand")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return !(op == stack_pointer_rtx
+ || op == arg_pointer_rtx
+ || op == frame_pointer_rtx
+ || IN_RANGE (REGNO (op),
+ FIRST_PSEUDO_REGISTER, LAST_VIRTUAL_REGISTER));
+})
+
;; Return nonzero if X is a constant whose absolute value is greater
;; than 2.