+2005-05-26 David Ung <davidu@mips.com>
+
+ * config/mips/mips.c (mips_use_ins_ext_p): New helper function
+ that determines whether the MIPS32/64 R2 ext/ins should be used.
+ * config/mips/mips.h (ISA_HAS_EXT_INS): New macro.
+ * config/mips/mips.md (extzv): Changed predicate for operand to
+ nonimmediate_operand. Add code to generate insn patterns for
+ extzvsi and extzvdi.
+ (extzv<mode>): New pattern to match mips32/64 r2 ext insn.
+ (insv): Similarly for insertion.
+ (insv<mode>): Similarly.
+
2005-05-26 Paolo Bonzini <bonzini@gnu.org>
* simplify-rtx.c (avoid_constant_pool_reference): Support
}
return true;
}
-\f
+
+/* Return true if (zero_extract OP SIZE POSITION) can be used as the
+ source of an "ext" instruction or the destination of an "ins"
+ instruction. OP must be a register operand and the following
+ conditions must hold:
+
+ 0 <= POSITION < GET_MODE_BITSIZE (GET_MODE (op))
+ 0 < SIZE <= GET_MODE_BITSIZE (GET_MODE (op))
+ 0 < POSITION + SIZE <= GET_MODE_BITSIZE (GET_MODE (op))
+
+ Also reject lengths equal to a word as they are better handled
+ by the move patterns. */
+
+bool
+mips_use_ins_ext_p (rtx op, rtx size, rtx position)
+{
+ HOST_WIDE_INT len, pos;
+
+ if (!ISA_HAS_EXT_INS
+ || !register_operand (op, VOIDmode)
+ || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD)
+ return false;
+
+ len = INTVAL (size);
+ pos = INTVAL (position);
+
+ if (len <= 0 || len >= GET_MODE_BITSIZE (GET_MODE (op))
+ || pos < 0 || pos + len > GET_MODE_BITSIZE (GET_MODE (op)))
+ return false;
+
+ return true;
+}
+
/* Set up globals to generate code for the ISA or processor
described by INFO. */
(define_expand "extzv"
[(set (match_operand 0 "register_operand")
- (zero_extract (match_operand:QI 1 "memory_operand")
+ (zero_extract (match_operand 1 "nonimmediate_operand")
(match_operand 2 "immediate_operand")
(match_operand 3 "immediate_operand")))]
"!TARGET_MIPS16"
INTVAL (operands[2]),
INTVAL (operands[3])))
DONE;
+ else if (mips_use_ins_ext_p (operands[1], operands[2], operands[3]))
+ {
+ if (GET_MODE (operands[0]) == DImode)
+ emit_insn (gen_extzvdi (operands[0], operands[1], operands[2],
+ operands[3]));
+ else
+ emit_insn (gen_extzvsi (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
else
FAIL;
})
+(define_insn "extzv<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (zero_extract:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:SI 2 "immediate_operand" "I")
+ (match_operand:SI 3 "immediate_operand" "I")))]
+ "mips_use_ins_ext_p (operands[1], operands[2], operands[3])"
+ "<d>ext\t%0,%1,%3,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+
(define_expand "insv"
- [(set (zero_extract (match_operand:QI 0 "memory_operand")
+ [(set (zero_extract (match_operand 0 "nonimmediate_operand")
(match_operand 1 "immediate_operand")
(match_operand 2 "immediate_operand"))
(match_operand 3 "reg_or_0_operand"))]
INTVAL (operands[1]),
INTVAL (operands[2])))
DONE;
- else
- FAIL;
+ else if (mips_use_ins_ext_p (operands[0], operands[1], operands[2]))
+ {
+ if (GET_MODE (operands[0]) == DImode)
+ emit_insn (gen_insvdi (operands[0], operands[1], operands[2],
+ operands[3]));
+ else
+ emit_insn (gen_insvsi (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
+ else
+ FAIL;
})
+(define_insn "insv<mode>"
+ [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand" "+d")
+ (match_operand:SI 1 "immediate_operand" "I")
+ (match_operand:SI 2 "immediate_operand" "I"))
+ (match_operand:GPR 3 "reg_or_0_operand" "dJ"))]
+ "mips_use_ins_ext_p (operands[0], operands[1], operands[2])"
+ "<d>ins\t%0,%z3,%2,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
;; Unaligned word moves generated by the bit field patterns.
;;
;; As far as the rtl is concerned, both the left-part and right-part