-def SHL8rCL : I <"shl", 0xD2, MRM4r > , UsesCL; // R8 <<= cl
-def SHL16rCL : I <"shl", 0xD3, MRM4r >, OpSize, UsesCL; // R16 <<= cl
-def SHL32rCL : I <"shl", 0xD3, MRM4r > , UsesCL; // R32 <<= cl
-def SHL8mCL : Im8 <"shl", 0xD2, MRM4m > , UsesCL; // [mem8] <<= cl
-def SHL16mCL : Im16 <"shl", 0xD3, MRM4m >, OpSize, UsesCL; // [mem16] <<= cl
-def SHL32mCL : Im32 <"shl", 0xD3, MRM4m > , UsesCL; // [mem32] <<= cl
-
-def SHL8ri : Ii8 <"shl", 0xC0, MRM4r >; // R8 <<= imm8
-def SHL16ri : Ii8 <"shl", 0xC1, MRM4r >, OpSize; // R16 <<= imm8
-def SHL32ri : Ii8 <"shl", 0xC1, MRM4r >; // R32 <<= imm8
-def SHL8mi : Im8i8 <"shl", 0xC0, MRM4m >; // [mem8] <<= imm8
-def SHL16mi : Im16i8<"shl", 0xC1, MRM4m >, OpSize; // [mem16] <<= imm8
-def SHL32mi : Im32i8<"shl", 0xC1, MRM4m >; // [mem32] <<= imm8
-
-def SHR8rCL : I <"shr", 0xD2, MRM5r > , UsesCL; // R8 >>= cl
-def SHR16rCL : I <"shr", 0xD3, MRM5r >, OpSize, UsesCL; // R16 >>= cl
-def SHR32rCL : I <"shr", 0xD3, MRM5r > , UsesCL; // R32 >>= cl
-def SHR8mCL : Im8 <"shr", 0xD2, MRM5m > , UsesCL; // [mem8] >>= cl
-def SHR16mCL : Im16 <"shr", 0xD3, MRM5m >, OpSize, UsesCL; // [mem16] >>= cl
-def SHR32mCL : Im32 <"shr", 0xD3, MRM5m > , UsesCL; // [mem32] >>= cl
-
-def SHR8ri : Ii8 <"shr", 0xC0, MRM5r >; // R8 >>= imm8
-def SHR16ri : Ii8 <"shr", 0xC1, MRM5r >, OpSize; // R16 >>= imm8
-def SHR32ri : Ii8 <"shr", 0xC1, MRM5r >; // R32 >>= imm8
-def SHR8mi : Im8i8 <"shr", 0xC0, MRM5m >; // [mem8] >>= imm8
-def SHR16mi : Im16i8<"shr", 0xC1, MRM5m >, OpSize; // [mem16] >>= imm8
-def SHR32mi : Im32i8<"shr", 0xC1, MRM5m >; // [mem32] >>= imm8
-
-def SAR8rCL : I <"sar", 0xD2, MRM7r > , UsesCL; // R8 >>>= cl
-def SAR16rCL : I <"sar", 0xD3, MRM7r >, OpSize, UsesCL; // R16 >>>= cl
-def SAR32rCL : I <"sar", 0xD3, MRM7r > , UsesCL; // R32 >>>= cl
-def SAR8mCL : Im8 <"sar", 0xD2, MRM7m > , UsesCL; // [mem8] >>>= cl
-def SAR16mCL : Im16 <"sar", 0xD3, MRM7m >, OpSize, UsesCL; // [mem16] >>>= cl
-def SAR32mCL : Im32 <"sar", 0xD3, MRM7m > , UsesCL; // [mem32] >>>= cl
-
-def SAR8ri : Ii8 <"sar", 0xC0, MRM7r >; // R8 >>>= imm8
-def SAR16ri : Ii8 <"sar", 0xC1, MRM7r >, OpSize; // R16 >>>= imm8
-def SAR32ri : Ii8 <"sar", 0xC1, MRM7r >; // R32 >>>= imm8
-def SAR8mi : Im8i8 <"sar", 0xC0, MRM7m >; // [mem8] >>>= imm8
-def SAR16mi : Im16i8<"sar", 0xC1, MRM7m >, OpSize; // [mem16] >>>= imm8
-def SAR32mi : Im32i8<"sar", 0xC1, MRM7m >; // [mem32] >>>= imm8
-
-def SHLD32rrCL : I <"shld", 0xA5, MRMDestReg>, TB, UsesCL; // R32 <<= R32,R32 cl
-def SHLD32mrCL : Im32 <"shld", 0xA5, MRMDestMem>, TB, UsesCL; // [mem32] <<= [mem32],R32 cl
-def SHLD32rri8 : Ii8 <"shld", 0xA4, MRMDestReg>, TB; // R32 <<= R32,R32 imm8
-def SHLD32mri8 : Im32i8<"shld", 0xA4, MRMDestMem>, TB; // [mem32] <<= [mem32],R32 imm8
-
-def SHRD32rrCL : I <"shrd", 0xAD, MRMDestReg>, TB, UsesCL; // R32 >>= R32,R32 cl
-def SHRD32mrCL : Im32 <"shrd", 0xAD, MRMDestMem>, TB, UsesCL; // [mem32] >>= [mem32],R32 cl
-def SHRD32rri8 : Ii8 <"shrd", 0xAC, MRMDestReg>, TB; // R32 >>= R32,R32 imm8
-def SHRD32mri8 : Im32i8<"shrd", 0xAC, MRMDestMem>, TB; // [mem32] >>= [mem32],R32 imm8
-
-
-// Arithmetic...
-def ADD8rr : I <"add", 0x00, MRMDestReg>, Pattern<(set R8 , (plus R8 , R8 ))>;
-def ADD16rr : I <"add", 0x01, MRMDestReg>, OpSize, Pattern<(set R16, (plus R16, R16))>;
-def ADD32rr : I <"add", 0x01, MRMDestReg>, Pattern<(set R32, (plus R32, R32))>;
-def ADD8mr : Im8 <"add", 0x00, MRMDestMem>; // [mem8] += R8
-def ADD16mr : Im16 <"add", 0x01, MRMDestMem>, OpSize; // [mem16] += R16
-def ADD32mr : Im32 <"add", 0x01, MRMDestMem>; // [mem32] += R32
-def ADD8rm : Im8 <"add", 0x02, MRMSrcMem >; // R8 += [mem8]
-def ADD16rm : Im16 <"add", 0x03, MRMSrcMem >, OpSize; // R16 += [mem16]
-def ADD32rm : Im32 <"add", 0x03, MRMSrcMem >; // R32 += [mem32]
-
-def ADD8ri : Ii8 <"add", 0x80, MRM0r >, Pattern<(set R8 , (plus R8 , imm))>;
-def ADD16ri : Ii16 <"add", 0x81, MRM0r >, OpSize, Pattern<(set R16, (plus R16, imm))>;
-def ADD32ri : Ii32 <"add", 0x81, MRM0r >, Pattern<(set R32, (plus R32, imm))>;
-def ADD8mi : Im8i8 <"add", 0x80, MRM0m >; // [mem8] += I8
-def ADD16mi : Im16i16<"add", 0x81, MRM0m >, OpSize; // [mem16] += I16
-def ADD32mi : Im32i32<"add", 0x81, MRM0m >; // [mem32] += I32
-
-def ADD16ri8 : Ii8 <"add", 0x83, MRM0r >, OpSize; // ADDri with sign extended 8 bit imm
-def ADD32ri8 : Ii8 <"add", 0x83, MRM0r >;
-def ADD16mi8 : Im16i8<"add", 0x83, MRM0m >, OpSize; // [mem16] += I8
-def ADD32mi8 : Im32i8<"add", 0x83, MRM0m >; // [mem32] += I8
-
-def ADC32rr : I <"adc", 0x11, MRMDestReg>; // R32 += R32+Carry
-def ADC32mr : Im32 <"adc", 0x11, MRMDestMem>; // [mem32] += R32+Carry
-def ADC32rm : Im32 <"adc", 0x13, MRMSrcMem >; // R32 += [mem32]+Carry
-def ADC32ri : Ii32 <"adc", 0x81, MRM2r >; // R32 += I32+Carry
-def ADC32ri8 : Ii8 <"adc", 0x83, MRM2r >; // R32 += I8+Carry
-def ADC32mi : Im32i32<"adc", 0x81, MRM2m >; // [mem32] += I32+Carry
-def ADC32mi8 : Im32i8 <"adc", 0x83, MRM2m >; // [mem32] += I8+Carry
-
-def SUB8rr : I <"sub", 0x28, MRMDestReg>, Pattern<(set R8 , (minus R8 , R8 ))>;
-def SUB16rr : I <"sub", 0x29, MRMDestReg>, OpSize, Pattern<(set R16, (minus R16, R16))>;
-def SUB32rr : I <"sub", 0x29, MRMDestReg>, Pattern<(set R32, (minus R32, R32))>;
-def SUB8mr : Im8 <"sub", 0x28, MRMDestMem>; // [mem8] -= R8
-def SUB16mr : Im16 <"sub", 0x29, MRMDestMem>, OpSize; // [mem16] -= R16
-def SUB32mr : Im32 <"sub", 0x29, MRMDestMem>; // [mem32] -= R32
-def SUB8rm : Im8 <"sub", 0x2A, MRMSrcMem >; // R8 -= [mem8]
-def SUB16rm : Im16 <"sub", 0x2B, MRMSrcMem >, OpSize; // R16 -= [mem16]
-def SUB32rm : Im32 <"sub", 0x2B, MRMSrcMem >; // R32 -= [mem32]
-
-def SUB8ri : Ii8 <"sub", 0x80, MRM5r >, Pattern<(set R8 , (minus R8 , imm))>;
-def SUB16ri : Ii16 <"sub", 0x81, MRM5r >, OpSize, Pattern<(set R16, (minus R16, imm))>;
-def SUB32ri : Ii32 <"sub", 0x81, MRM5r >, Pattern<(set R32, (minus R32, imm))>;
-def SUB8mi : Im8i8 <"sub", 0x80, MRM5m >; // [mem8] -= I8
-def SUB16mi : Im16i16<"sub", 0x81, MRM5m >, OpSize; // [mem16] -= I16
-def SUB32mi : Im32i32<"sub", 0x81, MRM5m >; // [mem32] -= I32
-
-def SUB16ri8 : Ii8 <"sub", 0x83, MRM5r >, OpSize;
-def SUB32ri8 : Ii8 <"sub", 0x83, MRM5r >;
-def SUB16mi8 : Im16i8<"sub", 0x83, MRM5m >, OpSize; // [mem16] -= I8
-def SUB32mi8 : Im32i8<"sub", 0x83, MRM5m >; // [mem32] -= I8
-
-def SBB32rr : I <"sbb", 0x19, MRMDestReg>; // R32 -= R32+Carry
-def SBB32mr : Im32 <"sbb", 0x19, MRMDestMem>; // [mem32] -= R32+Carry
-def SBB32rm : Im32 <"sbb", 0x1B, MRMSrcMem >; // R32 -= [mem32]+Carry
-def SBB32ri : Ii32 <"sbb", 0x81, MRM3r >; // R32 -= I32+Carry
-def SBB32ri8 : Ii8 <"sbb", 0x83, MRM3r >; // R32 -= I8+Carry
-def SBB32mi : Im32i32<"sbb", 0x81, MRM3m >; // [mem32] -= I32+Carry
-def SBB32mi8 : Im32i8 <"sbb", 0x83, MRM3m >; // [mem32] -= I8+Carry
-
-def IMUL16rr : I <"imul", 0xAF, MRMSrcReg>, TB, OpSize, Pattern<(set R16, (times R16, R16))>;
-def IMUL32rr : I <"imul", 0xAF, MRMSrcReg>, TB , Pattern<(set R32, (times R32, R32))>;
-def IMUL16rm : Im16 <"imul", 0xAF, MRMSrcMem>, TB, OpSize;
-def IMUL32rm : Im32 <"imul", 0xAF, MRMSrcMem>, TB ;
+def SHL8rCL : I<0xD2, MRM4r, (ops R8 :$dst, R8 :$src),
+ "shl{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+def SHL16rCL : I<0xD3, MRM4r, (ops R16:$dst, R16:$src),
+ "shl{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+def SHL32rCL : I<0xD3, MRM4r, (ops R32:$dst, R32:$src),
+ "shl{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+
+def SHL8ri : Ii8<0xC0, MRM4r, (ops R8 :$dst, R8 :$src1, i8imm:$src2),
+ "shl{b} {$src2, $dst|$dst, $src2}">;
+let isConvertibleToThreeAddress = 1 in { // Can transform into LEA.
+def SHL16ri : Ii8<0xC1, MRM4r, (ops R16:$dst, R16:$src1, i8imm:$src2),
+ "shl{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def SHL32ri : Ii8<0xC1, MRM4r, (ops R32:$dst, R32:$src1, i8imm:$src2),
+ "shl{l} {$src2, $dst|$dst, $src2}">;
+}
+
+let isTwoAddress = 0 in {
+ def SHL8mCL : I<0xD2, MRM4m, (ops i8mem :$dst),
+ "shl{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def SHL16mCL : I<0xD3, MRM4m, (ops i16mem:$dst),
+ "shl{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+ def SHL32mCL : I<0xD3, MRM4m, (ops i32mem:$dst),
+ "shl{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def SHL8mi : Ii8<0xC0, MRM4m, (ops i8mem :$dst, i8imm:$src),
+ "shl{b} {$src, $dst|$dst, $src}">;
+ def SHL16mi : Ii8<0xC1, MRM4m, (ops i16mem:$dst, i8imm:$src),
+ "shl{w} {$src, $dst|$dst, $src}">, OpSize;
+ def SHL32mi : Ii8<0xC1, MRM4m, (ops i32mem:$dst, i8imm:$src),
+ "shl{l} {$src, $dst|$dst, $src}">;
+}
+
+def SHR8rCL : I<0xD2, MRM5r, (ops R8 :$dst, R8 :$src),
+ "shr{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+def SHR16rCL : I<0xD3, MRM5r, (ops R16:$dst, R16:$src),
+ "shr{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+def SHR32rCL : I<0xD3, MRM5r, (ops R32:$dst, R32:$src),
+ "shr{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+
+def SHR8ri : Ii8<0xC0, MRM5r, (ops R8:$dst, R8:$src1, i8imm:$src2),
+ "shr{b} {$src2, $dst|$dst, $src2}">;
+def SHR16ri : Ii8<0xC1, MRM5r, (ops R16:$dst, R16:$src1, i8imm:$src2),
+ "shr{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def SHR32ri : Ii8<0xC1, MRM5r, (ops R32:$dst, R32:$src1, i8imm:$src2),
+ "shr{l} {$src2, $dst|$dst, $src2}">;
+
+let isTwoAddress = 0 in {
+ def SHR8mCL : I<0xD2, MRM5m, (ops i8mem :$dst),
+ "shr{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def SHR16mCL : I<0xD3, MRM5m, (ops i16mem:$dst),
+ "shr{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+ def SHR32mCL : I<0xD3, MRM5m, (ops i32mem:$dst),
+ "shr{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def SHR8mi : Ii8<0xC0, MRM5m, (ops i8mem :$dst, i8imm:$src),
+ "shr{b} {$src, $dst|$dst, $src}">;
+ def SHR16mi : Ii8<0xC1, MRM5m, (ops i16mem:$dst, i8imm:$src),
+ "shr{w} {$src, $dst|$dst, $src}">, OpSize;
+ def SHR32mi : Ii8<0xC1, MRM5m, (ops i32mem:$dst, i8imm:$src),
+ "shr{l} {$src, $dst|$dst, $src}">;
+}
+
+def SAR8rCL : I<0xD2, MRM7r, (ops R8 :$dst, R8 :$src),
+ "sar{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+def SAR16rCL : I<0xD3, MRM7r, (ops R16:$dst, R16:$src),
+ "sar{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+def SAR32rCL : I<0xD3, MRM7r, (ops R32:$dst, R32:$src),
+ "sar{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+
+def SAR8ri : Ii8<0xC0, MRM7r, (ops R8 :$dst, R8 :$src1, i8imm:$src2),
+ "sar{b} {$src2, $dst|$dst, $src2}">;
+def SAR16ri : Ii8<0xC1, MRM7r, (ops R16:$dst, R16:$src1, i8imm:$src2),
+ "sar{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def SAR32ri : Ii8<0xC1, MRM7r, (ops R32:$dst, R32:$src1, i8imm:$src2),
+ "sar{l} {$src2, $dst|$dst, $src2}">;
+let isTwoAddress = 0 in {
+ def SAR8mCL : I<0xD2, MRM7m, (ops i8mem :$dst),
+ "sar{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def SAR16mCL : I<0xD3, MRM7m, (ops i16mem:$dst),
+ "sar{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+ def SAR32mCL : I<0xD3, MRM7m, (ops i32mem:$dst),
+ "sar{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def SAR8mi : Ii8<0xC0, MRM7m, (ops i8mem :$dst, i8imm:$src),
+ "sar{b} {$src, $dst|$dst, $src}">;
+ def SAR16mi : Ii8<0xC1, MRM7m, (ops i16mem:$dst, i8imm:$src),
+ "sar{w} {$src, $dst|$dst, $src}">, OpSize;
+ def SAR32mi : Ii8<0xC1, MRM7m, (ops i32mem:$dst, i8imm:$src),
+ "sar{l} {$src, $dst|$dst, $src}">;
+}
+
+// Rotate instructions
+// FIXME: provide shorter instructions when imm8 == 1
+def ROL8rCL : I<0xD2, MRM0r, (ops R8 :$dst, R8 :$src),
+ "rol{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+def ROL16rCL : I<0xD3, MRM0r, (ops R16:$dst, R16:$src),
+ "rol{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+def ROL32rCL : I<0xD3, MRM0r, (ops R32:$dst, R32:$src),
+ "rol{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+
+def ROL8ri : Ii8<0xC0, MRM0r, (ops R8 :$dst, R8 :$src1, i8imm:$src2),
+ "rol{b} {$src2, $dst|$dst, $src2}">;
+def ROL16ri : Ii8<0xC1, MRM0r, (ops R16:$dst, R16:$src1, i8imm:$src2),
+ "rol{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def ROL32ri : Ii8<0xC1, MRM0r, (ops R32:$dst, R32:$src1, i8imm:$src2),
+ "rol{l} {$src2, $dst|$dst, $src2}">;
+
+let isTwoAddress = 0 in {
+ def ROL8mCL : I<0xD2, MRM0m, (ops i8mem :$dst),
+ "rol{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def ROL16mCL : I<0xD3, MRM0m, (ops i16mem:$dst),
+ "rol{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+ def ROL32mCL : I<0xD3, MRM0m, (ops i32mem:$dst),
+ "rol{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def ROL8mi : Ii8<0xC0, MRM0m, (ops i8mem :$dst, i8imm:$src),
+ "rol{b} {$src, $dst|$dst, $src}">;
+ def ROL16mi : Ii8<0xC1, MRM0m, (ops i16mem:$dst, i8imm:$src),
+ "rol{w} {$src, $dst|$dst, $src}">, OpSize;
+ def ROL32mi : Ii8<0xC1, MRM0m, (ops i32mem:$dst, i8imm:$src),
+ "rol{l} {$src, $dst|$dst, $src}">;
+}
+
+def ROR8rCL : I<0xD2, MRM1r, (ops R8 :$dst, R8 :$src),
+ "ror{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+def ROR16rCL : I<0xD3, MRM1r, (ops R16:$dst, R16:$src),
+ "ror{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+def ROR32rCL : I<0xD3, MRM1r, (ops R32:$dst, R32:$src),
+ "ror{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+
+def ROR8ri : Ii8<0xC0, MRM1r, (ops R8 :$dst, R8 :$src1, i8imm:$src2),
+ "ror{b} {$src2, $dst|$dst, $src2}">;
+def ROR16ri : Ii8<0xC1, MRM1r, (ops R16:$dst, R16:$src1, i8imm:$src2),
+ "ror{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def ROR32ri : Ii8<0xC1, MRM1r, (ops R32:$dst, R32:$src1, i8imm:$src2),
+ "ror{l} {$src2, $dst|$dst, $src2}">;
+let isTwoAddress = 0 in {
+ def ROR8mCL : I<0xD2, MRM1m, (ops i8mem :$dst),
+ "ror{b} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def ROR16mCL : I<0xD3, MRM1m, (ops i16mem:$dst),
+ "ror{w} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>, OpSize;
+ def ROR32mCL : I<0xD3, MRM1m, (ops i32mem:$dst),
+ "ror{l} {%cl, $dst|$dst, %CL}">, Imp<[CL],[]>;
+ def ROR8mi : Ii8<0xC0, MRM1m, (ops i8mem :$dst, i8imm:$src),
+ "ror{b} {$src, $dst|$dst, $src}">;
+ def ROR16mi : Ii8<0xC1, MRM1m, (ops i16mem:$dst, i8imm:$src),
+ "ror{w} {$src, $dst|$dst, $src}">, OpSize;
+ def ROR32mi : Ii8<0xC1, MRM1m, (ops i32mem:$dst, i8imm:$src),
+ "ror{l} {$src, $dst|$dst, $src}">;
+}
+
+
+
+// Double shift instructions (generalizations of rotate)
+
+def SHLD32rrCL : I<0xA5, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
+ "shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}">,
+ Imp<[CL],[]>, TB;
+def SHRD32rrCL : I<0xAD, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
+ "shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}">,
+ Imp<[CL],[]>, TB;
+def SHLD16rrCL : I<0xA5, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2),
+ "shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}">,
+ Imp<[CL],[]>, TB, OpSize;
+def SHRD16rrCL : I<0xAD, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2),
+ "shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}">,
+ Imp<[CL],[]>, TB, OpSize;
+
+let isCommutable = 1 in { // These instructions commute to each other.
+def SHLD32rri8 : Ii8<0xA4, MRMDestReg,
+ (ops R32:$dst, R32:$src1, R32:$src2, i8imm:$src3),
+ "shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}">, TB;
+def SHRD32rri8 : Ii8<0xAC, MRMDestReg,
+ (ops R32:$dst, R32:$src1, R32:$src2, i8imm:$src3),
+ "shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}">, TB;
+def SHLD16rri8 : Ii8<0xA4, MRMDestReg,
+ (ops R16:$dst, R16:$src1, R16:$src2, i8imm:$src3),
+ "shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}">,
+ TB, OpSize;
+def SHRD16rri8 : Ii8<0xAC, MRMDestReg,
+ (ops R16:$dst, R16:$src1, R16:$src2, i8imm:$src3),
+ "shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}">,
+ TB, OpSize;
+}
+
+let isTwoAddress = 0 in {
+ def SHLD32mrCL : I<0xA5, MRMDestMem, (ops i32mem:$dst, R32:$src2),
+ "shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}">,
+ Imp<[CL],[]>, TB;
+ def SHRD32mrCL : I<0xAD, MRMDestMem, (ops i32mem:$dst, R32:$src2),
+ "shrd{l} {%cl, $src2, $dst|$dst, $src2, %CL}">,
+ Imp<[CL],[]>, TB;
+ def SHLD32mri8 : Ii8<0xA4, MRMDestMem,
+ (ops i32mem:$dst, R32:$src2, i8imm:$src3),
+ "shld{l} {$src3, $src2, $dst|$dst, $src2, $src3}">, TB;
+ def SHRD32mri8 : Ii8<0xAC, MRMDestMem,
+ (ops i32mem:$dst, R32:$src2, i8imm:$src3),
+ "shrd{l} {$src3, $src2, $dst|$dst, $src2, $src3}">, TB;
+
+ def SHLD16mrCL : I<0xA5, MRMDestMem, (ops i16mem:$dst, R16:$src2),
+ "shld{w} {%cl, $src2, $dst|$dst, $src2, %CL}">,
+ Imp<[CL],[]>, TB, OpSize;
+ def SHRD16mrCL : I<0xAD, MRMDestMem, (ops i16mem:$dst, R16:$src2),
+ "shrd{w} {%cl, $src2, $dst|$dst, $src2, %CL}">,
+ Imp<[CL],[]>, TB, OpSize;
+ def SHLD16mri8 : Ii8<0xA4, MRMDestMem,
+ (ops i16mem:$dst, R16:$src2, i8imm:$src3),
+ "shld{w} {$src3, $src2, $dst|$dst, $src2, $src3}">,
+ TB, OpSize;
+ def SHRD16mri8 : Ii8<0xAC, MRMDestMem,
+ (ops i16mem:$dst, R16:$src2, i8imm:$src3),
+ "shrd{w} {$src3, $src2, $dst|$dst, $src2, $src3}">,
+ TB, OpSize;
+}
+
+
+// Arithmetic.
+let isCommutable = 1 in { // X = ADD Y, Z --> X = ADD Z, Y
+def ADD8rr : I<0x00, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2),
+ "add{b} {$src2, $dst|$dst, $src2}">;
+let isConvertibleToThreeAddress = 1 in { // Can transform into LEA.
+def ADD16rr : I<0x01, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2),
+ "add{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def ADD32rr : I<0x01, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
+ "add{l} {$src2, $dst|$dst, $src2}">;
+} // end isConvertibleToThreeAddress
+} // end isCommutable
+def ADD8rm : I<0x02, MRMSrcMem, (ops R8 :$dst, R8 :$src1, i8mem :$src2),
+ "add{b} {$src2, $dst|$dst, $src2}">;
+def ADD16rm : I<0x03, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
+ "add{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def ADD32rm : I<0x03, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
+ "add{l} {$src2, $dst|$dst, $src2}">;
+
+def ADD8ri : Ii8<0x80, MRM0r, (ops R8:$dst, R8:$src1, i8imm:$src2),
+ "add{b} {$src2, $dst|$dst, $src2}">;
+
+let isConvertibleToThreeAddress = 1 in { // Can transform into LEA.
+def ADD16ri : Ii16<0x81, MRM0r, (ops R16:$dst, R16:$src1, i16imm:$src2),
+ "add{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def ADD32ri : Ii32<0x81, MRM0r, (ops R32:$dst, R32:$src1, i32imm:$src2),
+ "add{l} {$src2, $dst|$dst, $src2}">;
+}
+
+def ADD16ri8 : Ii8<0x83, MRM0r, (ops R16:$dst, R16:$src1, i8imm:$src2),
+ "add{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def ADD32ri8 : Ii8<0x83, MRM0r, (ops R32:$dst, R32:$src1, i8imm:$src2),
+ "add{l} {$src2, $dst|$dst, $src2}">;
+
+let isTwoAddress = 0 in {
+ def ADD8mr : I<0x00, MRMDestMem, (ops i8mem :$dst, R8 :$src2),
+ "add{b} {$src2, $dst|$dst, $src2}">;
+ def ADD16mr : I<0x01, MRMDestMem, (ops i16mem:$dst, R16:$src2),
+ "add{w} {$src2, $dst|$dst, $src2}">, OpSize;
+ def ADD32mr : I<0x01, MRMDestMem, (ops i32mem:$dst, R32:$src2),
+ "add{l} {$src2, $dst|$dst, $src2}">;
+ def ADD8mi : Ii8<0x80, MRM0m, (ops i8mem :$dst, i8imm :$src2),
+ "add{b} {$src2, $dst|$dst, $src2}">;
+ def ADD16mi : Ii16<0x81, MRM0m, (ops i16mem:$dst, i16imm:$src2),
+ "add{w} {$src2, $dst|$dst, $src2}">, OpSize;
+ def ADD32mi : Ii32<0x81, MRM0m, (ops i32mem:$dst, i32imm:$src2),
+ "add{l} {$src2, $dst|$dst, $src2}">;
+ def ADD16mi8 : Ii8<0x83, MRM0m, (ops i16mem:$dst, i8imm :$src2),
+ "add{w} {$src2, $dst|$dst, $src2}">, OpSize;
+ def ADD32mi8 : Ii8<0x83, MRM0m, (ops i32mem:$dst, i8imm :$src2),
+ "add{l} {$src2, $dst|$dst, $src2}">;
+}
+
+let isCommutable = 1 in { // X = ADC Y, Z --> X = ADC Z, Y
+def ADC32rr : I<0x11, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
+ "adc{l} {$src2, $dst|$dst, $src2}">;
+}
+def ADC32rm : I<0x13, MRMSrcMem , (ops R32:$dst, R32:$src1, i32mem:$src2),
+ "adc{l} {$src2, $dst|$dst, $src2}">;
+def ADC32ri : Ii32<0x81, MRM2r, (ops R32:$dst, R32:$src1, i32imm:$src2),
+ "adc{l} {$src2, $dst|$dst, $src2}">;
+def ADC32ri8 : Ii8<0x83, MRM2r, (ops R32:$dst, R32:$src1, i8imm:$src2),
+ "adc{l} {$src2, $dst|$dst, $src2}">;
+
+let isTwoAddress = 0 in {
+ def ADC32mr : I<0x11, MRMDestMem, (ops i32mem:$dst, R32:$src2),
+ "adc{l} {$src2, $dst|$dst, $src2}">;
+ def ADC32mi : Ii32<0x81, MRM2m, (ops i32mem:$dst, i32imm:$src2),
+ "adc{l} {$src2, $dst|$dst, $src2}">;
+ def ADC32mi8 : Ii8<0x83, MRM2m, (ops i32mem:$dst, i8imm :$src2),
+ "adc{l} {$src2, $dst|$dst, $src2}">;
+}
+
+def SUB8rr : I<0x28, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2),
+ "sub{b} {$src2, $dst|$dst, $src2}">;
+def SUB16rr : I<0x29, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2),
+ "sub{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def SUB32rr : I<0x29, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
+ "sub{l} {$src2, $dst|$dst, $src2}">;
+def SUB8rm : I<0x2A, MRMSrcMem, (ops R8 :$dst, R8 :$src1, i8mem :$src2),
+ "sub{b} {$src2, $dst|$dst, $src2}">;
+def SUB16rm : I<0x2B, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
+ "sub{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def SUB32rm : I<0x2B, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
+ "sub{l} {$src2, $dst|$dst, $src2}">;
+
+def SUB8ri : Ii8 <0x80, MRM5r, (ops R8:$dst, R8:$src1, i8imm:$src2),
+ "sub{b} {$src2, $dst|$dst, $src2}">;
+def SUB16ri : Ii16<0x81, MRM5r, (ops R16:$dst, R16:$src1, i16imm:$src2),
+ "sub{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def SUB32ri : Ii32<0x81, MRM5r, (ops R32:$dst, R32:$src1, i32imm:$src2),
+ "sub{l} {$src2, $dst|$dst, $src2}">;
+def SUB16ri8 : Ii8<0x83, MRM5r, (ops R16:$dst, R16:$src1, i8imm:$src2),
+ "sub{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def SUB32ri8 : Ii8<0x83, MRM5r, (ops R32:$dst, R32:$src1, i8imm:$src2),
+ "sub{l} {$src2, $dst|$dst, $src2}">;
+let isTwoAddress = 0 in {
+ def SUB8mr : I<0x28, MRMDestMem, (ops i8mem :$dst, R8 :$src2),
+ "sub{b} {$src2, $dst|$dst, $src2}">;
+ def SUB16mr : I<0x29, MRMDestMem, (ops i16mem:$dst, R16:$src2),
+ "sub{w} {$src2, $dst|$dst, $src2}">, OpSize;
+ def SUB32mr : I<0x29, MRMDestMem, (ops i32mem:$dst, R32:$src2),
+ "sub{l} {$src2, $dst|$dst, $src2}">;
+ def SUB8mi : Ii8<0x80, MRM5m, (ops i8mem :$dst, i8imm:$src2),
+ "sub{b} {$src2, $dst|$dst, $src2}">;
+ def SUB16mi : Ii16<0x81, MRM5m, (ops i16mem:$dst, i16imm:$src2),
+ "sub{w} {$src2, $dst|$dst, $src2}">, OpSize;
+ def SUB32mi : Ii32<0x81, MRM5m, (ops i32mem:$dst, i32imm:$src2),
+ "sub{l} {$src2, $dst|$dst, $src2}">;
+ def SUB16mi8 : Ii8<0x83, MRM5m, (ops i16mem:$dst, i8imm :$src2),
+ "sub{w} {$src2, $dst|$dst, $src2}">, OpSize;
+ def SUB32mi8 : Ii8<0x83, MRM5m, (ops i32mem:$dst, i8imm :$src2),
+ "sub{l} {$src2, $dst|$dst, $src2}">;
+}
+
+def SBB32rr : I<0x19, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
+ "sbb{l} {$src2, $dst|$dst, $src2}">;
+
+let isTwoAddress = 0 in {
+ def SBB32mr : I<0x19, MRMDestMem, (ops i32mem:$dst, R32:$src2),
+ "sbb{l} {$src2, $dst|$dst, $src2}">;
+ def SBB8mi : Ii32<0x80, MRM3m, (ops i8mem:$dst, i8imm:$src2),
+ "sbb{b} {$src2, $dst|$dst, $src2}">;
+ def SBB16mi : Ii32<0x81, MRM3m, (ops i16mem:$dst, i16imm:$src2),
+ "sbb{w} {$src2, $dst|$dst, $src2}">, OpSize;
+ def SBB32mi : Ii32<0x81, MRM3m, (ops i32mem:$dst, i32imm:$src2),
+ "sbb{l} {$src2, $dst|$dst, $src2}">;
+ def SBB16mi8 : Ii8<0x83, MRM3m, (ops i16mem:$dst, i8imm :$src2),
+ "sbb{w} {$src2, $dst|$dst, $src2}">, OpSize;
+ def SBB32mi8 : Ii8<0x83, MRM3m, (ops i32mem:$dst, i8imm :$src2),
+ "sbb{l} {$src2, $dst|$dst, $src2}">;
+}
+def SBB8ri : Ii8<0x80, MRM3r, (ops R8:$dst, R8:$src1, i8imm:$src2),
+ "sbb{b} {$src2, $dst|$dst, $src2}">;
+def SBB16ri : Ii16<0x81, MRM3r, (ops R16:$dst, R16:$src1, i16imm:$src2),
+ "sbb{w} {$src2, $dst|$dst, $src2}">, OpSize;
+
+def SBB32rm : I<0x1B, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
+ "sbb{l} {$src2, $dst|$dst, $src2}">;
+def SBB32ri : Ii32<0x81, MRM3r, (ops R32:$dst, R32:$src1, i32imm:$src2),
+ "sbb{l} {$src2, $dst|$dst, $src2}">;
+
+def SBB16ri8 : Ii8<0x83, MRM3r, (ops R16:$dst, R16:$src1, i8imm:$src2),
+ "sbb{w} {$src2, $dst|$dst, $src2}">, OpSize;
+def SBB32ri8 : Ii8<0x83, MRM3r, (ops R32:$dst, R32:$src1, i8imm:$src2),
+ "sbb{l} {$src2, $dst|$dst, $src2}">;
+
+let isCommutable = 1 in { // X = IMUL Y, Z --> X = IMUL Z, Y
+def IMUL16rr : I<0xAF, MRMSrcReg, (ops R16:$dst, R16:$src1, R16:$src2),
+ "imul{w} {$src2, $dst|$dst, $src2}">, TB, OpSize;
+def IMUL32rr : I<0xAF, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
+ "imul{l} {$src2, $dst|$dst, $src2}">, TB;
+}
+def IMUL16rm : I<0xAF, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
+ "imul{w} {$src2, $dst|$dst, $src2}">, TB, OpSize;
+def IMUL32rm : I<0xAF, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
+ "imul{l} {$src2, $dst|$dst, $src2}">, TB;