xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86InstrShiftRotate.td (revision 9f23cbd6cae82fd77edfad7173432fa8dccd0a95)
1//===-- X86InstrShiftRotate.td - Shift and Rotate Instrs ---*- tablegen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file describes the shift and rotate instructions.
10//
11//===----------------------------------------------------------------------===//
12
13// FIXME: Someone needs to smear multipattern goodness all over this file.
14
15let Defs = [EFLAGS] in {
16
17let Constraints = "$src1 = $dst" in {
18let Uses = [CL], SchedRW = [WriteShiftCL] in {
19def SHL8rCL  : I<0xD2, MRM4r, (outs GR8 :$dst), (ins GR8 :$src1),
20                 "shl{b}\t{%cl, $dst|$dst, cl}",
21                 [(set GR8:$dst, (shl GR8:$src1, CL))]>;
22def SHL16rCL : I<0xD3, MRM4r, (outs GR16:$dst), (ins GR16:$src1),
23                 "shl{w}\t{%cl, $dst|$dst, cl}",
24                 [(set GR16:$dst, (shl GR16:$src1, CL))]>, OpSize16;
25def SHL32rCL : I<0xD3, MRM4r, (outs GR32:$dst), (ins GR32:$src1),
26                 "shl{l}\t{%cl, $dst|$dst, cl}",
27                 [(set GR32:$dst, (shl GR32:$src1, CL))]>, OpSize32;
28def SHL64rCL : RI<0xD3, MRM4r, (outs GR64:$dst), (ins GR64:$src1),
29                  "shl{q}\t{%cl, $dst|$dst, cl}",
30                  [(set GR64:$dst, (shl GR64:$src1, CL))]>;
31} // Uses = [CL], SchedRW
32
33let SchedRW = [WriteShift] in {
34let isConvertibleToThreeAddress = 1 in {   // Can transform into LEA.
35def SHL8ri   : Ii8<0xC0, MRM4r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2),
36                   "shl{b}\t{$src2, $dst|$dst, $src2}",
37                   [(set GR8:$dst, (shl GR8:$src1, (i8 imm:$src2)))]>;
38
39def SHL16ri  : Ii8<0xC1, MRM4r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2),
40                   "shl{w}\t{$src2, $dst|$dst, $src2}",
41                   [(set GR16:$dst, (shl GR16:$src1, (i8 imm:$src2)))]>,
42                   OpSize16;
43def SHL32ri  : Ii8<0xC1, MRM4r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2),
44                   "shl{l}\t{$src2, $dst|$dst, $src2}",
45                   [(set GR32:$dst, (shl GR32:$src1, (i8 imm:$src2)))]>,
46                   OpSize32;
47def SHL64ri  : RIi8<0xC1, MRM4r, (outs GR64:$dst),
48                    (ins GR64:$src1, u8imm:$src2),
49                    "shl{q}\t{$src2, $dst|$dst, $src2}",
50                    [(set GR64:$dst, (shl GR64:$src1, (i8 imm:$src2)))]>;
51} // isConvertibleToThreeAddress = 1
52
53// NOTE: We don't include patterns for shifts of a register by one, because
54// 'add reg,reg' is cheaper (and we have a Pat pattern for shift-by-one).
55let hasSideEffects = 0 in {
56def SHL8r1   : I<0xD0, MRM4r, (outs GR8:$dst), (ins GR8:$src1),
57                 "shl{b}\t$dst", []>;
58def SHL16r1  : I<0xD1, MRM4r, (outs GR16:$dst), (ins GR16:$src1),
59                 "shl{w}\t$dst", []>, OpSize16;
60def SHL32r1  : I<0xD1, MRM4r, (outs GR32:$dst), (ins GR32:$src1),
61                 "shl{l}\t$dst", []>, OpSize32;
62def SHL64r1  : RI<0xD1, MRM4r, (outs GR64:$dst), (ins GR64:$src1),
63                 "shl{q}\t$dst", []>;
64} // hasSideEffects = 0
65} // SchedRW
66} // Constraints = "$src = $dst"
67
68// FIXME: Why do we need an explicit "Uses = [CL]" when the instr has a pattern
69// using CL?
70let Uses = [CL], SchedRW = [WriteShiftCLLd, WriteRMW] in {
71def SHL8mCL  : I<0xD2, MRM4m, (outs), (ins i8mem :$dst),
72                 "shl{b}\t{%cl, $dst|$dst, cl}",
73                 [(store (shl (loadi8 addr:$dst), CL), addr:$dst)]>;
74def SHL16mCL : I<0xD3, MRM4m, (outs), (ins i16mem:$dst),
75                 "shl{w}\t{%cl, $dst|$dst, cl}",
76                 [(store (shl (loadi16 addr:$dst), CL), addr:$dst)]>,
77                 OpSize16;
78def SHL32mCL : I<0xD3, MRM4m, (outs), (ins i32mem:$dst),
79                 "shl{l}\t{%cl, $dst|$dst, cl}",
80                 [(store (shl (loadi32 addr:$dst), CL), addr:$dst)]>,
81                 OpSize32;
82def SHL64mCL : RI<0xD3, MRM4m, (outs), (ins i64mem:$dst),
83                  "shl{q}\t{%cl, $dst|$dst, cl}",
84                  [(store (shl (loadi64 addr:$dst), CL), addr:$dst)]>,
85                  Requires<[In64BitMode]>;
86} // Uses, SchedRW
87
88let SchedRW = [WriteShiftLd, WriteRMW] in {
89def SHL8mi   : Ii8<0xC0, MRM4m, (outs), (ins i8mem :$dst, u8imm:$src),
90                   "shl{b}\t{$src, $dst|$dst, $src}",
91                [(store (shl (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>;
92def SHL16mi  : Ii8<0xC1, MRM4m, (outs), (ins i16mem:$dst, u8imm:$src),
93                   "shl{w}\t{$src, $dst|$dst, $src}",
94               [(store (shl (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
95               OpSize16;
96def SHL32mi  : Ii8<0xC1, MRM4m, (outs), (ins i32mem:$dst, u8imm:$src),
97                   "shl{l}\t{$src, $dst|$dst, $src}",
98               [(store (shl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
99               OpSize32;
100def SHL64mi : RIi8<0xC1, MRM4m, (outs), (ins i64mem:$dst, u8imm:$src),
101                  "shl{q}\t{$src, $dst|$dst, $src}",
102                  [(store (shl (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
103                  Requires<[In64BitMode]>;
104
105// Shift by 1
106def SHL8m1   : I<0xD0, MRM4m, (outs), (ins i8mem :$dst),
107                 "shl{b}\t$dst",
108                [(store (shl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
109def SHL16m1  : I<0xD1, MRM4m, (outs), (ins i16mem:$dst),
110                 "shl{w}\t$dst",
111                 [(store (shl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,
112                 OpSize16;
113def SHL32m1  : I<0xD1, MRM4m, (outs), (ins i32mem:$dst),
114                 "shl{l}\t$dst",
115                 [(store (shl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>,
116                 OpSize32;
117def SHL64m1 : RI<0xD1, MRM4m, (outs), (ins i64mem:$dst),
118                  "shl{q}\t$dst",
119                 [(store (shl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>,
120                 Requires<[In64BitMode]>;
121} // SchedRW
122
123let Constraints = "$src1 = $dst" in {
124let Uses = [CL], SchedRW = [WriteShiftCL] in {
125def SHR8rCL  : I<0xD2, MRM5r, (outs GR8 :$dst), (ins GR8 :$src1),
126                 "shr{b}\t{%cl, $dst|$dst, cl}",
127                 [(set GR8:$dst, (srl GR8:$src1, CL))]>;
128def SHR16rCL : I<0xD3, MRM5r, (outs GR16:$dst), (ins GR16:$src1),
129                 "shr{w}\t{%cl, $dst|$dst, cl}",
130                 [(set GR16:$dst, (srl GR16:$src1, CL))]>, OpSize16;
131def SHR32rCL : I<0xD3, MRM5r, (outs GR32:$dst), (ins GR32:$src1),
132                 "shr{l}\t{%cl, $dst|$dst, cl}",
133                 [(set GR32:$dst, (srl GR32:$src1, CL))]>, OpSize32;
134def SHR64rCL : RI<0xD3, MRM5r, (outs GR64:$dst), (ins GR64:$src1),
135                  "shr{q}\t{%cl, $dst|$dst, cl}",
136                  [(set GR64:$dst, (srl GR64:$src1, CL))]>;
137} // Uses, SchedRW
138
139let SchedRW = [WriteShift] in {
140def SHR8ri   : Ii8<0xC0, MRM5r, (outs GR8:$dst), (ins GR8:$src1, u8imm:$src2),
141                   "shr{b}\t{$src2, $dst|$dst, $src2}",
142                   [(set GR8:$dst, (srl GR8:$src1, (i8 imm:$src2)))]>;
143def SHR16ri  : Ii8<0xC1, MRM5r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2),
144                   "shr{w}\t{$src2, $dst|$dst, $src2}",
145                   [(set GR16:$dst, (srl GR16:$src1, (i8 imm:$src2)))]>,
146                   OpSize16;
147def SHR32ri  : Ii8<0xC1, MRM5r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2),
148                   "shr{l}\t{$src2, $dst|$dst, $src2}",
149                   [(set GR32:$dst, (srl GR32:$src1, (i8 imm:$src2)))]>,
150                   OpSize32;
151def SHR64ri : RIi8<0xC1, MRM5r, (outs GR64:$dst), (ins GR64:$src1, u8imm:$src2),
152                  "shr{q}\t{$src2, $dst|$dst, $src2}",
153                  [(set GR64:$dst, (srl GR64:$src1, (i8 imm:$src2)))]>;
154
155// Shift right by 1
156def SHR8r1   : I<0xD0, MRM5r, (outs GR8:$dst), (ins GR8:$src1),
157                 "shr{b}\t$dst",
158                 [(set GR8:$dst, (srl GR8:$src1, (i8 1)))]>;
159def SHR16r1  : I<0xD1, MRM5r, (outs GR16:$dst), (ins GR16:$src1),
160                 "shr{w}\t$dst",
161                 [(set GR16:$dst, (srl GR16:$src1, (i8 1)))]>, OpSize16;
162def SHR32r1  : I<0xD1, MRM5r, (outs GR32:$dst), (ins GR32:$src1),
163                 "shr{l}\t$dst",
164                 [(set GR32:$dst, (srl GR32:$src1, (i8 1)))]>, OpSize32;
165def SHR64r1  : RI<0xD1, MRM5r, (outs GR64:$dst), (ins GR64:$src1),
166                 "shr{q}\t$dst",
167                 [(set GR64:$dst, (srl GR64:$src1, (i8 1)))]>;
168} // SchedRW
169} // Constraints = "$src = $dst"
170
171
172let Uses = [CL], SchedRW = [WriteShiftCLLd, WriteRMW] in {
173def SHR8mCL  : I<0xD2, MRM5m, (outs), (ins i8mem :$dst),
174                 "shr{b}\t{%cl, $dst|$dst, cl}",
175                 [(store (srl (loadi8 addr:$dst), CL), addr:$dst)]>;
176def SHR16mCL : I<0xD3, MRM5m, (outs), (ins i16mem:$dst),
177                 "shr{w}\t{%cl, $dst|$dst, cl}",
178                 [(store (srl (loadi16 addr:$dst), CL), addr:$dst)]>,
179                 OpSize16;
180def SHR32mCL : I<0xD3, MRM5m, (outs), (ins i32mem:$dst),
181                 "shr{l}\t{%cl, $dst|$dst, cl}",
182                 [(store (srl (loadi32 addr:$dst), CL), addr:$dst)]>,
183                 OpSize32;
184def SHR64mCL : RI<0xD3, MRM5m, (outs), (ins i64mem:$dst),
185                  "shr{q}\t{%cl, $dst|$dst, cl}",
186                  [(store (srl (loadi64 addr:$dst), CL), addr:$dst)]>,
187                  Requires<[In64BitMode]>;
188} // Uses, SchedRW
189
190let SchedRW = [WriteShiftLd, WriteRMW] in {
191def SHR8mi   : Ii8<0xC0, MRM5m, (outs), (ins i8mem :$dst, u8imm:$src),
192                   "shr{b}\t{$src, $dst|$dst, $src}",
193                [(store (srl (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>;
194def SHR16mi  : Ii8<0xC1, MRM5m, (outs), (ins i16mem:$dst, u8imm:$src),
195                   "shr{w}\t{$src, $dst|$dst, $src}",
196               [(store (srl (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
197               OpSize16;
198def SHR32mi  : Ii8<0xC1, MRM5m, (outs), (ins i32mem:$dst, u8imm:$src),
199                   "shr{l}\t{$src, $dst|$dst, $src}",
200               [(store (srl (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
201               OpSize32;
202def SHR64mi : RIi8<0xC1, MRM5m, (outs), (ins i64mem:$dst, u8imm:$src),
203                  "shr{q}\t{$src, $dst|$dst, $src}",
204                 [(store (srl (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
205                 Requires<[In64BitMode]>;
206
207// Shift by 1
208def SHR8m1   : I<0xD0, MRM5m, (outs), (ins i8mem :$dst),
209                 "shr{b}\t$dst",
210                 [(store (srl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
211def SHR16m1  : I<0xD1, MRM5m, (outs), (ins i16mem:$dst),
212                 "shr{w}\t$dst",
213                 [(store (srl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,
214                 OpSize16;
215def SHR32m1  : I<0xD1, MRM5m, (outs), (ins i32mem:$dst),
216                 "shr{l}\t$dst",
217                 [(store (srl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>,
218                 OpSize32;
219def SHR64m1 : RI<0xD1, MRM5m, (outs), (ins i64mem:$dst),
220                  "shr{q}\t$dst",
221                 [(store (srl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>,
222                 Requires<[In64BitMode]>;
223} // SchedRW
224
225let Constraints = "$src1 = $dst" in {
226let Uses = [CL], SchedRW = [WriteShiftCL] in {
227def SAR8rCL  : I<0xD2, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1),
228                 "sar{b}\t{%cl, $dst|$dst, cl}",
229                 [(set GR8:$dst, (sra GR8:$src1, CL))]>;
230def SAR16rCL : I<0xD3, MRM7r, (outs GR16:$dst), (ins GR16:$src1),
231                 "sar{w}\t{%cl, $dst|$dst, cl}",
232                 [(set GR16:$dst, (sra GR16:$src1, CL))]>,
233                 OpSize16;
234def SAR32rCL : I<0xD3, MRM7r, (outs GR32:$dst), (ins GR32:$src1),
235                 "sar{l}\t{%cl, $dst|$dst, cl}",
236                 [(set GR32:$dst, (sra GR32:$src1, CL))]>,
237                 OpSize32;
238def SAR64rCL : RI<0xD3, MRM7r, (outs GR64:$dst), (ins GR64:$src1),
239                 "sar{q}\t{%cl, $dst|$dst, cl}",
240                 [(set GR64:$dst, (sra GR64:$src1, CL))]>;
241} // Uses, SchedRW
242
243let SchedRW = [WriteShift] in {
244def SAR8ri   : Ii8<0xC0, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2),
245                   "sar{b}\t{$src2, $dst|$dst, $src2}",
246                   [(set GR8:$dst, (sra GR8:$src1, (i8 imm:$src2)))]>;
247def SAR16ri  : Ii8<0xC1, MRM7r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2),
248                   "sar{w}\t{$src2, $dst|$dst, $src2}",
249                   [(set GR16:$dst, (sra GR16:$src1, (i8 imm:$src2)))]>,
250                   OpSize16;
251def SAR32ri  : Ii8<0xC1, MRM7r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2),
252                   "sar{l}\t{$src2, $dst|$dst, $src2}",
253                   [(set GR32:$dst, (sra GR32:$src1, (i8 imm:$src2)))]>,
254                   OpSize32;
255def SAR64ri  : RIi8<0xC1, MRM7r, (outs GR64:$dst),
256                    (ins GR64:$src1, u8imm:$src2),
257                    "sar{q}\t{$src2, $dst|$dst, $src2}",
258                    [(set GR64:$dst, (sra GR64:$src1, (i8 imm:$src2)))]>;
259
260// Shift by 1
261def SAR8r1   : I<0xD0, MRM7r, (outs GR8 :$dst), (ins GR8 :$src1),
262                 "sar{b}\t$dst",
263                 [(set GR8:$dst, (sra GR8:$src1, (i8 1)))]>;
264def SAR16r1  : I<0xD1, MRM7r, (outs GR16:$dst), (ins GR16:$src1),
265                 "sar{w}\t$dst",
266                 [(set GR16:$dst, (sra GR16:$src1, (i8 1)))]>, OpSize16;
267def SAR32r1  : I<0xD1, MRM7r, (outs GR32:$dst), (ins GR32:$src1),
268                 "sar{l}\t$dst",
269                 [(set GR32:$dst, (sra GR32:$src1, (i8 1)))]>, OpSize32;
270def SAR64r1  : RI<0xD1, MRM7r, (outs GR64:$dst), (ins GR64:$src1),
271                  "sar{q}\t$dst",
272                  [(set GR64:$dst, (sra GR64:$src1, (i8 1)))]>;
273} // SchedRW
274} // Constraints = "$src = $dst"
275
276
277let Uses = [CL], SchedRW = [WriteShiftCLLd, WriteRMW] in {
278def SAR8mCL  : I<0xD2, MRM7m, (outs), (ins i8mem :$dst),
279                 "sar{b}\t{%cl, $dst|$dst, cl}",
280                 [(store (sra (loadi8 addr:$dst), CL), addr:$dst)]>;
281def SAR16mCL : I<0xD3, MRM7m, (outs), (ins i16mem:$dst),
282                 "sar{w}\t{%cl, $dst|$dst, cl}",
283                 [(store (sra (loadi16 addr:$dst), CL), addr:$dst)]>,
284                 OpSize16;
285def SAR32mCL : I<0xD3, MRM7m, (outs), (ins i32mem:$dst),
286                 "sar{l}\t{%cl, $dst|$dst, cl}",
287                 [(store (sra (loadi32 addr:$dst), CL), addr:$dst)]>,
288                 OpSize32;
289def SAR64mCL : RI<0xD3, MRM7m, (outs), (ins i64mem:$dst),
290                 "sar{q}\t{%cl, $dst|$dst, cl}",
291                 [(store (sra (loadi64 addr:$dst), CL), addr:$dst)]>,
292                 Requires<[In64BitMode]>;
293} // Uses, SchedRW
294
295let SchedRW = [WriteShiftLd, WriteRMW] in {
296def SAR8mi   : Ii8<0xC0, MRM7m, (outs), (ins i8mem :$dst, u8imm:$src),
297                   "sar{b}\t{$src, $dst|$dst, $src}",
298                [(store (sra (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>;
299def SAR16mi  : Ii8<0xC1, MRM7m, (outs), (ins i16mem:$dst, u8imm:$src),
300                   "sar{w}\t{$src, $dst|$dst, $src}",
301               [(store (sra (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
302               OpSize16;
303def SAR32mi  : Ii8<0xC1, MRM7m, (outs), (ins i32mem:$dst, u8imm:$src),
304                   "sar{l}\t{$src, $dst|$dst, $src}",
305               [(store (sra (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
306               OpSize32;
307def SAR64mi  : RIi8<0xC1, MRM7m, (outs), (ins i64mem:$dst, u8imm:$src),
308                    "sar{q}\t{$src, $dst|$dst, $src}",
309                 [(store (sra (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
310                 Requires<[In64BitMode]>;
311
312// Shift by 1
313def SAR8m1   : I<0xD0, MRM7m, (outs), (ins i8mem :$dst),
314                 "sar{b}\t$dst",
315                [(store (sra (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
316def SAR16m1  : I<0xD1, MRM7m, (outs), (ins i16mem:$dst),
317                 "sar{w}\t$dst",
318               [(store (sra (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,
319               OpSize16;
320def SAR32m1  : I<0xD1, MRM7m, (outs), (ins i32mem:$dst),
321                 "sar{l}\t$dst",
322               [(store (sra (loadi32 addr:$dst), (i8 1)), addr:$dst)]>,
323               OpSize32;
324def SAR64m1 : RI<0xD1, MRM7m, (outs), (ins i64mem:$dst),
325                  "sar{q}\t$dst",
326                 [(store (sra (loadi64 addr:$dst), (i8 1)), addr:$dst)]>,
327                 Requires<[In64BitMode]>;
328} // SchedRW
329
330//===----------------------------------------------------------------------===//
331// Rotate instructions
332//===----------------------------------------------------------------------===//
333
334let hasSideEffects = 0 in {
335let Constraints = "$src1 = $dst" in {
336
337let Uses = [CL, EFLAGS], SchedRW = [WriteRotateCL] in {
338def RCL8rCL : I<0xD2, MRM2r, (outs GR8:$dst), (ins GR8:$src1),
339                "rcl{b}\t{%cl, $dst|$dst, cl}", []>;
340def RCL16rCL : I<0xD3, MRM2r, (outs GR16:$dst), (ins GR16:$src1),
341                 "rcl{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16;
342def RCL32rCL : I<0xD3, MRM2r, (outs GR32:$dst), (ins GR32:$src1),
343                 "rcl{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32;
344def RCL64rCL : RI<0xD3, MRM2r, (outs GR64:$dst), (ins GR64:$src1),
345                  "rcl{q}\t{%cl, $dst|$dst, cl}", []>;
346} // Uses = [CL, EFLAGS], SchedRW
347
348let Uses = [EFLAGS], SchedRW = [WriteRotate] in {
349def RCL8r1 : I<0xD0, MRM2r, (outs GR8:$dst), (ins GR8:$src1),
350               "rcl{b}\t$dst", []>;
351def RCL8ri : Ii8<0xC0, MRM2r, (outs GR8:$dst), (ins GR8:$src1, u8imm:$cnt),
352                 "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>;
353def RCL16r1 : I<0xD1, MRM2r, (outs GR16:$dst), (ins GR16:$src1),
354                "rcl{w}\t$dst", []>, OpSize16;
355def RCL16ri : Ii8<0xC1, MRM2r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$cnt),
356                  "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16;
357def RCL32r1 : I<0xD1, MRM2r, (outs GR32:$dst), (ins GR32:$src1),
358                "rcl{l}\t$dst", []>, OpSize32;
359def RCL32ri : Ii8<0xC1, MRM2r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$cnt),
360                  "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32;
361def RCL64r1 : RI<0xD1, MRM2r, (outs GR64:$dst), (ins GR64:$src1),
362                 "rcl{q}\t$dst", []>;
363def RCL64ri : RIi8<0xC1, MRM2r, (outs GR64:$dst), (ins GR64:$src1, u8imm:$cnt),
364                   "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>;
365} // Uses = [EFLAGS], SchedRW
366
367let Uses = [CL, EFLAGS], SchedRW = [WriteRotateCL] in {
368def RCR8rCL : I<0xD2, MRM3r, (outs GR8:$dst), (ins GR8:$src1),
369                "rcr{b}\t{%cl, $dst|$dst, cl}", []>;
370def RCR16rCL : I<0xD3, MRM3r, (outs GR16:$dst), (ins GR16:$src1),
371                 "rcr{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16;
372def RCR32rCL : I<0xD3, MRM3r, (outs GR32:$dst), (ins GR32:$src1),
373                 "rcr{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32;
374def RCR64rCL : RI<0xD3, MRM3r, (outs GR64:$dst), (ins GR64:$src1),
375                  "rcr{q}\t{%cl, $dst|$dst, cl}", []>;
376} // Uses = [CL, EFLAGS], SchedRW
377
378let Uses = [EFLAGS], SchedRW = [WriteRotate] in {
379def RCR8r1 : I<0xD0, MRM3r, (outs GR8:$dst), (ins GR8:$src1),
380               "rcr{b}\t$dst", []>;
381def RCR8ri : Ii8<0xC0, MRM3r, (outs GR8:$dst), (ins GR8:$src1, u8imm:$cnt),
382                 "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>;
383def RCR16r1 : I<0xD1, MRM3r, (outs GR16:$dst), (ins GR16:$src1),
384                "rcr{w}\t$dst", []>, OpSize16;
385def RCR16ri : Ii8<0xC1, MRM3r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$cnt),
386                  "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16;
387def RCR32r1 : I<0xD1, MRM3r, (outs GR32:$dst), (ins GR32:$src1),
388                "rcr{l}\t$dst", []>, OpSize32;
389def RCR32ri : Ii8<0xC1, MRM3r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$cnt),
390                  "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32;
391def RCR64r1 : RI<0xD1, MRM3r, (outs GR64:$dst), (ins GR64:$src1),
392                 "rcr{q}\t$dst", []>;
393def RCR64ri : RIi8<0xC1, MRM3r, (outs GR64:$dst), (ins GR64:$src1, u8imm:$cnt),
394                   "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>;
395} // Uses = [EFLAGS], SchedRW
396
397} // Constraints = "$src = $dst"
398
399let mayStore = 1 in {
400let Uses = [EFLAGS], SchedRW = [WriteRotateLd, WriteRMW] in {
401def RCL8m1 : I<0xD0, MRM2m, (outs), (ins i8mem:$dst),
402               "rcl{b}\t$dst", []>;
403def RCL8mi : Ii8<0xC0, MRM2m, (outs), (ins i8mem:$dst, u8imm:$cnt),
404                 "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>;
405def RCL16m1 : I<0xD1, MRM2m, (outs), (ins i16mem:$dst),
406                "rcl{w}\t$dst", []>, OpSize16;
407def RCL16mi : Ii8<0xC1, MRM2m, (outs), (ins i16mem:$dst, u8imm:$cnt),
408                  "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16;
409def RCL32m1 : I<0xD1, MRM2m, (outs), (ins i32mem:$dst),
410                "rcl{l}\t$dst", []>, OpSize32;
411def RCL32mi : Ii8<0xC1, MRM2m, (outs), (ins i32mem:$dst, u8imm:$cnt),
412                  "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32;
413def RCL64m1 : RI<0xD1, MRM2m, (outs), (ins i64mem:$dst),
414                 "rcl{q}\t$dst", []>, Requires<[In64BitMode]>;
415def RCL64mi : RIi8<0xC1, MRM2m, (outs), (ins i64mem:$dst, u8imm:$cnt),
416                   "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>,
417                   Requires<[In64BitMode]>;
418
419def RCR8m1 : I<0xD0, MRM3m, (outs), (ins i8mem:$dst),
420               "rcr{b}\t$dst", []>;
421def RCR8mi : Ii8<0xC0, MRM3m, (outs), (ins i8mem:$dst, u8imm:$cnt),
422                 "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>;
423def RCR16m1 : I<0xD1, MRM3m, (outs), (ins i16mem:$dst),
424                "rcr{w}\t$dst", []>, OpSize16;
425def RCR16mi : Ii8<0xC1, MRM3m, (outs), (ins i16mem:$dst, u8imm:$cnt),
426                  "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize16;
427def RCR32m1 : I<0xD1, MRM3m, (outs), (ins i32mem:$dst),
428                "rcr{l}\t$dst", []>, OpSize32;
429def RCR32mi : Ii8<0xC1, MRM3m, (outs), (ins i32mem:$dst, u8imm:$cnt),
430                  "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize32;
431def RCR64m1 : RI<0xD1, MRM3m, (outs), (ins i64mem:$dst),
432                 "rcr{q}\t$dst", []>, Requires<[In64BitMode]>;
433def RCR64mi : RIi8<0xC1, MRM3m, (outs), (ins i64mem:$dst, u8imm:$cnt),
434                   "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>,
435                   Requires<[In64BitMode]>;
436} // Uses = [EFLAGS], SchedRW
437
438let Uses = [CL, EFLAGS], SchedRW = [WriteRotateCLLd, WriteRMW] in {
439def RCL8mCL : I<0xD2, MRM2m, (outs), (ins i8mem:$dst),
440                "rcl{b}\t{%cl, $dst|$dst, cl}", []>;
441def RCL16mCL : I<0xD3, MRM2m, (outs), (ins i16mem:$dst),
442                 "rcl{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16;
443def RCL32mCL : I<0xD3, MRM2m, (outs), (ins i32mem:$dst),
444                 "rcl{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32;
445def RCL64mCL : RI<0xD3, MRM2m, (outs), (ins i64mem:$dst),
446                  "rcl{q}\t{%cl, $dst|$dst, cl}", []>,
447                  Requires<[In64BitMode]>;
448
449def RCR8mCL : I<0xD2, MRM3m, (outs), (ins i8mem:$dst),
450                "rcr{b}\t{%cl, $dst|$dst, cl}", []>;
451def RCR16mCL : I<0xD3, MRM3m, (outs), (ins i16mem:$dst),
452                 "rcr{w}\t{%cl, $dst|$dst, cl}", []>, OpSize16;
453def RCR32mCL : I<0xD3, MRM3m, (outs), (ins i32mem:$dst),
454                 "rcr{l}\t{%cl, $dst|$dst, cl}", []>, OpSize32;
455def RCR64mCL : RI<0xD3, MRM3m, (outs), (ins i64mem:$dst),
456                  "rcr{q}\t{%cl, $dst|$dst, cl}", []>,
457                  Requires<[In64BitMode]>;
458} // Uses = [CL, EFLAGS], SchedRW
459} // mayStore
460} // hasSideEffects = 0
461
462let Constraints = "$src1 = $dst" in {
463// FIXME: provide shorter instructions when imm8 == 1
464let Uses = [CL], SchedRW = [WriteRotateCL] in {
465def ROL8rCL  : I<0xD2, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1),
466                 "rol{b}\t{%cl, $dst|$dst, cl}",
467                 [(set GR8:$dst, (rotl GR8:$src1, CL))]>;
468def ROL16rCL : I<0xD3, MRM0r, (outs GR16:$dst), (ins GR16:$src1),
469                 "rol{w}\t{%cl, $dst|$dst, cl}",
470                 [(set GR16:$dst, (rotl GR16:$src1, CL))]>, OpSize16;
471def ROL32rCL : I<0xD3, MRM0r, (outs GR32:$dst), (ins GR32:$src1),
472                 "rol{l}\t{%cl, $dst|$dst, cl}",
473                 [(set GR32:$dst, (rotl GR32:$src1, CL))]>, OpSize32;
474def ROL64rCL : RI<0xD3, MRM0r, (outs GR64:$dst), (ins GR64:$src1),
475                  "rol{q}\t{%cl, $dst|$dst, cl}",
476                  [(set GR64:$dst, (rotl GR64:$src1, CL))]>;
477} // Uses, SchedRW
478
479let SchedRW = [WriteRotate] in {
480def ROL8ri   : Ii8<0xC0, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2),
481                   "rol{b}\t{$src2, $dst|$dst, $src2}",
482                   [(set GR8:$dst, (rotl GR8:$src1, (i8 imm:$src2)))]>;
483def ROL16ri  : Ii8<0xC1, MRM0r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2),
484                   "rol{w}\t{$src2, $dst|$dst, $src2}",
485                   [(set GR16:$dst, (rotl GR16:$src1, (i8 imm:$src2)))]>,
486                   OpSize16;
487def ROL32ri  : Ii8<0xC1, MRM0r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2),
488                   "rol{l}\t{$src2, $dst|$dst, $src2}",
489                   [(set GR32:$dst, (rotl GR32:$src1, (i8 imm:$src2)))]>,
490                   OpSize32;
491def ROL64ri  : RIi8<0xC1, MRM0r, (outs GR64:$dst),
492                    (ins GR64:$src1, u8imm:$src2),
493                    "rol{q}\t{$src2, $dst|$dst, $src2}",
494                    [(set GR64:$dst, (rotl GR64:$src1, (i8 imm:$src2)))]>;
495
496// Rotate by 1
497def ROL8r1   : I<0xD0, MRM0r, (outs GR8 :$dst), (ins GR8 :$src1),
498                 "rol{b}\t$dst",
499                 [(set GR8:$dst, (rotl GR8:$src1, (i8 1)))]>;
500def ROL16r1  : I<0xD1, MRM0r, (outs GR16:$dst), (ins GR16:$src1),
501                 "rol{w}\t$dst",
502                 [(set GR16:$dst, (rotl GR16:$src1, (i8 1)))]>, OpSize16;
503def ROL32r1  : I<0xD1, MRM0r, (outs GR32:$dst), (ins GR32:$src1),
504                 "rol{l}\t$dst",
505                 [(set GR32:$dst, (rotl GR32:$src1, (i8 1)))]>, OpSize32;
506def ROL64r1  : RI<0xD1, MRM0r, (outs GR64:$dst), (ins GR64:$src1),
507                  "rol{q}\t$dst",
508                  [(set GR64:$dst, (rotl GR64:$src1, (i8 1)))]>;
509} // SchedRW
510} // Constraints = "$src = $dst"
511
512let Uses = [CL], SchedRW = [WriteRotateCLLd, WriteRMW] in {
513def ROL8mCL  : I<0xD2, MRM0m, (outs), (ins i8mem :$dst),
514                 "rol{b}\t{%cl, $dst|$dst, cl}",
515                 [(store (rotl (loadi8 addr:$dst), CL), addr:$dst)]>;
516def ROL16mCL : I<0xD3, MRM0m, (outs), (ins i16mem:$dst),
517                 "rol{w}\t{%cl, $dst|$dst, cl}",
518                 [(store (rotl (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize16;
519def ROL32mCL : I<0xD3, MRM0m, (outs), (ins i32mem:$dst),
520                 "rol{l}\t{%cl, $dst|$dst, cl}",
521                 [(store (rotl (loadi32 addr:$dst), CL), addr:$dst)]>, OpSize32;
522def ROL64mCL :  RI<0xD3, MRM0m, (outs), (ins i64mem:$dst),
523                   "rol{q}\t{%cl, $dst|$dst, cl}",
524                   [(store (rotl (loadi64 addr:$dst), CL), addr:$dst)]>,
525                   Requires<[In64BitMode]>;
526} // Uses, SchedRW
527
528let SchedRW = [WriteRotateLd, WriteRMW] in {
529def ROL8mi   : Ii8<0xC0, MRM0m, (outs), (ins i8mem :$dst, u8imm:$src1),
530                   "rol{b}\t{$src1, $dst|$dst, $src1}",
531               [(store (rotl (loadi8 addr:$dst), (i8 imm:$src1)), addr:$dst)]>;
532def ROL16mi  : Ii8<0xC1, MRM0m, (outs), (ins i16mem:$dst, u8imm:$src1),
533                   "rol{w}\t{$src1, $dst|$dst, $src1}",
534              [(store (rotl (loadi16 addr:$dst), (i8 imm:$src1)), addr:$dst)]>,
535              OpSize16;
536def ROL32mi  : Ii8<0xC1, MRM0m, (outs), (ins i32mem:$dst, u8imm:$src1),
537                   "rol{l}\t{$src1, $dst|$dst, $src1}",
538              [(store (rotl (loadi32 addr:$dst), (i8 imm:$src1)), addr:$dst)]>,
539              OpSize32;
540def ROL64mi  : RIi8<0xC1, MRM0m, (outs), (ins i64mem:$dst, u8imm:$src1),
541                    "rol{q}\t{$src1, $dst|$dst, $src1}",
542                [(store (rotl (loadi64 addr:$dst), (i8 imm:$src1)), addr:$dst)]>,
543                Requires<[In64BitMode]>;
544
545// Rotate by 1
546def ROL8m1   : I<0xD0, MRM0m, (outs), (ins i8mem :$dst),
547                 "rol{b}\t$dst",
548                 [(store (rotl (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
549def ROL16m1  : I<0xD1, MRM0m, (outs), (ins i16mem:$dst),
550                 "rol{w}\t$dst",
551                 [(store (rotl (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,
552                 OpSize16;
553def ROL32m1  : I<0xD1, MRM0m, (outs), (ins i32mem:$dst),
554                 "rol{l}\t$dst",
555                 [(store (rotl (loadi32 addr:$dst), (i8 1)), addr:$dst)]>,
556                 OpSize32;
557def ROL64m1  : RI<0xD1, MRM0m, (outs), (ins i64mem:$dst),
558                 "rol{q}\t$dst",
559                 [(store (rotl (loadi64 addr:$dst), (i8 1)), addr:$dst)]>,
560                 Requires<[In64BitMode]>;
561} // SchedRW
562
563let Constraints = "$src1 = $dst" in {
564let Uses = [CL], SchedRW = [WriteRotateCL] in {
565def ROR8rCL  : I<0xD2, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1),
566                 "ror{b}\t{%cl, $dst|$dst, cl}",
567                 [(set GR8:$dst, (rotr GR8:$src1, CL))]>;
568def ROR16rCL : I<0xD3, MRM1r, (outs GR16:$dst), (ins GR16:$src1),
569                 "ror{w}\t{%cl, $dst|$dst, cl}",
570                 [(set GR16:$dst, (rotr GR16:$src1, CL))]>, OpSize16;
571def ROR32rCL : I<0xD3, MRM1r, (outs GR32:$dst), (ins GR32:$src1),
572                 "ror{l}\t{%cl, $dst|$dst, cl}",
573                 [(set GR32:$dst, (rotr GR32:$src1, CL))]>, OpSize32;
574def ROR64rCL : RI<0xD3, MRM1r, (outs GR64:$dst), (ins GR64:$src1),
575                  "ror{q}\t{%cl, $dst|$dst, cl}",
576                  [(set GR64:$dst, (rotr GR64:$src1, CL))]>;
577}
578
579let SchedRW = [WriteRotate] in {
580def ROR8ri   : Ii8<0xC0, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1, u8imm:$src2),
581                   "ror{b}\t{$src2, $dst|$dst, $src2}",
582                   [(set GR8:$dst, (rotr GR8:$src1, (i8 imm:$src2)))]>;
583def ROR16ri  : Ii8<0xC1, MRM1r, (outs GR16:$dst), (ins GR16:$src1, u8imm:$src2),
584                   "ror{w}\t{$src2, $dst|$dst, $src2}",
585                   [(set GR16:$dst, (rotr GR16:$src1, (i8 imm:$src2)))]>,
586                   OpSize16;
587def ROR32ri  : Ii8<0xC1, MRM1r, (outs GR32:$dst), (ins GR32:$src1, u8imm:$src2),
588                   "ror{l}\t{$src2, $dst|$dst, $src2}",
589                   [(set GR32:$dst, (rotr GR32:$src1, (i8 imm:$src2)))]>,
590                   OpSize32;
591def ROR64ri  : RIi8<0xC1, MRM1r, (outs GR64:$dst),
592                    (ins GR64:$src1, u8imm:$src2),
593                    "ror{q}\t{$src2, $dst|$dst, $src2}",
594                    [(set GR64:$dst, (rotr GR64:$src1, (i8 imm:$src2)))]>;
595
596// Rotate by 1
597def ROR8r1   : I<0xD0, MRM1r, (outs GR8 :$dst), (ins GR8 :$src1),
598                 "ror{b}\t$dst",
599                 [(set GR8:$dst, (rotr GR8:$src1, (i8 1)))]>;
600def ROR16r1  : I<0xD1, MRM1r, (outs GR16:$dst), (ins GR16:$src1),
601                 "ror{w}\t$dst",
602                 [(set GR16:$dst, (rotr GR16:$src1, (i8 1)))]>, OpSize16;
603def ROR32r1  : I<0xD1, MRM1r, (outs GR32:$dst), (ins GR32:$src1),
604                 "ror{l}\t$dst",
605                 [(set GR32:$dst, (rotr GR32:$src1, (i8 1)))]>, OpSize32;
606def ROR64r1  : RI<0xD1, MRM1r, (outs GR64:$dst), (ins GR64:$src1),
607                  "ror{q}\t$dst",
608                  [(set GR64:$dst, (rotr GR64:$src1, (i8 1)))]>;
609} // SchedRW
610} // Constraints = "$src = $dst", SchedRW
611
612let Uses = [CL], SchedRW = [WriteRotateCLLd, WriteRMW] in {
613def ROR8mCL  : I<0xD2, MRM1m, (outs), (ins i8mem :$dst),
614                 "ror{b}\t{%cl, $dst|$dst, cl}",
615                 [(store (rotr (loadi8 addr:$dst), CL), addr:$dst)]>;
616def ROR16mCL : I<0xD3, MRM1m, (outs), (ins i16mem:$dst),
617                 "ror{w}\t{%cl, $dst|$dst, cl}",
618                 [(store (rotr (loadi16 addr:$dst), CL), addr:$dst)]>, OpSize16;
619def ROR32mCL : I<0xD3, MRM1m, (outs), (ins i32mem:$dst),
620                 "ror{l}\t{%cl, $dst|$dst, cl}",
621                 [(store (rotr (loadi32 addr:$dst), CL), addr:$dst)]>, OpSize32;
622def ROR64mCL : RI<0xD3, MRM1m, (outs), (ins i64mem:$dst),
623                  "ror{q}\t{%cl, $dst|$dst, cl}",
624                  [(store (rotr (loadi64 addr:$dst), CL), addr:$dst)]>,
625                  Requires<[In64BitMode]>;
626} // Uses, SchedRW
627
628let SchedRW = [WriteRotateLd, WriteRMW] in {
629def ROR8mi   : Ii8<0xC0, MRM1m, (outs), (ins i8mem :$dst, u8imm:$src),
630                   "ror{b}\t{$src, $dst|$dst, $src}",
631                   [(store (rotr (loadi8 addr:$dst), (i8 imm:$src)), addr:$dst)]>;
632def ROR16mi  : Ii8<0xC1, MRM1m, (outs), (ins i16mem:$dst, u8imm:$src),
633                   "ror{w}\t{$src, $dst|$dst, $src}",
634                   [(store (rotr (loadi16 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
635                   OpSize16;
636def ROR32mi  : Ii8<0xC1, MRM1m, (outs), (ins i32mem:$dst, u8imm:$src),
637                   "ror{l}\t{$src, $dst|$dst, $src}",
638                   [(store (rotr (loadi32 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
639                   OpSize32;
640def ROR64mi  : RIi8<0xC1, MRM1m, (outs), (ins i64mem:$dst, u8imm:$src),
641                    "ror{q}\t{$src, $dst|$dst, $src}",
642                    [(store (rotr (loadi64 addr:$dst), (i8 imm:$src)), addr:$dst)]>,
643                    Requires<[In64BitMode]>;
644
645// Rotate by 1
646def ROR8m1   : I<0xD0, MRM1m, (outs), (ins i8mem :$dst),
647                 "ror{b}\t$dst",
648                 [(store (rotr (loadi8 addr:$dst), (i8 1)), addr:$dst)]>;
649def ROR16m1  : I<0xD1, MRM1m, (outs), (ins i16mem:$dst),
650                 "ror{w}\t$dst",
651                 [(store (rotr (loadi16 addr:$dst), (i8 1)), addr:$dst)]>,
652                 OpSize16;
653def ROR32m1  : I<0xD1, MRM1m, (outs), (ins i32mem:$dst),
654                 "ror{l}\t$dst",
655                 [(store (rotr (loadi32 addr:$dst), (i8 1)), addr:$dst)]>,
656                 OpSize32;
657def ROR64m1  : RI<0xD1, MRM1m, (outs), (ins i64mem:$dst),
658                 "ror{q}\t$dst",
659                 [(store (rotr (loadi64 addr:$dst), (i8 1)), addr:$dst)]>,
660                 Requires<[In64BitMode]>;
661} // SchedRW
662
663
664//===----------------------------------------------------------------------===//
665// Double shift instructions (generalizations of rotate)
666//===----------------------------------------------------------------------===//
667
668let Constraints = "$src1 = $dst" in {
669
670let Uses = [CL], SchedRW = [WriteSHDrrcl] in {
671def SHLD16rrCL : I<0xA5, MRMDestReg, (outs GR16:$dst),
672                   (ins GR16:$src1, GR16:$src2),
673                   "shld{w}\t{%cl, $src2, $dst|$dst, $src2, cl}",
674                   [(set GR16:$dst, (X86fshl GR16:$src1, GR16:$src2, CL))]>,
675                   TB, OpSize16;
676def SHRD16rrCL : I<0xAD, MRMDestReg, (outs GR16:$dst),
677                   (ins GR16:$src1, GR16:$src2),
678                   "shrd{w}\t{%cl, $src2, $dst|$dst, $src2, cl}",
679                   [(set GR16:$dst, (X86fshr GR16:$src2, GR16:$src1, CL))]>,
680                   TB, OpSize16;
681def SHLD32rrCL : I<0xA5, MRMDestReg, (outs GR32:$dst),
682                   (ins GR32:$src1, GR32:$src2),
683                   "shld{l}\t{%cl, $src2, $dst|$dst, $src2, cl}",
684                   [(set GR32:$dst, (fshl GR32:$src1, GR32:$src2, CL))]>,
685                   TB, OpSize32;
686def SHRD32rrCL : I<0xAD, MRMDestReg, (outs GR32:$dst),
687                   (ins GR32:$src1, GR32:$src2),
688                   "shrd{l}\t{%cl, $src2, $dst|$dst, $src2, cl}",
689                   [(set GR32:$dst, (fshr GR32:$src2, GR32:$src1, CL))]>,
690                   TB, OpSize32;
691def SHLD64rrCL : RI<0xA5, MRMDestReg, (outs GR64:$dst),
692                    (ins GR64:$src1, GR64:$src2),
693                    "shld{q}\t{%cl, $src2, $dst|$dst, $src2, cl}",
694                    [(set GR64:$dst, (fshl GR64:$src1, GR64:$src2, CL))]>,
695                    TB;
696def SHRD64rrCL : RI<0xAD, MRMDestReg, (outs GR64:$dst),
697                    (ins GR64:$src1, GR64:$src2),
698                    "shrd{q}\t{%cl, $src2, $dst|$dst, $src2, cl}",
699                    [(set GR64:$dst, (fshr GR64:$src2, GR64:$src1, CL))]>,
700                    TB;
701} // Uses, SchedRW
702
703let isCommutable = 1, SchedRW = [WriteSHDrri] in {  // These instructions commute to each other.
704def SHLD16rri8 : Ii8<0xA4, MRMDestReg,
705                     (outs GR16:$dst),
706                     (ins GR16:$src1, GR16:$src2, u8imm:$src3),
707                     "shld{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
708                     [(set GR16:$dst, (X86fshl GR16:$src1, GR16:$src2,
709                                      (i8 imm:$src3)))]>,
710                     TB, OpSize16;
711def SHRD16rri8 : Ii8<0xAC, MRMDestReg,
712                     (outs GR16:$dst),
713                     (ins GR16:$src1, GR16:$src2, u8imm:$src3),
714                     "shrd{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
715                     [(set GR16:$dst, (X86fshr GR16:$src2, GR16:$src1,
716                                      (i8 imm:$src3)))]>,
717                     TB, OpSize16;
718def SHLD32rri8 : Ii8<0xA4, MRMDestReg,
719                     (outs GR32:$dst),
720                     (ins GR32:$src1, GR32:$src2, u8imm:$src3),
721                     "shld{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
722                     [(set GR32:$dst, (fshl GR32:$src1, GR32:$src2,
723                                      (i8 imm:$src3)))]>,
724                 TB, OpSize32;
725def SHRD32rri8 : Ii8<0xAC, MRMDestReg,
726                     (outs GR32:$dst),
727                     (ins GR32:$src1, GR32:$src2, u8imm:$src3),
728                     "shrd{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
729                     [(set GR32:$dst, (fshr GR32:$src2, GR32:$src1,
730                                      (i8 imm:$src3)))]>,
731                 TB, OpSize32;
732def SHLD64rri8 : RIi8<0xA4, MRMDestReg,
733                      (outs GR64:$dst),
734                      (ins GR64:$src1, GR64:$src2, u8imm:$src3),
735                      "shld{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
736                      [(set GR64:$dst, (fshl GR64:$src1, GR64:$src2,
737                                       (i8 imm:$src3)))]>,
738                 TB;
739def SHRD64rri8 : RIi8<0xAC, MRMDestReg,
740                      (outs GR64:$dst),
741                      (ins GR64:$src1, GR64:$src2, u8imm:$src3),
742                      "shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
743                      [(set GR64:$dst, (fshr GR64:$src2, GR64:$src1,
744                                       (i8 imm:$src3)))]>,
745                 TB;
746} // SchedRW
747} // Constraints = "$src = $dst"
748
749let Uses = [CL], SchedRW = [WriteSHDmrcl] in {
750def SHLD16mrCL : I<0xA5, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2),
751                   "shld{w}\t{%cl, $src2, $dst|$dst, $src2, cl}",
752                   [(store (X86fshl (loadi16 addr:$dst), GR16:$src2, CL),
753                                    addr:$dst)]>, TB, OpSize16;
754def SHRD16mrCL : I<0xAD, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2),
755                  "shrd{w}\t{%cl, $src2, $dst|$dst, $src2, cl}",
756                  [(store (X86fshr GR16:$src2, (loadi16 addr:$dst), CL),
757                                   addr:$dst)]>, TB, OpSize16;
758
759def SHLD32mrCL : I<0xA5, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2),
760                   "shld{l}\t{%cl, $src2, $dst|$dst, $src2, cl}",
761                   [(store (fshl (loadi32 addr:$dst), GR32:$src2, CL),
762                     addr:$dst)]>, TB, OpSize32;
763def SHRD32mrCL : I<0xAD, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2),
764                  "shrd{l}\t{%cl, $src2, $dst|$dst, $src2, cl}",
765                  [(store (fshr GR32:$src2, (loadi32 addr:$dst), CL),
766                                addr:$dst)]>, TB, OpSize32;
767
768def SHLD64mrCL : RI<0xA5, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2),
769                    "shld{q}\t{%cl, $src2, $dst|$dst, $src2, cl}",
770                    [(store (fshl (loadi64 addr:$dst), GR64:$src2, CL),
771                                  addr:$dst)]>, TB;
772def SHRD64mrCL : RI<0xAD, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2),
773                    "shrd{q}\t{%cl, $src2, $dst|$dst, $src2, cl}",
774                    [(store (fshr GR64:$src2, (loadi64 addr:$dst), CL),
775                                  addr:$dst)]>, TB;
776} // Uses, SchedRW
777
778let SchedRW = [WriteSHDmri] in {
779def SHLD16mri8 : Ii8<0xA4, MRMDestMem,
780                    (outs), (ins i16mem:$dst, GR16:$src2, u8imm:$src3),
781                    "shld{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
782                    [(store (X86fshl (loadi16 addr:$dst), GR16:$src2,
783                                     (i8 imm:$src3)), addr:$dst)]>,
784                    TB, OpSize16;
785def SHRD16mri8 : Ii8<0xAC, MRMDestMem,
786                     (outs), (ins i16mem:$dst, GR16:$src2, u8imm:$src3),
787                     "shrd{w}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
788                    [(store (X86fshr GR16:$src2, (loadi16 addr:$dst),
789                                     (i8 imm:$src3)), addr:$dst)]>,
790                     TB, OpSize16;
791
792def SHLD32mri8 : Ii8<0xA4, MRMDestMem,
793                    (outs), (ins i32mem:$dst, GR32:$src2, u8imm:$src3),
794                    "shld{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
795                    [(store (fshl (loadi32 addr:$dst), GR32:$src2,
796                                  (i8 imm:$src3)), addr:$dst)]>,
797                    TB, OpSize32;
798def SHRD32mri8 : Ii8<0xAC, MRMDestMem,
799                     (outs), (ins i32mem:$dst, GR32:$src2, u8imm:$src3),
800                     "shrd{l}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
801                     [(store (fshr GR32:$src2, (loadi32 addr:$dst),
802                                   (i8 imm:$src3)), addr:$dst)]>,
803                     TB, OpSize32;
804
805def SHLD64mri8 : RIi8<0xA4, MRMDestMem,
806                      (outs), (ins i64mem:$dst, GR64:$src2, u8imm:$src3),
807                      "shld{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
808                      [(store (fshl (loadi64 addr:$dst), GR64:$src2,
809                                    (i8 imm:$src3)), addr:$dst)]>,
810                 TB;
811def SHRD64mri8 : RIi8<0xAC, MRMDestMem,
812                      (outs), (ins i64mem:$dst, GR64:$src2, u8imm:$src3),
813                      "shrd{q}\t{$src3, $src2, $dst|$dst, $src2, $src3}",
814                      [(store (fshr GR64:$src2, (loadi64 addr:$dst),
815                                    (i8 imm:$src3)), addr:$dst)]>,
816                 TB;
817} // SchedRW
818
819} // Defs = [EFLAGS]
820
821// Use the opposite rotate if allows us to use the rotate by 1 instruction.
822def : Pat<(rotl GR8:$src1,  (i8 7)),  (ROR8r1  GR8:$src1)>;
823def : Pat<(rotl GR16:$src1, (i8 15)), (ROR16r1 GR16:$src1)>;
824def : Pat<(rotl GR32:$src1, (i8 31)), (ROR32r1 GR32:$src1)>;
825def : Pat<(rotl GR64:$src1, (i8 63)), (ROR64r1 GR64:$src1)>;
826def : Pat<(rotr GR8:$src1,  (i8 7)),  (ROL8r1  GR8:$src1)>;
827def : Pat<(rotr GR16:$src1, (i8 15)), (ROL16r1 GR16:$src1)>;
828def : Pat<(rotr GR32:$src1, (i8 31)), (ROL32r1 GR32:$src1)>;
829def : Pat<(rotr GR64:$src1, (i8 63)), (ROL64r1 GR64:$src1)>;
830
831def : Pat<(store (rotl (loadi8 addr:$dst), (i8 7)), addr:$dst),
832          (ROR8m1 addr:$dst)>;
833def : Pat<(store (rotl (loadi16 addr:$dst), (i8 15)), addr:$dst),
834          (ROR16m1 addr:$dst)>;
835def : Pat<(store (rotl (loadi32 addr:$dst), (i8 31)), addr:$dst),
836          (ROR32m1 addr:$dst)>;
837def : Pat<(store (rotl (loadi64 addr:$dst), (i8 63)), addr:$dst),
838          (ROR64m1 addr:$dst)>, Requires<[In64BitMode]>;
839
840def : Pat<(store (rotr (loadi8 addr:$dst), (i8 7)), addr:$dst),
841          (ROL8m1 addr:$dst)>;
842def : Pat<(store (rotr (loadi16 addr:$dst), (i8 15)), addr:$dst),
843          (ROL16m1 addr:$dst)>;
844def : Pat<(store (rotr (loadi32 addr:$dst), (i8 31)), addr:$dst),
845          (ROL32m1 addr:$dst)>;
846def : Pat<(store (rotr (loadi64 addr:$dst), (i8 63)), addr:$dst),
847          (ROL64m1 addr:$dst)>, Requires<[In64BitMode]>;
848
849// Sandy Bridge and newer Intel processors support faster rotates using
850// SHLD to avoid a partial flag update on the normal rotate instructions.
851// Use a pseudo so that TwoInstructionPass and register allocation will see
852// this as unary instruction.
853let Predicates = [HasFastSHLDRotate], AddedComplexity = 5,
854    Defs = [EFLAGS], isPseudo = 1, SchedRW = [WriteSHDrri],
855    Constraints = "$src1 = $dst" in {
856  def SHLDROT32ri  : I<0, Pseudo, (outs GR32:$dst),
857                       (ins GR32:$src1, u8imm:$shamt), "",
858                     [(set GR32:$dst, (rotl GR32:$src1, (i8 imm:$shamt)))]>;
859  def SHLDROT64ri  : I<0, Pseudo, (outs GR64:$dst),
860                       (ins GR64:$src1, u8imm:$shamt), "",
861                     [(set GR64:$dst, (rotl GR64:$src1, (i8 imm:$shamt)))]>;
862
863  def SHRDROT32ri  : I<0, Pseudo, (outs GR32:$dst),
864                       (ins GR32:$src1, u8imm:$shamt), "",
865                     [(set GR32:$dst, (rotr GR32:$src1, (i8 imm:$shamt)))]>;
866  def SHRDROT64ri  : I<0, Pseudo, (outs GR64:$dst),
867                       (ins GR64:$src1, u8imm:$shamt), "",
868                     [(set GR64:$dst, (rotr GR64:$src1, (i8 imm:$shamt)))]>;
869}
870
871def ROT32L2R_imm8  : SDNodeXForm<imm, [{
872  // Convert a ROTL shamt to a ROTR shamt on 32-bit integer.
873  return getI8Imm(32 - N->getZExtValue(), SDLoc(N));
874}]>;
875
876def ROT64L2R_imm8  : SDNodeXForm<imm, [{
877  // Convert a ROTL shamt to a ROTR shamt on 64-bit integer.
878  return getI8Imm(64 - N->getZExtValue(), SDLoc(N));
879}]>;
880
881// NOTE: We use WriteShift for these rotates as they avoid the stalls
882// of many of the older x86 rotate instructions.
883multiclass bmi_rotate<string asm, RegisterClass RC, X86MemOperand x86memop> {
884let hasSideEffects = 0 in {
885  def ri : Ii8<0xF0, MRMSrcReg, (outs RC:$dst), (ins RC:$src1, u8imm:$src2),
886               !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
887               []>, TAXD, VEX, Sched<[WriteShift]>;
888  let mayLoad = 1 in
889  def mi : Ii8<0xF0, MRMSrcMem, (outs RC:$dst),
890               (ins x86memop:$src1, u8imm:$src2),
891               !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
892               []>, TAXD, VEX, Sched<[WriteShiftLd]>;
893}
894}
895
896multiclass bmi_shift<string asm, RegisterClass RC, X86MemOperand x86memop> {
897let hasSideEffects = 0 in {
898  def rr : I<0xF7, MRMSrcReg4VOp3, (outs RC:$dst), (ins RC:$src1, RC:$src2),
899             !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>,
900             VEX, Sched<[WriteShift]>;
901  let mayLoad = 1 in
902  def rm : I<0xF7, MRMSrcMem4VOp3,
903             (outs RC:$dst), (ins x86memop:$src1, RC:$src2),
904             !strconcat(asm, "\t{$src2, $src1, $dst|$dst, $src1, $src2}"), []>,
905             VEX, Sched<[WriteShift.Folded,
906                         // x86memop:$src1
907                         ReadDefault, ReadDefault, ReadDefault, ReadDefault,
908                         ReadDefault,
909                         // RC:$src2
910                         WriteShift.ReadAfterFold]>;
911}
912}
913
914let Predicates = [HasBMI2] in {
915  defm RORX32 : bmi_rotate<"rorx{l}", GR32, i32mem>;
916  defm RORX64 : bmi_rotate<"rorx{q}", GR64, i64mem>, VEX_W;
917  defm SARX32 : bmi_shift<"sarx{l}", GR32, i32mem>, T8XS;
918  defm SARX64 : bmi_shift<"sarx{q}", GR64, i64mem>, T8XS, VEX_W;
919  defm SHRX32 : bmi_shift<"shrx{l}", GR32, i32mem>, T8XD;
920  defm SHRX64 : bmi_shift<"shrx{q}", GR64, i64mem>, T8XD, VEX_W;
921  defm SHLX32 : bmi_shift<"shlx{l}", GR32, i32mem>, T8PD;
922  defm SHLX64 : bmi_shift<"shlx{q}", GR64, i64mem>, T8PD, VEX_W;
923
924  // Prefer RORX which is non-destructive and doesn't update EFLAGS.
925  let AddedComplexity = 10 in {
926    def : Pat<(rotr GR32:$src, (i8 imm:$shamt)),
927              (RORX32ri GR32:$src, imm:$shamt)>;
928    def : Pat<(rotr GR64:$src, (i8 imm:$shamt)),
929              (RORX64ri GR64:$src, imm:$shamt)>;
930
931    def : Pat<(rotl GR32:$src, (i8 imm:$shamt)),
932              (RORX32ri GR32:$src, (ROT32L2R_imm8 imm:$shamt))>;
933    def : Pat<(rotl GR64:$src, (i8 imm:$shamt)),
934              (RORX64ri GR64:$src, (ROT64L2R_imm8 imm:$shamt))>;
935  }
936
937  def : Pat<(rotr (loadi32 addr:$src), (i8 imm:$shamt)),
938            (RORX32mi addr:$src, imm:$shamt)>;
939  def : Pat<(rotr (loadi64 addr:$src), (i8 imm:$shamt)),
940            (RORX64mi addr:$src, imm:$shamt)>;
941
942  def : Pat<(rotl (loadi32 addr:$src), (i8 imm:$shamt)),
943            (RORX32mi addr:$src, (ROT32L2R_imm8 imm:$shamt))>;
944  def : Pat<(rotl (loadi64 addr:$src), (i8 imm:$shamt)),
945            (RORX64mi addr:$src, (ROT64L2R_imm8 imm:$shamt))>;
946
947  // Prefer SARX/SHRX/SHLX over SAR/SHR/SHL with variable shift BUT not
948  // immediate shift, i.e. the following code is considered better
949  //
950  //  mov %edi, %esi
951  //  shl $imm, %esi
952  //  ... %edi, ...
953  //
954  // than
955  //
956  //  movb $imm, %sil
957  //  shlx %sil, %edi, %esi
958  //  ... %edi, ...
959  //
960  let AddedComplexity = 1 in {
961    def : Pat<(sra GR32:$src1, GR8:$src2),
962              (SARX32rr GR32:$src1,
963                        (INSERT_SUBREG
964                          (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
965    def : Pat<(sra GR64:$src1, GR8:$src2),
966              (SARX64rr GR64:$src1,
967                        (INSERT_SUBREG
968                          (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
969
970    def : Pat<(srl GR32:$src1, GR8:$src2),
971              (SHRX32rr GR32:$src1,
972                        (INSERT_SUBREG
973                          (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
974    def : Pat<(srl GR64:$src1, GR8:$src2),
975              (SHRX64rr GR64:$src1,
976                        (INSERT_SUBREG
977                          (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
978
979    def : Pat<(shl GR32:$src1, GR8:$src2),
980              (SHLX32rr GR32:$src1,
981                        (INSERT_SUBREG
982                          (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
983    def : Pat<(shl GR64:$src1, GR8:$src2),
984              (SHLX64rr GR64:$src1,
985                        (INSERT_SUBREG
986                          (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
987  }
988
989  // We prefer to use
990  //  mov (%ecx), %esi
991  //  shl $imm, $esi
992  //
993  // over
994  //
995  //  movb $imm, %al
996  //  shlx %al, (%ecx), %esi
997  //
998  // This priority is enforced by IsProfitableToFoldLoad.
999  def : Pat<(sra (loadi32 addr:$src1), GR8:$src2),
1000            (SARX32rm addr:$src1,
1001                      (INSERT_SUBREG
1002                        (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1003  def : Pat<(sra (loadi64 addr:$src1), GR8:$src2),
1004            (SARX64rm addr:$src1,
1005                      (INSERT_SUBREG
1006                        (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1007
1008  def : Pat<(srl (loadi32 addr:$src1), GR8:$src2),
1009            (SHRX32rm addr:$src1,
1010                      (INSERT_SUBREG
1011                        (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1012  def : Pat<(srl (loadi64 addr:$src1), GR8:$src2),
1013            (SHRX64rm addr:$src1,
1014                      (INSERT_SUBREG
1015                        (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1016
1017  def : Pat<(shl (loadi32 addr:$src1), GR8:$src2),
1018            (SHLX32rm addr:$src1,
1019                      (INSERT_SUBREG
1020                        (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1021  def : Pat<(shl (loadi64 addr:$src1), GR8:$src2),
1022            (SHLX64rm addr:$src1,
1023                      (INSERT_SUBREG
1024                        (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>;
1025}
1026
1027def : Pat<(rotl GR8:$src1, (i8 relocImm:$src2)),
1028          (ROL8ri GR8:$src1, relocImm:$src2)>;
1029def : Pat<(rotl GR16:$src1, (i8 relocImm:$src2)),
1030          (ROL16ri GR16:$src1, relocImm:$src2)>;
1031def : Pat<(rotl GR32:$src1, (i8 relocImm:$src2)),
1032          (ROL32ri GR32:$src1, relocImm:$src2)>;
1033def : Pat<(rotl GR64:$src1, (i8 relocImm:$src2)),
1034          (ROL64ri GR64:$src1, relocImm:$src2)>;
1035
1036def : Pat<(rotr GR8:$src1, (i8 relocImm:$src2)),
1037          (ROR8ri GR8:$src1, relocImm:$src2)>;
1038def : Pat<(rotr GR16:$src1, (i8 relocImm:$src2)),
1039          (ROR16ri GR16:$src1, relocImm:$src2)>;
1040def : Pat<(rotr GR32:$src1, (i8 relocImm:$src2)),
1041          (ROR32ri GR32:$src1, relocImm:$src2)>;
1042def : Pat<(rotr GR64:$src1, (i8 relocImm:$src2)),
1043          (ROR64ri GR64:$src1, relocImm:$src2)>;
1044