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