| OLD | NEW |
| 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// | 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| 11 /// This file implements the InstX8632 and OperandX8632 classes, | 11 /// This file defines X8632 specific data related to X8632 Instructions and |
| 12 /// primarily the constructors and the dump()/emit() methods. | 12 /// Instruction traits. These are declared in the IceTargetLoweringX8632Traits.h |
| 13 /// header file. |
| 14 /// |
| 15 /// This file also defines X8632 operand specific methods (dump and emit.) |
| 13 /// | 16 /// |
| 14 //===----------------------------------------------------------------------===// | 17 //===----------------------------------------------------------------------===// |
| 15 | |
| 16 #include "IceInstX8632.h" | 18 #include "IceInstX8632.h" |
| 17 | 19 |
| 18 #include "IceAssemblerX8632.h" | 20 #include "IceAssemblerX8632.h" |
| 19 #include "IceCfg.h" | 21 #include "IceCfg.h" |
| 20 #include "IceCfgNode.h" | 22 #include "IceCfgNode.h" |
| 21 #include "IceConditionCodesX8632.h" | 23 #include "IceConditionCodesX8632.h" |
| 22 #include "IceInst.h" | 24 #include "IceInst.h" |
| 23 #include "IceRegistersX8632.h" | 25 #include "IceRegistersX8632.h" |
| 24 #include "IceTargetLoweringX8632.h" | 26 #include "IceTargetLoweringX8632.h" |
| 25 #include "IceOperand.h" | 27 #include "IceOperand.h" |
| 26 | 28 |
| 27 namespace Ice { | 29 namespace Ice { |
| 28 | 30 |
| 29 namespace { | 31 namespace X86Internal { |
| 30 | 32 |
| 31 const struct InstX8632BrAttributes_ { | 33 const MachineTraits<TargetX8632>::InstBrAttributesType |
| 32 X8632::Traits::Cond::BrCond Opposite; | 34 MachineTraits<TargetX8632>::InstBrAttributes[] = { |
| 33 const char *DisplayString; | |
| 34 const char *EmitString; | |
| 35 } InstX8632BrAttributes[] = { | |
| 36 #define X(tag, encode, opp, dump, emit) \ | 35 #define X(tag, encode, opp, dump, emit) \ |
| 37 { X8632::Traits::Cond::opp, dump, emit } \ | 36 { X8632::Traits::Cond::opp, dump, emit } \ |
| 38 , | 37 , |
| 39 ICEINSTX8632BR_TABLE | 38 ICEINSTX8632BR_TABLE |
| 40 #undef X | 39 #undef X |
| 41 }; | 40 }; |
| 42 | 41 |
| 43 const struct InstX8632CmppsAttributes_ { | 42 const MachineTraits<TargetX8632>::InstCmppsAttributesType |
| 44 const char *EmitString; | 43 MachineTraits<TargetX8632>::InstCmppsAttributes[] = { |
| 45 } InstX8632CmppsAttributes[] = { | |
| 46 #define X(tag, emit) \ | 44 #define X(tag, emit) \ |
| 47 { emit } \ | 45 { emit } \ |
| 48 , | 46 , |
| 49 ICEINSTX8632CMPPS_TABLE | 47 ICEINSTX8632CMPPS_TABLE |
| 50 #undef X | 48 #undef X |
| 51 }; | 49 }; |
| 52 | 50 |
| 53 const struct TypeX8632Attributes_ { | 51 const MachineTraits<TargetX8632>::TypeAttributesType |
| 54 const char *CvtString; // i (integer), s (single FP), d (double FP) | 52 MachineTraits<TargetX8632>::TypeAttributes[] = { |
| 55 const char *SdSsString; // ss, sd, or <blank> | |
| 56 const char *PackString; // b, w, d, or <blank> | |
| 57 const char *WidthString; // b, w, l, q, or <blank> | |
| 58 const char *FldString; // s, l, or <blank> | |
| 59 } TypeX8632Attributes[] = { | |
| 60 #define X(tag, elementty, cvt, sdss, pack, width, fld) \ | 53 #define X(tag, elementty, cvt, sdss, pack, width, fld) \ |
| 61 { cvt, sdss, pack, width, fld } \ | 54 { cvt, sdss, pack, width, fld } \ |
| 62 , | 55 , |
| 63 ICETYPEX8632_TABLE | 56 ICETYPEX8632_TABLE |
| 64 #undef X | 57 #undef X |
| 65 }; | 58 }; |
| 66 | 59 |
| 67 const char *InstX8632SegmentRegNames[] = { | 60 const char *MachineTraits<TargetX8632>::InstSegmentRegNames[] = { |
| 68 #define X(val, name, prefix) name, | 61 #define X(val, name, prefix) name, |
| 69 SEG_REGX8632_TABLE | 62 SEG_REGX8632_TABLE |
| 70 #undef X | 63 #undef X |
| 71 }; | 64 }; |
| 72 | 65 |
| 73 uint8_t InstX8632SegmentPrefixes[] = { | 66 uint8_t MachineTraits<TargetX8632>::InstSegmentPrefixes[] = { |
| 74 #define X(val, name, prefix) prefix, | 67 #define X(val, name, prefix) prefix, |
| 75 SEG_REGX8632_TABLE | 68 SEG_REGX8632_TABLE |
| 76 #undef X | 69 #undef X |
| 77 }; | 70 }; |
| 78 | 71 |
| 79 } // end of anonymous namespace | 72 void MachineTraits<TargetX8632>::X86Operand::dump(const Cfg *, |
| 80 | 73 Ostream &Str) const { |
| 81 const char *InstX8632::getWidthString(Type Ty) { | 74 if (BuildDefs::dump()) |
| 82 return TypeX8632Attributes[Ty].WidthString; | 75 Str << "<OperandX8632>"; |
| 83 } | 76 } |
| 84 | 77 |
| 85 const char *InstX8632::getFldString(Type Ty) { | 78 MachineTraits<TargetX8632>::X86OperandMem::X86OperandMem( |
| 86 return TypeX8632Attributes[Ty].FldString; | 79 Cfg *Func, Type Ty, Variable *Base, Constant *Offset, Variable *Index, |
| 87 } | 80 uint16_t Shift, SegmentRegisters SegmentReg) |
| 88 | 81 : X86Operand(kMem, Ty), Base(Base), Offset(Offset), Index(Index), |
| 89 X8632::Traits::Cond::BrCond | |
| 90 InstX8632::getOppositeCondition(X8632::Traits::Cond::BrCond Cond) { | |
| 91 return InstX8632BrAttributes[Cond].Opposite; | |
| 92 } | |
| 93 | |
| 94 OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base, | |
| 95 Constant *Offset, Variable *Index, | |
| 96 uint16_t Shift, SegmentRegisters SegmentReg) | |
| 97 : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index), | |
| 98 Shift(Shift), SegmentReg(SegmentReg), Randomized(false) { | 82 Shift(Shift), SegmentReg(SegmentReg), Randomized(false) { |
| 99 assert(Shift <= 3); | 83 assert(Shift <= 3); |
| 100 Vars = nullptr; | 84 Vars = nullptr; |
| 101 NumVars = 0; | 85 NumVars = 0; |
| 102 if (Base) | 86 if (Base) |
| 103 ++NumVars; | 87 ++NumVars; |
| 104 if (Index) | 88 if (Index) |
| 105 ++NumVars; | 89 ++NumVars; |
| 106 if (NumVars) { | 90 if (NumVars) { |
| 107 Vars = Func->allocateArrayOf<Variable *>(NumVars); | 91 Vars = Func->allocateArrayOf<Variable *>(NumVars); |
| 108 SizeT I = 0; | 92 SizeT I = 0; |
| 109 if (Base) | 93 if (Base) |
| 110 Vars[I++] = Base; | 94 Vars[I++] = Base; |
| 111 if (Index) | 95 if (Index) |
| 112 Vars[I++] = Index; | 96 Vars[I++] = Index; |
| 113 assert(I == NumVars); | 97 assert(I == NumVars); |
| 114 } | 98 } |
| 115 } | 99 } |
| 116 | 100 |
| 117 InstX8632FakeRMW::InstX8632FakeRMW(Cfg *Func, Operand *Data, Operand *Addr, | 101 void MachineTraits<TargetX8632>::X86OperandMem::emit(const Cfg *Func) const { |
| 118 InstArithmetic::OpKind Op, Variable *Beacon) | |
| 119 : InstX8632(Func, InstX8632::FakeRMW, 3, nullptr), Op(Op) { | |
| 120 addSource(Data); | |
| 121 addSource(Addr); | |
| 122 addSource(Beacon); | |
| 123 } | |
| 124 | |
| 125 InstX8632AdjustStack::InstX8632AdjustStack(Cfg *Func, SizeT Amount, | |
| 126 Variable *Esp) | |
| 127 : InstX8632(Func, InstX8632::Adjuststack, 1, Esp), Amount(Amount) { | |
| 128 addSource(Esp); | |
| 129 } | |
| 130 | |
| 131 InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1, | |
| 132 Operand *Source2) | |
| 133 : InstX8632(Func, InstX8632::Mul, 2, Dest) { | |
| 134 addSource(Source1); | |
| 135 addSource(Source2); | |
| 136 } | |
| 137 | |
| 138 InstX8632Shld::InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1, | |
| 139 Variable *Source2) | |
| 140 : InstX8632(Func, InstX8632::Shld, 3, Dest) { | |
| 141 addSource(Dest); | |
| 142 addSource(Source1); | |
| 143 addSource(Source2); | |
| 144 } | |
| 145 | |
| 146 InstX8632Shrd::InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1, | |
| 147 Variable *Source2) | |
| 148 : InstX8632(Func, InstX8632::Shrd, 3, Dest) { | |
| 149 addSource(Dest); | |
| 150 addSource(Source1); | |
| 151 addSource(Source2); | |
| 152 } | |
| 153 | |
| 154 InstX8632Label::InstX8632Label(Cfg *Func, TargetX8632 *Target) | |
| 155 : InstX8632(Func, InstX8632::Label, 0, nullptr), | |
| 156 Number(Target->makeNextLabelNumber()) {} | |
| 157 | |
| 158 IceString InstX8632Label::getName(const Cfg *Func) const { | |
| 159 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number); | |
| 160 } | |
| 161 | |
| 162 InstX8632Br::InstX8632Br(Cfg *Func, const CfgNode *TargetTrue, | |
| 163 const CfgNode *TargetFalse, | |
| 164 const InstX8632Label *Label, | |
| 165 X8632::Traits::Cond::BrCond Condition) | |
| 166 : InstX8632(Func, InstX8632::Br, 0, nullptr), Condition(Condition), | |
| 167 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {} | |
| 168 | |
| 169 bool InstX8632Br::optimizeBranch(const CfgNode *NextNode) { | |
| 170 // If there is no next block, then there can be no fallthrough to | |
| 171 // optimize. | |
| 172 if (NextNode == nullptr) | |
| 173 return false; | |
| 174 // Intra-block conditional branches can't be optimized. | |
| 175 if (Label) | |
| 176 return false; | |
| 177 // If there is no fallthrough node, such as a non-default case label | |
| 178 // for a switch instruction, then there is no opportunity to | |
| 179 // optimize. | |
| 180 if (getTargetFalse() == nullptr) | |
| 181 return false; | |
| 182 | |
| 183 // Unconditional branch to the next node can be removed. | |
| 184 if (Condition == X8632::Traits::Cond::Br_None && | |
| 185 getTargetFalse() == NextNode) { | |
| 186 assert(getTargetTrue() == nullptr); | |
| 187 setDeleted(); | |
| 188 return true; | |
| 189 } | |
| 190 // If the fallthrough is to the next node, set fallthrough to nullptr | |
| 191 // to indicate. | |
| 192 if (getTargetFalse() == NextNode) { | |
| 193 TargetFalse = nullptr; | |
| 194 return true; | |
| 195 } | |
| 196 // If TargetTrue is the next node, and TargetFalse is not nullptr | |
| 197 // (which was already tested above), then invert the branch | |
| 198 // condition, swap the targets, and set new fallthrough to nullptr. | |
| 199 if (getTargetTrue() == NextNode) { | |
| 200 assert(Condition != X8632::Traits::Cond::Br_None); | |
| 201 Condition = getOppositeCondition(Condition); | |
| 202 TargetTrue = getTargetFalse(); | |
| 203 TargetFalse = nullptr; | |
| 204 return true; | |
| 205 } | |
| 206 return false; | |
| 207 } | |
| 208 | |
| 209 bool InstX8632Br::repointEdge(CfgNode *OldNode, CfgNode *NewNode) { | |
| 210 if (TargetFalse == OldNode) { | |
| 211 TargetFalse = NewNode; | |
| 212 return true; | |
| 213 } else if (TargetTrue == OldNode) { | |
| 214 TargetTrue = NewNode; | |
| 215 return true; | |
| 216 } | |
| 217 return false; | |
| 218 } | |
| 219 | |
| 220 InstX8632Jmp::InstX8632Jmp(Cfg *Func, Operand *Target) | |
| 221 : InstX8632(Func, InstX8632::Jmp, 1, nullptr) { | |
| 222 addSource(Target); | |
| 223 } | |
| 224 | |
| 225 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) | |
| 226 : InstX8632(Func, InstX8632::Call, 1, Dest) { | |
| 227 HasSideEffects = true; | |
| 228 addSource(CallTarget); | |
| 229 } | |
| 230 | |
| 231 InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, | |
| 232 X8632::Traits::Cond::BrCond Condition) | |
| 233 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) { | |
| 234 // The final result is either the original Dest, or Source, so mark | |
| 235 // both as sources. | |
| 236 addSource(Dest); | |
| 237 addSource(Source); | |
| 238 } | |
| 239 | |
| 240 InstX8632Cmpps::InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source, | |
| 241 X8632::Traits::Cond::CmppsCond Condition) | |
| 242 : InstX8632(Func, InstX8632::Cmpps, 2, Dest), Condition(Condition) { | |
| 243 addSource(Dest); | |
| 244 addSource(Source); | |
| 245 } | |
| 246 | |
| 247 InstX8632Cmpxchg::InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr, | |
| 248 Variable *Eax, Variable *Desired, | |
| 249 bool Locked) | |
| 250 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 3, | |
| 251 llvm::dyn_cast<Variable>(DestOrAddr), Locked) { | |
| 252 assert(Eax->getRegNum() == RegX8632::Reg_eax); | |
| 253 addSource(DestOrAddr); | |
| 254 addSource(Eax); | |
| 255 addSource(Desired); | |
| 256 } | |
| 257 | |
| 258 InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632Mem *Addr, | |
| 259 Variable *Edx, Variable *Eax, | |
| 260 Variable *Ecx, Variable *Ebx, | |
| 261 bool Locked) | |
| 262 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 5, nullptr, Locked) { | |
| 263 assert(Edx->getRegNum() == RegX8632::Reg_edx); | |
| 264 assert(Eax->getRegNum() == RegX8632::Reg_eax); | |
| 265 assert(Ecx->getRegNum() == RegX8632::Reg_ecx); | |
| 266 assert(Ebx->getRegNum() == RegX8632::Reg_ebx); | |
| 267 addSource(Addr); | |
| 268 addSource(Edx); | |
| 269 addSource(Eax); | |
| 270 addSource(Ecx); | |
| 271 addSource(Ebx); | |
| 272 } | |
| 273 | |
| 274 InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source, | |
| 275 CvtVariant Variant) | |
| 276 : InstX8632(Func, InstX8632::Cvt, 1, Dest), Variant(Variant) { | |
| 277 addSource(Source); | |
| 278 } | |
| 279 | |
| 280 InstX8632Icmp::InstX8632Icmp(Cfg *Func, Operand *Src0, Operand *Src1) | |
| 281 : InstX8632(Func, InstX8632::Icmp, 2, nullptr) { | |
| 282 addSource(Src0); | |
| 283 addSource(Src1); | |
| 284 } | |
| 285 | |
| 286 InstX8632Ucomiss::InstX8632Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1) | |
| 287 : InstX8632(Func, InstX8632::Ucomiss, 2, nullptr) { | |
| 288 addSource(Src0); | |
| 289 addSource(Src1); | |
| 290 } | |
| 291 | |
| 292 InstX8632UD2::InstX8632UD2(Cfg *Func) | |
| 293 : InstX8632(Func, InstX8632::UD2, 0, nullptr) {} | |
| 294 | |
| 295 InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2) | |
| 296 : InstX8632(Func, InstX8632::Test, 2, nullptr) { | |
| 297 addSource(Src1); | |
| 298 addSource(Src2); | |
| 299 } | |
| 300 | |
| 301 InstX8632Mfence::InstX8632Mfence(Cfg *Func) | |
| 302 : InstX8632(Func, InstX8632::Mfence, 0, nullptr) { | |
| 303 HasSideEffects = true; | |
| 304 } | |
| 305 | |
| 306 InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem) | |
| 307 : InstX8632(Func, InstX8632::Store, 2, nullptr) { | |
| 308 addSource(Value); | |
| 309 addSource(Mem); | |
| 310 } | |
| 311 | |
| 312 InstX8632StoreP::InstX8632StoreP(Cfg *Func, Variable *Value, | |
| 313 OperandX8632Mem *Mem) | |
| 314 : InstX8632(Func, InstX8632::StoreP, 2, nullptr) { | |
| 315 addSource(Value); | |
| 316 addSource(Mem); | |
| 317 } | |
| 318 | |
| 319 InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Variable *Value, | |
| 320 OperandX8632Mem *Mem) | |
| 321 : InstX8632(Func, InstX8632::StoreQ, 2, nullptr) { | |
| 322 addSource(Value); | |
| 323 addSource(Mem); | |
| 324 } | |
| 325 | |
| 326 InstX8632Nop::InstX8632Nop(Cfg *Func, InstX8632Nop::NopVariant Variant) | |
| 327 : InstX8632(Func, InstX8632::Nop, 0, nullptr), Variant(Variant) {} | |
| 328 | |
| 329 InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src) | |
| 330 : InstX8632(Func, InstX8632::Fld, 1, nullptr) { | |
| 331 addSource(Src); | |
| 332 } | |
| 333 | |
| 334 InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest) | |
| 335 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {} | |
| 336 | |
| 337 InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest) | |
| 338 : InstX8632(Func, InstX8632::Pop, 0, Dest) { | |
| 339 // A pop instruction affects the stack pointer and so it should not | |
| 340 // be allowed to be automatically dead-code eliminated. (The | |
| 341 // corresponding push instruction doesn't need this treatment | |
| 342 // because it has no dest variable and therefore won't be dead-code | |
| 343 // eliminated.) This is needed for late-stage liveness analysis | |
| 344 // (e.g. asm-verbose mode). | |
| 345 HasSideEffects = true; | |
| 346 } | |
| 347 | |
| 348 InstX8632Push::InstX8632Push(Cfg *Func, Variable *Source) | |
| 349 : InstX8632(Func, InstX8632::Push, 1, nullptr) { | |
| 350 addSource(Source); | |
| 351 } | |
| 352 | |
| 353 InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) | |
| 354 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, nullptr) { | |
| 355 if (Source) | |
| 356 addSource(Source); | |
| 357 } | |
| 358 | |
| 359 InstX8632Setcc::InstX8632Setcc(Cfg *Func, Variable *Dest, | |
| 360 X8632::Traits::Cond::BrCond Cond) | |
| 361 : InstX8632(Func, InstX8632::Setcc, 0, Dest), Condition(Cond) {} | |
| 362 | |
| 363 InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source, | |
| 364 bool Locked) | |
| 365 : InstX8632Lockable(Func, InstX8632::Xadd, 2, | |
| 366 llvm::dyn_cast<Variable>(Dest), Locked) { | |
| 367 addSource(Dest); | |
| 368 addSource(Source); | |
| 369 } | |
| 370 | |
| 371 InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source) | |
| 372 : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) { | |
| 373 addSource(Dest); | |
| 374 addSource(Source); | |
| 375 } | |
| 376 | |
| 377 // ======================== Dump routines ======================== // | |
| 378 | |
| 379 void InstX8632::dump(const Cfg *Func) const { | |
| 380 if (!BuildDefs::dump()) | |
| 381 return; | |
| 382 Ostream &Str = Func->getContext()->getStrDump(); | |
| 383 Str << "[X8632] "; | |
| 384 Inst::dump(Func); | |
| 385 } | |
| 386 | |
| 387 void InstX8632FakeRMW::dump(const Cfg *Func) const { | |
| 388 if (!BuildDefs::dump()) | |
| 389 return; | |
| 390 Ostream &Str = Func->getContext()->getStrDump(); | |
| 391 Type Ty = getData()->getType(); | |
| 392 Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *"; | |
| 393 getAddr()->dump(Func); | |
| 394 Str << ", "; | |
| 395 getData()->dump(Func); | |
| 396 Str << ", beacon="; | |
| 397 getBeacon()->dump(Func); | |
| 398 } | |
| 399 | |
| 400 void InstX8632Label::emit(const Cfg *Func) const { | |
| 401 if (!BuildDefs::dump()) | |
| 402 return; | |
| 403 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 404 Str << getName(Func) << ":"; | |
| 405 } | |
| 406 | |
| 407 void InstX8632Label::emitIAS(const Cfg *Func) const { | |
| 408 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 409 Asm->BindLocalLabel(Number); | |
| 410 } | |
| 411 | |
| 412 void InstX8632Label::dump(const Cfg *Func) const { | |
| 413 if (!BuildDefs::dump()) | |
| 414 return; | |
| 415 Ostream &Str = Func->getContext()->getStrDump(); | |
| 416 Str << getName(Func) << ":"; | |
| 417 } | |
| 418 | |
| 419 void InstX8632Br::emit(const Cfg *Func) const { | |
| 420 if (!BuildDefs::dump()) | |
| 421 return; | |
| 422 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 423 Str << "\t"; | |
| 424 | |
| 425 if (Condition == X8632::Traits::Cond::Br_None) { | |
| 426 Str << "jmp"; | |
| 427 } else { | |
| 428 Str << InstX8632BrAttributes[Condition].EmitString; | |
| 429 } | |
| 430 | |
| 431 if (Label) { | |
| 432 Str << "\t" << Label->getName(Func); | |
| 433 } else { | |
| 434 if (Condition == X8632::Traits::Cond::Br_None) { | |
| 435 Str << "\t" << getTargetFalse()->getAsmName(); | |
| 436 } else { | |
| 437 Str << "\t" << getTargetTrue()->getAsmName(); | |
| 438 if (getTargetFalse()) { | |
| 439 Str << "\n\tjmp\t" << getTargetFalse()->getAsmName(); | |
| 440 } | |
| 441 } | |
| 442 } | |
| 443 } | |
| 444 | |
| 445 void InstX8632Br::emitIAS(const Cfg *Func) const { | |
| 446 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 447 if (Label) { | |
| 448 X8632::Label *L = Asm->GetOrCreateLocalLabel(Label->getNumber()); | |
| 449 // In all these cases, local Labels should only be used for Near. | |
| 450 const bool Near = true; | |
| 451 if (Condition == X8632::Traits::Cond::Br_None) { | |
| 452 Asm->jmp(L, Near); | |
| 453 } else { | |
| 454 Asm->j(Condition, L, Near); | |
| 455 } | |
| 456 } else { | |
| 457 // Pessimistically assume it's far. This only affects Labels that | |
| 458 // are not Bound. | |
| 459 const bool Near = false; | |
| 460 if (Condition == X8632::Traits::Cond::Br_None) { | |
| 461 X8632::Label *L = | |
| 462 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); | |
| 463 assert(!getTargetTrue()); | |
| 464 Asm->jmp(L, Near); | |
| 465 } else { | |
| 466 X8632::Label *L = | |
| 467 Asm->GetOrCreateCfgNodeLabel(getTargetTrue()->getIndex()); | |
| 468 Asm->j(Condition, L, Near); | |
| 469 if (getTargetFalse()) { | |
| 470 X8632::Label *L2 = | |
| 471 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); | |
| 472 Asm->jmp(L2, Near); | |
| 473 } | |
| 474 } | |
| 475 } | |
| 476 } | |
| 477 | |
| 478 void InstX8632Br::dump(const Cfg *Func) const { | |
| 479 if (!BuildDefs::dump()) | |
| 480 return; | |
| 481 Ostream &Str = Func->getContext()->getStrDump(); | |
| 482 Str << "br "; | |
| 483 | |
| 484 if (Condition == X8632::Traits::Cond::Br_None) { | |
| 485 Str << "label %" | |
| 486 << (Label ? Label->getName(Func) : getTargetFalse()->getName()); | |
| 487 return; | |
| 488 } | |
| 489 | |
| 490 Str << InstX8632BrAttributes[Condition].DisplayString; | |
| 491 if (Label) { | |
| 492 Str << ", label %" << Label->getName(Func); | |
| 493 } else { | |
| 494 Str << ", label %" << getTargetTrue()->getName(); | |
| 495 if (getTargetFalse()) { | |
| 496 Str << ", label %" << getTargetFalse()->getName(); | |
| 497 } | |
| 498 } | |
| 499 } | |
| 500 | |
| 501 void InstX8632Jmp::emit(const Cfg *Func) const { | |
| 502 if (!BuildDefs::dump()) | |
| 503 return; | |
| 504 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 505 assert(getSrcSize() == 1); | |
| 506 Str << "\tjmp\t*"; | |
| 507 getJmpTarget()->emit(Func); | |
| 508 } | |
| 509 | |
| 510 void InstX8632Jmp::emitIAS(const Cfg *Func) const { | |
| 511 // Note: Adapted (mostly copied) from InstX8632Call::emitIAS(). | |
| 512 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 513 Operand *Target = getJmpTarget(); | |
| 514 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { | |
| 515 if (Var->hasReg()) { | |
| 516 Asm->jmp(RegX8632::getEncodedGPR(Var->getRegNum())); | |
| 517 } else { | |
| 518 // The jmp instruction with a memory operand should be possible | |
| 519 // to encode, but it isn't a valid sandboxed instruction, and | |
| 520 // there shouldn't be a register allocation issue to jump | |
| 521 // through a scratch register, so we don't really need to bother | |
| 522 // implementing it. | |
| 523 llvm::report_fatal_error("Assembler can't jmp to memory operand"); | |
| 524 } | |
| 525 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { | |
| 526 (void)Mem; | |
| 527 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 528 llvm::report_fatal_error("Assembler can't jmp to memory operand"); | |
| 529 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { | |
| 530 assert(CR->getOffset() == 0 && "We only support jumping to a function"); | |
| 531 Asm->jmp(CR); | |
| 532 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { | |
| 533 // NaCl trampoline calls refer to an address within the sandbox directly. | |
| 534 // This is usually only needed for non-IRT builds and otherwise not | |
| 535 // very portable or stable. Usually this is only done for "calls" | |
| 536 // and not jumps. | |
| 537 // TODO(jvoung): Support this when there is a lowering that | |
| 538 // actually triggers this case. | |
| 539 (void)Imm; | |
| 540 llvm::report_fatal_error("Unexpected jmp to absolute address"); | |
| 541 } else { | |
| 542 llvm::report_fatal_error("Unexpected operand type"); | |
| 543 } | |
| 544 } | |
| 545 | |
| 546 void InstX8632Jmp::dump(const Cfg *Func) const { | |
| 547 if (!BuildDefs::dump()) | |
| 548 return; | |
| 549 Ostream &Str = Func->getContext()->getStrDump(); | |
| 550 Str << "jmp "; | |
| 551 getJmpTarget()->dump(Func); | |
| 552 } | |
| 553 | |
| 554 void InstX8632Call::emit(const Cfg *Func) const { | |
| 555 if (!BuildDefs::dump()) | |
| 556 return; | |
| 557 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 558 assert(getSrcSize() == 1); | |
| 559 Str << "\tcall\t"; | |
| 560 if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getCallTarget())) { | |
| 561 // Emit without a leading '$'. | |
| 562 Str << CI->getValue(); | |
| 563 } else if (const auto CallTarget = | |
| 564 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { | |
| 565 CallTarget->emitWithoutPrefix(Func->getTarget()); | |
| 566 } else { | |
| 567 Str << "*"; | |
| 568 getCallTarget()->emit(Func); | |
| 569 } | |
| 570 Func->getTarget()->resetStackAdjustment(); | |
| 571 } | |
| 572 | |
| 573 void InstX8632Call::emitIAS(const Cfg *Func) const { | |
| 574 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 575 Operand *Target = getCallTarget(); | |
| 576 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { | |
| 577 if (Var->hasReg()) { | |
| 578 Asm->call(RegX8632::getEncodedGPR(Var->getRegNum())); | |
| 579 } else { | |
| 580 Asm->call(static_cast<TargetX8632 *>(Func->getTarget()) | |
| 581 ->stackVarToAsmOperand(Var)); | |
| 582 } | |
| 583 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { | |
| 584 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 585 Asm->call(Mem->toAsmAddress(Asm)); | |
| 586 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { | |
| 587 assert(CR->getOffset() == 0 && "We only support calling a function"); | |
| 588 Asm->call(CR); | |
| 589 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { | |
| 590 Asm->call(X8632::Immediate(Imm->getValue())); | |
| 591 } else { | |
| 592 llvm_unreachable("Unexpected operand type"); | |
| 593 } | |
| 594 Func->getTarget()->resetStackAdjustment(); | |
| 595 } | |
| 596 | |
| 597 void InstX8632Call::dump(const Cfg *Func) const { | |
| 598 if (!BuildDefs::dump()) | |
| 599 return; | |
| 600 Ostream &Str = Func->getContext()->getStrDump(); | |
| 601 if (getDest()) { | |
| 602 dumpDest(Func); | |
| 603 Str << " = "; | |
| 604 } | |
| 605 Str << "call "; | |
| 606 getCallTarget()->dump(Func); | |
| 607 } | |
| 608 | |
| 609 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for | |
| 610 // shift instructions, in order to be syntactically valid. The | |
| 611 // Opcode parameter needs to be char* and not IceString because of | |
| 612 // template issues. | |
| 613 void InstX8632::emitTwoAddress(const char *Opcode, const Inst *Inst, | |
| 614 const Cfg *Func, bool ShiftHack) { | |
| 615 if (!BuildDefs::dump()) | |
| 616 return; | |
| 617 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 618 assert(Inst->getSrcSize() == 2); | |
| 619 Operand *Dest = Inst->getDest(); | |
| 620 if (Dest == nullptr) | |
| 621 Dest = Inst->getSrc(0); | |
| 622 assert(Dest == Inst->getSrc(0)); | |
| 623 Operand *Src1 = Inst->getSrc(1); | |
| 624 Str << "\t" << Opcode << InstX8632::getWidthString(Dest->getType()) << "\t"; | |
| 625 const auto ShiftReg = llvm::dyn_cast<Variable>(Src1); | |
| 626 if (ShiftHack && ShiftReg && ShiftReg->getRegNum() == RegX8632::Reg_ecx) | |
| 627 Str << "%cl"; | |
| 628 else | |
| 629 Src1->emit(Func); | |
| 630 Str << ", "; | |
| 631 Dest->emit(Func); | |
| 632 } | |
| 633 | |
| 634 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, | |
| 635 const X8632::AssemblerX8632::GPREmitterOneOp &Emitter) { | |
| 636 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 637 if (const auto Var = llvm::dyn_cast<Variable>(Op)) { | |
| 638 if (Var->hasReg()) { | |
| 639 // We cheat a little and use GPRRegister even for byte operations. | |
| 640 RegX8632::GPRRegister VarReg = | |
| 641 RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); | |
| 642 (Asm->*(Emitter.Reg))(Ty, VarReg); | |
| 643 } else { | |
| 644 X8632::Traits::Address StackAddr( | |
| 645 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 646 ->stackVarToAsmOperand(Var)); | |
| 647 (Asm->*(Emitter.Addr))(Ty, StackAddr); | |
| 648 } | |
| 649 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) { | |
| 650 Mem->emitSegmentOverride(Asm); | |
| 651 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm)); | |
| 652 } else { | |
| 653 llvm_unreachable("Unexpected operand type"); | |
| 654 } | |
| 655 } | |
| 656 | |
| 657 template <bool VarCanBeByte, bool SrcCanBeByte> | |
| 658 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, | |
| 659 const Operand *Src, | |
| 660 const X8632::AssemblerX8632::GPREmitterRegOp &Emitter) { | |
| 661 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 662 assert(Var->hasReg()); | |
| 663 // We cheat a little and use GPRRegister even for byte operations. | |
| 664 RegX8632::GPRRegister VarReg = | |
| 665 VarCanBeByte ? RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()) | |
| 666 : RegX8632::getEncodedGPR(Var->getRegNum()); | |
| 667 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | |
| 668 if (SrcVar->hasReg()) { | |
| 669 RegX8632::GPRRegister SrcReg = | |
| 670 SrcCanBeByte | |
| 671 ? RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()) | |
| 672 : RegX8632::getEncodedGPR(SrcVar->getRegNum()); | |
| 673 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); | |
| 674 } else { | |
| 675 X8632::Traits::Address SrcStackAddr = | |
| 676 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 677 ->stackVarToAsmOperand(SrcVar); | |
| 678 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); | |
| 679 } | |
| 680 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | |
| 681 Mem->emitSegmentOverride(Asm); | |
| 682 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); | |
| 683 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | |
| 684 (Asm->*(Emitter.GPRImm))(Ty, VarReg, X8632::Immediate(Imm->getValue())); | |
| 685 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { | |
| 686 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc); | |
| 687 (Asm->*(Emitter.GPRImm))(Ty, VarReg, | |
| 688 X8632::Immediate(Reloc->getOffset(), Fixup)); | |
| 689 } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Src)) { | |
| 690 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); | |
| 691 } else { | |
| 692 llvm_unreachable("Unexpected operand type"); | |
| 693 } | |
| 694 } | |
| 695 | |
| 696 void emitIASAddrOpTyGPR( | |
| 697 const Cfg *Func, Type Ty, const X8632::Traits::Address &Addr, | |
| 698 const Operand *Src, | |
| 699 const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) { | |
| 700 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 701 // Src can only be Reg or Immediate. | |
| 702 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | |
| 703 assert(SrcVar->hasReg()); | |
| 704 RegX8632::GPRRegister SrcReg = | |
| 705 RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); | |
| 706 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); | |
| 707 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | |
| 708 (Asm->*(Emitter.AddrImm))(Ty, Addr, X8632::Immediate(Imm->getValue())); | |
| 709 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { | |
| 710 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Reloc); | |
| 711 (Asm->*(Emitter.AddrImm))(Ty, Addr, | |
| 712 X8632::Immediate(Reloc->getOffset(), Fixup)); | |
| 713 } else { | |
| 714 llvm_unreachable("Unexpected operand type"); | |
| 715 } | |
| 716 } | |
| 717 | |
| 718 void emitIASAsAddrOpTyGPR( | |
| 719 const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1, | |
| 720 const X8632::AssemblerX8632::GPREmitterAddrOp &Emitter) { | |
| 721 if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) { | |
| 722 assert(!Op0Var->hasReg()); | |
| 723 X8632::Traits::Address StackAddr( | |
| 724 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 725 ->stackVarToAsmOperand(Op0Var)); | |
| 726 emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter); | |
| 727 } else if (const auto Op0Mem = llvm::dyn_cast<OperandX8632Mem>(Op0)) { | |
| 728 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 729 Op0Mem->emitSegmentOverride(Asm); | |
| 730 emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm), Op1, Emitter); | |
| 731 } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Op0)) { | |
| 732 emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter); | |
| 733 } else { | |
| 734 llvm_unreachable("Unexpected operand type"); | |
| 735 } | |
| 736 } | |
| 737 | |
| 738 void InstX8632::emitIASGPRShift( | |
| 739 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, | |
| 740 const X8632::AssemblerX8632::GPREmitterShiftOp &Emitter) { | |
| 741 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 742 // Technically, the Dest Var can be mem as well, but we only use Reg. | |
| 743 // We can extend this to check Dest if we decide to use that form. | |
| 744 assert(Var->hasReg()); | |
| 745 // We cheat a little and use GPRRegister even for byte operations. | |
| 746 RegX8632::GPRRegister VarReg = | |
| 747 RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); | |
| 748 // Src must be reg == ECX or an Imm8. | |
| 749 // This is asserted by the assembler. | |
| 750 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | |
| 751 assert(SrcVar->hasReg()); | |
| 752 RegX8632::GPRRegister SrcReg = | |
| 753 RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); | |
| 754 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); | |
| 755 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | |
| 756 (Asm->*(Emitter.GPRImm))(Ty, VarReg, X8632::Immediate(Imm->getValue())); | |
| 757 } else { | |
| 758 llvm_unreachable("Unexpected operand type"); | |
| 759 } | |
| 760 } | |
| 761 | |
| 762 void emitIASGPRShiftDouble( | |
| 763 const Cfg *Func, const Variable *Dest, const Operand *Src1Op, | |
| 764 const Operand *Src2Op, | |
| 765 const X8632::AssemblerX8632::GPREmitterShiftD &Emitter) { | |
| 766 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 767 // Dest can be reg or mem, but we only use the reg variant. | |
| 768 assert(Dest->hasReg()); | |
| 769 RegX8632::GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum()); | |
| 770 // SrcVar1 must be reg. | |
| 771 const auto SrcVar1 = llvm::cast<Variable>(Src1Op); | |
| 772 assert(SrcVar1->hasReg()); | |
| 773 RegX8632::GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar1->getRegNum()); | |
| 774 Type Ty = SrcVar1->getType(); | |
| 775 // Src2 can be the implicit CL register or an immediate. | |
| 776 if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) { | |
| 777 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg, | |
| 778 X8632::Immediate(Imm->getValue())); | |
| 779 } else { | |
| 780 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegX8632::Reg_ecx); | |
| 781 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg); | |
| 782 } | |
| 783 } | |
| 784 | |
| 785 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, | |
| 786 const Operand *Src, | |
| 787 const X8632::AssemblerX8632::XmmEmitterShiftOp &Emitter) { | |
| 788 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 789 assert(Var->hasReg()); | |
| 790 RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum()); | |
| 791 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | |
| 792 if (SrcVar->hasReg()) { | |
| 793 RegX8632::XmmRegister SrcReg = | |
| 794 RegX8632::getEncodedXmm(SrcVar->getRegNum()); | |
| 795 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); | |
| 796 } else { | |
| 797 X8632::Traits::Address SrcStackAddr = | |
| 798 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 799 ->stackVarToAsmOperand(SrcVar); | |
| 800 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); | |
| 801 } | |
| 802 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | |
| 803 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 804 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); | |
| 805 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | |
| 806 (Asm->*(Emitter.XmmImm))(Ty, VarReg, X8632::Immediate(Imm->getValue())); | |
| 807 } else { | |
| 808 llvm_unreachable("Unexpected operand type"); | |
| 809 } | |
| 810 } | |
| 811 | |
| 812 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, | |
| 813 const Operand *Src, | |
| 814 const X8632::AssemblerX8632::XmmEmitterRegOp &Emitter) { | |
| 815 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 816 assert(Var->hasReg()); | |
| 817 RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum()); | |
| 818 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | |
| 819 if (SrcVar->hasReg()) { | |
| 820 RegX8632::XmmRegister SrcReg = | |
| 821 RegX8632::getEncodedXmm(SrcVar->getRegNum()); | |
| 822 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); | |
| 823 } else { | |
| 824 X8632::Traits::Address SrcStackAddr = | |
| 825 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 826 ->stackVarToAsmOperand(SrcVar); | |
| 827 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); | |
| 828 } | |
| 829 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | |
| 830 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 831 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); | |
| 832 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { | |
| 833 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, | |
| 834 X8632::Traits::Address::ofConstPool(Asm, Imm)); | |
| 835 } else { | |
| 836 llvm_unreachable("Unexpected operand type"); | |
| 837 } | |
| 838 } | |
| 839 | |
| 840 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | |
| 841 SReg_t (*srcEnc)(int32_t)> | |
| 842 void emitIASCastRegOp( | |
| 843 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src, | |
| 844 const X8632::AssemblerX8632::CastEmitterRegOp<DReg_t, SReg_t> Emitter) { | |
| 845 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 846 assert(Dest->hasReg()); | |
| 847 DReg_t DestReg = destEnc(Dest->getRegNum()); | |
| 848 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | |
| 849 if (SrcVar->hasReg()) { | |
| 850 SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); | |
| 851 (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg); | |
| 852 } else { | |
| 853 X8632::Traits::Address SrcStackAddr = | |
| 854 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 855 ->stackVarToAsmOperand(SrcVar); | |
| 856 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr); | |
| 857 } | |
| 858 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | |
| 859 Mem->emitSegmentOverride(Asm); | |
| 860 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, Mem->toAsmAddress(Asm)); | |
| 861 } else { | |
| 862 llvm_unreachable("Unexpected operand type"); | |
| 863 } | |
| 864 } | |
| 865 | |
| 866 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | |
| 867 SReg_t (*srcEnc)(int32_t)> | |
| 868 void emitIASThreeOpImmOps( | |
| 869 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0, | |
| 870 const Operand *Src1, | |
| 871 const X8632::AssemblerX8632::ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) { | |
| 872 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 873 // This only handles Dest being a register, and Src1 being an immediate. | |
| 874 assert(Dest->hasReg()); | |
| 875 DReg_t DestReg = destEnc(Dest->getRegNum()); | |
| 876 X8632::Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue()); | |
| 877 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src0)) { | |
| 878 if (SrcVar->hasReg()) { | |
| 879 SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); | |
| 880 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm); | |
| 881 } else { | |
| 882 X8632::Traits::Address SrcStackAddr = | |
| 883 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 884 ->stackVarToAsmOperand(SrcVar); | |
| 885 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm); | |
| 886 } | |
| 887 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src0)) { | |
| 888 Mem->emitSegmentOverride(Asm); | |
| 889 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, Mem->toAsmAddress(Asm), | |
| 890 Imm); | |
| 891 } else { | |
| 892 llvm_unreachable("Unexpected operand type"); | |
| 893 } | |
| 894 } | |
| 895 | |
| 896 void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, | |
| 897 const Operand *Src, | |
| 898 const X8632::AssemblerX8632::XmmEmitterMovOps Emitter) { | |
| 899 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 900 if (Dest->hasReg()) { | |
| 901 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); | |
| 902 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | |
| 903 if (SrcVar->hasReg()) { | |
| 904 (Asm->*(Emitter.XmmXmm))(DestReg, | |
| 905 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | |
| 906 } else { | |
| 907 X8632::Traits::Address StackAddr( | |
| 908 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 909 ->stackVarToAsmOperand(SrcVar)); | |
| 910 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr); | |
| 911 } | |
| 912 } else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | |
| 913 assert(SrcMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 914 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm)); | |
| 915 } else { | |
| 916 llvm_unreachable("Unexpected operand type"); | |
| 917 } | |
| 918 } else { | |
| 919 X8632::Traits::Address StackAddr( | |
| 920 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 921 ->stackVarToAsmOperand(Dest)); | |
| 922 // Src must be a register in this case. | |
| 923 const auto SrcVar = llvm::cast<Variable>(Src); | |
| 924 assert(SrcVar->hasReg()); | |
| 925 (Asm->*(Emitter.AddrXmm))(StackAddr, | |
| 926 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | |
| 927 } | |
| 928 } | |
| 929 | |
| 930 // In-place ops | |
| 931 template <> const char *InstX8632Bswap::Opcode = "bswap"; | |
| 932 template <> const char *InstX8632Neg::Opcode = "neg"; | |
| 933 // Unary ops | |
| 934 template <> const char *InstX8632Bsf::Opcode = "bsf"; | |
| 935 template <> const char *InstX8632Bsr::Opcode = "bsr"; | |
| 936 template <> const char *InstX8632Lea::Opcode = "lea"; | |
| 937 template <> const char *InstX8632Movd::Opcode = "movd"; | |
| 938 template <> const char *InstX8632Movsx::Opcode = "movs"; | |
| 939 template <> const char *InstX8632Movzx::Opcode = "movz"; | |
| 940 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; | |
| 941 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; | |
| 942 // Mov-like ops | |
| 943 template <> const char *InstX8632Mov::Opcode = "mov"; | |
| 944 template <> const char *InstX8632Movp::Opcode = "movups"; | |
| 945 template <> const char *InstX8632Movq::Opcode = "movq"; | |
| 946 // Binary ops | |
| 947 template <> const char *InstX8632Add::Opcode = "add"; | |
| 948 template <> const char *InstX8632AddRMW::Opcode = "add"; | |
| 949 template <> const char *InstX8632Addps::Opcode = "addps"; | |
| 950 template <> const char *InstX8632Adc::Opcode = "adc"; | |
| 951 template <> const char *InstX8632AdcRMW::Opcode = "adc"; | |
| 952 template <> const char *InstX8632Addss::Opcode = "addss"; | |
| 953 template <> const char *InstX8632Padd::Opcode = "padd"; | |
| 954 template <> const char *InstX8632Sub::Opcode = "sub"; | |
| 955 template <> const char *InstX8632SubRMW::Opcode = "sub"; | |
| 956 template <> const char *InstX8632Subps::Opcode = "subps"; | |
| 957 template <> const char *InstX8632Subss::Opcode = "subss"; | |
| 958 template <> const char *InstX8632Sbb::Opcode = "sbb"; | |
| 959 template <> const char *InstX8632SbbRMW::Opcode = "sbb"; | |
| 960 template <> const char *InstX8632Psub::Opcode = "psub"; | |
| 961 template <> const char *InstX8632And::Opcode = "and"; | |
| 962 template <> const char *InstX8632AndRMW::Opcode = "and"; | |
| 963 template <> const char *InstX8632Pand::Opcode = "pand"; | |
| 964 template <> const char *InstX8632Pandn::Opcode = "pandn"; | |
| 965 template <> const char *InstX8632Or::Opcode = "or"; | |
| 966 template <> const char *InstX8632OrRMW::Opcode = "or"; | |
| 967 template <> const char *InstX8632Por::Opcode = "por"; | |
| 968 template <> const char *InstX8632Xor::Opcode = "xor"; | |
| 969 template <> const char *InstX8632XorRMW::Opcode = "xor"; | |
| 970 template <> const char *InstX8632Pxor::Opcode = "pxor"; | |
| 971 template <> const char *InstX8632Imul::Opcode = "imul"; | |
| 972 template <> const char *InstX8632Mulps::Opcode = "mulps"; | |
| 973 template <> const char *InstX8632Mulss::Opcode = "mulss"; | |
| 974 template <> const char *InstX8632Pmull::Opcode = "pmull"; | |
| 975 template <> const char *InstX8632Pmuludq::Opcode = "pmuludq"; | |
| 976 template <> const char *InstX8632Div::Opcode = "div"; | |
| 977 template <> const char *InstX8632Divps::Opcode = "divps"; | |
| 978 template <> const char *InstX8632Idiv::Opcode = "idiv"; | |
| 979 template <> const char *InstX8632Divss::Opcode = "divss"; | |
| 980 template <> const char *InstX8632Rol::Opcode = "rol"; | |
| 981 template <> const char *InstX8632Shl::Opcode = "shl"; | |
| 982 template <> const char *InstX8632Psll::Opcode = "psll"; | |
| 983 template <> const char *InstX8632Shr::Opcode = "shr"; | |
| 984 template <> const char *InstX8632Sar::Opcode = "sar"; | |
| 985 template <> const char *InstX8632Psra::Opcode = "psra"; | |
| 986 template <> const char *InstX8632Psrl::Opcode = "psrl"; | |
| 987 template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq"; | |
| 988 template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt"; | |
| 989 template <> const char *InstX8632MovssRegs::Opcode = "movss"; | |
| 990 // Ternary ops | |
| 991 template <> const char *InstX8632Insertps::Opcode = "insertps"; | |
| 992 template <> const char *InstX8632Shufps::Opcode = "shufps"; | |
| 993 template <> const char *InstX8632Pinsr::Opcode = "pinsr"; | |
| 994 template <> const char *InstX8632Blendvps::Opcode = "blendvps"; | |
| 995 template <> const char *InstX8632Pblendvb::Opcode = "pblendvb"; | |
| 996 // Three address ops | |
| 997 template <> const char *InstX8632Pextr::Opcode = "pextr"; | |
| 998 template <> const char *InstX8632Pshufd::Opcode = "pshufd"; | |
| 999 | |
| 1000 // Inplace GPR ops | |
| 1001 template <> | |
| 1002 const X8632::AssemblerX8632::GPREmitterOneOp InstX8632Bswap::Emitter = { | |
| 1003 &X8632::AssemblerX8632::bswap, nullptr /* only a reg form exists */ | |
| 1004 }; | |
| 1005 template <> | |
| 1006 const X8632::AssemblerX8632::GPREmitterOneOp InstX8632Neg::Emitter = { | |
| 1007 &X8632::AssemblerX8632::neg, &X8632::AssemblerX8632::neg}; | |
| 1008 | |
| 1009 // Unary GPR ops | |
| 1010 template <> | |
| 1011 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Bsf::Emitter = { | |
| 1012 &X8632::AssemblerX8632::bsf, &X8632::AssemblerX8632::bsf, nullptr}; | |
| 1013 template <> | |
| 1014 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Bsr::Emitter = { | |
| 1015 &X8632::AssemblerX8632::bsr, &X8632::AssemblerX8632::bsr, nullptr}; | |
| 1016 template <> | |
| 1017 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Lea::Emitter = { | |
| 1018 /* reg/reg and reg/imm are illegal */ nullptr, &X8632::AssemblerX8632::lea, | |
| 1019 nullptr}; | |
| 1020 template <> | |
| 1021 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Movsx::Emitter = { | |
| 1022 &X8632::AssemblerX8632::movsx, &X8632::AssemblerX8632::movsx, nullptr}; | |
| 1023 template <> | |
| 1024 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Movzx::Emitter = { | |
| 1025 &X8632::AssemblerX8632::movzx, &X8632::AssemblerX8632::movzx, nullptr}; | |
| 1026 | |
| 1027 // Unary XMM ops | |
| 1028 template <> | |
| 1029 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Sqrtss::Emitter = { | |
| 1030 &X8632::AssemblerX8632::sqrtss, &X8632::AssemblerX8632::sqrtss}; | |
| 1031 | |
| 1032 // Binary GPR ops | |
| 1033 template <> | |
| 1034 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Add::Emitter = { | |
| 1035 &X8632::AssemblerX8632::add, &X8632::AssemblerX8632::add, | |
| 1036 &X8632::AssemblerX8632::add}; | |
| 1037 template <> | |
| 1038 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AddRMW::Emitter = { | |
| 1039 &X8632::AssemblerX8632::add, &X8632::AssemblerX8632::add}; | |
| 1040 template <> | |
| 1041 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Adc::Emitter = { | |
| 1042 &X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc, | |
| 1043 &X8632::AssemblerX8632::adc}; | |
| 1044 template <> | |
| 1045 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AdcRMW::Emitter = { | |
| 1046 &X8632::AssemblerX8632::adc, &X8632::AssemblerX8632::adc}; | |
| 1047 template <> | |
| 1048 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632And::Emitter = { | |
| 1049 &X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And, | |
| 1050 &X8632::AssemblerX8632::And}; | |
| 1051 template <> | |
| 1052 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632AndRMW::Emitter = { | |
| 1053 &X8632::AssemblerX8632::And, &X8632::AssemblerX8632::And}; | |
| 1054 template <> | |
| 1055 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Or::Emitter = { | |
| 1056 &X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or, | |
| 1057 &X8632::AssemblerX8632::Or}; | |
| 1058 template <> | |
| 1059 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632OrRMW::Emitter = { | |
| 1060 &X8632::AssemblerX8632::Or, &X8632::AssemblerX8632::Or}; | |
| 1061 template <> | |
| 1062 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sbb::Emitter = { | |
| 1063 &X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb, | |
| 1064 &X8632::AssemblerX8632::sbb}; | |
| 1065 template <> | |
| 1066 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632SbbRMW::Emitter = { | |
| 1067 &X8632::AssemblerX8632::sbb, &X8632::AssemblerX8632::sbb}; | |
| 1068 template <> | |
| 1069 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Sub::Emitter = { | |
| 1070 &X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub, | |
| 1071 &X8632::AssemblerX8632::sub}; | |
| 1072 template <> | |
| 1073 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632SubRMW::Emitter = { | |
| 1074 &X8632::AssemblerX8632::sub, &X8632::AssemblerX8632::sub}; | |
| 1075 template <> | |
| 1076 const X8632::AssemblerX8632::GPREmitterRegOp InstX8632Xor::Emitter = { | |
| 1077 &X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor, | |
| 1078 &X8632::AssemblerX8632::Xor}; | |
| 1079 template <> | |
| 1080 const X8632::AssemblerX8632::GPREmitterAddrOp InstX8632XorRMW::Emitter = { | |
| 1081 &X8632::AssemblerX8632::Xor, &X8632::AssemblerX8632::Xor}; | |
| 1082 | |
| 1083 // Binary Shift GPR ops | |
| 1084 template <> | |
| 1085 const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Rol::Emitter = { | |
| 1086 &X8632::AssemblerX8632::rol, &X8632::AssemblerX8632::rol}; | |
| 1087 template <> | |
| 1088 const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Sar::Emitter = { | |
| 1089 &X8632::AssemblerX8632::sar, &X8632::AssemblerX8632::sar}; | |
| 1090 template <> | |
| 1091 const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Shl::Emitter = { | |
| 1092 &X8632::AssemblerX8632::shl, &X8632::AssemblerX8632::shl}; | |
| 1093 template <> | |
| 1094 const X8632::AssemblerX8632::GPREmitterShiftOp InstX8632Shr::Emitter = { | |
| 1095 &X8632::AssemblerX8632::shr, &X8632::AssemblerX8632::shr}; | |
| 1096 | |
| 1097 // Binary XMM ops | |
| 1098 template <> | |
| 1099 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Addss::Emitter = { | |
| 1100 &X8632::AssemblerX8632::addss, &X8632::AssemblerX8632::addss}; | |
| 1101 template <> | |
| 1102 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Addps::Emitter = { | |
| 1103 &X8632::AssemblerX8632::addps, &X8632::AssemblerX8632::addps}; | |
| 1104 template <> | |
| 1105 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Divss::Emitter = { | |
| 1106 &X8632::AssemblerX8632::divss, &X8632::AssemblerX8632::divss}; | |
| 1107 template <> | |
| 1108 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Divps::Emitter = { | |
| 1109 &X8632::AssemblerX8632::divps, &X8632::AssemblerX8632::divps}; | |
| 1110 template <> | |
| 1111 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Mulss::Emitter = { | |
| 1112 &X8632::AssemblerX8632::mulss, &X8632::AssemblerX8632::mulss}; | |
| 1113 template <> | |
| 1114 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Mulps::Emitter = { | |
| 1115 &X8632::AssemblerX8632::mulps, &X8632::AssemblerX8632::mulps}; | |
| 1116 template <> | |
| 1117 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Padd::Emitter = { | |
| 1118 &X8632::AssemblerX8632::padd, &X8632::AssemblerX8632::padd}; | |
| 1119 template <> | |
| 1120 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pand::Emitter = { | |
| 1121 &X8632::AssemblerX8632::pand, &X8632::AssemblerX8632::pand}; | |
| 1122 template <> | |
| 1123 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pandn::Emitter = { | |
| 1124 &X8632::AssemblerX8632::pandn, &X8632::AssemblerX8632::pandn}; | |
| 1125 template <> | |
| 1126 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pcmpeq::Emitter = { | |
| 1127 &X8632::AssemblerX8632::pcmpeq, &X8632::AssemblerX8632::pcmpeq}; | |
| 1128 template <> | |
| 1129 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pcmpgt::Emitter = { | |
| 1130 &X8632::AssemblerX8632::pcmpgt, &X8632::AssemblerX8632::pcmpgt}; | |
| 1131 template <> | |
| 1132 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pmull::Emitter = { | |
| 1133 &X8632::AssemblerX8632::pmull, &X8632::AssemblerX8632::pmull}; | |
| 1134 template <> | |
| 1135 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pmuludq::Emitter = { | |
| 1136 &X8632::AssemblerX8632::pmuludq, &X8632::AssemblerX8632::pmuludq}; | |
| 1137 template <> | |
| 1138 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Por::Emitter = { | |
| 1139 &X8632::AssemblerX8632::por, &X8632::AssemblerX8632::por}; | |
| 1140 template <> | |
| 1141 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Psub::Emitter = { | |
| 1142 &X8632::AssemblerX8632::psub, &X8632::AssemblerX8632::psub}; | |
| 1143 template <> | |
| 1144 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Pxor::Emitter = { | |
| 1145 &X8632::AssemblerX8632::pxor, &X8632::AssemblerX8632::pxor}; | |
| 1146 template <> | |
| 1147 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Subss::Emitter = { | |
| 1148 &X8632::AssemblerX8632::subss, &X8632::AssemblerX8632::subss}; | |
| 1149 template <> | |
| 1150 const X8632::AssemblerX8632::XmmEmitterRegOp InstX8632Subps::Emitter = { | |
| 1151 &X8632::AssemblerX8632::subps, &X8632::AssemblerX8632::subps}; | |
| 1152 | |
| 1153 // Binary XMM Shift ops | |
| 1154 template <> | |
| 1155 const X8632::AssemblerX8632::XmmEmitterShiftOp InstX8632Psll::Emitter = { | |
| 1156 &X8632::AssemblerX8632::psll, &X8632::AssemblerX8632::psll, | |
| 1157 &X8632::AssemblerX8632::psll}; | |
| 1158 template <> | |
| 1159 const X8632::AssemblerX8632::XmmEmitterShiftOp InstX8632Psra::Emitter = { | |
| 1160 &X8632::AssemblerX8632::psra, &X8632::AssemblerX8632::psra, | |
| 1161 &X8632::AssemblerX8632::psra}; | |
| 1162 template <> | |
| 1163 const X8632::AssemblerX8632::XmmEmitterShiftOp InstX8632Psrl::Emitter = { | |
| 1164 &X8632::AssemblerX8632::psrl, &X8632::AssemblerX8632::psrl, | |
| 1165 &X8632::AssemblerX8632::psrl}; | |
| 1166 | |
| 1167 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const { | |
| 1168 if (!BuildDefs::dump()) | |
| 1169 return; | |
| 1170 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1171 assert(getSrcSize() == 1); | |
| 1172 Type Ty = getSrc(0)->getType(); | |
| 1173 assert(isScalarFloatingType(Ty)); | |
| 1174 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t"; | |
| 1175 getSrc(0)->emit(Func); | |
| 1176 Str << ", "; | |
| 1177 getDest()->emit(Func); | |
| 1178 } | |
| 1179 | |
| 1180 template <> void InstX8632Addss::emit(const Cfg *Func) const { | |
| 1181 if (!BuildDefs::dump()) | |
| 1182 return; | |
| 1183 char buf[30]; | |
| 1184 snprintf(buf, llvm::array_lengthof(buf), "add%s", | |
| 1185 TypeX8632Attributes[getDest()->getType()].SdSsString); | |
| 1186 emitTwoAddress(buf, this, Func); | |
| 1187 } | |
| 1188 | |
| 1189 template <> void InstX8632Padd::emit(const Cfg *Func) const { | |
| 1190 if (!BuildDefs::dump()) | |
| 1191 return; | |
| 1192 char buf[30]; | |
| 1193 snprintf(buf, llvm::array_lengthof(buf), "padd%s", | |
| 1194 TypeX8632Attributes[getDest()->getType()].PackString); | |
| 1195 emitTwoAddress(buf, this, Func); | |
| 1196 } | |
| 1197 | |
| 1198 template <> void InstX8632Pmull::emit(const Cfg *Func) const { | |
| 1199 if (!BuildDefs::dump()) | |
| 1200 return; | |
| 1201 char buf[30]; | |
| 1202 bool TypesAreValid = getDest()->getType() == IceType_v4i32 || | |
| 1203 getDest()->getType() == IceType_v8i16; | |
| 1204 bool InstructionSetIsValid = | |
| 1205 getDest()->getType() == IceType_v8i16 || | |
| 1206 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 1207 X8632::Traits::SSE4_1; | |
| 1208 (void)TypesAreValid; | |
| 1209 (void)InstructionSetIsValid; | |
| 1210 assert(TypesAreValid); | |
| 1211 assert(InstructionSetIsValid); | |
| 1212 snprintf(buf, llvm::array_lengthof(buf), "pmull%s", | |
| 1213 TypeX8632Attributes[getDest()->getType()].PackString); | |
| 1214 emitTwoAddress(buf, this, Func); | |
| 1215 } | |
| 1216 | |
| 1217 template <> void InstX8632Pmull::emitIAS(const Cfg *Func) const { | |
| 1218 Type Ty = getDest()->getType(); | |
| 1219 bool TypesAreValid = Ty == IceType_v4i32 || Ty == IceType_v8i16; | |
| 1220 bool InstructionSetIsValid = | |
| 1221 Ty == IceType_v8i16 || | |
| 1222 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 1223 X8632::Traits::SSE4_1; | |
| 1224 (void)TypesAreValid; | |
| 1225 (void)InstructionSetIsValid; | |
| 1226 assert(TypesAreValid); | |
| 1227 assert(InstructionSetIsValid); | |
| 1228 assert(getSrcSize() == 2); | |
| 1229 Type ElementTy = typeElementType(Ty); | |
| 1230 emitIASRegOpTyXMM(Func, ElementTy, getDest(), getSrc(1), Emitter); | |
| 1231 } | |
| 1232 | |
| 1233 template <> void InstX8632Subss::emit(const Cfg *Func) const { | |
| 1234 if (!BuildDefs::dump()) | |
| 1235 return; | |
| 1236 char buf[30]; | |
| 1237 snprintf(buf, llvm::array_lengthof(buf), "sub%s", | |
| 1238 TypeX8632Attributes[getDest()->getType()].SdSsString); | |
| 1239 emitTwoAddress(buf, this, Func); | |
| 1240 } | |
| 1241 | |
| 1242 template <> void InstX8632Psub::emit(const Cfg *Func) const { | |
| 1243 if (!BuildDefs::dump()) | |
| 1244 return; | |
| 1245 char buf[30]; | |
| 1246 snprintf(buf, llvm::array_lengthof(buf), "psub%s", | |
| 1247 TypeX8632Attributes[getDest()->getType()].PackString); | |
| 1248 emitTwoAddress(buf, this, Func); | |
| 1249 } | |
| 1250 | |
| 1251 template <> void InstX8632Mulss::emit(const Cfg *Func) const { | |
| 1252 if (!BuildDefs::dump()) | |
| 1253 return; | |
| 1254 char buf[30]; | |
| 1255 snprintf(buf, llvm::array_lengthof(buf), "mul%s", | |
| 1256 TypeX8632Attributes[getDest()->getType()].SdSsString); | |
| 1257 emitTwoAddress(buf, this, Func); | |
| 1258 } | |
| 1259 | |
| 1260 template <> void InstX8632Pmuludq::emit(const Cfg *Func) const { | |
| 1261 if (!BuildDefs::dump()) | |
| 1262 return; | |
| 1263 assert(getSrc(0)->getType() == IceType_v4i32 && | |
| 1264 getSrc(1)->getType() == IceType_v4i32); | |
| 1265 emitTwoAddress(Opcode, this, Func); | |
| 1266 } | |
| 1267 | |
| 1268 template <> void InstX8632Divss::emit(const Cfg *Func) const { | |
| 1269 if (!BuildDefs::dump()) | |
| 1270 return; | |
| 1271 char buf[30]; | |
| 1272 snprintf(buf, llvm::array_lengthof(buf), "div%s", | |
| 1273 TypeX8632Attributes[getDest()->getType()].SdSsString); | |
| 1274 emitTwoAddress(buf, this, Func); | |
| 1275 } | |
| 1276 | |
| 1277 template <> void InstX8632Div::emit(const Cfg *Func) const { | |
| 1278 if (!BuildDefs::dump()) | |
| 1279 return; | |
| 1280 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1281 assert(getSrcSize() == 3); | |
| 1282 Operand *Src1 = getSrc(1); | |
| 1283 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; | |
| 1284 Src1->emit(Func); | |
| 1285 } | |
| 1286 | |
| 1287 template <> void InstX8632Div::emitIAS(const Cfg *Func) const { | |
| 1288 assert(getSrcSize() == 3); | |
| 1289 const Operand *Src = getSrc(1); | |
| 1290 Type Ty = Src->getType(); | |
| 1291 const static X8632::AssemblerX8632::GPREmitterOneOp Emitter = { | |
| 1292 &X8632::AssemblerX8632::div, &X8632::AssemblerX8632::div}; | |
| 1293 emitIASOpTyGPR(Func, Ty, Src, Emitter); | |
| 1294 } | |
| 1295 | |
| 1296 template <> void InstX8632Idiv::emit(const Cfg *Func) const { | |
| 1297 if (!BuildDefs::dump()) | |
| 1298 return; | |
| 1299 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1300 assert(getSrcSize() == 3); | |
| 1301 Operand *Src1 = getSrc(1); | |
| 1302 Str << "\t" << Opcode << getWidthString(Src1->getType()) << "\t"; | |
| 1303 Src1->emit(Func); | |
| 1304 } | |
| 1305 | |
| 1306 template <> void InstX8632Idiv::emitIAS(const Cfg *Func) const { | |
| 1307 assert(getSrcSize() == 3); | |
| 1308 const Operand *Src = getSrc(1); | |
| 1309 Type Ty = Src->getType(); | |
| 1310 const static X8632::AssemblerX8632::GPREmitterOneOp Emitter = { | |
| 1311 &X8632::AssemblerX8632::idiv, &X8632::AssemblerX8632::idiv}; | |
| 1312 emitIASOpTyGPR(Func, Ty, Src, Emitter); | |
| 1313 } | |
| 1314 | |
| 1315 namespace { | |
| 1316 | |
| 1317 // pblendvb and blendvps take xmm0 as a final implicit argument. | |
| 1318 void emitVariableBlendInst(const char *Opcode, const Inst *Inst, | |
| 1319 const Cfg *Func) { | |
| 1320 if (!BuildDefs::dump()) | |
| 1321 return; | |
| 1322 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1323 assert(Inst->getSrcSize() == 3); | |
| 1324 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == | |
| 1325 RegX8632::Reg_xmm0); | |
| 1326 Str << "\t" << Opcode << "\t"; | |
| 1327 Inst->getSrc(1)->emit(Func); | |
| 1328 Str << ", "; | |
| 1329 Inst->getDest()->emit(Func); | |
| 1330 } | |
| 1331 | |
| 1332 void emitIASVariableBlendInst( | |
| 1333 const Inst *Inst, const Cfg *Func, | |
| 1334 const X8632::AssemblerX8632::XmmEmitterRegOp &Emitter) { | |
| 1335 assert(Inst->getSrcSize() == 3); | |
| 1336 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() == | |
| 1337 RegX8632::Reg_xmm0); | |
| 1338 const Variable *Dest = Inst->getDest(); | |
| 1339 const Operand *Src = Inst->getSrc(1); | |
| 1340 emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter); | |
| 1341 } | |
| 1342 | |
| 1343 } // end anonymous namespace | |
| 1344 | |
| 1345 template <> void InstX8632Blendvps::emit(const Cfg *Func) const { | |
| 1346 if (!BuildDefs::dump()) | |
| 1347 return; | |
| 1348 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 1349 X8632::Traits::SSE4_1); | |
| 1350 emitVariableBlendInst(Opcode, this, Func); | |
| 1351 } | |
| 1352 | |
| 1353 template <> void InstX8632Blendvps::emitIAS(const Cfg *Func) const { | |
| 1354 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 1355 X8632::Traits::SSE4_1); | |
| 1356 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { | |
| 1357 &X8632::AssemblerX8632::blendvps, &X8632::AssemblerX8632::blendvps}; | |
| 1358 emitIASVariableBlendInst(this, Func, Emitter); | |
| 1359 } | |
| 1360 | |
| 1361 template <> void InstX8632Pblendvb::emit(const Cfg *Func) const { | |
| 1362 if (!BuildDefs::dump()) | |
| 1363 return; | |
| 1364 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 1365 X8632::Traits::SSE4_1); | |
| 1366 emitVariableBlendInst(Opcode, this, Func); | |
| 1367 } | |
| 1368 | |
| 1369 template <> void InstX8632Pblendvb::emitIAS(const Cfg *Func) const { | |
| 1370 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 1371 X8632::Traits::SSE4_1); | |
| 1372 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { | |
| 1373 &X8632::AssemblerX8632::pblendvb, &X8632::AssemblerX8632::pblendvb}; | |
| 1374 emitIASVariableBlendInst(this, Func, Emitter); | |
| 1375 } | |
| 1376 | |
| 1377 template <> void InstX8632Imul::emit(const Cfg *Func) const { | |
| 1378 if (!BuildDefs::dump()) | |
| 1379 return; | |
| 1380 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1381 assert(getSrcSize() == 2); | |
| 1382 Variable *Dest = getDest(); | |
| 1383 if (isByteSizedArithType(Dest->getType())) { | |
| 1384 // The 8-bit version of imul only allows the form "imul r/m8". | |
| 1385 const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0)); | |
| 1386 (void)Src0Var; | |
| 1387 assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax); | |
| 1388 Str << "\timulb\t"; | |
| 1389 getSrc(1)->emit(Func); | |
| 1390 } else if (llvm::isa<Constant>(getSrc(1))) { | |
| 1391 Str << "\timul" << getWidthString(Dest->getType()) << "\t"; | |
| 1392 getSrc(1)->emit(Func); | |
| 1393 Str << ", "; | |
| 1394 getSrc(0)->emit(Func); | |
| 1395 Str << ", "; | |
| 1396 Dest->emit(Func); | |
| 1397 } else { | |
| 1398 emitTwoAddress("imul", this, Func); | |
| 1399 } | |
| 1400 } | |
| 1401 | |
| 1402 template <> void InstX8632Imul::emitIAS(const Cfg *Func) const { | |
| 1403 assert(getSrcSize() == 2); | |
| 1404 const Variable *Var = getDest(); | |
| 1405 Type Ty = Var->getType(); | |
| 1406 const Operand *Src = getSrc(1); | |
| 1407 if (isByteSizedArithType(Ty)) { | |
| 1408 // The 8-bit version of imul only allows the form "imul r/m8". | |
| 1409 const auto Src0Var = llvm::dyn_cast<Variable>(getSrc(0)); | |
| 1410 (void)Src0Var; | |
| 1411 assert(Src0Var && Src0Var->getRegNum() == RegX8632::Reg_eax); | |
| 1412 const X8632::AssemblerX8632::GPREmitterOneOp Emitter = { | |
| 1413 &X8632::AssemblerX8632::imul, &X8632::AssemblerX8632::imul}; | |
| 1414 emitIASOpTyGPR(Func, Ty, getSrc(1), Emitter); | |
| 1415 } else { | |
| 1416 // We only use imul as a two-address instruction even though | |
| 1417 // there is a 3 operand version when one of the operands is a constant. | |
| 1418 assert(Var == getSrc(0)); | |
| 1419 const X8632::AssemblerX8632::GPREmitterRegOp Emitter = { | |
| 1420 &X8632::AssemblerX8632::imul, &X8632::AssemblerX8632::imul, | |
| 1421 &X8632::AssemblerX8632::imul}; | |
| 1422 emitIASRegOpTyGPR(Func, Ty, Var, Src, Emitter); | |
| 1423 } | |
| 1424 } | |
| 1425 | |
| 1426 template <> void InstX8632Insertps::emitIAS(const Cfg *Func) const { | |
| 1427 assert(getSrcSize() == 3); | |
| 1428 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 1429 X8632::Traits::SSE4_1); | |
| 1430 const Variable *Dest = getDest(); | |
| 1431 assert(Dest == getSrc(0)); | |
| 1432 Type Ty = Dest->getType(); | |
| 1433 static const X8632::AssemblerX8632::ThreeOpImmEmitter< | |
| 1434 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { | |
| 1435 &X8632::AssemblerX8632::insertps, &X8632::AssemblerX8632::insertps}; | |
| 1436 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, | |
| 1437 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( | |
| 1438 Func, Ty, Dest, getSrc(1), getSrc(2), Emitter); | |
| 1439 } | |
| 1440 | |
| 1441 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const { | |
| 1442 if (!BuildDefs::dump()) | |
| 1443 return; | |
| 1444 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1445 assert(getSrcSize() == 1); | |
| 1446 Operand *Src0 = getSrc(0); | |
| 1447 assert(llvm::isa<Variable>(Src0)); | |
| 1448 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); | |
| 1449 switch (Src0->getType()) { | |
| 1450 default: | |
| 1451 llvm_unreachable("unexpected source type!"); | |
| 1452 break; | |
| 1453 case IceType_i8: | |
| 1454 assert(getDest()->getRegNum() == RegX8632::Reg_eax); | |
| 1455 Str << "\tcbtw"; | |
| 1456 break; | |
| 1457 case IceType_i16: | |
| 1458 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | |
| 1459 Str << "\tcwtd"; | |
| 1460 break; | |
| 1461 case IceType_i32: | |
| 1462 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | |
| 1463 Str << "\tcltd"; | |
| 1464 break; | |
| 1465 } | |
| 1466 } | |
| 1467 | |
| 1468 template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const { | |
| 1469 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 1470 assert(getSrcSize() == 1); | |
| 1471 Operand *Src0 = getSrc(0); | |
| 1472 assert(llvm::isa<Variable>(Src0)); | |
| 1473 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); | |
| 1474 switch (Src0->getType()) { | |
| 1475 default: | |
| 1476 llvm_unreachable("unexpected source type!"); | |
| 1477 break; | |
| 1478 case IceType_i8: | |
| 1479 assert(getDest()->getRegNum() == RegX8632::Reg_eax); | |
| 1480 Asm->cbw(); | |
| 1481 break; | |
| 1482 case IceType_i16: | |
| 1483 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | |
| 1484 Asm->cwd(); | |
| 1485 break; | |
| 1486 case IceType_i32: | |
| 1487 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | |
| 1488 Asm->cdq(); | |
| 1489 break; | |
| 1490 } | |
| 1491 } | |
| 1492 | |
| 1493 void InstX8632Mul::emit(const Cfg *Func) const { | |
| 1494 if (!BuildDefs::dump()) | |
| 1495 return; | |
| 1496 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1497 assert(getSrcSize() == 2); | |
| 1498 assert(llvm::isa<Variable>(getSrc(0))); | |
| 1499 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); | |
| 1500 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? | |
| 1501 Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; | |
| 1502 getSrc(1)->emit(Func); | |
| 1503 } | |
| 1504 | |
| 1505 void InstX8632Mul::emitIAS(const Cfg *Func) const { | |
| 1506 assert(getSrcSize() == 2); | |
| 1507 assert(llvm::isa<Variable>(getSrc(0))); | |
| 1508 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); | |
| 1509 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? | |
| 1510 const Operand *Src = getSrc(1); | |
| 1511 Type Ty = Src->getType(); | |
| 1512 const static X8632::AssemblerX8632::GPREmitterOneOp Emitter = { | |
| 1513 &X8632::AssemblerX8632::mul, &X8632::AssemblerX8632::mul}; | |
| 1514 emitIASOpTyGPR(Func, Ty, Src, Emitter); | |
| 1515 } | |
| 1516 | |
| 1517 void InstX8632Mul::dump(const Cfg *Func) const { | |
| 1518 if (!BuildDefs::dump()) | |
| 1519 return; | |
| 1520 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1521 dumpDest(Func); | |
| 1522 Str << " = mul." << getDest()->getType() << " "; | |
| 1523 dumpSources(Func); | |
| 1524 } | |
| 1525 | |
| 1526 void InstX8632Shld::emit(const Cfg *Func) const { | |
| 1527 if (!BuildDefs::dump()) | |
| 1528 return; | |
| 1529 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1530 Variable *Dest = getDest(); | |
| 1531 assert(getSrcSize() == 3); | |
| 1532 assert(Dest == getSrc(0)); | |
| 1533 Str << "\tshld" << getWidthString(Dest->getType()) << "\t"; | |
| 1534 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | |
| 1535 (void)ShiftReg; | |
| 1536 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | |
| 1537 Str << "%cl"; | |
| 1538 } else { | |
| 1539 getSrc(2)->emit(Func); | |
| 1540 } | |
| 1541 Str << ", "; | |
| 1542 getSrc(1)->emit(Func); | |
| 1543 Str << ", "; | |
| 1544 Dest->emit(Func); | |
| 1545 } | |
| 1546 | |
| 1547 void InstX8632Shld::emitIAS(const Cfg *Func) const { | |
| 1548 assert(getSrcSize() == 3); | |
| 1549 assert(getDest() == getSrc(0)); | |
| 1550 const Variable *Dest = getDest(); | |
| 1551 const Operand *Src1 = getSrc(1); | |
| 1552 const Operand *Src2 = getSrc(2); | |
| 1553 static const X8632::AssemblerX8632::GPREmitterShiftD Emitter = { | |
| 1554 &X8632::AssemblerX8632::shld, &X8632::AssemblerX8632::shld}; | |
| 1555 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); | |
| 1556 } | |
| 1557 | |
| 1558 void InstX8632Shld::dump(const Cfg *Func) const { | |
| 1559 if (!BuildDefs::dump()) | |
| 1560 return; | |
| 1561 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1562 dumpDest(Func); | |
| 1563 Str << " = shld." << getDest()->getType() << " "; | |
| 1564 dumpSources(Func); | |
| 1565 } | |
| 1566 | |
| 1567 void InstX8632Shrd::emit(const Cfg *Func) const { | |
| 1568 if (!BuildDefs::dump()) | |
| 1569 return; | |
| 1570 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1571 Variable *Dest = getDest(); | |
| 1572 assert(getSrcSize() == 3); | |
| 1573 assert(Dest == getSrc(0)); | |
| 1574 Str << "\tshrd" << getWidthString(Dest->getType()) << "\t"; | |
| 1575 if (const auto ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) { | |
| 1576 (void)ShiftReg; | |
| 1577 assert(ShiftReg->getRegNum() == RegX8632::Reg_ecx); | |
| 1578 Str << "%cl"; | |
| 1579 } else { | |
| 1580 getSrc(2)->emit(Func); | |
| 1581 } | |
| 1582 Str << ", "; | |
| 1583 getSrc(1)->emit(Func); | |
| 1584 Str << ", "; | |
| 1585 Dest->emit(Func); | |
| 1586 } | |
| 1587 | |
| 1588 void InstX8632Shrd::emitIAS(const Cfg *Func) const { | |
| 1589 assert(getSrcSize() == 3); | |
| 1590 assert(getDest() == getSrc(0)); | |
| 1591 const Variable *Dest = getDest(); | |
| 1592 const Operand *Src1 = getSrc(1); | |
| 1593 const Operand *Src2 = getSrc(2); | |
| 1594 static const X8632::AssemblerX8632::GPREmitterShiftD Emitter = { | |
| 1595 &X8632::AssemblerX8632::shrd, &X8632::AssemblerX8632::shrd}; | |
| 1596 emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter); | |
| 1597 } | |
| 1598 | |
| 1599 void InstX8632Shrd::dump(const Cfg *Func) const { | |
| 1600 if (!BuildDefs::dump()) | |
| 1601 return; | |
| 1602 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1603 dumpDest(Func); | |
| 1604 Str << " = shrd." << getDest()->getType() << " "; | |
| 1605 dumpSources(Func); | |
| 1606 } | |
| 1607 | |
| 1608 void InstX8632Cmov::emit(const Cfg *Func) const { | |
| 1609 if (!BuildDefs::dump()) | |
| 1610 return; | |
| 1611 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1612 Variable *Dest = getDest(); | |
| 1613 Str << "\t"; | |
| 1614 assert(Condition != X8632::Traits::Cond::Br_None); | |
| 1615 assert(getDest()->hasReg()); | |
| 1616 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString | |
| 1617 << getWidthString(Dest->getType()) << "\t"; | |
| 1618 getSrc(1)->emit(Func); | |
| 1619 Str << ", "; | |
| 1620 Dest->emit(Func); | |
| 1621 } | |
| 1622 | |
| 1623 void InstX8632Cmov::emitIAS(const Cfg *Func) const { | |
| 1624 assert(Condition != X8632::Traits::Cond::Br_None); | |
| 1625 assert(getDest()->hasReg()); | |
| 1626 assert(getSrcSize() == 2); | |
| 1627 Operand *Src = getSrc(1); | |
| 1628 Type SrcTy = Src->getType(); | |
| 1629 assert(SrcTy == IceType_i16 || SrcTy == IceType_i32); | |
| 1630 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 1631 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { | |
| 1632 if (SrcVar->hasReg()) { | |
| 1633 Asm->cmov(SrcTy, Condition, | |
| 1634 RegX8632::getEncodedGPR(getDest()->getRegNum()), | |
| 1635 RegX8632::getEncodedGPR(SrcVar->getRegNum())); | |
| 1636 } else { | |
| 1637 Asm->cmov(SrcTy, Condition, | |
| 1638 RegX8632::getEncodedGPR(getDest()->getRegNum()), | |
| 1639 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 1640 ->stackVarToAsmOperand(SrcVar)); | |
| 1641 } | |
| 1642 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | |
| 1643 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 1644 Asm->cmov(SrcTy, Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()), | |
| 1645 Mem->toAsmAddress(Asm)); | |
| 1646 } else { | |
| 1647 llvm_unreachable("Unexpected operand type"); | |
| 1648 } | |
| 1649 } | |
| 1650 | |
| 1651 void InstX8632Cmov::dump(const Cfg *Func) const { | |
| 1652 if (!BuildDefs::dump()) | |
| 1653 return; | |
| 1654 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1655 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; | |
| 1656 Str << getDest()->getType() << " "; | |
| 1657 dumpDest(Func); | |
| 1658 Str << ", "; | |
| 1659 dumpSources(Func); | |
| 1660 } | |
| 1661 | |
| 1662 void InstX8632Cmpps::emit(const Cfg *Func) const { | |
| 1663 if (!BuildDefs::dump()) | |
| 1664 return; | |
| 1665 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1666 assert(getSrcSize() == 2); | |
| 1667 assert(Condition < X8632::Traits::Cond::Cmpps_Invalid); | |
| 1668 Str << "\t"; | |
| 1669 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" | |
| 1670 << "\t"; | |
| 1671 getSrc(1)->emit(Func); | |
| 1672 Str << ", "; | |
| 1673 getDest()->emit(Func); | |
| 1674 } | |
| 1675 | |
| 1676 void InstX8632Cmpps::emitIAS(const Cfg *Func) const { | |
| 1677 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 1678 assert(getSrcSize() == 2); | |
| 1679 assert(Condition < X8632::Traits::Cond::Cmpps_Invalid); | |
| 1680 // Assuming there isn't any load folding for cmpps, and vector constants | |
| 1681 // are not allowed in PNaCl. | |
| 1682 assert(llvm::isa<Variable>(getSrc(1))); | |
| 1683 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); | |
| 1684 if (SrcVar->hasReg()) { | |
| 1685 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), | |
| 1686 RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition); | |
| 1687 } else { | |
| 1688 X8632::Traits::Address SrcStackAddr = | |
| 1689 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 1690 ->stackVarToAsmOperand(SrcVar); | |
| 1691 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr, | |
| 1692 Condition); | |
| 1693 } | |
| 1694 } | |
| 1695 | |
| 1696 void InstX8632Cmpps::dump(const Cfg *Func) const { | |
| 1697 if (!BuildDefs::dump()) | |
| 1698 return; | |
| 1699 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1700 assert(Condition < X8632::Traits::Cond::Cmpps_Invalid); | |
| 1701 dumpDest(Func); | |
| 1702 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" | |
| 1703 << "\t"; | |
| 1704 dumpSources(Func); | |
| 1705 } | |
| 1706 | |
| 1707 void InstX8632Cmpxchg::emit(const Cfg *Func) const { | |
| 1708 if (!BuildDefs::dump()) | |
| 1709 return; | |
| 1710 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1711 assert(getSrcSize() == 3); | |
| 1712 if (Locked) { | |
| 1713 Str << "\tlock"; | |
| 1714 } | |
| 1715 Str << "\tcmpxchg" << getWidthString(getSrc(0)->getType()) << "\t"; | |
| 1716 getSrc(2)->emit(Func); | |
| 1717 Str << ", "; | |
| 1718 getSrc(0)->emit(Func); | |
| 1719 } | |
| 1720 | |
| 1721 void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { | |
| 1722 assert(getSrcSize() == 3); | |
| 1723 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 1724 Type Ty = getSrc(0)->getType(); | |
| 1725 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | |
| 1726 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 1727 const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm); | |
| 1728 const auto VarReg = llvm::cast<Variable>(getSrc(2)); | |
| 1729 assert(VarReg->hasReg()); | |
| 1730 const RegX8632::GPRRegister Reg = | |
| 1731 RegX8632::getEncodedGPR(VarReg->getRegNum()); | |
| 1732 Asm->cmpxchg(Ty, Addr, Reg, Locked); | |
| 1733 } | |
| 1734 | |
| 1735 void InstX8632Cmpxchg::dump(const Cfg *Func) const { | |
| 1736 if (!BuildDefs::dump()) | |
| 1737 return; | |
| 1738 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1739 if (Locked) { | |
| 1740 Str << "lock "; | |
| 1741 } | |
| 1742 Str << "cmpxchg." << getSrc(0)->getType() << " "; | |
| 1743 dumpSources(Func); | |
| 1744 } | |
| 1745 | |
| 1746 void InstX8632Cmpxchg8b::emit(const Cfg *Func) const { | |
| 1747 if (!BuildDefs::dump()) | |
| 1748 return; | |
| 1749 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1750 assert(getSrcSize() == 5); | |
| 1751 if (Locked) { | |
| 1752 Str << "\tlock"; | |
| 1753 } | |
| 1754 Str << "\tcmpxchg8b\t"; | |
| 1755 getSrc(0)->emit(Func); | |
| 1756 } | |
| 1757 | |
| 1758 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { | |
| 1759 assert(getSrcSize() == 5); | |
| 1760 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 1761 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | |
| 1762 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 1763 const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm); | |
| 1764 Asm->cmpxchg8b(Addr, Locked); | |
| 1765 } | |
| 1766 | |
| 1767 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const { | |
| 1768 if (!BuildDefs::dump()) | |
| 1769 return; | |
| 1770 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1771 if (Locked) { | |
| 1772 Str << "lock "; | |
| 1773 } | |
| 1774 Str << "cmpxchg8b "; | |
| 1775 dumpSources(Func); | |
| 1776 } | |
| 1777 | |
| 1778 void InstX8632Cvt::emit(const Cfg *Func) const { | |
| 1779 if (!BuildDefs::dump()) | |
| 1780 return; | |
| 1781 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1782 assert(getSrcSize() == 1); | |
| 1783 Str << "\tcvt"; | |
| 1784 if (isTruncating()) | |
| 1785 Str << "t"; | |
| 1786 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" | |
| 1787 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t"; | |
| 1788 getSrc(0)->emit(Func); | |
| 1789 Str << ", "; | |
| 1790 getDest()->emit(Func); | |
| 1791 } | |
| 1792 | |
| 1793 void InstX8632Cvt::emitIAS(const Cfg *Func) const { | |
| 1794 assert(getSrcSize() == 1); | |
| 1795 const Variable *Dest = getDest(); | |
| 1796 const Operand *Src = getSrc(0); | |
| 1797 Type DestTy = Dest->getType(); | |
| 1798 Type SrcTy = Src->getType(); | |
| 1799 switch (Variant) { | |
| 1800 case Si2ss: { | |
| 1801 assert(isScalarIntegerType(SrcTy)); | |
| 1802 assert(typeWidthInBytes(SrcTy) <= 4); | |
| 1803 assert(isScalarFloatingType(DestTy)); | |
| 1804 static const X8632::AssemblerX8632::CastEmitterRegOp< | |
| 1805 RegX8632::XmmRegister, RegX8632::GPRRegister> Emitter = { | |
| 1806 &X8632::AssemblerX8632::cvtsi2ss, &X8632::AssemblerX8632::cvtsi2ss}; | |
| 1807 emitIASCastRegOp<RegX8632::XmmRegister, RegX8632::GPRRegister, | |
| 1808 RegX8632::getEncodedXmm, RegX8632::getEncodedGPR>( | |
| 1809 Func, DestTy, Dest, Src, Emitter); | |
| 1810 return; | |
| 1811 } | |
| 1812 case Tss2si: { | |
| 1813 assert(isScalarFloatingType(SrcTy)); | |
| 1814 assert(isScalarIntegerType(DestTy)); | |
| 1815 assert(typeWidthInBytes(DestTy) <= 4); | |
| 1816 static const X8632::AssemblerX8632::CastEmitterRegOp< | |
| 1817 RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = { | |
| 1818 &X8632::AssemblerX8632::cvttss2si, &X8632::AssemblerX8632::cvttss2si}; | |
| 1819 emitIASCastRegOp<RegX8632::GPRRegister, RegX8632::XmmRegister, | |
| 1820 RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>( | |
| 1821 Func, SrcTy, Dest, Src, Emitter); | |
| 1822 return; | |
| 1823 } | |
| 1824 case Float2float: { | |
| 1825 assert(isScalarFloatingType(SrcTy)); | |
| 1826 assert(isScalarFloatingType(DestTy)); | |
| 1827 assert(DestTy != SrcTy); | |
| 1828 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { | |
| 1829 &X8632::AssemblerX8632::cvtfloat2float, | |
| 1830 &X8632::AssemblerX8632::cvtfloat2float}; | |
| 1831 emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter); | |
| 1832 return; | |
| 1833 } | |
| 1834 case Dq2ps: { | |
| 1835 assert(isVectorIntegerType(SrcTy)); | |
| 1836 assert(isVectorFloatingType(DestTy)); | |
| 1837 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { | |
| 1838 &X8632::AssemblerX8632::cvtdq2ps, &X8632::AssemblerX8632::cvtdq2ps}; | |
| 1839 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter); | |
| 1840 return; | |
| 1841 } | |
| 1842 case Tps2dq: { | |
| 1843 assert(isVectorFloatingType(SrcTy)); | |
| 1844 assert(isVectorIntegerType(DestTy)); | |
| 1845 static const X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { | |
| 1846 &X8632::AssemblerX8632::cvttps2dq, &X8632::AssemblerX8632::cvttps2dq}; | |
| 1847 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter); | |
| 1848 return; | |
| 1849 } | |
| 1850 } | |
| 1851 } | |
| 1852 | |
| 1853 void InstX8632Cvt::dump(const Cfg *Func) const { | |
| 1854 if (!BuildDefs::dump()) | |
| 1855 return; | |
| 1856 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1857 dumpDest(Func); | |
| 1858 Str << " = cvt"; | |
| 1859 if (isTruncating()) | |
| 1860 Str << "t"; | |
| 1861 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2" | |
| 1862 << TypeX8632Attributes[getDest()->getType()].CvtString << " "; | |
| 1863 dumpSources(Func); | |
| 1864 } | |
| 1865 | |
| 1866 void InstX8632Icmp::emit(const Cfg *Func) const { | |
| 1867 if (!BuildDefs::dump()) | |
| 1868 return; | |
| 1869 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1870 assert(getSrcSize() == 2); | |
| 1871 Str << "\tcmp" << getWidthString(getSrc(0)->getType()) << "\t"; | |
| 1872 getSrc(1)->emit(Func); | |
| 1873 Str << ", "; | |
| 1874 getSrc(0)->emit(Func); | |
| 1875 } | |
| 1876 | |
| 1877 void InstX8632Icmp::emitIAS(const Cfg *Func) const { | |
| 1878 assert(getSrcSize() == 2); | |
| 1879 const Operand *Src0 = getSrc(0); | |
| 1880 const Operand *Src1 = getSrc(1); | |
| 1881 Type Ty = Src0->getType(); | |
| 1882 static const X8632::AssemblerX8632::GPREmitterRegOp RegEmitter = { | |
| 1883 &X8632::AssemblerX8632::cmp, &X8632::AssemblerX8632::cmp, | |
| 1884 &X8632::AssemblerX8632::cmp}; | |
| 1885 static const X8632::AssemblerX8632::GPREmitterAddrOp AddrEmitter = { | |
| 1886 &X8632::AssemblerX8632::cmp, &X8632::AssemblerX8632::cmp}; | |
| 1887 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { | |
| 1888 if (SrcVar0->hasReg()) { | |
| 1889 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); | |
| 1890 return; | |
| 1891 } | |
| 1892 } | |
| 1893 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); | |
| 1894 } | |
| 1895 | |
| 1896 void InstX8632Icmp::dump(const Cfg *Func) const { | |
| 1897 if (!BuildDefs::dump()) | |
| 1898 return; | |
| 1899 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1900 Str << "cmp." << getSrc(0)->getType() << " "; | |
| 1901 dumpSources(Func); | |
| 1902 } | |
| 1903 | |
| 1904 void InstX8632Ucomiss::emit(const Cfg *Func) const { | |
| 1905 if (!BuildDefs::dump()) | |
| 1906 return; | |
| 1907 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1908 assert(getSrcSize() == 2); | |
| 1909 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString | |
| 1910 << "\t"; | |
| 1911 getSrc(1)->emit(Func); | |
| 1912 Str << ", "; | |
| 1913 getSrc(0)->emit(Func); | |
| 1914 } | |
| 1915 | |
| 1916 void InstX8632Ucomiss::emitIAS(const Cfg *Func) const { | |
| 1917 assert(getSrcSize() == 2); | |
| 1918 // Currently src0 is always a variable by convention, to avoid having | |
| 1919 // two memory operands. | |
| 1920 assert(llvm::isa<Variable>(getSrc(0))); | |
| 1921 const auto Src0Var = llvm::cast<Variable>(getSrc(0)); | |
| 1922 Type Ty = Src0Var->getType(); | |
| 1923 const static X8632::AssemblerX8632::XmmEmitterRegOp Emitter = { | |
| 1924 &X8632::AssemblerX8632::ucomiss, &X8632::AssemblerX8632::ucomiss}; | |
| 1925 emitIASRegOpTyXMM(Func, Ty, Src0Var, getSrc(1), Emitter); | |
| 1926 } | |
| 1927 | |
| 1928 void InstX8632Ucomiss::dump(const Cfg *Func) const { | |
| 1929 if (!BuildDefs::dump()) | |
| 1930 return; | |
| 1931 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1932 Str << "ucomiss." << getSrc(0)->getType() << " "; | |
| 1933 dumpSources(Func); | |
| 1934 } | |
| 1935 | |
| 1936 void InstX8632UD2::emit(const Cfg *Func) const { | |
| 1937 if (!BuildDefs::dump()) | |
| 1938 return; | |
| 1939 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1940 assert(getSrcSize() == 0); | |
| 1941 Str << "\tud2"; | |
| 1942 } | |
| 1943 | |
| 1944 void InstX8632UD2::emitIAS(const Cfg *Func) const { | |
| 1945 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 1946 Asm->ud2(); | |
| 1947 } | |
| 1948 | |
| 1949 void InstX8632UD2::dump(const Cfg *Func) const { | |
| 1950 if (!BuildDefs::dump()) | |
| 1951 return; | |
| 1952 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1953 Str << "ud2"; | |
| 1954 } | |
| 1955 | |
| 1956 void InstX8632Test::emit(const Cfg *Func) const { | |
| 1957 if (!BuildDefs::dump()) | |
| 1958 return; | |
| 1959 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1960 assert(getSrcSize() == 2); | |
| 1961 Str << "\ttest" << getWidthString(getSrc(0)->getType()) << "\t"; | |
| 1962 getSrc(1)->emit(Func); | |
| 1963 Str << ", "; | |
| 1964 getSrc(0)->emit(Func); | |
| 1965 } | |
| 1966 | |
| 1967 void InstX8632Test::emitIAS(const Cfg *Func) const { | |
| 1968 assert(getSrcSize() == 2); | |
| 1969 const Operand *Src0 = getSrc(0); | |
| 1970 const Operand *Src1 = getSrc(1); | |
| 1971 Type Ty = Src0->getType(); | |
| 1972 // The Reg/Addr form of test is not encodeable. | |
| 1973 static const X8632::AssemblerX8632::GPREmitterRegOp RegEmitter = { | |
| 1974 &X8632::AssemblerX8632::test, nullptr, &X8632::AssemblerX8632::test}; | |
| 1975 static const X8632::AssemblerX8632::GPREmitterAddrOp AddrEmitter = { | |
| 1976 &X8632::AssemblerX8632::test, &X8632::AssemblerX8632::test}; | |
| 1977 if (const auto SrcVar0 = llvm::dyn_cast<Variable>(Src0)) { | |
| 1978 if (SrcVar0->hasReg()) { | |
| 1979 emitIASRegOpTyGPR(Func, Ty, SrcVar0, Src1, RegEmitter); | |
| 1980 return; | |
| 1981 } | |
| 1982 } | |
| 1983 llvm_unreachable("Nothing actually generates this so it's untested"); | |
| 1984 emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter); | |
| 1985 } | |
| 1986 | |
| 1987 void InstX8632Test::dump(const Cfg *Func) const { | |
| 1988 if (!BuildDefs::dump()) | |
| 1989 return; | |
| 1990 Ostream &Str = Func->getContext()->getStrDump(); | |
| 1991 Str << "test." << getSrc(0)->getType() << " "; | |
| 1992 dumpSources(Func); | |
| 1993 } | |
| 1994 | |
| 1995 void InstX8632Mfence::emit(const Cfg *Func) const { | |
| 1996 if (!BuildDefs::dump()) | |
| 1997 return; | |
| 1998 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 1999 assert(getSrcSize() == 0); | |
| 2000 Str << "\tmfence"; | |
| 2001 } | |
| 2002 | |
| 2003 void InstX8632Mfence::emitIAS(const Cfg *Func) const { | |
| 2004 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2005 Asm->mfence(); | |
| 2006 } | |
| 2007 | |
| 2008 void InstX8632Mfence::dump(const Cfg *Func) const { | |
| 2009 if (!BuildDefs::dump()) | |
| 2010 return; | |
| 2011 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2012 Str << "mfence"; | |
| 2013 } | |
| 2014 | |
| 2015 void InstX8632Store::emit(const Cfg *Func) const { | |
| 2016 if (!BuildDefs::dump()) | |
| 2017 return; | |
| 2018 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2019 assert(getSrcSize() == 2); | |
| 2020 Type Ty = getSrc(0)->getType(); | |
| 2021 Str << "\tmov" << getWidthString(Ty) << TypeX8632Attributes[Ty].SdSsString | |
| 2022 << "\t"; | |
| 2023 getSrc(0)->emit(Func); | |
| 2024 Str << ", "; | |
| 2025 getSrc(1)->emit(Func); | |
| 2026 } | |
| 2027 | |
| 2028 void InstX8632Store::emitIAS(const Cfg *Func) const { | |
| 2029 assert(getSrcSize() == 2); | |
| 2030 const Operand *Dest = getSrc(1); | |
| 2031 const Operand *Src = getSrc(0); | |
| 2032 Type DestTy = Dest->getType(); | |
| 2033 if (isScalarFloatingType(DestTy)) { | |
| 2034 // Src must be a register, since Dest is a Mem operand of some kind. | |
| 2035 const auto SrcVar = llvm::cast<Variable>(Src); | |
| 2036 assert(SrcVar->hasReg()); | |
| 2037 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); | |
| 2038 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2039 if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) { | |
| 2040 assert(!DestVar->hasReg()); | |
| 2041 X8632::Traits::Address StackAddr( | |
| 2042 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 2043 ->stackVarToAsmOperand(DestVar)); | |
| 2044 Asm->movss(DestTy, StackAddr, SrcReg); | |
| 2045 } else { | |
| 2046 const auto DestMem = llvm::cast<OperandX8632Mem>(Dest); | |
| 2047 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 2048 Asm->movss(DestTy, DestMem->toAsmAddress(Asm), SrcReg); | |
| 2049 } | |
| 2050 return; | |
| 2051 } else { | |
| 2052 assert(isScalarIntegerType(DestTy)); | |
| 2053 static const X8632::AssemblerX8632::GPREmitterAddrOp GPRAddrEmitter = { | |
| 2054 &X8632::AssemblerX8632::mov, &X8632::AssemblerX8632::mov}; | |
| 2055 emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter); | |
| 2056 } | |
| 2057 } | |
| 2058 | |
| 2059 void InstX8632Store::dump(const Cfg *Func) const { | |
| 2060 if (!BuildDefs::dump()) | |
| 2061 return; | |
| 2062 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2063 Str << "mov." << getSrc(0)->getType() << " "; | |
| 2064 getSrc(1)->dump(Func); | |
| 2065 Str << ", "; | |
| 2066 getSrc(0)->dump(Func); | |
| 2067 } | |
| 2068 | |
| 2069 void InstX8632StoreP::emit(const Cfg *Func) const { | |
| 2070 if (!BuildDefs::dump()) | |
| 2071 return; | |
| 2072 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2073 assert(getSrcSize() == 2); | |
| 2074 Str << "\tmovups\t"; | |
| 2075 getSrc(0)->emit(Func); | |
| 2076 Str << ", "; | |
| 2077 getSrc(1)->emit(Func); | |
| 2078 } | |
| 2079 | |
| 2080 void InstX8632StoreP::emitIAS(const Cfg *Func) const { | |
| 2081 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2082 assert(getSrcSize() == 2); | |
| 2083 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); | |
| 2084 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | |
| 2085 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 2086 assert(SrcVar->hasReg()); | |
| 2087 Asm->movups(DestMem->toAsmAddress(Asm), | |
| 2088 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | |
| 2089 } | |
| 2090 | |
| 2091 void InstX8632StoreP::dump(const Cfg *Func) const { | |
| 2092 if (!BuildDefs::dump()) | |
| 2093 return; | |
| 2094 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2095 Str << "storep." << getSrc(0)->getType() << " "; | |
| 2096 getSrc(1)->dump(Func); | |
| 2097 Str << ", "; | |
| 2098 getSrc(0)->dump(Func); | |
| 2099 } | |
| 2100 | |
| 2101 void InstX8632StoreQ::emit(const Cfg *Func) const { | |
| 2102 if (!BuildDefs::dump()) | |
| 2103 return; | |
| 2104 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2105 assert(getSrcSize() == 2); | |
| 2106 assert(getSrc(1)->getType() == IceType_i64 || | |
| 2107 getSrc(1)->getType() == IceType_f64); | |
| 2108 Str << "\tmovq\t"; | |
| 2109 getSrc(0)->emit(Func); | |
| 2110 Str << ", "; | |
| 2111 getSrc(1)->emit(Func); | |
| 2112 } | |
| 2113 | |
| 2114 void InstX8632StoreQ::emitIAS(const Cfg *Func) const { | |
| 2115 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2116 assert(getSrcSize() == 2); | |
| 2117 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); | |
| 2118 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | |
| 2119 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 2120 assert(SrcVar->hasReg()); | |
| 2121 Asm->movq(DestMem->toAsmAddress(Asm), | |
| 2122 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | |
| 2123 } | |
| 2124 | |
| 2125 void InstX8632StoreQ::dump(const Cfg *Func) const { | |
| 2126 if (!BuildDefs::dump()) | |
| 2127 return; | |
| 2128 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2129 Str << "storeq." << getSrc(0)->getType() << " "; | |
| 2130 getSrc(1)->dump(Func); | |
| 2131 Str << ", "; | |
| 2132 getSrc(0)->dump(Func); | |
| 2133 } | |
| 2134 | |
| 2135 template <> void InstX8632Lea::emit(const Cfg *Func) const { | |
| 2136 if (!BuildDefs::dump()) | |
| 2137 return; | |
| 2138 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2139 assert(getSrcSize() == 1); | |
| 2140 assert(getDest()->hasReg()); | |
| 2141 Str << "\tleal\t"; | |
| 2142 Operand *Src0 = getSrc(0); | |
| 2143 if (const auto Src0Var = llvm::dyn_cast<Variable>(Src0)) { | |
| 2144 Type Ty = Src0Var->getType(); | |
| 2145 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an | |
| 2146 // acceptable type. | |
| 2147 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty)->emit(Func); | |
| 2148 } else { | |
| 2149 Src0->emit(Func); | |
| 2150 } | |
| 2151 Str << ", "; | |
| 2152 getDest()->emit(Func); | |
| 2153 } | |
| 2154 | |
| 2155 template <> void InstX8632Mov::emit(const Cfg *Func) const { | |
| 2156 if (!BuildDefs::dump()) | |
| 2157 return; | |
| 2158 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2159 assert(getSrcSize() == 1); | |
| 2160 Operand *Src = getSrc(0); | |
| 2161 Type SrcTy = Src->getType(); | |
| 2162 Type DestTy = getDest()->getType(); | |
| 2163 Str << "\tmov" << (!isScalarFloatingType(DestTy) | |
| 2164 ? getWidthString(SrcTy) | |
| 2165 : TypeX8632Attributes[DestTy].SdSsString) << "\t"; | |
| 2166 // For an integer truncation operation, src is wider than dest. | |
| 2167 // Ideally, we use a mov instruction whose data width matches the | |
| 2168 // narrower dest. This is a problem if e.g. src is a register like | |
| 2169 // esi or si where there is no 8-bit version of the register. To be | |
| 2170 // safe, we instead widen the dest to match src. This works even | |
| 2171 // for stack-allocated dest variables because typeWidthOnStack() | |
| 2172 // pads to a 4-byte boundary even if only a lower portion is used. | |
| 2173 // TODO: This assert disallows usages such as copying a floating point | |
| 2174 // value between a vector and a scalar (which movss is used for). | |
| 2175 // Clean this up. | |
| 2176 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) == | |
| 2177 Func->getTarget()->typeWidthInBytesOnStack(SrcTy)); | |
| 2178 Src->emit(Func); | |
| 2179 Str << ", "; | |
| 2180 getDest()->asType(SrcTy)->emit(Func); | |
| 2181 } | |
| 2182 | |
| 2183 template <> void InstX8632Mov::emitIAS(const Cfg *Func) const { | |
| 2184 assert(getSrcSize() == 1); | |
| 2185 const Variable *Dest = getDest(); | |
| 2186 const Operand *Src = getSrc(0); | |
| 2187 Type DestTy = Dest->getType(); | |
| 2188 Type SrcTy = Src->getType(); | |
| 2189 // Mov can be used for GPRs or XMM registers. Also, the type does not | |
| 2190 // necessarily match (Mov can be used for bitcasts). However, when | |
| 2191 // the type does not match, one of the operands must be a register. | |
| 2192 // Thus, the strategy is to find out if Src or Dest are a register, | |
| 2193 // then use that register's type to decide on which emitter set to use. | |
| 2194 // The emitter set will include reg-reg movs, but that case should | |
| 2195 // be unused when the types don't match. | |
| 2196 static const X8632::AssemblerX8632::XmmEmitterRegOp XmmRegEmitter = { | |
| 2197 &X8632::AssemblerX8632::movss, &X8632::AssemblerX8632::movss}; | |
| 2198 static const X8632::AssemblerX8632::GPREmitterRegOp GPRRegEmitter = { | |
| 2199 &X8632::AssemblerX8632::mov, &X8632::AssemblerX8632::mov, | |
| 2200 &X8632::AssemblerX8632::mov}; | |
| 2201 static const X8632::AssemblerX8632::GPREmitterAddrOp GPRAddrEmitter = { | |
| 2202 &X8632::AssemblerX8632::mov, &X8632::AssemblerX8632::mov}; | |
| 2203 // For an integer truncation operation, src is wider than dest. | |
| 2204 // Ideally, we use a mov instruction whose data width matches the | |
| 2205 // narrower dest. This is a problem if e.g. src is a register like | |
| 2206 // esi or si where there is no 8-bit version of the register. To be | |
| 2207 // safe, we instead widen the dest to match src. This works even | |
| 2208 // for stack-allocated dest variables because typeWidthOnStack() | |
| 2209 // pads to a 4-byte boundary even if only a lower portion is used. | |
| 2210 // TODO: This assert disallows usages such as copying a floating point | |
| 2211 // value between a vector and a scalar (which movss is used for). | |
| 2212 // Clean this up. | |
| 2213 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) == | |
| 2214 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); | |
| 2215 if (Dest->hasReg()) { | |
| 2216 if (isScalarFloatingType(DestTy)) { | |
| 2217 emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter); | |
| 2218 return; | |
| 2219 } else { | |
| 2220 assert(isScalarIntegerType(DestTy)); | |
| 2221 // Widen DestTy for truncation (see above note). We should only do this | |
| 2222 // when both Src and Dest are integer types. | |
| 2223 if (isScalarIntegerType(SrcTy)) { | |
| 2224 DestTy = SrcTy; | |
| 2225 } | |
| 2226 emitIASRegOpTyGPR(Func, DestTy, Dest, Src, GPRRegEmitter); | |
| 2227 return; | |
| 2228 } | |
| 2229 } else { | |
| 2230 // Dest must be Stack and Src *could* be a register. Use Src's type | |
| 2231 // to decide on the emitters. | |
| 2232 X8632::Traits::Address StackAddr( | |
| 2233 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 2234 ->stackVarToAsmOperand(Dest)); | |
| 2235 if (isScalarFloatingType(SrcTy)) { | |
| 2236 // Src must be a register. | |
| 2237 const auto SrcVar = llvm::cast<Variable>(Src); | |
| 2238 assert(SrcVar->hasReg()); | |
| 2239 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2240 Asm->movss(SrcTy, StackAddr, | |
| 2241 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | |
| 2242 return; | |
| 2243 } else { | |
| 2244 // Src can be a register or immediate. | |
| 2245 assert(isScalarIntegerType(SrcTy)); | |
| 2246 emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter); | |
| 2247 return; | |
| 2248 } | |
| 2249 return; | |
| 2250 } | |
| 2251 } | |
| 2252 | |
| 2253 template <> void InstX8632Movd::emitIAS(const Cfg *Func) const { | |
| 2254 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2255 assert(getSrcSize() == 1); | |
| 2256 const Variable *Dest = getDest(); | |
| 2257 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); | |
| 2258 // For insert/extract element (one of Src/Dest is an Xmm vector and | |
| 2259 // the other is an int type). | |
| 2260 if (SrcVar->getType() == IceType_i32) { | |
| 2261 assert(isVectorType(Dest->getType())); | |
| 2262 assert(Dest->hasReg()); | |
| 2263 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); | |
| 2264 if (SrcVar->hasReg()) { | |
| 2265 Asm->movd(DestReg, RegX8632::getEncodedGPR(SrcVar->getRegNum())); | |
| 2266 } else { | |
| 2267 X8632::Traits::Address StackAddr( | |
| 2268 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 2269 ->stackVarToAsmOperand(SrcVar)); | |
| 2270 Asm->movd(DestReg, StackAddr); | |
| 2271 } | |
| 2272 } else { | |
| 2273 assert(isVectorType(SrcVar->getType())); | |
| 2274 assert(SrcVar->hasReg()); | |
| 2275 assert(Dest->getType() == IceType_i32); | |
| 2276 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); | |
| 2277 if (Dest->hasReg()) { | |
| 2278 Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg); | |
| 2279 } else { | |
| 2280 X8632::Traits::Address StackAddr( | |
| 2281 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 2282 ->stackVarToAsmOperand(Dest)); | |
| 2283 Asm->movd(StackAddr, SrcReg); | |
| 2284 } | |
| 2285 } | |
| 2286 } | |
| 2287 | |
| 2288 template <> void InstX8632Movp::emit(const Cfg *Func) const { | |
| 2289 if (!BuildDefs::dump()) | |
| 2290 return; | |
| 2291 // TODO(wala,stichnot): movups works with all vector operands, but | |
| 2292 // there exist other instructions (movaps, movdqa, movdqu) that may | |
| 2293 // perform better, depending on the data type and alignment of the | |
| 2294 // operands. | |
| 2295 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2296 assert(getSrcSize() == 1); | |
| 2297 Str << "\tmovups\t"; | |
| 2298 getSrc(0)->emit(Func); | |
| 2299 Str << ", "; | |
| 2300 getDest()->emit(Func); | |
| 2301 } | |
| 2302 | |
| 2303 template <> void InstX8632Movp::emitIAS(const Cfg *Func) const { | |
| 2304 assert(getSrcSize() == 1); | |
| 2305 assert(isVectorType(getDest()->getType())); | |
| 2306 const Variable *Dest = getDest(); | |
| 2307 const Operand *Src = getSrc(0); | |
| 2308 const static X8632::AssemblerX8632::XmmEmitterMovOps Emitter = { | |
| 2309 &X8632::AssemblerX8632::movups, &X8632::AssemblerX8632::movups, | |
| 2310 &X8632::AssemblerX8632::movups}; | |
| 2311 emitIASMovlikeXMM(Func, Dest, Src, Emitter); | |
| 2312 } | |
| 2313 | |
| 2314 template <> void InstX8632Movq::emit(const Cfg *Func) const { | |
| 2315 if (!BuildDefs::dump()) | |
| 2316 return; | |
| 2317 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2318 assert(getSrcSize() == 1); | |
| 2319 assert(getDest()->getType() == IceType_i64 || | |
| 2320 getDest()->getType() == IceType_f64); | |
| 2321 Str << "\tmovq\t"; | |
| 2322 getSrc(0)->emit(Func); | |
| 2323 Str << ", "; | |
| 2324 getDest()->emit(Func); | |
| 2325 } | |
| 2326 | |
| 2327 template <> void InstX8632Movq::emitIAS(const Cfg *Func) const { | |
| 2328 assert(getSrcSize() == 1); | |
| 2329 assert(getDest()->getType() == IceType_i64 || | |
| 2330 getDest()->getType() == IceType_f64); | |
| 2331 const Variable *Dest = getDest(); | |
| 2332 const Operand *Src = getSrc(0); | |
| 2333 const static X8632::AssemblerX8632::XmmEmitterMovOps Emitter = { | |
| 2334 &X8632::AssemblerX8632::movq, &X8632::AssemblerX8632::movq, | |
| 2335 &X8632::AssemblerX8632::movq}; | |
| 2336 emitIASMovlikeXMM(Func, Dest, Src, Emitter); | |
| 2337 } | |
| 2338 | |
| 2339 template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const { | |
| 2340 // This is Binop variant is only intended to be used for reg-reg moves | |
| 2341 // where part of the Dest register is untouched. | |
| 2342 assert(getSrcSize() == 2); | |
| 2343 const Variable *Dest = getDest(); | |
| 2344 assert(Dest == getSrc(0)); | |
| 2345 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); | |
| 2346 assert(Dest->hasReg() && SrcVar->hasReg()); | |
| 2347 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2348 Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()), | |
| 2349 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | |
| 2350 } | |
| 2351 | |
| 2352 template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const { | |
| 2353 assert(getSrcSize() == 1); | |
| 2354 const Variable *Dest = getDest(); | |
| 2355 const Operand *Src = getSrc(0); | |
| 2356 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice | |
| 2357 // we just use the full register for Dest to avoid having an | |
| 2358 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy. | |
| 2359 Type SrcTy = Src->getType(); | |
| 2360 assert(typeWidthInBytes(Dest->getType()) > 1); | |
| 2361 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); | |
| 2362 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); | |
| 2363 } | |
| 2364 | |
| 2365 template <> void InstX8632Movzx::emitIAS(const Cfg *Func) const { | |
| 2366 assert(getSrcSize() == 1); | |
| 2367 const Variable *Dest = getDest(); | |
| 2368 const Operand *Src = getSrc(0); | |
| 2369 Type SrcTy = Src->getType(); | |
| 2370 assert(typeWidthInBytes(Dest->getType()) > 1); | |
| 2371 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); | |
| 2372 emitIASRegOpTyGPR<false, true>(Func, SrcTy, Dest, Src, Emitter); | |
| 2373 } | |
| 2374 | |
| 2375 void InstX8632Nop::emit(const Cfg *Func) const { | |
| 2376 if (!BuildDefs::dump()) | |
| 2377 return; | |
| 2378 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2379 // TODO: Emit the right code for each variant. | |
| 2380 Str << "\tnop\t# variant = " << Variant; | |
| 2381 } | |
| 2382 | |
| 2383 void InstX8632Nop::emitIAS(const Cfg *Func) const { | |
| 2384 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2385 // TODO: Emit the right code for the variant. | |
| 2386 Asm->nop(); | |
| 2387 } | |
| 2388 | |
| 2389 void InstX8632Nop::dump(const Cfg *Func) const { | |
| 2390 if (!BuildDefs::dump()) | |
| 2391 return; | |
| 2392 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2393 Str << "nop (variant = " << Variant << ")"; | |
| 2394 } | |
| 2395 | |
| 2396 void InstX8632Fld::emit(const Cfg *Func) const { | |
| 2397 if (!BuildDefs::dump()) | |
| 2398 return; | |
| 2399 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2400 assert(getSrcSize() == 1); | |
| 2401 Type Ty = getSrc(0)->getType(); | |
| 2402 SizeT Width = typeWidthInBytes(Ty); | |
| 2403 const auto Var = llvm::dyn_cast<Variable>(getSrc(0)); | |
| 2404 if (Var && Var->hasReg()) { | |
| 2405 // This is a physical xmm register, so we need to spill it to a | |
| 2406 // temporary stack slot. | |
| 2407 Str << "\tsubl\t$" << Width << ", %esp" | |
| 2408 << "\n"; | |
| 2409 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"; | |
| 2410 Var->emit(Func); | |
| 2411 Str << ", (%esp)\n"; | |
| 2412 Str << "\tfld" << getFldString(Ty) << "\t" | |
| 2413 << "(%esp)\n"; | |
| 2414 Str << "\taddl\t$" << Width << ", %esp"; | |
| 2415 return; | |
| 2416 } | |
| 2417 Str << "\tfld" << getFldString(Ty) << "\t"; | |
| 2418 getSrc(0)->emit(Func); | |
| 2419 } | |
| 2420 | |
| 2421 void InstX8632Fld::emitIAS(const Cfg *Func) const { | |
| 2422 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2423 assert(getSrcSize() == 1); | |
| 2424 const Operand *Src = getSrc(0); | |
| 2425 Type Ty = Src->getType(); | |
| 2426 if (const auto Var = llvm::dyn_cast<Variable>(Src)) { | |
| 2427 if (Var->hasReg()) { | |
| 2428 // This is a physical xmm register, so we need to spill it to a | |
| 2429 // temporary stack slot. | |
| 2430 X8632::Immediate Width(typeWidthInBytes(Ty)); | |
| 2431 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | |
| 2432 X8632::Traits::Address StackSlot = | |
| 2433 X8632::Traits::Address(RegX8632::Encoded_Reg_esp, 0); | |
| 2434 Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum())); | |
| 2435 Asm->fld(Ty, StackSlot); | |
| 2436 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | |
| 2437 } else { | |
| 2438 X8632::Traits::Address StackAddr( | |
| 2439 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 2440 ->stackVarToAsmOperand(Var)); | |
| 2441 Asm->fld(Ty, StackAddr); | |
| 2442 } | |
| 2443 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | |
| 2444 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 2445 Asm->fld(Ty, Mem->toAsmAddress(Asm)); | |
| 2446 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { | |
| 2447 Asm->fld(Ty, X8632::Traits::Address::ofConstPool(Asm, Imm)); | |
| 2448 } else { | |
| 2449 llvm_unreachable("Unexpected operand type"); | |
| 2450 } | |
| 2451 } | |
| 2452 | |
| 2453 void InstX8632Fld::dump(const Cfg *Func) const { | |
| 2454 if (!BuildDefs::dump()) | |
| 2455 return; | |
| 2456 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2457 Str << "fld." << getSrc(0)->getType() << " "; | |
| 2458 dumpSources(Func); | |
| 2459 } | |
| 2460 | |
| 2461 void InstX8632Fstp::emit(const Cfg *Func) const { | |
| 2462 if (!BuildDefs::dump()) | |
| 2463 return; | |
| 2464 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2465 assert(getSrcSize() == 0); | |
| 2466 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to | |
| 2467 // "partially" delete the fstp if the Dest is unused. | |
| 2468 // Even if Dest is unused, the fstp should be kept for the SideEffects | |
| 2469 // of popping the stack. | |
| 2470 if (!getDest()) { | |
| 2471 Str << "\tfstp\tst(0)"; | |
| 2472 return; | |
| 2473 } | |
| 2474 Type Ty = getDest()->getType(); | |
| 2475 size_t Width = typeWidthInBytes(Ty); | |
| 2476 if (!getDest()->hasReg()) { | |
| 2477 Str << "\tfstp" << getFldString(Ty) << "\t"; | |
| 2478 getDest()->emit(Func); | |
| 2479 return; | |
| 2480 } | |
| 2481 // Dest is a physical (xmm) register, so st(0) needs to go through | |
| 2482 // memory. Hack this by creating a temporary stack slot, spilling | |
| 2483 // st(0) there, loading it into the xmm register, and deallocating | |
| 2484 // the stack slot. | |
| 2485 Str << "\tsubl\t$" << Width << ", %esp\n"; | |
| 2486 Str << "\tfstp" << getFldString(Ty) << "\t" | |
| 2487 << "(%esp)\n"; | |
| 2488 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" | |
| 2489 << "(%esp), "; | |
| 2490 getDest()->emit(Func); | |
| 2491 Str << "\n"; | |
| 2492 Str << "\taddl\t$" << Width << ", %esp"; | |
| 2493 } | |
| 2494 | |
| 2495 void InstX8632Fstp::emitIAS(const Cfg *Func) const { | |
| 2496 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2497 assert(getSrcSize() == 0); | |
| 2498 const Variable *Dest = getDest(); | |
| 2499 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to | |
| 2500 // "partially" delete the fstp if the Dest is unused. | |
| 2501 // Even if Dest is unused, the fstp should be kept for the SideEffects | |
| 2502 // of popping the stack. | |
| 2503 if (!Dest) { | |
| 2504 Asm->fstp(RegX8632::getEncodedSTReg(0)); | |
| 2505 return; | |
| 2506 } | |
| 2507 Type Ty = Dest->getType(); | |
| 2508 if (!Dest->hasReg()) { | |
| 2509 X8632::Traits::Address StackAddr( | |
| 2510 static_cast<TargetX8632 *>(Func->getTarget()) | |
| 2511 ->stackVarToAsmOperand(Dest)); | |
| 2512 Asm->fstp(Ty, StackAddr); | |
| 2513 } else { | |
| 2514 // Dest is a physical (xmm) register, so st(0) needs to go through | |
| 2515 // memory. Hack this by creating a temporary stack slot, spilling | |
| 2516 // st(0) there, loading it into the xmm register, and deallocating | |
| 2517 // the stack slot. | |
| 2518 X8632::Immediate Width(typeWidthInBytes(Ty)); | |
| 2519 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | |
| 2520 X8632::Traits::Address StackSlot = | |
| 2521 X8632::Traits::Address(RegX8632::Encoded_Reg_esp, 0); | |
| 2522 Asm->fstp(Ty, StackSlot); | |
| 2523 Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot); | |
| 2524 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | |
| 2525 } | |
| 2526 } | |
| 2527 | |
| 2528 void InstX8632Fstp::dump(const Cfg *Func) const { | |
| 2529 if (!BuildDefs::dump()) | |
| 2530 return; | |
| 2531 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2532 dumpDest(Func); | |
| 2533 Str << " = fstp." << getDest()->getType() << ", st(0)"; | |
| 2534 } | |
| 2535 | |
| 2536 template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const { | |
| 2537 if (!BuildDefs::dump()) | |
| 2538 return; | |
| 2539 char buf[30]; | |
| 2540 snprintf(buf, llvm::array_lengthof(buf), "pcmpeq%s", | |
| 2541 TypeX8632Attributes[getDest()->getType()].PackString); | |
| 2542 emitTwoAddress(buf, this, Func); | |
| 2543 } | |
| 2544 | |
| 2545 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const { | |
| 2546 if (!BuildDefs::dump()) | |
| 2547 return; | |
| 2548 char buf[30]; | |
| 2549 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s", | |
| 2550 TypeX8632Attributes[getDest()->getType()].PackString); | |
| 2551 emitTwoAddress(buf, this, Func); | |
| 2552 } | |
| 2553 | |
| 2554 template <> void InstX8632Pextr::emit(const Cfg *Func) const { | |
| 2555 if (!BuildDefs::dump()) | |
| 2556 return; | |
| 2557 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2558 assert(getSrcSize() == 2); | |
| 2559 // pextrb and pextrd are SSE4.1 instructions. | |
| 2560 assert(getSrc(0)->getType() == IceType_v8i16 || | |
| 2561 getSrc(0)->getType() == IceType_v8i1 || | |
| 2562 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 2563 X8632::Traits::SSE4_1); | |
| 2564 Str << "\t" << Opcode << TypeX8632Attributes[getSrc(0)->getType()].PackString | |
| 2565 << "\t"; | |
| 2566 getSrc(1)->emit(Func); | |
| 2567 Str << ", "; | |
| 2568 getSrc(0)->emit(Func); | |
| 2569 Str << ", "; | |
| 2570 Variable *Dest = getDest(); | |
| 2571 // pextrw must take a register dest. There is an SSE4.1 version that takes | |
| 2572 // a memory dest, but we aren't using it. For uniformity, just restrict | |
| 2573 // them all to have a register dest for now. | |
| 2574 assert(Dest->hasReg()); | |
| 2575 Dest->asType(IceType_i32)->emit(Func); | |
| 2576 } | |
| 2577 | |
| 2578 template <> void InstX8632Pextr::emitIAS(const Cfg *Func) const { | |
| 2579 assert(getSrcSize() == 2); | |
| 2580 // pextrb and pextrd are SSE4.1 instructions. | |
| 2581 const Variable *Dest = getDest(); | |
| 2582 Type DispatchTy = Dest->getType(); | |
| 2583 assert(DispatchTy == IceType_i16 || | |
| 2584 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 2585 X8632::Traits::SSE4_1); | |
| 2586 // pextrw must take a register dest. There is an SSE4.1 version that takes | |
| 2587 // a memory dest, but we aren't using it. For uniformity, just restrict | |
| 2588 // them all to have a register dest for now. | |
| 2589 assert(Dest->hasReg()); | |
| 2590 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2). | |
| 2591 assert(llvm::cast<Variable>(getSrc(0))->hasReg()); | |
| 2592 static const X8632::AssemblerX8632::ThreeOpImmEmitter< | |
| 2593 RegX8632::GPRRegister, RegX8632::XmmRegister> Emitter = { | |
| 2594 &X8632::AssemblerX8632::pextr, nullptr}; | |
| 2595 emitIASThreeOpImmOps<RegX8632::GPRRegister, RegX8632::XmmRegister, | |
| 2596 RegX8632::getEncodedGPR, RegX8632::getEncodedXmm>( | |
| 2597 Func, DispatchTy, Dest, getSrc(0), getSrc(1), Emitter); | |
| 2598 } | |
| 2599 | |
| 2600 template <> void InstX8632Pinsr::emit(const Cfg *Func) const { | |
| 2601 if (!BuildDefs::dump()) | |
| 2602 return; | |
| 2603 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2604 assert(getSrcSize() == 3); | |
| 2605 // pinsrb and pinsrd are SSE4.1 instructions. | |
| 2606 assert(getDest()->getType() == IceType_v8i16 || | |
| 2607 getDest()->getType() == IceType_v8i1 || | |
| 2608 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 2609 X8632::Traits::SSE4_1); | |
| 2610 Str << "\t" << Opcode << TypeX8632Attributes[getDest()->getType()].PackString | |
| 2611 << "\t"; | |
| 2612 getSrc(2)->emit(Func); | |
| 2613 Str << ", "; | |
| 2614 Operand *Src1 = getSrc(1); | |
| 2615 if (const auto Src1Var = llvm::dyn_cast<Variable>(Src1)) { | |
| 2616 // If src1 is a register, it should always be r32. | |
| 2617 if (Src1Var->hasReg()) { | |
| 2618 Src1Var->asType(IceType_i32)->emit(Func); | |
| 2619 } else { | |
| 2620 Src1Var->emit(Func); | |
| 2621 } | |
| 2622 } else { | |
| 2623 Src1->emit(Func); | |
| 2624 } | |
| 2625 Str << ", "; | |
| 2626 getDest()->emit(Func); | |
| 2627 } | |
| 2628 | |
| 2629 template <> void InstX8632Pinsr::emitIAS(const Cfg *Func) const { | |
| 2630 assert(getSrcSize() == 3); | |
| 2631 assert(getDest() == getSrc(0)); | |
| 2632 // pinsrb and pinsrd are SSE4.1 instructions. | |
| 2633 const Operand *Src0 = getSrc(1); | |
| 2634 Type DispatchTy = Src0->getType(); | |
| 2635 assert(DispatchTy == IceType_i16 || | |
| 2636 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >= | |
| 2637 X8632::Traits::SSE4_1); | |
| 2638 // If src1 is a register, it should always be r32 (this should fall out | |
| 2639 // from the encodings for ByteRegs overlapping the encodings for r32), | |
| 2640 // but we have to trust the regalloc to not choose "ah", where it | |
| 2641 // doesn't overlap. | |
| 2642 static const X8632::AssemblerX8632::ThreeOpImmEmitter< | |
| 2643 RegX8632::XmmRegister, RegX8632::GPRRegister> Emitter = { | |
| 2644 &X8632::AssemblerX8632::pinsr, &X8632::AssemblerX8632::pinsr}; | |
| 2645 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::GPRRegister, | |
| 2646 RegX8632::getEncodedXmm, RegX8632::getEncodedGPR>( | |
| 2647 Func, DispatchTy, getDest(), Src0, getSrc(2), Emitter); | |
| 2648 } | |
| 2649 | |
| 2650 template <> void InstX8632Pshufd::emitIAS(const Cfg *Func) const { | |
| 2651 assert(getSrcSize() == 2); | |
| 2652 const Variable *Dest = getDest(); | |
| 2653 Type Ty = Dest->getType(); | |
| 2654 static const X8632::AssemblerX8632::ThreeOpImmEmitter< | |
| 2655 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { | |
| 2656 &X8632::AssemblerX8632::pshufd, &X8632::AssemblerX8632::pshufd}; | |
| 2657 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, | |
| 2658 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( | |
| 2659 Func, Ty, Dest, getSrc(0), getSrc(1), Emitter); | |
| 2660 } | |
| 2661 | |
| 2662 template <> void InstX8632Shufps::emitIAS(const Cfg *Func) const { | |
| 2663 assert(getSrcSize() == 3); | |
| 2664 const Variable *Dest = getDest(); | |
| 2665 assert(Dest == getSrc(0)); | |
| 2666 Type Ty = Dest->getType(); | |
| 2667 static const X8632::AssemblerX8632::ThreeOpImmEmitter< | |
| 2668 RegX8632::XmmRegister, RegX8632::XmmRegister> Emitter = { | |
| 2669 &X8632::AssemblerX8632::shufps, &X8632::AssemblerX8632::shufps}; | |
| 2670 emitIASThreeOpImmOps<RegX8632::XmmRegister, RegX8632::XmmRegister, | |
| 2671 RegX8632::getEncodedXmm, RegX8632::getEncodedXmm>( | |
| 2672 Func, Ty, Dest, getSrc(1), getSrc(2), Emitter); | |
| 2673 } | |
| 2674 | |
| 2675 void InstX8632Pop::emit(const Cfg *Func) const { | |
| 2676 if (!BuildDefs::dump()) | |
| 2677 return; | |
| 2678 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2679 assert(getSrcSize() == 0); | |
| 2680 Str << "\tpop\t"; | |
| 2681 getDest()->emit(Func); | |
| 2682 } | |
| 2683 | |
| 2684 void InstX8632Pop::emitIAS(const Cfg *Func) const { | |
| 2685 assert(getSrcSize() == 0); | |
| 2686 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2687 if (getDest()->hasReg()) { | |
| 2688 Asm->popl(RegX8632::getEncodedGPR(getDest()->getRegNum())); | |
| 2689 } else { | |
| 2690 Asm->popl(static_cast<TargetX8632 *>(Func->getTarget()) | |
| 2691 ->stackVarToAsmOperand(getDest())); | |
| 2692 } | |
| 2693 } | |
| 2694 | |
| 2695 void InstX8632Pop::dump(const Cfg *Func) const { | |
| 2696 if (!BuildDefs::dump()) | |
| 2697 return; | |
| 2698 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2699 dumpDest(Func); | |
| 2700 Str << " = pop." << getDest()->getType() << " "; | |
| 2701 } | |
| 2702 | |
| 2703 void InstX8632AdjustStack::emit(const Cfg *Func) const { | |
| 2704 if (!BuildDefs::dump()) | |
| 2705 return; | |
| 2706 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2707 Str << "\tsubl\t$" << Amount << ", %esp"; | |
| 2708 Func->getTarget()->updateStackAdjustment(Amount); | |
| 2709 } | |
| 2710 | |
| 2711 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { | |
| 2712 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2713 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, X8632::Immediate(Amount)); | |
| 2714 Func->getTarget()->updateStackAdjustment(Amount); | |
| 2715 } | |
| 2716 | |
| 2717 void InstX8632AdjustStack::dump(const Cfg *Func) const { | |
| 2718 if (!BuildDefs::dump()) | |
| 2719 return; | |
| 2720 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2721 Str << "esp = sub.i32 esp, " << Amount; | |
| 2722 } | |
| 2723 | |
| 2724 void InstX8632Push::emit(const Cfg *Func) const { | |
| 2725 if (!BuildDefs::dump()) | |
| 2726 return; | |
| 2727 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2728 assert(getSrcSize() == 1); | |
| 2729 // Push is currently only used for saving GPRs. | |
| 2730 const auto Var = llvm::cast<Variable>(getSrc(0)); | |
| 2731 assert(Var->hasReg()); | |
| 2732 Str << "\tpush\t"; | |
| 2733 Var->emit(Func); | |
| 2734 } | |
| 2735 | |
| 2736 void InstX8632Push::emitIAS(const Cfg *Func) const { | |
| 2737 assert(getSrcSize() == 1); | |
| 2738 // Push is currently only used for saving GPRs. | |
| 2739 const auto Var = llvm::cast<Variable>(getSrc(0)); | |
| 2740 assert(Var->hasReg()); | |
| 2741 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2742 Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum())); | |
| 2743 } | |
| 2744 | |
| 2745 void InstX8632Push::dump(const Cfg *Func) const { | |
| 2746 if (!BuildDefs::dump()) | |
| 2747 return; | |
| 2748 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2749 Str << "push." << getSrc(0)->getType() << " "; | |
| 2750 dumpSources(Func); | |
| 2751 } | |
| 2752 | |
| 2753 template <> void InstX8632Psll::emit(const Cfg *Func) const { | |
| 2754 if (!BuildDefs::dump()) | |
| 2755 return; | |
| 2756 assert(getDest()->getType() == IceType_v8i16 || | |
| 2757 getDest()->getType() == IceType_v8i1 || | |
| 2758 getDest()->getType() == IceType_v4i32 || | |
| 2759 getDest()->getType() == IceType_v4i1); | |
| 2760 char buf[30]; | |
| 2761 snprintf(buf, llvm::array_lengthof(buf), "psll%s", | |
| 2762 TypeX8632Attributes[getDest()->getType()].PackString); | |
| 2763 emitTwoAddress(buf, this, Func); | |
| 2764 } | |
| 2765 | |
| 2766 template <> void InstX8632Psra::emit(const Cfg *Func) const { | |
| 2767 if (!BuildDefs::dump()) | |
| 2768 return; | |
| 2769 assert(getDest()->getType() == IceType_v8i16 || | |
| 2770 getDest()->getType() == IceType_v8i1 || | |
| 2771 getDest()->getType() == IceType_v4i32 || | |
| 2772 getDest()->getType() == IceType_v4i1); | |
| 2773 char buf[30]; | |
| 2774 snprintf(buf, llvm::array_lengthof(buf), "psra%s", | |
| 2775 TypeX8632Attributes[getDest()->getType()].PackString); | |
| 2776 emitTwoAddress(buf, this, Func); | |
| 2777 } | |
| 2778 | |
| 2779 template <> void InstX8632Psrl::emit(const Cfg *Func) const { | |
| 2780 if (!BuildDefs::dump()) | |
| 2781 return; | |
| 2782 char buf[30]; | |
| 2783 snprintf(buf, llvm::array_lengthof(buf), "psrl%s", | |
| 2784 TypeX8632Attributes[getDest()->getType()].PackString); | |
| 2785 emitTwoAddress(buf, this, Func); | |
| 2786 } | |
| 2787 | |
| 2788 void InstX8632Ret::emit(const Cfg *Func) const { | |
| 2789 if (!BuildDefs::dump()) | |
| 2790 return; | |
| 2791 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2792 Str << "\tret"; | |
| 2793 } | |
| 2794 | |
| 2795 void InstX8632Ret::emitIAS(const Cfg *Func) const { | |
| 2796 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2797 Asm->ret(); | |
| 2798 } | |
| 2799 | |
| 2800 void InstX8632Ret::dump(const Cfg *Func) const { | |
| 2801 if (!BuildDefs::dump()) | |
| 2802 return; | |
| 2803 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2804 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); | |
| 2805 Str << "ret." << Ty << " "; | |
| 2806 dumpSources(Func); | |
| 2807 } | |
| 2808 | |
| 2809 void InstX8632Setcc::emit(const Cfg *Func) const { | |
| 2810 if (!BuildDefs::dump()) | |
| 2811 return; | |
| 2812 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2813 Str << "\tset" << InstX8632BrAttributes[Condition].DisplayString << "\t"; | |
| 2814 Dest->emit(Func); | |
| 2815 } | |
| 2816 | |
| 2817 void InstX8632Setcc::emitIAS(const Cfg *Func) const { | |
| 2818 assert(Condition != X8632::Traits::Cond::Br_None); | |
| 2819 assert(getDest()->getType() == IceType_i1); | |
| 2820 assert(getSrcSize() == 0); | |
| 2821 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2822 if (getDest()->hasReg()) | |
| 2823 Asm->setcc(Condition, RegX8632::getEncodedByteReg(getDest()->getRegNum())); | |
| 2824 else | |
| 2825 Asm->setcc(Condition, static_cast<TargetX8632 *>(Func->getTarget()) | |
| 2826 ->stackVarToAsmOperand(getDest())); | |
| 2827 return; | |
| 2828 } | |
| 2829 | |
| 2830 void InstX8632Setcc::dump(const Cfg *Func) const { | |
| 2831 if (!BuildDefs::dump()) | |
| 2832 return; | |
| 2833 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2834 Str << "setcc." << InstX8632BrAttributes[Condition].DisplayString << " "; | |
| 2835 dumpDest(Func); | |
| 2836 } | |
| 2837 | |
| 2838 void InstX8632Xadd::emit(const Cfg *Func) const { | |
| 2839 if (!BuildDefs::dump()) | |
| 2840 return; | |
| 2841 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2842 if (Locked) { | |
| 2843 Str << "\tlock"; | |
| 2844 } | |
| 2845 Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t"; | |
| 2846 getSrc(1)->emit(Func); | |
| 2847 Str << ", "; | |
| 2848 getSrc(0)->emit(Func); | |
| 2849 } | |
| 2850 | |
| 2851 void InstX8632Xadd::emitIAS(const Cfg *Func) const { | |
| 2852 assert(getSrcSize() == 2); | |
| 2853 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2854 Type Ty = getSrc(0)->getType(); | |
| 2855 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | |
| 2856 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 2857 const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm); | |
| 2858 const auto VarReg = llvm::cast<Variable>(getSrc(1)); | |
| 2859 assert(VarReg->hasReg()); | |
| 2860 const RegX8632::GPRRegister Reg = | |
| 2861 RegX8632::getEncodedGPR(VarReg->getRegNum()); | |
| 2862 Asm->xadd(Ty, Addr, Reg, Locked); | |
| 2863 } | |
| 2864 | |
| 2865 void InstX8632Xadd::dump(const Cfg *Func) const { | |
| 2866 if (!BuildDefs::dump()) | |
| 2867 return; | |
| 2868 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2869 if (Locked) { | |
| 2870 Str << "lock "; | |
| 2871 } | |
| 2872 Type Ty = getSrc(0)->getType(); | |
| 2873 Str << "xadd." << Ty << " "; | |
| 2874 dumpSources(Func); | |
| 2875 } | |
| 2876 | |
| 2877 void InstX8632Xchg::emit(const Cfg *Func) const { | |
| 2878 if (!BuildDefs::dump()) | |
| 2879 return; | |
| 2880 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 2881 Str << "\txchg" << getWidthString(getSrc(0)->getType()) << "\t"; | |
| 2882 getSrc(1)->emit(Func); | |
| 2883 Str << ", "; | |
| 2884 getSrc(0)->emit(Func); | |
| 2885 } | |
| 2886 | |
| 2887 void InstX8632Xchg::emitIAS(const Cfg *Func) const { | |
| 2888 assert(getSrcSize() == 2); | |
| 2889 X8632::AssemblerX8632 *Asm = Func->getAssembler<X8632::AssemblerX8632>(); | |
| 2890 Type Ty = getSrc(0)->getType(); | |
| 2891 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | |
| 2892 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | |
| 2893 const X8632::Traits::Address Addr = Mem->toAsmAddress(Asm); | |
| 2894 const auto VarReg = llvm::cast<Variable>(getSrc(1)); | |
| 2895 assert(VarReg->hasReg()); | |
| 2896 const RegX8632::GPRRegister Reg = | |
| 2897 RegX8632::getEncodedGPR(VarReg->getRegNum()); | |
| 2898 Asm->xchg(Ty, Addr, Reg); | |
| 2899 } | |
| 2900 | |
| 2901 void InstX8632Xchg::dump(const Cfg *Func) const { | |
| 2902 if (!BuildDefs::dump()) | |
| 2903 return; | |
| 2904 Ostream &Str = Func->getContext()->getStrDump(); | |
| 2905 Type Ty = getSrc(0)->getType(); | |
| 2906 Str << "xchg." << Ty << " "; | |
| 2907 dumpSources(Func); | |
| 2908 } | |
| 2909 | |
| 2910 void OperandX8632Mem::emit(const Cfg *Func) const { | |
| 2911 if (!BuildDefs::dump()) | 102 if (!BuildDefs::dump()) |
| 2912 return; | 103 return; |
| 2913 Ostream &Str = Func->getContext()->getStrEmit(); | 104 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2914 if (SegmentReg != DefaultSegment) { | 105 if (SegmentReg != DefaultSegment) { |
| 2915 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 106 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2916 Str << "%" << InstX8632SegmentRegNames[SegmentReg] << ":"; | 107 Str << "%" << X8632::Traits::InstSegmentRegNames[SegmentReg] << ":"; |
| 2917 } | 108 } |
| 2918 // Emit as Offset(Base,Index,1<<Shift). | 109 // Emit as Offset(Base,Index,1<<Shift). |
| 2919 // Offset is emitted without the leading '$'. | 110 // Offset is emitted without the leading '$'. |
| 2920 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. | 111 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. |
| 2921 if (!Offset) { | 112 if (!Offset) { |
| 2922 // No offset, emit nothing. | 113 // No offset, emit nothing. |
| 2923 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { | 114 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
| 2924 if (Base == nullptr || CI->getValue()) | 115 if (Base == nullptr || CI->getValue()) |
| 2925 // Emit a non-zero offset without a leading '$'. | 116 // Emit a non-zero offset without a leading '$'. |
| 2926 Str << CI->getValue(); | 117 Str << CI->getValue(); |
| 2927 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 118 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
| 2928 CR->emitWithoutPrefix(Func->getTarget()); | 119 CR->emitWithoutPrefix(Func->getTarget()); |
| 2929 } else { | 120 } else { |
| 2930 llvm_unreachable("Invalid offset type for x86 mem operand"); | 121 llvm_unreachable("Invalid offset type for x86 mem operand"); |
| 2931 } | 122 } |
| 2932 | 123 |
| 2933 if (Base) { | 124 if (Base) { |
| 2934 Str << "("; | 125 Str << "("; |
| 2935 Base->emit(Func); | 126 Base->emit(Func); |
| 2936 if (Index) { | 127 if (Index) { |
| 2937 Str << ","; | 128 Str << ","; |
| 2938 Index->emit(Func); | 129 Index->emit(Func); |
| 2939 if (Shift) | 130 if (Shift) |
| 2940 Str << "," << (1u << Shift); | 131 Str << "," << (1u << Shift); |
| 2941 } | 132 } |
| 2942 Str << ")"; | 133 Str << ")"; |
| 2943 } | 134 } |
| 2944 } | 135 } |
| 2945 | 136 |
| 2946 void OperandX8632Mem::dump(const Cfg *Func, Ostream &Str) const { | 137 void MachineTraits<TargetX8632>::X86OperandMem::dump(const Cfg *Func, |
| 138 Ostream &Str) const { |
| 2947 if (!BuildDefs::dump()) | 139 if (!BuildDefs::dump()) |
| 2948 return; | 140 return; |
| 2949 if (SegmentReg != DefaultSegment) { | 141 if (SegmentReg != DefaultSegment) { |
| 2950 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 142 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 2951 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 143 Str << X8632::Traits::InstSegmentRegNames[SegmentReg] << ":"; |
| 2952 } | 144 } |
| 2953 bool Dumped = false; | 145 bool Dumped = false; |
| 2954 Str << "["; | 146 Str << "["; |
| 2955 if (Base) { | 147 if (Base) { |
| 2956 if (Func) | 148 if (Func) |
| 2957 Base->dump(Func); | 149 Base->dump(Func); |
| 2958 else | 150 else |
| 2959 Base->dump(Str); | 151 Base->dump(Str); |
| 2960 Dumped = true; | 152 Dumped = true; |
| 2961 } | 153 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2987 Str << "+"; | 179 Str << "+"; |
| 2988 Offset->dump(Func, Str); | 180 Offset->dump(Func, Str); |
| 2989 } | 181 } |
| 2990 } else { | 182 } else { |
| 2991 // There is only the offset. | 183 // There is only the offset. |
| 2992 Offset->dump(Func, Str); | 184 Offset->dump(Func, Str); |
| 2993 } | 185 } |
| 2994 Str << "]"; | 186 Str << "]"; |
| 2995 } | 187 } |
| 2996 | 188 |
| 2997 void OperandX8632Mem::emitSegmentOverride(X8632::AssemblerX8632 *Asm) const { | 189 void MachineTraits<TargetX8632>::X86OperandMem::emitSegmentOverride( |
| 190 MachineTraits<TargetX8632>::Assembler *Asm) const { |
| 2998 if (SegmentReg != DefaultSegment) { | 191 if (SegmentReg != DefaultSegment) { |
| 2999 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 192 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
| 3000 Asm->emitSegmentOverride(InstX8632SegmentPrefixes[SegmentReg]); | 193 Asm->emitSegmentOverride(X8632::Traits::InstSegmentPrefixes[SegmentReg]); |
| 3001 } | 194 } |
| 3002 } | 195 } |
| 3003 | 196 |
| 3004 X8632::Traits::Address OperandX8632Mem::toAsmAddress(Assembler *Asm) const { | 197 MachineTraits<TargetX8632>::Address |
| 198 MachineTraits<TargetX8632>::X86OperandMem::toAsmAddress( |
| 199 MachineTraits<TargetX8632>::Assembler *Asm) const { |
| 3005 int32_t Disp = 0; | 200 int32_t Disp = 0; |
| 3006 AssemblerFixup *Fixup = nullptr; | 201 AssemblerFixup *Fixup = nullptr; |
| 3007 // Determine the offset (is it relocatable?) | 202 // Determine the offset (is it relocatable?) |
| 3008 if (getOffset()) { | 203 if (getOffset()) { |
| 3009 if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getOffset())) { | 204 if (const auto CI = llvm::dyn_cast<ConstantInteger32>(getOffset())) { |
| 3010 Disp = static_cast<int32_t>(CI->getValue()); | 205 Disp = static_cast<int32_t>(CI->getValue()); |
| 3011 } else if (const auto CR = | 206 } else if (const auto CR = |
| 3012 llvm::dyn_cast<ConstantRelocatable>(getOffset())) { | 207 llvm::dyn_cast<ConstantRelocatable>(getOffset())) { |
| 3013 Disp = CR->getOffset(); | 208 Disp = CR->getOffset(); |
| 3014 Fixup = Asm->createFixup(llvm::ELF::R_386_32, CR); | 209 Fixup = Asm->createFixup(llvm::ELF::R_386_32, CR); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3030 return X8632::Traits::Address( | 225 return X8632::Traits::Address( |
| 3031 RegX8632::getEncodedGPR(getIndex()->getRegNum()), | 226 RegX8632::getEncodedGPR(getIndex()->getRegNum()), |
| 3032 X8632::Traits::ScaleFactor(getShift()), Disp); | 227 X8632::Traits::ScaleFactor(getShift()), Disp); |
| 3033 } else if (Fixup) { | 228 } else if (Fixup) { |
| 3034 return X8632::Traits::Address::Absolute(Disp, Fixup); | 229 return X8632::Traits::Address::Absolute(Disp, Fixup); |
| 3035 } else { | 230 } else { |
| 3036 return X8632::Traits::Address::Absolute(Disp); | 231 return X8632::Traits::Address::Absolute(Disp); |
| 3037 } | 232 } |
| 3038 } | 233 } |
| 3039 | 234 |
| 3040 X8632::Traits::Address VariableSplit::toAsmAddress(const Cfg *Func) const { | 235 MachineTraits<TargetX8632>::Address |
| 236 MachineTraits<TargetX8632>::VariableSplit::toAsmAddress(const Cfg *Func) const { |
| 3041 assert(!Var->hasReg()); | 237 assert(!Var->hasReg()); |
| 3042 const TargetLowering *Target = Func->getTarget(); | 238 const ::Ice::TargetLowering *Target = Func->getTarget(); |
| 3043 int32_t Offset = | 239 int32_t Offset = |
| 3044 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); | 240 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); |
| 3045 return X8632::Traits::Address( | 241 return X8632::Traits::Address( |
| 3046 RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset); | 242 RegX8632::getEncodedGPR(Target->getFrameOrStackReg()), Offset); |
| 3047 } | 243 } |
| 3048 | 244 |
| 3049 void VariableSplit::emit(const Cfg *Func) const { | 245 void MachineTraits<TargetX8632>::VariableSplit::emit(const Cfg *Func) const { |
| 3050 if (!BuildDefs::dump()) | 246 if (!BuildDefs::dump()) |
| 3051 return; | 247 return; |
| 3052 Ostream &Str = Func->getContext()->getStrEmit(); | 248 Ostream &Str = Func->getContext()->getStrEmit(); |
| 3053 assert(!Var->hasReg()); | 249 assert(!Var->hasReg()); |
| 3054 // The following is copied/adapted from TargetX8632::emitVariable(). | 250 // The following is copied/adapted from TargetX8632::emitVariable(). |
| 3055 const TargetLowering *Target = Func->getTarget(); | 251 const ::Ice::TargetLowering *Target = Func->getTarget(); |
| 3056 const Type Ty = IceType_i32; | 252 const Type Ty = IceType_i32; |
| 3057 int32_t Offset = | 253 int32_t Offset = |
| 3058 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); | 254 Var->getStackOffset() + Target->getStackAdjustment() + getOffset(); |
| 3059 if (Offset) | 255 if (Offset) |
| 3060 Str << Offset; | 256 Str << Offset; |
| 3061 Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; | 257 Str << "(%" << Target->getRegName(Target->getFrameOrStackReg(), Ty) << ")"; |
| 3062 } | 258 } |
| 3063 | 259 |
| 3064 void VariableSplit::dump(const Cfg *Func, Ostream &Str) const { | 260 void MachineTraits<TargetX8632>::VariableSplit::dump(const Cfg *Func, |
| 261 Ostream &Str) const { |
| 3065 if (!BuildDefs::dump()) | 262 if (!BuildDefs::dump()) |
| 3066 return; | 263 return; |
| 3067 switch (Part) { | 264 switch (Part) { |
| 3068 case Low: | 265 case Low: |
| 3069 Str << "low"; | 266 Str << "low"; |
| 3070 break; | 267 break; |
| 3071 case High: | 268 case High: |
| 3072 Str << "high"; | 269 Str << "high"; |
| 3073 break; | 270 break; |
| 3074 } | 271 } |
| 3075 Str << "("; | 272 Str << "("; |
| 3076 if (Func) | 273 if (Func) |
| 3077 Var->dump(Func); | 274 Var->dump(Func); |
| 3078 else | 275 else |
| 3079 Var->dump(Str); | 276 Var->dump(Str); |
| 3080 Str << ")"; | 277 Str << ")"; |
| 3081 } | 278 } |
| 3082 | 279 |
| 280 } // namespace X86Internal |
| 3083 } // end of namespace Ice | 281 } // end of namespace Ice |
| 282 |
| 283 X86INSTS_DEFINE_STATIC_DATA(TargetX8632); |
| OLD | NEW |