| OLD | NEW |
| 1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=// | 1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| (...skipping 2529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2540 Ostream &Str = Func->getContext()->getStrDump(); | 2540 Ostream &Str = Func->getContext()->getStrDump(); |
| 2541 Str << "nop (variant = " << Variant << ")"; | 2541 Str << "nop (variant = " << Variant << ")"; |
| 2542 } | 2542 } |
| 2543 | 2543 |
| 2544 template <class Machine> void InstX86Fld<Machine>::emit(const Cfg *Func) const { | 2544 template <class Machine> void InstX86Fld<Machine>::emit(const Cfg *Func) const { |
| 2545 if (!BuildDefs::dump()) | 2545 if (!BuildDefs::dump()) |
| 2546 return; | 2546 return; |
| 2547 Ostream &Str = Func->getContext()->getStrEmit(); | 2547 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2548 assert(this->getSrcSize() == 1); | 2548 assert(this->getSrcSize() == 1); |
| 2549 Type Ty = this->getSrc(0)->getType(); | 2549 Type Ty = this->getSrc(0)->getType(); |
| 2550 SizeT Width = typeWidthInBytes(Ty); | |
| 2551 const auto *Var = llvm::dyn_cast<Variable>(this->getSrc(0)); | 2550 const auto *Var = llvm::dyn_cast<Variable>(this->getSrc(0)); |
| 2552 if (Var && Var->hasReg()) { | 2551 if (Var && Var->hasReg()) { |
| 2553 // This is a physical xmm register, so we need to spill it to a temporary | 2552 // This is a physical xmm register, so we need to spill it to a temporary |
| 2554 // stack slot. | 2553 // stack slot. Function prolog emission guarantees that there is sufficient |
| 2555 Str << "\tsubl\t$" << Width << ", %esp" | 2554 // space to do this. |
| 2556 << "\n"; | |
| 2557 Str << "\tmov" | 2555 Str << "\tmov" |
| 2558 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t"; | 2556 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t"; |
| 2559 Var->emit(Func); | 2557 Var->emit(Func); |
| 2560 Str << ", (%esp)\n"; | 2558 Str << ", (%esp)\n"; |
| 2561 Str << "\tfld" << this->getFldString(Ty) << "\t" | 2559 Str << "\tfld" << this->getFldString(Ty) << "\t" |
| 2562 << "(%esp)\n"; | 2560 << "(%esp)"; |
| 2563 Str << "\taddl\t$" << Width << ", %esp"; | |
| 2564 return; | 2561 return; |
| 2565 } | 2562 } |
| 2566 Str << "\tfld" << this->getFldString(Ty) << "\t"; | 2563 Str << "\tfld" << this->getFldString(Ty) << "\t"; |
| 2567 this->getSrc(0)->emit(Func); | 2564 this->getSrc(0)->emit(Func); |
| 2568 } | 2565 } |
| 2569 | 2566 |
| 2570 template <class Machine> | 2567 template <class Machine> |
| 2571 void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const { | 2568 void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const { |
| 2572 typename InstX86Base<Machine>::Traits::Assembler *Asm = | 2569 typename InstX86Base<Machine>::Traits::Assembler *Asm = |
| 2573 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); | 2570 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); |
| 2574 assert(this->getSrcSize() == 1); | 2571 assert(this->getSrcSize() == 1); |
| 2575 const Operand *Src = this->getSrc(0); | 2572 const Operand *Src = this->getSrc(0); |
| 2576 auto *Target = InstX86Base<Machine>::getTarget(Func); | 2573 auto *Target = InstX86Base<Machine>::getTarget(Func); |
| 2577 Type Ty = Src->getType(); | 2574 Type Ty = Src->getType(); |
| 2578 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) { | 2575 if (const auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| 2579 if (Var->hasReg()) { | 2576 if (Var->hasReg()) { |
| 2580 // This is a physical xmm register, so we need to spill it to a temporary | 2577 // This is a physical xmm register, so we need to spill it to a temporary |
| 2581 // stack slot. | 2578 // stack slot. Function prolog emission guarantees that there is |
| 2582 Immediate Width(typeWidthInBytes(Ty)); | 2579 // sufficient space to do this. |
| 2583 Asm->sub(IceType_i32, | |
| 2584 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, | |
| 2585 Width); | |
| 2586 typename InstX86Base<Machine>::Traits::Address StackSlot = | 2580 typename InstX86Base<Machine>::Traits::Address StackSlot = |
| 2587 typename InstX86Base<Machine>::Traits::Address( | 2581 typename InstX86Base<Machine>::Traits::Address( |
| 2588 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0, | 2582 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0, |
| 2589 AssemblerFixup::NoFixup); | 2583 AssemblerFixup::NoFixup); |
| 2590 Asm->movss(Ty, StackSlot, | 2584 Asm->movss(Ty, StackSlot, |
| 2591 InstX86Base<Machine>::Traits::getEncodedXmm(Var->getRegNum())); | 2585 InstX86Base<Machine>::Traits::getEncodedXmm(Var->getRegNum())); |
| 2592 Asm->fld(Ty, StackSlot); | 2586 Asm->fld(Ty, StackSlot); |
| 2593 Asm->add(IceType_i32, | |
| 2594 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, | |
| 2595 Width); | |
| 2596 } else { | 2587 } else { |
| 2597 typename InstX86Base<Machine>::Traits::Address StackAddr( | 2588 typename InstX86Base<Machine>::Traits::Address StackAddr( |
| 2598 Target->stackVarToAsmOperand(Var)); | 2589 Target->stackVarToAsmOperand(Var)); |
| 2599 Asm->fld(Ty, StackAddr); | 2590 Asm->fld(Ty, StackAddr); |
| 2600 } | 2591 } |
| 2601 } else if (const auto *Mem = llvm::dyn_cast< | 2592 } else if (const auto *Mem = llvm::dyn_cast< |
| 2602 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) { | 2593 typename InstX86Base<Machine>::Traits::X86OperandMem>(Src)) { |
| 2603 assert(Mem->getSegmentRegister() == | 2594 assert(Mem->getSegmentRegister() == |
| 2604 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment); | 2595 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment); |
| 2605 Asm->fld(Ty, Mem->toAsmAddress(Asm, Target)); | 2596 Asm->fld(Ty, Mem->toAsmAddress(Asm, Target)); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2639 } | 2630 } |
| 2640 // Dest is a physical (xmm) register, so st(0) needs to go through memory. | 2631 // Dest is a physical (xmm) register, so st(0) needs to go through memory. |
| 2641 // Hack this by using caller-reserved memory at the top of stack, spilling | 2632 // Hack this by using caller-reserved memory at the top of stack, spilling |
| 2642 // st(0) there, and loading it into the xmm register. | 2633 // st(0) there, and loading it into the xmm register. |
| 2643 Str << "\tfstp" << this->getFldString(Ty) << "\t" | 2634 Str << "\tfstp" << this->getFldString(Ty) << "\t" |
| 2644 << "(%esp)\n"; | 2635 << "(%esp)\n"; |
| 2645 Str << "\tmov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString | 2636 Str << "\tmov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString |
| 2646 << "\t" | 2637 << "\t" |
| 2647 << "(%esp), "; | 2638 << "(%esp), "; |
| 2648 this->getDest()->emit(Func); | 2639 this->getDest()->emit(Func); |
| 2649 Str << "\n"; | |
| 2650 } | 2640 } |
| 2651 | 2641 |
| 2652 template <class Machine> | 2642 template <class Machine> |
| 2653 void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const { | 2643 void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const { |
| 2654 typename InstX86Base<Machine>::Traits::Assembler *Asm = | 2644 typename InstX86Base<Machine>::Traits::Assembler *Asm = |
| 2655 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); | 2645 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); |
| 2656 assert(this->getSrcSize() == 0); | 2646 assert(this->getSrcSize() == 0); |
| 2657 const Variable *Dest = this->getDest(); | 2647 const Variable *Dest = this->getDest(); |
| 2658 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to | 2648 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to |
| 2659 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused, | 2649 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused, |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3244 return; | 3234 return; |
| 3245 Ostream &Str = Func->getContext()->getStrDump(); | 3235 Ostream &Str = Func->getContext()->getStrDump(); |
| 3246 Str << "IACA_END"; | 3236 Str << "IACA_END"; |
| 3247 } | 3237 } |
| 3248 | 3238 |
| 3249 } // end of namespace X86Internal | 3239 } // end of namespace X86Internal |
| 3250 | 3240 |
| 3251 } // end of namespace Ice | 3241 } // end of namespace Ice |
| 3252 | 3242 |
| 3253 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H | 3243 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H |
| OLD | NEW |