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