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