diff options
author | Richard Sandiford <richard@codesourcery.com> | 2006-09-10 19:28:48 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2006-09-10 19:28:48 +0000 |
commit | 9226543b679c84014627a7bdec0503061b3af43d (patch) | |
tree | b9dc496a59b71728c2401746553b841ebcbcaa38 /gcc/config/mips | |
parent | ca6f2eefa4d61ec714e0d63d39e9120ad1e72e66 (diff) | |
download | gcc-9226543b679c84014627a7bdec0503061b3af43d.zip gcc-9226543b679c84014627a7bdec0503061b3af43d.tar.gz gcc-9226543b679c84014627a7bdec0503061b3af43d.tar.bz2 |
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_<load>l, mov_<load>r): Use it to check
that the size of the source matches the size of the destination.
(mov_<store>l, mov_<store>r): Likewise.
gcc/testsuite/
PR target/29006
* gcc.c-torture/execute/pr29006.c: New test.
From-SVN: r116822
Diffstat (limited to 'gcc/config/mips')
-rw-r--r-- | gcc/config/mips/mips-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 20 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 8 |
3 files changed, 23 insertions, 6 deletions
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>mode, operands[1])" "<load>l\t%0,%2" [(set_attr "type" "load") (set_attr "mode" "<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>mode, operands[1])" "<load>r\t%0,%2" [(set_attr "type" "load") (set_attr "mode" "<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>mode, operands[0])" "<store>l\t%z1,%2" [(set_attr "type" "store") (set_attr "mode" "<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>mode, operands[0])" "<store>r\t%z1,%2" [(set_attr "type" "store") (set_attr "mode" "<MODE>")]) |