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