blob: 6b8f3c1b0f531f1a3a10380ca66935e4961faec0 [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//
18// This file defines the AssemblerX86 template class for x86, the base of all
19// X86 assemblers.
20//
21//===----------------------------------------------------------------------===//
22
23#ifndef SUBZERO_SRC_ICEASSEMBLERX86BASE_H
24#define SUBZERO_SRC_ICEASSEMBLERX86BASE_H
25
26#include "IceAssembler.h"
27#include "IceDefs.h"
28#include "IceOperand.h"
29#include "IceTypes.h"
30#include "IceUtils.h"
31
32namespace Ice {
33
34namespace X86Internal {
35
36template <class Machine> class AssemblerX86Base;
37template <class Machine> struct MachineTraits;
38
39constexpr int MAX_NOP_SIZE = 8;
40
41class Immediate {
42 Immediate(const Immediate &) = delete;
43 Immediate &operator=(const Immediate &) = delete;
44
45public:
46 explicit Immediate(int32_t value) : value_(value) {}
47
48 Immediate(RelocOffsetT offset, AssemblerFixup *fixup)
49 : value_(offset), fixup_(fixup) {
50 // Use the Offset in the "value" for now. If we decide to process fixups,
51 // we'll need to patch that offset with the true value.
52 }
53
54 int32_t value() const { return value_; }
55 AssemblerFixup *fixup() const { return fixup_; }
56
57 bool is_int8() const {
58 // We currently only allow 32-bit fixups, and they usually have value = 0,
59 // so if fixup_ != nullptr, it shouldn't be classified as int8/16.
60 return fixup_ == nullptr && Utils::IsInt(8, value_);
61 }
62 bool is_uint8() const {
63 return fixup_ == nullptr && Utils::IsUint(8, value_);
64 }
65 bool is_uint16() const {
66 return fixup_ == nullptr && Utils::IsUint(16, value_);
67 }
68
69private:
70 const int32_t value_;
71 AssemblerFixup *fixup_ = nullptr;
72};
73
Andrew Scull86df4e92015-07-30 13:54:44 -070074/// X86 allows near and far jumps.
75class Label final : public Ice::Label {
John Porto5d0acff2015-06-30 15:29:21 -070076 Label(const Label &) = delete;
77 Label &operator=(const Label &) = delete;
78
79public:
Andrew Scull86df4e92015-07-30 13:54:44 -070080 Label() = default;
John Porto5d0acff2015-06-30 15:29:21 -070081 ~Label() = default;
82
Andrew Scull86df4e92015-07-30 13:54:44 -070083 void finalCheck() const override {
84 Ice::Label::finalCheck();
85 assert(!hasNear());
John Porto5d0acff2015-06-30 15:29:21 -070086 }
87
Andrew Scull86df4e92015-07-30 13:54:44 -070088 /// Returns the position of an earlier branch instruction which assumes that
89 /// this label is "near", and bumps iterator to the next near position.
90 intptr_t getNearPosition() {
91 assert(hasNear());
92 intptr_t Pos = UnresolvedNearPositions.back();
93 UnresolvedNearPositions.pop_back();
94 return Pos;
John Porto5d0acff2015-06-30 15:29:21 -070095 }
96
Andrew Scull86df4e92015-07-30 13:54:44 -070097 bool hasNear() const { return !UnresolvedNearPositions.empty(); }
98 bool isUnused() const override {
99 return Ice::Label::isUnused() && !hasNear();
John Porto5d0acff2015-06-30 15:29:21 -0700100 }
101
John Porto5d0acff2015-06-30 15:29:21 -0700102private:
Andrew Scull86df4e92015-07-30 13:54:44 -0700103 void nearLinkTo(intptr_t position) {
104 assert(!isBound());
105 UnresolvedNearPositions.push_back(position);
John Porto5d0acff2015-06-30 15:29:21 -0700106 }
107
Andrew Scull86df4e92015-07-30 13:54:44 -0700108 llvm::SmallVector<intptr_t, 20> UnresolvedNearPositions;
John Porto5d0acff2015-06-30 15:29:21 -0700109
110 template <class> friend class AssemblerX86Base;
111};
112
113template <class Machine> class AssemblerX86Base : public Assembler {
114 AssemblerX86Base(const AssemblerX86Base &) = delete;
115 AssemblerX86Base &operator=(const AssemblerX86Base &) = delete;
116
117protected:
Karl Schimpfc5abdc12015-10-09 13:29:13 -0700118 AssemblerX86Base(AssemblerKind Kind, GlobalContext *Ctx,
119 bool use_far_branches)
120 : Assembler(Kind, Ctx) {
John Porto5d0acff2015-06-30 15:29:21 -0700121 // This mode is only needed and implemented for MIPS and ARM.
122 assert(!use_far_branches);
123 (void)use_far_branches;
124 }
125
126public:
127 using Traits = MachineTraits<Machine>;
128
129 ~AssemblerX86Base() override;
130
131 static const bool kNearJump = true;
132 static const bool kFarJump = false;
133
134 void alignFunction() override;
135
136 SizeT getBundleAlignLog2Bytes() const override { return 5; }
137
Andrew Scull86df4e92015-07-30 13:54:44 -0700138 const char *getAlignDirective() const override { return ".p2align"; }
John Porto5d0acff2015-06-30 15:29:21 -0700139
140 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
141 static const uint8_t Padding[] = {0xF4};
142 return llvm::ArrayRef<uint8_t>(Padding, 1);
143 }
144
145 void padWithNop(intptr_t Padding) override {
146 while (Padding > MAX_NOP_SIZE) {
147 nop(MAX_NOP_SIZE);
148 Padding -= MAX_NOP_SIZE;
149 }
150 if (Padding)
151 nop(Padding);
152 }
153
Jan Voungc2ec5812015-08-05 09:35:18 -0700154 Ice::Label *getCfgNodeLabel(SizeT NodeNumber) override;
John Porto5d0acff2015-06-30 15:29:21 -0700155 void bindCfgNodeLabel(SizeT NodeNumber) override;
Jan Voungc2ec5812015-08-05 09:35:18 -0700156 Label *getOrCreateCfgNodeLabel(SizeT Number);
Andrew Scull86df4e92015-07-30 13:54:44 -0700157 Label *getOrCreateLocalLabel(SizeT Number);
158 void bindLocalLabel(SizeT Number);
John Porto5d0acff2015-06-30 15:29:21 -0700159
160 bool fixupIsPCRel(FixupKind Kind) const override {
161 // Currently assuming this is the only PC-rel relocation type used.
162 // TODO(jpp): Traits.PcRelTypes.count(Kind) != 0
163 return Kind == Traits::PcRelFixup;
164 }
165
166 // Operations to emit GPR instructions (and dispatch on operand type).
Andrew Scull8072bae2015-09-14 16:01:26 -0700167 using TypedEmitGPR = void (AssemblerX86Base::*)(Type,
168 typename Traits::GPRRegister);
169 using TypedEmitAddr =
170 void (AssemblerX86Base::*)(Type, const typename Traits::Address &);
John Porto5d0acff2015-06-30 15:29:21 -0700171 struct GPREmitterOneOp {
172 TypedEmitGPR Reg;
173 TypedEmitAddr Addr;
174 };
175
Andrew Scull8072bae2015-09-14 16:01:26 -0700176 using TypedEmitGPRGPR = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700177 Type, typename Traits::GPRRegister, typename Traits::GPRRegister);
Andrew Scull8072bae2015-09-14 16:01:26 -0700178 using TypedEmitGPRAddr = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700179 Type, typename Traits::GPRRegister, const typename Traits::Address &);
Andrew Scull8072bae2015-09-14 16:01:26 -0700180 using TypedEmitGPRImm = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700181 Type, typename Traits::GPRRegister, const Immediate &);
182 struct GPREmitterRegOp {
183 TypedEmitGPRGPR GPRGPR;
184 TypedEmitGPRAddr GPRAddr;
185 TypedEmitGPRImm GPRImm;
186 };
187
188 struct GPREmitterShiftOp {
189 // Technically, Addr/GPR and Addr/Imm are also allowed, but */Addr are not.
190 // In practice, we always normalize the Dest to a Register first.
191 TypedEmitGPRGPR GPRGPR;
192 TypedEmitGPRImm GPRImm;
193 };
194
Andrew Scull8072bae2015-09-14 16:01:26 -0700195 using TypedEmitGPRGPRImm = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700196 Type, typename Traits::GPRRegister, typename Traits::GPRRegister,
197 const Immediate &);
198 struct GPREmitterShiftD {
Andrew Scull57e12682015-09-16 11:30:19 -0700199 // Technically AddrGPR and AddrGPRImm are also allowed, but in practice we
200 // always normalize Dest to a Register first.
John Porto5d0acff2015-06-30 15:29:21 -0700201 TypedEmitGPRGPR GPRGPR;
202 TypedEmitGPRGPRImm GPRGPRImm;
203 };
204
Andrew Scull8072bae2015-09-14 16:01:26 -0700205 using TypedEmitAddrGPR = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700206 Type, const typename Traits::Address &, typename Traits::GPRRegister);
Andrew Scull8072bae2015-09-14 16:01:26 -0700207 using TypedEmitAddrImm = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700208 Type, const typename Traits::Address &, const Immediate &);
209 struct GPREmitterAddrOp {
210 TypedEmitAddrGPR AddrGPR;
211 TypedEmitAddrImm AddrImm;
212 };
213
214 // Operations to emit XMM instructions (and dispatch on operand type).
Andrew Scull8072bae2015-09-14 16:01:26 -0700215 using TypedEmitXmmXmm = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700216 Type, typename Traits::XmmRegister, typename Traits::XmmRegister);
Andrew Scull8072bae2015-09-14 16:01:26 -0700217 using TypedEmitXmmAddr = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700218 Type, typename Traits::XmmRegister, const typename Traits::Address &);
219 struct XmmEmitterRegOp {
220 TypedEmitXmmXmm XmmXmm;
221 TypedEmitXmmAddr XmmAddr;
222 };
223
Andrew Scull8072bae2015-09-14 16:01:26 -0700224 using EmitXmmXmm = void (AssemblerX86Base::*)(typename Traits::XmmRegister,
225 typename Traits::XmmRegister);
226 using EmitXmmAddr = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700227 typename Traits::XmmRegister, const typename Traits::Address &);
Andrew Scull8072bae2015-09-14 16:01:26 -0700228 using EmitAddrXmm = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700229 const typename Traits::Address &, typename Traits::XmmRegister);
230 struct XmmEmitterMovOps {
231 EmitXmmXmm XmmXmm;
232 EmitXmmAddr XmmAddr;
233 EmitAddrXmm AddrXmm;
234 };
235
Andrew Scull8072bae2015-09-14 16:01:26 -0700236 using TypedEmitXmmImm = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700237 Type, typename Traits::XmmRegister, const Immediate &);
238
239 struct XmmEmitterShiftOp {
240 TypedEmitXmmXmm XmmXmm;
241 TypedEmitXmmAddr XmmAddr;
242 TypedEmitXmmImm XmmImm;
243 };
244
245 // Cross Xmm/GPR cast instructions.
246 template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp {
Andrew Scull8072bae2015-09-14 16:01:26 -0700247 using TypedEmitRegs = void (AssemblerX86Base::*)(Type, DReg_t, Type,
248 SReg_t);
249 using TypedEmitAddr = void (AssemblerX86Base::*)(
John Porto1d235422015-08-12 12:37:53 -0700250 Type, DReg_t, Type, const typename Traits::Address &);
John Porto5d0acff2015-06-30 15:29:21 -0700251
252 TypedEmitRegs RegReg;
253 TypedEmitAddr RegAddr;
254 };
255
Andrew Scull57e12682015-09-16 11:30:19 -0700256 // Three operand (potentially) cross Xmm/GPR instructions. The last operand
257 // must be an immediate.
John Porto5d0acff2015-06-30 15:29:21 -0700258 template <typename DReg_t, typename SReg_t> struct ThreeOpImmEmitter {
Andrew Scull8072bae2015-09-14 16:01:26 -0700259 using TypedEmitRegRegImm = void (AssemblerX86Base::*)(Type, DReg_t, SReg_t,
260 const Immediate &);
261 using TypedEmitRegAddrImm = void (AssemblerX86Base::*)(
John Porto5d0acff2015-06-30 15:29:21 -0700262 Type, DReg_t, const typename Traits::Address &, const Immediate &);
263
264 TypedEmitRegRegImm RegRegImm;
265 TypedEmitRegAddrImm RegAddrImm;
266 };
267
268 /*
269 * Emit Machine Instructions.
270 */
271 void call(typename Traits::GPRRegister reg);
272 void call(const typename Traits::Address &address);
John Porto2fea26c2015-07-28 16:28:07 -0700273 void call(const ConstantRelocatable *label); // not testable.
John Porto5d0acff2015-06-30 15:29:21 -0700274 void call(const Immediate &abs_address);
275
276 static const intptr_t kCallExternalLabelSize = 5;
277
278 void pushl(typename Traits::GPRRegister reg);
279
280 void popl(typename Traits::GPRRegister reg);
281 void popl(const typename Traits::Address &address);
282
John Porto2fea26c2015-07-28 16:28:07 -0700283 template <typename T = Traits,
284 typename = typename std::enable_if<T::HasPusha>::type>
John Porto5d0acff2015-06-30 15:29:21 -0700285 void pushal();
John Porto2fea26c2015-07-28 16:28:07 -0700286 template <typename T = Traits,
287 typename = typename std::enable_if<T::HasPopa>::type>
John Porto5d0acff2015-06-30 15:29:21 -0700288 void popal();
289
290 void setcc(typename Traits::Cond::BrCond condition,
291 typename Traits::ByteRegister dst);
292 void setcc(typename Traits::Cond::BrCond condition,
293 const typename Traits::Address &address);
294
295 void mov(Type Ty, typename Traits::GPRRegister dst, const Immediate &src);
296 void mov(Type Ty, typename Traits::GPRRegister dst,
297 typename Traits::GPRRegister src);
John Porto5d0acff2015-06-30 15:29:21 -0700298 void mov(Type Ty, typename Traits::GPRRegister dst,
299 const typename Traits::Address &src);
300 void mov(Type Ty, const typename Traits::Address &dst,
301 typename Traits::GPRRegister src);
302 void mov(Type Ty, const typename Traits::Address &dst, const Immediate &imm);
303
John Porto1d235422015-08-12 12:37:53 -0700304 template <typename T = Traits>
305 typename std::enable_if<T::Is64Bit, void>::type
306 movabs(const typename Traits::GPRRegister Dst, uint64_t Imm64);
307 template <typename T = Traits>
308 typename std::enable_if<!T::Is64Bit, void>::type
309 movabs(const typename Traits::GPRRegister, uint64_t) {
310 llvm::report_fatal_error("movabs is only supported in 64-bit x86 targets.");
311 }
John Porto2fea26c2015-07-28 16:28:07 -0700312
John Porto5d0acff2015-06-30 15:29:21 -0700313 void movzx(Type Ty, typename Traits::GPRRegister dst,
314 typename Traits::GPRRegister src);
315 void movzx(Type Ty, typename Traits::GPRRegister dst,
316 const typename Traits::Address &src);
317 void movsx(Type Ty, typename Traits::GPRRegister dst,
318 typename Traits::GPRRegister src);
319 void movsx(Type Ty, typename Traits::GPRRegister dst,
320 const typename Traits::Address &src);
321
322 void lea(Type Ty, typename Traits::GPRRegister dst,
323 const typename Traits::Address &src);
324
325 void cmov(Type Ty, typename Traits::Cond::BrCond cond,
326 typename Traits::GPRRegister dst, typename Traits::GPRRegister src);
327 void cmov(Type Ty, typename Traits::Cond::BrCond cond,
328 typename Traits::GPRRegister dst,
329 const typename Traits::Address &src);
330
331 void rep_movsb();
332
333 void movss(Type Ty, typename Traits::XmmRegister dst,
334 const typename Traits::Address &src);
335 void movss(Type Ty, const typename Traits::Address &dst,
336 typename Traits::XmmRegister src);
337 void movss(Type Ty, typename Traits::XmmRegister dst,
338 typename Traits::XmmRegister src);
339
John Porto1d235422015-08-12 12:37:53 -0700340 void movd(Type SrcTy, typename Traits::XmmRegister dst,
341 typename Traits::GPRRegister src);
342 void movd(Type SrcTy, typename Traits::XmmRegister dst,
John Porto5d0acff2015-06-30 15:29:21 -0700343 const typename Traits::Address &src);
John Porto1d235422015-08-12 12:37:53 -0700344 void movd(Type DestTy, typename Traits::GPRRegister dst,
345 typename Traits::XmmRegister src);
346 void movd(Type DestTy, const typename Traits::Address &dst,
John Porto5d0acff2015-06-30 15:29:21 -0700347 typename Traits::XmmRegister src);
348
349 void movq(typename Traits::XmmRegister dst, typename Traits::XmmRegister src);
350 void movq(const typename Traits::Address &dst,
351 typename Traits::XmmRegister src);
352 void movq(typename Traits::XmmRegister dst,
353 const typename Traits::Address &src);
354
355 void addss(Type Ty, typename Traits::XmmRegister dst,
356 typename Traits::XmmRegister src);
357 void addss(Type Ty, typename Traits::XmmRegister dst,
358 const typename Traits::Address &src);
359 void subss(Type Ty, typename Traits::XmmRegister dst,
360 typename Traits::XmmRegister src);
361 void subss(Type Ty, typename Traits::XmmRegister dst,
362 const typename Traits::Address &src);
363 void mulss(Type Ty, typename Traits::XmmRegister dst,
364 typename Traits::XmmRegister src);
365 void mulss(Type Ty, typename Traits::XmmRegister dst,
366 const typename Traits::Address &src);
367 void divss(Type Ty, typename Traits::XmmRegister dst,
368 typename Traits::XmmRegister src);
369 void divss(Type Ty, typename Traits::XmmRegister dst,
370 const typename Traits::Address &src);
371
372 void movaps(typename Traits::XmmRegister dst,
373 typename Traits::XmmRegister src);
374
375 void movups(typename Traits::XmmRegister dst,
376 typename Traits::XmmRegister src);
377 void movups(typename Traits::XmmRegister dst,
378 const typename Traits::Address &src);
379 void movups(const typename Traits::Address &dst,
380 typename Traits::XmmRegister src);
381
382 void padd(Type Ty, typename Traits::XmmRegister dst,
383 typename Traits::XmmRegister src);
384 void padd(Type Ty, typename Traits::XmmRegister dst,
385 const typename Traits::Address &src);
386 void pand(Type Ty, typename Traits::XmmRegister dst,
387 typename Traits::XmmRegister src);
388 void pand(Type Ty, typename Traits::XmmRegister dst,
389 const typename Traits::Address &src);
390 void pandn(Type Ty, typename Traits::XmmRegister dst,
391 typename Traits::XmmRegister src);
392 void pandn(Type Ty, typename Traits::XmmRegister dst,
393 const typename Traits::Address &src);
394 void pmull(Type Ty, typename Traits::XmmRegister dst,
395 typename Traits::XmmRegister src);
396 void pmull(Type Ty, typename Traits::XmmRegister dst,
397 const typename Traits::Address &src);
398 void pmuludq(Type Ty, typename Traits::XmmRegister dst,
399 typename Traits::XmmRegister src);
400 void pmuludq(Type Ty, typename Traits::XmmRegister dst,
401 const typename Traits::Address &src);
402 void por(Type Ty, typename Traits::XmmRegister dst,
403 typename Traits::XmmRegister src);
404 void por(Type Ty, typename Traits::XmmRegister dst,
405 const typename Traits::Address &src);
406 void psub(Type Ty, typename Traits::XmmRegister dst,
407 typename Traits::XmmRegister src);
408 void psub(Type Ty, typename Traits::XmmRegister dst,
409 const typename Traits::Address &src);
410 void pxor(Type Ty, typename Traits::XmmRegister dst,
411 typename Traits::XmmRegister src);
412 void pxor(Type Ty, typename Traits::XmmRegister dst,
413 const typename Traits::Address &src);
414
415 void psll(Type Ty, typename Traits::XmmRegister dst,
416 typename Traits::XmmRegister src);
417 void psll(Type Ty, typename Traits::XmmRegister dst,
418 const typename Traits::Address &src);
419 void psll(Type Ty, typename Traits::XmmRegister dst, const Immediate &src);
420
421 void psra(Type Ty, typename Traits::XmmRegister dst,
422 typename Traits::XmmRegister src);
423 void psra(Type Ty, typename Traits::XmmRegister dst,
424 const typename Traits::Address &src);
425 void psra(Type Ty, typename Traits::XmmRegister dst, const Immediate &src);
426 void psrl(Type Ty, typename Traits::XmmRegister dst,
427 typename Traits::XmmRegister src);
428 void psrl(Type Ty, typename Traits::XmmRegister dst,
429 const typename Traits::Address &src);
430 void psrl(Type Ty, typename Traits::XmmRegister dst, const Immediate &src);
431
432 void addps(Type Ty, typename Traits::XmmRegister dst,
433 typename Traits::XmmRegister src);
434 void addps(Type Ty, typename Traits::XmmRegister dst,
435 const typename Traits::Address &src);
436 void subps(Type Ty, typename Traits::XmmRegister dst,
437 typename Traits::XmmRegister src);
438 void subps(Type Ty, typename Traits::XmmRegister dst,
439 const typename Traits::Address &src);
440 void divps(Type Ty, typename Traits::XmmRegister dst,
441 typename Traits::XmmRegister src);
442 void divps(Type Ty, typename Traits::XmmRegister dst,
443 const typename Traits::Address &src);
444 void mulps(Type Ty, typename Traits::XmmRegister dst,
445 typename Traits::XmmRegister src);
446 void mulps(Type Ty, typename Traits::XmmRegister dst,
447 const typename Traits::Address &src);
448 void minps(typename Traits::XmmRegister dst,
449 typename Traits::XmmRegister src);
450 void maxps(typename Traits::XmmRegister dst,
451 typename Traits::XmmRegister src);
452 void andps(typename Traits::XmmRegister dst,
453 typename Traits::XmmRegister src);
454 void andps(typename Traits::XmmRegister dst,
455 const typename Traits::Address &src);
456 void orps(typename Traits::XmmRegister dst, typename Traits::XmmRegister src);
457
458 void blendvps(Type Ty, typename Traits::XmmRegister dst,
459 typename Traits::XmmRegister src);
460 void blendvps(Type Ty, typename Traits::XmmRegister dst,
461 const typename Traits::Address &src);
462 void pblendvb(Type Ty, typename Traits::XmmRegister dst,
463 typename Traits::XmmRegister src);
464 void pblendvb(Type Ty, typename Traits::XmmRegister dst,
465 const typename Traits::Address &src);
466
467 void cmpps(typename Traits::XmmRegister dst, typename Traits::XmmRegister src,
468 typename Traits::Cond::CmppsCond CmpCondition);
469 void cmpps(typename Traits::XmmRegister dst,
470 const typename Traits::Address &src,
471 typename Traits::Cond::CmppsCond CmpCondition);
472
473 void sqrtps(typename Traits::XmmRegister dst);
474 void rsqrtps(typename Traits::XmmRegister dst);
475 void reciprocalps(typename Traits::XmmRegister dst);
John Porto2fea26c2015-07-28 16:28:07 -0700476
John Porto5d0acff2015-06-30 15:29:21 -0700477 void movhlps(typename Traits::XmmRegister dst,
478 typename Traits::XmmRegister src);
479 void movlhps(typename Traits::XmmRegister dst,
480 typename Traits::XmmRegister src);
481 void unpcklps(typename Traits::XmmRegister dst,
482 typename Traits::XmmRegister src);
483 void unpckhps(typename Traits::XmmRegister dst,
484 typename Traits::XmmRegister src);
485 void unpcklpd(typename Traits::XmmRegister dst,
486 typename Traits::XmmRegister src);
487 void unpckhpd(typename Traits::XmmRegister dst,
488 typename Traits::XmmRegister src);
489
490 void set1ps(typename Traits::XmmRegister dst,
491 typename Traits::GPRRegister tmp, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700492
493 void minpd(typename Traits::XmmRegister dst,
494 typename Traits::XmmRegister src);
495 void maxpd(typename Traits::XmmRegister dst,
496 typename Traits::XmmRegister src);
497 void sqrtpd(typename Traits::XmmRegister dst);
John Porto5d0acff2015-06-30 15:29:21 -0700498
499 void pshufd(Type Ty, typename Traits::XmmRegister dst,
500 typename Traits::XmmRegister src, const Immediate &mask);
501 void pshufd(Type Ty, typename Traits::XmmRegister dst,
502 const typename Traits::Address &src, const Immediate &mask);
503 void shufps(Type Ty, typename Traits::XmmRegister dst,
504 typename Traits::XmmRegister src, const Immediate &mask);
505 void shufps(Type Ty, typename Traits::XmmRegister dst,
506 const typename Traits::Address &src, const Immediate &mask);
507
508 void cvtdq2ps(Type, typename Traits::XmmRegister dst,
509 typename Traits::XmmRegister src);
510 void cvtdq2ps(Type, typename Traits::XmmRegister dst,
511 const typename Traits::Address &src);
512
513 void cvttps2dq(Type, typename Traits::XmmRegister dst,
514 typename Traits::XmmRegister src);
515 void cvttps2dq(Type, typename Traits::XmmRegister dst,
516 const typename Traits::Address &src);
517
John Porto1d235422015-08-12 12:37:53 -0700518 void cvtsi2ss(Type DestTy, typename Traits::XmmRegister dst, Type SrcTy,
John Porto5d0acff2015-06-30 15:29:21 -0700519 typename Traits::GPRRegister src);
John Porto1d235422015-08-12 12:37:53 -0700520 void cvtsi2ss(Type DestTy, typename Traits::XmmRegister dst, Type SrcTy,
John Porto5d0acff2015-06-30 15:29:21 -0700521 const typename Traits::Address &src);
522
523 void cvtfloat2float(Type SrcTy, typename Traits::XmmRegister dst,
524 typename Traits::XmmRegister src);
525 void cvtfloat2float(Type SrcTy, typename Traits::XmmRegister dst,
526 const typename Traits::Address &src);
527
John Porto1d235422015-08-12 12:37:53 -0700528 void cvttss2si(Type DestTy, typename Traits::GPRRegister dst, Type SrcTy,
John Porto5d0acff2015-06-30 15:29:21 -0700529 typename Traits::XmmRegister src);
John Porto1d235422015-08-12 12:37:53 -0700530 void cvttss2si(Type DestTy, typename Traits::GPRRegister dst, Type SrcTy,
John Porto5d0acff2015-06-30 15:29:21 -0700531 const typename Traits::Address &src);
532
533 void ucomiss(Type Ty, typename Traits::XmmRegister a,
534 typename Traits::XmmRegister b);
535 void ucomiss(Type Ty, typename Traits::XmmRegister a,
536 const typename Traits::Address &b);
537
538 void movmskpd(typename Traits::GPRRegister dst,
539 typename Traits::XmmRegister src);
540 void movmskps(typename Traits::GPRRegister dst,
541 typename Traits::XmmRegister src);
542
543 void sqrtss(Type Ty, typename Traits::XmmRegister dst,
544 const typename Traits::Address &src);
545 void sqrtss(Type Ty, typename Traits::XmmRegister dst,
546 typename Traits::XmmRegister src);
547
548 void xorpd(typename Traits::XmmRegister dst,
549 const typename Traits::Address &src);
550 void xorpd(typename Traits::XmmRegister dst,
551 typename Traits::XmmRegister src);
552 void xorps(typename Traits::XmmRegister dst,
553 const typename Traits::Address &src);
554 void xorps(typename Traits::XmmRegister dst,
555 typename Traits::XmmRegister src);
556
557 void andpd(typename Traits::XmmRegister dst,
558 const typename Traits::Address &src);
559 void andpd(typename Traits::XmmRegister dst,
560 typename Traits::XmmRegister src);
561
562 void orpd(typename Traits::XmmRegister dst, typename Traits::XmmRegister src);
563
564 void insertps(Type Ty, typename Traits::XmmRegister dst,
565 typename Traits::XmmRegister src, const Immediate &imm);
566 void insertps(Type Ty, typename Traits::XmmRegister dst,
567 const typename Traits::Address &src, const Immediate &imm);
568
569 void pinsr(Type Ty, typename Traits::XmmRegister dst,
570 typename Traits::GPRRegister src, const Immediate &imm);
571 void pinsr(Type Ty, typename Traits::XmmRegister dst,
572 const typename Traits::Address &src, const Immediate &imm);
573
574 void pextr(Type Ty, typename Traits::GPRRegister dst,
575 typename Traits::XmmRegister src, const Immediate &imm);
John Porto5d0acff2015-06-30 15:29:21 -0700576
577 void pmovsxdq(typename Traits::XmmRegister dst,
578 typename Traits::XmmRegister src);
579
580 void pcmpeq(Type Ty, typename Traits::XmmRegister dst,
581 typename Traits::XmmRegister src);
582 void pcmpeq(Type Ty, typename Traits::XmmRegister dst,
583 const typename Traits::Address &src);
584 void pcmpgt(Type Ty, typename Traits::XmmRegister dst,
585 typename Traits::XmmRegister src);
586 void pcmpgt(Type Ty, typename Traits::XmmRegister dst,
587 const typename Traits::Address &src);
588
589 enum RoundingMode {
590 kRoundToNearest = 0x0,
591 kRoundDown = 0x1,
592 kRoundUp = 0x2,
593 kRoundToZero = 0x3
594 };
595 void roundsd(typename Traits::XmmRegister dst,
596 typename Traits::XmmRegister src, RoundingMode mode);
597
John Porto2fea26c2015-07-28 16:28:07 -0700598 //----------------------------------------------------------------------------
599 //
600 // Begin: X87 instructions. Only available when Traits::UsesX87.
601 //
602 //----------------------------------------------------------------------------
603 template <typename T = Traits,
604 typename = typename std::enable_if<T::UsesX87>::type>
605 void fld(Type Ty, const typename T::Address &src);
606 template <typename T = Traits,
607 typename = typename std::enable_if<T::UsesX87>::type>
608 void fstp(Type Ty, const typename T::Address &dst);
609 template <typename T = Traits,
610 typename = typename std::enable_if<T::UsesX87>::type>
611 void fstp(typename T::X87STRegister st);
John Porto5d0acff2015-06-30 15:29:21 -0700612
John Porto2fea26c2015-07-28 16:28:07 -0700613 template <typename T = Traits,
614 typename = typename std::enable_if<T::UsesX87>::type>
615 void fnstcw(const typename T::Address &dst);
616 template <typename T = Traits,
617 typename = typename std::enable_if<T::UsesX87>::type>
618 void fldcw(const typename T::Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700619
John Porto2fea26c2015-07-28 16:28:07 -0700620 template <typename T = Traits,
621 typename = typename std::enable_if<T::UsesX87>::type>
622 void fistpl(const typename T::Address &dst);
623 template <typename T = Traits,
624 typename = typename std::enable_if<T::UsesX87>::type>
625 void fistps(const typename T::Address &dst);
626 template <typename T = Traits,
627 typename = typename std::enable_if<T::UsesX87>::type>
628 void fildl(const typename T::Address &src);
629 template <typename T = Traits,
630 typename = typename std::enable_if<T::UsesX87>::type>
631 void filds(const typename T::Address &src);
John Porto5d0acff2015-06-30 15:29:21 -0700632
John Porto2fea26c2015-07-28 16:28:07 -0700633 template <typename T = Traits,
634 typename = typename std::enable_if<T::UsesX87>::type>
John Porto5d0acff2015-06-30 15:29:21 -0700635 void fincstp();
John Porto2fea26c2015-07-28 16:28:07 -0700636 //----------------------------------------------------------------------------
637 //
638 // End: X87 instructions.
639 //
640 //----------------------------------------------------------------------------
John Porto5d0acff2015-06-30 15:29:21 -0700641
642 void cmp(Type Ty, typename Traits::GPRRegister reg0,
643 typename Traits::GPRRegister reg1);
644 void cmp(Type Ty, typename Traits::GPRRegister reg,
645 const typename Traits::Address &address);
646 void cmp(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
647 void cmp(Type Ty, const typename Traits::Address &address,
648 typename Traits::GPRRegister reg);
649 void cmp(Type Ty, const typename Traits::Address &address,
650 const Immediate &imm);
651
652 void test(Type Ty, typename Traits::GPRRegister reg0,
653 typename Traits::GPRRegister reg1);
654 void test(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
655 void test(Type Ty, const typename Traits::Address &address,
656 typename Traits::GPRRegister reg);
657 void test(Type Ty, const typename Traits::Address &address,
658 const Immediate &imm);
659
660 void And(Type Ty, typename Traits::GPRRegister dst,
661 typename Traits::GPRRegister src);
662 void And(Type Ty, typename Traits::GPRRegister dst,
663 const typename Traits::Address &address);
664 void And(Type Ty, typename Traits::GPRRegister dst, const Immediate &imm);
665 void And(Type Ty, const typename Traits::Address &address,
666 typename Traits::GPRRegister reg);
667 void And(Type Ty, const typename Traits::Address &address,
668 const Immediate &imm);
669
670 void Or(Type Ty, typename Traits::GPRRegister dst,
671 typename Traits::GPRRegister src);
672 void Or(Type Ty, typename Traits::GPRRegister dst,
673 const typename Traits::Address &address);
674 void Or(Type Ty, typename Traits::GPRRegister dst, const Immediate &imm);
675 void Or(Type Ty, const typename Traits::Address &address,
676 typename Traits::GPRRegister reg);
677 void Or(Type Ty, const typename Traits::Address &address,
678 const Immediate &imm);
679
680 void Xor(Type Ty, typename Traits::GPRRegister dst,
681 typename Traits::GPRRegister src);
682 void Xor(Type Ty, typename Traits::GPRRegister dst,
683 const typename Traits::Address &address);
684 void Xor(Type Ty, typename Traits::GPRRegister dst, const Immediate &imm);
685 void Xor(Type Ty, const typename Traits::Address &address,
686 typename Traits::GPRRegister reg);
687 void Xor(Type Ty, const typename Traits::Address &address,
688 const Immediate &imm);
689
690 void add(Type Ty, typename Traits::GPRRegister dst,
691 typename Traits::GPRRegister src);
692 void add(Type Ty, typename Traits::GPRRegister reg,
693 const typename Traits::Address &address);
694 void add(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
695 void add(Type Ty, const typename Traits::Address &address,
696 typename Traits::GPRRegister reg);
697 void add(Type Ty, const typename Traits::Address &address,
698 const Immediate &imm);
699
700 void adc(Type Ty, typename Traits::GPRRegister dst,
701 typename Traits::GPRRegister src);
702 void adc(Type Ty, typename Traits::GPRRegister dst,
703 const typename Traits::Address &address);
704 void adc(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
705 void adc(Type Ty, const typename Traits::Address &address,
706 typename Traits::GPRRegister reg);
707 void adc(Type Ty, const typename Traits::Address &address,
708 const Immediate &imm);
709
710 void sub(Type Ty, typename Traits::GPRRegister dst,
711 typename Traits::GPRRegister src);
712 void sub(Type Ty, typename Traits::GPRRegister reg,
713 const typename Traits::Address &address);
714 void sub(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
715 void sub(Type Ty, const typename Traits::Address &address,
716 typename Traits::GPRRegister reg);
717 void sub(Type Ty, const typename Traits::Address &address,
718 const Immediate &imm);
719
720 void sbb(Type Ty, typename Traits::GPRRegister dst,
721 typename Traits::GPRRegister src);
722 void sbb(Type Ty, typename Traits::GPRRegister reg,
723 const typename Traits::Address &address);
724 void sbb(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
725 void sbb(Type Ty, const typename Traits::Address &address,
726 typename Traits::GPRRegister reg);
727 void sbb(Type Ty, const typename Traits::Address &address,
728 const Immediate &imm);
729
730 void cbw();
731 void cwd();
732 void cdq();
John Porto1d235422015-08-12 12:37:53 -0700733 template <typename T = Traits>
734 typename std::enable_if<T::Is64Bit, void>::type cqo();
735 template <typename T = Traits>
736 typename std::enable_if<!T::Is64Bit, void>::type cqo() {
737 llvm::report_fatal_error("CQO is only available in 64-bit x86 backends.");
738 }
John Porto5d0acff2015-06-30 15:29:21 -0700739
740 void div(Type Ty, typename Traits::GPRRegister reg);
741 void div(Type Ty, const typename Traits::Address &address);
742
743 void idiv(Type Ty, typename Traits::GPRRegister reg);
744 void idiv(Type Ty, const typename Traits::Address &address);
745
746 void imul(Type Ty, typename Traits::GPRRegister dst,
747 typename Traits::GPRRegister src);
748 void imul(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
749 void imul(Type Ty, typename Traits::GPRRegister reg,
750 const typename Traits::Address &address);
751
752 void imul(Type Ty, typename Traits::GPRRegister reg);
753 void imul(Type Ty, const typename Traits::Address &address);
754
David Sehre11f8782015-10-06 10:26:57 -0700755 void imul(Type Ty, typename Traits::GPRRegister dst,
756 typename Traits::GPRRegister src, const Immediate &imm);
757 void imul(Type Ty, typename Traits::GPRRegister dst,
758 const typename Traits::Address &address, const Immediate &imm);
759
John Porto5d0acff2015-06-30 15:29:21 -0700760 void mul(Type Ty, typename Traits::GPRRegister reg);
761 void mul(Type Ty, const typename Traits::Address &address);
762
John Porto2fea26c2015-07-28 16:28:07 -0700763 template <class T = Traits,
764 typename = typename std::enable_if<!T::Is64Bit>::type>
John Porto5d0acff2015-06-30 15:29:21 -0700765 void incl(typename Traits::GPRRegister reg);
766 void incl(const typename Traits::Address &address);
767
John Porto2fea26c2015-07-28 16:28:07 -0700768 template <class T = Traits,
769 typename = typename std::enable_if<!T::Is64Bit>::type>
John Porto5d0acff2015-06-30 15:29:21 -0700770 void decl(typename Traits::GPRRegister reg);
771 void decl(const typename Traits::Address &address);
772
773 void rol(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
774 void rol(Type Ty, typename Traits::GPRRegister operand,
775 typename Traits::GPRRegister shifter);
776 void rol(Type Ty, const typename Traits::Address &operand,
777 typename Traits::GPRRegister shifter);
778
779 void shl(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
780 void shl(Type Ty, typename Traits::GPRRegister operand,
781 typename Traits::GPRRegister shifter);
782 void shl(Type Ty, const typename Traits::Address &operand,
783 typename Traits::GPRRegister shifter);
784
785 void shr(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
786 void shr(Type Ty, typename Traits::GPRRegister operand,
787 typename Traits::GPRRegister shifter);
788 void shr(Type Ty, const typename Traits::Address &operand,
789 typename Traits::GPRRegister shifter);
790
791 void sar(Type Ty, typename Traits::GPRRegister reg, const Immediate &imm);
792 void sar(Type Ty, typename Traits::GPRRegister operand,
793 typename Traits::GPRRegister shifter);
794 void sar(Type Ty, const typename Traits::Address &address,
795 typename Traits::GPRRegister shifter);
796
797 void shld(Type Ty, typename Traits::GPRRegister dst,
798 typename Traits::GPRRegister src);
799 void shld(Type Ty, typename Traits::GPRRegister dst,
800 typename Traits::GPRRegister src, const Immediate &imm);
801 void shld(Type Ty, const typename Traits::Address &operand,
802 typename Traits::GPRRegister src);
803 void shrd(Type Ty, typename Traits::GPRRegister dst,
804 typename Traits::GPRRegister src);
805 void shrd(Type Ty, typename Traits::GPRRegister dst,
806 typename Traits::GPRRegister src, const Immediate &imm);
807 void shrd(Type Ty, const typename Traits::Address &dst,
808 typename Traits::GPRRegister src);
809
810 void neg(Type Ty, typename Traits::GPRRegister reg);
811 void neg(Type Ty, const typename Traits::Address &addr);
812 void notl(typename Traits::GPRRegister reg);
813
814 void bsf(Type Ty, typename Traits::GPRRegister dst,
815 typename Traits::GPRRegister src);
816 void bsf(Type Ty, typename Traits::GPRRegister dst,
817 const typename Traits::Address &src);
818 void bsr(Type Ty, typename Traits::GPRRegister dst,
819 typename Traits::GPRRegister src);
820 void bsr(Type Ty, typename Traits::GPRRegister dst,
821 const typename Traits::Address &src);
822
823 void bswap(Type Ty, typename Traits::GPRRegister reg);
824
825 void bt(typename Traits::GPRRegister base,
826 typename Traits::GPRRegister offset);
827
828 void ret();
829 void ret(const Immediate &imm);
830
831 // 'size' indicates size in bytes and must be in the range 1..8.
832 void nop(int size = 1);
833 void int3();
834 void hlt();
835 void ud2();
836
John Portof746f3d2015-07-11 08:29:20 -0700837 // j(Label) is fully tested.
John Porto5d0acff2015-06-30 15:29:21 -0700838 void j(typename Traits::Cond::BrCond condition, Label *label,
839 bool near = kFarJump);
840 void j(typename Traits::Cond::BrCond condition,
John Porto2fea26c2015-07-28 16:28:07 -0700841 const ConstantRelocatable *label); // not testable.
John Porto5d0acff2015-06-30 15:29:21 -0700842
843 void jmp(typename Traits::GPRRegister reg);
844 void jmp(Label *label, bool near = kFarJump);
John Porto2fea26c2015-07-28 16:28:07 -0700845 void jmp(const ConstantRelocatable *label); // not testable.
John Porto5d0acff2015-06-30 15:29:21 -0700846
847 void mfence();
848
849 void lock();
850 void cmpxchg(Type Ty, const typename Traits::Address &address,
851 typename Traits::GPRRegister reg, bool Locked);
852 void cmpxchg8b(const typename Traits::Address &address, bool Locked);
853 void xadd(Type Ty, const typename Traits::Address &address,
854 typename Traits::GPRRegister reg, bool Locked);
Andrew Scullcfa628b2015-08-20 14:23:05 -0700855 void xchg(Type Ty, typename Traits::GPRRegister reg0,
856 typename Traits::GPRRegister reg1);
John Porto5d0acff2015-06-30 15:29:21 -0700857 void xchg(Type Ty, const typename Traits::Address &address,
858 typename Traits::GPRRegister reg);
859
Andrew Scull2c862522015-08-06 08:41:53 -0700860 /// \name Intel Architecture Code Analyzer markers.
861 /// @{
862 void iaca_start();
863 void iaca_end();
864 /// @}
865
John Porto5d0acff2015-06-30 15:29:21 -0700866 void emitSegmentOverride(uint8_t prefix);
867
868 intptr_t preferredLoopAlignment() { return 16; }
869 void align(intptr_t alignment, intptr_t offset);
870 void bind(Label *label);
871
872 intptr_t CodeSize() const { return Buffer.size(); }
873
John Porto2fea26c2015-07-28 16:28:07 -0700874protected:
John Porto5d0acff2015-06-30 15:29:21 -0700875 inline void emitUint8(uint8_t value);
John Porto2fea26c2015-07-28 16:28:07 -0700876
877private:
878 static constexpr Type RexTypeIrrelevant = IceType_i32;
John Porto453660f2015-07-31 14:52:52 -0700879 static constexpr Type RexTypeForceRexW = IceType_i64;
John Porto2fea26c2015-07-28 16:28:07 -0700880 static constexpr typename Traits::GPRRegister RexRegIrrelevant =
881 Traits::GPRRegister::Encoded_Reg_eax;
882
John Porto5d0acff2015-06-30 15:29:21 -0700883 inline void emitInt16(int16_t value);
884 inline void emitInt32(int32_t value);
885 inline void emitRegisterOperand(int rm, int reg);
John Porto2fea26c2015-07-28 16:28:07 -0700886 template <typename RegType, typename RmType>
887 inline void emitXmmRegisterOperand(RegType reg, RmType rm);
John Porto5d0acff2015-06-30 15:29:21 -0700888 inline void emitFixup(AssemblerFixup *fixup);
889 inline void emitOperandSizeOverride();
890
891 void emitOperand(int rm, const typename Traits::Operand &operand);
892 void emitImmediate(Type ty, const Immediate &imm);
893 void emitComplexI8(int rm, const typename Traits::Operand &operand,
894 const Immediate &immediate);
895 void emitComplex(Type Ty, int rm, const typename Traits::Operand &operand,
896 const Immediate &immediate);
897 void emitLabel(Label *label, intptr_t instruction_size);
898 void emitLabelLink(Label *label);
899 void emitNearLabelLink(Label *label);
900
901 void emitGenericShift(int rm, Type Ty, typename Traits::GPRRegister reg,
902 const Immediate &imm);
903 void emitGenericShift(int rm, Type Ty,
904 const typename Traits::Operand &operand,
905 typename Traits::GPRRegister shifter);
906
Andrew Scull8072bae2015-09-14 16:01:26 -0700907 using LabelVector = std::vector<Label *>;
John Porto5d0acff2015-06-30 15:29:21 -0700908 // A vector of pool-allocated x86 labels for CFG nodes.
909 LabelVector CfgNodeLabels;
910 // A vector of pool-allocated x86 labels for Local labels.
911 LabelVector LocalLabels;
912
Andrew Scull86df4e92015-07-30 13:54:44 -0700913 Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
John Porto5d0acff2015-06-30 15:29:21 -0700914
Andrew Scull57e12682015-09-16 11:30:19 -0700915 // The arith_int() methods factor out the commonality between the encodings
916 // of add(), Or(), adc(), sbb(), And(), sub(), Xor(), and cmp(). The Tag
John Porto5d0acff2015-06-30 15:29:21 -0700917 // parameter is statically asserted to be less than 8.
918 template <uint32_t Tag>
919 void arith_int(Type Ty, typename Traits::GPRRegister reg,
920 const Immediate &imm);
921
922 template <uint32_t Tag>
923 void arith_int(Type Ty, typename Traits::GPRRegister reg0,
924 typename Traits::GPRRegister reg1);
925
926 template <uint32_t Tag>
927 void arith_int(Type Ty, typename Traits::GPRRegister reg,
928 const typename Traits::Address &address);
929
930 template <uint32_t Tag>
931 void arith_int(Type Ty, const typename Traits::Address &address,
932 typename Traits::GPRRegister reg);
933
934 template <uint32_t Tag>
935 void arith_int(Type Ty, const typename Traits::Address &address,
936 const Immediate &imm);
John Porto2fea26c2015-07-28 16:28:07 -0700937
938 // gprEncoding returns Reg encoding for operand emission. For x86-64 we mask
939 // out the 4th bit as it is encoded in the REX.[RXB] bits. No other bits are
940 // touched because we don't want to mask errors.
941 template <typename RegType, typename T = Traits>
942 typename std::enable_if<T::Is64Bit, typename T::GPRRegister>::type
943 gprEncoding(const RegType Reg) {
944 return static_cast<typename Traits::GPRRegister>(static_cast<uint8_t>(Reg) &
945 ~0x08);
946 }
947
948 template <typename RegType, typename T = Traits>
949 typename std::enable_if<!T::Is64Bit, typename T::GPRRegister>::type
950 gprEncoding(const RegType Reg) {
951 return static_cast<typename T::GPRRegister>(Reg);
952 }
953
954 template <typename RegType>
955 bool is8BitRegisterRequiringRex(const Type Ty, const RegType Reg) {
956 static constexpr bool IsGPR =
957 std::is_same<typename std::decay<RegType>::type,
958 typename Traits::ByteRegister>::value ||
959 std::is_same<typename std::decay<RegType>::type,
960 typename Traits::GPRRegister>::value;
961
962 return IsGPR && (Reg & 0x04) != 0 && (Reg & 0x08) == 0 &&
John Porto1d235422015-08-12 12:37:53 -0700963 isByteSizedType(Ty);
Jim Stichnotha8d47132015-09-08 14:43:38 -0700964 }
John Porto2fea26c2015-07-28 16:28:07 -0700965
Andrew Scull57e12682015-09-16 11:30:19 -0700966 // assembleAndEmitRex is used for determining which (if any) rex prefix
967 // should be emitted for the current instruction. It allows different types
968 // for Reg and Rm because they could be of different types (e.g., in mov[sz]x
969 // instructions.) If Addr is not nullptr, then Rm is ignored, and Rex.B is
John Porto2fea26c2015-07-28 16:28:07 -0700970 // determined by Addr instead. TyRm is still used to determine Addr's size.
971 template <typename RegType, typename RmType, typename T = Traits>
972 typename std::enable_if<T::Is64Bit, void>::type
973 assembleAndEmitRex(const Type TyReg, const RegType Reg, const Type TyRm,
974 const RmType Rm,
975 const typename T::Address *Addr = nullptr) {
976 const uint8_t W = (TyReg == IceType_i64 || TyRm == IceType_i64)
977 ? T::Operand::RexW
978 : T::Operand::RexNone;
979 const uint8_t R = (Reg & 0x08) ? T::Operand::RexR : T::Operand::RexNone;
Jim Stichnotha8d47132015-09-08 14:43:38 -0700980 const uint8_t X = (Addr != nullptr)
981 ? (typename T::Operand::RexBits)Addr->rexX()
982 : T::Operand::RexNone;
John Porto2fea26c2015-07-28 16:28:07 -0700983 const uint8_t B =
Jim Stichnotha8d47132015-09-08 14:43:38 -0700984 (Addr != nullptr)
985 ? (typename T::Operand::RexBits)Addr->rexB()
986 : (Rm & 0x08) ? T::Operand::RexB : T::Operand::RexNone;
John Porto2fea26c2015-07-28 16:28:07 -0700987 const uint8_t Prefix = W | R | X | B;
988 if (Prefix != T::Operand::RexNone) {
989 emitUint8(Prefix);
990 } else if (is8BitRegisterRequiringRex(TyReg, Reg) ||
991 (Addr == nullptr && is8BitRegisterRequiringRex(TyRm, Rm))) {
992 emitUint8(T::Operand::RexBase);
993 }
994 }
995
996 template <typename RegType, typename RmType, typename T = Traits>
997 typename std::enable_if<!T::Is64Bit, void>::type
998 assembleAndEmitRex(const Type, const RegType, const Type, const RmType,
999 const typename T::Address * = nullptr) {}
1000
1001 // emitRexRB is used for emitting a Rex prefix instructions with two explicit
1002 // register operands in its mod-rm byte.
1003 template <typename RegType, typename RmType>
1004 void emitRexRB(const Type Ty, const RegType Reg, const RmType Rm) {
1005 assembleAndEmitRex(Ty, Reg, Ty, Rm);
1006 }
1007
1008 template <typename RegType, typename RmType>
1009 void emitRexRB(const Type TyReg, const RegType Reg, const Type TyRm,
1010 const RmType Rm) {
1011 assembleAndEmitRex(TyReg, Reg, TyRm, Rm);
1012 }
1013
Andrew Scull57e12682015-09-16 11:30:19 -07001014 // emitRexB is used for emitting a Rex prefix if one is needed on encoding
1015 // the Reg field in an x86 instruction. It is invoked by the template when
1016 // Reg is the single register operand in the instruction (e.g., push Reg.)
John Porto2fea26c2015-07-28 16:28:07 -07001017 template <typename RmType> void emitRexB(const Type Ty, const RmType Rm) {
1018 emitRexRB(Ty, RexRegIrrelevant, Ty, Rm);
1019 }
1020
1021 // emitRex is used for emitting a Rex prefix for an address and a GPR. The
1022 // address may contain zero, one, or two registers.
1023 template <typename RegType>
1024 void emitRex(const Type Ty, const typename Traits::Address &Addr,
1025 const RegType Reg) {
1026 assembleAndEmitRex(Ty, Reg, Ty, RexRegIrrelevant, &Addr);
1027 }
1028
1029 template <typename RegType>
1030 void emitRex(const Type AddrTy, const typename Traits::Address &Addr,
1031 const Type TyReg, const RegType Reg) {
1032 assembleAndEmitRex(TyReg, Reg, AddrTy, RexRegIrrelevant, &Addr);
1033 }
John Porto5d0acff2015-06-30 15:29:21 -07001034};
1035
1036template <class Machine>
1037inline void AssemblerX86Base<Machine>::emitUint8(uint8_t value) {
1038 Buffer.emit<uint8_t>(value);
1039}
1040
1041template <class Machine>
1042inline void AssemblerX86Base<Machine>::emitInt16(int16_t value) {
1043 Buffer.emit<int16_t>(value);
1044}
1045
1046template <class Machine>
1047inline void AssemblerX86Base<Machine>::emitInt32(int32_t value) {
1048 Buffer.emit<int32_t>(value);
1049}
1050
1051template <class Machine>
John Porto2fea26c2015-07-28 16:28:07 -07001052inline void AssemblerX86Base<Machine>::emitRegisterOperand(int reg, int rm) {
1053 assert(reg >= 0 && reg < 8);
John Porto5d0acff2015-06-30 15:29:21 -07001054 assert(rm >= 0 && rm < 8);
John Porto2fea26c2015-07-28 16:28:07 -07001055 Buffer.emit<uint8_t>(0xC0 + (reg << 3) + rm);
John Porto5d0acff2015-06-30 15:29:21 -07001056}
1057
1058template <class Machine>
John Porto2fea26c2015-07-28 16:28:07 -07001059template <typename RegType, typename RmType>
1060inline void AssemblerX86Base<Machine>::emitXmmRegisterOperand(RegType reg,
1061 RmType rm) {
1062 emitRegisterOperand(gprEncoding(reg), gprEncoding(rm));
John Porto5d0acff2015-06-30 15:29:21 -07001063}
1064
1065template <class Machine>
1066inline void AssemblerX86Base<Machine>::emitFixup(AssemblerFixup *fixup) {
1067 Buffer.emitFixup(fixup);
1068}
1069
1070template <class Machine>
1071inline void AssemblerX86Base<Machine>::emitOperandSizeOverride() {
1072 emitUint8(0x66);
1073}
1074
1075} // end of namespace X86Internal
1076
John Porto5d0acff2015-06-30 15:29:21 -07001077} // end of namespace Ice
1078
1079#include "IceAssemblerX86BaseImpl.h"
1080
1081#endif // SUBZERO_SRC_ICEASSEMBLERX86BASE_H