1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===//
3 // The Subzero Code Generator
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the InstX8632 and OperandX8632 classes,
11 // primarily the constructors and the dump()/emit() methods.
13 //===----------------------------------------------------------------------===//
16 #include "IceCfgNode.h"
18 #include "IceInstX8632.h"
19 #include "IceTargetLoweringX8632.h"
20 #include "IceOperand.h"
26 const struct InstX8632BrAttributes_ {
27 const char *DisplayString;
28 const char *EmitString;
29 } InstX8632BrAttributes[] = {
30 #define X(tag, dump, emit) \
37 const struct InstX8632CmppsAttributes_ {
38 const char *EmitString;
39 } InstX8632CmppsAttributes[] = {
40 #define X(tag, emit) \
43 ICEINSTX8632CMPPS_TABLE
47 const struct TypeX8632Attributes_ {
48 const char *CvtString; // i (integer), s (single FP), d (double FP)
49 const char *SdSsString; // ss, sd, or <blank>
50 const char *PackString; // b, w, d, or <blank>
51 const char *WidthString; // {byte,word,dword,qword} ptr
52 } TypeX8632Attributes[] = {
53 #define X(tag, elementty, cvt, sdss, pack, width) \
54 { cvt, "" sdss, pack, width } \
60 const char *InstX8632SegmentRegNames[] = {
61 #define X(val, name) name,
66 } // end of anonymous namespace
68 const char *InstX8632::getWidthString(Type Ty) {
69 return TypeX8632Attributes[Ty].WidthString;
72 OperandX8632Mem::OperandX8632Mem(Cfg *Func, Type Ty, Variable *Base,
73 Constant *Offset, Variable *Index,
74 uint16_t Shift, SegmentRegisters SegmentReg)
75 : OperandX8632(kMem, Ty), Base(Base), Offset(Offset), Index(Index),
76 Shift(Shift), SegmentReg(SegmentReg) {
85 Vars = Func->allocateArrayOf<Variable *>(NumVars);
95 InstX8632AdjustStack::InstX8632AdjustStack(Cfg *Func, SizeT Amount)
96 : InstX8632(Func, InstX8632::Adjuststack, 0, NULL), Amount(Amount) {}
98 InstX8632Mul::InstX8632Mul(Cfg *Func, Variable *Dest, Variable *Source1,
100 : InstX8632(Func, InstX8632::Mul, 2, Dest) {
105 InstX8632Shld::InstX8632Shld(Cfg *Func, Variable *Dest, Variable *Source1,
107 : InstX8632(Func, InstX8632::Shld, 3, Dest) {
113 InstX8632Shrd::InstX8632Shrd(Cfg *Func, Variable *Dest, Variable *Source1,
115 : InstX8632(Func, InstX8632::Shrd, 3, Dest) {
121 InstX8632Label::InstX8632Label(Cfg *Func, TargetX8632 *Target)
122 : InstX8632(Func, InstX8632::Label, 0, NULL),
123 Number(Target->makeNextLabelNumber()) {}
125 IceString InstX8632Label::getName(const Cfg *Func) const {
127 snprintf(buf, llvm::array_lengthof(buf), "%u", Number);
128 return ".L" + Func->getFunctionName() + "$local$__" + buf;
131 InstX8632Br::InstX8632Br(Cfg *Func, CfgNode *TargetTrue, CfgNode *TargetFalse,
132 InstX8632Label *Label, InstX8632::BrCond Condition)
133 : InstX8632(Func, InstX8632::Br, 0, NULL), Condition(Condition),
134 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label) {}
136 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
137 : InstX8632(Func, InstX8632::Call, 1, Dest) {
138 HasSideEffects = true;
139 addSource(CallTarget);
142 InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source,
143 InstX8632::BrCond Condition)
144 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) {
145 // The final result is either the original Dest, or Source, so mark
151 InstX8632Cmpps::InstX8632Cmpps(Cfg *Func, Variable *Dest, Operand *Source,
152 InstX8632Cmpps::CmppsCond Condition)
153 : InstX8632(Func, InstX8632::Cmpps, 2, Dest), Condition(Condition) {
158 InstX8632Cmpxchg::InstX8632Cmpxchg(Cfg *Func, Operand *DestOrAddr,
159 Variable *Eax, Variable *Desired,
161 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 3,
162 llvm::dyn_cast<Variable>(DestOrAddr), Locked) {
163 assert(Eax->getRegNum() == TargetX8632::Reg_eax);
164 addSource(DestOrAddr);
169 InstX8632Cmpxchg8b::InstX8632Cmpxchg8b(Cfg *Func, OperandX8632 *Addr,
170 Variable *Edx, Variable *Eax,
171 Variable *Ecx, Variable *Ebx,
173 : InstX8632Lockable(Func, InstX8632::Cmpxchg, 5, NULL, Locked) {
174 assert(Edx->getRegNum() == TargetX8632::Reg_edx);
175 assert(Eax->getRegNum() == TargetX8632::Reg_eax);
176 assert(Ecx->getRegNum() == TargetX8632::Reg_ecx);
177 assert(Ebx->getRegNum() == TargetX8632::Reg_ebx);
185 InstX8632Cvt::InstX8632Cvt(Cfg *Func, Variable *Dest, Operand *Source,
187 : InstX8632(Func, InstX8632::Cvt, 1, Dest), Trunc(Trunc) {
191 InstX8632Icmp::InstX8632Icmp(Cfg *Func, Operand *Src0, Operand *Src1)
192 : InstX8632(Func, InstX8632::Icmp, 2, NULL) {
197 InstX8632Ucomiss::InstX8632Ucomiss(Cfg *Func, Operand *Src0, Operand *Src1)
198 : InstX8632(Func, InstX8632::Ucomiss, 2, NULL) {
203 InstX8632UD2::InstX8632UD2(Cfg *Func)
204 : InstX8632(Func, InstX8632::UD2, 0, NULL) {}
206 InstX8632Test::InstX8632Test(Cfg *Func, Operand *Src1, Operand *Src2)
207 : InstX8632(Func, InstX8632::Test, 2, NULL) {
212 InstX8632Mfence::InstX8632Mfence(Cfg *Func)
213 : InstX8632(Func, InstX8632::Mfence, 0, NULL) {
214 HasSideEffects = true;
217 InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem)
218 : InstX8632(Func, InstX8632::Store, 2, NULL) {
223 InstX8632StoreP::InstX8632StoreP(Cfg *Func, Operand *Value, OperandX8632 *Mem)
224 : InstX8632(Func, InstX8632::StoreP, 2, NULL) {
229 InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem)
230 : InstX8632(Func, InstX8632::StoreQ, 2, NULL) {
235 InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source)
236 : InstX8632(Func, InstX8632::Movsx, 1, Dest) {
240 InstX8632Movzx::InstX8632Movzx(Cfg *Func, Variable *Dest, Operand *Source)
241 : InstX8632(Func, InstX8632::Movzx, 1, Dest) {
245 InstX8632Nop::InstX8632Nop(Cfg *Func, InstX8632Nop::NopVariant Variant)
246 : InstX8632(Func, InstX8632::Nop, 0, NULL), Variant(Variant) {}
248 InstX8632Fld::InstX8632Fld(Cfg *Func, Operand *Src)
249 : InstX8632(Func, InstX8632::Fld, 1, NULL) {
253 InstX8632Fstp::InstX8632Fstp(Cfg *Func, Variable *Dest)
254 : InstX8632(Func, InstX8632::Fstp, 0, Dest) {}
256 InstX8632Pop::InstX8632Pop(Cfg *Func, Variable *Dest)
257 : InstX8632(Func, InstX8632::Pop, 0, Dest) {}
259 InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source,
260 bool SuppressStackAdjustment)
261 : InstX8632(Func, InstX8632::Push, 1, NULL),
262 SuppressStackAdjustment(SuppressStackAdjustment) {
266 InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source)
267 : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) {
272 InstX8632Xadd::InstX8632Xadd(Cfg *Func, Operand *Dest, Variable *Source,
274 : InstX8632Lockable(Func, InstX8632::Xadd, 2,
275 llvm::dyn_cast<Variable>(Dest), Locked) {
280 InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source)
281 : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
286 // ======================== Dump routines ======================== //
288 void InstX8632::dump(const Cfg *Func) const {
289 Ostream &Str = Func->getContext()->getStrDump();
294 void InstX8632Label::emit(const Cfg *Func) const {
295 Ostream &Str = Func->getContext()->getStrEmit();
296 Str << getName(Func) << ":\n";
299 void InstX8632Label::dump(const Cfg *Func) const {
300 Ostream &Str = Func->getContext()->getStrDump();
301 Str << getName(Func) << ":";
304 void InstX8632Br::emit(const Cfg *Func) const {
305 Ostream &Str = Func->getContext()->getStrEmit();
308 if (Condition == Br_None) {
311 Str << InstX8632BrAttributes[Condition].EmitString;
315 Str << "\t" << Label->getName(Func) << "\n";
317 if (Condition == Br_None) {
318 Str << "\t" << getTargetFalse()->getAsmName() << "\n";
320 Str << "\t" << getTargetTrue()->getAsmName() << "\n";
321 if (getTargetFalse()) {
322 Str << "\tjmp\t" << getTargetFalse()->getAsmName() << "\n";
328 void InstX8632Br::dump(const Cfg *Func) const {
329 Ostream &Str = Func->getContext()->getStrDump();
332 if (Condition == Br_None) {
334 << (Label ? Label->getName(Func) : getTargetFalse()->getName());
338 Str << InstX8632BrAttributes[Condition].DisplayString;
340 Str << ", label %" << Label->getName(Func);
342 Str << ", label %" << getTargetTrue()->getName();
343 if (getTargetFalse()) {
344 Str << ", label %" << getTargetFalse()->getName();
349 void InstX8632Call::emit(const Cfg *Func) const {
350 Ostream &Str = Func->getContext()->getStrEmit();
351 assert(getSrcSize() == 1);
353 getCallTarget()->emit(Func);
355 Func->getTarget()->resetStackAdjustment();
358 void InstX8632Call::dump(const Cfg *Func) const {
359 Ostream &Str = Func->getContext()->getStrDump();
365 getCallTarget()->dump(Func);
368 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for
369 // shift instructions, in order to be syntactically valid. The
370 // Opcode parameter needs to be char* and not IceString because of
372 void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func,
374 Ostream &Str = Func->getContext()->getStrEmit();
375 assert(Inst->getSrcSize() == 2);
376 assert(Inst->getDest() == Inst->getSrc(0));
377 Str << "\t" << Opcode << "\t";
378 Inst->getDest()->emit(Func);
380 bool EmittedSrc1 = false;
382 Variable *ShiftReg = llvm::dyn_cast<Variable>(Inst->getSrc(1));
383 if (ShiftReg && ShiftReg->getRegNum() == TargetX8632::Reg_ecx) {
389 Inst->getSrc(1)->emit(Func);
393 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
394 const Variable *Src = llvm::dyn_cast<const Variable>(Source);
397 if (Dest->hasReg() && Dest->getRegNum() == Src->getRegNum()) {
398 // TODO: On x86-64, instructions like "mov eax, eax" are used to
399 // clear the upper 32 bits of rax. We need to recognize and
403 if (!Dest->hasReg() && !Src->hasReg() &&
404 Dest->getStackOffset() == Src->getStackOffset())
410 template <> const char *InstX8632Bswap::Opcode = "bswap";
411 template <> const char *InstX8632Neg::Opcode = "neg";
413 template <> const char *InstX8632Bsf::Opcode = "bsf";
414 template <> const char *InstX8632Bsr::Opcode = "bsr";
415 template <> const char *InstX8632Lea::Opcode = "lea";
416 template <> const char *InstX8632Movd::Opcode = "movd";
417 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss";
418 template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq";
420 template <> const char *InstX8632Mov::Opcode = "mov";
421 template <> const char *InstX8632Movp::Opcode = "movups";
422 template <> const char *InstX8632Movq::Opcode = "movq";
424 template <> const char *InstX8632Add::Opcode = "add";
425 template <> const char *InstX8632Addps::Opcode = "addps";
426 template <> const char *InstX8632Adc::Opcode = "adc";
427 template <> const char *InstX8632Addss::Opcode = "addss";
428 template <> const char *InstX8632Padd::Opcode = "padd";
429 template <> const char *InstX8632Sub::Opcode = "sub";
430 template <> const char *InstX8632Subps::Opcode = "subps";
431 template <> const char *InstX8632Subss::Opcode = "subss";
432 template <> const char *InstX8632Sbb::Opcode = "sbb";
433 template <> const char *InstX8632Psub::Opcode = "psub";
434 template <> const char *InstX8632And::Opcode = "and";
435 template <> const char *InstX8632Pand::Opcode = "pand";
436 template <> const char *InstX8632Pandn::Opcode = "pandn";
437 template <> const char *InstX8632Or::Opcode = "or";
438 template <> const char *InstX8632Por::Opcode = "por";
439 template <> const char *InstX8632Xor::Opcode = "xor";
440 template <> const char *InstX8632Pxor::Opcode = "pxor";
441 template <> const char *InstX8632Imul::Opcode = "imul";
442 template <> const char *InstX8632Mulps::Opcode = "mulps";
443 template <> const char *InstX8632Mulss::Opcode = "mulss";
444 template <> const char *InstX8632Pmull::Opcode = "pmull";
445 template <> const char *InstX8632Pmuludq::Opcode = "pmuludq";
446 template <> const char *InstX8632Div::Opcode = "div";
447 template <> const char *InstX8632Divps::Opcode = "divps";
448 template <> const char *InstX8632Idiv::Opcode = "idiv";
449 template <> const char *InstX8632Divss::Opcode = "divss";
450 template <> const char *InstX8632Rol::Opcode = "rol";
451 template <> const char *InstX8632Shl::Opcode = "shl";
452 template <> const char *InstX8632Psll::Opcode = "psll";
453 template <> const char *InstX8632Shr::Opcode = "shr";
454 template <> const char *InstX8632Sar::Opcode = "sar";
455 template <> const char *InstX8632Psra::Opcode = "psra";
456 template <> const char *InstX8632Pcmpeq::Opcode = "pcmpeq";
457 template <> const char *InstX8632Pcmpgt::Opcode = "pcmpgt";
458 template <> const char *InstX8632Movss::Opcode = "movss";
460 template <> const char *InstX8632Insertps::Opcode = "insertps";
461 template <> const char *InstX8632Shufps::Opcode = "shufps";
462 template <> const char *InstX8632Pinsr::Opcode = "pinsr";
463 template <> const char *InstX8632Blendvps::Opcode = "blendvps";
464 template <> const char *InstX8632Pblendvb::Opcode = "pblendvb";
466 template <> const char *InstX8632Pextr::Opcode = "pextr";
467 template <> const char *InstX8632Pshufd::Opcode = "pshufd";
469 template <> void InstX8632Sqrtss::emit(const Cfg *Func) const {
470 Ostream &Str = Func->getContext()->getStrEmit();
471 assert(getSrcSize() == 1);
472 Type Ty = getSrc(0)->getType();
473 assert(Ty == IceType_f32 || Ty == IceType_f64);
474 Str << "\tsqrt" << TypeX8632Attributes[Ty].SdSsString << "\t";
475 getDest()->emit(Func);
477 getSrc(0)->emit(Func);
481 template <> void InstX8632Addss::emit(const Cfg *Func) const {
483 snprintf(buf, llvm::array_lengthof(buf), "add%s",
484 TypeX8632Attributes[getDest()->getType()].SdSsString);
485 emitTwoAddress(buf, this, Func);
488 template <> void InstX8632Padd::emit(const Cfg *Func) const {
490 snprintf(buf, llvm::array_lengthof(buf), "padd%s",
491 TypeX8632Attributes[getDest()->getType()].PackString);
492 emitTwoAddress(buf, this, Func);
495 template <> void InstX8632Pmull::emit(const Cfg *Func) const {
497 bool TypesAreValid = getDest()->getType() == IceType_v4i32 ||
498 getDest()->getType() == IceType_v8i16;
499 bool InstructionSetIsValid =
500 getDest()->getType() == IceType_v8i16 ||
501 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
504 (void)InstructionSetIsValid;
505 assert(TypesAreValid);
506 assert(InstructionSetIsValid);
507 snprintf(buf, llvm::array_lengthof(buf), "pmull%s",
508 TypeX8632Attributes[getDest()->getType()].PackString);
509 emitTwoAddress(buf, this, Func);
512 template <> void InstX8632Subss::emit(const Cfg *Func) const {
514 snprintf(buf, llvm::array_lengthof(buf), "sub%s",
515 TypeX8632Attributes[getDest()->getType()].SdSsString);
516 emitTwoAddress(buf, this, Func);
519 template <> void InstX8632Psub::emit(const Cfg *Func) const {
521 snprintf(buf, llvm::array_lengthof(buf), "psub%s",
522 TypeX8632Attributes[getDest()->getType()].PackString);
523 emitTwoAddress(buf, this, Func);
526 template <> void InstX8632Mulss::emit(const Cfg *Func) const {
528 snprintf(buf, llvm::array_lengthof(buf), "mul%s",
529 TypeX8632Attributes[getDest()->getType()].SdSsString);
530 emitTwoAddress(buf, this, Func);
533 template <> void InstX8632Pmuludq::emit(const Cfg *Func) const {
534 assert(getSrc(0)->getType() == IceType_v4i32 &&
535 getSrc(1)->getType() == IceType_v4i32);
536 emitTwoAddress(Opcode, this, Func);
539 template <> void InstX8632Divss::emit(const Cfg *Func) const {
541 snprintf(buf, llvm::array_lengthof(buf), "div%s",
542 TypeX8632Attributes[getDest()->getType()].SdSsString);
543 emitTwoAddress(buf, this, Func);
546 template <> void InstX8632Div::emit(const Cfg *Func) const {
547 Ostream &Str = Func->getContext()->getStrEmit();
548 assert(getSrcSize() == 3);
549 Str << "\t" << Opcode << "\t";
550 getSrc(1)->emit(Func);
554 template <> void InstX8632Idiv::emit(const Cfg *Func) const {
555 Ostream &Str = Func->getContext()->getStrEmit();
556 assert(getSrcSize() == 3);
557 Str << "\t" << Opcode << "\t";
558 getSrc(1)->emit(Func);
565 // pblendvb and blendvps take xmm0 as a final implicit argument.
566 void emitVariableBlendInst(const char *Opcode, const Inst *Inst,
568 Ostream &Str = Func->getContext()->getStrEmit();
569 assert(Inst->getSrcSize() == 3);
570 assert(llvm::isa<Variable>(Inst->getSrc(2)));
571 assert(llvm::cast<Variable>(Inst->getSrc(2))->getRegNum() ==
572 TargetX8632::Reg_xmm0);
573 Str << "\t" << Opcode << "\t";
574 Inst->getDest()->emit(Func);
576 Inst->getSrc(1)->emit(Func);
580 } // end anonymous namespace
582 template <> void InstX8632Blendvps::emit(const Cfg *Func) const {
583 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
584 TargetX8632::SSE4_1);
585 emitVariableBlendInst(Opcode, this, Func);
588 template <> void InstX8632Pblendvb::emit(const Cfg *Func) const {
589 assert(static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet() >=
590 TargetX8632::SSE4_1);
591 emitVariableBlendInst(Opcode, this, Func);
594 template <> void InstX8632Imul::emit(const Cfg *Func) const {
595 Ostream &Str = Func->getContext()->getStrEmit();
596 assert(getSrcSize() == 2);
597 if (getDest()->getType() == IceType_i8) {
598 // The 8-bit version of imul only allows the form "imul r/m8".
599 Variable *Src0 = llvm::dyn_cast<Variable>(getSrc(0));
601 assert(Src0 && Src0->getRegNum() == TargetX8632::Reg_eax);
603 getSrc(1)->emit(Func);
605 } else if (llvm::isa<Constant>(getSrc(1))) {
607 getDest()->emit(Func);
609 getSrc(0)->emit(Func);
611 getSrc(1)->emit(Func);
614 emitTwoAddress("imul", this, Func);
618 template <> void InstX8632Cbwdq::emit(const Cfg *Func) const {
619 Ostream &Str = Func->getContext()->getStrEmit();
620 assert(getSrcSize() == 1);
621 Operand *Src0 = getSrc(0);
622 assert(llvm::isa<Variable>(Src0));
623 assert(llvm::cast<Variable>(Src0)->getRegNum() == TargetX8632::Reg_eax);
624 switch (Src0->getType()) {
626 llvm_unreachable("unexpected source type!");
629 assert(getDest()->getRegNum() == TargetX8632::Reg_eax);
633 assert(getDest()->getRegNum() == TargetX8632::Reg_edx);
637 assert(getDest()->getRegNum() == TargetX8632::Reg_edx);
643 void InstX8632Mul::emit(const Cfg *Func) const {
644 Ostream &Str = Func->getContext()->getStrEmit();
645 assert(getSrcSize() == 2);
646 assert(llvm::isa<Variable>(getSrc(0)));
647 assert(llvm::dyn_cast<Variable>(getSrc(0))->getRegNum() ==
648 TargetX8632::Reg_eax);
649 assert(getDest()->getRegNum() == TargetX8632::Reg_eax); // TODO: allow edx?
651 getSrc(1)->emit(Func);
655 void InstX8632Mul::dump(const Cfg *Func) const {
656 Ostream &Str = Func->getContext()->getStrDump();
658 Str << " = mul." << getDest()->getType() << " ";
662 void InstX8632Shld::emit(const Cfg *Func) const {
663 Ostream &Str = Func->getContext()->getStrEmit();
664 assert(getSrcSize() == 3);
665 assert(getDest() == getSrc(0));
667 getDest()->emit(Func);
669 getSrc(1)->emit(Func);
671 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) {
673 assert(ShiftReg->getRegNum() == TargetX8632::Reg_ecx);
676 getSrc(2)->emit(Func);
681 void InstX8632Shld::dump(const Cfg *Func) const {
682 Ostream &Str = Func->getContext()->getStrDump();
684 Str << " = shld." << getDest()->getType() << " ";
688 void InstX8632Shrd::emit(const Cfg *Func) const {
689 Ostream &Str = Func->getContext()->getStrEmit();
690 assert(getSrcSize() == 3);
691 assert(getDest() == getSrc(0));
693 getDest()->emit(Func);
695 getSrc(1)->emit(Func);
697 if (Variable *ShiftReg = llvm::dyn_cast<Variable>(getSrc(2))) {
699 assert(ShiftReg->getRegNum() == TargetX8632::Reg_ecx);
702 getSrc(2)->emit(Func);
707 void InstX8632Shrd::dump(const Cfg *Func) const {
708 Ostream &Str = Func->getContext()->getStrDump();
710 Str << " = shrd." << getDest()->getType() << " ";
714 void InstX8632Cmov::emit(const Cfg *Func) const {
715 Ostream &Str = Func->getContext()->getStrEmit();
717 assert(Condition != Br_None);
718 assert(getDest()->hasReg());
719 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "\t";
720 getDest()->emit(Func);
722 getSrc(1)->emit(Func);
726 void InstX8632Cmov::dump(const Cfg *Func) const {
727 Ostream &Str = Func->getContext()->getStrDump();
728 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << ".";
729 Str << getDest()->getType() << " ";
735 void InstX8632Cmpps::emit(const Cfg *Func) const {
736 Ostream &Str = Func->getContext()->getStrEmit();
737 assert(getSrcSize() == 2);
738 assert(Condition < Cmpps_Invalid);
740 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
742 getDest()->emit(Func);
744 getSrc(1)->emit(Func);
748 void InstX8632Cmpps::dump(const Cfg *Func) const {
749 Ostream &Str = Func->getContext()->getStrDump();
750 assert(Condition < Cmpps_Invalid);
752 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps"
757 void InstX8632Cmpxchg::emit(const Cfg *Func) const {
758 Ostream &Str = Func->getContext()->getStrEmit();
759 assert(getSrcSize() == 3);
763 Str << "\tcmpxchg\t";
764 getSrc(0)->emit(Func);
766 getSrc(2)->emit(Func);
770 void InstX8632Cmpxchg::dump(const Cfg *Func) const {
771 Ostream &Str = Func->getContext()->getStrDump();
775 Str << "cmpxchg." << getSrc(0)->getType() << " ";
779 void InstX8632Cmpxchg8b::emit(const Cfg *Func) const {
780 Ostream &Str = Func->getContext()->getStrEmit();
781 assert(getSrcSize() == 5);
785 Str << "\tcmpxchg8b\t";
786 getSrc(0)->emit(Func);
790 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const {
791 Ostream &Str = Func->getContext()->getStrDump();
799 void InstX8632Cvt::emit(const Cfg *Func) const {
800 Ostream &Str = Func->getContext()->getStrEmit();
801 assert(getSrcSize() == 1);
805 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2"
806 << TypeX8632Attributes[getDest()->getType()].CvtString << "\t";
807 getDest()->emit(Func);
809 getSrc(0)->emit(Func);
813 void InstX8632Cvt::dump(const Cfg *Func) const {
814 Ostream &Str = Func->getContext()->getStrDump();
819 Str << TypeX8632Attributes[getSrc(0)->getType()].CvtString << "2"
820 << TypeX8632Attributes[getDest()->getType()].CvtString << " ";
824 void InstX8632Icmp::emit(const Cfg *Func) const {
825 Ostream &Str = Func->getContext()->getStrEmit();
826 assert(getSrcSize() == 2);
828 getSrc(0)->emit(Func);
830 getSrc(1)->emit(Func);
834 void InstX8632Icmp::dump(const Cfg *Func) const {
835 Ostream &Str = Func->getContext()->getStrDump();
836 Str << "cmp." << getSrc(0)->getType() << " ";
840 void InstX8632Ucomiss::emit(const Cfg *Func) const {
841 Ostream &Str = Func->getContext()->getStrEmit();
842 assert(getSrcSize() == 2);
843 Str << "\tucomi" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString
845 getSrc(0)->emit(Func);
847 getSrc(1)->emit(Func);
851 void InstX8632Ucomiss::dump(const Cfg *Func) const {
852 Ostream &Str = Func->getContext()->getStrDump();
853 Str << "ucomiss." << getSrc(0)->getType() << " ";
857 void InstX8632UD2::emit(const Cfg *Func) const {
858 Ostream &Str = Func->getContext()->getStrEmit();
859 assert(getSrcSize() == 0);
863 void InstX8632UD2::dump(const Cfg *Func) const {
864 Ostream &Str = Func->getContext()->getStrDump();
868 void InstX8632Test::emit(const Cfg *Func) const {
869 Ostream &Str = Func->getContext()->getStrEmit();
870 assert(getSrcSize() == 2);
872 getSrc(0)->emit(Func);
874 getSrc(1)->emit(Func);
878 void InstX8632Test::dump(const Cfg *Func) const {
879 Ostream &Str = Func->getContext()->getStrDump();
880 Str << "test." << getSrc(0)->getType() << " ";
884 void InstX8632Mfence::emit(const Cfg *Func) const {
885 Ostream &Str = Func->getContext()->getStrEmit();
886 assert(getSrcSize() == 0);
890 void InstX8632Mfence::dump(const Cfg *Func) const {
891 Ostream &Str = Func->getContext()->getStrDump();
895 void InstX8632Store::emit(const Cfg *Func) const {
896 Ostream &Str = Func->getContext()->getStrEmit();
897 assert(getSrcSize() == 2);
898 Str << "\tmov" << TypeX8632Attributes[getSrc(0)->getType()].SdSsString
900 getSrc(1)->emit(Func);
902 getSrc(0)->emit(Func);
906 void InstX8632Store::dump(const Cfg *Func) const {
907 Ostream &Str = Func->getContext()->getStrDump();
908 Str << "mov." << getSrc(0)->getType() << " ";
909 getSrc(1)->dump(Func);
911 getSrc(0)->dump(Func);
914 void InstX8632StoreP::emit(const Cfg *Func) const {
915 Ostream &Str = Func->getContext()->getStrEmit();
916 assert(getSrcSize() == 2);
918 getSrc(1)->emit(Func);
920 getSrc(0)->emit(Func);
924 void InstX8632StoreP::dump(const Cfg *Func) const {
925 Ostream &Str = Func->getContext()->getStrDump();
926 Str << "storep." << getSrc(0)->getType() << " ";
927 getSrc(1)->dump(Func);
929 getSrc(0)->dump(Func);
932 void InstX8632StoreQ::emit(const Cfg *Func) const {
933 Ostream &Str = Func->getContext()->getStrEmit();
934 assert(getSrcSize() == 2);
935 assert(getSrc(1)->getType() == IceType_i64 ||
936 getSrc(1)->getType() == IceType_f64);
938 getSrc(1)->emit(Func);
940 getSrc(0)->emit(Func);
944 void InstX8632StoreQ::dump(const Cfg *Func) const {
945 Ostream &Str = Func->getContext()->getStrDump();
946 Str << "storeq." << getSrc(0)->getType() << " ";
947 getSrc(1)->dump(Func);
949 getSrc(0)->dump(Func);
952 template <> void InstX8632Lea::emit(const Cfg *Func) const {
953 Ostream &Str = Func->getContext()->getStrEmit();
954 assert(getSrcSize() == 1);
955 assert(getDest()->hasReg());
957 getDest()->emit(Func);
959 Operand *Src0 = getSrc(0);
960 if (Variable *VSrc0 = llvm::dyn_cast<Variable>(Src0)) {
961 Type Ty = VSrc0->getType();
962 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
964 VSrc0->asType(isVectorType(Ty) ? IceType_i32 : Ty).emit(Func);
971 template <> void InstX8632Mov::emit(const Cfg *Func) const {
972 Ostream &Str = Func->getContext()->getStrEmit();
973 assert(getSrcSize() == 1);
974 Operand *Src = getSrc(0);
975 // The llvm-mc assembler using Intel syntax has a bug in which "mov
976 // reg, RelocatableConstant" does not generate the right instruction
977 // with a relocation. To work around, we emit "lea reg,
978 // RelocatableConstant". Also, the lowering and legalization is
979 // changed to allow relocatable constants only in Assign and Call
980 // instructions or in Mem operands. TODO(stichnot): remove LEAHACK
981 // once a proper emitter is used.
983 // In addition, llvm-mc doesn't like "lea eax, bp" or "lea eax, Sp"
984 // or "lea eax, flags" etc., when the relocatable constant name is a
985 // reserved word. The hack-on-top-of-hack is to temporarily drop
986 // into AT&T syntax for this lea instruction.
987 bool UseLeaHack = llvm::isa<ConstantRelocatable>(Src);
989 Str << ".att_syntax\n";
992 Str << "\tmov" << TypeX8632Attributes[getDest()->getType()].SdSsString;
995 // For an integer truncation operation, src is wider than dest.
996 // Ideally, we use a mov instruction whose data width matches the
997 // narrower dest. This is a problem if e.g. src is a register like
998 // esi or si where there is no 8-bit version of the register. To be
999 // safe, we instead widen the dest to match src. This works even
1000 // for stack-allocated dest variables because typeWidthOnStack()
1001 // pads to a 4-byte boundary even if only a lower portion is used.
1002 // TODO: This assert disallows usages such as copying a floating point
1003 // value between a vector and a scalar (which movss is used for).
1005 assert(Func->getTarget()->typeWidthInBytesOnStack(getDest()->getType()) ==
1006 Func->getTarget()->typeWidthInBytesOnStack(Src->getType()));
1010 getDest()->emit(Func);
1012 Str << ".intel_syntax\n";
1014 getDest()->asType(Src->getType()).emit(Func);
1021 template <> void InstX8632Movp::emit(const Cfg *Func) const {
1022 // TODO(wala,stichnot): movups works with all vector operands, but
1023 // there exist other instructions (movaps, movdqa, movdqu) that may
1024 // perform better, depending on the data type and alignment of the
1026 Ostream &Str = Func->getContext()->getStrEmit();
1027 assert(getSrcSize() == 1);
1028 Str << "\tmovups\t";
1029 getDest()->emit(Func);
1031 getSrc(0)->emit(Func);
1035 template <> void InstX8632Movq::emit(const Cfg *Func) const {
1036 Ostream &Str = Func->getContext()->getStrEmit();
1037 assert(getSrcSize() == 1);
1038 assert(getDest()->getType() == IceType_i64 ||
1039 getDest()->getType() == IceType_f64);
1041 getDest()->emit(Func);
1043 getSrc(0)->emit(Func);
1047 void InstX8632Movsx::emit(const Cfg *Func) const {
1048 Ostream &Str = Func->getContext()->getStrEmit();
1049 assert(getSrcSize() == 1);
1051 getDest()->emit(Func);
1053 getSrc(0)->emit(Func);
1057 void InstX8632Movsx::dump(const Cfg *Func) const {
1058 Ostream &Str = Func->getContext()->getStrDump();
1059 Str << "movsx." << getDest()->getType() << "." << getSrc(0)->getType();
1066 void InstX8632Movzx::emit(const Cfg *Func) const {
1067 Ostream &Str = Func->getContext()->getStrEmit();
1068 assert(getSrcSize() == 1);
1070 getDest()->emit(Func);
1072 getSrc(0)->emit(Func);
1076 void InstX8632Movzx::dump(const Cfg *Func) const {
1077 Ostream &Str = Func->getContext()->getStrDump();
1078 Str << "movzx." << getDest()->getType() << "." << getSrc(0)->getType();
1085 void InstX8632Nop::emit(const Cfg *Func) const {
1086 Ostream &Str = Func->getContext()->getStrEmit();
1087 // TODO: Emit the right code for each variant.
1088 Str << "\tnop\t# variant = " << Variant << "\n";
1091 void InstX8632Nop::dump(const Cfg *Func) const {
1092 Ostream &Str = Func->getContext()->getStrDump();
1093 Str << "nop (variant = " << Variant << ")";
1096 void InstX8632Fld::emit(const Cfg *Func) const {
1097 Ostream &Str = Func->getContext()->getStrEmit();
1098 assert(getSrcSize() == 1);
1099 Type Ty = getSrc(0)->getType();
1100 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0));
1101 if (Var && Var->hasReg()) {
1102 // This is a physical xmm register, so we need to spill it to a
1103 // temporary stack slot.
1104 SizeT Width = typeWidthInBytes(Ty);
1105 Str << "\tsub\tesp, " << Width << "\n";
1106 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"
1107 << TypeX8632Attributes[Ty].WidthString << " [esp], ";
1110 Str << "\tfld\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n";
1111 Str << "\tadd\tesp, " << Width << "\n";
1115 getSrc(0)->emit(Func);
1119 void InstX8632Fld::dump(const Cfg *Func) const {
1120 Ostream &Str = Func->getContext()->getStrDump();
1121 Str << "fld." << getSrc(0)->getType() << " ";
1125 void InstX8632Fstp::emit(const Cfg *Func) const {
1126 Ostream &Str = Func->getContext()->getStrEmit();
1127 assert(getSrcSize() == 0);
1128 if (getDest() == NULL) {
1129 Str << "\tfstp\tst(0)\n";
1132 if (!getDest()->hasReg()) {
1134 getDest()->emit(Func);
1138 // Dest is a physical (xmm) register, so st(0) needs to go through
1139 // memory. Hack this by creating a temporary stack slot, spilling
1140 // st(0) there, loading it into the xmm register, and deallocating
1142 Type Ty = getDest()->getType();
1143 size_t Width = typeWidthInBytes(Ty);
1144 Str << "\tsub\tesp, " << Width << "\n";
1145 Str << "\tfstp\t" << TypeX8632Attributes[Ty].WidthString << " [esp]\n";
1146 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t";
1147 getDest()->emit(Func);
1148 Str << ", " << TypeX8632Attributes[Ty].WidthString << " [esp]\n";
1149 Str << "\tadd\tesp, " << Width << "\n";
1152 void InstX8632Fstp::dump(const Cfg *Func) const {
1153 Ostream &Str = Func->getContext()->getStrDump();
1155 Str << " = fstp." << getDest()->getType() << ", st(0)";
1159 template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const {
1161 snprintf(buf, llvm::array_lengthof(buf), "pcmpeq%s",
1162 TypeX8632Attributes[getDest()->getType()].PackString);
1163 emitTwoAddress(buf, this, Func);
1166 template <> void InstX8632Pcmpgt::emit(const Cfg *Func) const {
1168 snprintf(buf, llvm::array_lengthof(buf), "pcmpgt%s",
1169 TypeX8632Attributes[getDest()->getType()].PackString);
1170 emitTwoAddress(buf, this, Func);
1173 template <> void InstX8632Pextr::emit(const Cfg *Func) const {
1174 Ostream &Str = Func->getContext()->getStrEmit();
1175 assert(getSrcSize() == 2);
1176 // pextrb and pextrd are SSE4.1 instructions.
1177 assert(getSrc(0)->getType() == IceType_v8i16 ||
1178 getSrc(0)->getType() == IceType_v8i1 ||
1179 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet()
1180 >= TargetX8632::SSE4_1);
1181 Str << "\t" << Opcode
1182 << TypeX8632Attributes[getSrc(0)->getType()].PackString << "\t";
1183 Variable *Dest = getDest();
1184 // pextrw must take a register dest.
1185 assert(Dest->getType() != IceType_i16 || Dest->hasReg());
1186 Dest->asType(IceType_i32).emit(Func);
1188 getSrc(0)->emit(Func);
1190 getSrc(1)->emit(Func);
1194 template <> void InstX8632Pinsr::emit(const Cfg *Func) const {
1195 Ostream &Str = Func->getContext()->getStrEmit();
1196 assert(getSrcSize() == 3);
1197 // pinsrb and pinsrd are SSE4.1 instructions.
1198 assert(getDest()->getType() == IceType_v8i16 ||
1199 getDest()->getType() == IceType_v8i1 ||
1200 static_cast<TargetX8632 *>(Func->getTarget())->getInstructionSet()
1201 >= TargetX8632::SSE4_1);
1202 Str << "\t" << Opcode
1203 << TypeX8632Attributes[getDest()->getType()].PackString << "\t";
1204 getDest()->emit(Func);
1206 Operand *Src1 = getSrc(1);
1207 if (Variable *VSrc1 = llvm::dyn_cast<Variable>(Src1)) {
1208 // If src1 is a register, it should always be r32.
1209 if (VSrc1->hasReg()) {
1210 VSrc1->asType(IceType_i32).emit(Func);
1218 getSrc(2)->emit(Func);
1222 void InstX8632Pop::emit(const Cfg *Func) const {
1223 Ostream &Str = Func->getContext()->getStrEmit();
1224 assert(getSrcSize() == 0);
1226 getDest()->emit(Func);
1230 void InstX8632Pop::dump(const Cfg *Func) const {
1231 Ostream &Str = Func->getContext()->getStrDump();
1233 Str << " = pop." << getDest()->getType() << " ";
1236 void InstX8632AdjustStack::emit(const Cfg *Func) const {
1237 Ostream &Str = Func->getContext()->getStrEmit();
1238 Str << "\tsub\tesp, " << Amount << "\n";
1239 Func->getTarget()->updateStackAdjustment(Amount);
1242 void InstX8632AdjustStack::dump(const Cfg *Func) const {
1243 Ostream &Str = Func->getContext()->getStrDump();
1244 Str << "esp = sub.i32 esp, " << Amount;
1247 void InstX8632Push::emit(const Cfg *Func) const {
1248 Ostream &Str = Func->getContext()->getStrEmit();
1249 assert(getSrcSize() == 1);
1250 Type Ty = getSrc(0)->getType();
1251 Variable *Var = llvm::dyn_cast<Variable>(getSrc(0));
1252 if ((isVectorType(Ty) || Ty == IceType_f32 || Ty == IceType_f64) && Var &&
1254 // The xmm registers can't be directly pushed, so we fake it by
1255 // decrementing esp and then storing to [esp].
1256 Str << "\tsub\tesp, " << typeWidthInBytes(Ty) << "\n";
1257 if (!SuppressStackAdjustment)
1258 Func->getTarget()->updateStackAdjustment(typeWidthInBytes(Ty));
1259 if (isVectorType(Ty)) {
1260 Str << "\tmovups\txmmword ptr [esp], ";
1262 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t"
1263 << TypeX8632Attributes[Ty].WidthString << " [esp], ";
1265 getSrc(0)->emit(Func);
1267 } else if (Ty == IceType_f64 && (!Var || !Var->hasReg())) {
1268 // A double on the stack has to be pushed as two halves. Push the
1269 // upper half followed by the lower half for little-endian. TODO:
1271 llvm_unreachable("Missing support for pushing doubles from memory");
1274 getSrc(0)->emit(Func);
1276 if (!SuppressStackAdjustment)
1277 Func->getTarget()->updateStackAdjustment(4);
1281 void InstX8632Push::dump(const Cfg *Func) const {
1282 Ostream &Str = Func->getContext()->getStrDump();
1283 Str << "push." << getSrc(0)->getType() << " ";
1287 template <> void InstX8632Psll::emit(const Cfg *Func) const {
1288 assert(getDest()->getType() == IceType_v8i16 ||
1289 getDest()->getType() == IceType_v8i1 ||
1290 getDest()->getType() == IceType_v4i32 ||
1291 getDest()->getType() == IceType_v4i1);
1293 snprintf(buf, llvm::array_lengthof(buf), "psll%s",
1294 TypeX8632Attributes[getDest()->getType()].PackString);
1295 emitTwoAddress(buf, this, Func);
1298 template <> void InstX8632Psra::emit(const Cfg *Func) const {
1299 assert(getDest()->getType() == IceType_v8i16 ||
1300 getDest()->getType() == IceType_v8i1 ||
1301 getDest()->getType() == IceType_v4i32 ||
1302 getDest()->getType() == IceType_v4i1);
1304 snprintf(buf, llvm::array_lengthof(buf), "psra%s",
1305 TypeX8632Attributes[getDest()->getType()].PackString);
1306 emitTwoAddress(buf, this, Func);
1309 void InstX8632Ret::emit(const Cfg *Func) const {
1310 Ostream &Str = Func->getContext()->getStrEmit();
1314 void InstX8632Ret::dump(const Cfg *Func) const {
1315 Ostream &Str = Func->getContext()->getStrDump();
1316 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType());
1317 Str << "ret." << Ty << " ";
1321 void InstX8632Xadd::emit(const Cfg *Func) const {
1322 Ostream &Str = Func->getContext()->getStrEmit();
1327 getSrc(0)->emit(Func);
1329 getSrc(1)->emit(Func);
1333 void InstX8632Xadd::dump(const Cfg *Func) const {
1334 Ostream &Str = Func->getContext()->getStrDump();
1338 Type Ty = getSrc(0)->getType();
1339 Str << "xadd." << Ty << " ";
1343 void InstX8632Xchg::emit(const Cfg *Func) const {
1344 Ostream &Str = Func->getContext()->getStrEmit();
1346 getSrc(0)->emit(Func);
1348 getSrc(1)->emit(Func);
1352 void InstX8632Xchg::dump(const Cfg *Func) const {
1353 Ostream &Str = Func->getContext()->getStrDump();
1354 Type Ty = getSrc(0)->getType();
1355 Str << "xchg." << Ty << " ";
1359 void OperandX8632::dump(const Cfg *Func) const {
1360 Ostream &Str = Func->getContext()->getStrDump();
1361 Str << "<OperandX8632>";
1364 void OperandX8632Mem::emit(const Cfg *Func) const {
1365 Ostream &Str = Func->getContext()->getStrEmit();
1366 Str << TypeX8632Attributes[getType()].WidthString << " ";
1367 if (SegmentReg != DefaultSegment) {
1368 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
1369 Str << InstX8632SegmentRegNames[SegmentReg] << ":";
1371 // TODO: The following is an almost verbatim paste of dump().
1372 bool Dumped = false;
1382 Str << (1u << Shift) << "*";
1386 // Pretty-print the Offset.
1387 bool OffsetIsZero = false;
1388 bool OffsetIsNegative = false;
1389 if (Offset == NULL) {
1390 OffsetIsZero = true;
1391 } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) {
1392 OffsetIsZero = (CI->getValue() == 0);
1393 OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0);
1396 if (!OffsetIsZero) { // Suppress if Offset is known to be 0
1397 if (!OffsetIsNegative) // Suppress if Offset is known to be negative
1402 // There is only the offset.
1408 void OperandX8632Mem::dump(const Cfg *Func) const {
1409 Ostream &Str = Func->getContext()->getStrDump();
1410 if (SegmentReg != DefaultSegment) {
1411 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM);
1412 Str << InstX8632SegmentRegNames[SegmentReg] << ":";
1414 bool Dumped = false;
1424 Str << (1u << Shift) << "*";
1428 // Pretty-print the Offset.
1429 bool OffsetIsZero = false;
1430 bool OffsetIsNegative = false;
1431 if (Offset == NULL) {
1432 OffsetIsZero = true;
1433 } else if (ConstantInteger *CI = llvm::dyn_cast<ConstantInteger>(Offset)) {
1434 OffsetIsZero = (CI->getValue() == 0);
1435 OffsetIsNegative = (static_cast<int64_t>(CI->getValue()) < 0);
1438 if (!OffsetIsZero) { // Suppress if Offset is known to be 0
1439 if (!OffsetIsNegative) // Suppress if Offset is known to be negative
1444 // There is only the offset.
1450 void VariableSplit::emit(const Cfg *Func) const {
1451 Ostream &Str = Func->getContext()->getStrEmit();
1452 assert(Var->getLocalUseNode() == NULL ||
1453 Var->getLocalUseNode() == Func->getCurrentNode());
1454 assert(!Var->hasReg());
1455 // The following is copied/adapted from TargetX8632::emitVariable().
1456 const TargetLowering *Target = Func->getTarget();
1457 const Type Ty = IceType_i32;
1458 Str << TypeX8632Attributes[Ty].WidthString << " ["
1459 << Target->getRegName(Target->getFrameOrStackReg(), Ty);
1460 int32_t Offset = Var->getStackOffset() + Target->getStackAdjustment();
1471 void VariableSplit::dump(const Cfg *Func) const {
1472 Ostream &Str = Func->getContext()->getStrDump();
1489 } // end of namespace Ice