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