xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceAssemblerX8632.h (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1 //===- subzero/src/IceAssemblerX8632.h - Assembler for x86-32 ---*- C++ -*-===//
2 //
3 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
4 // for details. All rights reserved. Use of this source code is governed by a
5 // BSD-style license that can be found in the LICENSE file.
6 //
7 // Modified by the Subzero authors.
8 //
9 //===----------------------------------------------------------------------===//
10 //
11 //                        The Subzero Code Generator
12 //
13 // This file is distributed under the University of Illinois Open Source
14 // License. See LICENSE.TXT for details.
15 //
16 //===----------------------------------------------------------------------===//
17 ///
18 /// \file
19 /// \brief Declares the Assembler class for X86-32.
20 ///
21 //===----------------------------------------------------------------------===//
22 
23 #ifndef SUBZERO_SRC_ICEASSEMBLERX8632_H
24 #define SUBZERO_SRC_ICEASSEMBLERX8632_H
25 
26 #include "IceAssembler.h"
27 #include "IceConditionCodesX86.h"
28 #include "IceDefs.h"
29 #include "IceOperand.h"
30 #include "IceRegistersX8632.h"
31 #include "IceTypes.h"
32 #include "IceUtils.h"
33 
34 namespace Ice {
35 namespace X8632 {
36 
37 using BrCond = CondX86::BrCond;
38 using CmppsCond = CondX86::CmppsCond;
39 using RegisterSet = ::Ice::RegX8632;
40 using GPRRegister = RegisterSet::GPRRegister;
41 using ByteRegister = RegisterSet::ByteRegister;
42 using XmmRegister = RegisterSet::XmmRegister;
43 
44 class X86OperandMem;
45 class VariableSplit;
46 class TargetX8632;
47 
48 constexpr FixupKind FK_PcRel = llvm::ELF::R_386_PC32;
49 constexpr FixupKind FK_Abs = llvm::ELF::R_386_32;
50 constexpr FixupKind FK_Gotoff = llvm::ELF::R_386_GOTOFF;
51 constexpr FixupKind FK_GotPC = llvm::ELF::R_386_GOTPC;
52 
53 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
54 
55 class AsmOperand {
56 public:
AsmOperand(const AsmOperand & other)57   AsmOperand(const AsmOperand &other)
58       : fixup_(other.fixup_), length_(other.length_) {
59     memmove(&encoding_[0], &other.encoding_[0], other.length_);
60   }
61 
62   AsmOperand &operator=(const AsmOperand &other) {
63     length_ = other.length_;
64     fixup_ = other.fixup_;
65     memmove(&encoding_[0], &other.encoding_[0], other.length_);
66     return *this;
67   }
68 
mod()69   uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
70 
rm()71   GPRRegister rm() const {
72     return static_cast<GPRRegister>(encoding_at(0) & 7);
73   }
74 
scale()75   ScaleFactor scale() const {
76     return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
77   }
78 
index()79   GPRRegister index() const {
80     return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
81   }
82 
base()83   GPRRegister base() const {
84     return static_cast<GPRRegister>(encoding_at(1) & 7);
85   }
86 
disp8()87   int8_t disp8() const {
88     assert(length_ >= 2);
89     return static_cast<int8_t>(encoding_[length_ - 1]);
90   }
91 
fixup()92   AssemblerFixup *fixup() const { return fixup_; }
93 
94 protected:
AsmOperand()95   AsmOperand()
96       : fixup_(nullptr), length_(0) {} // Needed by subclass AsmAddress.
97 
SetModRM(int mod,GPRRegister rm)98   void SetModRM(int mod, GPRRegister rm) {
99     assert((mod & ~3) == 0);
100     encoding_[0] = (mod << 6) | rm;
101     length_ = 1;
102   }
103 
SetSIB(ScaleFactor scale,GPRRegister index,GPRRegister base)104   void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
105     assert(length_ == 1);
106     assert((scale & ~3) == 0);
107     encoding_[1] = (scale << 6) | (index << 3) | base;
108     length_ = 2;
109   }
110 
SetDisp8(int8_t disp)111   void SetDisp8(int8_t disp) {
112     assert(length_ == 1 || length_ == 2);
113     encoding_[length_++] = static_cast<uint8_t>(disp);
114   }
115 
SetDisp32(int32_t disp)116   void SetDisp32(int32_t disp) {
117     assert(length_ == 1 || length_ == 2);
118     intptr_t disp_size = sizeof(disp);
119     memmove(&encoding_[length_], &disp, disp_size);
120     length_ += disp_size;
121   }
122 
SetFixup(AssemblerFixup * fixup)123   void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
124 
125 private:
126   AssemblerFixup *fixup_;
127   uint8_t encoding_[6];
128   uint8_t length_;
129 
AsmOperand(GPRRegister reg)130   explicit AsmOperand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
131 
132   /// Get the operand encoding byte at the given index.
encoding_at(intptr_t index)133   uint8_t encoding_at(intptr_t index) const {
134     assert(index >= 0 && index < length_);
135     return encoding_[index];
136   }
137 
138   /// Returns whether or not this operand is really the given register in
139   /// disguise. Used from the assembler to generate better encodings.
IsRegister(GPRRegister reg)140   bool IsRegister(GPRRegister reg) const {
141     return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
142            && ((encoding_[0] & 0x07) == reg); // Register codes match.
143   }
144 
145   friend class AssemblerX8632;
146 };
147 
148 class AsmAddress : public AsmOperand {
149   AsmAddress() = delete;
150 
151 public:
152   AsmAddress(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup = nullptr) {
153     SetBase(Base, Disp, Fixup);
154   }
155   AsmAddress(const Variable *Var, const TargetX8632 *Target);
156   AsmAddress(const X86OperandMem *Mem, Ice::Assembler *Asm,
157              const Ice::TargetLowering *Target);
158   AsmAddress(const VariableSplit *Split, const Cfg *Func);
159 
160   // Address into the constant pool.
AsmAddress(const Constant * Imm,Ice::Assembler * Asm)161   AsmAddress(const Constant *Imm, Ice::Assembler *Asm) {
162     AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
163     const RelocOffsetT Offset = 0;
164     SetAbsolute(Offset, Fixup);
165   }
166 
167 private:
AsmAddress(const AsmAddress & other)168   AsmAddress(const AsmAddress &other) : AsmOperand(other) {}
169 
170   AsmAddress &operator=(const AsmAddress &other) {
171     AsmOperand::operator=(other);
172     return *this;
173   }
174 
SetBase(GPRRegister Base,int32_t Disp,AssemblerFixup * Fixup)175   void SetBase(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
176     if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
177       SetModRM(0, Base);
178       if (Base == RegX8632::Encoded_Reg_esp)
179         SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
180     } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
181       SetModRM(1, Base);
182       if (Base == RegX8632::Encoded_Reg_esp)
183         SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
184       SetDisp8(Disp);
185     } else {
186       SetModRM(2, Base);
187       if (Base == RegX8632::Encoded_Reg_esp)
188         SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base);
189       SetDisp32(Disp);
190       if (Fixup)
191         SetFixup(Fixup);
192     }
193   }
194 
SetIndex(GPRRegister Index,ScaleFactor Scale,int32_t Disp,AssemblerFixup * Fixup)195   void SetIndex(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
196                 AssemblerFixup *Fixup) {
197     assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
198     SetModRM(0, RegX8632::Encoded_Reg_esp);
199     SetSIB(Scale, Index, RegX8632::Encoded_Reg_ebp);
200     SetDisp32(Disp);
201     if (Fixup)
202       SetFixup(Fixup);
203   }
204 
SetBaseIndex(GPRRegister Base,GPRRegister Index,ScaleFactor Scale,int32_t Disp,AssemblerFixup * Fixup)205   void SetBaseIndex(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
206                     int32_t Disp, AssemblerFixup *Fixup) {
207     assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
208     if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) {
209       SetModRM(0, RegX8632::Encoded_Reg_esp);
210       SetSIB(Scale, Index, Base);
211     } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
212       SetModRM(1, RegX8632::Encoded_Reg_esp);
213       SetSIB(Scale, Index, Base);
214       SetDisp8(Disp);
215     } else {
216       SetModRM(2, RegX8632::Encoded_Reg_esp);
217       SetSIB(Scale, Index, Base);
218       SetDisp32(Disp);
219       if (Fixup)
220         SetFixup(Fixup);
221     }
222   }
223 
224   /// Generate an absolute address expression on x86-32.
SetAbsolute(RelocOffsetT Offset,AssemblerFixup * Fixup)225   void SetAbsolute(RelocOffsetT Offset, AssemblerFixup *Fixup) {
226     SetModRM(0, RegX8632::Encoded_Reg_ebp);
227     // Use the Offset in the displacement for now. If we decide to process
228     // fixups later, we'll need to patch up the emitted displacement.
229     SetDisp32(Offset);
230     if (Fixup)
231       SetFixup(Fixup);
232   }
233 };
234 
235 class AssemblerX8632 : public ::Ice::Assembler {
236   AssemblerX8632(const AssemblerX8632 &) = delete;
237   AssemblerX8632 &operator=(const AssemblerX8632 &) = delete;
238 
239 protected:
AssemblerX8632()240   explicit AssemblerX8632() : Assembler(Asm_X8632) {}
241 
242 public:
243   static constexpr int MAX_NOP_SIZE = 8;
244 
classof(const Assembler * Asm)245   static bool classof(const Assembler *Asm) {
246     return Asm->getKind() == Asm_X8632;
247   }
248 
249   class Immediate {
250     Immediate(const Immediate &) = delete;
251     Immediate &operator=(const Immediate &) = delete;
252 
253   public:
Immediate(int32_t value)254     explicit Immediate(int32_t value) : value_(value) {}
255 
Immediate(AssemblerFixup * fixup)256     explicit Immediate(AssemblerFixup *fixup) : fixup_(fixup) {}
257 
value()258     int32_t value() const { return value_; }
fixup()259     AssemblerFixup *fixup() const { return fixup_; }
260 
is_int8()261     bool is_int8() const {
262       // We currently only allow 32-bit fixups, and they usually have value = 0,
263       // so if fixup_ != nullptr, it shouldn't be classified as int8/16.
264       return fixup_ == nullptr && Utils::IsInt(8, value_);
265     }
is_uint8()266     bool is_uint8() const {
267       return fixup_ == nullptr && Utils::IsUint(8, value_);
268     }
is_uint16()269     bool is_uint16() const {
270       return fixup_ == nullptr && Utils::IsUint(16, value_);
271     }
272 
273   private:
274     const int32_t value_ = 0;
275     AssemblerFixup *fixup_ = nullptr;
276   };
277 
278   /// X86 allows near and far jumps.
279   class Label final : public Ice::Label {
280     Label(const Label &) = delete;
281     Label &operator=(const Label &) = delete;
282 
283   public:
284     Label() = default;
285     ~Label() = default;
286 
finalCheck()287     void finalCheck() const override {
288       Ice::Label::finalCheck();
289       assert(!hasNear());
290     }
291 
292     /// Returns the position of an earlier branch instruction which assumes that
293     /// this label is "near", and bumps iterator to the next near position.
getNearPosition()294     intptr_t getNearPosition() {
295       assert(hasNear());
296       intptr_t Pos = UnresolvedNearPositions.back();
297       UnresolvedNearPositions.pop_back();
298       return Pos;
299     }
300 
hasNear()301     bool hasNear() const { return !UnresolvedNearPositions.empty(); }
isUnused()302     bool isUnused() const override {
303       return Ice::Label::isUnused() && !hasNear();
304     }
305 
306   private:
307     friend class AssemblerX8632;
308 
nearLinkTo(const Assembler & Asm,intptr_t position)309     void nearLinkTo(const Assembler &Asm, intptr_t position) {
310       if (Asm.getPreliminary())
311         return;
312       assert(!isBound());
313       UnresolvedNearPositions.push_back(position);
314     }
315 
316     llvm::SmallVector<intptr_t, 20> UnresolvedNearPositions;
317   };
318 
319 public:
320   ~AssemblerX8632() override;
321 
322   static const bool kNearJump = true;
323   static const bool kFarJump = false;
324 
325   void alignFunction() override;
326 
getBundleAlignLog2Bytes()327   SizeT getBundleAlignLog2Bytes() const override { return 5; }
328 
getAlignDirective()329   const char *getAlignDirective() const override { return ".p2align"; }
330 
getNonExecBundlePadding()331   llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
332     static const uint8_t Padding[] = {0xF4};
333     return llvm::ArrayRef<uint8_t>(Padding, 1);
334   }
335 
padWithNop(intptr_t Padding)336   void padWithNop(intptr_t Padding) override {
337     while (Padding > MAX_NOP_SIZE) {
338       nop(MAX_NOP_SIZE);
339       Padding -= MAX_NOP_SIZE;
340     }
341     if (Padding)
342       nop(Padding);
343   }
344 
345   Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override;
346   void bindCfgNodeLabel(const CfgNode *Node) override;
347   Label *getOrCreateCfgNodeLabel(SizeT Number);
348   Label *getOrCreateLocalLabel(SizeT Number);
349   void bindLocalLabel(SizeT Number);
350 
fixupIsPCRel(FixupKind Kind)351   bool fixupIsPCRel(FixupKind Kind) const override {
352     // Currently assuming this is the only PC-rel relocation type used.
353     // TODO(jpp): Traits.PcRelTypes.count(Kind) != 0
354     return Kind == FK_PcRel;
355   }
356 
357   // Operations to emit GPR instructions (and dispatch on operand type).
358   using TypedEmitGPR = void (AssemblerX8632::*)(Type, GPRRegister);
359   using TypedEmitAddr = void (AssemblerX8632::*)(Type, const AsmAddress &);
360   struct GPREmitterOneOp {
361     TypedEmitGPR Reg;
362     TypedEmitAddr Addr;
363   };
364 
365   using TypedEmitGPRGPR = void (AssemblerX8632::*)(Type, GPRRegister,
366                                                    GPRRegister);
367   using TypedEmitGPRAddr = void (AssemblerX8632::*)(Type, GPRRegister,
368                                                     const AsmAddress &);
369   using TypedEmitGPRImm = void (AssemblerX8632::*)(Type, GPRRegister,
370                                                    const Immediate &);
371   struct GPREmitterRegOp {
372     TypedEmitGPRGPR GPRGPR;
373     TypedEmitGPRAddr GPRAddr;
374     TypedEmitGPRImm GPRImm;
375   };
376 
377   struct GPREmitterShiftOp {
378     // Technically, Addr/GPR and Addr/Imm are also allowed, but */Addr are
379     // not. In practice, we always normalize the Dest to a Register first.
380     TypedEmitGPRGPR GPRGPR;
381     TypedEmitGPRImm GPRImm;
382   };
383 
384   using TypedEmitGPRGPRImm = void (AssemblerX8632::*)(Type, GPRRegister,
385                                                       GPRRegister,
386                                                       const Immediate &);
387   struct GPREmitterShiftD {
388     // Technically AddrGPR and AddrGPRImm are also allowed, but in practice we
389     // always normalize Dest to a Register first.
390     TypedEmitGPRGPR GPRGPR;
391     TypedEmitGPRGPRImm GPRGPRImm;
392   };
393 
394   using TypedEmitAddrGPR = void (AssemblerX8632::*)(Type, const AsmAddress &,
395                                                     GPRRegister);
396   using TypedEmitAddrImm = void (AssemblerX8632::*)(Type, const AsmAddress &,
397                                                     const Immediate &);
398   struct GPREmitterAddrOp {
399     TypedEmitAddrGPR AddrGPR;
400     TypedEmitAddrImm AddrImm;
401   };
402 
403   // Operations to emit XMM instructions (and dispatch on operand type).
404   using TypedEmitXmmXmm = void (AssemblerX8632::*)(Type, XmmRegister,
405                                                    XmmRegister);
406   using TypedEmitXmmAddr = void (AssemblerX8632::*)(Type, XmmRegister,
407                                                     const AsmAddress &);
408   struct XmmEmitterRegOp {
409     TypedEmitXmmXmm XmmXmm;
410     TypedEmitXmmAddr XmmAddr;
411   };
412 
413   using EmitXmmXmm = void (AssemblerX8632::*)(XmmRegister, XmmRegister);
414   using EmitXmmAddr = void (AssemblerX8632::*)(XmmRegister, const AsmAddress &);
415   using EmitAddrXmm = void (AssemblerX8632::*)(const AsmAddress &, XmmRegister);
416   struct XmmEmitterMovOps {
417     EmitXmmXmm XmmXmm;
418     EmitXmmAddr XmmAddr;
419     EmitAddrXmm AddrXmm;
420   };
421 
422   using TypedEmitXmmImm = void (AssemblerX8632::*)(Type, XmmRegister,
423                                                    const Immediate &);
424 
425   struct XmmEmitterShiftOp {
426     TypedEmitXmmXmm XmmXmm;
427     TypedEmitXmmAddr XmmAddr;
428     TypedEmitXmmImm XmmImm;
429   };
430 
431   // Cross Xmm/GPR cast instructions.
432   template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp {
433     using TypedEmitRegs = void (AssemblerX8632::*)(Type, DReg_t, Type, SReg_t);
434     using TypedEmitAddr = void (AssemblerX8632::*)(Type, DReg_t, Type,
435                                                    const AsmAddress &);
436 
437     TypedEmitRegs RegReg;
438     TypedEmitAddr RegAddr;
439   };
440 
441   // Three operand (potentially) cross Xmm/GPR instructions. The last operand
442   // must be an immediate.
443   template <typename DReg_t, typename SReg_t> struct ThreeOpImmEmitter {
444     using TypedEmitRegRegImm = void (AssemblerX8632::*)(Type, DReg_t, SReg_t,
445                                                         const Immediate &);
446     using TypedEmitRegAddrImm = void (AssemblerX8632::*)(Type, DReg_t,
447                                                          const AsmAddress &,
448                                                          const Immediate &);
449 
450     TypedEmitRegRegImm RegRegImm;
451     TypedEmitRegAddrImm RegAddrImm;
452   };
453 
454   /*
455    * Emit Machine Instructions.
456    */
457   void call(GPRRegister reg);
458   void call(const AsmAddress &address);
459   void call(const ConstantRelocatable *label); // not testable.
460   void call(const Immediate &abs_address);
461 
462   static const intptr_t kCallExternalLabelSize = 5;
463 
464   void pushl(GPRRegister reg);
465   void pushl(const Immediate &Imm);
466   void pushl(const ConstantRelocatable *Label);
467 
468   void popl(GPRRegister reg);
469   void popl(const AsmAddress &address);
470 
471   void pushal();
472   void popal();
473 
474   void setcc(BrCond condition, ByteRegister dst);
475   void setcc(BrCond condition, const AsmAddress &address);
476 
477   void mov(Type Ty, GPRRegister dst, const Immediate &src);
478   void mov(Type Ty, GPRRegister dst, GPRRegister src);
479   void mov(Type Ty, GPRRegister dst, const AsmAddress &src);
480   void mov(Type Ty, const AsmAddress &dst, GPRRegister src);
481   void mov(Type Ty, const AsmAddress &dst, const Immediate &imm);
482 
483   void movzx(Type Ty, GPRRegister dst, GPRRegister src);
484   void movzx(Type Ty, GPRRegister dst, const AsmAddress &src);
485   void movsx(Type Ty, GPRRegister dst, GPRRegister src);
486   void movsx(Type Ty, GPRRegister dst, const AsmAddress &src);
487 
488   void lea(Type Ty, GPRRegister dst, const AsmAddress &src);
489 
490   void cmov(Type Ty, BrCond cond, GPRRegister dst, GPRRegister src);
491   void cmov(Type Ty, BrCond cond, GPRRegister dst, const AsmAddress &src);
492 
493   void rep_movsb();
494 
495   void movss(Type Ty, XmmRegister dst, const AsmAddress &src);
496   void movss(Type Ty, const AsmAddress &dst, XmmRegister src);
497   void movss(Type Ty, XmmRegister dst, XmmRegister src);
498 
499   void movd(Type SrcTy, XmmRegister dst, GPRRegister src);
500   void movd(Type SrcTy, XmmRegister dst, const AsmAddress &src);
501   void movd(Type DestTy, GPRRegister dst, XmmRegister src);
502   void movd(Type DestTy, const AsmAddress &dst, XmmRegister src);
503 
504   void movq(XmmRegister dst, XmmRegister src);
505   void movq(const AsmAddress &dst, XmmRegister src);
506   void movq(XmmRegister dst, const AsmAddress &src);
507 
508   void addss(Type Ty, XmmRegister dst, XmmRegister src);
509   void addss(Type Ty, XmmRegister dst, const AsmAddress &src);
510   void subss(Type Ty, XmmRegister dst, XmmRegister src);
511   void subss(Type Ty, XmmRegister dst, const AsmAddress &src);
512   void mulss(Type Ty, XmmRegister dst, XmmRegister src);
513   void mulss(Type Ty, XmmRegister dst, const AsmAddress &src);
514   void divss(Type Ty, XmmRegister dst, XmmRegister src);
515   void divss(Type Ty, XmmRegister dst, const AsmAddress &src);
516 
517   void movaps(XmmRegister dst, XmmRegister src);
518 
519   void movups(XmmRegister dst, XmmRegister src);
520   void movups(XmmRegister dst, const AsmAddress &src);
521   void movups(const AsmAddress &dst, XmmRegister src);
522 
523   void padd(Type Ty, XmmRegister dst, XmmRegister src);
524   void padd(Type Ty, XmmRegister dst, const AsmAddress &src);
525   void padds(Type Ty, XmmRegister dst, XmmRegister src);
526   void padds(Type Ty, XmmRegister dst, const AsmAddress &src);
527   void paddus(Type Ty, XmmRegister dst, XmmRegister src);
528   void paddus(Type Ty, XmmRegister dst, const AsmAddress &src);
529   void pand(Type Ty, XmmRegister dst, XmmRegister src);
530   void pand(Type Ty, XmmRegister dst, const AsmAddress &src);
531   void pandn(Type Ty, XmmRegister dst, XmmRegister src);
532   void pandn(Type Ty, XmmRegister dst, const AsmAddress &src);
533   void pmull(Type Ty, XmmRegister dst, XmmRegister src);
534   void pmull(Type Ty, XmmRegister dst, const AsmAddress &src);
535   void pmulhw(Type Ty, XmmRegister dst, XmmRegister src);
536   void pmulhw(Type Ty, XmmRegister dst, const AsmAddress &src);
537   void pmulhuw(Type Ty, XmmRegister dst, XmmRegister src);
538   void pmulhuw(Type Ty, XmmRegister dst, const AsmAddress &src);
539   void pmaddwd(Type Ty, XmmRegister dst, XmmRegister src);
540   void pmaddwd(Type Ty, XmmRegister dst, const AsmAddress &src);
541   void pmuludq(Type Ty, XmmRegister dst, XmmRegister src);
542   void pmuludq(Type Ty, XmmRegister dst, const AsmAddress &src);
543   void por(Type Ty, XmmRegister dst, XmmRegister src);
544   void por(Type Ty, XmmRegister dst, const AsmAddress &src);
545   void psub(Type Ty, XmmRegister dst, XmmRegister src);
546   void psub(Type Ty, XmmRegister dst, const AsmAddress &src);
547   void psubs(Type Ty, XmmRegister dst, XmmRegister src);
548   void psubs(Type Ty, XmmRegister dst, const AsmAddress &src);
549   void psubus(Type Ty, XmmRegister dst, XmmRegister src);
550   void psubus(Type Ty, XmmRegister dst, const AsmAddress &src);
551   void pxor(Type Ty, XmmRegister dst, XmmRegister src);
552   void pxor(Type Ty, XmmRegister dst, const AsmAddress &src);
553 
554   void psll(Type Ty, XmmRegister dst, XmmRegister src);
555   void psll(Type Ty, XmmRegister dst, const AsmAddress &src);
556   void psll(Type Ty, XmmRegister dst, const Immediate &src);
557 
558   void psra(Type Ty, XmmRegister dst, XmmRegister src);
559   void psra(Type Ty, XmmRegister dst, const AsmAddress &src);
560   void psra(Type Ty, XmmRegister dst, const Immediate &src);
561   void psrl(Type Ty, XmmRegister dst, XmmRegister src);
562   void psrl(Type Ty, XmmRegister dst, const AsmAddress &src);
563   void psrl(Type Ty, XmmRegister dst, const Immediate &src);
564 
565   void addps(Type Ty, XmmRegister dst, XmmRegister src);
566   void addps(Type Ty, XmmRegister dst, const AsmAddress &src);
567   void subps(Type Ty, XmmRegister dst, XmmRegister src);
568   void subps(Type Ty, XmmRegister dst, const AsmAddress &src);
569   void divps(Type Ty, XmmRegister dst, XmmRegister src);
570   void divps(Type Ty, XmmRegister dst, const AsmAddress &src);
571   void mulps(Type Ty, XmmRegister dst, XmmRegister src);
572   void mulps(Type Ty, XmmRegister dst, const AsmAddress &src);
573   void minps(Type Ty, XmmRegister dst, const AsmAddress &src);
574   void minps(Type Ty, XmmRegister dst, XmmRegister src);
575   void minss(Type Ty, XmmRegister dst, const AsmAddress &src);
576   void minss(Type Ty, XmmRegister dst, XmmRegister src);
577   void maxps(Type Ty, XmmRegister dst, const AsmAddress &src);
578   void maxps(Type Ty, XmmRegister dst, XmmRegister src);
579   void maxss(Type Ty, XmmRegister dst, const AsmAddress &src);
580   void maxss(Type Ty, XmmRegister dst, XmmRegister src);
581   void andnps(Type Ty, XmmRegister dst, const AsmAddress &src);
582   void andnps(Type Ty, XmmRegister dst, XmmRegister src);
583   void andps(Type Ty, XmmRegister dst, const AsmAddress &src);
584   void andps(Type Ty, XmmRegister dst, XmmRegister src);
585   void orps(Type Ty, XmmRegister dst, const AsmAddress &src);
586   void orps(Type Ty, XmmRegister dst, XmmRegister src);
587 
588   void blendvps(Type Ty, XmmRegister dst, XmmRegister src);
589   void blendvps(Type Ty, XmmRegister dst, const AsmAddress &src);
590   void pblendvb(Type Ty, XmmRegister dst, XmmRegister src);
591   void pblendvb(Type Ty, XmmRegister dst, const AsmAddress &src);
592 
593   void cmpps(Type Ty, XmmRegister dst, XmmRegister src, CmppsCond CmpCondition);
594   void cmpps(Type Ty, XmmRegister dst, const AsmAddress &src,
595              CmppsCond CmpCondition);
596 
597   void sqrtps(XmmRegister dst);
598   void rsqrtps(XmmRegister dst);
599   void reciprocalps(XmmRegister dst);
600 
601   void movhlps(XmmRegister dst, XmmRegister src);
602   void movlhps(XmmRegister dst, XmmRegister src);
603   void unpcklps(XmmRegister dst, XmmRegister src);
604   void unpckhps(XmmRegister dst, XmmRegister src);
605   void unpcklpd(XmmRegister dst, XmmRegister src);
606   void unpckhpd(XmmRegister dst, XmmRegister src);
607 
608   void set1ps(XmmRegister dst, GPRRegister tmp, const Immediate &imm);
609 
610   void sqrtpd(XmmRegister dst);
611 
612   void pshufb(Type Ty, XmmRegister dst, XmmRegister src);
613   void pshufb(Type Ty, XmmRegister dst, const AsmAddress &src);
614   void pshufd(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mask);
615   void pshufd(Type Ty, XmmRegister dst, const AsmAddress &src,
616               const Immediate &mask);
617   void punpckl(Type Ty, XmmRegister Dst, XmmRegister Src);
618   void punpckl(Type Ty, XmmRegister Dst, const AsmAddress &Src);
619   void punpckh(Type Ty, XmmRegister Dst, XmmRegister Src);
620   void punpckh(Type Ty, XmmRegister Dst, const AsmAddress &Src);
621   void packss(Type Ty, XmmRegister Dst, XmmRegister Src);
622   void packss(Type Ty, XmmRegister Dst, const AsmAddress &Src);
623   void packus(Type Ty, XmmRegister Dst, XmmRegister Src);
624   void packus(Type Ty, XmmRegister Dst, const AsmAddress &Src);
625   void shufps(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mask);
626   void shufps(Type Ty, XmmRegister dst, const AsmAddress &src,
627               const Immediate &mask);
628 
629   void cvtdq2ps(Type, XmmRegister dst, XmmRegister src);
630   void cvtdq2ps(Type, XmmRegister dst, const AsmAddress &src);
631 
632   void cvttps2dq(Type, XmmRegister dst, XmmRegister src);
633   void cvttps2dq(Type, XmmRegister dst, const AsmAddress &src);
634 
635   void cvtps2dq(Type, XmmRegister dst, XmmRegister src);
636   void cvtps2dq(Type, XmmRegister dst, const AsmAddress &src);
637 
638   void cvtsi2ss(Type DestTy, XmmRegister dst, Type SrcTy, GPRRegister src);
639   void cvtsi2ss(Type DestTy, XmmRegister dst, Type SrcTy,
640                 const AsmAddress &src);
641 
642   void cvtfloat2float(Type SrcTy, XmmRegister dst, XmmRegister src);
643   void cvtfloat2float(Type SrcTy, XmmRegister dst, const AsmAddress &src);
644 
645   void cvttss2si(Type DestTy, GPRRegister dst, Type SrcTy, XmmRegister src);
646   void cvttss2si(Type DestTy, GPRRegister dst, Type SrcTy,
647                  const AsmAddress &src);
648 
649   void cvtss2si(Type DestTy, GPRRegister dst, Type SrcTy, XmmRegister src);
650   void cvtss2si(Type DestTy, GPRRegister dst, Type SrcTy,
651                 const AsmAddress &src);
652 
653   void ucomiss(Type Ty, XmmRegister a, XmmRegister b);
654   void ucomiss(Type Ty, XmmRegister a, const AsmAddress &b);
655 
656   void movmsk(Type Ty, GPRRegister dst, XmmRegister src);
657 
658   void sqrt(Type Ty, XmmRegister dst, const AsmAddress &src);
659   void sqrt(Type Ty, XmmRegister dst, XmmRegister src);
660 
661   void xorps(Type Ty, XmmRegister dst, const AsmAddress &src);
662   void xorps(Type Ty, XmmRegister dst, XmmRegister src);
663 
664   void insertps(Type Ty, XmmRegister dst, XmmRegister src,
665                 const Immediate &imm);
666   void insertps(Type Ty, XmmRegister dst, const AsmAddress &src,
667                 const Immediate &imm);
668 
669   void pinsr(Type Ty, XmmRegister dst, GPRRegister src, const Immediate &imm);
670   void pinsr(Type Ty, XmmRegister dst, const AsmAddress &src,
671              const Immediate &imm);
672 
673   void pextr(Type Ty, GPRRegister dst, XmmRegister src, const Immediate &imm);
674 
675   void pmovsxdq(XmmRegister dst, XmmRegister src);
676 
677   void pcmpeq(Type Ty, XmmRegister dst, XmmRegister src);
678   void pcmpeq(Type Ty, XmmRegister dst, const AsmAddress &src);
679   void pcmpgt(Type Ty, XmmRegister dst, XmmRegister src);
680   void pcmpgt(Type Ty, XmmRegister dst, const AsmAddress &src);
681 
682   enum RoundingMode {
683     kRoundToNearest = 0x0,
684     kRoundDown = 0x1,
685     kRoundUp = 0x2,
686     kRoundToZero = 0x3
687   };
688   void round(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mode);
689   void round(Type Ty, XmmRegister dst, const AsmAddress &src,
690              const Immediate &mode);
691 
692   //----------------------------------------------------------------------------
693   //
694   // Begin: X87 instructions.
695   //
696   //----------------------------------------------------------------------------
697   void fld(Type Ty, const AsmAddress &src);
698   void fstp(Type Ty, const AsmAddress &dst);
699   void fstp(RegX8632::X87STRegister st);
700 
701   void fnstcw(const AsmAddress &dst);
702   void fldcw(const AsmAddress &src);
703 
704   void fistpl(const AsmAddress &dst);
705   void fistps(const AsmAddress &dst);
706   void fildl(const AsmAddress &src);
707   void filds(const AsmAddress &src);
708 
709   void fincstp();
710   //----------------------------------------------------------------------------
711   //
712   // End: X87 instructions.
713   //
714   //----------------------------------------------------------------------------
715 
716   void cmp(Type Ty, GPRRegister reg0, GPRRegister reg1);
717   void cmp(Type Ty, GPRRegister reg, const AsmAddress &address);
718   void cmp(Type Ty, GPRRegister reg, const Immediate &imm);
719   void cmp(Type Ty, const AsmAddress &address, GPRRegister reg);
720   void cmp(Type Ty, const AsmAddress &address, const Immediate &imm);
721 
722   void test(Type Ty, GPRRegister reg0, GPRRegister reg1);
723   void test(Type Ty, GPRRegister reg, const Immediate &imm);
724   void test(Type Ty, const AsmAddress &address, GPRRegister reg);
725   void test(Type Ty, const AsmAddress &address, const Immediate &imm);
726 
727   void And(Type Ty, GPRRegister dst, GPRRegister src);
728   void And(Type Ty, GPRRegister dst, const AsmAddress &address);
729   void And(Type Ty, GPRRegister dst, const Immediate &imm);
730   void And(Type Ty, const AsmAddress &address, GPRRegister reg);
731   void And(Type Ty, const AsmAddress &address, const Immediate &imm);
732 
733   void Or(Type Ty, GPRRegister dst, GPRRegister src);
734   void Or(Type Ty, GPRRegister dst, const AsmAddress &address);
735   void Or(Type Ty, GPRRegister dst, const Immediate &imm);
736   void Or(Type Ty, const AsmAddress &address, GPRRegister reg);
737   void Or(Type Ty, const AsmAddress &address, const Immediate &imm);
738 
739   void Xor(Type Ty, GPRRegister dst, GPRRegister src);
740   void Xor(Type Ty, GPRRegister dst, const AsmAddress &address);
741   void Xor(Type Ty, GPRRegister dst, const Immediate &imm);
742   void Xor(Type Ty, const AsmAddress &address, GPRRegister reg);
743   void Xor(Type Ty, const AsmAddress &address, const Immediate &imm);
744 
745   void add(Type Ty, GPRRegister dst, GPRRegister src);
746   void add(Type Ty, GPRRegister reg, const AsmAddress &address);
747   void add(Type Ty, GPRRegister reg, const Immediate &imm);
748   void add(Type Ty, const AsmAddress &address, GPRRegister reg);
749   void add(Type Ty, const AsmAddress &address, const Immediate &imm);
750 
751   void adc(Type Ty, GPRRegister dst, GPRRegister src);
752   void adc(Type Ty, GPRRegister dst, const AsmAddress &address);
753   void adc(Type Ty, GPRRegister reg, const Immediate &imm);
754   void adc(Type Ty, const AsmAddress &address, GPRRegister reg);
755   void adc(Type Ty, const AsmAddress &address, const Immediate &imm);
756 
757   void sub(Type Ty, GPRRegister dst, GPRRegister src);
758   void sub(Type Ty, GPRRegister reg, const AsmAddress &address);
759   void sub(Type Ty, GPRRegister reg, const Immediate &imm);
760   void sub(Type Ty, const AsmAddress &address, GPRRegister reg);
761   void sub(Type Ty, const AsmAddress &address, const Immediate &imm);
762 
763   void sbb(Type Ty, GPRRegister dst, GPRRegister src);
764   void sbb(Type Ty, GPRRegister reg, const AsmAddress &address);
765   void sbb(Type Ty, GPRRegister reg, const Immediate &imm);
766   void sbb(Type Ty, const AsmAddress &address, GPRRegister reg);
767   void sbb(Type Ty, const AsmAddress &address, const Immediate &imm);
768 
769   void cbw();
770   void cwd();
771   void cdq();
772 
773   void div(Type Ty, GPRRegister reg);
774   void div(Type Ty, const AsmAddress &address);
775 
776   void idiv(Type Ty, GPRRegister reg);
777   void idiv(Type Ty, const AsmAddress &address);
778 
779   void imul(Type Ty, GPRRegister dst, GPRRegister src);
780   void imul(Type Ty, GPRRegister reg, const Immediate &imm);
781   void imul(Type Ty, GPRRegister reg, const AsmAddress &address);
782 
783   void imul(Type Ty, GPRRegister reg);
784   void imul(Type Ty, const AsmAddress &address);
785 
786   void imul(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
787   void imul(Type Ty, GPRRegister dst, const AsmAddress &address,
788             const Immediate &imm);
789 
790   void mul(Type Ty, GPRRegister reg);
791   void mul(Type Ty, const AsmAddress &address);
792 
793   void incl(GPRRegister reg);
794   void incl(const AsmAddress &address);
795 
796   void decl(GPRRegister reg);
797   void decl(const AsmAddress &address);
798 
799   void rol(Type Ty, GPRRegister reg, const Immediate &imm);
800   void rol(Type Ty, GPRRegister operand, GPRRegister shifter);
801   void rol(Type Ty, const AsmAddress &operand, GPRRegister shifter);
802 
803   void shl(Type Ty, GPRRegister reg, const Immediate &imm);
804   void shl(Type Ty, GPRRegister operand, GPRRegister shifter);
805   void shl(Type Ty, const AsmAddress &operand, GPRRegister shifter);
806 
807   void shr(Type Ty, GPRRegister reg, const Immediate &imm);
808   void shr(Type Ty, GPRRegister operand, GPRRegister shifter);
809   void shr(Type Ty, const AsmAddress &operand, GPRRegister shifter);
810 
811   void sar(Type Ty, GPRRegister reg, const Immediate &imm);
812   void sar(Type Ty, GPRRegister operand, GPRRegister shifter);
813   void sar(Type Ty, const AsmAddress &address, GPRRegister shifter);
814 
815   void shld(Type Ty, GPRRegister dst, GPRRegister src);
816   void shld(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
817   void shld(Type Ty, const AsmAddress &operand, GPRRegister src);
818   void shrd(Type Ty, GPRRegister dst, GPRRegister src);
819   void shrd(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
820   void shrd(Type Ty, const AsmAddress &dst, GPRRegister src);
821 
822   void neg(Type Ty, GPRRegister reg);
823   void neg(Type Ty, const AsmAddress &addr);
824   void notl(GPRRegister reg);
825 
826   void bsf(Type Ty, GPRRegister dst, GPRRegister src);
827   void bsf(Type Ty, GPRRegister dst, const AsmAddress &src);
828   void bsr(Type Ty, GPRRegister dst, GPRRegister src);
829   void bsr(Type Ty, GPRRegister dst, const AsmAddress &src);
830 
831   void bswap(Type Ty, GPRRegister reg);
832 
833   void bt(GPRRegister base, GPRRegister offset);
834 
835   void ret();
836   void ret(const Immediate &imm);
837 
838   // 'size' indicates size in bytes and must be in the range 1..8.
839   void nop(int size = 1);
840   void int3();
841   void hlt();
842   void ud2();
843 
844   // j(Label) is fully tested.
845   void j(BrCond condition, Label *label, bool near = kFarJump);
846   void j(BrCond condition, const ConstantRelocatable *label); // not testable.
847 
848   void jmp(GPRRegister reg);
849   void jmp(Label *label, bool near = kFarJump);
850   void jmp(const ConstantRelocatable *label); // not testable.
851   void jmp(const Immediate &abs_address);
852 
853   void mfence();
854 
855   void lock();
856   void cmpxchg(Type Ty, const AsmAddress &address, GPRRegister reg,
857                bool Locked);
858   void cmpxchg8b(const AsmAddress &address, bool Locked);
859   void xadd(Type Ty, const AsmAddress &address, GPRRegister reg, bool Locked);
860   void xchg(Type Ty, GPRRegister reg0, GPRRegister reg1);
861   void xchg(Type Ty, const AsmAddress &address, GPRRegister reg);
862 
863   /// \name Intel Architecture Code Analyzer markers.
864   /// @{
865   void iaca_start();
866   void iaca_end();
867   /// @}
868 
869   void emitSegmentOverride(uint8_t prefix);
870 
preferredLoopAlignment()871   intptr_t preferredLoopAlignment() { return 16; }
872   void align(intptr_t alignment, intptr_t offset);
873   void bind(Label *label);
874 
CodeSize()875   intptr_t CodeSize() const { return Buffer.size(); }
876 
877 protected:
878   inline void emitUint8(uint8_t value);
879 
880 private:
881   ENABLE_MAKE_UNIQUE;
882 
883   static constexpr Type RexTypeIrrelevant = IceType_i32;
884   static constexpr Type RexTypeForceRexW = IceType_i64;
885   static constexpr GPRRegister RexRegIrrelevant = GPRRegister::Encoded_Reg_eax;
886 
887   inline void emitInt16(int16_t value);
888   inline void emitInt32(int32_t value);
889   inline void emitRegisterOperand(int rm, int reg);
890   template <typename RegType, typename RmType>
891   inline void emitXmmRegisterOperand(RegType reg, RmType rm);
892   inline void emitOperandSizeOverride();
893 
894   void emitOperand(int rm, const AsmOperand &operand, RelocOffsetT Addend = 0);
895   void emitImmediate(Type ty, const Immediate &imm);
896   void emitComplexI8(int rm, const AsmOperand &operand,
897                      const Immediate &immediate);
898   void emitComplex(Type Ty, int rm, const AsmOperand &operand,
899                    const Immediate &immediate);
900   void emitLabel(Label *label, intptr_t instruction_size);
901   void emitLabelLink(Label *label);
902   void emitNearLabelLink(Label *label);
903 
904   void emitGenericShift(int rm, Type Ty, GPRRegister reg, const Immediate &imm);
905   void emitGenericShift(int rm, Type Ty, const AsmOperand &operand,
906                         GPRRegister shifter);
907 
908   using LabelVector = std::vector<Label *>;
909   // A vector of pool-allocated x86 labels for CFG nodes.
910   LabelVector CfgNodeLabels;
911   // A vector of pool-allocated x86 labels for Local labels.
912   LabelVector LocalLabels;
913 
914   Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
915 
916   // The arith_int() methods factor out the commonality between the encodings
917   // of add(), Or(), adc(), sbb(), And(), sub(), Xor(), and cmp(). The Tag
918   // parameter is statically asserted to be less than 8.
919   template <uint32_t Tag>
920   void arith_int(Type Ty, GPRRegister reg, const Immediate &imm);
921 
922   template <uint32_t Tag>
923   void arith_int(Type Ty, GPRRegister reg0, GPRRegister reg1);
924 
925   template <uint32_t Tag>
926   void arith_int(Type Ty, GPRRegister reg, const AsmAddress &address);
927 
928   template <uint32_t Tag>
929   void arith_int(Type Ty, const AsmAddress &address, GPRRegister reg);
930 
931   template <uint32_t Tag>
932   void arith_int(Type Ty, const AsmAddress &address, const Immediate &imm);
933 
934   // gprEncoding returns Reg encoding for operand emission.
gprEncoding(const RegType Reg)935   template <typename RegType> GPRRegister gprEncoding(const RegType Reg) {
936     return static_cast<GPRRegister>(Reg);
937   }
938 };
939 
emitUint8(uint8_t value)940 inline void AssemblerX8632::emitUint8(uint8_t value) {
941   Buffer.emit<uint8_t>(value);
942 }
943 
emitInt16(int16_t value)944 inline void AssemblerX8632::emitInt16(int16_t value) {
945   Buffer.emit<int16_t>(value);
946 }
947 
emitInt32(int32_t value)948 inline void AssemblerX8632::emitInt32(int32_t value) {
949   Buffer.emit<int32_t>(value);
950 }
951 
emitRegisterOperand(int reg,int rm)952 inline void AssemblerX8632::emitRegisterOperand(int reg, int rm) {
953   assert(reg >= 0 && reg < 8);
954   assert(rm >= 0 && rm < 8);
955   Buffer.emit<uint8_t>(0xC0 + (reg << 3) + rm);
956 }
957 
958 template <typename RegType, typename RmType>
emitXmmRegisterOperand(RegType reg,RmType rm)959 inline void AssemblerX8632::emitXmmRegisterOperand(RegType reg, RmType rm) {
960   emitRegisterOperand(gprEncoding(reg), gprEncoding(rm));
961 }
962 
emitOperandSizeOverride()963 inline void AssemblerX8632::emitOperandSizeOverride() { emitUint8(0x66); }
964 
965 using Label = AssemblerX8632::Label;
966 using Immediate = AssemblerX8632::Immediate;
967 
968 } // end of namespace X8632
969 } // end of namespace Ice
970 
971 #endif // SUBZERO_SRC_ICEASSEMBLERX8632_H
972