aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/mips
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2012-11-18 17:34:06 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2012-11-18 17:34:06 +0000
commitd2eeb2d179a4353af0a8ff989222301c4f7dc11b (patch)
tree2d71577e02e248f2a39d8d852e69ab9ea07433d6 /gcc/config/mips
parentfcdd52b73c0b23bffd5ce5ba591f994547333429 (diff)
downloadgcc-d2eeb2d179a4353af0a8ff989222301c4f7dc11b.zip
gcc-d2eeb2d179a4353af0a8ff989222301c4f7dc11b.tar.gz
gcc-d2eeb2d179a4353af0a8ff989222301c4f7dc11b.tar.bz2
gcc/
* doc/md.texi (extv@var{m}, extvmisalign@var{m}, extzv@var{m}) (extzvmisalign@var{m}, insv@var{m}, insvmisalign@var{m}): Document. (insv, extv, extzv): Deprecate. * optabs.def (insv_optab, extv_optab, extzv_optab) (insvmisalign_optab, extvmisalign_optab, extzvmisalign_optab): New optabs. * optabs.c (get_optab_extraction_insn): New function. (get_extraction_insn): Use it. * config/mips/mips.md (extv): Split into... (extvmisalign<mode>, extv<mode>): ...these new patterns. Rename existing extv<mode> pattern to... (*extv<mode>): ...this. (extzv): Split into... (extzvmisalign<mode>, extzv<mode>): ...these new patterns. Rename existing extzv<mode> pattern to... (*extzv<mode>): ...this. (insv): Split into... (insvmisalign<mode>, insv<mode>): ...these new patterns. Rename existing insv<mode> pattern to... (*insv<mode>): ...this. Use const_int_operand rather than immediate_operand. * config/mips/mips.c (mips_block_move_straight): Use set_mem_size to set the size of BLKmode accesses. (mips_get_unaligned_mem): Require OP0 to be a BLKmode memory, turning it from an "rtx *" to an rtx. (mips_expand_ext_as_unaligned_load): Simplify for new optab interface. Update call to mips_get_unaligned_mem. (mips_expand_ins_as_unaligned_store): Update call to mips_get_unaligned_mem. From-SVN: r193606
Diffstat (limited to 'gcc/config/mips')
-rw-r--r--gcc/config/mips/mips.c48
-rw-r--r--gcc/config/mips/mips.md115
2 files changed, 69 insertions, 94 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 78c5a88..b6a2290 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -7096,6 +7096,7 @@ mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
else
{
rtx part = adjust_address (src, BLKmode, offset);
+ set_mem_size (part, delta);
if (!mips_expand_ext_as_unaligned_load (regs[i], part, bits, 0, 0))
gcc_unreachable ();
}
@@ -7108,6 +7109,7 @@ mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
else
{
rtx part = adjust_address (dest, BLKmode, offset);
+ set_mem_size (part, delta);
if (!mips_expand_ins_as_unaligned_store (part, regs[i], bits, 0))
gcc_unreachable ();
}
@@ -7359,10 +7361,8 @@ mips_expand_atomic_qihi (union mips_gen_fn_ptrs generator,
}
/* Return true if it is possible to use left/right accesses for a
- bitfield of WIDTH bits starting BITPOS bits into *OP. When
- returning true, update *OP, *LEFT and *RIGHT as follows:
-
- *OP is a BLKmode reference to the whole field.
+ bitfield of WIDTH bits starting BITPOS bits into BLKmode memory OP.
+ When returning true, update *LEFT and *RIGHT as follows:
*LEFT is a QImode reference to the first byte if big endian or
the last byte if little endian. This address can be used in the
@@ -7372,16 +7372,11 @@ mips_expand_atomic_qihi (union mips_gen_fn_ptrs generator,
can be used in the patterning right-side instruction. */
static bool
-mips_get_unaligned_mem (rtx *op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos,
+mips_get_unaligned_mem (rtx op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos,
rtx *left, rtx *right)
{
rtx first, last;
- /* Check that the operand really is a MEM. Not all the extv and
- extzv predicates are checked. */
- if (!MEM_P (*op))
- return false;
-
/* Check that the size is valid. */
if (width != 32 && (!TARGET_64BIT || width != 64))
return false;
@@ -7394,20 +7389,12 @@ mips_get_unaligned_mem (rtx *op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos,
/* Reject aligned bitfields: we want to use a normal load or store
instead of a left/right pair. */
- if (MEM_ALIGN (*op) >= width)
+ if (MEM_ALIGN (op) >= width)
return false;
- /* Create a copy of *OP that refers to the whole field. This also has
- the effect of legitimizing *OP's address for BLKmode, possibly
- simplifying it. */
- *op = copy_rtx (adjust_address (*op, BLKmode, 0));
- set_mem_size (*op, width / BITS_PER_UNIT);
-
- /* Get references to both ends of the field. We deliberately don't
- use the original QImode *OP for FIRST since the new BLKmode one
- might have a simpler address. */
- first = adjust_address (*op, QImode, 0);
- last = adjust_address (*op, QImode, width / BITS_PER_UNIT - 1);
+ /* Get references to both ends of the field. */
+ first = adjust_address (op, QImode, 0);
+ last = adjust_address (op, QImode, width / BITS_PER_UNIT - 1);
/* Allocate to LEFT and RIGHT according to endianness. LEFT should
correspond to the MSB and RIGHT to the LSB. */
@@ -7435,14 +7422,6 @@ mips_expand_ext_as_unaligned_load (rtx dest, rtx src, HOST_WIDE_INT width,
rtx dest1 = NULL_RTX;
/* If TARGET_64BIT, the destination of a 32-bit "extz" or "extzv" will
- be a paradoxical word_mode subreg. This is the only case in which
- we allow the destination to be larger than the source. */
- if (GET_CODE (dest) == SUBREG
- && GET_MODE (dest) == DImode
- && GET_MODE (SUBREG_REG (dest)) == SImode)
- dest = SUBREG_REG (dest);
-
- /* If TARGET_64BIT, the destination of a 32-bit "extz" or "extzv" will
be a DImode, create a new temp and emit a zero extend at the end. */
if (GET_MODE (dest) == DImode
&& REG_P (dest)
@@ -7452,12 +7431,7 @@ mips_expand_ext_as_unaligned_load (rtx dest, rtx src, HOST_WIDE_INT width,
dest = gen_reg_rtx (SImode);
}
- /* After the above adjustment, the destination must be the same
- width as the source. */
- if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
- return false;
-
- if (!mips_get_unaligned_mem (&src, width, bitpos, &left, &right))
+ if (!mips_get_unaligned_mem (src, width, bitpos, &left, &right))
return false;
temp = gen_reg_rtx (GET_MODE (dest));
@@ -7499,7 +7473,7 @@ mips_expand_ins_as_unaligned_store (rtx dest, rtx src, HOST_WIDE_INT width,
rtx left, right;
enum machine_mode mode;
- if (!mips_get_unaligned_mem (&dest, width, bitpos, &left, &right))
+ if (!mips_get_unaligned_mem (dest, width, bitpos, &left, &right))
return false;
mode = mode_for_size (width, MODE_INT, 0);
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index f6a1312..a3aa922 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -3777,11 +3777,11 @@
;; Bit field extract patterns which use lwl/lwr or ldl/ldr.
-(define_expand "extv"
- [(set (match_operand 0 "register_operand")
- (sign_extract (match_operand 1 "nonimmediate_operand")
- (match_operand 2 "const_int_operand")
- (match_operand 3 "const_int_operand")))]
+(define_expand "extvmisalign<mode>"
+ [(set (match_operand:GPR 0 "register_operand")
+ (sign_extract:GPR (match_operand:BLK 1 "memory_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
"!TARGET_MIPS16"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
@@ -3789,22 +3789,22 @@
INTVAL (operands[3]),
/*unsigned=*/ false))
DONE;
- else if (register_operand (operands[1], GET_MODE (operands[0]))
- && ISA_HAS_EXTS && UINTVAL (operands[2]) <= 32)
- {
- if (GET_MODE (operands[0]) == DImode)
- emit_insn (gen_extvdi (operands[0], operands[1], operands[2],
- operands[3]));
- else
- emit_insn (gen_extvsi (operands[0], operands[1], operands[2],
- operands[3]));
- DONE;
- }
else
FAIL;
})
-(define_insn "extv<mode>"
+(define_expand "extv<mode>"
+ [(set (match_operand:GPR 0 "register_operand")
+ (sign_extract:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
+ "ISA_HAS_EXTS"
+{
+ if (UINTVAL (operands[2]) > 32)
+ FAIL;
+})
+
+(define_insn "*extv<mode>"
[(set (match_operand:GPR 0 "register_operand" "=d")
(sign_extract:GPR (match_operand:GPR 1 "register_operand" "d")
(match_operand 2 "const_int_operand" "")
@@ -3814,35 +3814,35 @@
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
-
-(define_expand "extzv"
- [(set (match_operand 0 "register_operand")
- (zero_extract (match_operand 1 "nonimmediate_operand")
- (match_operand 2 "const_int_operand")
- (match_operand 3 "const_int_operand")))]
+(define_expand "extzvmisalign<mode>"
+ [(set (match_operand:GPR 0 "register_operand")
+ (zero_extract:GPR (match_operand:BLK 1 "memory_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
"!TARGET_MIPS16"
{
if (mips_expand_ext_as_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]),
INTVAL (operands[3]),
- /*unsigned=*/true))
+ /*unsigned=*/ true))
DONE;
- else if (mips_use_ins_ext_p (operands[1], INTVAL (operands[2]),
- INTVAL (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>"
+(define_expand "extzv<mode>"
+ [(set (match_operand:GPR 0 "register_operand")
+ (zero_extract:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand 2 "const_int_operand")
+ (match_operand 3 "const_int_operand")))]
+ ""
+{
+ if (!mips_use_ins_ext_p (operands[1], INTVAL (operands[2]),
+ INTVAL (operands[3])))
+ 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 2 "const_int_operand" "")
@@ -3865,36 +3865,37 @@
(set_attr "mode" "SI")])
-(define_expand "insv"
- [(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"))]
+(define_expand "insvmisalign<mode>"
+ [(set (zero_extract:GPR (match_operand:BLK 0 "memory_operand")
+ (match_operand 1 "const_int_operand")
+ (match_operand 2 "const_int_operand"))
+ (match_operand:GPR 3 "reg_or_0_operand"))]
"!TARGET_MIPS16"
{
if (mips_expand_ins_as_unaligned_store (operands[0], operands[3],
INTVAL (operands[1]),
INTVAL (operands[2])))
DONE;
- else if (mips_use_ins_ext_p (operands[0], INTVAL (operands[1]),
- INTVAL (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;
+ else
+ FAIL;
+})
+
+(define_expand "insv<mode>"
+ [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand")
+ (match_operand 1 "const_int_operand")
+ (match_operand 2 "const_int_operand"))
+ (match_operand:GPR 3 "reg_or_0_operand"))]
+ ""
+{
+ if (!mips_use_ins_ext_p (operands[0], INTVAL (operands[1]),
+ INTVAL (operands[2])))
+ FAIL;
})
-(define_insn "insv<mode>"
+(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:SI 1 "const_int_operand" "")
+ (match_operand:SI 2 "const_int_operand" ""))
(match_operand:GPR 3 "reg_or_0_operand" "dJ"))]
"mips_use_ins_ext_p (operands[0], INTVAL (operands[1]),
INTVAL (operands[2]))"