blob: d38dca78b897a3fa3ab9e6b8c9d7203cc2a33109 [file] [log] [blame]
Jan Voungf76fd372014-10-16 15:39:22 -07001//===- subzero/src/assembler_ia32.h - Assembler for x86-32 ------*- C++ -*-===//
Jan Voung8acded02014-09-22 18:02:25 -07002// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
3// for details. All rights reserved. Use of this source code is governed by a
4// BSD-style license that can be found in the LICENSE file.
5//
6// Modified by the Subzero authors.
7//
Jan Voungf76fd372014-10-16 15:39:22 -07008//===----------------------------------------------------------------------===//
Jan Voung8acded02014-09-22 18:02:25 -07009//
10// The Subzero Code Generator
11//
12// This file is distributed under the University of Illinois Open Source
13// License. See LICENSE.TXT for details.
14//
15//===----------------------------------------------------------------------===//
16//
17// This file implements the Assembler class for x86-32.
18//
19//===----------------------------------------------------------------------===//
20
21#ifndef SUBZERO_SRC_ASSEMBLER_IA32_H_
22#define SUBZERO_SRC_ASSEMBLER_IA32_H_
23
Jan Voung8acded02014-09-22 18:02:25 -070024#include "IceConditionCodesX8632.h"
Jan Voungfe14fb82014-10-13 15:56:32 -070025#include "IceDefs.h"
26#include "IceOperand.h"
Jan Voung8acded02014-09-22 18:02:25 -070027#include "IceRegistersX8632.h"
28#include "IceTypes.h"
29#include "IceUtils.h"
30
31#include "assembler.h"
32
33namespace Ice {
34
35class Assembler;
Jan Voung8acded02014-09-22 18:02:25 -070036
37using RegX8632::GPRRegister;
38using RegX8632::XmmRegister;
39using RegX8632::ByteRegister;
Jan Voung479e5632014-10-08 21:05:27 -070040using RegX8632::X87STRegister;
Jan Voung8acded02014-09-22 18:02:25 -070041
42namespace x86 {
43
44const int MAX_NOP_SIZE = 8;
45
46enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
47
48class DisplacementRelocation : public AssemblerFixup {
Jan Voungf76fd372014-10-16 15:39:22 -070049 DisplacementRelocation(const DisplacementRelocation &) = delete;
50 DisplacementRelocation &operator=(const DisplacementRelocation &) = delete;
51
Jan Voung8acded02014-09-22 18:02:25 -070052public:
53 static DisplacementRelocation *create(Assembler *Asm, FixupKind Kind,
54 const ConstantRelocatable *Sym) {
55 return new (Asm->Allocate<DisplacementRelocation>())
56 DisplacementRelocation(Kind, Sym);
57 }
58
Jan Voung8acded02014-09-22 18:02:25 -070059private:
60 DisplacementRelocation(FixupKind Kind, const ConstantRelocatable *Sym)
61 : AssemblerFixup(Kind, Sym) {}
Jan Voung8acded02014-09-22 18:02:25 -070062};
63
64class Immediate {
Jan Voungf76fd372014-10-16 15:39:22 -070065 Immediate(const Immediate &) = delete;
66 Immediate &operator=(const Immediate &) = delete;
67
Jan Voung8acded02014-09-22 18:02:25 -070068public:
Jan Voung359c0362014-11-04 10:40:03 -080069 explicit Immediate(int32_t value) : value_(value), fixup_(nullptr) {}
Jan Voung8acded02014-09-22 18:02:25 -070070
Jan Voungfe14fb82014-10-13 15:56:32 -070071 explicit Immediate(AssemblerFixup *fixup)
72 : value_(fixup->value()->getOffset()), fixup_(fixup) {
73 // Use the Offset in the "value" for now. If the symbol is part of
74 // ".bss", then the relocation's symbol will be plain ".bss" and
75 // the value will need to be adjusted further to be sym's
76 // bss offset + Offset.
77 }
Jan Voung8acded02014-09-22 18:02:25 -070078
79 int32_t value() const { return value_; }
Jan Voungfe14fb82014-10-13 15:56:32 -070080 AssemblerFixup *fixup() const { return fixup_; }
Jan Voung8acded02014-09-22 18:02:25 -070081
Jan Voungfe14fb82014-10-13 15:56:32 -070082 bool is_int8() const {
83 // We currently only allow 32-bit fixups, and they usually have value = 0,
Jan Voung359c0362014-11-04 10:40:03 -080084 // so if fixup_ != nullptr, it shouldn't be classified as int8/16.
85 return fixup_ == nullptr && Utils::IsInt(8, value_);
Jan Voungfe14fb82014-10-13 15:56:32 -070086 }
Jan Voung359c0362014-11-04 10:40:03 -080087 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 }
Jan Voung8acded02014-09-22 18:02:25 -070093
94private:
95 const int32_t value_;
Jan Voungfe14fb82014-10-13 15:56:32 -070096 AssemblerFixup *fixup_;
Jan Voung8acded02014-09-22 18:02:25 -070097};
98
99class Operand {
100public:
Jan Voungf76fd372014-10-16 15:39:22 -0700101 Operand(const Operand &other) : length_(other.length_), fixup_(other.fixup_) {
102 memmove(&encoding_[0], &other.encoding_[0], other.length_);
103 }
104
105 Operand &operator=(const Operand &other) {
106 length_ = other.length_;
107 fixup_ = other.fixup_;
108 memmove(&encoding_[0], &other.encoding_[0], other.length_);
109 return *this;
110 }
111
Jan Voung8acded02014-09-22 18:02:25 -0700112 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
113
114 GPRRegister rm() const {
115 return static_cast<GPRRegister>(encoding_at(0) & 7);
116 }
117
118 ScaleFactor scale() const {
119 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
120 }
121
122 GPRRegister index() const {
123 return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
124 }
125
126 GPRRegister base() const {
127 return static_cast<GPRRegister>(encoding_at(1) & 7);
128 }
129
130 int8_t disp8() const {
131 assert(length_ >= 2);
132 return static_cast<int8_t>(encoding_[length_ - 1]);
133 }
134
135 int32_t disp32() const {
136 assert(length_ >= 5);
137 return bit_copy<int32_t>(encoding_[length_ - 4]);
138 }
139
140 AssemblerFixup *fixup() const { return fixup_; }
141
Jan Voung8acded02014-09-22 18:02:25 -0700142protected:
Jan Voung359c0362014-11-04 10:40:03 -0800143 Operand() : length_(0), fixup_(nullptr) {} // Needed by subclass Address.
Jan Voung8acded02014-09-22 18:02:25 -0700144
145 void SetModRM(int mod, GPRRegister rm) {
146 assert((mod & ~3) == 0);
147 encoding_[0] = (mod << 6) | rm;
148 length_ = 1;
149 }
150
151 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
152 assert(length_ == 1);
153 assert((scale & ~3) == 0);
154 encoding_[1] = (scale << 6) | (index << 3) | base;
155 length_ = 2;
156 }
157
158 void SetDisp8(int8_t disp) {
159 assert(length_ == 1 || length_ == 2);
160 encoding_[length_++] = static_cast<uint8_t>(disp);
161 }
162
163 void SetDisp32(int32_t disp) {
164 assert(length_ == 1 || length_ == 2);
165 intptr_t disp_size = sizeof(disp);
166 memmove(&encoding_[length_], &disp, disp_size);
167 length_ += disp_size;
168 }
169
170 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
171
172private:
173 uint8_t length_;
174 uint8_t encoding_[6];
Jan Voung8acded02014-09-22 18:02:25 -0700175 AssemblerFixup *fixup_;
176
Jan Voung359c0362014-11-04 10:40:03 -0800177 explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
Jan Voung8acded02014-09-22 18:02:25 -0700178
179 // Get the operand encoding byte at the given index.
180 uint8_t encoding_at(intptr_t index) const {
181 assert(index >= 0 && index < length_);
182 return encoding_[index];
183 }
184
185 // Returns whether or not this operand is really the given register in
186 // disguise. Used from the assembler to generate better encodings.
187 bool IsRegister(GPRRegister reg) const {
188 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
189 && ((encoding_[0] & 0x07) == reg); // Register codes match.
190 }
191
192 friend class AssemblerX86;
193};
194
195class Address : public Operand {
196public:
Jan Voungf76fd372014-10-16 15:39:22 -0700197 Address(const Address &other) : Operand(other) {}
198
199 Address &operator=(const Address &other) {
200 Operand::operator=(other);
201 return *this;
202 }
203
Jan Voung8acded02014-09-22 18:02:25 -0700204 Address(GPRRegister base, int32_t disp) {
205 if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
206 SetModRM(0, base);
207 if (base == RegX8632::Encoded_Reg_esp)
208 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
209 } else if (Utils::IsInt(8, disp)) {
210 SetModRM(1, base);
211 if (base == RegX8632::Encoded_Reg_esp)
212 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
213 SetDisp8(disp);
214 } else {
215 SetModRM(2, base);
216 if (base == RegX8632::Encoded_Reg_esp)
217 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
218 SetDisp32(disp);
219 }
220 }
221
222 Address(GPRRegister index, ScaleFactor scale, int32_t disp) {
223 assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
224 SetModRM(0, RegX8632::Encoded_Reg_esp);
225 SetSIB(scale, index, RegX8632::Encoded_Reg_ebp);
226 SetDisp32(disp);
227 }
228
229 Address(GPRRegister base, GPRRegister index, ScaleFactor scale,
230 int32_t disp) {
231 assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
232 if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
233 SetModRM(0, RegX8632::Encoded_Reg_esp);
234 SetSIB(scale, index, base);
235 } else if (Utils::IsInt(8, disp)) {
236 SetModRM(1, RegX8632::Encoded_Reg_esp);
237 SetSIB(scale, index, base);
238 SetDisp8(disp);
239 } else {
240 SetModRM(2, RegX8632::Encoded_Reg_esp);
241 SetSIB(scale, index, base);
242 SetDisp32(disp);
243 }
244 }
245
Jan Voungfe14fb82014-10-13 15:56:32 -0700246 static Address Absolute(const uintptr_t addr) {
Jan Voung8acded02014-09-22 18:02:25 -0700247 Address result;
248 result.SetModRM(0, RegX8632::Encoded_Reg_ebp);
249 result.SetDisp32(addr);
Jan Voungfe14fb82014-10-13 15:56:32 -0700250 return result;
251 }
252
253 static Address Absolute(AssemblerFixup *fixup) {
254 Address result;
255 result.SetModRM(0, RegX8632::Encoded_Reg_ebp);
256 // Use the Offset in the displacement for now. If the symbol is part of
257 // ".bss", then the relocation's symbol will be plain .bss and the
258 // displacement will need to be adjusted further to be sym's
259 // bss offset + Offset.
260 result.SetDisp32(fixup->value()->getOffset());
Jan Voung8acded02014-09-22 18:02:25 -0700261 result.SetFixup(fixup);
262 return result;
263 }
264
265 static Address ofConstPool(GlobalContext *Ctx, Assembler *Asm,
266 const Constant *Imm);
267
268private:
269 Address() {} // Needed by Address::Absolute.
270};
271
272class Label {
Jan Voungf76fd372014-10-16 15:39:22 -0700273 Label(const Label &) = delete;
274 Label &operator=(const Label &) = delete;
275
Jan Voung8acded02014-09-22 18:02:25 -0700276public:
277 Label() : position_(0), num_unresolved_(0) {
Jan Voungf76fd372014-10-16 15:39:22 -0700278#ifndef NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -0700279 for (int i = 0; i < kMaxUnresolvedBranches; i++) {
280 unresolved_near_positions_[i] = -1;
281 }
Jan Voungf76fd372014-10-16 15:39:22 -0700282#endif // !NDEBUG
Jan Voung8acded02014-09-22 18:02:25 -0700283 }
284
Jan Voung7e1e4852014-10-24 10:29:30 -0700285 ~Label() {}
286
287 void FinalCheck() const {
Jan Voung8acded02014-09-22 18:02:25 -0700288 // Assert if label is being destroyed with unresolved branches pending.
289 assert(!IsLinked());
290 assert(!HasNear());
291 }
292
293 // TODO(jvoung): why are labels offset by this?
294 static const uint32_t kWordSize = sizeof(uint32_t);
295
296 // Returns the position for bound labels (branches that come after this
297 // are considered backward branches). Cannot be used for unused or linked
298 // labels.
299 intptr_t Position() const {
300 assert(IsBound());
301 return -position_ - kWordSize;
302 }
303
304 // Returns the position of an earlier branch instruction that was linked
305 // to this label (branches that use this are considered forward branches).
306 // The linked instructions form a linked list, of sorts, using the
307 // instruction's displacement field for the location of the next
308 // instruction that is also linked to this label.
309 intptr_t LinkPosition() const {
310 assert(IsLinked());
311 return position_ - kWordSize;
312 }
313
314 // Returns the position of an earlier branch instruction which
315 // assumes that this label is "near", and bumps iterator to the
316 // next near position.
317 intptr_t NearPosition() {
318 assert(HasNear());
319 return unresolved_near_positions_[--num_unresolved_];
320 }
321
322 bool IsBound() const { return position_ < 0; }
323 bool IsLinked() const { return position_ > 0; }
324 bool IsUnused() const { return (position_ == 0) && (num_unresolved_ == 0); }
325 bool HasNear() const { return num_unresolved_ != 0; }
326
327private:
328 void BindTo(intptr_t position) {
329 assert(!IsBound());
330 assert(!HasNear());
331 position_ = -position - kWordSize;
332 assert(IsBound());
333 }
334
335 void LinkTo(intptr_t position) {
336 assert(!IsBound());
337 position_ = position + kWordSize;
338 assert(IsLinked());
339 }
340
341 void NearLinkTo(intptr_t position) {
342 assert(!IsBound());
343 assert(num_unresolved_ < kMaxUnresolvedBranches);
344 unresolved_near_positions_[num_unresolved_++] = position;
345 }
346
347 static const int kMaxUnresolvedBranches = 20;
348
349 intptr_t position_;
350 intptr_t num_unresolved_;
351 intptr_t unresolved_near_positions_[kMaxUnresolvedBranches];
352
353 friend class AssemblerX86;
Jan Voung8acded02014-09-22 18:02:25 -0700354};
355
356class AssemblerX86 : public Assembler {
Jan Voungf76fd372014-10-16 15:39:22 -0700357 AssemblerX86(const AssemblerX86 &) = delete;
358 AssemblerX86 &operator=(const AssemblerX86 &) = delete;
359
Jan Voung8acded02014-09-22 18:02:25 -0700360public:
Jan Voung0faec4c2014-11-05 17:29:56 -0800361 explicit AssemblerX86(bool use_far_branches = false) : Assembler() {
Jan Voung8acded02014-09-22 18:02:25 -0700362 // This mode is only needed and implemented for MIPS and ARM.
363 assert(!use_far_branches);
Jim Stichnoth9c234e22014-10-01 09:28:21 -0700364 (void)use_far_branches;
Jan Voung8acded02014-09-22 18:02:25 -0700365 }
Jan Voung7e1e4852014-10-24 10:29:30 -0700366 ~AssemblerX86() override;
Jan Voung8acded02014-09-22 18:02:25 -0700367
368 static const bool kNearJump = true;
369 static const bool kFarJump = false;
370
Jan Voung08c3bcd2014-12-01 17:55:16 -0800371 void alignFunction() override;
372
373 SizeT getBundleAlignLog2Bytes() const override { return 5; }
374
375 llvm::ArrayRef<uint8_t> getNonExecBundlePadding() const override {
376 static const uint8_t Padding[] = {0xF4};
377 return llvm::ArrayRef<uint8_t>(Padding, 1);
378 }
379
Jan Voung7e1e4852014-10-24 10:29:30 -0700380 Label *GetOrCreateCfgNodeLabel(SizeT NodeNumber);
381 void BindCfgNodeLabel(SizeT NodeNumber) override;
382 Label *GetOrCreateLocalLabel(SizeT Number);
383 void BindLocalLabel(SizeT Number);
384
Jan Voung3b43b892014-09-24 13:32:39 -0700385 // Operations to emit GPR instructions (and dispatch on operand type).
386 typedef void (AssemblerX86::*TypedEmitGPR)(Type, GPRRegister);
387 typedef void (AssemblerX86::*TypedEmitAddr)(Type, const Address &);
388 struct GPREmitterOneOp {
389 TypedEmitGPR Reg;
390 TypedEmitAddr Addr;
391 };
392
393 typedef void (AssemblerX86::*TypedEmitGPRGPR)(Type, GPRRegister, GPRRegister);
394 typedef void (AssemblerX86::*TypedEmitGPRAddr)(Type, GPRRegister,
395 const Address &);
396 typedef void (AssemblerX86::*TypedEmitGPRImm)(Type, GPRRegister,
397 const Immediate &);
398 struct GPREmitterRegOp {
399 TypedEmitGPRGPR GPRGPR;
400 TypedEmitGPRAddr GPRAddr;
401 TypedEmitGPRImm GPRImm;
402 };
403
Jan Voung8bcca042014-10-03 21:58:02 -0700404 struct GPREmitterShiftOp {
Jan Voung8bcca042014-10-03 21:58:02 -0700405 // Technically, Addr/GPR and Addr/Imm are also allowed, but */Addr are not.
406 // In practice, we always normalize the Dest to a Register first.
Jan Voung962befa2014-10-15 09:32:58 -0700407 TypedEmitGPRGPR GPRGPR;
408 TypedEmitGPRImm GPRImm;
409 };
410
411 typedef void (AssemblerX86::*TypedEmitGPRGPRImm)(Type, GPRRegister,
412 GPRRegister,
413 const Immediate &);
414 struct GPREmitterShiftD {
415 // Technically AddrGPR and AddrGPRImm are also allowed, but in practice
416 // we always normalize Dest to a Register first.
417 TypedEmitGPRGPR GPRGPR;
418 TypedEmitGPRGPRImm GPRGPRImm;
Jan Voung8bcca042014-10-03 21:58:02 -0700419 };
420
Jan Vounge4dc61b2014-10-06 08:53:52 -0700421 typedef void (AssemblerX86::*TypedEmitAddrGPR)(Type, const Address &,
422 GPRRegister);
423 typedef void (AssemblerX86::*TypedEmitAddrImm)(Type, const Address &,
424 const Immediate &);
425 struct GPREmitterAddrOp {
426 TypedEmitAddrGPR AddrGPR;
427 TypedEmitAddrImm AddrImm;
428 };
429
Jan Voung8acded02014-09-22 18:02:25 -0700430 // Operations to emit XMM instructions (and dispatch on operand type).
431 typedef void (AssemblerX86::*TypedEmitXmmXmm)(Type, XmmRegister, XmmRegister);
432 typedef void (AssemblerX86::*TypedEmitXmmAddr)(Type, XmmRegister,
433 const Address &);
Jan Vounge4dc61b2014-10-06 08:53:52 -0700434 struct XmmEmitterRegOp {
Jan Voung8acded02014-09-22 18:02:25 -0700435 TypedEmitXmmXmm XmmXmm;
436 TypedEmitXmmAddr XmmAddr;
Jan Vounge4dc61b2014-10-06 08:53:52 -0700437 };
438
439 typedef void (AssemblerX86::*EmitXmmXmm)(XmmRegister, XmmRegister);
440 typedef void (AssemblerX86::*EmitXmmAddr)(XmmRegister, const Address &);
441 typedef void (AssemblerX86::*EmitAddrXmm)(const Address &, XmmRegister);
442 struct XmmEmitterMovOps {
443 EmitXmmXmm XmmXmm;
444 EmitXmmAddr XmmAddr;
445 EmitAddrXmm AddrXmm;
Jan Voung8acded02014-09-22 18:02:25 -0700446 };
447
Jan Voung8bcca042014-10-03 21:58:02 -0700448 typedef void (AssemblerX86::*TypedEmitXmmImm)(Type, XmmRegister,
449 const Immediate &);
450
451 struct XmmEmitterShiftOp {
452 TypedEmitXmmXmm XmmXmm;
453 TypedEmitXmmAddr XmmAddr;
454 TypedEmitXmmImm XmmImm;
455 };
456
Jan Voung699bf022014-10-08 13:52:10 -0700457 // Cross Xmm/GPR cast instructions.
458 template <typename DReg_t, typename SReg_t> struct CastEmitterRegOp {
459 typedef void (AssemblerX86::*TypedEmitRegs)(Type, DReg_t, SReg_t);
460 typedef void (AssemblerX86::*TypedEmitAddr)(Type, DReg_t, const Address &);
461
462 TypedEmitRegs RegReg;
463 TypedEmitAddr RegAddr;
464 };
465
Jan Voung962befa2014-10-15 09:32:58 -0700466 // Three operand (potentially) cross Xmm/GPR instructions.
467 // The last operand must be an immediate.
468 template <typename DReg_t, typename SReg_t> struct ThreeOpImmEmitter {
469 typedef void (AssemblerX86::*TypedEmitRegRegImm)(Type, DReg_t, SReg_t,
470 const Immediate &);
471 typedef void (AssemblerX86::*TypedEmitRegAddrImm)(Type, DReg_t,
472 const Address &,
473 const Immediate &);
474
475 TypedEmitRegRegImm RegRegImm;
476 TypedEmitRegAddrImm RegAddrImm;
477 };
478
Jan Voung8acded02014-09-22 18:02:25 -0700479 /*
480 * Emit Machine Instructions.
481 */
482 void call(GPRRegister reg);
483 void call(const Address &address);
Jan Voung8acded02014-09-22 18:02:25 -0700484 void call(const ConstantRelocatable *label);
485
486 static const intptr_t kCallExternalLabelSize = 5;
487
488 void pushl(GPRRegister reg);
Jan Voung8acded02014-09-22 18:02:25 -0700489
490 void popl(GPRRegister reg);
491 void popl(const Address &address);
492
493 void pushal();
494 void popal();
495
496 void setcc(CondX86::BrCond condition, ByteRegister dst);
497
Jan Voungfe14fb82014-10-13 15:56:32 -0700498 void mov(Type Ty, GPRRegister dst, const Immediate &src);
499 void mov(Type Ty, GPRRegister dst, GPRRegister src);
Jan Voung8acded02014-09-22 18:02:25 -0700500
Jan Voungfe14fb82014-10-13 15:56:32 -0700501 void mov(Type Ty, GPRRegister dst, const Address &src);
502 void mov(Type Ty, const Address &dst, GPRRegister src);
503 void mov(Type Ty, const Address &dst, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700504
Jan Voung39d4aca2014-10-15 15:16:54 -0700505 void movzx(Type Ty, GPRRegister dst, GPRRegister src);
506 void movzx(Type Ty, GPRRegister dst, const Address &src);
507 void movsx(Type Ty, GPRRegister dst, GPRRegister src);
508 void movsx(Type Ty, GPRRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700509
Jan Voung3b43b892014-09-24 13:32:39 -0700510 void lea(Type Ty, GPRRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700511
512 void cmov(CondX86::BrCond cond, GPRRegister dst, GPRRegister src);
513
514 void rep_movsb();
515
Jan Voung479e5632014-10-08 21:05:27 -0700516 void movss(Type Ty, XmmRegister dst, const Address &src);
517 void movss(Type Ty, const Address &dst, XmmRegister src);
518 void movss(Type Ty, XmmRegister dst, XmmRegister src);
Jan Voung8acded02014-09-22 18:02:25 -0700519
520 void movd(XmmRegister dst, GPRRegister src);
Jan Voung3b43b892014-09-24 13:32:39 -0700521 void movd(XmmRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700522 void movd(GPRRegister dst, XmmRegister src);
Jan Voung3b43b892014-09-24 13:32:39 -0700523 void movd(const Address &dst, XmmRegister src);
Jan Voung8acded02014-09-22 18:02:25 -0700524
Jan Vounge4dc61b2014-10-06 08:53:52 -0700525 void movq(XmmRegister dst, XmmRegister src);
Jan Voung8acded02014-09-22 18:02:25 -0700526 void movq(const Address &dst, XmmRegister src);
527 void movq(XmmRegister dst, const Address &src);
528
529 void addss(Type Ty, XmmRegister dst, XmmRegister src);
530 void addss(Type Ty, XmmRegister dst, const Address &src);
531 void subss(Type Ty, XmmRegister dst, XmmRegister src);
532 void subss(Type Ty, XmmRegister dst, const Address &src);
533 void mulss(Type Ty, XmmRegister dst, XmmRegister src);
534 void mulss(Type Ty, XmmRegister dst, const Address &src);
535 void divss(Type Ty, XmmRegister dst, XmmRegister src);
536 void divss(Type Ty, XmmRegister dst, const Address &src);
537
Jan Voung8acded02014-09-22 18:02:25 -0700538 void movaps(XmmRegister dst, XmmRegister src);
539
Jan Vounge4dc61b2014-10-06 08:53:52 -0700540 void movups(XmmRegister dst, XmmRegister src);
Jan Voung8acded02014-09-22 18:02:25 -0700541 void movups(XmmRegister dst, const Address &src);
542 void movups(const Address &dst, XmmRegister src);
543
544 void padd(Type Ty, XmmRegister dst, XmmRegister src);
545 void padd(Type Ty, XmmRegister dst, const Address &src);
546 void pand(Type Ty, XmmRegister dst, XmmRegister src);
547 void pand(Type Ty, XmmRegister dst, const Address &src);
548 void pandn(Type Ty, XmmRegister dst, XmmRegister src);
549 void pandn(Type Ty, XmmRegister dst, const Address &src);
Jan Voung8bcca042014-10-03 21:58:02 -0700550 void pmull(Type Ty, XmmRegister dst, XmmRegister src);
551 void pmull(Type Ty, XmmRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700552 void pmuludq(Type Ty, XmmRegister dst, XmmRegister src);
553 void pmuludq(Type Ty, XmmRegister dst, const Address &src);
554 void por(Type Ty, XmmRegister dst, XmmRegister src);
555 void por(Type Ty, XmmRegister dst, const Address &src);
556 void psub(Type Ty, XmmRegister dst, XmmRegister src);
557 void psub(Type Ty, XmmRegister dst, const Address &src);
558 void pxor(Type Ty, XmmRegister dst, XmmRegister src);
559 void pxor(Type Ty, XmmRegister dst, const Address &src);
560
Jan Voung8bcca042014-10-03 21:58:02 -0700561 void psll(Type Ty, XmmRegister dst, XmmRegister src);
562 void psll(Type Ty, XmmRegister dst, const Address &src);
563 void psll(Type Ty, XmmRegister dst, const Immediate &src);
564
565 void psra(Type Ty, XmmRegister dst, XmmRegister src);
566 void psra(Type Ty, XmmRegister dst, const Address &src);
567 void psra(Type Ty, XmmRegister dst, const Immediate &src);
568
Jan Voung8acded02014-09-22 18:02:25 -0700569 void addps(Type Ty, XmmRegister dst, XmmRegister src);
570 void addps(Type Ty, XmmRegister dst, const Address &src);
571 void subps(Type Ty, XmmRegister dst, XmmRegister src);
572 void subps(Type Ty, XmmRegister dst, const Address &src);
573 void divps(Type Ty, XmmRegister dst, XmmRegister src);
574 void divps(Type Ty, XmmRegister dst, const Address &src);
575 void mulps(Type Ty, XmmRegister dst, XmmRegister src);
576 void mulps(Type Ty, XmmRegister dst, const Address &src);
577 void minps(XmmRegister dst, XmmRegister src);
578 void maxps(XmmRegister dst, XmmRegister src);
579 void andps(XmmRegister dst, XmmRegister src);
580 void andps(XmmRegister dst, const Address &src);
581 void orps(XmmRegister dst, XmmRegister src);
582
Jan Voungd026c442014-10-13 14:06:50 -0700583 void blendvps(Type Ty, XmmRegister dst, XmmRegister src);
584 void blendvps(Type Ty, XmmRegister dst, const Address &src);
585 void pblendvb(Type Ty, XmmRegister dst, XmmRegister src);
586 void pblendvb(Type Ty, XmmRegister dst, const Address &src);
587
Jan Voung8acded02014-09-22 18:02:25 -0700588 void cmpps(XmmRegister dst, XmmRegister src, CondX86::CmppsCond CmpCondition);
589 void cmpps(XmmRegister dst, const Address &src,
590 CondX86::CmppsCond CmpCondition);
591
592 void sqrtps(XmmRegister dst);
593 void rsqrtps(XmmRegister dst);
594 void reciprocalps(XmmRegister dst);
595 void movhlps(XmmRegister dst, XmmRegister src);
596 void movlhps(XmmRegister dst, XmmRegister src);
597 void unpcklps(XmmRegister dst, XmmRegister src);
598 void unpckhps(XmmRegister dst, XmmRegister src);
599 void unpcklpd(XmmRegister dst, XmmRegister src);
600 void unpckhpd(XmmRegister dst, XmmRegister src);
601
602 void set1ps(XmmRegister dst, GPRRegister tmp, const Immediate &imm);
603 void shufps(XmmRegister dst, XmmRegister src, const Immediate &mask);
604
605 void minpd(XmmRegister dst, XmmRegister src);
606 void maxpd(XmmRegister dst, XmmRegister src);
607 void sqrtpd(XmmRegister dst);
Jan Voung8acded02014-09-22 18:02:25 -0700608 void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask);
609
Jan Voung962befa2014-10-15 09:32:58 -0700610 void pshufd(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mask);
611 void pshufd(Type Ty, XmmRegister dst, const Address &src,
612 const Immediate &mask);
613 void shufps(Type Ty, XmmRegister dst, XmmRegister src, const Immediate &mask);
614 void shufps(Type Ty, XmmRegister dst, const Address &src,
615 const Immediate &mask);
616
Jan Voung699bf022014-10-08 13:52:10 -0700617 void cvtdq2ps(Type, XmmRegister dst, XmmRegister src);
618 void cvtdq2ps(Type, XmmRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700619
Jan Voung699bf022014-10-08 13:52:10 -0700620 void cvttps2dq(Type, XmmRegister dst, XmmRegister src);
621 void cvttps2dq(Type, XmmRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700622
Jan Voung699bf022014-10-08 13:52:10 -0700623 void cvtsi2ss(Type DestTy, XmmRegister dst, GPRRegister src);
624 void cvtsi2ss(Type DestTy, XmmRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700625
Jan Voung699bf022014-10-08 13:52:10 -0700626 void cvtfloat2float(Type SrcTy, XmmRegister dst, XmmRegister src);
627 void cvtfloat2float(Type SrcTy, XmmRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700628
Jan Voung699bf022014-10-08 13:52:10 -0700629 void cvttss2si(Type SrcTy, GPRRegister dst, XmmRegister src);
630 void cvttss2si(Type SrcTy, GPRRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700631
632 void ucomiss(Type Ty, XmmRegister a, XmmRegister b);
633 void ucomiss(Type Ty, XmmRegister a, const Address &b);
634
635 void movmskpd(GPRRegister dst, XmmRegister src);
636 void movmskps(GPRRegister dst, XmmRegister src);
637
638 void sqrtss(Type Ty, XmmRegister dst, const Address &src);
639 void sqrtss(Type Ty, XmmRegister dst, XmmRegister src);
640
641 void xorpd(XmmRegister dst, const Address &src);
642 void xorpd(XmmRegister dst, XmmRegister src);
643 void xorps(XmmRegister dst, const Address &src);
644 void xorps(XmmRegister dst, XmmRegister src);
645
646 void andpd(XmmRegister dst, const Address &src);
647 void andpd(XmmRegister dst, XmmRegister src);
648
649 void orpd(XmmRegister dst, XmmRegister src);
650
Jan Voung962befa2014-10-15 09:32:58 -0700651 void insertps(Type Ty, XmmRegister dst, XmmRegister src,
652 const Immediate &imm);
653 void insertps(Type Ty, XmmRegister dst, const Address &src,
654 const Immediate &imm);
655
656 void pinsr(Type Ty, XmmRegister dst, GPRRegister src, const Immediate &imm);
657 void pinsr(Type Ty, XmmRegister dst, const Address &src,
658 const Immediate &imm);
659
660 void pextr(Type Ty, GPRRegister dst, XmmRegister src, const Immediate &imm);
661 void pextr(Type Ty, GPRRegister dst, const Address &src,
662 const Immediate &imm);
663
Jan Voung8acded02014-09-22 18:02:25 -0700664 void pmovsxdq(XmmRegister dst, XmmRegister src);
Jan Voung0ac50dc2014-09-30 08:36:06 -0700665
666 void pcmpeq(Type Ty, XmmRegister dst, XmmRegister src);
667 void pcmpeq(Type Ty, XmmRegister dst, const Address &src);
668 void pcmpgt(Type Ty, XmmRegister dst, XmmRegister src);
669 void pcmpgt(Type Ty, XmmRegister dst, const Address &src);
Jan Voung8acded02014-09-22 18:02:25 -0700670
671 enum RoundingMode {
672 kRoundToNearest = 0x0,
673 kRoundDown = 0x1,
674 kRoundUp = 0x2,
675 kRoundToZero = 0x3
676 };
677 void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode);
678
Jan Voung479e5632014-10-08 21:05:27 -0700679 void fld(Type Ty, const Address &src);
680 void fstp(Type Ty, const Address &dst);
681 void fstp(X87STRegister st);
Jan Voung8acded02014-09-22 18:02:25 -0700682
683 void fnstcw(const Address &dst);
684 void fldcw(const Address &src);
685
686 void fistpl(const Address &dst);
687 void fistps(const Address &dst);
688 void fildl(const Address &src);
689 void filds(const Address &src);
690
691 void fincstp();
692
Jan Vounge4dc61b2014-10-06 08:53:52 -0700693 void cmp(Type Ty, GPRRegister reg0, GPRRegister reg1);
694 void cmp(Type Ty, GPRRegister reg, const Address &address);
695 void cmp(Type Ty, GPRRegister reg, const Immediate &imm);
696 void cmp(Type Ty, const Address &address, GPRRegister reg);
697 void cmp(Type Ty, const Address &address, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700698
Jan Vounge4dc61b2014-10-06 08:53:52 -0700699 void test(Type Ty, GPRRegister reg0, GPRRegister reg1);
700 void test(Type Ty, GPRRegister reg, const Immediate &imm);
701 void test(Type Ty, const Address &address, GPRRegister reg);
702 void test(Type Ty, const Address &address, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700703
Jan Voungaf2780c2014-09-26 11:14:30 -0700704 void And(Type Ty, GPRRegister dst, GPRRegister src);
705 void And(Type Ty, GPRRegister dst, const Address &address);
706 void And(Type Ty, GPRRegister dst, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700707
Jan Voungaf2780c2014-09-26 11:14:30 -0700708 void Or(Type Ty, GPRRegister dst, GPRRegister src);
709 void Or(Type Ty, GPRRegister dst, const Address &address);
710 void Or(Type Ty, GPRRegister dst, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700711
Jan Voungaf2780c2014-09-26 11:14:30 -0700712 void Xor(Type Ty, GPRRegister dst, GPRRegister src);
713 void Xor(Type Ty, GPRRegister dst, const Address &address);
714 void Xor(Type Ty, GPRRegister dst, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700715
Jan Voungaf2780c2014-09-26 11:14:30 -0700716 void add(Type Ty, GPRRegister dst, GPRRegister src);
717 void add(Type Ty, GPRRegister reg, const Address &address);
718 void add(Type Ty, GPRRegister reg, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700719
Jan Voungaf2780c2014-09-26 11:14:30 -0700720 void adc(Type Ty, GPRRegister dst, GPRRegister src);
721 void adc(Type Ty, GPRRegister dst, const Address &address);
722 void adc(Type Ty, GPRRegister reg, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700723
Jan Voungaf2780c2014-09-26 11:14:30 -0700724 void sub(Type Ty, GPRRegister dst, GPRRegister src);
725 void sub(Type Ty, GPRRegister reg, const Address &address);
726 void sub(Type Ty, GPRRegister reg, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700727
Jan Voungaf2780c2014-09-26 11:14:30 -0700728 void sbb(Type Ty, GPRRegister dst, GPRRegister src);
729 void sbb(Type Ty, GPRRegister reg, const Address &address);
730 void sbb(Type Ty, GPRRegister reg, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700731
Jan Voung03532e52014-09-23 13:32:18 -0700732 void cbw();
733 void cwd();
Jan Voung8acded02014-09-22 18:02:25 -0700734 void cdq();
735
Jan Voungaf2780c2014-09-26 11:14:30 -0700736 void div(Type Ty, GPRRegister reg);
737 void div(Type Ty, const Address &address);
738
739 void idiv(Type Ty, GPRRegister reg);
740 void idiv(Type Ty, const Address &address);
Jan Voung8acded02014-09-22 18:02:25 -0700741
Jan Voung0ac50dc2014-09-30 08:36:06 -0700742 void imul(Type Ty, GPRRegister dst, GPRRegister src);
743 void imul(Type Ty, GPRRegister reg, const Immediate &imm);
744 void imul(Type Ty, GPRRegister reg, const Address &address);
Jan Voung8acded02014-09-22 18:02:25 -0700745
Jan Voung0ac50dc2014-09-30 08:36:06 -0700746 void imul(Type Ty, GPRRegister reg);
747 void imul(Type Ty, const Address &address);
Jan Voung8acded02014-09-22 18:02:25 -0700748
Jan Voungaf2780c2014-09-26 11:14:30 -0700749 void mul(Type Ty, GPRRegister reg);
750 void mul(Type Ty, const Address &address);
Jan Voung8acded02014-09-22 18:02:25 -0700751
752 void incl(GPRRegister reg);
753 void incl(const Address &address);
754
755 void decl(GPRRegister reg);
756 void decl(const Address &address);
757
Jan Voung8bcca042014-10-03 21:58:02 -0700758 void rol(Type Ty, GPRRegister reg, const Immediate &imm);
759 void rol(Type Ty, GPRRegister operand, GPRRegister shifter);
760 void rol(Type Ty, const Address &operand, GPRRegister shifter);
761
762 void shl(Type Ty, GPRRegister reg, const Immediate &imm);
763 void shl(Type Ty, GPRRegister operand, GPRRegister shifter);
764 void shl(Type Ty, const Address &operand, GPRRegister shifter);
765
766 void shr(Type Ty, GPRRegister reg, const Immediate &imm);
767 void shr(Type Ty, GPRRegister operand, GPRRegister shifter);
768 void shr(Type Ty, const Address &operand, GPRRegister shifter);
769
770 void sar(Type Ty, GPRRegister reg, const Immediate &imm);
771 void sar(Type Ty, GPRRegister operand, GPRRegister shifter);
772 void sar(Type Ty, const Address &address, GPRRegister shifter);
773
Jan Voung962befa2014-10-15 09:32:58 -0700774 void shld(Type Ty, GPRRegister dst, GPRRegister src);
775 void shld(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
776 void shld(Type Ty, const Address &operand, GPRRegister src);
777 void shrd(Type Ty, GPRRegister dst, GPRRegister src);
778 void shrd(Type Ty, GPRRegister dst, GPRRegister src, const Immediate &imm);
779 void shrd(Type Ty, const Address &dst, GPRRegister src);
Jan Voung8acded02014-09-22 18:02:25 -0700780
Jan Voung3b43b892014-09-24 13:32:39 -0700781 void neg(Type Ty, GPRRegister reg);
782 void neg(Type Ty, const Address &addr);
Jan Voung8acded02014-09-22 18:02:25 -0700783 void notl(GPRRegister reg);
784
Jan Voung3b43b892014-09-24 13:32:39 -0700785 void bsf(Type Ty, GPRRegister dst, GPRRegister src);
786 void bsf(Type Ty, GPRRegister dst, const Address &src);
787 void bsr(Type Ty, GPRRegister dst, GPRRegister src);
788 void bsr(Type Ty, GPRRegister dst, const Address &src);
789
790 void bswap(Type Ty, GPRRegister reg);
Jan Voung8acded02014-09-22 18:02:25 -0700791
792 void bt(GPRRegister base, GPRRegister offset);
793
794 void ret();
795 void ret(const Immediate &imm);
796
797 // 'size' indicates size in bytes and must be in the range 1..8.
798 void nop(int size = 1);
799 void int3();
800 void hlt();
Jan Vounge4dc61b2014-10-06 08:53:52 -0700801 void ud2();
Jan Voung8acded02014-09-22 18:02:25 -0700802
803 void j(CondX86::BrCond condition, Label *label, bool near = kFarJump);
804 void j(CondX86::BrCond condition, const ConstantRelocatable *label);
805
806 void jmp(GPRRegister reg);
807 void jmp(Label *label, bool near = kFarJump);
808 void jmp(const ConstantRelocatable *label);
809
Jan Voungaf2780c2014-09-26 11:14:30 -0700810 void mfence();
811
Jan Voung8acded02014-09-22 18:02:25 -0700812 void lock();
Jan Voung03532e52014-09-23 13:32:18 -0700813 void cmpxchg(Type Ty, const Address &address, GPRRegister reg);
814 void cmpxchg8b(const Address &address);
815 void xadd(Type Ty, const Address &address, GPRRegister reg);
816 void xchg(Type Ty, const Address &address, GPRRegister reg);
Jan Voung8acded02014-09-22 18:02:25 -0700817
Jan Voung03532e52014-09-23 13:32:18 -0700818 void LockCmpxchg(Type Ty, const Address &address, GPRRegister reg) {
Jan Voung8acded02014-09-22 18:02:25 -0700819 lock();
Jan Voung03532e52014-09-23 13:32:18 -0700820 cmpxchg(Ty, address, reg);
Jan Voung8acded02014-09-22 18:02:25 -0700821 }
822
Jan Voungf76fd372014-10-16 15:39:22 -0700823 void EmitSegmentOverride(uint8_t prefix);
Jan Voungfe14fb82014-10-13 15:56:32 -0700824
Jan Voung8acded02014-09-22 18:02:25 -0700825 intptr_t PreferredLoopAlignment() { return 16; }
826 void Align(intptr_t alignment, intptr_t offset);
827 void Bind(Label *label);
828
829 intptr_t CodeSize() const { return buffer_.Size(); }
830
Jan Voung8acded02014-09-22 18:02:25 -0700831private:
832 inline void EmitUint8(uint8_t value);
Jim Stichnoth94c4c8e2014-09-28 20:30:21 -0700833 inline void EmitInt16(int16_t value);
Jan Voung8acded02014-09-22 18:02:25 -0700834 inline void EmitInt32(int32_t value);
835 inline void EmitRegisterOperand(int rm, int reg);
836 inline void EmitXmmRegisterOperand(int rm, XmmRegister reg);
837 inline void EmitFixup(AssemblerFixup *fixup);
838 inline void EmitOperandSizeOverride();
839
840 void EmitOperand(int rm, const Operand &operand);
Jim Stichnoth94c4c8e2014-09-28 20:30:21 -0700841 void EmitImmediate(Type ty, const Immediate &imm);
Jan Voung8acded02014-09-22 18:02:25 -0700842 void EmitComplexI8(int rm, const Operand &operand,
843 const Immediate &immediate);
Jim Stichnoth94c4c8e2014-09-28 20:30:21 -0700844 void EmitComplex(Type Ty, int rm, const Operand &operand,
845 const Immediate &immediate);
Jan Voung8acded02014-09-22 18:02:25 -0700846 void EmitLabel(Label *label, intptr_t instruction_size);
847 void EmitLabelLink(Label *label);
848 void EmitNearLabelLink(Label *label);
849
Jan Voung8bcca042014-10-03 21:58:02 -0700850 void EmitGenericShift(int rm, Type Ty, GPRRegister reg, const Immediate &imm);
851 void EmitGenericShift(int rm, Type Ty, const Operand &operand,
852 GPRRegister shifter);
Jan Voung8acded02014-09-22 18:02:25 -0700853
Jan Voung7e1e4852014-10-24 10:29:30 -0700854 typedef std::vector<Label *> LabelVector;
855 // A vector of pool-allocated x86 labels for CFG nodes.
856 LabelVector CfgNodeLabels;
857 // A vector of pool-allocated x86 labels for Local labels.
858 LabelVector LocalLabels;
859
860 Label *GetOrCreateLabel(SizeT Number, LabelVector &Labels);
Jan Voung8acded02014-09-22 18:02:25 -0700861};
862
863inline void AssemblerX86::EmitUint8(uint8_t value) {
864 buffer_.Emit<uint8_t>(value);
865}
866
Jim Stichnoth94c4c8e2014-09-28 20:30:21 -0700867inline void AssemblerX86::EmitInt16(int16_t value) {
868 buffer_.Emit<int16_t>(value);
869}
870
Jan Voung8acded02014-09-22 18:02:25 -0700871inline void AssemblerX86::EmitInt32(int32_t value) {
872 buffer_.Emit<int32_t>(value);
873}
874
875inline void AssemblerX86::EmitRegisterOperand(int rm, int reg) {
876 assert(rm >= 0 && rm < 8);
877 buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg);
878}
879
880inline void AssemblerX86::EmitXmmRegisterOperand(int rm, XmmRegister reg) {
881 EmitRegisterOperand(rm, static_cast<GPRRegister>(reg));
882}
883
884inline void AssemblerX86::EmitFixup(AssemblerFixup *fixup) {
885 buffer_.EmitFixup(fixup);
886}
887
888inline void AssemblerX86::EmitOperandSizeOverride() { EmitUint8(0x66); }
889
890} // end of namespace x86
891} // end of namespace Ice
892
893#endif // SUBZERO_SRC_ASSEMBLER_IA32_H_