1 ;; GCC machine description for i386 synchronization instructions.
3 ;; Free Software Foundation, Inc.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING. If not, write to
19 ;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 ;; Boston, MA 02110-1301, USA.
22 (define_mode_macro IMODE [QI HI SI (DI "TARGET_64BIT")])
23 (define_mode_attr modesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
24 (define_mode_attr modeconstraint [(QI "q") (HI "r") (SI "r") (DI "r")])
25 (define_mode_attr immconstraint [(QI "i") (HI "i") (SI "i") (DI "e")])
27 ;; ??? It would be possible to use cmpxchg8b on pentium for DImode
28 ;; changes. It's complicated because the insn uses ecx:ebx as the
29 ;; new value; note that the registers are reversed from the order
30 ;; that they'd be in with (reg:DI 2 ecx). Similarly for TImode
31 ;; data in 64-bit mode.
33 (define_insn "sync_compare_and_swap<mode>"
34 [(set (match_operand:IMODE 0 "register_operand" "=a")
35 (match_operand:IMODE 1 "memory_operand" "+m"))
37 (unspec_volatile:IMODE
39 (match_operand:IMODE 2 "register_operand" "a")
40 (match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
42 (clobber (reg:CC FLAGS_REG))]
44 "lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
46 (define_expand "sync_compare_and_swap_cc<mode>"
48 [(set (match_operand:IMODE 0 "register_operand" "")
49 (match_operand:IMODE 1 "memory_operand" ""))
51 (unspec_volatile:IMODE
53 (match_operand:IMODE 2 "register_operand" "")
54 (match_operand:IMODE 3 "register_operand" "")]
58 (unspec_volatile:IMODE
59 [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2)
63 operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG);
64 ix86_compare_op0 = operands[3];
65 ix86_compare_op1 = NULL;
66 ix86_compare_emitted = operands[4];
69 (define_insn "*sync_compare_and_swap_cc<mode>"
70 [(set (match_operand:IMODE 0 "register_operand" "=a")
71 (match_operand:IMODE 1 "memory_operand" "+m"))
73 (unspec_volatile:IMODE
75 (match_operand:IMODE 2 "register_operand" "a")
76 (match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
78 (set (reg:CCZ FLAGS_REG)
80 (unspec_volatile:IMODE
81 [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2)
84 "lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
86 (define_insn "sync_old_add<mode>"
87 [(set (match_operand:IMODE 0 "register_operand" "=<modeconstraint>")
88 (unspec_volatile:IMODE
89 [(match_operand:IMODE 1 "memory_operand" "+m")] UNSPECV_XCHG))
91 (plus:IMODE (match_dup 1)
92 (match_operand:IMODE 2 "register_operand" "0")))
93 (clobber (reg:CC FLAGS_REG))]
95 "lock\;xadd{<modesuffix>}\t{%0, %1|%1, %0}")
97 ;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space.
98 (define_insn "sync_lock_test_and_set<mode>"
99 [(set (match_operand:IMODE 0 "register_operand" "=<modeconstraint>")
100 (unspec_volatile:IMODE
101 [(match_operand:IMODE 1 "memory_operand" "+m")] UNSPECV_XCHG))
103 (match_operand:IMODE 2 "register_operand" "0"))]
105 "xchg{<modesuffix>}\t{%1, %0|%0, %1}")
107 (define_insn "sync_add<mode>"
108 [(set (match_operand:IMODE 0 "memory_operand" "=m")
109 (unspec_volatile:IMODE
110 [(plus:IMODE (match_dup 0)
111 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
113 (clobber (reg:CC FLAGS_REG))]
115 "lock\;add{<modesuffix>}\t{%1, %0|%0, %1}")
117 (define_insn "sync_sub<mode>"
118 [(set (match_operand:IMODE 0 "memory_operand" "=m")
119 (unspec_volatile:IMODE
120 [(minus:IMODE (match_dup 0)
121 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
123 (clobber (reg:CC FLAGS_REG))]
125 "lock\;sub{<modesuffix>}\t{%1, %0|%0, %1}")
127 (define_insn "sync_ior<mode>"
128 [(set (match_operand:IMODE 0 "memory_operand" "=m")
129 (unspec_volatile:IMODE
130 [(ior:IMODE (match_dup 0)
131 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
133 (clobber (reg:CC FLAGS_REG))]
135 "lock\;or{<modesuffix>}\t{%1, %0|%0, %1}")
137 (define_insn "sync_and<mode>"
138 [(set (match_operand:IMODE 0 "memory_operand" "=m")
139 (unspec_volatile:IMODE
140 [(and:IMODE (match_dup 0)
141 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
143 (clobber (reg:CC FLAGS_REG))]
145 "lock\;and{<modesuffix>}\t{%1, %0|%0, %1}")
147 (define_insn "sync_xor<mode>"
148 [(set (match_operand:IMODE 0 "memory_operand" "=m")
149 (unspec_volatile:IMODE
150 [(xor:IMODE (match_dup 0)
151 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
153 (clobber (reg:CC FLAGS_REG))]
155 "lock\;xor{<modesuffix>}\t{%1, %0|%0, %1}")