annotate gcc/config/riscv/sync.md @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ;; Machine description for RISC-V atomic operations.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 ;; Copyright (C) 2011-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 ;; Contributed by Andrew Waterman (andrew@sifive.com).
kono
parents:
diff changeset
4 ;; Based on MIPS target for GNU compiler.
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 ;; This file is part of GCC.
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 ;; GCC is free software; you can redistribute it and/or modify
kono
parents:
diff changeset
9 ;; it under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
10 ;; the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
11 ;; any later version.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 ;; GCC is distributed in the hope that it will be useful,
kono
parents:
diff changeset
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kono
parents:
diff changeset
16 ;; GNU General Public License for more details.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 ;; You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
19 ;; along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
20 ;; <http://www.gnu.org/licenses/>.
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 (define_c_enum "unspec" [
kono
parents:
diff changeset
23 UNSPEC_COMPARE_AND_SWAP
kono
parents:
diff changeset
24 UNSPEC_SYNC_OLD_OP
kono
parents:
diff changeset
25 UNSPEC_SYNC_EXCHANGE
kono
parents:
diff changeset
26 UNSPEC_ATOMIC_STORE
kono
parents:
diff changeset
27 UNSPEC_MEMORY_BARRIER
kono
parents:
diff changeset
28 ])
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 (define_code_iterator any_atomic [plus ior xor and])
kono
parents:
diff changeset
31 (define_code_attr atomic_optab
kono
parents:
diff changeset
32 [(plus "add") (ior "or") (xor "xor") (and "and")])
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 ;; Memory barriers.
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 (define_expand "mem_thread_fence"
kono
parents:
diff changeset
37 [(match_operand:SI 0 "const_int_operand" "")] ;; model
kono
parents:
diff changeset
38 ""
kono
parents:
diff changeset
39 {
kono
parents:
diff changeset
40 if (INTVAL (operands[0]) != MEMMODEL_RELAXED)
kono
parents:
diff changeset
41 {
kono
parents:
diff changeset
42 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
kono
parents:
diff changeset
43 MEM_VOLATILE_P (mem) = 1;
kono
parents:
diff changeset
44 emit_insn (gen_mem_thread_fence_1 (mem, operands[0]));
kono
parents:
diff changeset
45 }
kono
parents:
diff changeset
46 DONE;
kono
parents:
diff changeset
47 })
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 ;; Until the RISC-V memory model (hence its mapping from C++) is finalized,
kono
parents:
diff changeset
50 ;; conservatively emit a full FENCE.
kono
parents:
diff changeset
51 (define_insn "mem_thread_fence_1"
kono
parents:
diff changeset
52 [(set (match_operand:BLK 0 "" "")
kono
parents:
diff changeset
53 (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
kono
parents:
diff changeset
54 (match_operand:SI 1 "const_int_operand" "")] ;; model
kono
parents:
diff changeset
55 ""
kono
parents:
diff changeset
56 "fence\tiorw,iorw")
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 ;; Atomic memory operations.
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 ;; Implement atomic stores with amoswap. Fall back to fences for atomic loads.
kono
parents:
diff changeset
61 (define_insn "atomic_store<mode>"
kono
parents:
diff changeset
62 [(set (match_operand:GPR 0 "memory_operand" "=A")
kono
parents:
diff changeset
63 (unspec_volatile:GPR
kono
parents:
diff changeset
64 [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
kono
parents:
diff changeset
65 (match_operand:SI 2 "const_int_operand")] ;; model
kono
parents:
diff changeset
66 UNSPEC_ATOMIC_STORE))]
kono
parents:
diff changeset
67 "TARGET_ATOMIC"
kono
parents:
diff changeset
68 "%F2amoswap.<amo>%A2 zero,%z1,%0"
kono
parents:
diff changeset
69 [(set (attr "length") (const_int 8))])
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 (define_insn "atomic_<atomic_optab><mode>"
kono
parents:
diff changeset
72 [(set (match_operand:GPR 0 "memory_operand" "+A")
kono
parents:
diff changeset
73 (unspec_volatile:GPR
kono
parents:
diff changeset
74 [(any_atomic:GPR (match_dup 0)
kono
parents:
diff changeset
75 (match_operand:GPR 1 "reg_or_0_operand" "rJ"))
kono
parents:
diff changeset
76 (match_operand:SI 2 "const_int_operand")] ;; model
kono
parents:
diff changeset
77 UNSPEC_SYNC_OLD_OP))]
kono
parents:
diff changeset
78 "TARGET_ATOMIC"
kono
parents:
diff changeset
79 "%F2amo<insn>.<amo>%A2 zero,%z1,%0"
kono
parents:
diff changeset
80 [(set (attr "length") (const_int 8))])
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 (define_insn "atomic_fetch_<atomic_optab><mode>"
kono
parents:
diff changeset
83 [(set (match_operand:GPR 0 "register_operand" "=&r")
kono
parents:
diff changeset
84 (match_operand:GPR 1 "memory_operand" "+A"))
kono
parents:
diff changeset
85 (set (match_dup 1)
kono
parents:
diff changeset
86 (unspec_volatile:GPR
kono
parents:
diff changeset
87 [(any_atomic:GPR (match_dup 1)
kono
parents:
diff changeset
88 (match_operand:GPR 2 "reg_or_0_operand" "rJ"))
kono
parents:
diff changeset
89 (match_operand:SI 3 "const_int_operand")] ;; model
kono
parents:
diff changeset
90 UNSPEC_SYNC_OLD_OP))]
kono
parents:
diff changeset
91 "TARGET_ATOMIC"
kono
parents:
diff changeset
92 "%F3amo<insn>.<amo>%A3 %0,%z2,%1"
kono
parents:
diff changeset
93 [(set (attr "length") (const_int 8))])
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 (define_insn "atomic_exchange<mode>"
kono
parents:
diff changeset
96 [(set (match_operand:GPR 0 "register_operand" "=&r")
kono
parents:
diff changeset
97 (unspec_volatile:GPR
kono
parents:
diff changeset
98 [(match_operand:GPR 1 "memory_operand" "+A")
kono
parents:
diff changeset
99 (match_operand:SI 3 "const_int_operand")] ;; model
kono
parents:
diff changeset
100 UNSPEC_SYNC_EXCHANGE))
kono
parents:
diff changeset
101 (set (match_dup 1)
kono
parents:
diff changeset
102 (match_operand:GPR 2 "register_operand" "0"))]
kono
parents:
diff changeset
103 "TARGET_ATOMIC"
kono
parents:
diff changeset
104 "%F3amoswap.<amo>%A3 %0,%z2,%1"
kono
parents:
diff changeset
105 [(set (attr "length") (const_int 8))])
kono
parents:
diff changeset
106
kono
parents:
diff changeset
107 (define_insn "atomic_cas_value_strong<mode>"
kono
parents:
diff changeset
108 [(set (match_operand:GPR 0 "register_operand" "=&r")
kono
parents:
diff changeset
109 (match_operand:GPR 1 "memory_operand" "+A"))
kono
parents:
diff changeset
110 (set (match_dup 1)
kono
parents:
diff changeset
111 (unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ")
kono
parents:
diff changeset
112 (match_operand:GPR 3 "reg_or_0_operand" "rJ")
kono
parents:
diff changeset
113 (match_operand:SI 4 "const_int_operand") ;; mod_s
kono
parents:
diff changeset
114 (match_operand:SI 5 "const_int_operand")] ;; mod_f
kono
parents:
diff changeset
115 UNSPEC_COMPARE_AND_SWAP))
kono
parents:
diff changeset
116 (clobber (match_scratch:GPR 6 "=&r"))]
kono
parents:
diff changeset
117 "TARGET_ATOMIC"
kono
parents:
diff changeset
118 "%F5 1: lr.<amo>%A5 %0,%1; bne %0,%z2,1f; sc.<amo>%A4 %6,%z3,%1; bnez %6,1b; 1:"
kono
parents:
diff changeset
119 [(set (attr "length") (const_int 20))])
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 (define_expand "atomic_compare_and_swap<mode>"
kono
parents:
diff changeset
122 [(match_operand:SI 0 "register_operand" "") ;; bool output
kono
parents:
diff changeset
123 (match_operand:GPR 1 "register_operand" "") ;; val output
kono
parents:
diff changeset
124 (match_operand:GPR 2 "memory_operand" "") ;; memory
kono
parents:
diff changeset
125 (match_operand:GPR 3 "reg_or_0_operand" "") ;; expected value
kono
parents:
diff changeset
126 (match_operand:GPR 4 "reg_or_0_operand" "") ;; desired value
kono
parents:
diff changeset
127 (match_operand:SI 5 "const_int_operand" "") ;; is_weak
kono
parents:
diff changeset
128 (match_operand:SI 6 "const_int_operand" "") ;; mod_s
kono
parents:
diff changeset
129 (match_operand:SI 7 "const_int_operand" "")] ;; mod_f
kono
parents:
diff changeset
130 "TARGET_ATOMIC"
kono
parents:
diff changeset
131 {
kono
parents:
diff changeset
132 emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
kono
parents:
diff changeset
133 operands[3], operands[4],
kono
parents:
diff changeset
134 operands[6], operands[7]));
kono
parents:
diff changeset
135
kono
parents:
diff changeset
136 rtx compare = operands[1];
kono
parents:
diff changeset
137 if (operands[3] != const0_rtx)
kono
parents:
diff changeset
138 {
kono
parents:
diff changeset
139 rtx difference = gen_rtx_MINUS (<MODE>mode, operands[1], operands[3]);
kono
parents:
diff changeset
140 compare = gen_reg_rtx (<MODE>mode);
kono
parents:
diff changeset
141 emit_insn (gen_rtx_SET (compare, difference));
kono
parents:
diff changeset
142 }
kono
parents:
diff changeset
143
kono
parents:
diff changeset
144 if (word_mode != <MODE>mode)
kono
parents:
diff changeset
145 {
kono
parents:
diff changeset
146 rtx reg = gen_reg_rtx (word_mode);
kono
parents:
diff changeset
147 emit_insn (gen_rtx_SET (reg, gen_rtx_SIGN_EXTEND (word_mode, compare)));
kono
parents:
diff changeset
148 compare = reg;
kono
parents:
diff changeset
149 }
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 emit_insn (gen_rtx_SET (operands[0], gen_rtx_EQ (SImode, compare, const0_rtx)));
kono
parents:
diff changeset
152 DONE;
kono
parents:
diff changeset
153 })
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 (define_expand "atomic_test_and_set"
kono
parents:
diff changeset
156 [(match_operand:QI 0 "register_operand" "") ;; bool output
kono
parents:
diff changeset
157 (match_operand:QI 1 "memory_operand" "+A") ;; memory
kono
parents:
diff changeset
158 (match_operand:SI 2 "const_int_operand" "")] ;; model
kono
parents:
diff changeset
159 "TARGET_ATOMIC"
kono
parents:
diff changeset
160 {
kono
parents:
diff changeset
161 /* We have no QImode atomics, so use the address LSBs to form a mask,
kono
parents:
diff changeset
162 then use an aligned SImode atomic. */
kono
parents:
diff changeset
163 rtx result = operands[0];
kono
parents:
diff changeset
164 rtx mem = operands[1];
kono
parents:
diff changeset
165 rtx model = operands[2];
kono
parents:
diff changeset
166 rtx addr = force_reg (Pmode, XEXP (mem, 0));
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 rtx aligned_addr = gen_reg_rtx (Pmode);
kono
parents:
diff changeset
169 emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, GEN_INT (-4)));
kono
parents:
diff changeset
170
kono
parents:
diff changeset
171 rtx aligned_mem = change_address (mem, SImode, aligned_addr);
kono
parents:
diff changeset
172 set_mem_alias_set (aligned_mem, 0);
kono
parents:
diff changeset
173
kono
parents:
diff changeset
174 rtx offset = gen_reg_rtx (SImode);
kono
parents:
diff changeset
175 emit_move_insn (offset, gen_rtx_AND (SImode, gen_lowpart (SImode, addr),
kono
parents:
diff changeset
176 GEN_INT (3)));
kono
parents:
diff changeset
177
kono
parents:
diff changeset
178 rtx tmp = gen_reg_rtx (SImode);
kono
parents:
diff changeset
179 emit_move_insn (tmp, GEN_INT (1));
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 rtx shmt = gen_reg_rtx (SImode);
kono
parents:
diff changeset
182 emit_move_insn (shmt, gen_rtx_ASHIFT (SImode, offset, GEN_INT (3)));
kono
parents:
diff changeset
183
kono
parents:
diff changeset
184 rtx word = gen_reg_rtx (SImode);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
185 emit_move_insn (word, gen_rtx_ASHIFT (SImode, tmp,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
186 gen_lowpart (QImode, shmt)));
111
kono
parents:
diff changeset
187
kono
parents:
diff changeset
188 tmp = gen_reg_rtx (SImode);
kono
parents:
diff changeset
189 emit_insn (gen_atomic_fetch_orsi (tmp, aligned_mem, word, model));
kono
parents:
diff changeset
190
kono
parents:
diff changeset
191 emit_move_insn (gen_lowpart (SImode, result),
kono
parents:
diff changeset
192 gen_rtx_LSHIFTRT (SImode, tmp,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
193 gen_lowpart (QImode, shmt)));
111
kono
parents:
diff changeset
194 DONE;
kono
parents:
diff changeset
195 })