Evan Cheng | ffcb95b | 2006-02-21 19:13:53 +0000 | [diff] [blame] | 1 | //==- X86InstrFPStack.td - Describe the X86 Instruction Set -------*- C++ -*-=// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file was developed by the Evan Cheng and is distributed under |
| 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file describes the X86 x87 FPU instruction set, defining the |
| 11 | // instructions, and properties of the instructions which are needed for code |
| 12 | // generation, machine code emission, and analysis. |
| 13 | // |
| 14 | //===----------------------------------------------------------------------===// |
| 15 | |
Evan Cheng | 06a8aa1 | 2006-03-17 19:55:52 +0000 | [diff] [blame] | 16 | //===----------------------------------------------------------------------===// |
Evan Cheng | 2246f84 | 2006-03-18 01:23:20 +0000 | [diff] [blame] | 17 | // FPStack specific DAG Nodes. |
| 18 | //===----------------------------------------------------------------------===// |
| 19 | |
| 20 | def SDTX86FpGet : SDTypeProfile<1, 0, [SDTCisVT<0, f64>]>; |
| 21 | def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>; |
| 22 | def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, |
| 23 | SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>; |
| 24 | def SDTX86Fst : SDTypeProfile<0, 3, [SDTCisFP<0>, |
| 25 | SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>; |
| 26 | def SDTX86Fild : SDTypeProfile<1, 2, [SDTCisVT<0, f64>, SDTCisPtrTy<1>, |
| 27 | SDTCisVT<2, OtherVT>]>; |
| 28 | def SDTX86FpToIMem: SDTypeProfile<0, 2, [SDTCisFP<0>, SDTCisPtrTy<1>]>; |
| 29 | |
| 30 | def X86fpget : SDNode<"X86ISD::FP_GET_RESULT", SDTX86FpGet, |
| 31 | [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; |
| 32 | def X86fpset : SDNode<"X86ISD::FP_SET_RESULT", SDTX86FpSet, |
| 33 | [SDNPHasChain, SDNPOutFlag]>; |
| 34 | def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, |
| 35 | [SDNPHasChain]>; |
| 36 | def X86fst : SDNode<"X86ISD::FST", SDTX86Fst, |
| 37 | [SDNPHasChain, SDNPInFlag]>; |
| 38 | def X86fild : SDNode<"X86ISD::FILD", SDTX86Fild, |
| 39 | [SDNPHasChain]>; |
| 40 | def X86fildflag: SDNode<"X86ISD::FILD_FLAG",SDTX86Fild, |
| 41 | [SDNPHasChain, SDNPOutFlag]>; |
| 42 | def X86fp_to_i16mem : SDNode<"X86ISD::FP_TO_INT16_IN_MEM", SDTX86FpToIMem, |
| 43 | [SDNPHasChain]>; |
| 44 | def X86fp_to_i32mem : SDNode<"X86ISD::FP_TO_INT32_IN_MEM", SDTX86FpToIMem, |
| 45 | [SDNPHasChain]>; |
| 46 | def X86fp_to_i64mem : SDNode<"X86ISD::FP_TO_INT64_IN_MEM", SDTX86FpToIMem, |
| 47 | [SDNPHasChain]>; |
| 48 | |
| 49 | //===----------------------------------------------------------------------===// |
Evan Cheng | 06a8aa1 | 2006-03-17 19:55:52 +0000 | [diff] [blame] | 50 | // FPStack pattern fragments |
| 51 | //===----------------------------------------------------------------------===// |
| 52 | |
Evan Cheng | 06a8aa1 | 2006-03-17 19:55:52 +0000 | [diff] [blame] | 53 | def fp64imm0 : PatLeaf<(f64 fpimm), [{ |
| 54 | return N->isExactlyValue(+0.0); |
| 55 | }]>; |
| 56 | |
| 57 | def fp64immneg0 : PatLeaf<(f64 fpimm), [{ |
| 58 | return N->isExactlyValue(-0.0); |
| 59 | }]>; |
| 60 | |
| 61 | def fp64imm1 : PatLeaf<(f64 fpimm), [{ |
| 62 | return N->isExactlyValue(+1.0); |
| 63 | }]>; |
| 64 | |
| 65 | def fp64immneg1 : PatLeaf<(f64 fpimm), [{ |
| 66 | return N->isExactlyValue(-1.0); |
| 67 | }]>; |
| 68 | |
| 69 | def extloadf64f32 : PatFrag<(ops node:$ptr), (f64 (extload node:$ptr, f32))>; |
| 70 | |
Evan Cheng | 4e4c71e | 2006-02-21 20:00:20 +0000 | [diff] [blame] | 71 | // Some 'special' instructions |
| 72 | let usesCustomDAGSchedInserter = 1 in { // Expanded by the scheduler. |
| 73 | def FP_TO_INT16_IN_MEM : I<0, Pseudo, |
| 74 | (ops i16mem:$dst, RFP:$src), |
| 75 | "#FP_TO_INT16_IN_MEM PSEUDO!", |
| 76 | [(X86fp_to_i16mem RFP:$src, addr:$dst)]>; |
| 77 | def FP_TO_INT32_IN_MEM : I<0, Pseudo, |
| 78 | (ops i32mem:$dst, RFP:$src), |
| 79 | "#FP_TO_INT32_IN_MEM PSEUDO!", |
| 80 | [(X86fp_to_i32mem RFP:$src, addr:$dst)]>; |
| 81 | def FP_TO_INT64_IN_MEM : I<0, Pseudo, |
| 82 | (ops i64mem:$dst, RFP:$src), |
| 83 | "#FP_TO_INT64_IN_MEM PSEUDO!", |
| 84 | [(X86fp_to_i64mem RFP:$src, addr:$dst)]>; |
| 85 | } |
| 86 | |
| 87 | let isTerminator = 1 in |
| 88 | let Defs = [FP0, FP1, FP2, FP3, FP4, FP5, FP6] in |
| 89 | def FP_REG_KILL : I<0, Pseudo, (ops), "#FP_REG_KILL", []>; |
| 90 | |
Evan Cheng | ffcb95b | 2006-02-21 19:13:53 +0000 | [diff] [blame] | 91 | // All FP Stack operations are represented with two instructions here. The |
| 92 | // first instruction, generated by the instruction selector, uses "RFP" |
| 93 | // registers: a traditional register file to reference floating point values. |
| 94 | // These instructions are all psuedo instructions and use the "Fp" prefix. |
| 95 | // The second instruction is defined with FPI, which is the actual instruction |
| 96 | // emitted by the assembler. The FP stackifier pass converts one to the other |
| 97 | // after register allocation occurs. |
| 98 | // |
| 99 | // Note that the FpI instruction should have instruction selection info (e.g. |
| 100 | // a pattern) and the FPI instruction should have emission info (e.g. opcode |
| 101 | // encoding and asm printing info). |
| 102 | |
| 103 | // FPI - Floating Point Instruction template. |
| 104 | class FPI<bits<8> o, Format F, dag ops, string asm> : I<o, F, ops, asm, []> {} |
| 105 | |
| 106 | // FpI_ - Floating Point Psuedo Instruction template. Not Predicated. |
| 107 | class FpI_<dag ops, FPFormat fp, list<dag> pattern> |
| 108 | : X86Inst<0, Pseudo, NoImm, ops, ""> { |
| 109 | let FPForm = fp; let FPFormBits = FPForm.Value; |
| 110 | let Pattern = pattern; |
| 111 | } |
| 112 | |
| 113 | // Random Pseudo Instructions. |
| 114 | def FpGETRESULT : FpI_<(ops RFP:$dst), SpecialFP, |
| 115 | [(set RFP:$dst, X86fpget)]>; // FPR = ST(0) |
| 116 | |
| 117 | let noResults = 1 in |
| 118 | def FpSETRESULT : FpI_<(ops RFP:$src), SpecialFP, |
| 119 | [(X86fpset RFP:$src)]>, Imp<[], [ST0]>; // ST(0) = FPR |
| 120 | |
| 121 | // FpI - Floating Point Psuedo Instruction template. Predicated on FPStack. |
| 122 | class FpI<dag ops, FPFormat fp, list<dag> pattern> : |
| 123 | FpI_<ops, fp, pattern>, Requires<[FPStack]>; |
| 124 | |
| 125 | |
| 126 | def FpMOV : FpI<(ops RFP:$dst, RFP:$src), SpecialFP, []>; // f1 = fmov f2 |
| 127 | |
| 128 | // Arithmetic |
| 129 | // Add, Sub, Mul, Div. |
| 130 | def FpADD : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP, |
| 131 | [(set RFP:$dst, (fadd RFP:$src1, RFP:$src2))]>; |
| 132 | def FpSUB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP, |
| 133 | [(set RFP:$dst, (fsub RFP:$src1, RFP:$src2))]>; |
| 134 | def FpMUL : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP, |
| 135 | [(set RFP:$dst, (fmul RFP:$src1, RFP:$src2))]>; |
| 136 | def FpDIV : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), TwoArgFP, |
| 137 | [(set RFP:$dst, (fdiv RFP:$src1, RFP:$src2))]>; |
| 138 | |
| 139 | class FPST0rInst<bits<8> o, string asm> |
| 140 | : FPI<o, AddRegFrm, (ops RST:$op), asm>, D8; |
| 141 | class FPrST0Inst<bits<8> o, string asm> |
| 142 | : FPI<o, AddRegFrm, (ops RST:$op), asm>, DC; |
| 143 | class FPrST0PInst<bits<8> o, string asm> |
| 144 | : FPI<o, AddRegFrm, (ops RST:$op), asm>, DE; |
| 145 | |
| 146 | // Binary Ops with a memory source. |
| 147 | def FpADD32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, |
| 148 | [(set RFP:$dst, (fadd RFP:$src1, |
| 149 | (extloadf64f32 addr:$src2)))]>; |
| 150 | // ST(0) = ST(0) + [mem32] |
| 151 | def FpADD64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW, |
| 152 | [(set RFP:$dst, (fadd RFP:$src1, (loadf64 addr:$src2)))]>; |
| 153 | // ST(0) = ST(0) + [mem64] |
| 154 | def FpMUL32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, |
| 155 | [(set RFP:$dst, (fmul RFP:$src1, |
| 156 | (extloadf64f32 addr:$src2)))]>; |
| 157 | // ST(0) = ST(0) * [mem32] |
| 158 | def FpMUL64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW, |
| 159 | [(set RFP:$dst, (fmul RFP:$src1, (loadf64 addr:$src2)))]>; |
| 160 | // ST(0) = ST(0) * [mem64] |
| 161 | def FpSUB32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, |
| 162 | [(set RFP:$dst, (fsub RFP:$src1, |
| 163 | (extloadf64f32 addr:$src2)))]>; |
| 164 | // ST(0) = ST(0) - [mem32] |
| 165 | def FpSUB64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW, |
| 166 | [(set RFP:$dst, (fsub RFP:$src1, (loadf64 addr:$src2)))]>; |
| 167 | // ST(0) = ST(0) - [mem64] |
| 168 | def FpSUBR32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, |
| 169 | [(set RFP:$dst, (fsub (extloadf64f32 addr:$src2), |
| 170 | RFP:$src1))]>; |
| 171 | // ST(0) = [mem32] - ST(0) |
| 172 | def FpSUBR64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW, |
| 173 | [(set RFP:$dst, (fsub (loadf64 addr:$src2), RFP:$src1))]>; |
| 174 | // ST(0) = [mem64] - ST(0) |
| 175 | def FpDIV32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, |
| 176 | [(set RFP:$dst, (fdiv RFP:$src1, |
| 177 | (extloadf64f32 addr:$src2)))]>; |
| 178 | // ST(0) = ST(0) / [mem32] |
| 179 | def FpDIV64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW, |
| 180 | [(set RFP:$dst, (fdiv RFP:$src1, (loadf64 addr:$src2)))]>; |
| 181 | // ST(0) = ST(0) / [mem64] |
| 182 | def FpDIVR32m : FpI<(ops RFP:$dst, RFP:$src1, f32mem:$src2), OneArgFPRW, |
| 183 | [(set RFP:$dst, (fdiv (extloadf64f32 addr:$src2), |
| 184 | RFP:$src1))]>; |
| 185 | // ST(0) = [mem32] / ST(0) |
| 186 | def FpDIVR64m : FpI<(ops RFP:$dst, RFP:$src1, f64mem:$src2), OneArgFPRW, |
| 187 | [(set RFP:$dst, (fdiv (loadf64 addr:$src2), RFP:$src1))]>; |
| 188 | // ST(0) = [mem64] / ST(0) |
| 189 | |
| 190 | |
| 191 | def FADD32m : FPI<0xD8, MRM0m, (ops f32mem:$src), "fadd{s} $src">; |
| 192 | def FADD64m : FPI<0xDC, MRM0m, (ops f64mem:$src), "fadd{l} $src">; |
| 193 | def FMUL32m : FPI<0xD8, MRM1m, (ops f32mem:$src), "fmul{s} $src">; |
| 194 | def FMUL64m : FPI<0xDC, MRM1m, (ops f64mem:$src), "fmul{l} $src">; |
| 195 | def FSUB32m : FPI<0xD8, MRM4m, (ops f32mem:$src), "fsub{s} $src">; |
| 196 | def FSUB64m : FPI<0xDC, MRM4m, (ops f64mem:$src), "fsub{l} $src">; |
| 197 | def FSUBR32m : FPI<0xD8, MRM5m, (ops f32mem:$src), "fsubr{s} $src">; |
| 198 | def FSUBR64m : FPI<0xDC, MRM5m, (ops f64mem:$src), "fsubr{l} $src">; |
| 199 | def FDIV32m : FPI<0xD8, MRM6m, (ops f32mem:$src), "fdiv{s} $src">; |
| 200 | def FDIV64m : FPI<0xDC, MRM6m, (ops f64mem:$src), "fdiv{l} $src">; |
| 201 | def FDIVR32m : FPI<0xD8, MRM7m, (ops f32mem:$src), "fdivr{s} $src">; |
| 202 | def FDIVR64m : FPI<0xDC, MRM7m, (ops f64mem:$src), "fdivr{l} $src">; |
| 203 | |
| 204 | def FpIADD16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW, |
| 205 | [(set RFP:$dst, (fadd RFP:$src1, |
| 206 | (X86fild addr:$src2, i16)))]>; |
| 207 | // ST(0) = ST(0) + [mem16int] |
| 208 | def FpIADD32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW, |
| 209 | [(set RFP:$dst, (fadd RFP:$src1, |
| 210 | (X86fild addr:$src2, i32)))]>; |
| 211 | // ST(0) = ST(0) + [mem32int] |
| 212 | def FpIMUL16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW, |
| 213 | [(set RFP:$dst, (fmul RFP:$src1, |
| 214 | (X86fild addr:$src2, i16)))]>; |
| 215 | // ST(0) = ST(0) * [mem16int] |
| 216 | def FpIMUL32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW, |
| 217 | [(set RFP:$dst, (fmul RFP:$src1, |
| 218 | (X86fild addr:$src2, i32)))]>; |
| 219 | // ST(0) = ST(0) * [mem32int] |
| 220 | def FpISUB16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW, |
| 221 | [(set RFP:$dst, (fsub RFP:$src1, |
| 222 | (X86fild addr:$src2, i16)))]>; |
| 223 | // ST(0) = ST(0) - [mem16int] |
| 224 | def FpISUB32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW, |
| 225 | [(set RFP:$dst, (fsub RFP:$src1, |
| 226 | (X86fild addr:$src2, i32)))]>; |
| 227 | // ST(0) = ST(0) - [mem32int] |
| 228 | def FpISUBR16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW, |
| 229 | [(set RFP:$dst, (fsub (X86fild addr:$src2, i16), |
| 230 | RFP:$src1))]>; |
| 231 | // ST(0) = [mem16int] - ST(0) |
| 232 | def FpISUBR32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW, |
| 233 | [(set RFP:$dst, (fsub (X86fild addr:$src2, i32), |
| 234 | RFP:$src1))]>; |
| 235 | // ST(0) = [mem32int] - ST(0) |
| 236 | def FpIDIV16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW, |
| 237 | [(set RFP:$dst, (fdiv RFP:$src1, |
| 238 | (X86fild addr:$src2, i16)))]>; |
| 239 | // ST(0) = ST(0) / [mem16int] |
| 240 | def FpIDIV32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW, |
| 241 | [(set RFP:$dst, (fdiv RFP:$src1, |
| 242 | (X86fild addr:$src2, i32)))]>; |
| 243 | // ST(0) = ST(0) / [mem32int] |
| 244 | def FpIDIVR16m : FpI<(ops RFP:$dst, RFP:$src1, i16mem:$src2), OneArgFPRW, |
| 245 | [(set RFP:$dst, (fdiv (X86fild addr:$src2, i16), |
| 246 | RFP:$src1))]>; |
| 247 | // ST(0) = [mem16int] / ST(0) |
| 248 | def FpIDIVR32m : FpI<(ops RFP:$dst, RFP:$src1, i32mem:$src2), OneArgFPRW, |
| 249 | [(set RFP:$dst, (fdiv (X86fild addr:$src2, i32), |
| 250 | RFP:$src1))]>; |
| 251 | // ST(0) = [mem32int] / ST(0) |
| 252 | |
| 253 | def FIADD16m : FPI<0xDE, MRM0m, (ops i16mem:$src), "fiadd{s} $src">; |
| 254 | def FIADD32m : FPI<0xDA, MRM0m, (ops i32mem:$src), "fiadd{l} $src">; |
| 255 | def FIMUL16m : FPI<0xDE, MRM1m, (ops i16mem:$src), "fimul{s} $src">; |
| 256 | def FIMUL32m : FPI<0xDA, MRM1m, (ops i32mem:$src), "fimul{l} $src">; |
| 257 | def FISUB16m : FPI<0xDE, MRM4m, (ops i16mem:$src), "fisub{s} $src">; |
| 258 | def FISUB32m : FPI<0xDA, MRM4m, (ops i32mem:$src), "fisub{l} $src">; |
| 259 | def FISUBR16m : FPI<0xDE, MRM5m, (ops i16mem:$src), "fisubr{s} $src">; |
| 260 | def FISUBR32m : FPI<0xDA, MRM5m, (ops i32mem:$src), "fisubr{l} $src">; |
| 261 | def FIDIV16m : FPI<0xDE, MRM6m, (ops i16mem:$src), "fidiv{s} $src">; |
| 262 | def FIDIV32m : FPI<0xDA, MRM6m, (ops i32mem:$src), "fidiv{l} $src">; |
| 263 | def FIDIVR16m : FPI<0xDE, MRM7m, (ops i16mem:$src), "fidivr{s} $src">; |
| 264 | def FIDIVR32m : FPI<0xDA, MRM7m, (ops i32mem:$src), "fidivr{l} $src">; |
| 265 | |
| 266 | // NOTE: GAS and apparently all other AT&T style assemblers have a broken notion |
| 267 | // of some of the 'reverse' forms of the fsub and fdiv instructions. As such, |
| 268 | // we have to put some 'r's in and take them out of weird places. |
| 269 | def FADDST0r : FPST0rInst <0xC0, "fadd $op">; |
| 270 | def FADDrST0 : FPrST0Inst <0xC0, "fadd {%st(0), $op|$op, %ST(0)}">; |
| 271 | def FADDPrST0 : FPrST0PInst<0xC0, "faddp $op">; |
| 272 | def FSUBRST0r : FPST0rInst <0xE8, "fsubr $op">; |
| 273 | def FSUBrST0 : FPrST0Inst <0xE8, "fsub{r} {%st(0), $op|$op, %ST(0)}">; |
| 274 | def FSUBPrST0 : FPrST0PInst<0xE8, "fsub{r}p $op">; |
| 275 | def FSUBST0r : FPST0rInst <0xE0, "fsub $op">; |
| 276 | def FSUBRrST0 : FPrST0Inst <0xE0, "fsub{|r} {%st(0), $op|$op, %ST(0)}">; |
| 277 | def FSUBRPrST0 : FPrST0PInst<0xE0, "fsub{|r}p $op">; |
| 278 | def FMULST0r : FPST0rInst <0xC8, "fmul $op">; |
| 279 | def FMULrST0 : FPrST0Inst <0xC8, "fmul {%st(0), $op|$op, %ST(0)}">; |
| 280 | def FMULPrST0 : FPrST0PInst<0xC8, "fmulp $op">; |
| 281 | def FDIVRST0r : FPST0rInst <0xF8, "fdivr $op">; |
| 282 | def FDIVrST0 : FPrST0Inst <0xF8, "fdiv{r} {%st(0), $op|$op, %ST(0)}">; |
| 283 | def FDIVPrST0 : FPrST0PInst<0xF8, "fdiv{r}p $op">; |
| 284 | def FDIVST0r : FPST0rInst <0xF0, "fdiv $op">; |
| 285 | def FDIVRrST0 : FPrST0Inst <0xF0, "fdiv{|r} {%st(0), $op|$op, %ST(0)}">; |
| 286 | def FDIVRPrST0 : FPrST0PInst<0xF0, "fdiv{|r}p $op">; |
| 287 | |
| 288 | |
| 289 | // Unary operations. |
| 290 | def FpCHS : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, |
| 291 | [(set RFP:$dst, (fneg RFP:$src))]>; |
| 292 | def FpABS : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, |
| 293 | [(set RFP:$dst, (fabs RFP:$src))]>; |
| 294 | def FpSQRT : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, |
| 295 | [(set RFP:$dst, (fsqrt RFP:$src))]>; |
| 296 | def FpSIN : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, |
| 297 | [(set RFP:$dst, (fsin RFP:$src))]>; |
| 298 | def FpCOS : FpI<(ops RFP:$dst, RFP:$src), OneArgFPRW, |
| 299 | [(set RFP:$dst, (fcos RFP:$src))]>; |
| 300 | def FpTST : FpI<(ops RFP:$src), OneArgFP, |
| 301 | []>; |
| 302 | |
| 303 | def FCHS : FPI<0xE0, RawFrm, (ops), "fchs">, D9; |
| 304 | def FABS : FPI<0xE1, RawFrm, (ops), "fabs">, D9; |
| 305 | def FSQRT : FPI<0xFA, RawFrm, (ops), "fsqrt">, D9; |
| 306 | def FSIN : FPI<0xFE, RawFrm, (ops), "fsin">, D9; |
| 307 | def FCOS : FPI<0xFF, RawFrm, (ops), "fcos">, D9; |
| 308 | def FTST : FPI<0xE4, RawFrm, (ops), "ftst">, D9; |
| 309 | |
| 310 | |
| 311 | // Floating point cmovs. |
| 312 | let isTwoAddress = 1 in { |
| 313 | def FpCMOVB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, |
| 314 | [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, |
| 315 | X86_COND_B))]>; |
| 316 | def FpCMOVBE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, |
| 317 | [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, |
| 318 | X86_COND_BE))]>; |
| 319 | def FpCMOVE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, |
| 320 | [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, |
| 321 | X86_COND_E))]>; |
| 322 | def FpCMOVP : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, |
| 323 | [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, |
| 324 | X86_COND_P))]>; |
| 325 | def FpCMOVNB : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, |
| 326 | [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, |
| 327 | X86_COND_AE))]>; |
| 328 | def FpCMOVNBE: FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, |
| 329 | [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, |
| 330 | X86_COND_A))]>; |
| 331 | def FpCMOVNE : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, |
| 332 | [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, |
| 333 | X86_COND_NE))]>; |
| 334 | def FpCMOVNP : FpI<(ops RFP:$dst, RFP:$src1, RFP:$src2), CondMovFP, |
| 335 | [(set RFP:$dst, (X86cmov RFP:$src1, RFP:$src2, |
| 336 | X86_COND_NP))]>; |
| 337 | } |
| 338 | |
| 339 | def FCMOVB : FPI<0xC0, AddRegFrm, (ops RST:$op), |
| 340 | "fcmovb {$op, %st(0)|%ST(0), $op}">, DA; |
| 341 | def FCMOVBE : FPI<0xD0, AddRegFrm, (ops RST:$op), |
| 342 | "fcmovbe {$op, %st(0)|%ST(0), $op}">, DA; |
| 343 | def FCMOVE : FPI<0xC8, AddRegFrm, (ops RST:$op), |
| 344 | "fcmove {$op, %st(0)|%ST(0), $op}">, DA; |
| 345 | def FCMOVP : FPI<0xD8, AddRegFrm, (ops RST:$op), |
| 346 | "fcmovu {$op, %st(0)|%ST(0), $op}">, DA; |
| 347 | def FCMOVNB : FPI<0xC0, AddRegFrm, (ops RST:$op), |
| 348 | "fcmovnb {$op, %st(0)|%ST(0), $op}">, DB; |
| 349 | def FCMOVNBE : FPI<0xD0, AddRegFrm, (ops RST:$op), |
| 350 | "fcmovnbe {$op, %st(0)|%ST(0), $op}">, DB; |
| 351 | def FCMOVNE : FPI<0xC8, AddRegFrm, (ops RST:$op), |
| 352 | "fcmovne {$op, %st(0)|%ST(0), $op}">, DB; |
| 353 | def FCMOVNP : FPI<0xD8, AddRegFrm, (ops RST:$op), |
| 354 | "fcmovnu {$op, %st(0)|%ST(0), $op}">, DB; |
| 355 | |
| 356 | // Floating point loads & stores. |
| 357 | def FpLD32m : FpI<(ops RFP:$dst, f32mem:$src), ZeroArgFP, |
| 358 | [(set RFP:$dst, (extloadf64f32 addr:$src))]>; |
| 359 | def FpLD64m : FpI<(ops RFP:$dst, f64mem:$src), ZeroArgFP, |
| 360 | [(set RFP:$dst, (loadf64 addr:$src))]>; |
| 361 | def FpILD16m : FpI<(ops RFP:$dst, i16mem:$src), ZeroArgFP, |
| 362 | [(set RFP:$dst, (X86fild addr:$src, i16))]>; |
| 363 | def FpILD32m : FpI<(ops RFP:$dst, i32mem:$src), ZeroArgFP, |
| 364 | [(set RFP:$dst, (X86fild addr:$src, i32))]>; |
| 365 | def FpILD64m : FpI<(ops RFP:$dst, i64mem:$src), ZeroArgFP, |
| 366 | [(set RFP:$dst, (X86fild addr:$src, i64))]>; |
| 367 | |
| 368 | def FpST32m : FpI<(ops f32mem:$op, RFP:$src), OneArgFP, |
| 369 | [(truncstore RFP:$src, addr:$op, f32)]>; |
| 370 | def FpST64m : FpI<(ops f64mem:$op, RFP:$src), OneArgFP, |
| 371 | [(store RFP:$src, addr:$op)]>; |
| 372 | |
| 373 | def FpSTP32m : FpI<(ops f32mem:$op, RFP:$src), OneArgFP, []>; |
| 374 | def FpSTP64m : FpI<(ops f64mem:$op, RFP:$src), OneArgFP, []>; |
| 375 | def FpIST16m : FpI<(ops i16mem:$op, RFP:$src), OneArgFP, []>; |
| 376 | def FpIST32m : FpI<(ops i32mem:$op, RFP:$src), OneArgFP, []>; |
| 377 | def FpIST64m : FpI<(ops i64mem:$op, RFP:$src), OneArgFP, []>; |
| 378 | |
| 379 | def FLD32m : FPI<0xD9, MRM0m, (ops f32mem:$src), "fld{s} $src">; |
| 380 | def FLD64m : FPI<0xDD, MRM0m, (ops f64mem:$src), "fld{l} $src">; |
| 381 | def FILD16m : FPI<0xDF, MRM0m, (ops i16mem:$src), "fild{s} $src">; |
| 382 | def FILD32m : FPI<0xDB, MRM0m, (ops i32mem:$src), "fild{l} $src">; |
| 383 | def FILD64m : FPI<0xDF, MRM5m, (ops i64mem:$src), "fild{ll} $src">; |
| 384 | def FST32m : FPI<0xD9, MRM2m, (ops f32mem:$dst), "fst{s} $dst">; |
| 385 | def FST64m : FPI<0xDD, MRM2m, (ops f64mem:$dst), "fst{l} $dst">; |
| 386 | def FSTP32m : FPI<0xD9, MRM3m, (ops f32mem:$dst), "fstp{s} $dst">; |
| 387 | def FSTP64m : FPI<0xDD, MRM3m, (ops f64mem:$dst), "fstp{l} $dst">; |
| 388 | def FIST16m : FPI<0xDF, MRM2m, (ops i16mem:$dst), "fist{s} $dst">; |
| 389 | def FIST32m : FPI<0xDB, MRM2m, (ops i32mem:$dst), "fist{l} $dst">; |
| 390 | def FISTP16m : FPI<0xDF, MRM3m, (ops i16mem:$dst), "fistp{s} $dst">; |
| 391 | def FISTP32m : FPI<0xDB, MRM3m, (ops i32mem:$dst), "fistp{l} $dst">; |
| 392 | def FISTP64m : FPI<0xDF, MRM7m, (ops i64mem:$dst), "fistp{ll} $dst">; |
| 393 | |
| 394 | // FISTTP requires SSE3 even though it's a FPStack op. |
| 395 | def FpISTT16m : FpI_<(ops i16mem:$op, RFP:$src), OneArgFP, |
| 396 | [(X86fp_to_i16mem RFP:$src, addr:$op)]>, |
| 397 | Requires<[HasSSE3]>; |
| 398 | def FpISTT32m : FpI_<(ops i32mem:$op, RFP:$src), OneArgFP, |
| 399 | [(X86fp_to_i32mem RFP:$src, addr:$op)]>, |
| 400 | Requires<[HasSSE3]>; |
| 401 | def FpISTT64m : FpI_<(ops i64mem:$op, RFP:$src), OneArgFP, |
| 402 | [(X86fp_to_i64mem RFP:$src, addr:$op)]>, |
| 403 | Requires<[HasSSE3]>; |
| 404 | |
| 405 | def FISTTP16m : FPI<0xDF, MRM1m, (ops i16mem:$dst), "fisttp{s} $dst">; |
| 406 | def FISTTP32m : FPI<0xDB, MRM1m, (ops i32mem:$dst), "fisttp{l} $dst">; |
| 407 | def FISTTP64m : FPI<0xDD, MRM1m, (ops i64mem:$dst), "fisttp{ll} $dst">; |
| 408 | |
| 409 | // FP Stack manipulation instructions. |
| 410 | def FLDrr : FPI<0xC0, AddRegFrm, (ops RST:$op), "fld $op">, D9; |
| 411 | def FSTrr : FPI<0xD0, AddRegFrm, (ops RST:$op), "fst $op">, DD; |
| 412 | def FSTPrr : FPI<0xD8, AddRegFrm, (ops RST:$op), "fstp $op">, DD; |
| 413 | def FXCH : FPI<0xC8, AddRegFrm, (ops RST:$op), "fxch $op">, D9; |
| 414 | |
| 415 | // Floating point constant loads. |
| 416 | def FpLD0 : FpI<(ops RFP:$dst), ZeroArgFP, |
| 417 | [(set RFP:$dst, fp64imm0)]>; |
| 418 | def FpLD1 : FpI<(ops RFP:$dst), ZeroArgFP, |
| 419 | [(set RFP:$dst, fp64imm1)]>; |
| 420 | |
| 421 | def FLD0 : FPI<0xEE, RawFrm, (ops), "fldz">, D9; |
| 422 | def FLD1 : FPI<0xE8, RawFrm, (ops), "fld1">, D9; |
| 423 | |
| 424 | |
| 425 | // Floating point compares. |
| 426 | def FpUCOMr : FpI<(ops RFP:$lhs, RFP:$rhs), CompareFP, |
| 427 | []>; // FPSW = cmp ST(0) with ST(i) |
| 428 | def FpUCOMIr : FpI<(ops RFP:$lhs, RFP:$rhs), CompareFP, |
| 429 | [(X86cmp RFP:$lhs, RFP:$rhs)]>; // CC = cmp ST(0) with ST(i) |
| 430 | |
| 431 | def FUCOMr : FPI<0xE0, AddRegFrm, // FPSW = cmp ST(0) with ST(i) |
| 432 | (ops RST:$reg), |
| 433 | "fucom $reg">, DD, Imp<[ST0],[]>; |
| 434 | def FUCOMPr : FPI<0xE8, AddRegFrm, // FPSW = cmp ST(0) with ST(i), pop |
| 435 | (ops RST:$reg), |
| 436 | "fucomp $reg">, DD, Imp<[ST0],[]>; |
| 437 | def FUCOMPPr : FPI<0xE9, RawFrm, // cmp ST(0) with ST(1), pop, pop |
| 438 | (ops), |
| 439 | "fucompp">, DA, Imp<[ST0],[]>; |
| 440 | |
| 441 | def FUCOMIr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i) |
| 442 | (ops RST:$reg), |
| 443 | "fucomi {$reg, %st(0)|%ST(0), $reg}">, DB, Imp<[ST0],[]>; |
| 444 | def FUCOMIPr : FPI<0xE8, AddRegFrm, // CC = cmp ST(0) with ST(i), pop |
| 445 | (ops RST:$reg), |
| 446 | "fucomip {$reg, %st(0)|%ST(0), $reg}">, DF, Imp<[ST0],[]>; |
| 447 | |
| 448 | |
| 449 | // Floating point flag ops. |
| 450 | def FNSTSW8r : I<0xE0, RawFrm, // AX = fp flags |
| 451 | (ops), "fnstsw", []>, DF, Imp<[],[AX]>; |
| 452 | |
| 453 | def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world |
| 454 | (ops i16mem:$dst), "fnstcw $dst", []>; |
| 455 | def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] |
| 456 | (ops i16mem:$dst), "fldcw $dst", []>; |
Evan Cheng | 4e4c71e | 2006-02-21 20:00:20 +0000 | [diff] [blame] | 457 | |
| 458 | //===----------------------------------------------------------------------===// |
| 459 | // Non-Instruction Patterns |
| 460 | //===----------------------------------------------------------------------===// |
| 461 | |
| 462 | // Required for RET of f32 / f64 values. |
| 463 | def : Pat<(X86fld addr:$src, f32), (FpLD32m addr:$src)>; |
| 464 | def : Pat<(X86fld addr:$src, f64), (FpLD64m addr:$src)>; |
| 465 | |
| 466 | // Required for CALL which return f32 / f64 values. |
| 467 | def : Pat<(X86fst RFP:$src, addr:$op, f32), (FpST32m addr:$op, RFP:$src)>; |
| 468 | def : Pat<(X86fst RFP:$src, addr:$op, f64), (FpST64m addr:$op, RFP:$src)>; |
| 469 | |
| 470 | // Floating point constant -0.0 and -1.0 |
| 471 | def : Pat<(f64 fp64immneg0), (FpCHS (FpLD0))>, Requires<[FPStack]>; |
| 472 | def : Pat<(f64 fp64immneg1), (FpCHS (FpLD1))>, Requires<[FPStack]>; |
| 473 | |
| 474 | // Used to conv. i64 to f64 since there isn't a SSE version. |
| 475 | def : Pat<(X86fildflag addr:$src, i64), (FpILD64m addr:$src)>; |