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