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