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