Newer
Older
Chris Lattner
committed
def SAR8ri : Ii8<0xC0, MRM7r, (ops R8 :$dst, R8 :$src1, i8imm:$src2),
"sar{b} {$src2, $dst|$dst, $src2}",
[(set R8:$dst, (sra R8:$src1, (i8 imm:$src2)))]>;
def SAR16ri : Ii8<0xC1, MRM7r, (ops R16:$dst, R16:$src1, i8imm:$src2),
"sar{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (sra R16:$src1, (i8 imm:$src2)))]>,
OpSize;
def SAR32ri : Ii8<0xC1, MRM7r, (ops R32:$dst, R32:$src1, i8imm:$src2),
"sar{l} {$src2, $dst|$dst, $src2}",
Chris Lattner
committed
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}", []>;
Chris Lattner
committed
}
// 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)
Chris Lattner
committed
def SHLD32rrCL : I<0xA5, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
"shld{l} {%cl, $src2, $dst|$dst, $src2, %CL}", []>,
Imp<[CL],[]>, TB;
Chris Lattner
committed
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;
Chris Lattner
committed
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;
Chris Lattner
committed
}
Chris Lattner
committed
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;
Chris Lattner
committed
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}",
[(set R8:$dst, (add R8:$src1, R8:$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}",
[(set R16:$dst, (add R16:$src1, R16:$src2))]>, OpSize;
def ADD32rr : I<0x01, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
"add{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (add R32:$src1, R32:$src2))]>;
} // end isConvertibleToThreeAddress
} // end isCommutable
def ADD8rm : I<0x02, MRMSrcMem, (ops R8 :$dst, R8 :$src1, i8mem :$src2),
Evan Cheng
committed
"add{b} {$src2, $dst|$dst, $src2}",
[(set R8:$dst, (add R8:$src1, (load addr:$src2)))]>;
def ADD16rm : I<0x03, MRMSrcMem, (ops R16:$dst, R16:$src1, i16mem:$src2),
Evan Cheng
committed
"add{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (add R16:$src1, (load addr:$src2)))]>, OpSize;
def ADD32rm : I<0x03, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
Evan Cheng
committed
"add{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (add R32:$src1, (load addr:$src2)))]>;
def ADD8ri : Ii8<0x80, MRM0r, (ops R8:$dst, R8:$src1, i8imm:$src2),
"add{b} {$src2, $dst|$dst, $src2}",
[(set R8:$dst, (add R8:$src1, imm:$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}",
[(set R16:$dst, (add R16:$src1, imm:$src2))]>, OpSize;
def ADD32ri : Ii32<0x81, MRM0r, (ops R32:$dst, R32:$src1, i32imm:$src2),
"add{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (add R32:$src1, imm:$src2))]>;
// FIXME: move ADD16ri8 above ADD16ri to optimize for space.
def ADD16ri8 : Ii8<0x83, MRM0r, (ops R16:$dst, R16:$src1, i16i8imm:$src2),
"add{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (add R16:$src1, immSExt8:$src2))]>, OpSize;
def ADD32ri8 : Ii8<0x83, MRM0r, (ops R32:$dst, R32:$src1, i32i8imm:$src2),
"add{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (add R32:$src1, immSExt8:$src2))]>;
Chris Lattner
committed
let isTwoAddress = 0 in {
def ADD8mr : I<0x00, MRMDestMem, (ops i8mem :$dst, R8 :$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),
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}", []>;
Chris Lattner
committed
}
let isCommutable = 1 in { // X = ADC Y, Z --> X = ADC Z, Y
def ADC32rr : I<0x11, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
def ADC32rm : I<0x13, MRMSrcMem , (ops R32:$dst, R32:$src1, i32mem:$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}", []>;
Chris Lattner
committed
let isTwoAddress = 0 in {
def ADC32mr : I<0x11, MRMDestMem, (ops i32mem:$dst, R32:$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}", []>;
Chris Lattner
committed
}
def SUB8rr : I<0x28, MRMDestReg, (ops R8 :$dst, R8 :$src1, R8 :$src2),
"sub{b} {$src2, $dst|$dst, $src2}",
[(set R8:$dst, (sub R8:$src1, R8:$src2))]>;
def SUB16rr : I<0x29, MRMDestReg, (ops R16:$dst, R16:$src1, R16:$src2),
"sub{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (sub R16:$src1, R16:$src2))]>, OpSize;
def SUB32rr : I<0x29, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
"sub{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (sub R32:$src1, R32:$src2))]>;
def SUB8rm : I<0x2A, MRMSrcMem, (ops R8 :$dst, R8 :$src1, i8mem :$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),
Chris Lattner
committed
def SUB8ri : Ii8 <0x80, MRM5r, (ops R8:$dst, R8:$src1, i8imm:$src2),
"sub{b} {$src2, $dst|$dst, $src2}",
[(set R8:$dst, (sub R8:$src1, imm:$src2))]>;
Chris Lattner
committed
def SUB16ri : Ii16<0x81, MRM5r, (ops R16:$dst, R16:$src1, i16imm:$src2),
"sub{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (sub R16:$src1, imm:$src2))]>, OpSize;
Chris Lattner
committed
def SUB32ri : Ii32<0x81, MRM5r, (ops R32:$dst, R32:$src1, i32imm:$src2),
"sub{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (sub R32:$src1, imm:$src2))]>;
def SUB16ri8 : Ii8<0x83, MRM5r, (ops R16:$dst, R16:$src1, i16i8imm:$src2),
"sub{w} {$src2, $dst|$dst, $src2}",
[(set R16:$dst, (sub R16:$src1, immSExt8:$src2))]>, OpSize;
def SUB32ri8 : Ii8<0x83, MRM5r, (ops R32:$dst, R32:$src1, i32i8imm:$src2),
"sub{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (sub R32:$src1, immSExt8:$src2))]>;
Chris Lattner
committed
let isTwoAddress = 0 in {
def SUB8mr : I<0x28, MRMDestMem, (ops i8mem :$dst, R8 :$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),
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}", []>;
Chris Lattner
committed
}
def SBB32rr : I<0x19, MRMDestReg, (ops R32:$dst, R32:$src1, R32:$src2),
Chris Lattner
committed
let isTwoAddress = 0 in {
def SBB32mr : I<0x19, MRMDestMem, (ops i32mem:$dst, R32:$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}", []>;
Chris Lattner
committed
}
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;
Chris Lattner
committed
def SBB32rm : I<0x1B, MRMSrcMem, (ops R32:$dst, R32:$src1, i32mem:$src2),
Chris Lattner
committed
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;
Chris Lattner
committed
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}",
[(set R16:$dst, (mul R16:$src1, R16:$src2))]>, TB, OpSize;
def IMUL32rr : I<0xAF, MRMSrcReg, (ops R32:$dst, R32:$src1, R32:$src2),
"imul{l} {$src2, $dst|$dst, $src2}",
[(set R32:$dst, (mul R32:$src1, R32:$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),
} // end Two Address instructions
Chris Lattner
committed
// Suprisingly enough, these are not two address instructions!
def IMUL16rri : Ii16<0x69, MRMSrcReg, // R16 = R16*I16
(ops R16:$dst, R16:$src1, i16imm:$src2),
"imul{w} {$src2, $src1, $dst|$dst, $src1, $src2}",
[(set R16:$dst, (mul R16:$src1, imm:$src2))]>,
OpSize;
def IMUL32rri : Ii32<0x69, MRMSrcReg, // R32 = R32*I32
(ops R32:$dst, R32:$src1, i32imm:$src2),
"imul{l} {$src2, $src1, $dst|$dst, $src1, $src2}",
[(set R32:$dst, (mul R32:$src1, imm:$src2))]>;
def IMUL16rri8 : Ii8<0x6B, MRMSrcReg, // R16 = R16*I8
(ops R16:$dst, R16:$src1, i16i8imm:$src2),
"imul{w} {$src2, $src1, $dst|$dst, $src1, $src2}",
[(set R16:$dst, (mul R16:$src1, immSExt8:$src2))]>, OpSize;
def IMUL32rri8 : Ii8<0x6B, MRMSrcReg, // R32 = R32*I8
(ops R32:$dst, R32:$src1, i32i8imm:$src2),
"imul{l} {$src2, $src1, $dst|$dst, $src1, $src2}",
[(set R32:$dst, (mul R32:$src1, immSExt8:$src2))]>;
def IMUL16rmi : Ii16<0x69, MRMSrcMem, // R16 = [mem16]*I16
(ops R32:$dst, i16mem:$src1, i16imm:$src2),
"imul{w} {$src2, $src1, $dst|$dst, $src1, $src2}", []>, OpSize;
def IMUL32rmi : Ii32<0x69, MRMSrcMem, // R32 = [mem32]*I32
(ops R32:$dst, i32mem:$src1, i32imm:$src2),
"imul{l} {$src2, $src1, $dst|$dst, $src1, $src2}", []>;
def IMUL16rmi8 : Ii8<0x6B, MRMSrcMem, // R16 = [mem16]*I8
(ops R32:$dst, i16mem:$src1, i8imm :$src2),
"imul{w} {$src2, $src1, $dst|$dst, $src1, $src2}", []>, OpSize;
def IMUL32rmi8 : Ii8<0x6B, MRMSrcMem, // R32 = [mem32]*I8
(ops R32:$dst, i32mem:$src1, i8imm: $src2),
"imul{l} {$src2, $src1, $dst|$dst, $src1, $src2}", []>;
//===----------------------------------------------------------------------===//
// Test instructions are just like AND, except they don't generate a result.
//
Chris Lattner
committed
def TEST8rr : I<0x84, MRMDestReg, (ops R8:$src1, R8:$src2),
Chris Lattner
committed
def TEST16rr : I<0x85, MRMDestReg, (ops R16:$src1, R16:$src2),
"test{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
Chris Lattner
committed
def TEST32rr : I<0x85, MRMDestReg, (ops R32:$src1, R32:$src2),
Chris Lattner
committed
def TEST8mr : I<0x84, MRMDestMem, (ops i8mem :$src1, R8 :$src2),
Chris Lattner
committed
def TEST16mr : I<0x85, MRMDestMem, (ops i16mem:$src1, R16:$src2),
"test{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
Chris Lattner
committed
def TEST32mr : I<0x85, MRMDestMem, (ops i32mem:$src1, R32:$src2),
Chris Lattner
committed
def TEST8rm : I<0x84, MRMSrcMem, (ops R8 :$src1, i8mem :$src2),
Chris Lattner
committed
def TEST16rm : I<0x85, MRMSrcMem, (ops R16:$src1, i16mem:$src2),
"test{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
Chris Lattner
committed
def TEST32rm : I<0x85, MRMSrcMem, (ops R32:$src1, i32mem:$src2),
def TEST8ri : Ii8 <0xF6, MRM0r, // flags = R8 & imm8
(ops R8:$src1, i8imm:$src2),
"test{b} {$src2, $src1|$src1, $src2}", []>;
def TEST16ri : Ii16<0xF7, MRM0r, // flags = R16 & imm16
(ops R16:$src1, i16imm:$src2),
"test{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
def TEST32ri : Ii32<0xF7, MRM0r, // flags = R32 & imm32
(ops R32:$src1, i32imm:$src2),
"test{l} {$src2, $src1|$src1, $src2}", []>;
def TEST8mi : Ii8 <0xF6, MRM0m, // flags = [mem8] & imm8
(ops i32mem:$src1, i8imm:$src2),
"test{b} {$src2, $src1|$src1, $src2}", []>;
def TEST16mi : Ii16<0xF7, MRM0m, // flags = [mem16] & imm16
(ops i16mem:$src1, i16imm:$src2),
"test{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
def TEST32mi : Ii32<0xF7, MRM0m, // flags = [mem32] & imm32
(ops i32mem:$src1, i32imm:$src2),
"test{l} {$src2, $src1|$src1, $src2}", []>;
// Condition code ops, incl. set if equal/not equal/...
def SAHF : I<0x9E, RawFrm, (ops), "sahf", []>, Imp<[AH],[]>; // flags = AH
def LAHF : I<0x9F, RawFrm, (ops), "lahf", []>, Imp<[],[AH]>; // AH = flags
def SETBr : I<0x92, MRM0r,
(ops R8 :$dst), "setb $dst", []>, TB; // R8 = < unsign
def SETBm : I<0x92, MRM0m,
(ops i8mem:$dst), "setb $dst", []>, TB; // [mem8] = < unsign
def SETAEr : I<0x93, MRM0r,
(ops R8 :$dst), "setae $dst", []>, TB; // R8 = >= unsign
def SETAEm : I<0x93, MRM0m,
(ops i8mem:$dst), "setae $dst", []>, TB; // [mem8] = >= unsign
def SETEr : I<0x94, MRM0r,
(ops R8 :$dst), "sete $dst", []>, TB; // R8 = ==
def SETEm : I<0x94, MRM0m,
(ops i8mem:$dst), "sete $dst", []>, TB; // [mem8] = ==
def SETNEr : I<0x95, MRM0r,
(ops R8 :$dst), "setne $dst", []>, TB; // R8 = !=
def SETNEm : I<0x95, MRM0m,
(ops i8mem:$dst), "setne $dst", []>, TB; // [mem8] = !=
def SETBEr : I<0x96, MRM0r,
(ops R8 :$dst), "setbe $dst", []>, TB; // R8 = <= unsign
def SETBEm : I<0x96, MRM0m,
(ops i8mem:$dst), "setbe $dst", []>, TB; // [mem8] = <= unsign
def SETAr : I<0x97, MRM0r,
(ops R8 :$dst), "seta $dst", []>, TB; // R8 = > signed
def SETAm : I<0x97, MRM0m,
(ops i8mem:$dst), "seta $dst", []>, TB; // [mem8] = > signed
def SETSr : I<0x98, MRM0r,
(ops R8 :$dst), "sets $dst", []>, TB; // R8 = <sign bit>
def SETSm : I<0x98, MRM0m,
(ops i8mem:$dst), "sets $dst", []>, TB; // [mem8] = <sign bit>
def SETNSr : I<0x99, MRM0r,
(ops R8 :$dst), "setns $dst", []>, TB; // R8 = !<sign bit>
def SETNSm : I<0x99, MRM0m,
(ops i8mem:$dst), "setns $dst", []>, TB; // [mem8] = !<sign bit>
def SETPr : I<0x9A, MRM0r,
(ops R8 :$dst), "setp $dst", []>, TB; // R8 = parity
def SETPm : I<0x9A, MRM0m,
(ops i8mem:$dst), "setp $dst", []>, TB; // [mem8] = parity
(ops R8 :$dst), "setnp $dst", []>, TB; // R8 = not parity
(ops i8mem:$dst), "setnp $dst", []>, TB; // [mem8] = not parity
def SETLr : I<0x9C, MRM0r,
(ops R8 :$dst), "setl $dst", []>, TB; // R8 = < signed
def SETLm : I<0x9C, MRM0m,
(ops i8mem:$dst), "setl $dst", []>, TB; // [mem8] = < signed
def SETGEr : I<0x9D, MRM0r,
(ops R8 :$dst), "setge $dst", []>, TB; // R8 = >= signed
def SETGEm : I<0x9D, MRM0m,
(ops i8mem:$dst), "setge $dst", []>, TB; // [mem8] = >= signed
def SETLEr : I<0x9E, MRM0r,
(ops R8 :$dst), "setle $dst", []>, TB; // R8 = <= signed
def SETLEm : I<0x9E, MRM0m,
(ops i8mem:$dst), "setle $dst", []>, TB; // [mem8] = <= signed
def SETGr : I<0x9F, MRM0r,
(ops R8 :$dst), "setg $dst", []>, TB; // R8 = < signed
def SETGm : I<0x9F, MRM0m,
(ops i8mem:$dst), "setg $dst", []>, TB; // [mem8] = < signed
def CMP8rr : I<0x38, MRMDestReg,
(ops R8 :$src1, R8 :$src2),
def CMP16rr : I<0x39, MRMDestReg,
(ops R16:$src1, R16:$src2),
"cmp{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
def CMP32rr : I<0x39, MRMDestReg,
(ops R32:$src1, R32:$src2),
def CMP8mr : I<0x38, MRMDestMem,
(ops i8mem :$src1, R8 :$src2),
def CMP16mr : I<0x39, MRMDestMem,
(ops i16mem:$src1, R16:$src2),
"cmp{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
def CMP32mr : I<0x39, MRMDestMem,
(ops i32mem:$src1, R32:$src2),
def CMP8rm : I<0x3A, MRMSrcMem,
(ops R8 :$src1, i8mem :$src2),
def CMP16rm : I<0x3B, MRMSrcMem,
(ops R16:$src1, i16mem:$src2),
"cmp{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
def CMP32rm : I<0x3B, MRMSrcMem,
(ops R32:$src1, i32mem:$src2),
def CMP8ri : Ii8<0x80, MRM7r,
(ops R16:$src1, i8imm:$src2),
"cmp{b} {$src2, $src1|$src1, $src2}", []>;
def CMP16ri : Ii16<0x81, MRM7r,
(ops R16:$src1, i16imm:$src2),
"cmp{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
def CMP32ri : Ii32<0x81, MRM7r,
(ops R32:$src1, i32imm:$src2),
"cmp{l} {$src2, $src1|$src1, $src2}", []>;
def CMP8mi : Ii8 <0x80, MRM7m,
(ops i8mem :$src1, i8imm :$src2),
"cmp{b} {$src2, $src1|$src1, $src2}", []>;
def CMP16mi : Ii16<0x81, MRM7m,
(ops i16mem:$src1, i16imm:$src2),
"cmp{w} {$src2, $src1|$src1, $src2}", []>, OpSize;
def CMP32mi : Ii32<0x81, MRM7m,
(ops i32mem:$src1, i32imm:$src2),
"cmp{l} {$src2, $src1|$src1, $src2}", []>;
def MOVSX16rr8 : I<0xBE, MRMSrcReg, (ops R16:$dst, R8 :$src),
"movs{bw|x} {$src, $dst|$dst, $src}",
[(set R16:$dst, (sext R8:$src))]>, TB, OpSize;
def MOVSX16rm8 : I<0xBE, MRMSrcMem, (ops R16:$dst, i8mem :$src),
"movs{bw|x} {$src, $dst|$dst, $src}", []>, TB, OpSize;
def MOVSX32rr8 : I<0xBE, MRMSrcReg, (ops R32:$dst, R8 :$src),
"movs{bl|x} {$src, $dst|$dst, $src}",
[(set R32:$dst, (sext R8:$src))]>, TB;
def MOVSX32rm8 : I<0xBE, MRMSrcMem, (ops R32:$dst, i8mem :$src),
"movs{bl|x} {$src, $dst|$dst, $src}", []>, TB;
def MOVSX32rr16: I<0xBF, MRMSrcReg, (ops R32:$dst, R16:$src),
"movs{wl|x} {$src, $dst|$dst, $src}",
[(set R32:$dst, (sext R16:$src))]>, TB;
def MOVSX32rm16: I<0xBF, MRMSrcMem, (ops R32:$dst, i16mem:$src),
"movs{wl|x} {$src, $dst|$dst, $src}", []>, TB;
def MOVZX16rr8 : I<0xB6, MRMSrcReg, (ops R16:$dst, R8 :$src),
"movz{bw|x} {$src, $dst|$dst, $src}",
[(set R16:$dst, (zext R8:$src))]>, TB, OpSize;
def MOVZX16rm8 : I<0xB6, MRMSrcMem, (ops R16:$dst, i8mem :$src),
"movz{bw|x} {$src, $dst|$dst, $src}", []>, TB, OpSize;
def MOVZX32rr8 : I<0xB6, MRMSrcReg, (ops R32:$dst, R8 :$src),
"movz{bl|x} {$src, $dst|$dst, $src}",
[(set R32:$dst, (zext R8:$src))]>, TB;
def MOVZX32rm8 : I<0xB6, MRMSrcMem, (ops R32:$dst, i8mem :$src),
"movz{bl|x} {$src, $dst|$dst, $src}", []>, TB;
def MOVZX32rr16: I<0xB7, MRMSrcReg, (ops R32:$dst, R16:$src),
"movz{wl|x} {$src, $dst|$dst, $src}",
[(set R32:$dst, (zext R16:$src))]>, TB;
def MOVZX32rm16: I<0xB7, MRMSrcMem, (ops R32:$dst, i16mem:$src),
"movz{wl|x} {$src, $dst|$dst, $src}", []>, TB;
//===----------------------------------------------------------------------===//
// XMM Floating point support (requires SSE2)
//===----------------------------------------------------------------------===//
def MOVSSrr : I<0x10, MRMSrcReg, (ops V4F4:$dst, V4F4:$src),
def MOVSSrm : I<0x10, MRMSrcMem, (ops V4F4:$dst, f32mem:$src),
def MOVSSmr : I<0x11, MRMDestMem, (ops f32mem:$dst, V4F4:$src),
def MOVSDrr : I<0x10, MRMSrcReg, (ops V2F8:$dst, V2F8:$src),
def MOVSDrm : I<0x10, MRMSrcMem, (ops V2F8:$dst, f64mem:$src),
def MOVSDmr : I<0x11, MRMDestMem, (ops f64mem:$dst, V2F8:$src),
def CVTTSD2SIrr: I<0x2C, MRMSrcReg, (ops R32:$dst, V2F8:$src),
"cvttsd2si {$src, $dst|$dst, $src}",
[(set R32:$dst, (fp_to_sint V2F8:$src))]>, XD;
def CVTTSD2SIrm: I<0x2C, MRMSrcMem, (ops R32:$dst, f64mem:$src),
def CVTTSS2SIrr: I<0x2C, MRMSrcReg, (ops R32:$dst, V4F4:$src),
"cvttss2si {$src, $dst|$dst, $src}",
[(set R32:$dst, (fp_to_sint V4F4:$src))]>, XS;
def CVTTSS2SIrm: I<0x2C, MRMSrcMem, (ops R32:$dst, f32mem:$src),
def CVTSD2SSrr: I<0x5A, MRMSrcReg, (ops V4F4:$dst, V2F8:$src),
"cvtsd2ss {$src, $dst|$dst, $src}",
[(set V4F4:$dst, (fround V2F8:$src))]>, XS;
def CVTSD2SSrm: I<0x5A, MRMSrcMem, (ops V4F4:$dst, f64mem:$src),
def CVTSS2SDrr: I<0x5A, MRMSrcReg, (ops V2F8:$dst, V4F4:$src),
"cvtss2sd {$src, $dst|$dst, $src}",
[(set V2F8:$dst, (fextend V4F4:$src))]>, XD;
def CVTSS2SDrm: I<0x5A, MRMSrcMem, (ops V2F8:$dst, f32mem:$src),
def CVTSI2SSrr: I<0x2A, MRMSrcReg, (ops V4F4:$dst, R32:$src),
"cvtsi2ss {$src, $dst|$dst, $src}",
[(set V4F4:$dst, (sint_to_fp R32:$src))]>, XS;
def CVTSI2SSrm: I<0x2A, MRMSrcMem, (ops V4F4:$dst, i32mem:$src),
def CVTSI2SDrr: I<0x2A, MRMSrcReg, (ops V2F8:$dst, R32:$src),
"cvtsi2sd {$src, $dst|$dst, $src}",
[(set V2F8:$dst, (sint_to_fp R32:$src))]>, XD;
def CVTSI2SDrm: I<0x2A, MRMSrcMem, (ops V2F8:$dst, i32mem:$src),
def SQRTSSrm : I<0x51, MRMSrcMem, (ops V4F4:$dst, f32mem:$src),
def SQRTSSrr : I<0x51, MRMSrcReg, (ops V4F4:$dst, V4F4:$src),
"sqrtss {$src, $dst|$dst, $src}",
[(set V4F4:$dst, (fsqrt V4F4:$src))]>, XS;
def SQRTSDrm : I<0x51, MRMSrcMem, (ops V2F8:$dst, f64mem:$src),
def SQRTSDrr : I<0x51, MRMSrcReg, (ops V2F8:$dst, V2F8:$src),
"sqrtsd {$src, $dst|$dst, $src}",
[(set V2F8:$dst, (fsqrt V2F8:$src))]>, XD;
def UCOMISDrr: I<0x2E, MRMSrcReg, (ops V2F8:$dst, V2F8:$src),
"ucomisd {$src, $dst|$dst, $src}", []>, TB, OpSize;
def UCOMISDrm: I<0x2E, MRMSrcMem, (ops V2F8:$dst, f64mem:$src),
"ucomisd {$src, $dst|$dst, $src}", []>, TB, OpSize;
def UCOMISSrr: I<0x2E, MRMSrcReg, (ops V4F4:$dst, V4F4:$src),
def UCOMISSrm: I<0x2E, MRMSrcMem, (ops V4F4:$dst, f32mem:$src),
// Pseudo-instructions that map fld0 to xorps/xorpd for sse.
// FIXME: remove when we can teach regalloc that xor reg, reg is ok.
def FLD0SS : I<0x57, MRMSrcReg, (ops V4F4:$dst),
def FLD0SD : I<0x57, MRMSrcReg, (ops V2F8:$dst),
let isTwoAddress = 1 in {
let isCommutable = 1 in {
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
def ADDSSrr : I<0x58, MRMSrcReg, (ops V4F4:$dst, V4F4:$src1, V4F4:$src2),
"addss {$src2, $dst|$dst, $src2}",
[(set V4F4:$dst, (fadd V4F4:$src1, V4F4:$src2))]>, XS;
def ADDSDrr : I<0x58, MRMSrcReg, (ops V2F8:$dst, V2F8:$src1, V2F8:$src2),
"addsd {$src2, $dst|$dst, $src2}",
[(set V2F8:$dst, (fadd V2F8:$src1, V2F8:$src2))]>, XD;
def ANDPSrr : I<0x54, MRMSrcReg, (ops V4F4:$dst, V4F4:$src1, V4F4:$src2),
"andps {$src2, $dst|$dst, $src2}", []>, TB;
def ANDPDrr : I<0x54, MRMSrcReg, (ops V2F8:$dst, V2F8:$src1, V2F8:$src2),
"andpd {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def MULSSrr : I<0x59, MRMSrcReg, (ops V4F4:$dst, V4F4:$src1, V4F4:$src2),
"mulss {$src2, $dst|$dst, $src2}",
[(set V4F4:$dst, (fmul V4F4:$src1, V4F4:$src2))]>, XS;
def MULSDrr : I<0x59, MRMSrcReg, (ops V2F8:$dst, V2F8:$src1, V2F8:$src2),
"mulsd {$src2, $dst|$dst, $src2}",
[(set V2F8:$dst, (fmul V2F8:$src1, V2F8:$src2))]>, XD;
def ORPSrr : I<0x56, MRMSrcReg, (ops V4F4:$dst, V4F4:$src1, V4F4:$src2),
"orps {$src2, $dst|$dst, $src2}", []>, TB;
def ORPDrr : I<0x56, MRMSrcReg, (ops V2F8:$dst, V2F8:$src1, V2F8:$src2),
"orpd {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def XORPSrr : I<0x57, MRMSrcReg, (ops V4F4:$dst, V4F4:$src1, V4F4:$src2),
"xorps {$src2, $dst|$dst, $src2}", []>, TB;
def XORPDrr : I<0x57, MRMSrcReg, (ops V2F8:$dst, V2F8:$src1, V2F8:$src2),
"xorpd {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
}
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
def ANDNPSrr : I<0x55, MRMSrcReg, (ops V4F4:$dst, V4F4:$src1, V4F4:$src2),
"andnps {$src2, $dst|$dst, $src2}", []>, TB;
def ANDNPDrr : I<0x55, MRMSrcReg, (ops V2F8:$dst, V2F8:$src1, V2F8:$src2),
"andnpd {$src2, $dst|$dst, $src2}", []>, TB, OpSize;
def ADDSSrm : I<0x58, MRMSrcMem, (ops V4F4:$dst, V4F4:$src1, f32mem:$src2),
"addss {$src2, $dst|$dst, $src2}", []>, XS;
def ADDSDrm : I<0x58, MRMSrcMem, (ops V2F8:$dst, V2F8:$src1, f64mem:$src2),
"addsd {$src2, $dst|$dst, $src2}", []>, XD;
def MULSSrm : I<0x59, MRMSrcMem, (ops V4F4:$dst, V4F4:$src1, f32mem:$src2),
"mulss {$src2, $dst|$dst, $src2}", []>, XS;
def MULSDrm : I<0x59, MRMSrcMem, (ops V2F8:$dst, V2F8:$src1, f64mem:$src2),
"mulsd {$src2, $dst|$dst, $src2}", []>, XD;
def DIVSSrm : I<0x5E, MRMSrcMem, (ops V4F4:$dst, V4F4:$src1, f32mem:$src2),
"divss {$src2, $dst|$dst, $src2}", []>, XS;
def DIVSSrr : I<0x5E, MRMSrcReg, (ops V4F4:$dst, V4F4:$src1, V4F4:$src2),
"divss {$src2, $dst|$dst, $src2}",
[(set V4F4:$dst, (fdiv V4F4:$src1, V4F4:$src2))]>, XS;
def DIVSDrm : I<0x5E, MRMSrcMem, (ops V2F8:$dst, V2F8:$src1, f64mem:$src2),
"divsd {$src2, $dst|$dst, $src2}", []>, XD;
def DIVSDrr : I<0x5E, MRMSrcReg, (ops V2F8:$dst, V2F8:$src1, V2F8:$src2),
"divsd {$src2, $dst|$dst, $src2}",
[(set V2F8:$dst, (fdiv V2F8:$src1, V2F8:$src2))]>, XD;
def SUBSSrm : I<0x5C, MRMSrcMem, (ops V4F4:$dst, V4F4:$src1, f32mem:$src2),
"subss {$src2, $dst|$dst, $src2}", []>, XS;
def SUBSSrr : I<0x5C, MRMSrcReg, (ops V4F4:$dst, V4F4:$src1, V4F4:$src2),
"subss {$src2, $dst|$dst, $src2}",
[(set V4F4:$dst, (fsub V4F4:$src1, V4F4:$src2))]>, XS;
def SUBSDrm : I<0x5C, MRMSrcMem, (ops V2F8:$dst, V2F8:$src1, f64mem:$src2),
"subsd {$src2, $dst|$dst, $src2}", []>, XD;
def SUBSDrr : I<0x5C, MRMSrcReg, (ops V2F8:$dst, V2F8:$src1, V2F8:$src2),
"subsd {$src2, $dst|$dst, $src2}",
[(set V2F8:$dst, (fsub V2F8:$src1, V2F8:$src2))]>, XD;
def CMPSSrr : I<0xC2, MRMSrcReg,
(ops V4F4:$dst, V4F4:$src1, V4F4:$src, SSECC:$cc),
"cmp${cc}ss {$src, $dst|$dst, $src}", []>, XS;
def CMPSSrm : I<0xC2, MRMSrcMem,
(ops V4F4:$dst, V4F4:$src1, f32mem:$src, SSECC:$cc),
"cmp${cc}ss {$src, $dst|$dst, $src}", []>, XS;
def CMPSDrr : I<0xC2, MRMSrcReg,
(ops V2F8:$dst, V2F8:$src1, V2F8:$src, SSECC:$cc),
"cmp${cc}sd {$src, $dst|$dst, $src}", []>, XD;
def CMPSDrm : I<0xC2, MRMSrcMem,
(ops V2F8:$dst, V2F8:$src1, f64mem:$src, SSECC:$cc),
"cmp${cc}sd {$src, $dst|$dst, $src}", []>, XD;
}
//===----------------------------------------------------------------------===//
// Miscellaneous Instructions
//===----------------------------------------------------------------------===//
def RDTSC : I<0x31, RawFrm, (ops), "rdtsc", []>, TB, Imp<[],[EAX,EDX]>;
//===----------------------------------------------------------------------===//
// Stack-based Floating point support
//===----------------------------------------------------------------------===//
// FIXME: These need to indicate mod/ref sets for FP regs... & FP 'TOP'
// Floating point instruction template
class FPI<bits<8> o, Format F, FPFormat fp, dag ops, string asm>
: X86Inst<o, F, NoImm, ops, asm> {
let FPForm = fp; let FPFormBits = FPForm.Value;
}
// Pseudo instructions for floating point. We use these pseudo instructions
// because they can be expanded by the fp spackifier into one of many different
// forms of instructions for doing these operations. Until the stackifier runs,
// we prefer to be abstract.
def FpMOV : FPI<0, Pseudo, SpecialFP,
def FpADD : FPI<0, Pseudo, TwoArgFP ,
(ops RFP:$dst, RFP:$src1, RFP:$src2), "">; // f1 = fadd f2, f3
def FpSUB : FPI<0, Pseudo, TwoArgFP ,
(ops RFP:$dst, RFP:$src1, RFP:$src2), "">; // f1 = fsub f2, f3
def FpMUL : FPI<0, Pseudo, TwoArgFP ,
(ops RFP:$dst, RFP:$src1, RFP:$src2), "">; // f1 = fmul f2, f3
def FpDIV : FPI<0, Pseudo, TwoArgFP ,
(ops RFP:$dst, RFP:$src1, RFP:$src2), "">; // f1 = fdiv f2, f3
def FpGETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$dst), "">,
Imp<[ST0], []>; // FPR = ST(0)
def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "">,
Imp<[], [ST0]>; // ST(0) = FPR
// FADD reg, mem: Before stackification, these are represented by:
// R1 = FADD* R2, [mem]
def FADD32m : FPI<0xD8, MRM0m, OneArgFPRW, // ST(0) = ST(0) + [mem32real]
(ops f32mem:$src, variable_ops),
"fadd{s} $src">;
def FADD64m : FPI<0xDC, MRM0m, OneArgFPRW, // ST(0) = ST(0) + [mem64real]
(ops f64mem:$src, variable_ops),
"fadd{l} $src">;
//def FIADD16m : FPI<0xDE, MRM0m, OneArgFPRW>; // ST(0) = ST(0) + [mem16int]
//def FIADD32m : FPI<0xDA, MRM0m, OneArgFPRW>; // ST(0) = ST(0) + [mem32int]
// FMUL reg, mem: Before stackification, these are represented by:
// R1 = FMUL* R2, [mem]
def FMUL32m : FPI<0xD8, MRM1m, OneArgFPRW, // ST(0) = ST(0) * [mem32real]
(ops f32mem:$src, variable_ops),
"fmul{s} $src">;
def FMUL64m : FPI<0xDC, MRM1m, OneArgFPRW, // ST(0) = ST(0) * [mem64real]
(ops f64mem:$src, variable_ops),
"fmul{l} $src">;
// ST(0) = ST(0) * [mem16int]
//def FIMUL16m : FPI16m<"fimul", 0xDE, MRM1m, OneArgFPRW>;
// ST(0) = ST(0) * [mem32int]
//def FIMUL32m : FPI32m<"fimul", 0xDA, MRM1m, OneArgFPRW>;
// FSUB reg, mem: Before stackification, these are represented by:
// R1 = FSUB* R2, [mem]
def FSUB32m : FPI<0xD8, MRM4m, OneArgFPRW, // ST(0) = ST(0) - [mem32real]
(ops f32mem:$src, variable_ops),
"fsub{s} $src">;
def FSUB64m : FPI<0xDC, MRM4m, OneArgFPRW, // ST(0) = ST(0) - [mem64real]
(ops f64mem:$src, variable_ops),
"fsub{l} $src">;
// ST(0) = ST(0) - [mem16int]
//def FISUB16m : FPI16m<"fisub", 0xDE, MRM4m, OneArgFPRW>;
// ST(0) = ST(0) - [mem32int]
//def FISUB32m : FPI32m<"fisub", 0xDA, MRM4m, OneArgFPRW>;
// FSUBR reg, mem: Before stackification, these are represented by:
// R1 = FSUBR* R2, [mem]
// Note that the order of operands does not reflect the operation being
// performed.
def FSUBR32m : FPI<0xD8, MRM5m, OneArgFPRW, // ST(0) = [mem32real] - ST(0)
(ops f32mem:$src, variable_ops),
"fsubr{s} $src">;
def FSUBR64m : FPI<0xDC, MRM5m, OneArgFPRW, // ST(0) = [mem64real] - ST(0)
(ops f64mem:$src, variable_ops),
"fsubr{l} $src">;
// ST(0) = [mem16int] - ST(0)
//def FISUBR16m : FPI16m<"fisubr", 0xDE, MRM5m, OneArgFPRW>;
// ST(0) = [mem32int] - ST(0)
//def FISUBR32m : FPI32m<"fisubr", 0xDA, MRM5m, OneArgFPRW>;
// FDIV reg, mem: Before stackification, these are represented by:
// R1 = FDIV* R2, [mem]
def FDIV32m : FPI<0xD8, MRM6m, OneArgFPRW, // ST(0) = ST(0) / [mem32real]
(ops f32mem:$src, variable_ops),
"fdiv{s} $src">;
def FDIV64m : FPI<0xDC, MRM6m, OneArgFPRW, // ST(0) = ST(0) / [mem64real]
(ops f64mem:$src, variable_ops),
"fdiv{l} $src">;
// ST(0) = ST(0) / [mem16int]
//def FIDIV16m : FPI16m<"fidiv", 0xDE, MRM6m, OneArgFPRW>;
// ST(0) = ST(0) / [mem32int]
//def FIDIV32m : FPI32m<"fidiv", 0xDA, MRM6m, OneArgFPRW>;
// FDIVR reg, mem: Before stackification, these are represented by:
// R1 = FDIVR* R2, [mem]
// Note that the order of operands does not reflect the operation being
// performed.
def FDIVR32m : FPI<0xD8, MRM7m, OneArgFPRW, // ST(0) = [mem32real] / ST(0)
(ops f32mem:$src, variable_ops),
"fdivr{s} $src">;
def FDIVR64m : FPI<0xDC, MRM7m, OneArgFPRW, // ST(0) = [mem64real] / ST(0)
(ops f64mem:$src, variable_ops),
"fdivr{l} $src">;
// ST(0) = [mem16int] / ST(0)
//def FIDIVR16m : FPI16m<"fidivr", 0xDE, MRM7m, OneArgFPRW>;
// ST(0) = [mem32int] / ST(0)
//def FIDIVR32m : FPI32m<"fidivr", 0xDA, MRM7m, OneArgFPRW>;
Chris Lattner
committed
// Floating point cmovs...
let isTwoAddress = 1, Uses = [ST0], Defs = [ST0] in {
def FCMOVB : FPI<0xC0, AddRegFrm, CondMovFP,
(ops RST:$op, variable_ops),
"fcmovb {$op, %ST(0)|%ST(0), $op}">, DA;
def FCMOVBE : FPI<0xD0, AddRegFrm, CondMovFP,
(ops RST:$op, variable_ops),
"fcmovbe {$op, %ST(0)|%ST(0), $op}">, DA;
def FCMOVE : FPI<0xC8, AddRegFrm, CondMovFP,
(ops RST:$op, variable_ops),
"fcmove {$op, %ST(0)|%ST(0), $op}">, DA;
def FCMOVP : FPI<0xD8, AddRegFrm, CondMovFP,
(ops RST:$op, variable_ops),
"fcmovu {$op, %ST(0)|%ST(0), $op}">, DA;
def FCMOVAE : FPI<0xC0, AddRegFrm, CondMovFP,
(ops RST:$op, variable_ops),
"fcmovae {$op, %ST(0)|%ST(0), $op}">, DB;
def FCMOVA : FPI<0xD0, AddRegFrm, CondMovFP,
(ops RST:$op, variable_ops),
"fcmova {$op, %ST(0)|%ST(0), $op}">, DB;
def FCMOVNE : FPI<0xC8, AddRegFrm, CondMovFP,
(ops RST:$op, variable_ops),
"fcmovne {$op, %ST(0)|%ST(0), $op}">, DB;
def FCMOVNP : FPI<0xD8, AddRegFrm, CondMovFP,
(ops RST:$op, variable_ops),
"fcmovnu {$op, %ST(0)|%ST(0), $op}">, DB;
Chris Lattner
committed
}
// Floating point loads & stores...
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
// FIXME: these are all marked variable_ops because they have an implicit
// destination. Instructions like FILD* that are generated by the instruction
// selector (not the fp stackifier) need more accurate operand accounting.
def FLDrr : FPI<0xC0, AddRegFrm, NotFP,
(ops RST:$src, variable_ops),
"fld $src">, D9;
def FLD32m : FPI<0xD9, MRM0m, ZeroArgFP,
(ops f32mem:$src, variable_ops),
"fld{s} $src">;
def FLD64m : FPI<0xDD, MRM0m, ZeroArgFP,
(ops f64mem:$src, variable_ops),
"fld{l} $src">;
def FLD80m : FPI<0xDB, MRM5m, ZeroArgFP,
(ops f80mem:$src, variable_ops),
"fld{t} $src">;
def FILD16m : FPI<0xDF, MRM0m, ZeroArgFP,
(ops i16mem:$src, variable_ops),
"fild{s} $src">;
def FILD32m : FPI<0xDB, MRM0m, ZeroArgFP,
(ops i32mem:$src, variable_ops),
"fild{l} $src">;
def FILD64m : FPI<0xDF, MRM5m, ZeroArgFP,
(ops i64mem:$src, variable_ops),
"fild{ll} $src">;
def FSTrr : FPI<0xD0, AddRegFrm, NotFP,
(ops RST:$op, variable_ops),
"fst $op">, DD;
def FSTPrr : FPI<0xD8, AddRegFrm, NotFP,
(ops RST:$op, variable_ops),
"fstp $op">, DD;
def FST32m : FPI<0xD9, MRM2m, OneArgFP,
(ops f32mem:$op, variable_ops),
"fst{s} $op">;
def FST64m : FPI<0xDD, MRM2m, OneArgFP,
(ops f64mem:$op, variable_ops),
"fst{l} $op">;
def FSTP32m : FPI<0xD9, MRM3m, OneArgFP,
(ops f32mem:$op, variable_ops),
"fstp{s} $op">;
def FSTP64m : FPI<0xDD, MRM3m, OneArgFP,
(ops f64mem:$op, variable_ops),
"fstp{l} $op">;
def FSTP80m : FPI<0xDB, MRM7m, OneArgFP,
(ops f80mem:$op, variable_ops),
"fstp{t} $op">;
def FIST16m : FPI<0xDF, MRM2m , OneArgFP,
(ops i16mem:$op, variable_ops),
"fist{s} $op">;
def FIST32m : FPI<0xDB, MRM2m , OneArgFP,
(ops i32mem:$op, variable_ops),
"fist{l} $op">;
def FISTP16m : FPI<0xDF, MRM3m , NotFP ,
(ops i16mem:$op, variable_ops),
"fistp{s} $op">;
def FISTP32m : FPI<0xDB, MRM3m , NotFP ,
(ops i32mem:$op, variable_ops),
"fistp{l} $op">;
def FISTP64m : FPI<0xDF, MRM7m , OneArgFP,
(ops i64mem:$op, variable_ops),
"fistp{ll} $op">;
def FXCH : FPI<0xC8, AddRegFrm, NotFP,
(ops RST:$op), "fxch $op">, D9; // fxch ST(i), ST(0)
// Floating point constant loads...
def FLD0 : FPI<0xEE, RawFrm, ZeroArgFP, (ops variable_ops), "fldz">, D9;
def FLD1 : FPI<0xE8, RawFrm, ZeroArgFP, (ops variable_ops), "fld1">, D9;
def FCHS : FPI<0xE0, RawFrm, OneArgFPRW, // f1 = fchs f2
(ops variable_ops),
"fchs">, D9;
def FABS : FPI<0xE1, RawFrm, OneArgFPRW, // f1 = fabs f2
(ops variable_ops),
"fabs">, D9;
def FSQRT : FPI<0xFA, RawFrm, OneArgFPRW, // fsqrt ST(0)
(ops variable_ops),
"fsqrt">, D9;
def FSIN : FPI<0xFE, RawFrm, OneArgFPRW, // fsin ST(0)
(ops variable_ops),
"fsin">, D9;
def FCOS : FPI<0xFF, RawFrm, OneArgFPRW, // fcos ST(0)
(ops variable_ops),
"fcos">, D9;
def FTST : FPI<0xE4, RawFrm, OneArgFP , // ftst ST(0)
(ops variable_ops),
"ftst">, D9;
// Binary arithmetic operations...
class FPST0rInst<bits<8> o, dag ops, string asm>
list<Register> Uses = [ST0];
list<Register> Defs = [ST0];
}
class FPrST0Inst<bits<8> o, dag ops, string asm>
list<Register> Uses = [ST0];
}
class FPrST0PInst<bits<8> o, dag ops, string asm>
list<Register> Uses = [ST0];
}
def FADDST0r : FPST0rInst <0xC0, (ops RST:$op),
"fadd $op">;
def FADDrST0 : FPrST0Inst <0xC0, (ops RST:$op),
"fadd {%ST(0), $op|$op, %ST(0)}">;
def FADDPrST0 : FPrST0PInst<0xC0, (ops RST:$op),
"faddp $op">;
// NOTE: GAS and apparently all other AT&T style assemblers have a broken notion
// of some of the 'reverse' forms of the fsub and fdiv instructions. As such,
// we have to put some 'r's in and take them out of weird places.
def FSUBRST0r : FPST0rInst <0xE8, (ops RST:$op),
"fsubr $op">;
def FSUBrST0 : FPrST0Inst <0xE8, (ops RST:$op),
"fsub{r} {%ST(0), $op|$op, %ST(0)}">;
def FSUBPrST0 : FPrST0PInst<0xE8, (ops RST:$op),
"fsub{r}p $op">;
def FSUBST0r : FPST0rInst <0xE0, (ops RST:$op),
"fsub $op">;
def FSUBRrST0 : FPrST0Inst <0xE0, (ops RST:$op),
"fsub{|r} {%ST(0), $op|$op, %ST(0)}">;
def FSUBRPrST0 : FPrST0PInst<0xE0, (ops RST:$op),
"fsub{|r}p $op">;
def FMULST0r : FPST0rInst <0xC8, (ops RST:$op),
"fmul $op">;
def FMULrST0 : FPrST0Inst <0xC8, (ops RST:$op),
"fmul {%ST(0), $op|$op, %ST(0)}">;
def FMULPrST0 : FPrST0PInst<0xC8, (ops RST:$op),
"fmulp $op">;
def FDIVRST0r : FPST0rInst <0xF8, (ops RST:$op),
"fdivr $op">;
def FDIVrST0 : FPrST0Inst <0xF8, (ops RST:$op),
"fdiv{r} {%ST(0), $op|$op, %ST(0)}">;
def FDIVPrST0 : FPrST0PInst<0xF8, (ops RST:$op),
"fdiv{r}p $op">;
def FDIVST0r : FPST0rInst <0xF0, (ops RST:$op), // ST(0) = ST(0) / ST(i)
"fdiv $op">;
def FDIVRrST0 : FPrST0Inst <0xF0, (ops RST:$op), // ST(i) = ST(0) / ST(i)