diff options
author | Martynas Venckus <martynas@cvs.openbsd.org> | 2012-12-10 18:06:13 +0000 |
---|---|---|
committer | Martynas Venckus <martynas@cvs.openbsd.org> | 2012-12-10 18:06:13 +0000 |
commit | b0df29af882c4d620b5f6e88a55df70741281ad7 (patch) | |
tree | d0c12eb6a7c4a80fa0316cadf39c44c8a49852d1 | |
parent | 8a035085bc3ae8fafd05f43d62117d440347efe8 (diff) |
Fix unaligned memory loads on Alpha. GCC used to generate them in
the following manner:
([reg:A & -8] << (64 - (((reg:FP+reg:B) & 0x7) << 3))) >> 56
This fails when we're doing loads with the offset from the frame
pointer %8. Since it's aligned, optimizer makes it a zero. The
correct expression is:
([reg:A & -8] << (56 - (((reg:FP+reg:B-1) & 0x7) << 3))) >> 56
This is actually a 13-year-old bug. Checked by Miod; a few files
in the kernel were affected. Spotted with SSP for Alpha.
OK miod@. Tested by naddy@.
-rw-r--r-- | gnu/gcc/gcc/config/alpha/alpha.md | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/gnu/gcc/gcc/config/alpha/alpha.md b/gnu/gcc/gcc/config/alpha/alpha.md index 17d4c77e69d..9dd70507427 100644 --- a/gnu/gcc/gcc/config/alpha/alpha.md +++ b/gnu/gcc/gcc/config/alpha/alpha.md @@ -1701,9 +1701,10 @@ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8)))) (set (match_dup 4) (ashift:DI (match_dup 3) - (minus:DI (const_int 64) + (minus:DI (const_int 56) (ashift:DI - (and:DI (match_dup 2) (const_int 7)) + (and:DI (plus:DI (match_dup 2) (const_int -1)) + (const_int 7)) (const_int 3))))) (set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_dup 4) (const_int 56)))] @@ -1751,9 +1752,10 @@ (mem:DI (and:DI (match_operand:DI 1 "" "") (const_int -8)))) (set (match_dup 4) (ashift:DI (match_dup 3) - (minus:DI (const_int 64) + (minus:DI (const_int 56) (ashift:DI - (and:DI (match_dup 2) (const_int 7)) + (and:DI (plus:DI (match_dup 2) (const_int -1)) + (const_int 7)) (const_int 3))))) (set (match_operand:DI 0 "register_operand" "") (ashiftrt:DI (match_dup 4) (const_int 48)))] @@ -1866,10 +1868,11 @@ [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (minus:DI (const_int 64) + (minus:DI (const_int 56) (ashift:DI (and:DI - (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int -1)) (const_int 7)) (const_int 3)))))] "! WORDS_BIG_ENDIAN" @@ -1895,10 +1898,11 @@ (ashift:DI (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") (const_int 2147483647)) - (minus:DI (const_int 64) + (minus:DI (const_int 56) (ashift:DI (and:DI - (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int -1)) (const_int 7)) (const_int 3)))))] "! WORDS_BIG_ENDIAN" @@ -1927,10 +1931,11 @@ (ashift:DI (and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") (const_int 65535)) - (minus:DI (const_int 64) + (minus:DI (const_int 56) (ashift:DI (and:DI - (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI") + (const_int -1)) (const_int 7)) (const_int 3)))))] "! WORDS_BIG_ENDIAN" |