blob: 92c7d0ab99fcc4980089f77cdd54f5c6f3ff482a [file] [log] [blame]
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
18#define ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_
19
20#include <vector>
Vladimir Marko80afd022015-05-19 18:08:00 +010021
Vladimir Marko93205e32016-04-13 11:59:46 +010022#include "base/arena_containers.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010023#include "base/bit_utils.h"
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070024#include "base/macros.h"
25#include "constants_x86_64.h"
26#include "globals.h"
27#include "managed_register_x86_64.h"
28#include "offsets.h"
Vladimir Marko93205e32016-04-13 11:59:46 +010029#include "utils/array_ref.h"
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070030#include "utils/assembler.h"
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070031
32namespace art {
33namespace x86_64 {
34
avignate5408b6b2014-06-04 17:59:44 +070035// Encodes an immediate value for operands.
36//
37// Note: Immediates can be 64b on x86-64 for certain instructions, but are often restricted
38// to 32b.
39//
40// Note: As we support cross-compilation, the value type must be int64_t. Please be aware of
41// conversion rules in expressions regarding negation, especially size_t on 32b.
Ian Rogerscf7f1912014-10-22 22:06:39 -070042class Immediate : public ValueObject {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070043 public:
Andreas Gampe277ccbd2014-11-03 21:36:10 -080044 explicit Immediate(int64_t value_in) : value_(value_in) {}
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070045
Andreas Gampe5a4fa822014-03-31 16:50:12 -070046 int64_t value() const { return value_; }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070047
Andreas Gampeab1eb0d2015-02-13 19:23:55 -080048 bool is_int8() const { return IsInt<8>(value_); }
49 bool is_uint8() const { return IsUint<8>(value_); }
50 bool is_int16() const { return IsInt<16>(value_); }
51 bool is_uint16() const { return IsUint<16>(value_); }
52 bool is_int32() const { return IsInt<32>(value_); }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070053
54 private:
Andreas Gampe5a4fa822014-03-31 16:50:12 -070055 const int64_t value_;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070056};
57
58
Ian Rogerscf7f1912014-10-22 22:06:39 -070059class Operand : public ValueObject {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070060 public:
61 uint8_t mod() const {
62 return (encoding_at(0) >> 6) & 3;
63 }
64
65 Register rm() const {
66 return static_cast<Register>(encoding_at(0) & 7);
67 }
68
69 ScaleFactor scale() const {
70 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
71 }
72
73 Register index() const {
74 return static_cast<Register>((encoding_at(1) >> 3) & 7);
75 }
76
77 Register base() const {
78 return static_cast<Register>(encoding_at(1) & 7);
79 }
80
Ian Rogers790a6b72014-04-01 10:36:00 -070081 uint8_t rex() const {
82 return rex_;
83 }
84
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070085 int8_t disp8() const {
86 CHECK_GE(length_, 2);
87 return static_cast<int8_t>(encoding_[length_ - 1]);
88 }
89
90 int32_t disp32() const {
91 CHECK_GE(length_, 5);
92 int32_t value;
93 memcpy(&value, &encoding_[length_ - 4], sizeof(value));
94 return value;
95 }
96
Ian Rogersdd7624d2014-03-14 17:43:00 -070097 bool IsRegister(CpuRegister reg) const {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070098 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
Ian Rogers790a6b72014-04-01 10:36:00 -070099 && ((encoding_[0] & 0x07) == reg.LowBits()) // Register codes match.
100 && (reg.NeedsRex() == ((rex_ & 1) != 0)); // REX.000B bits match.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700101 }
102
Mark Mendellf55c3e02015-03-26 21:07:46 -0400103 AssemblerFixup* GetFixup() const {
104 return fixup_;
105 }
106
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700107 protected:
108 // Operand can be sub classed (e.g: Address).
Mark Mendellf55c3e02015-03-26 21:07:46 -0400109 Operand() : rex_(0), length_(0), fixup_(nullptr) { }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700110
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800111 void SetModRM(uint8_t mod_in, CpuRegister rm_in) {
112 CHECK_EQ(mod_in & ~3, 0);
113 if (rm_in.NeedsRex()) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700114 rex_ |= 0x41; // REX.000B
115 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800116 encoding_[0] = (mod_in << 6) | rm_in.LowBits();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700117 length_ = 1;
118 }
119
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800120 void SetSIB(ScaleFactor scale_in, CpuRegister index_in, CpuRegister base_in) {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700121 CHECK_EQ(length_, 1);
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800122 CHECK_EQ(scale_in & ~3, 0);
123 if (base_in.NeedsRex()) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700124 rex_ |= 0x41; // REX.000B
125 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800126 if (index_in.NeedsRex()) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700127 rex_ |= 0x42; // REX.00X0
128 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800129 encoding_[1] = (scale_in << 6) | (static_cast<uint8_t>(index_in.LowBits()) << 3) |
130 static_cast<uint8_t>(base_in.LowBits());
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700131 length_ = 2;
132 }
133
134 void SetDisp8(int8_t disp) {
135 CHECK(length_ == 1 || length_ == 2);
136 encoding_[length_++] = static_cast<uint8_t>(disp);
137 }
138
139 void SetDisp32(int32_t disp) {
140 CHECK(length_ == 1 || length_ == 2);
141 int disp_size = sizeof(disp);
142 memmove(&encoding_[length_], &disp, disp_size);
143 length_ += disp_size;
144 }
145
Mark Mendellf55c3e02015-03-26 21:07:46 -0400146 void SetFixup(AssemblerFixup* fixup) {
147 fixup_ = fixup;
148 }
149
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700150 private:
Ian Rogers790a6b72014-04-01 10:36:00 -0700151 uint8_t rex_;
152 uint8_t length_;
153 uint8_t encoding_[6];
Mark Mendellf55c3e02015-03-26 21:07:46 -0400154 AssemblerFixup* fixup_;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700155
Mark Mendellf55c3e02015-03-26 21:07:46 -0400156 explicit Operand(CpuRegister reg) : rex_(0), length_(0), fixup_(nullptr) { SetModRM(3, reg); }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700157
158 // Get the operand encoding byte at the given index.
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800159 uint8_t encoding_at(int index_in) const {
160 CHECK_GE(index_in, 0);
161 CHECK_LT(index_in, length_);
162 return encoding_[index_in];
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700163 }
164
165 friend class X86_64Assembler;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700166};
167
168
169class Address : public Operand {
170 public:
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800171 Address(CpuRegister base_in, int32_t disp) {
172 Init(base_in, disp);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700173 }
174
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800175 Address(CpuRegister base_in, Offset disp) {
176 Init(base_in, disp.Int32Value());
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700177 }
178
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800179 Address(CpuRegister base_in, FrameOffset disp) {
180 CHECK_EQ(base_in.AsRegister(), RSP);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700181 Init(CpuRegister(RSP), disp.Int32Value());
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700182 }
183
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800184 Address(CpuRegister base_in, MemberOffset disp) {
185 Init(base_in, disp.Int32Value());
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700186 }
187
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800188 void Init(CpuRegister base_in, int32_t disp) {
Nicolas Geoffray784cc5c2014-12-18 20:25:18 +0000189 if (disp == 0 && base_in.LowBits() != RBP) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800190 SetModRM(0, base_in);
Nicolas Geoffray98893962015-01-21 12:32:32 +0000191 if (base_in.LowBits() == RSP) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800192 SetSIB(TIMES_1, CpuRegister(RSP), base_in);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700193 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700194 } else if (disp >= -128 && disp <= 127) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800195 SetModRM(1, base_in);
Nicolas Geoffray98893962015-01-21 12:32:32 +0000196 if (base_in.LowBits() == RSP) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800197 SetSIB(TIMES_1, CpuRegister(RSP), base_in);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700198 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700199 SetDisp8(disp);
200 } else {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800201 SetModRM(2, base_in);
Nicolas Geoffray98893962015-01-21 12:32:32 +0000202 if (base_in.LowBits() == RSP) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800203 SetSIB(TIMES_1, CpuRegister(RSP), base_in);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700204 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700205 SetDisp32(disp);
206 }
207 }
208
209
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800210 Address(CpuRegister index_in, ScaleFactor scale_in, int32_t disp) {
211 CHECK_NE(index_in.AsRegister(), RSP); // Illegal addressing mode.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700212 SetModRM(0, CpuRegister(RSP));
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800213 SetSIB(scale_in, index_in, CpuRegister(RBP));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700214 SetDisp32(disp);
215 }
216
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800217 Address(CpuRegister base_in, CpuRegister index_in, ScaleFactor scale_in, int32_t disp) {
218 CHECK_NE(index_in.AsRegister(), RSP); // Illegal addressing mode.
Nicolas Geoffray784cc5c2014-12-18 20:25:18 +0000219 if (disp == 0 && base_in.LowBits() != RBP) {
Ian Rogersdd7624d2014-03-14 17:43:00 -0700220 SetModRM(0, CpuRegister(RSP));
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800221 SetSIB(scale_in, index_in, base_in);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700222 } else if (disp >= -128 && disp <= 127) {
Ian Rogersdd7624d2014-03-14 17:43:00 -0700223 SetModRM(1, CpuRegister(RSP));
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800224 SetSIB(scale_in, index_in, base_in);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700225 SetDisp8(disp);
226 } else {
Ian Rogersdd7624d2014-03-14 17:43:00 -0700227 SetModRM(2, CpuRegister(RSP));
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800228 SetSIB(scale_in, index_in, base_in);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700229 SetDisp32(disp);
230 }
231 }
232
Ian Rogersdd7624d2014-03-14 17:43:00 -0700233 // If no_rip is true then the Absolute address isn't RIP relative.
Ian Rogers13735952014-10-08 12:43:28 -0700234 static Address Absolute(uintptr_t addr, bool no_rip = false) {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700235 Address result;
Ian Rogersdd7624d2014-03-14 17:43:00 -0700236 if (no_rip) {
237 result.SetModRM(0, CpuRegister(RSP));
238 result.SetSIB(TIMES_1, CpuRegister(RSP), CpuRegister(RBP));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700239 result.SetDisp32(addr);
240 } else {
Mark Mendell39dcf552015-04-09 20:42:42 -0400241 // RIP addressing is done using RBP as the base register.
242 // The value in RBP isn't used. Instead the offset is added to RIP.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700243 result.SetModRM(0, CpuRegister(RBP));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700244 result.SetDisp32(addr);
245 }
246 return result;
247 }
248
Mark Mendellf55c3e02015-03-26 21:07:46 -0400249 // An RIP relative address that will be fixed up later.
250 static Address RIP(AssemblerFixup* fixup) {
251 Address result;
Mark Mendell39dcf552015-04-09 20:42:42 -0400252 // RIP addressing is done using RBP as the base register.
253 // The value in RBP isn't used. Instead the offset is added to RIP.
Mark Mendellf55c3e02015-03-26 21:07:46 -0400254 result.SetModRM(0, CpuRegister(RBP));
255 result.SetDisp32(0);
256 result.SetFixup(fixup);
257 return result;
258 }
259
Ian Rogersdd7624d2014-03-14 17:43:00 -0700260 // If no_rip is true then the Absolute address isn't RIP relative.
261 static Address Absolute(ThreadOffset<8> addr, bool no_rip = false) {
262 return Absolute(addr.Int32Value(), no_rip);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700263 }
264
265 private:
266 Address() {}
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700267};
268
269
Mark Mendellf55c3e02015-03-26 21:07:46 -0400270/**
271 * Class to handle constant area values.
272 */
273class ConstantArea {
Mark Mendell9c86b482015-09-18 13:36:07 -0400274 public:
Vladimir Marko93205e32016-04-13 11:59:46 +0100275 explicit ConstantArea(ArenaAllocator* arena) : buffer_(arena->Adapter(kArenaAllocAssembler)) {}
Mark Mendellf55c3e02015-03-26 21:07:46 -0400276
Mark Mendell9c86b482015-09-18 13:36:07 -0400277 // Add a double to the constant area, returning the offset into
278 // the constant area where the literal resides.
279 size_t AddDouble(double v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400280
Mark Mendell9c86b482015-09-18 13:36:07 -0400281 // Add a float to the constant area, returning the offset into
282 // the constant area where the literal resides.
283 size_t AddFloat(float v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400284
Mark Mendell9c86b482015-09-18 13:36:07 -0400285 // Add an int32_t to the constant area, returning the offset into
286 // the constant area where the literal resides.
287 size_t AddInt32(int32_t v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400288
Mark Mendell9c86b482015-09-18 13:36:07 -0400289 // Add an int32_t to the end of the constant area, returning the offset into
290 // the constant area where the literal resides.
291 size_t AppendInt32(int32_t v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400292
Mark Mendell9c86b482015-09-18 13:36:07 -0400293 // Add an int64_t to the constant area, returning the offset into
294 // the constant area where the literal resides.
295 size_t AddInt64(int64_t v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400296
Mark Mendell9c86b482015-09-18 13:36:07 -0400297 size_t GetSize() const {
298 return buffer_.size() * elem_size_;
299 }
Mark Mendellf55c3e02015-03-26 21:07:46 -0400300
Vladimir Marko93205e32016-04-13 11:59:46 +0100301 ArrayRef<const int32_t> GetBuffer() const {
302 return ArrayRef<const int32_t>(buffer_);
Mark Mendell9c86b482015-09-18 13:36:07 -0400303 }
304
305 private:
306 static constexpr size_t elem_size_ = sizeof(int32_t);
Vladimir Marko93205e32016-04-13 11:59:46 +0100307 ArenaVector<int32_t> buffer_;
Mark Mendellf55c3e02015-03-26 21:07:46 -0400308};
309
310
Mark Mendell73f455e2015-08-21 09:30:05 -0400311// This is equivalent to the Label class, used in a slightly different context. We
312// inherit the functionality of the Label class, but prevent unintended
313// derived-to-base conversions by making the base class private.
314class NearLabel : private Label {
315 public:
316 NearLabel() : Label() {}
317
318 // Expose the Label routines that we need.
319 using Label::Position;
320 using Label::LinkPosition;
321 using Label::IsBound;
322 using Label::IsUnused;
323 using Label::IsLinked;
324
325 private:
326 using Label::BindTo;
327 using Label::LinkTo;
328
329 friend class x86_64::X86_64Assembler;
330
331 DISALLOW_COPY_AND_ASSIGN(NearLabel);
332};
333
334
Ian Rogersdd7624d2014-03-14 17:43:00 -0700335class X86_64Assembler FINAL : public Assembler {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700336 public:
Vladimir Marko93205e32016-04-13 11:59:46 +0100337 explicit X86_64Assembler(ArenaAllocator* arena) : Assembler(arena), constant_area_(arena) {}
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700338 virtual ~X86_64Assembler() {}
339
340 /*
341 * Emit Machine Instructions.
342 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700343 void call(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700344 void call(const Address& address);
345 void call(Label* label);
346
Ian Rogersdd7624d2014-03-14 17:43:00 -0700347 void pushq(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700348 void pushq(const Address& address);
349 void pushq(const Immediate& imm);
350
Ian Rogersdd7624d2014-03-14 17:43:00 -0700351 void popq(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700352 void popq(const Address& address);
353
Ian Rogersdd7624d2014-03-14 17:43:00 -0700354 void movq(CpuRegister dst, const Immediate& src);
355 void movl(CpuRegister dst, const Immediate& src);
356 void movq(CpuRegister dst, CpuRegister src);
357 void movl(CpuRegister dst, CpuRegister src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700358
Mark Mendell7a08fb52015-07-15 14:09:35 -0400359 void movntl(const Address& dst, CpuRegister src);
360 void movntq(const Address& dst, CpuRegister src);
361
Ian Rogersdd7624d2014-03-14 17:43:00 -0700362 void movq(CpuRegister dst, const Address& src);
363 void movl(CpuRegister dst, const Address& src);
364 void movq(const Address& dst, CpuRegister src);
Mark Mendellcfa410b2015-05-25 16:02:44 -0400365 void movq(const Address& dst, const Immediate& imm);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700366 void movl(const Address& dst, CpuRegister src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700367 void movl(const Address& dst, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700368
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800369 void cmov(Condition c, CpuRegister dst, CpuRegister src); // This is the 64b version.
370 void cmov(Condition c, CpuRegister dst, CpuRegister src, bool is64bit);
Mark Mendellabdac472016-02-12 13:49:03 -0500371 void cmov(Condition c, CpuRegister dst, const Address& src, bool is64bit);
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800372
Ian Rogersdd7624d2014-03-14 17:43:00 -0700373 void movzxb(CpuRegister dst, CpuRegister src);
374 void movzxb(CpuRegister dst, const Address& src);
375 void movsxb(CpuRegister dst, CpuRegister src);
376 void movsxb(CpuRegister dst, const Address& src);
377 void movb(CpuRegister dst, const Address& src);
378 void movb(const Address& dst, CpuRegister src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700379 void movb(const Address& dst, const Immediate& imm);
380
Ian Rogersdd7624d2014-03-14 17:43:00 -0700381 void movzxw(CpuRegister dst, CpuRegister src);
382 void movzxw(CpuRegister dst, const Address& src);
383 void movsxw(CpuRegister dst, CpuRegister src);
384 void movsxw(CpuRegister dst, const Address& src);
385 void movw(CpuRegister dst, const Address& src);
386 void movw(const Address& dst, CpuRegister src);
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +0100387 void movw(const Address& dst, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700388
Ian Rogersdd7624d2014-03-14 17:43:00 -0700389 void leaq(CpuRegister dst, const Address& src);
Nicolas Geoffray748f1402015-01-27 08:17:54 +0000390 void leal(CpuRegister dst, const Address& src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700391
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100392 void movaps(XmmRegister dst, XmmRegister src);
393
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700394 void movss(XmmRegister dst, const Address& src);
395 void movss(const Address& dst, XmmRegister src);
396 void movss(XmmRegister dst, XmmRegister src);
397
Roland Levillaindff1f282014-11-05 14:15:05 +0000398 void movsxd(CpuRegister dst, CpuRegister src);
399 void movsxd(CpuRegister dst, const Address& src);
400
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800401 void movd(XmmRegister dst, CpuRegister src); // Note: this is the r64 version, formally movq.
402 void movd(CpuRegister dst, XmmRegister src); // Note: this is the r64 version, formally movq.
403 void movd(XmmRegister dst, CpuRegister src, bool is64bit);
404 void movd(CpuRegister dst, XmmRegister src, bool is64bit);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700405
406 void addss(XmmRegister dst, XmmRegister src);
407 void addss(XmmRegister dst, const Address& src);
408 void subss(XmmRegister dst, XmmRegister src);
409 void subss(XmmRegister dst, const Address& src);
410 void mulss(XmmRegister dst, XmmRegister src);
411 void mulss(XmmRegister dst, const Address& src);
412 void divss(XmmRegister dst, XmmRegister src);
413 void divss(XmmRegister dst, const Address& src);
414
415 void movsd(XmmRegister dst, const Address& src);
416 void movsd(const Address& dst, XmmRegister src);
417 void movsd(XmmRegister dst, XmmRegister src);
418
419 void addsd(XmmRegister dst, XmmRegister src);
420 void addsd(XmmRegister dst, const Address& src);
421 void subsd(XmmRegister dst, XmmRegister src);
422 void subsd(XmmRegister dst, const Address& src);
423 void mulsd(XmmRegister dst, XmmRegister src);
424 void mulsd(XmmRegister dst, const Address& src);
425 void divsd(XmmRegister dst, XmmRegister src);
426 void divsd(XmmRegister dst, const Address& src);
427
Andreas Gampe851df202014-11-12 14:05:46 -0800428 void cvtsi2ss(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version.
Roland Levillain6d0e4832014-11-27 18:31:21 +0000429 void cvtsi2ss(XmmRegister dst, CpuRegister src, bool is64bit);
Mark Mendell40741f32015-04-20 22:10:34 -0400430 void cvtsi2ss(XmmRegister dst, const Address& src, bool is64bit);
Andreas Gampe851df202014-11-12 14:05:46 -0800431 void cvtsi2sd(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version.
Roland Levillain647b9ed2014-11-27 12:06:00 +0000432 void cvtsi2sd(XmmRegister dst, CpuRegister src, bool is64bit);
Mark Mendell40741f32015-04-20 22:10:34 -0400433 void cvtsi2sd(XmmRegister dst, const Address& src, bool is64bit);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700434
Andreas Gampe851df202014-11-12 14:05:46 -0800435 void cvtss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700436 void cvtss2sd(XmmRegister dst, XmmRegister src);
Mark Mendell40741f32015-04-20 22:10:34 -0400437 void cvtss2sd(XmmRegister dst, const Address& src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700438
Andreas Gampe851df202014-11-12 14:05:46 -0800439 void cvtsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700440 void cvtsd2ss(XmmRegister dst, XmmRegister src);
Mark Mendell40741f32015-04-20 22:10:34 -0400441 void cvtsd2ss(XmmRegister dst, const Address& src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700442
Andreas Gampe851df202014-11-12 14:05:46 -0800443 void cvttss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
Roland Levillain624279f2014-12-04 11:54:28 +0000444 void cvttss2si(CpuRegister dst, XmmRegister src, bool is64bit);
Andreas Gampe851df202014-11-12 14:05:46 -0800445 void cvttsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
Roland Levillain4c0b61f2014-12-05 12:06:01 +0000446 void cvttsd2si(CpuRegister dst, XmmRegister src, bool is64bit);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700447
448 void cvtdq2pd(XmmRegister dst, XmmRegister src);
449
450 void comiss(XmmRegister a, XmmRegister b);
Mark Mendell40741f32015-04-20 22:10:34 -0400451 void comiss(XmmRegister a, const Address& b);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700452 void comisd(XmmRegister a, XmmRegister b);
Mark Mendell40741f32015-04-20 22:10:34 -0400453 void comisd(XmmRegister a, const Address& b);
Calin Juravleddb7df22014-11-25 20:56:51 +0000454 void ucomiss(XmmRegister a, XmmRegister b);
Mark Mendell40741f32015-04-20 22:10:34 -0400455 void ucomiss(XmmRegister a, const Address& b);
Calin Juravleddb7df22014-11-25 20:56:51 +0000456 void ucomisd(XmmRegister a, XmmRegister b);
Mark Mendell40741f32015-04-20 22:10:34 -0400457 void ucomisd(XmmRegister a, const Address& b);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700458
Mark Mendellfb8d2792015-03-31 22:16:59 -0400459 void roundsd(XmmRegister dst, XmmRegister src, const Immediate& imm);
460 void roundss(XmmRegister dst, XmmRegister src, const Immediate& imm);
461
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700462 void sqrtsd(XmmRegister dst, XmmRegister src);
463 void sqrtss(XmmRegister dst, XmmRegister src);
464
465 void xorpd(XmmRegister dst, const Address& src);
466 void xorpd(XmmRegister dst, XmmRegister src);
467 void xorps(XmmRegister dst, const Address& src);
468 void xorps(XmmRegister dst, XmmRegister src);
469
470 void andpd(XmmRegister dst, const Address& src);
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800471 void andpd(XmmRegister dst, XmmRegister src);
472 void andps(XmmRegister dst, XmmRegister src);
473
474 void orpd(XmmRegister dst, XmmRegister src);
475 void orps(XmmRegister dst, XmmRegister src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700476
477 void flds(const Address& src);
478 void fstps(const Address& dst);
Mark Mendell24f2dfa2015-01-14 19:51:45 -0500479 void fsts(const Address& dst);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700480
481 void fldl(const Address& src);
482 void fstpl(const Address& dst);
Mark Mendell24f2dfa2015-01-14 19:51:45 -0500483 void fstl(const Address& dst);
484
485 void fstsw();
486
487 void fucompp();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700488
489 void fnstcw(const Address& dst);
490 void fldcw(const Address& src);
491
492 void fistpl(const Address& dst);
493 void fistps(const Address& dst);
494 void fildl(const Address& src);
Roland Levillain0a186012015-04-13 17:00:20 +0100495 void filds(const Address& src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700496
497 void fincstp();
498 void ffree(const Immediate& index);
499
500 void fsin();
501 void fcos();
502 void fptan();
Mark Mendell24f2dfa2015-01-14 19:51:45 -0500503 void fprem();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700504
Ian Rogersdd7624d2014-03-14 17:43:00 -0700505 void xchgl(CpuRegister dst, CpuRegister src);
Nicolas Geoffrayecb2f9b2014-06-13 08:59:59 +0000506 void xchgq(CpuRegister dst, CpuRegister src);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700507 void xchgl(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700508
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100509 void cmpw(const Address& address, const Immediate& imm);
510
Ian Rogersdd7624d2014-03-14 17:43:00 -0700511 void cmpl(CpuRegister reg, const Immediate& imm);
512 void cmpl(CpuRegister reg0, CpuRegister reg1);
513 void cmpl(CpuRegister reg, const Address& address);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700514 void cmpl(const Address& address, CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700515 void cmpl(const Address& address, const Immediate& imm);
516
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700517 void cmpq(CpuRegister reg0, CpuRegister reg1);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100518 void cmpq(CpuRegister reg0, const Immediate& imm);
519 void cmpq(CpuRegister reg0, const Address& address);
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000520 void cmpq(const Address& address, const Immediate& imm);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700521
Ian Rogersdd7624d2014-03-14 17:43:00 -0700522 void testl(CpuRegister reg1, CpuRegister reg2);
Calin Juravlecd6dffe2015-01-08 17:35:35 +0000523 void testl(CpuRegister reg, const Address& address);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700524 void testl(CpuRegister reg, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700525
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000526 void testq(CpuRegister reg1, CpuRegister reg2);
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100527 void testq(CpuRegister reg, const Address& address);
528
Ian Rogersdd7624d2014-03-14 17:43:00 -0700529 void andl(CpuRegister dst, const Immediate& imm);
530 void andl(CpuRegister dst, CpuRegister src);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000531 void andl(CpuRegister reg, const Address& address);
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100532 void andq(CpuRegister dst, const Immediate& imm);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000533 void andq(CpuRegister dst, CpuRegister src);
Mark Mendell40741f32015-04-20 22:10:34 -0400534 void andq(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700535
Ian Rogersdd7624d2014-03-14 17:43:00 -0700536 void orl(CpuRegister dst, const Immediate& imm);
537 void orl(CpuRegister dst, CpuRegister src);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000538 void orl(CpuRegister reg, const Address& address);
539 void orq(CpuRegister dst, CpuRegister src);
Mark Mendell3f6c7f62015-03-13 13:47:53 -0400540 void orq(CpuRegister dst, const Immediate& imm);
Mark Mendell40741f32015-04-20 22:10:34 -0400541 void orq(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700542
Ian Rogersdd7624d2014-03-14 17:43:00 -0700543 void xorl(CpuRegister dst, CpuRegister src);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000544 void xorl(CpuRegister dst, const Immediate& imm);
545 void xorl(CpuRegister reg, const Address& address);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700546 void xorq(CpuRegister dst, const Immediate& imm);
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100547 void xorq(CpuRegister dst, CpuRegister src);
Mark Mendell40741f32015-04-20 22:10:34 -0400548 void xorq(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700549
Ian Rogersdd7624d2014-03-14 17:43:00 -0700550 void addl(CpuRegister dst, CpuRegister src);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700551 void addl(CpuRegister reg, const Immediate& imm);
552 void addl(CpuRegister reg, const Address& address);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700553 void addl(const Address& address, CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700554 void addl(const Address& address, const Immediate& imm);
555
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700556 void addq(CpuRegister reg, const Immediate& imm);
557 void addq(CpuRegister dst, CpuRegister src);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100558 void addq(CpuRegister dst, const Address& address);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700559
Ian Rogersdd7624d2014-03-14 17:43:00 -0700560 void subl(CpuRegister dst, CpuRegister src);
561 void subl(CpuRegister reg, const Immediate& imm);
562 void subl(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700563
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700564 void subq(CpuRegister reg, const Immediate& imm);
565 void subq(CpuRegister dst, CpuRegister src);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100566 void subq(CpuRegister dst, const Address& address);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700567
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700568 void cdq();
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000569 void cqo();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700570
Ian Rogersdd7624d2014-03-14 17:43:00 -0700571 void idivl(CpuRegister reg);
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000572 void idivq(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700573
Ian Rogersdd7624d2014-03-14 17:43:00 -0700574 void imull(CpuRegister dst, CpuRegister src);
575 void imull(CpuRegister reg, const Immediate& imm);
Mark Mendell4a2aa4a2015-07-27 16:13:10 -0400576 void imull(CpuRegister dst, CpuRegister src, const Immediate& imm);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700577 void imull(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700578
Guillaume Sanchez0f88e872015-03-30 17:55:45 +0100579 void imulq(CpuRegister src);
Calin Juravle34bacdf2014-10-07 20:23:36 +0100580 void imulq(CpuRegister dst, CpuRegister src);
581 void imulq(CpuRegister reg, const Immediate& imm);
582 void imulq(CpuRegister reg, const Address& address);
Mark Mendell3f6c7f62015-03-13 13:47:53 -0400583 void imulq(CpuRegister dst, CpuRegister reg, const Immediate& imm);
Calin Juravle34bacdf2014-10-07 20:23:36 +0100584
Ian Rogersdd7624d2014-03-14 17:43:00 -0700585 void imull(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700586 void imull(const Address& address);
587
Ian Rogersdd7624d2014-03-14 17:43:00 -0700588 void mull(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700589 void mull(const Address& address);
590
Ian Rogersdd7624d2014-03-14 17:43:00 -0700591 void shll(CpuRegister reg, const Immediate& imm);
592 void shll(CpuRegister operand, CpuRegister shifter);
593 void shrl(CpuRegister reg, const Immediate& imm);
594 void shrl(CpuRegister operand, CpuRegister shifter);
595 void sarl(CpuRegister reg, const Immediate& imm);
596 void sarl(CpuRegister operand, CpuRegister shifter);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700597
Calin Juravle9aec02f2014-11-18 23:06:35 +0000598 void shlq(CpuRegister reg, const Immediate& imm);
599 void shlq(CpuRegister operand, CpuRegister shifter);
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +0100600 void shrq(CpuRegister reg, const Immediate& imm);
Calin Juravle9aec02f2014-11-18 23:06:35 +0000601 void shrq(CpuRegister operand, CpuRegister shifter);
602 void sarq(CpuRegister reg, const Immediate& imm);
603 void sarq(CpuRegister operand, CpuRegister shifter);
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +0100604
Ian Rogersdd7624d2014-03-14 17:43:00 -0700605 void negl(CpuRegister reg);
Roland Levillain2e07b4f2014-10-23 18:12:09 +0100606 void negq(CpuRegister reg);
Roland Levillain70566432014-10-24 16:20:17 +0100607
Ian Rogersdd7624d2014-03-14 17:43:00 -0700608 void notl(CpuRegister reg);
Roland Levillain70566432014-10-24 16:20:17 +0100609 void notq(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700610
611 void enter(const Immediate& imm);
612 void leave();
613
614 void ret();
615 void ret(const Immediate& imm);
616
617 void nop();
618 void int3();
619 void hlt();
620
621 void j(Condition condition, Label* label);
Mark Mendell73f455e2015-08-21 09:30:05 -0400622 void j(Condition condition, NearLabel* label);
623 void jrcxz(NearLabel* label);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700624
Ian Rogersdd7624d2014-03-14 17:43:00 -0700625 void jmp(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700626 void jmp(const Address& address);
627 void jmp(Label* label);
Mark Mendell73f455e2015-08-21 09:30:05 -0400628 void jmp(NearLabel* label);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700629
630 X86_64Assembler* lock();
Ian Rogersdd7624d2014-03-14 17:43:00 -0700631 void cmpxchgl(const Address& address, CpuRegister reg);
Mark Mendell58d25fd2015-04-03 14:52:31 -0400632 void cmpxchgq(const Address& address, CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700633
634 void mfence();
635
636 X86_64Assembler* gs();
637
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700638 void setcc(Condition condition, CpuRegister dst);
639
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800640 void bswapl(CpuRegister dst);
641 void bswapq(CpuRegister dst);
642
Mark Mendellbcee0922015-09-15 21:45:01 -0400643 void bsfl(CpuRegister dst, CpuRegister src);
644 void bsfl(CpuRegister dst, const Address& src);
645 void bsfq(CpuRegister dst, CpuRegister src);
646 void bsfq(CpuRegister dst, const Address& src);
647
Mark Mendell8ae3ffb2015-08-12 21:16:41 -0400648 void bsrl(CpuRegister dst, CpuRegister src);
649 void bsrl(CpuRegister dst, const Address& src);
650 void bsrq(CpuRegister dst, CpuRegister src);
651 void bsrq(CpuRegister dst, const Address& src);
652
Aart Bik3f67e692016-01-15 14:35:12 -0800653 void popcntl(CpuRegister dst, CpuRegister src);
654 void popcntl(CpuRegister dst, const Address& src);
655 void popcntq(CpuRegister dst, CpuRegister src);
656 void popcntq(CpuRegister dst, const Address& src);
657
Mark Mendellbcee0922015-09-15 21:45:01 -0400658 void rorl(CpuRegister reg, const Immediate& imm);
659 void rorl(CpuRegister operand, CpuRegister shifter);
660 void roll(CpuRegister reg, const Immediate& imm);
661 void roll(CpuRegister operand, CpuRegister shifter);
662
663 void rorq(CpuRegister reg, const Immediate& imm);
664 void rorq(CpuRegister operand, CpuRegister shifter);
665 void rolq(CpuRegister reg, const Immediate& imm);
666 void rolq(CpuRegister operand, CpuRegister shifter);
667
Andreas Gampe21030dd2015-05-07 14:46:15 -0700668 void repne_scasw();
agicsaki71311f82015-07-27 11:34:13 -0700669 void repe_cmpsw();
agicsaki970abfb2015-07-31 10:31:14 -0700670 void repe_cmpsl();
agicsaki3fd0e6a2015-08-03 20:14:29 -0700671 void repe_cmpsq();
Mark Mendellb9c4bbe2015-07-01 14:26:52 -0400672 void rep_movsw();
Andreas Gampe21030dd2015-05-07 14:46:15 -0700673
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700674 //
675 // Macros for High-level operations.
676 //
677
Ian Rogersdd7624d2014-03-14 17:43:00 -0700678 void AddImmediate(CpuRegister reg, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700679
680 void LoadDoubleConstant(XmmRegister dst, double value);
681
Ian Rogersdd7624d2014-03-14 17:43:00 -0700682 void LockCmpxchgl(const Address& address, CpuRegister reg) {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700683 lock()->cmpxchgl(address, reg);
684 }
685
Mark Mendell58d25fd2015-04-03 14:52:31 -0400686 void LockCmpxchgq(const Address& address, CpuRegister reg) {
687 lock()->cmpxchgq(address, reg);
688 }
689
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700690 //
691 // Misc. functionality
692 //
693 int PreferredLoopAlignment() { return 16; }
694 void Align(int alignment, int offset);
Andreas Gampe85b62f22015-09-09 13:15:38 -0700695 void Bind(Label* label) OVERRIDE;
696 void Jump(Label* label) OVERRIDE {
697 jmp(label);
698 }
Mark Mendell73f455e2015-08-21 09:30:05 -0400699 void Bind(NearLabel* label);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700700
701 //
702 // Overridden common assembler high-level functionality
703 //
704
705 // Emit code that will create an activation on the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700706 void BuildFrame(size_t frame_size, ManagedRegister method_reg,
707 const std::vector<ManagedRegister>& callee_save_regs,
708 const ManagedRegisterEntrySpills& entry_spills) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700709
710 // Emit code that will remove an activation from the stack
Ian Rogersdd7624d2014-03-14 17:43:00 -0700711 void RemoveFrame(size_t frame_size, const std::vector<ManagedRegister>& callee_save_regs)
712 OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700713
Ian Rogersdd7624d2014-03-14 17:43:00 -0700714 void IncreaseFrameSize(size_t adjust) OVERRIDE;
715 void DecreaseFrameSize(size_t adjust) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700716
717 // Store routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700718 void Store(FrameOffset offs, ManagedRegister src, size_t size) OVERRIDE;
719 void StoreRef(FrameOffset dest, ManagedRegister src) OVERRIDE;
720 void StoreRawPtr(FrameOffset dest, ManagedRegister src) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700721
Ian Rogersdd7624d2014-03-14 17:43:00 -0700722 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700723
Ian Rogersdd7624d2014-03-14 17:43:00 -0700724 void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm, ManagedRegister scratch)
725 OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700726
Ian Rogersdd7624d2014-03-14 17:43:00 -0700727 void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs,
728 ManagedRegister scratch) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700729
Ian Rogersdd7624d2014-03-14 17:43:00 -0700730 void StoreStackPointerToThread64(ThreadOffset<8> thr_offs) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700731
Ian Rogersdd7624d2014-03-14 17:43:00 -0700732 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off,
733 ManagedRegister scratch) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700734
735 // Load routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700736 void Load(ManagedRegister dest, FrameOffset src, size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700737
Ian Rogersdd7624d2014-03-14 17:43:00 -0700738 void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700739
Ian Rogersdd7624d2014-03-14 17:43:00 -0700740 void LoadRef(ManagedRegister dest, FrameOffset src) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700741
Mathieu Chartiere401d142015-04-22 13:56:20 -0700742 void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
Roland Levillain4d027112015-07-01 15:41:14 +0100743 bool unpoison_reference) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700744
Ian Rogersdd7624d2014-03-14 17:43:00 -0700745 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700746
Ian Rogersdd7624d2014-03-14 17:43:00 -0700747 void LoadRawPtrFromThread64(ManagedRegister dest, ThreadOffset<8> offs) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700748
749 // Copying routines
Ian Rogersdd7624d2014-03-14 17:43:00 -0700750 void Move(ManagedRegister dest, ManagedRegister src, size_t size);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700751
Ian Rogersdd7624d2014-03-14 17:43:00 -0700752 void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs,
753 ManagedRegister scratch) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700754
Ian Rogersdd7624d2014-03-14 17:43:00 -0700755 void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs, ManagedRegister scratch)
756 OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700757
Ian Rogersdd7624d2014-03-14 17:43:00 -0700758 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700759
Ian Rogersdd7624d2014-03-14 17:43:00 -0700760 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700761
Ian Rogersdd7624d2014-03-14 17:43:00 -0700762 void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset, ManagedRegister scratch,
763 size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700764
Ian Rogersdd7624d2014-03-14 17:43:00 -0700765 void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src, ManagedRegister scratch,
766 size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700767
Ian Rogersdd7624d2014-03-14 17:43:00 -0700768 void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset, ManagedRegister scratch,
769 size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700770
Ian Rogersdd7624d2014-03-14 17:43:00 -0700771 void Copy(ManagedRegister dest, Offset dest_offset, ManagedRegister src, Offset src_offset,
772 ManagedRegister scratch, size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700773
Ian Rogersdd7624d2014-03-14 17:43:00 -0700774 void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
775 ManagedRegister scratch, size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700776
Ian Rogersdd7624d2014-03-14 17:43:00 -0700777 void MemoryBarrier(ManagedRegister) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700778
779 // Sign extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700780 void SignExtend(ManagedRegister mreg, size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700781
782 // Zero extension
Ian Rogersdd7624d2014-03-14 17:43:00 -0700783 void ZeroExtend(ManagedRegister mreg, size_t size) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700784
785 // Exploit fast access in managed code to Thread::Current()
Ian Rogersdd7624d2014-03-14 17:43:00 -0700786 void GetCurrentThread(ManagedRegister tr) OVERRIDE;
787 void GetCurrentThread(FrameOffset dest_offset, ManagedRegister scratch) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700788
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700789 // Set up out_reg to hold a Object** into the handle scope, or to be null if the
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700790 // value is null and null_allowed. in_reg holds a possibly stale reference
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700791 // that can be used to avoid loading the handle scope entry to see if the value is
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700792 // null.
793 void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
794 ManagedRegister in_reg, bool null_allowed) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700795
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700796 // Set up out_off to hold a Object** into the handle scope, or to be null if the
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700797 // value is null and null_allowed.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700798 void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
799 ManagedRegister scratch, bool null_allowed) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700800
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700801 // src holds a handle scope entry (Object**) load this into dst
802 virtual void LoadReferenceFromHandleScope(ManagedRegister dst,
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700803 ManagedRegister src);
804
805 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
806 // know that src may not be null.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700807 void VerifyObject(ManagedRegister src, bool could_be_null) OVERRIDE;
808 void VerifyObject(FrameOffset src, bool could_be_null) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700809
810 // Call to address held at [base+offset]
Ian Rogersdd7624d2014-03-14 17:43:00 -0700811 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) OVERRIDE;
812 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) OVERRIDE;
813 void CallFromThread64(ThreadOffset<8> offset, ManagedRegister scratch) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700814
815 // Generate code to check if Thread::Current()->exception_ is non-null
816 // and branch to a ExceptionSlowPath if it is.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700817 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) OVERRIDE;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700818
Mark Mendell39dcf552015-04-09 20:42:42 -0400819 // Add a double to the constant area, returning the offset into
820 // the constant area where the literal resides.
Mark Mendell9c86b482015-09-18 13:36:07 -0400821 size_t AddDouble(double v) { return constant_area_.AddDouble(v); }
Mark Mendellf55c3e02015-03-26 21:07:46 -0400822
Mark Mendell39dcf552015-04-09 20:42:42 -0400823 // Add a float to the constant area, returning the offset into
824 // the constant area where the literal resides.
Mark Mendell9c86b482015-09-18 13:36:07 -0400825 size_t AddFloat(float v) { return constant_area_.AddFloat(v); }
Mark Mendellf55c3e02015-03-26 21:07:46 -0400826
Mark Mendell39dcf552015-04-09 20:42:42 -0400827 // Add an int32_t to the constant area, returning the offset into
828 // the constant area where the literal resides.
Mark Mendell9c86b482015-09-18 13:36:07 -0400829 size_t AddInt32(int32_t v) {
830 return constant_area_.AddInt32(v);
831 }
832
833 // Add an int32_t to the end of the constant area, returning the offset into
834 // the constant area where the literal resides.
835 size_t AppendInt32(int32_t v) {
836 return constant_area_.AppendInt32(v);
837 }
Mark Mendellf55c3e02015-03-26 21:07:46 -0400838
Mark Mendell39dcf552015-04-09 20:42:42 -0400839 // Add an int64_t to the constant area, returning the offset into
840 // the constant area where the literal resides.
Mark Mendell9c86b482015-09-18 13:36:07 -0400841 size_t AddInt64(int64_t v) { return constant_area_.AddInt64(v); }
Mark Mendellf55c3e02015-03-26 21:07:46 -0400842
Mark Mendell39dcf552015-04-09 20:42:42 -0400843 // Add the contents of the constant area to the assembler buffer.
Mark Mendellf55c3e02015-03-26 21:07:46 -0400844 void AddConstantArea();
845
Mark Mendell39dcf552015-04-09 20:42:42 -0400846 // Is the constant area empty? Return true if there are no literals in the constant area.
Mark Mendellf55c3e02015-03-26 21:07:46 -0400847 bool IsConstantAreaEmpty() const { return constant_area_.GetSize() == 0; }
848
Mark Mendell9c86b482015-09-18 13:36:07 -0400849 // Return the current size of the constant area.
850 size_t ConstantAreaSize() const { return constant_area_.GetSize(); }
851
Roland Levillain4d027112015-07-01 15:41:14 +0100852 //
853 // Heap poisoning.
854 //
855
856 // Poison a heap reference contained in `reg`.
857 void PoisonHeapReference(CpuRegister reg) { negl(reg); }
858 // Unpoison a heap reference contained in `reg`.
859 void UnpoisonHeapReference(CpuRegister reg) { negl(reg); }
860 // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
861 void MaybeUnpoisonHeapReference(CpuRegister reg) {
862 if (kPoisonHeapReferences) {
863 UnpoisonHeapReference(reg);
864 }
865 }
866
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700867 private:
Ian Rogersdd7624d2014-03-14 17:43:00 -0700868 void EmitUint8(uint8_t value);
869 void EmitInt32(int32_t value);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700870 void EmitInt64(int64_t value);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700871 void EmitRegisterOperand(uint8_t rm, uint8_t reg);
872 void EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg);
873 void EmitFixup(AssemblerFixup* fixup);
874 void EmitOperandSizeOverride();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700875
Ian Rogersdd7624d2014-03-14 17:43:00 -0700876 void EmitOperand(uint8_t rm, const Operand& operand);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700877 void EmitImmediate(const Immediate& imm);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700878 void EmitComplex(uint8_t rm, const Operand& operand, const Immediate& immediate);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700879 void EmitLabel(Label* label, int instruction_size);
880 void EmitLabelLink(Label* label);
Mark Mendell73f455e2015-08-21 09:30:05 -0400881 void EmitLabelLink(NearLabel* label);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700882
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +0100883 void EmitGenericShift(bool wide, int rm, CpuRegister reg, const Immediate& imm);
Calin Juravle9aec02f2014-11-18 23:06:35 +0000884 void EmitGenericShift(bool wide, int rm, CpuRegister operand, CpuRegister shifter);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700885
886 // If any input is not false, output the necessary rex prefix.
887 void EmitOptionalRex(bool force, bool w, bool r, bool x, bool b);
888
889 // Emit a rex prefix byte if necessary for reg. ie if reg is a register in the range R8 to R15.
890 void EmitOptionalRex32(CpuRegister reg);
891 void EmitOptionalRex32(CpuRegister dst, CpuRegister src);
892 void EmitOptionalRex32(XmmRegister dst, XmmRegister src);
893 void EmitOptionalRex32(CpuRegister dst, XmmRegister src);
894 void EmitOptionalRex32(XmmRegister dst, CpuRegister src);
895 void EmitOptionalRex32(const Operand& operand);
896 void EmitOptionalRex32(CpuRegister dst, const Operand& operand);
897 void EmitOptionalRex32(XmmRegister dst, const Operand& operand);
898
899 // Emit a REX.W prefix plus necessary register bit encodings.
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000900 void EmitRex64();
Ian Rogersdd7624d2014-03-14 17:43:00 -0700901 void EmitRex64(CpuRegister reg);
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000902 void EmitRex64(const Operand& operand);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700903 void EmitRex64(CpuRegister dst, CpuRegister src);
904 void EmitRex64(CpuRegister dst, const Operand& operand);
Mark Mendell40741f32015-04-20 22:10:34 -0400905 void EmitRex64(XmmRegister dst, const Operand& operand);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100906 void EmitRex64(XmmRegister dst, CpuRegister src);
Roland Levillain624279f2014-12-04 11:54:28 +0000907 void EmitRex64(CpuRegister dst, XmmRegister src);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700908
909 // Emit a REX prefix to normalize byte registers plus necessary register bit encodings.
910 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src);
911 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700912
Mark Mendellf55c3e02015-03-26 21:07:46 -0400913 ConstantArea constant_area_;
914
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700915 DISALLOW_COPY_AND_ASSIGN(X86_64Assembler);
916};
917
918inline void X86_64Assembler::EmitUint8(uint8_t value) {
919 buffer_.Emit<uint8_t>(value);
920}
921
922inline void X86_64Assembler::EmitInt32(int32_t value) {
923 buffer_.Emit<int32_t>(value);
924}
925
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700926inline void X86_64Assembler::EmitInt64(int64_t value) {
Roland Levillain55dcfb52014-10-24 18:09:09 +0100927 // Write this 64-bit value as two 32-bit words for alignment reasons
928 // (this is essentially when running on ARM, which does not allow
929 // 64-bit unaligned accesses). We assume little-endianness here.
930 EmitInt32(Low32Bits(value));
931 EmitInt32(High32Bits(value));
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700932}
933
Ian Rogersdd7624d2014-03-14 17:43:00 -0700934inline void X86_64Assembler::EmitRegisterOperand(uint8_t rm, uint8_t reg) {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700935 CHECK_GE(rm, 0);
936 CHECK_LT(rm, 8);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100937 buffer_.Emit<uint8_t>((0xC0 | (reg & 7)) + (rm << 3));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700938}
939
Ian Rogersdd7624d2014-03-14 17:43:00 -0700940inline void X86_64Assembler::EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg) {
941 EmitRegisterOperand(rm, static_cast<uint8_t>(reg.AsFloatRegister()));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700942}
943
944inline void X86_64Assembler::EmitFixup(AssemblerFixup* fixup) {
945 buffer_.EmitFixup(fixup);
946}
947
948inline void X86_64Assembler::EmitOperandSizeOverride() {
949 EmitUint8(0x66);
950}
951
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700952} // namespace x86_64
953} // namespace art
954
955#endif // ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_