diff options
author | 2015-12-01 15:18:29 +0000 | |
---|---|---|
committer | 2015-12-01 15:18:29 +0000 | |
commit | 697a24b00b9fb4ee95e42175a8cfed5d34a134c7 (patch) | |
tree | 99093afe168357169772e2f5c0bf05e01c4d98b4 | |
parent | Document that "tty" provides read-write access to /dev/tty too. (diff) | |
download | wireguard-openbsd-697a24b00b9fb4ee95e42175a8cfed5d34a134c7.tar.xz wireguard-openbsd-697a24b00b9fb4ee95e42175a8cfed5d34a134c7.zip |
Fix __sync_val_compare_and_swap_8() on i386 for code compiled with -fPIC.
In some cases GCC would generate a cmpxchg8b instruction with a memory
reference that used %ebx. This is wrong (and will almost certainly result
in SIGSEGV). This fix uses a new memory constraint "W" to prevent the use
of %ebx in this case. This differs from the approach taken by upstream so
there are no GPLv3 issues here.
Fixes the Mesa i965 dri module on i386.
ok jsg@
-rw-r--r-- | gnu/gcc/gcc/config/i386/constraints.md | 4 | ||||
-rw-r--r-- | gnu/gcc/gcc/config/i386/i386.c | 28 | ||||
-rw-r--r-- | gnu/gcc/gcc/config/i386/sync.md | 4 |
3 files changed, 34 insertions, 2 deletions
diff --git a/gnu/gcc/gcc/config/i386/constraints.md b/gnu/gcc/gcc/config/i386/constraints.md index 0ab4995f3b8..149a69878b4 100644 --- a/gnu/gcc/gcc/config/i386/constraints.md +++ b/gnu/gcc/gcc/config/i386/constraints.md @@ -150,3 +150,7 @@ to fit that range (for immediate operands in zero-extending x86-64 instructions)." (match_operand 0 "x86_64_zext_immediate_operand")) + +(define_memory_constraint "W" + "CMPXCHG8B memory reference." + (match_test "cmpxchg8b_mem_constraint (op)")) diff --git a/gnu/gcc/gcc/config/i386/i386.c b/gnu/gcc/gcc/config/i386/i386.c index 6fab6d81312..6f77b9ba5a7 100644 --- a/gnu/gcc/gcc/config/i386/i386.c +++ b/gnu/gcc/gcc/config/i386/i386.c @@ -4719,6 +4719,34 @@ standard_sse_constant_opcode (rtx insn, rtx x) gcc_unreachable (); } +int +cmpxchg8b_mem_constraint (rtx op) +{ + struct ix86_address parts; + + if (TARGET_64BIT || !flag_pic) + return 1; + + if (GET_CODE (op) != MEM) + return 0; + if (!ix86_decompose_address (XEXP (op, 0), &parts)) + return 0; + + if (parts.base && GET_CODE (parts.base) == SUBREG) + parts.base = SUBREG_REG (parts.base); + if (parts.index && GET_CODE (parts.index) == SUBREG) + parts.index = SUBREG_REG (parts.index); + + if (parts.base && REG_P (parts.base) + && REGNO_REG_CLASS (REGNO (parts.base)) == BREG) + return 0; + if (parts.index && REG_P (parts.index) + && REGNO_REG_CLASS (REGNO (parts.index)) == BREG) + return 0; + + return 1; +} + /* Returns 1 if OP contains a symbol reference */ int diff --git a/gnu/gcc/gcc/config/i386/sync.md b/gnu/gcc/gcc/config/i386/sync.md index 8c2fdb230b0..30566450fa4 100644 --- a/gnu/gcc/gcc/config/i386/sync.md +++ b/gnu/gcc/gcc/config/i386/sync.md @@ -109,7 +109,7 @@ ;; are just esi and edi. (define_insn "*sync_double_compare_and_swapdi_pic" [(set (match_operand:DI 0 "register_operand" "=A") - (match_operand:DI 1 "memory_operand" "+m")) + (match_operand:DI 1 "memory_operand" "+W")) (set (match_dup 1) (unspec_volatile:DI [(match_dup 1) @@ -202,7 +202,7 @@ ;; operand 3. (define_insn "*sync_double_compare_and_swap_ccdi_pic" [(set (match_operand:DI 0 "register_operand" "=A") - (match_operand:DI 1 "memory_operand" "+m")) + (match_operand:DI 1 "memory_operand" "+W")) (set (match_dup 1) (unspec_volatile:DI [(match_dup 1) |