blob: 9fd9baee93b5833f44cf11bdba72914bc191d102 [file] [log] [blame]
John Porto5d0acff2015-06-30 15:29:21 -07001//===- subzero/src/IceAssemblerX86Base.h - base x86 assembler -*- 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//
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080018/// \file
19/// \brief Defines the AssemblerX86 template class for x86, the base of all X86
20/// assemblers.
John Porto5d0acff2015-06-30 15:29:21 -070021//
22//===----------------------------------------------------------------------===//
23
24#ifndef SUBZERO_SRC_ICEASSEMBLERX86BASE_H
25#define SUBZERO_SRC_ICEASSEMBLERX86BASE_H
26
27#include "IceAssembler.h"
28#include "IceDefs.h"
29#include "IceOperand.h"
30#include "IceTypes.h"
31#include "IceUtils.h"
32
33namespace Ice {
34
John Porto4a566862016-01-04 09:33:41 -080035#ifndef X86NAMESPACE
36#error "You must define the X86 Target namespace."
37#endif
John Porto5d0acff2015-06-30 15:29:21 -070038
John Porto4a566862016-01-04 09:33:41 -080039namespace X86NAMESPACE {
John Porto5d0acff2015-06-30 15:29:21 -070040
John Porto4a566862016-01-04 09:33:41 -080041template <typename TraitsType>
42class AssemblerX86Base : public ::Ice::Assembler {
John Porto5d0acff2015-06-30 15:29:21 -070043 AssemblerX86Base(const AssemblerX86Base &) = delete;
44 AssemblerX86Base &operator=(const AssemblerX86Base &) = delete;
45
46protected:
Nicolas Capens3db8f7a2016-09-01 11:04:46 -040047 explicit AssemblerX86Base(
48 bool EmitAddrSizeOverridePrefix = TraitsType::Is64Bit)
John Porto56958cb2016-01-14 09:18:18 -080049 : Assembler(Traits::AsmKind),
50 EmitAddrSizeOverridePrefix(EmitAddrSizeOverridePrefix) {
51 assert(Traits::Is64Bit || !EmitAddrSizeOverridePrefix);
John Porto5d0acff2015-06-30 15:29:21 -070052 }
53
54public:
John Porto4a566862016-01-04 09:33:41 -080055 using Traits = TraitsType;
56 using Address = typename Traits::Address;
57 using ByteRegister = typename Traits::ByteRegister;
58 using BrCond = typename Traits::Cond::BrCond;
59 using CmppsCond = typename Traits::Cond::CmppsCond;
60 using GPRRegister = typename Traits::GPRRegister;
61 using Operand = typename Traits::Operand;
62 using XmmRegister = typename Traits::XmmRegister;
John Porto5d0acff2015-06-30 15:29:21 -070063
John Porto4a566862016-01-04 09:33:41 -080064 static constexpr int MAX_NOP_SIZE = 8;
65
66 static bool classof(const Assembler *Asm) {
67 return Asm->getKind() == Traits::AsmKind;
68 }
69
70 class Immediate {
71 Immediate(const Immediate &) = delete;
72 Immediate &operator=(const Immediate &) = delete;
73
74 public:
75 explicit Immediate(int32_t value) : value_(value) {}
76
John Porto6e8d3fa2016-02-04 10:35:20 -080077 explicit Immediate(AssemblerFixup *fixup) : fixup_(fixup) {}
John Porto4a566862016-01-04 09:33:41 -080078
79 int32_t value() const { return value_; }
80 AssemblerFixup *fixup() const { return fixup_; }
81
82 bool is_int8() const {
83 // We currently only allow 32-bit fixups, and they usually have value = 0,
84 // so if fixup_ != nullptr, it shouldn't be classified as int8/16.
85 return fixup_ == nullptr && Utils::IsInt(8, value_);
86 }
87 bool is_uint8() const {
88 return fixup_ == nullptr && Utils::IsUint(8, value_);
89 }
90 bool is_uint16() const {
91 return fixup_ == nullptr && Utils::IsUint(16, value_);
92 }
93
94 private:
John Porto6e8d3fa2016-02-04 10:35:20 -080095 const int32_t value_ = 0;
John Porto4a566862016-01-04 09:33:41 -080096 AssemblerFixup *fixup_ = nullptr;
97 };
98
99 /// X86 allows near and far jumps.
100 class Label final : public Ice::Label {
101 Label(const Label &) = delete;
102 Label &operator=(const Label &) = delete;
103
104 public:
105 Label() = default;
106 ~Label() = default;
107
108 void finalCheck() const override {
109 Ice::Label::finalCheck();
110 assert(!hasNear());
111 }
112
113 /// Returns the position of an earlier branch instruction which assumes that
114 /// this label is "near", and bumps iterator to the next near position.
115 intptr_t getNearPosition() {
116 assert(hasNear());
117 intptr_t Pos = UnresolvedNearPositions.back();
118 UnresolvedNearPositions.pop_back();
119 return Pos;
120 }
121
122 bool hasNear() const { return !UnresolvedNearPositions.empty(); }
123 bool isUnused() const override {
124 return Ice::Label::isUnused() && !hasNear();
125 }
126
127 private:
128 friend class AssemblerX86Base<TraitsType>;
129
130 void nearLinkTo(const Assembler &Asm, intptr_t position) {
131 if (Asm.getPreliminary())
132 return;
133 assert(!isBound());
134 UnresolvedNearPositions.push_back(position);
135 }
136
137 llvm::SmallVector<intptr_t, 20> UnresolvedNearPositions;
138 };
139
140public:
John Porto5d0acff2015-06-30 15:29:21 -0700141 ~AssemblerX86Base() override;
142
143 static const bool kNearJump = true;
144 static const bool kFarJump = false;
145
146 void alignFunction() override;
147
148 SizeT getBundleAlignLog2Bytes() const override { return 5; }
149
Andrew Scull86df4e92015-07-30 13:54:44 -0700150 const char *getAlignDirective() const override { return ".p2align"; }
John Porto5d0acff2015-06-30 15:29:21 -0700151
152 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
153 static const uint8_t Padding[] = {0xF4};
154 return llvm::ArrayRef<uint8_t>(Padding, 1);
155 }
156
157 void padWithNop(intptr_t Padding) override {
158 while (Padding > MAX_NOP_SIZE) {
159 nop(MAX_NOP_SIZE);
160 Padding -= MAX_NOP_SIZE;
161 }
162 if (Padding)
163 nop(Padding);
164 }
165
Jan Voungc2ec5812015-08-05 09:35:18 -0700166 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override;
Karl Schimpf50a33312015-10-23 09:19:48 -0700167 void bindCfgNodeLabel(const CfgNode *Node) override;
Jan Voungc2ec5812015-08-05 09:35:18 -0700168 Label *getOrCreateCfgNodeLabel(SizeT Number);
Andrew Scull86df4e92015-07-30 13:54:44 -0700169 Label *getOrCreateLocalLabel(SizeT Number);
170 void bindLocalLabel(SizeT Number);
John Porto5d0acff2015-06-30 15:29:21 -0700171
172 bool fixupIsPCRel(FixupKind Kind) const override {
173 // Currently assuming this is the only PC-rel relocation type used.
174 // TODO(jpp): Traits.PcRelTypes.count(Kind) != 0
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800175 return Kind == Traits::FK_PcRel;
John Porto5d0acff2015-06-30 15:29:21 -0700176 }
177
178 // Operations to emit GPR instructions (and dispatch on operand type).
John Porto4a566862016-01-04 09:33:41 -0800179 using TypedEmitGPR = void (AssemblerX86Base::*)(Type, GPRRegister);
180 using TypedEmitAddr = void (AssemblerX86Base::*)(Type, const Address &);
John Porto5d0acff2015-06-30 15:29:21 -0700181 struct GPREmitterOneOp {
182 TypedEmitGPR Reg;
183 TypedEmitAddr Addr;
184 };
185
John Porto4a566862016-01-04 09:33:41 -0800186 using TypedEmitGPRGPR = void (AssemblerX86Base::*)(Type, GPRRegister,
187 GPRRegister);
188 using TypedEmitGPRAddr = void (AssemblerX86Base::*)(Type, GPRRegister,
189 const Address &);
190 using TypedEmitGPRImm = void (AssemblerX86Base::*)(Type, GPRRegister,
191 const Immediate &);
John Porto5d0acff2015-06-30 15:29:21 -0700192 struct GPREmitterRegOp {
193 TypedEmitGPRGPR GPRGPR;
194 TypedEmitGPRAddr GPRAddr;
195 TypedEmitGPRImm GPRImm;
196 };
197
198 struct GPREmitterShiftOp {
John Porto4a566862016-01-04 09:33:41 -0800199 // Technically, Addr/GPR and Addr/Imm are also allowed, but */Addr are
200 // not. In practice, we always normalize the Dest to a Register first.
John Porto5d0acff2015-06-30 15:29:21 -0700201 TypedEmitGPRGPR GPRGPR;
202 TypedEmitGPRImm GPRImm;
203 };
204
John Porto4a566862016-01-04 09:33:41 -0800205 using TypedEmitGPRGPRImm = void (AssemblerX86Base::*)(Type, GPRRegister,
206 GPRRegister,
207 const Immediate &);
John Porto5d0acff2015-06-30 15:29:21 -0700208 struct GPREmitterShiftD {
Andrew Scull57e12682015-09-16 11:30:19 -0700209 // Technically AddrGPR and AddrGPRImm are also allowed, but in practice we
210 // always normalize Dest to a Register first.
John Porto5d0acff2015-06-30 15:29:21 -0700211 TypedEmitGPRGPR GPRGPR;
212 TypedEmitGPRGPRImm GPRGPRImm;
213 };
214
John Porto4a566862016-01-04 09:33:41 -0800215 using TypedEmitAddrGPR = void (AssemblerX86Base::*)(Type, const Address &,
216 GPRRegister);
217 using TypedEmitAddrImm = void (AssemblerX86Base::*)(Type, const Address &,
218 const Immediate &);
John Porto5d0acff2015-06-30 15:29:21 -0700219 struct GPREmitterAddrOp {
220 TypedEmitAddrGPR AddrGPR;
221 TypedEmitAddrImm AddrImm;
222 };
223
224 // Operations to emit XMM instructions (and dispatch on operand type).
John Porto4a566862016-01-04 09:33:41 -0800225 using TypedEmitXmmXmm = void (AssemblerX86Base::*)(Type, XmmRegister,
226 XmmRegister);
227 using TypedEmitXmmAddr = void (AssemblerX86Base::*)(Type, XmmRegister,
228 const Address &);
John Porto5d0acff2015-06-30 15:29:21 -0700229 struct XmmEmitterRegOp {
230 TypedEmitXmmXmm XmmXmm;
231 TypedEmitXmmAddr XmmAddr;
232 };
233
John Porto4a566862016-01-04 09:33:41 -0800234 using EmitXmmXmm = void (AssemblerX86Base::*)(XmmRegister, XmmRegister);
235 using EmitXmmAddr = void (AssemblerX86Base::*)(XmmRegister, const Address &);
236 using EmitAddrXmm = void (AssemblerX86Base::*)(const Address &, XmmRegister);
John Porto5d0acff2015-06-30 15:29:21 -0700237 struct XmmEmitterMovOps {
238 EmitXmmXmm XmmXmm;
239 EmitXmmAddr XmmAddr;
240 EmitAddrXmm AddrXmm;
241 };
242
John Porto4a566862016-01-04 09:33:41 -0800243 using TypedEmitXmmImm = void (AssemblerX86Base::*)(Type, XmmRegister,
244 const Immediate &);
John Porto5d0acff2015-06-30 15:29:21 -0700245
246 struct XmmEmitterShiftOp {
247 TypedEmitXmmXmm XmmXmm;
248 TypedEmitXmmAddr XmmAddr;
249 TypedEmitXmmImm XmmImm;
250 };
251
252 // Cross Xmm/GPR cast instructions.
253 template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp {
Andrew Scull8072bae2015-09-14 16:01:26 -0700254 using TypedEmitRegs = void (AssemblerX86Base::*)(Type, DReg_t, Type,
255 SReg_t);
John Porto4a566862016-01-04 09:33:41 -0800256 using TypedEmitAddr = void (AssemblerX86Base::*)(Type, DReg_t, Type,
257 const Address &);
John Porto5d0acff2015-06-30 15:29:21 -0700258
259 TypedEmitRegs RegReg;
260 TypedEmitAddr RegAddr;
261 };
262
Andrew Scull57e12682015-09-16 11:30:19 -0700263 // Three operand (potentially) cross Xmm/GPR instructions. The last operand
264 // must be an immediate.
John Porto5d0acff2015-06-30 15:29:21 -0700265 template <typename DReg_t, typename SReg_t> struct ThreeOpImmEmitter {
Andrew Scull8072bae2015-09-14 16:01:26 -0700266 using TypedEmitRegRegImm = void (AssemblerX86Base::*)(Type, DReg_t, SReg_t,
267 const Immediate &);
John Porto4a566862016-01-04 09:33:41 -0800268 using TypedEmitRegAddrImm = void (AssemblerX86Base::*)(Type, DReg_t,
269 const Address &,
270 const Immediate &);
John Porto5d0acff2015-06-30 15:29:21 -0700271
272 TypedEmitRegRegImm RegRegImm;
273 TypedEmitRegAddrImm RegAddrImm;
274 };
275
276 /*
277 * Emit Machine Instructions.
278 */
John Porto4a566862016-01-04 09:33:41 -0800279 void call(GPRRegister reg);
280 void call(const Address &address);
John Porto2fea26c2015-07-28 16:28:07 -0700281 void call(const ConstantRelocatable *label); // not testable.
John Porto5d0acff2015-06-30 15:29:21 -0700282 void call(const Immediate &abs_address);
283
284 static const intptr_t kCallExternalLabelSize = 5;
285
John Porto4a566862016-01-04 09:33:41 -0800286 void pushl(GPRRegister reg);
John Porto56958cb2016-01-14 09:18:18 -0800287 void pushl(const Immediate &Imm);
288 void pushl(const ConstantRelocatable *Label);
John Porto5d0acff2015-06-30 15:29:21 -0700289
John Porto4a566862016-01-04 09:33:41 -0800290 void popl(GPRRegister reg);
291 void popl(const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700292
John Porto2fea26c2015-07-28 16:28:07 -0700293 template <typename T = Traits,
294 typename = typename std::enable_if<T::HasPusha>::type>
John Porto5d0acff2015-06-30 15:29:21 -0700295 void pushal();
John Porto2fea26c2015-07-28 16:28:07 -0700296 template <typename T = Traits,
297 typename = typename std::enable_if<T::HasPopa>::type>
John Porto5d0acff2015-06-30 15:29:21 -0700298 void popal();
299
John Porto4a566862016-01-04 09:33:41 -0800300 void setcc(BrCond condition, ByteRegister dst);
301 void setcc(BrCond condition, const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700302
John Porto4a566862016-01-04 09:33:41 -0800303 void mov(Type Ty, GPRRegister dst, const Immediate &src);
304 void mov(Type Ty, GPRRegister dst, GPRRegister src);
305 void mov(Type Ty, GPRRegister dst, const Address &src);
306 void mov(Type Ty, const Address &dst, GPRRegister src);
307 void mov(Type Ty, const Address &dst, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700308
John Porto1d235422015-08-12 12:37:53 -0700309 template <typename T = Traits>
John Porto4a566862016-01-04 09:33:41 -0800310 typename std::enable_if<T::Is64Bit, void>::type movabs(const GPRRegister Dst,
311 uint64_t Imm64);
John Porto1d235422015-08-12 12:37:53 -0700312 template <typename T = Traits>
John Porto4a566862016-01-04 09:33:41 -0800313 typename std::enable_if<!T::Is64Bit, void>::type movabs(const GPRRegister,
314 uint64_t) {
John Porto1d235422015-08-12 12:37:53 -0700315 llvm::report_fatal_error("movabs is only supported in 64-bit x86 targets.");
316 }
John Porto2fea26c2015-07-28 16:28:07 -0700317
John Porto4a566862016-01-04 09:33:41 -0800318 void movzx(Type Ty, GPRRegister dst, GPRRegister src);
319 void movzx(Type Ty, GPRRegister dst, const Address &src);
320 void movsx(Type Ty, GPRRegister dst, GPRRegister src);
321 void movsx(Type Ty, GPRRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700322
John Porto4a566862016-01-04 09:33:41 -0800323 void lea(Type Ty, GPRRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700324
John Porto4a566862016-01-04 09:33:41 -0800325 void cmov(Type Ty, BrCond cond, GPRRegister dst, GPRRegister src);
326 void cmov(Type Ty, BrCond cond, GPRRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700327
328 void rep_movsb();
329
John Porto4a566862016-01-04 09:33:41 -0800330 void movss(Type Ty, XmmRegister dst, const Address &src);
331 void movss(Type Ty, const Address &dst, XmmRegister src);
332 void movss(Type Ty, XmmRegister dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700333
John Porto4a566862016-01-04 09:33:41 -0800334 void movd(Type SrcTy, XmmRegister dst, GPRRegister src);
335 void movd(Type SrcTy, XmmRegister dst, const Address &src);
336 void movd(Type DestTy, GPRRegister dst, XmmRegister src);
337 void movd(Type DestTy, const Address &dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700338
John Porto4a566862016-01-04 09:33:41 -0800339 void movq(XmmRegister dst, XmmRegister src);
340 void movq(const Address &dst, XmmRegister src);
341 void movq(XmmRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700342
John Porto4a566862016-01-04 09:33:41 -0800343 void addss(Type Ty, XmmRegister dst, XmmRegister src);
344 void addss(Type Ty, XmmRegister dst, const Address &src);
345 void subss(Type Ty, XmmRegister dst, XmmRegister src);
346 void subss(Type Ty, XmmRegister dst, const Address &src);
347 void mulss(Type Ty, XmmRegister dst, XmmRegister src);
348 void mulss(Type Ty, XmmRegister dst, const Address &src);
349 void divss(Type Ty, XmmRegister dst, XmmRegister src);
350 void divss(Type Ty, XmmRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700351
John Porto4a566862016-01-04 09:33:41 -0800352 void movaps(XmmRegister dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700353
John Porto4a566862016-01-04 09:33:41 -0800354 void movups(XmmRegister dst, XmmRegister src);
355 void movups(XmmRegister dst, const Address &src);
356 void movups(const Address &dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700357
John Porto4a566862016-01-04 09:33:41 -0800358 void padd(Type Ty, XmmRegister dst, XmmRegister src);
359 void padd(Type Ty, XmmRegister dst, const Address &src);
Nicolas Capens67a49b52016-10-26 13:18:35 -0400360 void padds(Type Ty, XmmRegister dst, XmmRegister src);
361 void padds(Type Ty, XmmRegister dst, const Address &src);
362 void paddus(Type Ty, XmmRegister dst, XmmRegister src);
363 void paddus(Type Ty, XmmRegister dst, const Address &src);
John Porto4a566862016-01-04 09:33:41 -0800364 void pand(Type Ty, XmmRegister dst, XmmRegister src);
365 void pand(Type Ty, XmmRegister dst, const Address &src);
366 void pandn(Type Ty, XmmRegister dst, XmmRegister src);
367 void pandn(Type Ty, XmmRegister dst, const Address &src);
368 void pmull(Type Ty, XmmRegister dst, XmmRegister src);
369 void pmull(Type Ty, XmmRegister dst, const Address &src);
Nicolas Capens13cde0f2016-10-26 10:36:11 -0400370 void pmulhw(Type Ty, XmmRegister dst, XmmRegister src);
371 void pmulhw(Type Ty, XmmRegister dst, const Address &src);
372 void pmulhuw(Type Ty, XmmRegister dst, XmmRegister src);
373 void pmulhuw(Type Ty, XmmRegister dst, const Address &src);
374 void pmaddwd(Type Ty, XmmRegister dst, XmmRegister src);
375 void pmaddwd(Type Ty, XmmRegister dst, const Address &src);
John Porto4a566862016-01-04 09:33:41 -0800376 void pmuludq(Type Ty, XmmRegister dst, XmmRegister src);
377 void pmuludq(Type Ty, XmmRegister dst, const Address &src);
378 void por(Type Ty, XmmRegister dst, XmmRegister src);
379 void por(Type Ty, XmmRegister dst, const Address &src);
380 void psub(Type Ty, XmmRegister dst, XmmRegister src);
381 void psub(Type Ty, XmmRegister dst, const Address &src);
Nicolas Capens67a49b52016-10-26 13:18:35 -0400382 void psubs(Type Ty, XmmRegister dst, XmmRegister src);
383 void psubs(Type Ty, XmmRegister dst, const Address &src);
384 void psubus(Type Ty, XmmRegister dst, XmmRegister src);
385 void psubus(Type Ty, XmmRegister dst, const Address &src);
John Porto4a566862016-01-04 09:33:41 -0800386 void pxor(Type Ty, XmmRegister dst, XmmRegister src);
387 void pxor(Type Ty, XmmRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700388
John Porto4a566862016-01-04 09:33:41 -0800389 void psll(Type Ty, XmmRegister dst, XmmRegister src);
390 void psll(Type Ty, XmmRegister dst, const Address &src);
391 void psll(Type Ty, XmmRegister dst, const Immediate &src);
John Porto5d0acff2015-06-30 15:29:21 -0700392
John Porto4a566862016-01-04 09:33:41 -0800393 void psra(Type Ty, XmmRegister dst, XmmRegister src);
394 void psra(Type Ty, XmmRegister dst, const Address &src);
395 void psra(Type Ty, XmmRegister dst, const Immediate &src);
396 void psrl(Type Ty, XmmRegister dst, XmmRegister src);
397 void psrl(Type Ty, XmmRegister dst, const Address &src);
398 void psrl(Type Ty, XmmRegister dst, const Immediate &src);
John Porto5d0acff2015-06-30 15:29:21 -0700399
John Porto4a566862016-01-04 09:33:41 -0800400 void addps(Type Ty, XmmRegister dst, XmmRegister src);
401 void addps(Type Ty, XmmRegister dst, const Address &src);
402 void subps(Type Ty, XmmRegister dst, XmmRegister src);
403 void subps(Type Ty, XmmRegister dst, const Address &src);
404 void divps(Type Ty, XmmRegister dst, XmmRegister src);
405 void divps(Type Ty, XmmRegister dst, const Address &src);
406 void mulps(Type Ty, XmmRegister dst, XmmRegister src);
407 void mulps(Type Ty, XmmRegister dst, const Address &src);
408 void minps(Type Ty, XmmRegister dst, const Address &src);
409 void minps(Type Ty, XmmRegister dst, XmmRegister src);
410 void minss(Type Ty, XmmRegister dst, const Address &src);
411 void minss(Type Ty, XmmRegister dst, XmmRegister src);
412 void maxps(Type Ty, XmmRegister dst, const Address &src);
413 void maxps(Type Ty, XmmRegister dst, XmmRegister src);
414 void maxss(Type Ty, XmmRegister dst, const Address &src);
415 void maxss(Type Ty, XmmRegister dst, XmmRegister src);
416 void andnps(Type Ty, XmmRegister dst, const Address &src);
417 void andnps(Type Ty, XmmRegister dst, XmmRegister src);
418 void andps(Type Ty, XmmRegister dst, const Address &src);
419 void andps(Type Ty, XmmRegister dst, XmmRegister src);
420 void orps(Type Ty, XmmRegister dst, const Address &src);
421 void orps(Type Ty, XmmRegister dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700422
John Porto4a566862016-01-04 09:33:41 -0800423 void blendvps(Type Ty, XmmRegister dst, XmmRegister src);
424 void blendvps(Type Ty, XmmRegister dst, const Address &src);
425 void pblendvb(Type Ty, XmmRegister dst, XmmRegister src);
426 void pblendvb(Type Ty, XmmRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700427
John Porto4a566862016-01-04 09:33:41 -0800428 void cmpps(Type Ty, XmmRegister dst, XmmRegister src, CmppsCond CmpCondition);
429 void cmpps(Type Ty, XmmRegister dst, const Address &src,
430 CmppsCond CmpCondition);
John Porto5d0acff2015-06-30 15:29:21 -0700431
John Porto4a566862016-01-04 09:33:41 -0800432 void sqrtps(XmmRegister dst);
433 void rsqrtps(XmmRegister dst);
434 void reciprocalps(XmmRegister dst);
John Porto2fea26c2015-07-28 16:28:07 -0700435
John Porto4a566862016-01-04 09:33:41 -0800436 void movhlps(XmmRegister dst, XmmRegister src);
437 void movlhps(XmmRegister dst, XmmRegister src);
438 void unpcklps(XmmRegister dst, XmmRegister src);
439 void unpckhps(XmmRegister dst, XmmRegister src);
440 void unpcklpd(XmmRegister dst, XmmRegister src);
441 void unpckhpd(XmmRegister dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700442
John Porto4a566862016-01-04 09:33:41 -0800443 void set1ps(XmmRegister dst, GPRRegister tmp, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700444
John Porto4a566862016-01-04 09:33:41 -0800445 void sqrtpd(XmmRegister dst);
John Porto5d0acff2015-06-30 15:29:21 -0700446
John Portode29f122016-04-26 19:16:07 -0700447 void pshufb(Type Ty, XmmRegister dst, XmmRegister src);
448 void pshufb(Type Ty, XmmRegister dst, const Address &src);
John Porto4a566862016-01-04 09:33:41 -0800449 void pshufd(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mask);
450 void pshufd(Type Ty, XmmRegister dst, const Address &src,
451 const Immediate &mask);
Nicolas Capens71c69372016-10-04 00:07:21 -0400452 void punpckl(Type Ty, XmmRegister Dst, XmmRegister Src);
453 void punpckl(Type Ty, XmmRegister Dst, const Address &Src);
Nicolas Capens1448d952016-10-14 16:37:09 -0400454 void punpckh(Type Ty, XmmRegister Dst, XmmRegister Src);
455 void punpckh(Type Ty, XmmRegister Dst, const Address &Src);
Nicolas Capens7638e272016-10-06 11:33:55 -0400456 void packss(Type Ty, XmmRegister Dst, XmmRegister Src);
457 void packss(Type Ty, XmmRegister Dst, const Address &Src);
458 void packus(Type Ty, XmmRegister Dst, XmmRegister Src);
459 void packus(Type Ty, XmmRegister Dst, const Address &Src);
John Porto4a566862016-01-04 09:33:41 -0800460 void shufps(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mask);
461 void shufps(Type Ty, XmmRegister dst, const Address &src,
462 const Immediate &mask);
John Porto5d0acff2015-06-30 15:29:21 -0700463
John Porto4a566862016-01-04 09:33:41 -0800464 void cvtdq2ps(Type, XmmRegister dst, XmmRegister src);
465 void cvtdq2ps(Type, XmmRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700466
John Porto4a566862016-01-04 09:33:41 -0800467 void cvttps2dq(Type, XmmRegister dst, XmmRegister src);
468 void cvttps2dq(Type, XmmRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700469
Nicolas Capensdbf81e02017-01-14 12:53:55 -0500470 void cvtps2dq(Type, XmmRegister dst, XmmRegister src);
471 void cvtps2dq(Type, XmmRegister dst, const Address &src);
472
John Porto4a566862016-01-04 09:33:41 -0800473 void cvtsi2ss(Type DestTy, XmmRegister dst, Type SrcTy, GPRRegister src);
474 void cvtsi2ss(Type DestTy, XmmRegister dst, Type SrcTy, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700475
John Porto4a566862016-01-04 09:33:41 -0800476 void cvtfloat2float(Type SrcTy, XmmRegister dst, XmmRegister src);
477 void cvtfloat2float(Type SrcTy, XmmRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700478
John Porto4a566862016-01-04 09:33:41 -0800479 void cvttss2si(Type DestTy, GPRRegister dst, Type SrcTy, XmmRegister src);
480 void cvttss2si(Type DestTy, GPRRegister dst, Type SrcTy, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700481
Nicolas Capensdbf81e02017-01-14 12:53:55 -0500482 void cvtss2si(Type DestTy, GPRRegister dst, Type SrcTy, XmmRegister src);
483 void cvtss2si(Type DestTy, GPRRegister dst, Type SrcTy, const Address &src);
484
John Porto4a566862016-01-04 09:33:41 -0800485 void ucomiss(Type Ty, XmmRegister a, XmmRegister b);
486 void ucomiss(Type Ty, XmmRegister a, const Address &b);
John Porto5d0acff2015-06-30 15:29:21 -0700487
Nicolas Capense3cabda2016-10-18 16:27:27 -0400488 void movmsk(Type Ty, GPRRegister dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700489
Nicolas Capens956cfd62016-10-31 14:28:09 -0400490 void sqrt(Type Ty, XmmRegister dst, const Address &src);
491 void sqrt(Type Ty, XmmRegister dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700492
John Porto4a566862016-01-04 09:33:41 -0800493 void xorps(Type Ty, XmmRegister dst, const Address &src);
494 void xorps(Type Ty, XmmRegister dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700495
John Porto4a566862016-01-04 09:33:41 -0800496 void insertps(Type Ty, XmmRegister dst, XmmRegister src,
497 const Immediate &imm);
498 void insertps(Type Ty, XmmRegister dst, const Address &src,
499 const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700500
John Porto4a566862016-01-04 09:33:41 -0800501 void pinsr(Type Ty, XmmRegister dst, GPRRegister src, const Immediate &imm);
502 void pinsr(Type Ty, XmmRegister dst, const Address &src,
503 const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700504
John Porto4a566862016-01-04 09:33:41 -0800505 void pextr(Type Ty, GPRRegister dst, XmmRegister src, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700506
John Porto4a566862016-01-04 09:33:41 -0800507 void pmovsxdq(XmmRegister dst, XmmRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700508
John Porto4a566862016-01-04 09:33:41 -0800509 void pcmpeq(Type Ty, XmmRegister dst, XmmRegister src);
510 void pcmpeq(Type Ty, XmmRegister dst, const Address &src);
511 void pcmpgt(Type Ty, XmmRegister dst, XmmRegister src);
512 void pcmpgt(Type Ty, XmmRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700513
514 enum RoundingMode {
515 kRoundToNearest = 0x0,
516 kRoundDown = 0x1,
517 kRoundUp = 0x2,
518 kRoundToZero = 0x3
519 };
Nicolas Capensf0d12c32016-10-27 15:17:41 -0400520 void round(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mode);
521 void round(Type Ty, XmmRegister dst, const Address &src,
522 const Immediate &mode);
John Porto5d0acff2015-06-30 15:29:21 -0700523
John Porto2fea26c2015-07-28 16:28:07 -0700524 //----------------------------------------------------------------------------
525 //
526 // Begin: X87 instructions. Only available when Traits::UsesX87.
527 //
528 //----------------------------------------------------------------------------
529 template <typename T = Traits,
530 typename = typename std::enable_if<T::UsesX87>::type>
531 void fld(Type Ty, const typename T::Address &src);
532 template <typename T = Traits,
533 typename = typename std::enable_if<T::UsesX87>::type>
534 void fstp(Type Ty, const typename T::Address &dst);
535 template <typename T = Traits,
536 typename = typename std::enable_if<T::UsesX87>::type>
537 void fstp(typename T::X87STRegister st);
John Porto5d0acff2015-06-30 15:29:21 -0700538
John Porto2fea26c2015-07-28 16:28:07 -0700539 template <typename T = Traits,
540 typename = typename std::enable_if<T::UsesX87>::type>
541 void fnstcw(const typename T::Address &dst);
542 template <typename T = Traits,
543 typename = typename std::enable_if<T::UsesX87>::type>
544 void fldcw(const typename T::Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700545
John Porto2fea26c2015-07-28 16:28:07 -0700546 template <typename T = Traits,
547 typename = typename std::enable_if<T::UsesX87>::type>
548 void fistpl(const typename T::Address &dst);
549 template <typename T = Traits,
550 typename = typename std::enable_if<T::UsesX87>::type>
551 void fistps(const typename T::Address &dst);
552 template <typename T = Traits,
553 typename = typename std::enable_if<T::UsesX87>::type>
554 void fildl(const typename T::Address &src);
555 template <typename T = Traits,
556 typename = typename std::enable_if<T::UsesX87>::type>
557 void filds(const typename T::Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700558
John Porto2fea26c2015-07-28 16:28:07 -0700559 template <typename T = Traits,
560 typename = typename std::enable_if<T::UsesX87>::type>
John Porto5d0acff2015-06-30 15:29:21 -0700561 void fincstp();
John Porto2fea26c2015-07-28 16:28:07 -0700562 //----------------------------------------------------------------------------
563 //
564 // End: X87 instructions.
565 //
566 //----------------------------------------------------------------------------
John Porto5d0acff2015-06-30 15:29:21 -0700567
John Porto4a566862016-01-04 09:33:41 -0800568 void cmp(Type Ty, GPRRegister reg0, GPRRegister reg1);
569 void cmp(Type Ty, GPRRegister reg, const Address &address);
570 void cmp(Type Ty, GPRRegister reg, const Immediate &imm);
571 void cmp(Type Ty, const Address &address, GPRRegister reg);
572 void cmp(Type Ty, const Address &address, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700573
John Porto4a566862016-01-04 09:33:41 -0800574 void test(Type Ty, GPRRegister reg0, GPRRegister reg1);
575 void test(Type Ty, GPRRegister reg, const Immediate &imm);
576 void test(Type Ty, const Address &address, GPRRegister reg);
577 void test(Type Ty, const Address &address, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700578
John Porto4a566862016-01-04 09:33:41 -0800579 void And(Type Ty, GPRRegister dst, GPRRegister src);
580 void And(Type Ty, GPRRegister dst, const Address &address);
581 void And(Type Ty, GPRRegister dst, const Immediate &imm);
582 void And(Type Ty, const Address &address, GPRRegister reg);
583 void And(Type Ty, const Address &address, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700584
John Porto4a566862016-01-04 09:33:41 -0800585 void Or(Type Ty, GPRRegister dst, GPRRegister src);
586 void Or(Type Ty, GPRRegister dst, const Address &address);
587 void Or(Type Ty, GPRRegister dst, const Immediate &imm);
588 void Or(Type Ty, const Address &address, GPRRegister reg);
589 void Or(Type Ty, const Address &address, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700590
John Porto4a566862016-01-04 09:33:41 -0800591 void Xor(Type Ty, GPRRegister dst, GPRRegister src);
592 void Xor(Type Ty, GPRRegister dst, const Address &address);
593 void Xor(Type Ty, GPRRegister dst, const Immediate &imm);
594 void Xor(Type Ty, const Address &address, GPRRegister reg);
595 void Xor(Type Ty, const Address &address, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700596
John Porto4a566862016-01-04 09:33:41 -0800597 void add(Type Ty, GPRRegister dst, GPRRegister src);
598 void add(Type Ty, GPRRegister reg, const Address &address);
599 void add(Type Ty, GPRRegister reg, const Immediate &imm);
600 void add(Type Ty, const Address &address, GPRRegister reg);
601 void add(Type Ty, const Address &address, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700602
John Porto4a566862016-01-04 09:33:41 -0800603 void adc(Type Ty, GPRRegister dst, GPRRegister src);
604 void adc(Type Ty, GPRRegister dst, const Address &address);
605 void adc(Type Ty, GPRRegister reg, const Immediate &imm);
606 void adc(Type Ty, const Address &address, GPRRegister reg);
607 void adc(Type Ty, const Address &address, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700608
John Porto4a566862016-01-04 09:33:41 -0800609 void sub(Type Ty, GPRRegister dst, GPRRegister src);
610 void sub(Type Ty, GPRRegister reg, const Address &address);
611 void sub(Type Ty, GPRRegister reg, const Immediate &imm);
612 void sub(Type Ty, const Address &address, GPRRegister reg);
613 void sub(Type Ty, const Address &address, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700614
John Porto4a566862016-01-04 09:33:41 -0800615 void sbb(Type Ty, GPRRegister dst, GPRRegister src);
616 void sbb(Type Ty, GPRRegister reg, const Address &address);
617 void sbb(Type Ty, GPRRegister reg, const Immediate &imm);
618 void sbb(Type Ty, const Address &address, GPRRegister reg);
619 void sbb(Type Ty, const Address &address, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700620
621 void cbw();
622 void cwd();
623 void cdq();
John Porto1d235422015-08-12 12:37:53 -0700624 template <typename T = Traits>
625 typename std::enable_if<T::Is64Bit, void>::type cqo();
626 template <typename T = Traits>
627 typename std::enable_if<!T::Is64Bit, void>::type cqo() {
628 llvm::report_fatal_error("CQO is only available in 64-bit x86 backends.");
629 }
John Porto5d0acff2015-06-30 15:29:21 -0700630
John Porto4a566862016-01-04 09:33:41 -0800631 void div(Type Ty, GPRRegister reg);
632 void div(Type Ty, const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700633
John Porto4a566862016-01-04 09:33:41 -0800634 void idiv(Type Ty, GPRRegister reg);
635 void idiv(Type Ty, const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700636
John Porto4a566862016-01-04 09:33:41 -0800637 void imul(Type Ty, GPRRegister dst, GPRRegister src);
638 void imul(Type Ty, GPRRegister reg, const Immediate &imm);
639 void imul(Type Ty, GPRRegister reg, const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700640
John Porto4a566862016-01-04 09:33:41 -0800641 void imul(Type Ty, GPRRegister reg);
642 void imul(Type Ty, const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700643
John Porto4a566862016-01-04 09:33:41 -0800644 void imul(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
645 void imul(Type Ty, GPRRegister dst, const Address &address,
646 const Immediate &imm);
David Sehre11f8782015-10-06 10:26:57 -0700647
John Porto4a566862016-01-04 09:33:41 -0800648 void mul(Type Ty, GPRRegister reg);
649 void mul(Type Ty, const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700650
John Porto2fea26c2015-07-28 16:28:07 -0700651 template <class T = Traits,
652 typename = typename std::enable_if<!T::Is64Bit>::type>
John Porto4a566862016-01-04 09:33:41 -0800653 void incl(GPRRegister reg);
654 void incl(const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700655
John Porto2fea26c2015-07-28 16:28:07 -0700656 template <class T = Traits,
657 typename = typename std::enable_if<!T::Is64Bit>::type>
John Porto4a566862016-01-04 09:33:41 -0800658 void decl(GPRRegister reg);
659 void decl(const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700660
John Porto4a566862016-01-04 09:33:41 -0800661 void rol(Type Ty, GPRRegister reg, const Immediate &imm);
662 void rol(Type Ty, GPRRegister operand, GPRRegister shifter);
663 void rol(Type Ty, const Address &operand, GPRRegister shifter);
John Porto5d0acff2015-06-30 15:29:21 -0700664
John Porto4a566862016-01-04 09:33:41 -0800665 void shl(Type Ty, GPRRegister reg, const Immediate &imm);
666 void shl(Type Ty, GPRRegister operand, GPRRegister shifter);
667 void shl(Type Ty, const Address &operand, GPRRegister shifter);
John Porto5d0acff2015-06-30 15:29:21 -0700668
John Porto4a566862016-01-04 09:33:41 -0800669 void shr(Type Ty, GPRRegister reg, const Immediate &imm);
670 void shr(Type Ty, GPRRegister operand, GPRRegister shifter);
671 void shr(Type Ty, const Address &operand, GPRRegister shifter);
John Porto5d0acff2015-06-30 15:29:21 -0700672
John Porto4a566862016-01-04 09:33:41 -0800673 void sar(Type Ty, GPRRegister reg, const Immediate &imm);
674 void sar(Type Ty, GPRRegister operand, GPRRegister shifter);
675 void sar(Type Ty, const Address &address, GPRRegister shifter);
John Porto5d0acff2015-06-30 15:29:21 -0700676
John Porto4a566862016-01-04 09:33:41 -0800677 void shld(Type Ty, GPRRegister dst, GPRRegister src);
678 void shld(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
679 void shld(Type Ty, const Address &operand, GPRRegister src);
680 void shrd(Type Ty, GPRRegister dst, GPRRegister src);
681 void shrd(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
682 void shrd(Type Ty, const Address &dst, GPRRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700683
John Porto4a566862016-01-04 09:33:41 -0800684 void neg(Type Ty, GPRRegister reg);
685 void neg(Type Ty, const Address &addr);
686 void notl(GPRRegister reg);
John Porto5d0acff2015-06-30 15:29:21 -0700687
John Porto4a566862016-01-04 09:33:41 -0800688 void bsf(Type Ty, GPRRegister dst, GPRRegister src);
689 void bsf(Type Ty, GPRRegister dst, const Address &src);
690 void bsr(Type Ty, GPRRegister dst, GPRRegister src);
691 void bsr(Type Ty, GPRRegister dst, const Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700692
John Porto4a566862016-01-04 09:33:41 -0800693 void bswap(Type Ty, GPRRegister reg);
John Porto5d0acff2015-06-30 15:29:21 -0700694
John Porto4a566862016-01-04 09:33:41 -0800695 void bt(GPRRegister base, GPRRegister offset);
John Porto5d0acff2015-06-30 15:29:21 -0700696
697 void ret();
698 void ret(const Immediate &imm);
699
700 // 'size' indicates size in bytes and must be in the range 1..8.
701 void nop(int size = 1);
702 void int3();
703 void hlt();
704 void ud2();
705
John Portof746f3d2015-07-11 08:29:20 -0700706 // j(Label) is fully tested.
John Porto4a566862016-01-04 09:33:41 -0800707 void j(BrCond condition, Label *label, bool near = kFarJump);
708 void j(BrCond condition, const ConstantRelocatable *label); // not testable.
John Porto5d0acff2015-06-30 15:29:21 -0700709
John Porto4a566862016-01-04 09:33:41 -0800710 void jmp(GPRRegister reg);
John Porto5d0acff2015-06-30 15:29:21 -0700711 void jmp(Label *label, bool near = kFarJump);
John Porto2fea26c2015-07-28 16:28:07 -0700712 void jmp(const ConstantRelocatable *label); // not testable.
John Porto34d276a2016-01-27 06:31:53 -0800713 void jmp(const Immediate &abs_address);
John Porto5d0acff2015-06-30 15:29:21 -0700714
715 void mfence();
716
717 void lock();
John Porto4a566862016-01-04 09:33:41 -0800718 void cmpxchg(Type Ty, const Address &address, GPRRegister reg, bool Locked);
719 void cmpxchg8b(const Address &address, bool Locked);
720 void xadd(Type Ty, const Address &address, GPRRegister reg, bool Locked);
721 void xchg(Type Ty, GPRRegister reg0, GPRRegister reg1);
722 void xchg(Type Ty, const Address &address, GPRRegister reg);
John Porto5d0acff2015-06-30 15:29:21 -0700723
Andrew Scull2c862522015-08-06 08:41:53 -0700724 /// \name Intel Architecture Code Analyzer markers.
725 /// @{
726 void iaca_start();
727 void iaca_end();
728 /// @}
729
John Porto5d0acff2015-06-30 15:29:21 -0700730 void emitSegmentOverride(uint8_t prefix);
731
732 intptr_t preferredLoopAlignment() { return 16; }
733 void align(intptr_t alignment, intptr_t offset);
734 void bind(Label *label);
735
736 intptr_t CodeSize() const { return Buffer.size(); }
737
John Porto2fea26c2015-07-28 16:28:07 -0700738protected:
John Porto5d0acff2015-06-30 15:29:21 -0700739 inline void emitUint8(uint8_t value);
John Porto2fea26c2015-07-28 16:28:07 -0700740
741private:
John Porto4a566862016-01-04 09:33:41 -0800742 ENABLE_MAKE_UNIQUE;
743
John Porto56958cb2016-01-14 09:18:18 -0800744 // EmidAddrSizeOverridePrefix directs the emission of the 0x67 prefix to
745 // force 32-bit registers when accessing memory. This is only used in native
746 // 64-bit.
747 const bool EmitAddrSizeOverridePrefix;
748
John Porto2fea26c2015-07-28 16:28:07 -0700749 static constexpr Type RexTypeIrrelevant = IceType_i32;
John Porto453660f2015-07-31 14:52:52 -0700750 static constexpr Type RexTypeForceRexW = IceType_i64;
John Porto4a566862016-01-04 09:33:41 -0800751 static constexpr GPRRegister RexRegIrrelevant =
John Porto2fea26c2015-07-28 16:28:07 -0700752 Traits::GPRRegister::Encoded_Reg_eax;
753
John Porto5d0acff2015-06-30 15:29:21 -0700754 inline void emitInt16(int16_t value);
755 inline void emitInt32(int32_t value);
756 inline void emitRegisterOperand(int rm, int reg);
John Porto2fea26c2015-07-28 16:28:07 -0700757 template <typename RegType, typename RmType>
758 inline void emitXmmRegisterOperand(RegType reg, RmType rm);
John Porto5d0acff2015-06-30 15:29:21 -0700759 inline void emitOperandSizeOverride();
760
John Portod1bd1d32016-01-26 11:44:01 -0800761 void emitOperand(int rm, const Operand &operand, RelocOffsetT Addend = 0);
John Porto5d0acff2015-06-30 15:29:21 -0700762 void emitImmediate(Type ty, const Immediate &imm);
John Porto4a566862016-01-04 09:33:41 -0800763 void emitComplexI8(int rm, const Operand &operand,
John Porto5d0acff2015-06-30 15:29:21 -0700764 const Immediate &immediate);
John Porto4a566862016-01-04 09:33:41 -0800765 void emitComplex(Type Ty, int rm, const Operand &operand,
John Porto5d0acff2015-06-30 15:29:21 -0700766 const Immediate &immediate);
767 void emitLabel(Label *label, intptr_t instruction_size);
768 void emitLabelLink(Label *label);
769 void emitNearLabelLink(Label *label);
770
John Porto4a566862016-01-04 09:33:41 -0800771 void emitGenericShift(int rm, Type Ty, GPRRegister reg, const Immediate &imm);
772 void emitGenericShift(int rm, Type Ty, const Operand &operand,
773 GPRRegister shifter);
John Porto5d0acff2015-06-30 15:29:21 -0700774
Andrew Scull8072bae2015-09-14 16:01:26 -0700775 using LabelVector = std::vector<Label *>;
John Porto5d0acff2015-06-30 15:29:21 -0700776 // A vector of pool-allocated x86 labels for CFG nodes.
777 LabelVector CfgNodeLabels;
778 // A vector of pool-allocated x86 labels for Local labels.
779 LabelVector LocalLabels;
780
Andrew Scull86df4e92015-07-30 13:54:44 -0700781 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
John Porto5d0acff2015-06-30 15:29:21 -0700782
John Porto3c275ce2015-12-22 08:14:00 -0800783 void emitAddrSizeOverridePrefix() {
John Porto56958cb2016-01-14 09:18:18 -0800784 if (!Traits::Is64Bit || !EmitAddrSizeOverridePrefix) {
John Porto3c275ce2015-12-22 08:14:00 -0800785 return;
786 }
787 static constexpr uint8_t AddrSizeOverridePrefix = 0x67;
788 emitUint8(AddrSizeOverridePrefix);
789 }
790
Andrew Scull57e12682015-09-16 11:30:19 -0700791 // The arith_int() methods factor out the commonality between the encodings
792 // of add(), Or(), adc(), sbb(), And(), sub(), Xor(), and cmp(). The Tag
John Porto5d0acff2015-06-30 15:29:21 -0700793 // parameter is statically asserted to be less than 8.
794 template <uint32_t Tag>
John Porto4a566862016-01-04 09:33:41 -0800795 void arith_int(Type Ty, GPRRegister reg, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700796
797 template <uint32_t Tag>
John Porto4a566862016-01-04 09:33:41 -0800798 void arith_int(Type Ty, GPRRegister reg0, GPRRegister reg1);
John Porto5d0acff2015-06-30 15:29:21 -0700799
800 template <uint32_t Tag>
John Porto4a566862016-01-04 09:33:41 -0800801 void arith_int(Type Ty, GPRRegister reg, const Address &address);
John Porto5d0acff2015-06-30 15:29:21 -0700802
803 template <uint32_t Tag>
John Porto4a566862016-01-04 09:33:41 -0800804 void arith_int(Type Ty, const Address &address, GPRRegister reg);
John Porto5d0acff2015-06-30 15:29:21 -0700805
806 template <uint32_t Tag>
John Porto4a566862016-01-04 09:33:41 -0800807 void arith_int(Type Ty, const Address &address, const Immediate &imm);
John Porto2fea26c2015-07-28 16:28:07 -0700808
809 // gprEncoding returns Reg encoding for operand emission. For x86-64 we mask
810 // out the 4th bit as it is encoded in the REX.[RXB] bits. No other bits are
811 // touched because we don't want to mask errors.
812 template <typename RegType, typename T = Traits>
813 typename std::enable_if<T::Is64Bit, typename T::GPRRegister>::type
814 gprEncoding(const RegType Reg) {
John Porto4a566862016-01-04 09:33:41 -0800815 return static_cast<GPRRegister>(static_cast<uint8_t>(Reg) & ~0x08);
John Porto2fea26c2015-07-28 16:28:07 -0700816 }
817
818 template <typename RegType, typename T = Traits>
819 typename std::enable_if<!T::Is64Bit, typename T::GPRRegister>::type
820 gprEncoding(const RegType Reg) {
821 return static_cast<typename T::GPRRegister>(Reg);
822 }
823
824 template <typename RegType>
825 bool is8BitRegisterRequiringRex(const Type Ty, const RegType Reg) {
826 static constexpr bool IsGPR =
John Porto4a566862016-01-04 09:33:41 -0800827 std::is_same<typename std::decay<RegType>::type, ByteRegister>::value ||
828 std::is_same<typename std::decay<RegType>::type, GPRRegister>::value;
John Porto2fea26c2015-07-28 16:28:07 -0700829
John Porto3c275ce2015-12-22 08:14:00 -0800830 // At this point in the assembler, we have encoded regs, so it is not
831 // possible to distinguish between the "new" low byte registers introduced
John Porto4a566862016-01-04 09:33:41 -0800832 // in x86-64 and the legacy [abcd]h registers. Because x86, we may still
833 // see ah (div) in the assembler, so we whitelist it here.
John Porto3c275ce2015-12-22 08:14:00 -0800834 //
John Porto4a566862016-01-04 09:33:41 -0800835 // The "local" uint32_t Encoded_Reg_ah is needed because RegType is an
836 // enum that is not necessarily the same type of
John Porto3c275ce2015-12-22 08:14:00 -0800837 // Traits::RegisterSet::Encoded_Reg_ah.
838 constexpr uint32_t Encoded_Reg_ah = Traits::RegisterSet::Encoded_Reg_ah;
John Porto2fea26c2015-07-28 16:28:07 -0700839 return IsGPR && (Reg & 0x04) != 0 && (Reg & 0x08) == 0 &&
John Porto3c275ce2015-12-22 08:14:00 -0800840 isByteSizedType(Ty) && (Reg != Encoded_Reg_ah);
Jim Stichnotha8d47132015-09-08 14:43:38 -0700841 }
John Porto2fea26c2015-07-28 16:28:07 -0700842
Andrew Scull57e12682015-09-16 11:30:19 -0700843 // assembleAndEmitRex is used for determining which (if any) rex prefix
844 // should be emitted for the current instruction. It allows different types
John Porto4a566862016-01-04 09:33:41 -0800845 // for Reg and Rm because they could be of different types (e.g., in
846 // mov[sz]x instructions.) If Addr is not nullptr, then Rm is ignored, and
847 // Rex.B is determined by Addr instead. TyRm is still used to determine
848 // Addr's size.
John Porto2fea26c2015-07-28 16:28:07 -0700849 template <typename RegType, typename RmType, typename T = Traits>
850 typename std::enable_if<T::Is64Bit, void>::type
851 assembleAndEmitRex(const Type TyReg, const RegType Reg, const Type TyRm,
852 const RmType Rm,
853 const typename T::Address *Addr = nullptr) {
854 const uint8_t W = (TyReg == IceType_i64 || TyRm == IceType_i64)
855 ? T::Operand::RexW
856 : T::Operand::RexNone;
857 const uint8_t R = (Reg & 0x08) ? T::Operand::RexR : T::Operand::RexNone;
Jim Stichnotha8d47132015-09-08 14:43:38 -0700858 const uint8_t X = (Addr != nullptr)
859 ? (typename T::Operand::RexBits)Addr->rexX()
860 : T::Operand::RexNone;
John Porto2fea26c2015-07-28 16:28:07 -0700861 const uint8_t B =
Jim Stichnotha8d47132015-09-08 14:43:38 -0700862 (Addr != nullptr)
863 ? (typename T::Operand::RexBits)Addr->rexB()
864 : (Rm & 0x08) ? T::Operand::RexB : T::Operand::RexNone;
John Porto2fea26c2015-07-28 16:28:07 -0700865 const uint8_t Prefix = W | R | X | B;
866 if (Prefix != T::Operand::RexNone) {
867 emitUint8(Prefix);
868 } else if (is8BitRegisterRequiringRex(TyReg, Reg) ||
869 (Addr == nullptr && is8BitRegisterRequiringRex(TyRm, Rm))) {
870 emitUint8(T::Operand::RexBase);
871 }
872 }
873
874 template <typename RegType, typename RmType, typename T = Traits>
875 typename std::enable_if<!T::Is64Bit, void>::type
876 assembleAndEmitRex(const Type, const RegType, const Type, const RmType,
877 const typename T::Address * = nullptr) {}
878
John Porto4a566862016-01-04 09:33:41 -0800879 // emitRexRB is used for emitting a Rex prefix instructions with two
880 // explicit register operands in its mod-rm byte.
John Porto2fea26c2015-07-28 16:28:07 -0700881 template <typename RegType, typename RmType>
882 void emitRexRB(const Type Ty, const RegType Reg, const RmType Rm) {
883 assembleAndEmitRex(Ty, Reg, Ty, Rm);
884 }
885
886 template <typename RegType, typename RmType>
887 void emitRexRB(const Type TyReg, const RegType Reg, const Type TyRm,
888 const RmType Rm) {
889 assembleAndEmitRex(TyReg, Reg, TyRm, Rm);
890 }
891
Andrew Scull57e12682015-09-16 11:30:19 -0700892 // emitRexB is used for emitting a Rex prefix if one is needed on encoding
893 // the Reg field in an x86 instruction. It is invoked by the template when
894 // Reg is the single register operand in the instruction (e.g., push Reg.)
John Porto2fea26c2015-07-28 16:28:07 -0700895 template <typename RmType> void emitRexB(const Type Ty, const RmType Rm) {
896 emitRexRB(Ty, RexRegIrrelevant, Ty, Rm);
897 }
898
899 // emitRex is used for emitting a Rex prefix for an address and a GPR. The
900 // address may contain zero, one, or two registers.
901 template <typename RegType>
John Porto4a566862016-01-04 09:33:41 -0800902 void emitRex(const Type Ty, const Address &Addr, const RegType Reg) {
John Porto2fea26c2015-07-28 16:28:07 -0700903 assembleAndEmitRex(Ty, Reg, Ty, RexRegIrrelevant, &Addr);
904 }
905
906 template <typename RegType>
John Porto4a566862016-01-04 09:33:41 -0800907 void emitRex(const Type AddrTy, const Address &Addr, const Type TyReg,
908 const RegType Reg) {
John Porto2fea26c2015-07-28 16:28:07 -0700909 assembleAndEmitRex(TyReg, Reg, AddrTy, RexRegIrrelevant, &Addr);
910 }
John Porto5d0acff2015-06-30 15:29:21 -0700911};
912
John Porto4a566862016-01-04 09:33:41 -0800913template <typename TraitsType>
914inline void AssemblerX86Base<TraitsType>::emitUint8(uint8_t value) {
John Porto5d0acff2015-06-30 15:29:21 -0700915 Buffer.emit<uint8_t>(value);
916}
917
John Porto4a566862016-01-04 09:33:41 -0800918template <typename TraitsType>
919inline void AssemblerX86Base<TraitsType>::emitInt16(int16_t value) {
John Porto5d0acff2015-06-30 15:29:21 -0700920 Buffer.emit<int16_t>(value);
921}
922
John Porto4a566862016-01-04 09:33:41 -0800923template <typename TraitsType>
924inline void AssemblerX86Base<TraitsType>::emitInt32(int32_t value) {
John Porto5d0acff2015-06-30 15:29:21 -0700925 Buffer.emit<int32_t>(value);
926}
927
John Porto4a566862016-01-04 09:33:41 -0800928template <typename TraitsType>
929inline void AssemblerX86Base<TraitsType>::emitRegisterOperand(int reg, int rm) {
John Porto2fea26c2015-07-28 16:28:07 -0700930 assert(reg >= 0 && reg < 8);
John Porto5d0acff2015-06-30 15:29:21 -0700931 assert(rm >= 0 && rm < 8);
John Porto2fea26c2015-07-28 16:28:07 -0700932 Buffer.emit<uint8_t>(0xC0 + (reg << 3) + rm);
John Porto5d0acff2015-06-30 15:29:21 -0700933}
934
John Porto4a566862016-01-04 09:33:41 -0800935template <typename TraitsType>
John Porto2fea26c2015-07-28 16:28:07 -0700936template <typename RegType, typename RmType>
John Porto4a566862016-01-04 09:33:41 -0800937inline void AssemblerX86Base<TraitsType>::emitXmmRegisterOperand(RegType reg,
938 RmType rm) {
John Porto2fea26c2015-07-28 16:28:07 -0700939 emitRegisterOperand(gprEncoding(reg), gprEncoding(rm));
John Porto5d0acff2015-06-30 15:29:21 -0700940}
941
John Porto4a566862016-01-04 09:33:41 -0800942template <typename TraitsType>
943inline void AssemblerX86Base<TraitsType>::emitOperandSizeOverride() {
John Porto5d0acff2015-06-30 15:29:21 -0700944 emitUint8(0x66);
945}
946
John Porto4a566862016-01-04 09:33:41 -0800947} // end of namespace X86NAMESPACE
John Porto5d0acff2015-06-30 15:29:21 -0700948
John Porto5d0acff2015-06-30 15:29:21 -0700949} // end of namespace Ice
950
951#include "IceAssemblerX86BaseImpl.h"
952
953#endif // SUBZERO_SRC_ICEASSEMBLERX86BASE_H