From 9226543b679c84014627a7bdec0503061b3af43d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 10 Sep 2006 19:28:48 +0000 Subject: re PR target/29006 (Incorrect zeroing of unaligned 64-bit fields on MIPS targets) gcc/ PR target/29006 * config/mips/mips-protos.h (mips_mem_fits_mode_p): Declare. * config/mips/mips.c (mips_expand_unaligned_store): Use the mode returned by mode_for_size, rather than the mode of src itself, to choose between 32-bit and 64-bit patterns. (mips_mem_fits_mode_p): New function. * config/mips/mips.md (mov_l, mov_r): Use it to check that the size of the source matches the size of the destination. (mov_l, mov_r): Likewise. gcc/testsuite/ PR target/29006 * gcc.c-torture/execute/pr29006.c: New test. From-SVN: r116822 --- gcc/config/mips/mips-protos.h | 1 + gcc/config/mips/mips.c | 20 ++++++++++++++++++-- gcc/config/mips/mips.md | 8 ++++---- 3 files changed, 23 insertions(+), 6 deletions(-) (limited to 'gcc/config/mips') diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 090c2ef..da1ccea 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -189,6 +189,7 @@ extern void mips_va_start (tree, rtx); extern bool mips_expand_unaligned_load (rtx, rtx, unsigned int, int); extern bool mips_expand_unaligned_store (rtx, rtx, unsigned int, int); +extern bool mips_mem_fits_mode_p (enum machine_mode mode, rtx x); extern void override_options (void); extern void mips_conditional_register_usage (void); extern void mips_order_regs_for_local_alloc (void); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index ff8ce7d..91e90e0 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -4541,13 +4541,15 @@ bool mips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos) { rtx left, right; + enum machine_mode mode; if (!mips_get_unaligned_mem (&dest, width, bitpos, &left, &right)) return false; - src = gen_lowpart (mode_for_size (width, MODE_INT, 0), src); + mode = mode_for_size (width, MODE_INT, 0); + src = gen_lowpart (mode, src); - if (GET_MODE (src) == DImode) + if (mode == DImode) { emit_insn (gen_mov_sdl (dest, src, left)); emit_insn (gen_mov_sdr (copy_rtx (dest), copy_rtx (src), right)); @@ -4560,6 +4562,20 @@ mips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos) return true; } +/* Return true if X is a MEM with the same size as MODE. */ + +bool +mips_mem_fits_mode_p (enum machine_mode mode, rtx x) +{ + rtx size; + + if (!MEM_P (x)) + return false; + + size = MEM_SIZE (x); + return size && INTVAL (size) == GET_MODE_SIZE (mode); +} + /* 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 diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 655cfbf..a9b9add 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -2970,7 +2970,7 @@ (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m") (match_operand:QI 2 "memory_operand" "m")] UNSPEC_LOAD_LEFT))] - "!TARGET_MIPS16" + "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[1])" "l\t%0,%2" [(set_attr "type" "load") (set_attr "mode" "")]) @@ -2981,7 +2981,7 @@ (match_operand:QI 2 "memory_operand" "m") (match_operand:GPR 3 "register_operand" "0")] UNSPEC_LOAD_RIGHT))] - "!TARGET_MIPS16" + "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[1])" "r\t%0,%2" [(set_attr "type" "load") (set_attr "mode" "")]) @@ -2991,7 +2991,7 @@ (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ") (match_operand:QI 2 "memory_operand" "m")] UNSPEC_STORE_LEFT))] - "!TARGET_MIPS16" + "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[0])" "l\t%z1,%2" [(set_attr "type" "store") (set_attr "mode" "")]) @@ -3002,7 +3002,7 @@ (match_operand:QI 2 "memory_operand" "m") (match_dup 0)] UNSPEC_STORE_RIGHT))] - "!TARGET_MIPS16" + "!TARGET_MIPS16 && mips_mem_fits_mode_p (mode, operands[0])" "r\t%z1,%2" [(set_attr "type" "store") (set_attr "mode" "")]) -- cgit v1.1