blob: ea944c200ec8426df55713baf78a8f74bfe8605d [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
jaishank20d1c942019-03-08 15:08:17 +053022#include "arch/x86_64/instruction_set_features_x86_64.h"
Vladimir Marko93205e32016-04-13 11:59:46 +010023#include "base/arena_containers.h"
David Brazdild9c90372016-09-14 16:53:55 +010024#include "base/array_ref.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010025#include "base/bit_utils.h"
David Sehr1979c642018-04-26 14:41:18 -070026#include "base/globals.h"
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070027#include "base/macros.h"
28#include "constants_x86_64.h"
Andreas Gampe09659c22017-09-18 18:23:32 -070029#include "heap_poisoning.h"
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070030#include "managed_register_x86_64.h"
31#include "offsets.h"
32#include "utils/assembler.h"
Andreas Gampe3b165bc2016-08-01 22:07:04 -070033#include "utils/jni_macro_assembler.h"
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070034
35namespace art {
36namespace x86_64 {
37
avignate5408b6b2014-06-04 17:59:44 +070038// Encodes an immediate value for operands.
39//
40// Note: Immediates can be 64b on x86-64 for certain instructions, but are often restricted
41// to 32b.
42//
43// Note: As we support cross-compilation, the value type must be int64_t. Please be aware of
44// conversion rules in expressions regarding negation, especially size_t on 32b.
Ian Rogerscf7f1912014-10-22 22:06:39 -070045class Immediate : public ValueObject {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070046 public:
Andreas Gampe277ccbd2014-11-03 21:36:10 -080047 explicit Immediate(int64_t value_in) : value_(value_in) {}
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070048
Andreas Gampe5a4fa822014-03-31 16:50:12 -070049 int64_t value() const { return value_; }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070050
Andreas Gampeab1eb0d2015-02-13 19:23:55 -080051 bool is_int8() const { return IsInt<8>(value_); }
52 bool is_uint8() const { return IsUint<8>(value_); }
53 bool is_int16() const { return IsInt<16>(value_); }
54 bool is_uint16() const { return IsUint<16>(value_); }
55 bool is_int32() const { return IsInt<32>(value_); }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070056
57 private:
Andreas Gampe5a4fa822014-03-31 16:50:12 -070058 const int64_t value_;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070059};
60
61
Ian Rogerscf7f1912014-10-22 22:06:39 -070062class Operand : public ValueObject {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +070063 public:
64 uint8_t mod() const {
65 return (encoding_at(0) >> 6) & 3;
66 }
67
68 Register rm() const {
69 return static_cast<Register>(encoding_at(0) & 7);
70 }
71
72 ScaleFactor scale() const {
73 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
74 }
75
76 Register index() const {
77 return static_cast<Register>((encoding_at(1) >> 3) & 7);
78 }
79
80 Register base() const {
81 return static_cast<Register>(encoding_at(1) & 7);
82 }
83
Aart Bikf7754e82017-09-20 10:33:06 -070084 CpuRegister cpu_rm() const {
85 int ext = (rex_ & 1) != 0 ? x86_64::R8 : x86_64::RAX;
86 return static_cast<CpuRegister>(rm() + ext);
87 }
88
89 CpuRegister cpu_index() const {
90 int ext = (rex_ & 2) != 0 ? x86_64::R8 : x86_64::RAX;
91 return static_cast<CpuRegister>(index() + ext);
92 }
93
94 CpuRegister cpu_base() const {
95 int ext = (rex_ & 1) != 0 ? x86_64::R8 : x86_64::RAX;
96 return static_cast<CpuRegister>(base() + ext);
97 }
98
Ian Rogers790a6b72014-04-01 10:36:00 -070099 uint8_t rex() const {
100 return rex_;
101 }
102
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700103 int8_t disp8() const {
104 CHECK_GE(length_, 2);
105 return static_cast<int8_t>(encoding_[length_ - 1]);
106 }
107
108 int32_t disp32() const {
109 CHECK_GE(length_, 5);
110 int32_t value;
111 memcpy(&value, &encoding_[length_ - 4], sizeof(value));
112 return value;
113 }
114
Ulya Trafimovichaf5d3042021-06-10 15:29:21 +0100115 int32_t disp() const {
116 switch (mod()) {
117 case 0:
118 // With mod 00b RBP is special and means disp32 (either in r/m or in SIB base).
119 return (rm() == RBP || (rm() == RSP && base() == RBP)) ? disp32() : 0;
120 case 1:
121 return disp8();
122 case 2:
123 return disp32();
124 default:
125 // Mod 11b means reg/reg, so there is no address and consequently no displacement.
126 DCHECK(false) << "there is no displacement in x86_64 reg/reg operand";
127 UNREACHABLE();
128 }
129 }
130
Ian Rogersdd7624d2014-03-14 17:43:00 -0700131 bool IsRegister(CpuRegister reg) const {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700132 return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only.
Ian Rogers790a6b72014-04-01 10:36:00 -0700133 && ((encoding_[0] & 0x07) == reg.LowBits()) // Register codes match.
134 && (reg.NeedsRex() == ((rex_ & 1) != 0)); // REX.000B bits match.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700135 }
136
Mark Mendellf55c3e02015-03-26 21:07:46 -0400137 AssemblerFixup* GetFixup() const {
138 return fixup_;
139 }
140
Ulya Trafimovichaf5d3042021-06-10 15:29:21 +0100141 inline bool operator==(const Operand &op) const {
142 return rex_ == op.rex_ &&
143 length_ == op.length_ &&
144 memcmp(encoding_, op.encoding_, length_) == 0 &&
145 fixup_ == op.fixup_;
146 }
147
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700148 protected:
149 // Operand can be sub classed (e.g: Address).
Mark Mendellf55c3e02015-03-26 21:07:46 -0400150 Operand() : rex_(0), length_(0), fixup_(nullptr) { }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700151
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800152 void SetModRM(uint8_t mod_in, CpuRegister rm_in) {
153 CHECK_EQ(mod_in & ~3, 0);
154 if (rm_in.NeedsRex()) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700155 rex_ |= 0x41; // REX.000B
156 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800157 encoding_[0] = (mod_in << 6) | rm_in.LowBits();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700158 length_ = 1;
159 }
160
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800161 void SetSIB(ScaleFactor scale_in, CpuRegister index_in, CpuRegister base_in) {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700162 CHECK_EQ(length_, 1);
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800163 CHECK_EQ(scale_in & ~3, 0);
164 if (base_in.NeedsRex()) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700165 rex_ |= 0x41; // REX.000B
166 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800167 if (index_in.NeedsRex()) {
Ian Rogers790a6b72014-04-01 10:36:00 -0700168 rex_ |= 0x42; // REX.00X0
169 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800170 encoding_[1] = (scale_in << 6) | (static_cast<uint8_t>(index_in.LowBits()) << 3) |
171 static_cast<uint8_t>(base_in.LowBits());
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700172 length_ = 2;
173 }
174
175 void SetDisp8(int8_t disp) {
176 CHECK(length_ == 1 || length_ == 2);
177 encoding_[length_++] = static_cast<uint8_t>(disp);
178 }
179
180 void SetDisp32(int32_t disp) {
181 CHECK(length_ == 1 || length_ == 2);
182 int disp_size = sizeof(disp);
183 memmove(&encoding_[length_], &disp, disp_size);
184 length_ += disp_size;
185 }
186
Mark Mendellf55c3e02015-03-26 21:07:46 -0400187 void SetFixup(AssemblerFixup* fixup) {
188 fixup_ = fixup;
189 }
190
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700191 private:
Ian Rogers790a6b72014-04-01 10:36:00 -0700192 uint8_t rex_;
193 uint8_t length_;
194 uint8_t encoding_[6];
Mark Mendellf55c3e02015-03-26 21:07:46 -0400195 AssemblerFixup* fixup_;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700196
Mark Mendellf55c3e02015-03-26 21:07:46 -0400197 explicit Operand(CpuRegister reg) : rex_(0), length_(0), fixup_(nullptr) { SetModRM(3, reg); }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700198
199 // Get the operand encoding byte at the given index.
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800200 uint8_t encoding_at(int index_in) const {
201 CHECK_GE(index_in, 0);
202 CHECK_LT(index_in, length_);
203 return encoding_[index_in];
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700204 }
205
206 friend class X86_64Assembler;
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700207};
208
209
210class Address : public Operand {
211 public:
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800212 Address(CpuRegister base_in, int32_t disp) {
213 Init(base_in, disp);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700214 }
215
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800216 Address(CpuRegister base_in, Offset disp) {
217 Init(base_in, disp.Int32Value());
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700218 }
219
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800220 Address(CpuRegister base_in, FrameOffset disp) {
221 CHECK_EQ(base_in.AsRegister(), RSP);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700222 Init(CpuRegister(RSP), disp.Int32Value());
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700223 }
224
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800225 Address(CpuRegister base_in, MemberOffset disp) {
226 Init(base_in, disp.Int32Value());
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700227 }
228
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800229 void Init(CpuRegister base_in, int32_t disp) {
Nicolas Geoffray784cc5c2014-12-18 20:25:18 +0000230 if (disp == 0 && base_in.LowBits() != RBP) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800231 SetModRM(0, base_in);
Nicolas Geoffray98893962015-01-21 12:32:32 +0000232 if (base_in.LowBits() == RSP) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800233 SetSIB(TIMES_1, CpuRegister(RSP), base_in);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700234 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700235 } else if (disp >= -128 && disp <= 127) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800236 SetModRM(1, base_in);
Nicolas Geoffray98893962015-01-21 12:32:32 +0000237 if (base_in.LowBits() == RSP) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800238 SetSIB(TIMES_1, CpuRegister(RSP), base_in);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700239 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700240 SetDisp8(disp);
241 } else {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800242 SetModRM(2, base_in);
Nicolas Geoffray98893962015-01-21 12:32:32 +0000243 if (base_in.LowBits() == RSP) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800244 SetSIB(TIMES_1, CpuRegister(RSP), base_in);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700245 }
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700246 SetDisp32(disp);
247 }
248 }
249
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800250 Address(CpuRegister index_in, ScaleFactor scale_in, int32_t disp) {
251 CHECK_NE(index_in.AsRegister(), RSP); // Illegal addressing mode.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700252 SetModRM(0, CpuRegister(RSP));
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800253 SetSIB(scale_in, index_in, CpuRegister(RBP));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700254 SetDisp32(disp);
255 }
256
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800257 Address(CpuRegister base_in, CpuRegister index_in, ScaleFactor scale_in, int32_t disp) {
258 CHECK_NE(index_in.AsRegister(), RSP); // Illegal addressing mode.
Nicolas Geoffray784cc5c2014-12-18 20:25:18 +0000259 if (disp == 0 && base_in.LowBits() != RBP) {
Ian Rogersdd7624d2014-03-14 17:43:00 -0700260 SetModRM(0, CpuRegister(RSP));
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800261 SetSIB(scale_in, index_in, base_in);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700262 } else if (disp >= -128 && disp <= 127) {
Ian Rogersdd7624d2014-03-14 17:43:00 -0700263 SetModRM(1, CpuRegister(RSP));
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800264 SetSIB(scale_in, index_in, base_in);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700265 SetDisp8(disp);
266 } else {
Ian Rogersdd7624d2014-03-14 17:43:00 -0700267 SetModRM(2, CpuRegister(RSP));
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800268 SetSIB(scale_in, index_in, base_in);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700269 SetDisp32(disp);
270 }
271 }
272
Ian Rogersdd7624d2014-03-14 17:43:00 -0700273 // If no_rip is true then the Absolute address isn't RIP relative.
Ian Rogers13735952014-10-08 12:43:28 -0700274 static Address Absolute(uintptr_t addr, bool no_rip = false) {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700275 Address result;
Ian Rogersdd7624d2014-03-14 17:43:00 -0700276 if (no_rip) {
277 result.SetModRM(0, CpuRegister(RSP));
278 result.SetSIB(TIMES_1, CpuRegister(RSP), CpuRegister(RBP));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700279 result.SetDisp32(addr);
280 } else {
Mark Mendell39dcf552015-04-09 20:42:42 -0400281 // RIP addressing is done using RBP as the base register.
282 // The value in RBP isn't used. Instead the offset is added to RIP.
Ian Rogersdd7624d2014-03-14 17:43:00 -0700283 result.SetModRM(0, CpuRegister(RBP));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700284 result.SetDisp32(addr);
285 }
286 return result;
287 }
288
Mark Mendellf55c3e02015-03-26 21:07:46 -0400289 // An RIP relative address that will be fixed up later.
290 static Address RIP(AssemblerFixup* fixup) {
291 Address result;
Mark Mendell39dcf552015-04-09 20:42:42 -0400292 // RIP addressing is done using RBP as the base register.
293 // The value in RBP isn't used. Instead the offset is added to RIP.
Mark Mendellf55c3e02015-03-26 21:07:46 -0400294 result.SetModRM(0, CpuRegister(RBP));
295 result.SetDisp32(0);
296 result.SetFixup(fixup);
297 return result;
298 }
299
Ian Rogersdd7624d2014-03-14 17:43:00 -0700300 // If no_rip is true then the Absolute address isn't RIP relative.
Andreas Gampe542451c2016-07-26 09:02:02 -0700301 static Address Absolute(ThreadOffset64 addr, bool no_rip = false) {
Ian Rogersdd7624d2014-03-14 17:43:00 -0700302 return Absolute(addr.Int32Value(), no_rip);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700303 }
304
Ulya Trafimovichaf5d3042021-06-10 15:29:21 +0100305 // Break the address into pieces and reassemble it again with a new displacement.
306 // Note that it may require a new addressing mode if displacement size is changed.
307 static Address displace(const Address &addr, int32_t disp) {
308 const int32_t new_disp = addr.disp() + disp;
309 const bool sib = addr.rm() == RSP;
310 const bool rbp = RBP == (sib ? addr.base() : addr.rm());
311 Address new_addr;
312 if (addr.mod() == 0 && rbp) {
313 // Special case: mod 00b and RBP in r/m or SIB base => 32-bit displacement.
314 // This case includes RIP-relative addressing.
315 new_addr.SetModRM(0, addr.cpu_rm());
316 if (sib) {
317 new_addr.SetSIB(addr.scale(), addr.cpu_index(), addr.cpu_base());
318 }
319 new_addr.SetDisp32(new_disp);
320 } else if (new_disp == 0 && !rbp) {
321 // Mod 00b (excluding a special case for RBP) => no displacement.
322 new_addr.SetModRM(0, addr.cpu_rm());
323 if (sib) {
324 new_addr.SetSIB(addr.scale(), addr.cpu_index(), addr.cpu_base());
325 }
326 } else if (new_disp >= -128 && new_disp <= 127) {
327 // Mod 01b => 8-bit displacement.
328 new_addr.SetModRM(1, addr.cpu_rm());
329 if (sib) {
330 new_addr.SetSIB(addr.scale(), addr.cpu_index(), addr.cpu_base());
331 }
332 new_addr.SetDisp8(new_disp);
333 } else {
334 // Mod 10b => 32-bit displacement.
335 new_addr.SetModRM(2, addr.cpu_rm());
336 if (sib) {
337 new_addr.SetSIB(addr.scale(), addr.cpu_index(), addr.cpu_base());
338 }
339 new_addr.SetDisp32(new_disp);
340 }
341 new_addr.SetFixup(addr.GetFixup());
342 return new_addr;
343 }
344
345 inline bool operator==(const Address& addr) const {
346 return static_cast<const Operand&>(*this) == static_cast<const Operand&>(addr);
347 }
348
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700349 private:
350 Address() {}
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700351};
352
Aart Bikf7754e82017-09-20 10:33:06 -0700353std::ostream& operator<<(std::ostream& os, const Address& addr);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700354
Mark Mendellf55c3e02015-03-26 21:07:46 -0400355/**
356 * Class to handle constant area values.
357 */
358class ConstantArea {
Mark Mendell9c86b482015-09-18 13:36:07 -0400359 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +0100360 explicit ConstantArea(ArenaAllocator* allocator)
361 : buffer_(allocator->Adapter(kArenaAllocAssembler)) {}
Mark Mendellf55c3e02015-03-26 21:07:46 -0400362
Mark Mendell9c86b482015-09-18 13:36:07 -0400363 // Add a double to the constant area, returning the offset into
364 // the constant area where the literal resides.
365 size_t AddDouble(double v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400366
Mark Mendell9c86b482015-09-18 13:36:07 -0400367 // Add a float to the constant area, returning the offset into
368 // the constant area where the literal resides.
369 size_t AddFloat(float v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400370
Mark Mendell9c86b482015-09-18 13:36:07 -0400371 // Add an int32_t to the constant area, returning the offset into
372 // the constant area where the literal resides.
373 size_t AddInt32(int32_t v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400374
Mark Mendell9c86b482015-09-18 13:36:07 -0400375 // Add an int32_t to the end of the constant area, returning the offset into
376 // the constant area where the literal resides.
377 size_t AppendInt32(int32_t v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400378
Mark Mendell9c86b482015-09-18 13:36:07 -0400379 // Add an int64_t to the constant area, returning the offset into
380 // the constant area where the literal resides.
381 size_t AddInt64(int64_t v);
Mark Mendellf55c3e02015-03-26 21:07:46 -0400382
Mark Mendell9c86b482015-09-18 13:36:07 -0400383 size_t GetSize() const {
384 return buffer_.size() * elem_size_;
385 }
Mark Mendellf55c3e02015-03-26 21:07:46 -0400386
Vladimir Marko93205e32016-04-13 11:59:46 +0100387 ArrayRef<const int32_t> GetBuffer() const {
388 return ArrayRef<const int32_t>(buffer_);
Mark Mendell9c86b482015-09-18 13:36:07 -0400389 }
390
391 private:
392 static constexpr size_t elem_size_ = sizeof(int32_t);
Vladimir Marko93205e32016-04-13 11:59:46 +0100393 ArenaVector<int32_t> buffer_;
Mark Mendellf55c3e02015-03-26 21:07:46 -0400394};
395
396
Mark Mendell73f455e2015-08-21 09:30:05 -0400397// This is equivalent to the Label class, used in a slightly different context. We
398// inherit the functionality of the Label class, but prevent unintended
399// derived-to-base conversions by making the base class private.
400class NearLabel : private Label {
401 public:
402 NearLabel() : Label() {}
403
404 // Expose the Label routines that we need.
405 using Label::Position;
406 using Label::LinkPosition;
407 using Label::IsBound;
408 using Label::IsUnused;
409 using Label::IsLinked;
410
411 private:
412 using Label::BindTo;
413 using Label::LinkTo;
414
415 friend class x86_64::X86_64Assembler;
416
417 DISALLOW_COPY_AND_ASSIGN(NearLabel);
418};
419
420
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100421class X86_64Assembler final : public Assembler {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700422 public:
jaishank20d1c942019-03-08 15:08:17 +0530423 explicit X86_64Assembler(ArenaAllocator* allocator,
424 const X86_64InstructionSetFeatures* instruction_set_features = nullptr)
425 : Assembler(allocator),
426 constant_area_(allocator),
427 has_AVX_(instruction_set_features != nullptr ? instruction_set_features->HasAVX(): false),
428 has_AVX2_(instruction_set_features != nullptr ? instruction_set_features->HasAVX2() : false) {}
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700429 virtual ~X86_64Assembler() {}
430
431 /*
432 * Emit Machine Instructions.
433 */
Ian Rogersdd7624d2014-03-14 17:43:00 -0700434 void call(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700435 void call(const Address& address);
436 void call(Label* label);
437
Ian Rogersdd7624d2014-03-14 17:43:00 -0700438 void pushq(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700439 void pushq(const Address& address);
440 void pushq(const Immediate& imm);
441
Ian Rogersdd7624d2014-03-14 17:43:00 -0700442 void popq(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700443 void popq(const Address& address);
444
Ian Rogersdd7624d2014-03-14 17:43:00 -0700445 void movq(CpuRegister dst, const Immediate& src);
446 void movl(CpuRegister dst, const Immediate& src);
447 void movq(CpuRegister dst, CpuRegister src);
448 void movl(CpuRegister dst, CpuRegister src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700449
Mark Mendell7a08fb52015-07-15 14:09:35 -0400450 void movntl(const Address& dst, CpuRegister src);
451 void movntq(const Address& dst, CpuRegister src);
452
Ian Rogersdd7624d2014-03-14 17:43:00 -0700453 void movq(CpuRegister dst, const Address& src);
454 void movl(CpuRegister dst, const Address& src);
455 void movq(const Address& dst, CpuRegister src);
Mark Mendellcfa410b2015-05-25 16:02:44 -0400456 void movq(const Address& dst, const Immediate& imm);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700457 void movl(const Address& dst, CpuRegister src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700458 void movl(const Address& dst, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700459
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800460 void cmov(Condition c, CpuRegister dst, CpuRegister src); // This is the 64b version.
461 void cmov(Condition c, CpuRegister dst, CpuRegister src, bool is64bit);
Mark Mendellabdac472016-02-12 13:49:03 -0500462 void cmov(Condition c, CpuRegister dst, const Address& src, bool is64bit);
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800463
Ian Rogersdd7624d2014-03-14 17:43:00 -0700464 void movzxb(CpuRegister dst, CpuRegister src);
465 void movzxb(CpuRegister dst, const Address& src);
466 void movsxb(CpuRegister dst, CpuRegister src);
467 void movsxb(CpuRegister dst, const Address& src);
468 void movb(CpuRegister dst, const Address& src);
469 void movb(const Address& dst, CpuRegister src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700470 void movb(const Address& dst, const Immediate& imm);
471
Ian Rogersdd7624d2014-03-14 17:43:00 -0700472 void movzxw(CpuRegister dst, CpuRegister src);
473 void movzxw(CpuRegister dst, const Address& src);
474 void movsxw(CpuRegister dst, CpuRegister src);
475 void movsxw(CpuRegister dst, const Address& src);
476 void movw(CpuRegister dst, const Address& src);
477 void movw(const Address& dst, CpuRegister src);
Nicolas Geoffray26a25ef2014-09-30 13:54:09 +0100478 void movw(const Address& dst, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700479
Ian Rogersdd7624d2014-03-14 17:43:00 -0700480 void leaq(CpuRegister dst, const Address& src);
Nicolas Geoffray748f1402015-01-27 08:17:54 +0000481 void leal(CpuRegister dst, const Address& src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700482
Aart Bikc7782262017-01-13 16:20:08 -0800483 void movaps(XmmRegister dst, XmmRegister src); // move
484 void movaps(XmmRegister dst, const Address& src); // load aligned
485 void movups(XmmRegister dst, const Address& src); // load unaligned
486 void movaps(const Address& dst, XmmRegister src); // store aligned
487 void movups(const Address& dst, XmmRegister src); // store unaligned
Nicolas Geoffray7fb49da2014-10-06 09:12:41 +0100488
jaishank20d1c942019-03-08 15:08:17 +0530489 void vmovaps(XmmRegister dst, XmmRegister src); // move
490 void vmovaps(XmmRegister dst, const Address& src); // load aligned
491 void vmovaps(const Address& dst, XmmRegister src); // store aligned
492 void vmovups(XmmRegister dst, const Address& src); // load unaligned
493 void vmovups(const Address& dst, XmmRegister src); // store unaligned
494
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700495 void movss(XmmRegister dst, const Address& src);
496 void movss(const Address& dst, XmmRegister src);
497 void movss(XmmRegister dst, XmmRegister src);
498
Roland Levillaindff1f282014-11-05 14:15:05 +0000499 void movsxd(CpuRegister dst, CpuRegister src);
500 void movsxd(CpuRegister dst, const Address& src);
501
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800502 void movd(XmmRegister dst, CpuRegister src); // Note: this is the r64 version, formally movq.
503 void movd(CpuRegister dst, XmmRegister src); // Note: this is the r64 version, formally movq.
504 void movd(XmmRegister dst, CpuRegister src, bool is64bit);
505 void movd(CpuRegister dst, XmmRegister src, bool is64bit);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700506
507 void addss(XmmRegister dst, XmmRegister src);
508 void addss(XmmRegister dst, const Address& src);
509 void subss(XmmRegister dst, XmmRegister src);
510 void subss(XmmRegister dst, const Address& src);
511 void mulss(XmmRegister dst, XmmRegister src);
512 void mulss(XmmRegister dst, const Address& src);
513 void divss(XmmRegister dst, XmmRegister src);
514 void divss(XmmRegister dst, const Address& src);
515
Aart Bikc7782262017-01-13 16:20:08 -0800516 void addps(XmmRegister dst, XmmRegister src); // no addr variant (for now)
517 void subps(XmmRegister dst, XmmRegister src);
518 void mulps(XmmRegister dst, XmmRegister src);
519 void divps(XmmRegister dst, XmmRegister src);
520
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530521 void vmulps(XmmRegister dst, XmmRegister src1, XmmRegister src2);
522 void vmulpd(XmmRegister dst, XmmRegister src1, XmmRegister src2);
523 void vdivps(XmmRegister dst, XmmRegister src1, XmmRegister src2);
524 void vdivpd(XmmRegister dst, XmmRegister src1, XmmRegister src2);
525
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530526 void vaddps(XmmRegister dst, XmmRegister add_left, XmmRegister add_right);
527 void vsubps(XmmRegister dst, XmmRegister add_left, XmmRegister add_right);
528 void vsubpd(XmmRegister dst, XmmRegister add_left, XmmRegister add_right);
529 void vaddpd(XmmRegister dst, XmmRegister add_left, XmmRegister add_right);
530
Shalini Salomi Bodapati6545ee32021-11-02 20:01:06 +0530531 void vfmadd213ss(XmmRegister accumulator, XmmRegister left, XmmRegister right);
532 void vfmadd213sd(XmmRegister accumulator, XmmRegister left, XmmRegister right);
533
Aart Bikc7782262017-01-13 16:20:08 -0800534 void movapd(XmmRegister dst, XmmRegister src); // move
535 void movapd(XmmRegister dst, const Address& src); // load aligned
536 void movupd(XmmRegister dst, const Address& src); // load unaligned
537 void movapd(const Address& dst, XmmRegister src); // store aligned
538 void movupd(const Address& dst, XmmRegister src); // store unaligned
539
jaishank20d1c942019-03-08 15:08:17 +0530540 void vmovapd(XmmRegister dst, XmmRegister src); // move
541 void vmovapd(XmmRegister dst, const Address& src); // load aligned
542 void vmovapd(const Address& dst, XmmRegister src); // store aligned
543 void vmovupd(XmmRegister dst, const Address& src); // load unaligned
544 void vmovupd(const Address& dst, XmmRegister src); // store unaligned
545
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700546 void movsd(XmmRegister dst, const Address& src);
547 void movsd(const Address& dst, XmmRegister src);
548 void movsd(XmmRegister dst, XmmRegister src);
549
550 void addsd(XmmRegister dst, XmmRegister src);
551 void addsd(XmmRegister dst, const Address& src);
552 void subsd(XmmRegister dst, XmmRegister src);
553 void subsd(XmmRegister dst, const Address& src);
554 void mulsd(XmmRegister dst, XmmRegister src);
555 void mulsd(XmmRegister dst, const Address& src);
556 void divsd(XmmRegister dst, XmmRegister src);
557 void divsd(XmmRegister dst, const Address& src);
558
Aart Bikc7782262017-01-13 16:20:08 -0800559 void addpd(XmmRegister dst, XmmRegister src); // no addr variant (for now)
560 void subpd(XmmRegister dst, XmmRegister src);
561 void mulpd(XmmRegister dst, XmmRegister src);
562 void divpd(XmmRegister dst, XmmRegister src);
563
Aart Bik68555e92017-02-13 14:28:45 -0800564 void movdqa(XmmRegister dst, XmmRegister src); // move
565 void movdqa(XmmRegister dst, const Address& src); // load aligned
566 void movdqu(XmmRegister dst, const Address& src); // load unaligned
567 void movdqa(const Address& dst, XmmRegister src); // store aligned
568 void movdqu(const Address& dst, XmmRegister src); // store unaligned
569
jaishank20d1c942019-03-08 15:08:17 +0530570 void vmovdqa(XmmRegister dst, XmmRegister src); // move
571 void vmovdqa(XmmRegister dst, const Address& src); // load aligned
572 void vmovdqa(const Address& dst, XmmRegister src); // store aligned
573 void vmovdqu(XmmRegister dst, const Address& src); // load unaligned
574 void vmovdqu(const Address& dst, XmmRegister src); // store unaligned
575
Aart Bike69d7a92017-02-17 11:48:23 -0800576 void paddb(XmmRegister dst, XmmRegister src); // no addr variant (for now)
577 void psubb(XmmRegister dst, XmmRegister src);
578
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530579 void vpaddb(XmmRegister dst, XmmRegister add_left, XmmRegister add_right);
580 void vpaddw(XmmRegister dst, XmmRegister add_left, XmmRegister add_right);
581
Aart Bike69d7a92017-02-17 11:48:23 -0800582 void paddw(XmmRegister dst, XmmRegister src);
583 void psubw(XmmRegister dst, XmmRegister src);
584 void pmullw(XmmRegister dst, XmmRegister src);
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530585 void vpmullw(XmmRegister dst, XmmRegister src1, XmmRegister src2);
Aart Bike69d7a92017-02-17 11:48:23 -0800586
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530587 void vpsubb(XmmRegister dst, XmmRegister src1, XmmRegister src2);
588 void vpsubw(XmmRegister dst, XmmRegister src1, XmmRegister src2);
589 void vpsubd(XmmRegister dst, XmmRegister src1, XmmRegister src2);
590
Aart Bike69d7a92017-02-17 11:48:23 -0800591 void paddd(XmmRegister dst, XmmRegister src);
Aart Bik68555e92017-02-13 14:28:45 -0800592 void psubd(XmmRegister dst, XmmRegister src);
593 void pmulld(XmmRegister dst, XmmRegister src);
Shalini Salomi Bodapatib45a4352019-07-10 16:09:41 +0530594 void vpmulld(XmmRegister dst, XmmRegister src1, XmmRegister src2);
Aart Bik68555e92017-02-13 14:28:45 -0800595
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530596 void vpaddd(XmmRegister dst, XmmRegister src1, XmmRegister src2);
597
Aart Bike69d7a92017-02-17 11:48:23 -0800598 void paddq(XmmRegister dst, XmmRegister src);
599 void psubq(XmmRegister dst, XmmRegister src);
600
Shalini Salomi Bodapati81d15be2019-05-30 11:00:42 +0530601 void vpaddq(XmmRegister dst, XmmRegister add_left, XmmRegister add_right);
602 void vpsubq(XmmRegister dst, XmmRegister add_left, XmmRegister add_right);
603
Aart Bik4ca17352018-03-07 15:47:39 -0800604 void paddusb(XmmRegister dst, XmmRegister src);
605 void paddsb(XmmRegister dst, XmmRegister src);
606 void paddusw(XmmRegister dst, XmmRegister src);
607 void paddsw(XmmRegister dst, XmmRegister src);
608 void psubusb(XmmRegister dst, XmmRegister src);
609 void psubsb(XmmRegister dst, XmmRegister src);
610 void psubusw(XmmRegister dst, XmmRegister src);
611 void psubsw(XmmRegister dst, XmmRegister src);
612
Andreas Gampe851df202014-11-12 14:05:46 -0800613 void cvtsi2ss(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version.
Roland Levillain6d0e4832014-11-27 18:31:21 +0000614 void cvtsi2ss(XmmRegister dst, CpuRegister src, bool is64bit);
Mark Mendell40741f32015-04-20 22:10:34 -0400615 void cvtsi2ss(XmmRegister dst, const Address& src, bool is64bit);
Andreas Gampe851df202014-11-12 14:05:46 -0800616 void cvtsi2sd(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version.
Roland Levillain647b9ed2014-11-27 12:06:00 +0000617 void cvtsi2sd(XmmRegister dst, CpuRegister src, bool is64bit);
Mark Mendell40741f32015-04-20 22:10:34 -0400618 void cvtsi2sd(XmmRegister dst, const Address& src, bool is64bit);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700619
Andreas Gampe851df202014-11-12 14:05:46 -0800620 void cvtss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700621 void cvtss2sd(XmmRegister dst, XmmRegister src);
Mark Mendell40741f32015-04-20 22:10:34 -0400622 void cvtss2sd(XmmRegister dst, const Address& src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700623
Andreas Gampe851df202014-11-12 14:05:46 -0800624 void cvtsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700625 void cvtsd2ss(XmmRegister dst, XmmRegister src);
Mark Mendell40741f32015-04-20 22:10:34 -0400626 void cvtsd2ss(XmmRegister dst, const Address& src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700627
Andreas Gampe851df202014-11-12 14:05:46 -0800628 void cvttss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
Roland Levillain624279f2014-12-04 11:54:28 +0000629 void cvttss2si(CpuRegister dst, XmmRegister src, bool is64bit);
Andreas Gampe851df202014-11-12 14:05:46 -0800630 void cvttsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
Roland Levillain4c0b61f2014-12-05 12:06:01 +0000631 void cvttsd2si(CpuRegister dst, XmmRegister src, bool is64bit);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700632
Aart Bik3ae3b592017-02-24 14:09:15 -0800633 void cvtdq2ps(XmmRegister dst, XmmRegister src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700634 void cvtdq2pd(XmmRegister dst, XmmRegister src);
635
636 void comiss(XmmRegister a, XmmRegister b);
Mark Mendell40741f32015-04-20 22:10:34 -0400637 void comiss(XmmRegister a, const Address& b);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700638 void comisd(XmmRegister a, XmmRegister b);
Mark Mendell40741f32015-04-20 22:10:34 -0400639 void comisd(XmmRegister a, const Address& b);
Calin Juravleddb7df22014-11-25 20:56:51 +0000640 void ucomiss(XmmRegister a, XmmRegister b);
Mark Mendell40741f32015-04-20 22:10:34 -0400641 void ucomiss(XmmRegister a, const Address& b);
Calin Juravleddb7df22014-11-25 20:56:51 +0000642 void ucomisd(XmmRegister a, XmmRegister b);
Mark Mendell40741f32015-04-20 22:10:34 -0400643 void ucomisd(XmmRegister a, const Address& b);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700644
Mark Mendellfb8d2792015-03-31 22:16:59 -0400645 void roundsd(XmmRegister dst, XmmRegister src, const Immediate& imm);
646 void roundss(XmmRegister dst, XmmRegister src, const Immediate& imm);
647
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700648 void sqrtsd(XmmRegister dst, XmmRegister src);
649 void sqrtss(XmmRegister dst, XmmRegister src);
650
651 void xorpd(XmmRegister dst, const Address& src);
652 void xorpd(XmmRegister dst, XmmRegister src);
653 void xorps(XmmRegister dst, const Address& src);
654 void xorps(XmmRegister dst, XmmRegister src);
Aart Bik68555e92017-02-13 14:28:45 -0800655 void pxor(XmmRegister dst, XmmRegister src); // no addr variant (for now)
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530656 void vpxor(XmmRegister dst, XmmRegister src1, XmmRegister src2);
657 void vxorps(XmmRegister dst, XmmRegister src1, XmmRegister src2);
658 void vxorpd(XmmRegister dst, XmmRegister src1, XmmRegister src2);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700659
660 void andpd(XmmRegister dst, const Address& src);
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800661 void andpd(XmmRegister dst, XmmRegister src);
Aart Bik68555e92017-02-13 14:28:45 -0800662 void andps(XmmRegister dst, XmmRegister src); // no addr variant (for now)
663 void pand(XmmRegister dst, XmmRegister src);
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530664 void vpand(XmmRegister dst, XmmRegister src1, XmmRegister src2);
665 void vandps(XmmRegister dst, XmmRegister src1, XmmRegister src2);
666 void vandpd(XmmRegister dst, XmmRegister src1, XmmRegister src2);
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800667
Shalini Salomi Bodapati8e5bc2d2018-10-24 11:50:56 +0530668 void andn(CpuRegister dst, CpuRegister src1, CpuRegister src2);
Aart Bik21c580b2017-03-13 11:52:07 -0700669 void andnpd(XmmRegister dst, XmmRegister src); // no addr variant (for now)
670 void andnps(XmmRegister dst, XmmRegister src);
671 void pandn(XmmRegister dst, XmmRegister src);
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530672 void vpandn(XmmRegister dst, XmmRegister src1, XmmRegister src2);
673 void vandnps(XmmRegister dst, XmmRegister src1, XmmRegister src2);
674 void vandnpd(XmmRegister dst, XmmRegister src1, XmmRegister src2);
Aart Bik21c580b2017-03-13 11:52:07 -0700675
Aart Bik68555e92017-02-13 14:28:45 -0800676 void orpd(XmmRegister dst, XmmRegister src); // no addr variant (for now)
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800677 void orps(XmmRegister dst, XmmRegister src);
Aart Bik68555e92017-02-13 14:28:45 -0800678 void por(XmmRegister dst, XmmRegister src);
Neeraj Solanki48349ad2019-08-05 23:16:56 +0530679 void vpor(XmmRegister dst, XmmRegister src1, XmmRegister src2);
680 void vorps(XmmRegister dst, XmmRegister src1, XmmRegister src2);
681 void vorpd(XmmRegister dst, XmmRegister src1, XmmRegister src2);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700682
Aart Bik67d3fd72017-03-31 15:11:53 -0700683 void pavgb(XmmRegister dst, XmmRegister src); // no addr variant (for now)
684 void pavgw(XmmRegister dst, XmmRegister src);
Aart Bik6005a872017-07-24 13:33:39 -0700685 void psadbw(XmmRegister dst, XmmRegister src);
686 void pmaddwd(XmmRegister dst, XmmRegister src);
Alex Light43f2f752019-12-04 17:48:45 +0000687 void vpmaddwd(XmmRegister dst, XmmRegister src1, XmmRegister src2);
Aart Bik6005a872017-07-24 13:33:39 -0700688 void phaddw(XmmRegister dst, XmmRegister src);
689 void phaddd(XmmRegister dst, XmmRegister src);
690 void haddps(XmmRegister dst, XmmRegister src);
691 void haddpd(XmmRegister dst, XmmRegister src);
692 void phsubw(XmmRegister dst, XmmRegister src);
693 void phsubd(XmmRegister dst, XmmRegister src);
694 void hsubps(XmmRegister dst, XmmRegister src);
695 void hsubpd(XmmRegister dst, XmmRegister src);
Aart Bik67d3fd72017-03-31 15:11:53 -0700696
Aart Bikc8e93c72017-05-10 10:49:22 -0700697 void pminsb(XmmRegister dst, XmmRegister src); // no addr variant (for now)
698 void pmaxsb(XmmRegister dst, XmmRegister src);
699 void pminsw(XmmRegister dst, XmmRegister src);
700 void pmaxsw(XmmRegister dst, XmmRegister src);
701 void pminsd(XmmRegister dst, XmmRegister src);
702 void pmaxsd(XmmRegister dst, XmmRegister src);
703
704 void pminub(XmmRegister dst, XmmRegister src); // no addr variant (for now)
705 void pmaxub(XmmRegister dst, XmmRegister src);
706 void pminuw(XmmRegister dst, XmmRegister src);
707 void pmaxuw(XmmRegister dst, XmmRegister src);
708 void pminud(XmmRegister dst, XmmRegister src);
709 void pmaxud(XmmRegister dst, XmmRegister src);
710
711 void minps(XmmRegister dst, XmmRegister src); // no addr variant (for now)
712 void maxps(XmmRegister dst, XmmRegister src);
713 void minpd(XmmRegister dst, XmmRegister src);
714 void maxpd(XmmRegister dst, XmmRegister src);
715
Aart Bik4b455332017-03-15 11:19:35 -0700716 void pcmpeqb(XmmRegister dst, XmmRegister src);
717 void pcmpeqw(XmmRegister dst, XmmRegister src);
718 void pcmpeqd(XmmRegister dst, XmmRegister src);
719 void pcmpeqq(XmmRegister dst, XmmRegister src);
720
Aart Bik8939c642017-04-03 14:09:01 -0700721 void pcmpgtb(XmmRegister dst, XmmRegister src);
722 void pcmpgtw(XmmRegister dst, XmmRegister src);
723 void pcmpgtd(XmmRegister dst, XmmRegister src);
724 void pcmpgtq(XmmRegister dst, XmmRegister src); // SSE4.2
725
Aart Bik12e06ed2017-01-31 16:11:24 -0800726 void shufpd(XmmRegister dst, XmmRegister src, const Immediate& imm);
727 void shufps(XmmRegister dst, XmmRegister src, const Immediate& imm);
Aart Bik68555e92017-02-13 14:28:45 -0800728 void pshufd(XmmRegister dst, XmmRegister src, const Immediate& imm);
Aart Bik12e06ed2017-01-31 16:11:24 -0800729
Aart Bike69d7a92017-02-17 11:48:23 -0800730 void punpcklbw(XmmRegister dst, XmmRegister src);
731 void punpcklwd(XmmRegister dst, XmmRegister src);
732 void punpckldq(XmmRegister dst, XmmRegister src);
733 void punpcklqdq(XmmRegister dst, XmmRegister src);
734
Aart Bik3332db82017-08-11 15:10:30 -0700735 void punpckhbw(XmmRegister dst, XmmRegister src);
736 void punpckhwd(XmmRegister dst, XmmRegister src);
737 void punpckhdq(XmmRegister dst, XmmRegister src);
738 void punpckhqdq(XmmRegister dst, XmmRegister src);
739
Aart Bike69d7a92017-02-17 11:48:23 -0800740 void psllw(XmmRegister reg, const Immediate& shift_count);
741 void pslld(XmmRegister reg, const Immediate& shift_count);
742 void psllq(XmmRegister reg, const Immediate& shift_count);
743
744 void psraw(XmmRegister reg, const Immediate& shift_count);
745 void psrad(XmmRegister reg, const Immediate& shift_count);
746 // no psraq
747
748 void psrlw(XmmRegister reg, const Immediate& shift_count);
749 void psrld(XmmRegister reg, const Immediate& shift_count);
750 void psrlq(XmmRegister reg, const Immediate& shift_count);
Aart Bik3332db82017-08-11 15:10:30 -0700751 void psrldq(XmmRegister reg, const Immediate& shift_count);
Aart Bike69d7a92017-02-17 11:48:23 -0800752
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700753 void flds(const Address& src);
754 void fstps(const Address& dst);
Mark Mendell24f2dfa2015-01-14 19:51:45 -0500755 void fsts(const Address& dst);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700756
757 void fldl(const Address& src);
758 void fstpl(const Address& dst);
Mark Mendell24f2dfa2015-01-14 19:51:45 -0500759 void fstl(const Address& dst);
760
761 void fstsw();
762
763 void fucompp();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700764
765 void fnstcw(const Address& dst);
766 void fldcw(const Address& src);
767
768 void fistpl(const Address& dst);
769 void fistps(const Address& dst);
770 void fildl(const Address& src);
Roland Levillain0a186012015-04-13 17:00:20 +0100771 void filds(const Address& src);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700772
773 void fincstp();
774 void ffree(const Immediate& index);
775
776 void fsin();
777 void fcos();
778 void fptan();
Mark Mendell24f2dfa2015-01-14 19:51:45 -0500779 void fprem();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700780
Ulya Trafimovichcd8286f2021-07-12 16:40:16 +0100781 void xchgb(CpuRegister dst, CpuRegister src);
782 void xchgb(CpuRegister reg, const Address& address);
783
784 void xchgw(CpuRegister dst, CpuRegister src);
785 void xchgw(CpuRegister reg, const Address& address);
786
Ian Rogersdd7624d2014-03-14 17:43:00 -0700787 void xchgl(CpuRegister dst, CpuRegister src);
788 void xchgl(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700789
Ulya Trafimovichcd8286f2021-07-12 16:40:16 +0100790 void xchgq(CpuRegister dst, CpuRegister src);
791 void xchgq(CpuRegister reg, const Address& address);
792
Ulya Trafimovich5d446a32021-07-20 15:51:48 +0100793 void xaddb(CpuRegister dst, CpuRegister src);
794 void xaddb(const Address& address, CpuRegister reg);
795
796 void xaddw(CpuRegister dst, CpuRegister src);
797 void xaddw(const Address& address, CpuRegister reg);
798
799 void xaddl(CpuRegister dst, CpuRegister src);
800 void xaddl(const Address& address, CpuRegister reg);
801
802 void xaddq(CpuRegister dst, CpuRegister src);
803 void xaddq(const Address& address, CpuRegister reg);
804
Serguei Katkov3b625932016-05-06 10:24:17 +0600805 void cmpb(const Address& address, const Immediate& imm);
Nicolas Geoffray3c049742014-09-24 18:10:46 +0100806 void cmpw(const Address& address, const Immediate& imm);
807
Ian Rogersdd7624d2014-03-14 17:43:00 -0700808 void cmpl(CpuRegister reg, const Immediate& imm);
809 void cmpl(CpuRegister reg0, CpuRegister reg1);
810 void cmpl(CpuRegister reg, const Address& address);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700811 void cmpl(const Address& address, CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700812 void cmpl(const Address& address, const Immediate& imm);
813
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700814 void cmpq(CpuRegister reg0, CpuRegister reg1);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100815 void cmpq(CpuRegister reg0, const Immediate& imm);
816 void cmpq(CpuRegister reg0, const Address& address);
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000817 void cmpq(const Address& address, const Immediate& imm);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700818
Ian Rogersdd7624d2014-03-14 17:43:00 -0700819 void testl(CpuRegister reg1, CpuRegister reg2);
Calin Juravlecd6dffe2015-01-08 17:35:35 +0000820 void testl(CpuRegister reg, const Address& address);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700821 void testl(CpuRegister reg, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700822
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000823 void testq(CpuRegister reg1, CpuRegister reg2);
Nicolas Geoffrayf12feb82014-07-17 18:32:41 +0100824 void testq(CpuRegister reg, const Address& address);
825
Vladimir Marko953437b2016-08-24 08:30:46 +0000826 void testb(const Address& address, const Immediate& imm);
827 void testl(const Address& address, const Immediate& imm);
828
Ian Rogersdd7624d2014-03-14 17:43:00 -0700829 void andl(CpuRegister dst, const Immediate& imm);
830 void andl(CpuRegister dst, CpuRegister src);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000831 void andl(CpuRegister reg, const Address& address);
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100832 void andq(CpuRegister dst, const Immediate& imm);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000833 void andq(CpuRegister dst, CpuRegister src);
Mark Mendell40741f32015-04-20 22:10:34 -0400834 void andq(CpuRegister reg, const Address& address);
Nicolas Geoffray9e5ad472020-08-26 15:27:38 +0100835 void andw(const Address& address, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700836
Ian Rogersdd7624d2014-03-14 17:43:00 -0700837 void orl(CpuRegister dst, const Immediate& imm);
838 void orl(CpuRegister dst, CpuRegister src);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000839 void orl(CpuRegister reg, const Address& address);
840 void orq(CpuRegister dst, CpuRegister src);
Mark Mendell3f6c7f62015-03-13 13:47:53 -0400841 void orq(CpuRegister dst, const Immediate& imm);
Mark Mendell40741f32015-04-20 22:10:34 -0400842 void orq(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700843
Ian Rogersdd7624d2014-03-14 17:43:00 -0700844 void xorl(CpuRegister dst, CpuRegister src);
Nicolas Geoffray9574c4b2014-11-12 13:19:37 +0000845 void xorl(CpuRegister dst, const Immediate& imm);
846 void xorl(CpuRegister reg, const Address& address);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700847 void xorq(CpuRegister dst, const Immediate& imm);
Nicolas Geoffray412f10c2014-06-19 10:00:34 +0100848 void xorq(CpuRegister dst, CpuRegister src);
Mark Mendell40741f32015-04-20 22:10:34 -0400849 void xorq(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700850
Ian Rogersdd7624d2014-03-14 17:43:00 -0700851 void addl(CpuRegister dst, CpuRegister src);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700852 void addl(CpuRegister reg, const Immediate& imm);
853 void addl(CpuRegister reg, const Address& address);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700854 void addl(const Address& address, CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700855 void addl(const Address& address, const Immediate& imm);
Nicolas Geoffrayded55942018-01-26 16:33:41 +0000856 void addw(const Address& address, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700857
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700858 void addq(CpuRegister reg, const Immediate& imm);
859 void addq(CpuRegister dst, CpuRegister src);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100860 void addq(CpuRegister dst, const Address& address);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700861
Ian Rogersdd7624d2014-03-14 17:43:00 -0700862 void subl(CpuRegister dst, CpuRegister src);
863 void subl(CpuRegister reg, const Immediate& imm);
864 void subl(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700865
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700866 void subq(CpuRegister reg, const Immediate& imm);
867 void subq(CpuRegister dst, CpuRegister src);
Nicolas Geoffray96f89a22014-07-11 10:57:49 +0100868 void subq(CpuRegister dst, const Address& address);
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700869
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700870 void cdq();
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000871 void cqo();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700872
Ian Rogersdd7624d2014-03-14 17:43:00 -0700873 void idivl(CpuRegister reg);
Calin Juravled6fb6cf2014-11-11 19:07:44 +0000874 void idivq(CpuRegister reg);
Vladimir Markobe7fe3b2020-07-09 10:58:12 +0100875 void divl(CpuRegister reg);
876 void divq(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700877
Ian Rogersdd7624d2014-03-14 17:43:00 -0700878 void imull(CpuRegister dst, CpuRegister src);
879 void imull(CpuRegister reg, const Immediate& imm);
Mark Mendell4a2aa4a2015-07-27 16:13:10 -0400880 void imull(CpuRegister dst, CpuRegister src, const Immediate& imm);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700881 void imull(CpuRegister reg, const Address& address);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700882
Guillaume Sanchez0f88e872015-03-30 17:55:45 +0100883 void imulq(CpuRegister src);
Calin Juravle34bacdf2014-10-07 20:23:36 +0100884 void imulq(CpuRegister dst, CpuRegister src);
885 void imulq(CpuRegister reg, const Immediate& imm);
886 void imulq(CpuRegister reg, const Address& address);
Mark Mendell3f6c7f62015-03-13 13:47:53 -0400887 void imulq(CpuRegister dst, CpuRegister reg, const Immediate& imm);
Calin Juravle34bacdf2014-10-07 20:23:36 +0100888
Ian Rogersdd7624d2014-03-14 17:43:00 -0700889 void imull(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700890 void imull(const Address& address);
891
Ian Rogersdd7624d2014-03-14 17:43:00 -0700892 void mull(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700893 void mull(const Address& address);
894
Ian Rogersdd7624d2014-03-14 17:43:00 -0700895 void shll(CpuRegister reg, const Immediate& imm);
896 void shll(CpuRegister operand, CpuRegister shifter);
897 void shrl(CpuRegister reg, const Immediate& imm);
898 void shrl(CpuRegister operand, CpuRegister shifter);
899 void sarl(CpuRegister reg, const Immediate& imm);
900 void sarl(CpuRegister operand, CpuRegister shifter);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700901
Calin Juravle9aec02f2014-11-18 23:06:35 +0000902 void shlq(CpuRegister reg, const Immediate& imm);
903 void shlq(CpuRegister operand, CpuRegister shifter);
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +0100904 void shrq(CpuRegister reg, const Immediate& imm);
Calin Juravle9aec02f2014-11-18 23:06:35 +0000905 void shrq(CpuRegister operand, CpuRegister shifter);
906 void sarq(CpuRegister reg, const Immediate& imm);
907 void sarq(CpuRegister operand, CpuRegister shifter);
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +0100908
Ian Rogersdd7624d2014-03-14 17:43:00 -0700909 void negl(CpuRegister reg);
Roland Levillain2e07b4f2014-10-23 18:12:09 +0100910 void negq(CpuRegister reg);
Roland Levillain70566432014-10-24 16:20:17 +0100911
Ian Rogersdd7624d2014-03-14 17:43:00 -0700912 void notl(CpuRegister reg);
Roland Levillain70566432014-10-24 16:20:17 +0100913 void notq(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700914
915 void enter(const Immediate& imm);
916 void leave();
917
918 void ret();
919 void ret(const Immediate& imm);
920
921 void nop();
922 void int3();
923 void hlt();
924
925 void j(Condition condition, Label* label);
Mark Mendell73f455e2015-08-21 09:30:05 -0400926 void j(Condition condition, NearLabel* label);
927 void jrcxz(NearLabel* label);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700928
Ian Rogersdd7624d2014-03-14 17:43:00 -0700929 void jmp(CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700930 void jmp(const Address& address);
931 void jmp(Label* label);
Mark Mendell73f455e2015-08-21 09:30:05 -0400932 void jmp(NearLabel* label);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700933
934 X86_64Assembler* lock();
Ulya Trafimovich5b8eb162021-06-28 12:38:20 +0100935 void cmpxchgb(const Address& address, CpuRegister reg);
936 void cmpxchgw(const Address& address, CpuRegister reg);
Ian Rogersdd7624d2014-03-14 17:43:00 -0700937 void cmpxchgl(const Address& address, CpuRegister reg);
Mark Mendell58d25fd2015-04-03 14:52:31 -0400938 void cmpxchgq(const Address& address, CpuRegister reg);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700939
940 void mfence();
941
942 X86_64Assembler* gs();
943
Andreas Gampe5a4fa822014-03-31 16:50:12 -0700944 void setcc(Condition condition, CpuRegister dst);
945
Andreas Gampe71fb52f2014-12-29 17:43:08 -0800946 void bswapl(CpuRegister dst);
947 void bswapq(CpuRegister dst);
948
Mark Mendellbcee0922015-09-15 21:45:01 -0400949 void bsfl(CpuRegister dst, CpuRegister src);
950 void bsfl(CpuRegister dst, const Address& src);
951 void bsfq(CpuRegister dst, CpuRegister src);
952 void bsfq(CpuRegister dst, const Address& src);
953
Shalini Salomi Bodapati8e5bc2d2018-10-24 11:50:56 +0530954 void blsi(CpuRegister dst, CpuRegister src); // no addr variant (for now)
955 void blsmsk(CpuRegister dst, CpuRegister src); // no addr variant (for now)
956 void blsr(CpuRegister dst, CpuRegister src); // no addr variant (for now)
957
Mark Mendell8ae3ffb2015-08-12 21:16:41 -0400958 void bsrl(CpuRegister dst, CpuRegister src);
959 void bsrl(CpuRegister dst, const Address& src);
960 void bsrq(CpuRegister dst, CpuRegister src);
961 void bsrq(CpuRegister dst, const Address& src);
962
Aart Bik3f67e692016-01-15 14:35:12 -0800963 void popcntl(CpuRegister dst, CpuRegister src);
964 void popcntl(CpuRegister dst, const Address& src);
965 void popcntq(CpuRegister dst, CpuRegister src);
966 void popcntq(CpuRegister dst, const Address& src);
967
Mark Mendellbcee0922015-09-15 21:45:01 -0400968 void rorl(CpuRegister reg, const Immediate& imm);
969 void rorl(CpuRegister operand, CpuRegister shifter);
970 void roll(CpuRegister reg, const Immediate& imm);
971 void roll(CpuRegister operand, CpuRegister shifter);
972
973 void rorq(CpuRegister reg, const Immediate& imm);
974 void rorq(CpuRegister operand, CpuRegister shifter);
975 void rolq(CpuRegister reg, const Immediate& imm);
976 void rolq(CpuRegister operand, CpuRegister shifter);
977
jessicahandojob03d6402016-09-07 12:16:53 -0700978 void repne_scasb();
Andreas Gampe21030dd2015-05-07 14:46:15 -0700979 void repne_scasw();
agicsaki71311f82015-07-27 11:34:13 -0700980 void repe_cmpsw();
agicsaki970abfb2015-07-31 10:31:14 -0700981 void repe_cmpsl();
agicsaki3fd0e6a2015-08-03 20:14:29 -0700982 void repe_cmpsq();
Mark Mendellb9c4bbe2015-07-01 14:26:52 -0400983 void rep_movsw();
Shalini Salomi Bodapati927a9962022-02-11 18:01:22 +0530984 void rep_movsb();
985 void rep_movsl();
Andreas Gampe21030dd2015-05-07 14:46:15 -0700986
Ulya Trafimovich06ed7442021-11-19 12:22:49 +0000987 void ud2();
988
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700989 //
990 // Macros for High-level operations.
991 //
992
Ian Rogersdd7624d2014-03-14 17:43:00 -0700993 void AddImmediate(CpuRegister reg, const Immediate& imm);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +0700994
995 void LoadDoubleConstant(XmmRegister dst, double value);
996
Ulya Trafimovich5b8eb162021-06-28 12:38:20 +0100997 void LockCmpxchgb(const Address& address, CpuRegister reg) {
998 lock()->cmpxchgb(address, reg);
999 }
1000
1001 void LockCmpxchgw(const Address& address, CpuRegister reg) {
1002 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1003 // We make sure that the operand size override bytecode is emited before the lock bytecode.
1004 // We test against clang which enforces this bytecode order.
1005 EmitOperandSizeOverride();
1006 EmitUint8(0xF0);
1007 EmitOptionalRex32(reg, address);
1008 EmitUint8(0x0F);
1009 EmitUint8(0xB1);
1010 EmitOperand(reg.LowBits(), address);
1011 }
1012
Ian Rogersdd7624d2014-03-14 17:43:00 -07001013 void LockCmpxchgl(const Address& address, CpuRegister reg) {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001014 lock()->cmpxchgl(address, reg);
1015 }
1016
Mark Mendell58d25fd2015-04-03 14:52:31 -04001017 void LockCmpxchgq(const Address& address, CpuRegister reg) {
1018 lock()->cmpxchgq(address, reg);
1019 }
1020
Ulya Trafimovich244f22b2021-07-20 16:56:30 +01001021 void LockXaddb(const Address& address, CpuRegister reg) {
1022 lock()->xaddb(address, reg);
1023 }
1024
1025 void LockXaddw(const Address& address, CpuRegister reg) {
1026 AssemblerBuffer::EnsureCapacity ensured(&buffer_);
1027 // We make sure that the operand size override bytecode is emited before the lock bytecode.
1028 // We test against clang which enforces this bytecode order.
1029 EmitOperandSizeOverride();
1030 EmitUint8(0xF0);
1031 EmitOptionalRex32(reg, address);
1032 EmitUint8(0x0F);
1033 EmitUint8(0xC1);
1034 EmitOperand(reg.LowBits(), address);
1035 }
1036
1037 void LockXaddl(const Address& address, CpuRegister reg) {
1038 lock()->xaddl(address, reg);
1039 }
1040
1041 void LockXaddq(const Address& address, CpuRegister reg) {
1042 lock()->xaddq(address, reg);
1043 }
1044
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001045 //
1046 // Misc. functionality
1047 //
1048 int PreferredLoopAlignment() { return 16; }
1049 void Align(int alignment, int offset);
Roland Levillainbbc6e7e2018-08-24 16:58:47 +01001050 void Bind(Label* label) override;
1051 void Jump(Label* label) override {
Andreas Gampe85b62f22015-09-09 13:15:38 -07001052 jmp(label);
1053 }
Mark Mendell73f455e2015-08-21 09:30:05 -04001054 void Bind(NearLabel* label);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001055
Mark Mendell39dcf552015-04-09 20:42:42 -04001056 // Add a double to the constant area, returning the offset into
1057 // the constant area where the literal resides.
Mark Mendell9c86b482015-09-18 13:36:07 -04001058 size_t AddDouble(double v) { return constant_area_.AddDouble(v); }
Mark Mendellf55c3e02015-03-26 21:07:46 -04001059
Mark Mendell39dcf552015-04-09 20:42:42 -04001060 // Add a float to the constant area, returning the offset into
1061 // the constant area where the literal resides.
Mark Mendell9c86b482015-09-18 13:36:07 -04001062 size_t AddFloat(float v) { return constant_area_.AddFloat(v); }
Mark Mendellf55c3e02015-03-26 21:07:46 -04001063
Mark Mendell39dcf552015-04-09 20:42:42 -04001064 // Add an int32_t to the constant area, returning the offset into
1065 // the constant area where the literal resides.
Mark Mendell9c86b482015-09-18 13:36:07 -04001066 size_t AddInt32(int32_t v) {
1067 return constant_area_.AddInt32(v);
1068 }
1069
1070 // Add an int32_t to the end of the constant area, returning the offset into
1071 // the constant area where the literal resides.
1072 size_t AppendInt32(int32_t v) {
1073 return constant_area_.AppendInt32(v);
1074 }
Mark Mendellf55c3e02015-03-26 21:07:46 -04001075
Mark Mendell39dcf552015-04-09 20:42:42 -04001076 // Add an int64_t to the constant area, returning the offset into
1077 // the constant area where the literal resides.
Mark Mendell9c86b482015-09-18 13:36:07 -04001078 size_t AddInt64(int64_t v) { return constant_area_.AddInt64(v); }
Mark Mendellf55c3e02015-03-26 21:07:46 -04001079
Mark Mendell39dcf552015-04-09 20:42:42 -04001080 // Add the contents of the constant area to the assembler buffer.
Mark Mendellf55c3e02015-03-26 21:07:46 -04001081 void AddConstantArea();
1082
Mark Mendell39dcf552015-04-09 20:42:42 -04001083 // Is the constant area empty? Return true if there are no literals in the constant area.
Mark Mendellf55c3e02015-03-26 21:07:46 -04001084 bool IsConstantAreaEmpty() const { return constant_area_.GetSize() == 0; }
1085
Mark Mendell9c86b482015-09-18 13:36:07 -04001086 // Return the current size of the constant area.
1087 size_t ConstantAreaSize() const { return constant_area_.GetSize(); }
1088
Roland Levillain4d027112015-07-01 15:41:14 +01001089 //
1090 // Heap poisoning.
1091 //
1092
1093 // Poison a heap reference contained in `reg`.
1094 void PoisonHeapReference(CpuRegister reg) { negl(reg); }
1095 // Unpoison a heap reference contained in `reg`.
1096 void UnpoisonHeapReference(CpuRegister reg) { negl(reg); }
Roland Levillain0b671c02016-08-19 12:02:34 +01001097 // Poison a heap reference contained in `reg` if heap poisoning is enabled.
1098 void MaybePoisonHeapReference(CpuRegister reg) {
1099 if (kPoisonHeapReferences) {
1100 PoisonHeapReference(reg);
1101 }
1102 }
Roland Levillain4d027112015-07-01 15:41:14 +01001103 // Unpoison a heap reference contained in `reg` if heap poisoning is enabled.
1104 void MaybeUnpoisonHeapReference(CpuRegister reg) {
1105 if (kPoisonHeapReferences) {
1106 UnpoisonHeapReference(reg);
1107 }
1108 }
1109
jaishank20d1c942019-03-08 15:08:17 +05301110 bool CpuHasAVXorAVX2FeatureFlag();
1111
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001112 private:
Ian Rogersdd7624d2014-03-14 17:43:00 -07001113 void EmitUint8(uint8_t value);
1114 void EmitInt32(int32_t value);
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001115 void EmitInt64(int64_t value);
Ian Rogersdd7624d2014-03-14 17:43:00 -07001116 void EmitRegisterOperand(uint8_t rm, uint8_t reg);
1117 void EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg);
1118 void EmitFixup(AssemblerFixup* fixup);
1119 void EmitOperandSizeOverride();
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001120
Ian Rogersdd7624d2014-03-14 17:43:00 -07001121 void EmitOperand(uint8_t rm, const Operand& operand);
Nicolas Geoffrayded55942018-01-26 16:33:41 +00001122 void EmitImmediate(const Immediate& imm, bool is_16_op = false);
1123 void EmitComplex(
1124 uint8_t rm, const Operand& operand, const Immediate& immediate, bool is_16_op = false);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001125 void EmitLabel(Label* label, int instruction_size);
1126 void EmitLabelLink(Label* label);
Mark Mendell73f455e2015-08-21 09:30:05 -04001127 void EmitLabelLink(NearLabel* label);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001128
Nicolas Geoffray1a43dd72014-07-17 15:15:34 +01001129 void EmitGenericShift(bool wide, int rm, CpuRegister reg, const Immediate& imm);
Calin Juravle9aec02f2014-11-18 23:06:35 +00001130 void EmitGenericShift(bool wide, int rm, CpuRegister operand, CpuRegister shifter);
Ian Rogersdd7624d2014-03-14 17:43:00 -07001131
1132 // If any input is not false, output the necessary rex prefix.
1133 void EmitOptionalRex(bool force, bool w, bool r, bool x, bool b);
1134
1135 // Emit a rex prefix byte if necessary for reg. ie if reg is a register in the range R8 to R15.
1136 void EmitOptionalRex32(CpuRegister reg);
1137 void EmitOptionalRex32(CpuRegister dst, CpuRegister src);
1138 void EmitOptionalRex32(XmmRegister dst, XmmRegister src);
1139 void EmitOptionalRex32(CpuRegister dst, XmmRegister src);
1140 void EmitOptionalRex32(XmmRegister dst, CpuRegister src);
1141 void EmitOptionalRex32(const Operand& operand);
1142 void EmitOptionalRex32(CpuRegister dst, const Operand& operand);
1143 void EmitOptionalRex32(XmmRegister dst, const Operand& operand);
1144
1145 // Emit a REX.W prefix plus necessary register bit encodings.
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001146 void EmitRex64();
Ian Rogersdd7624d2014-03-14 17:43:00 -07001147 void EmitRex64(CpuRegister reg);
Calin Juravled6fb6cf2014-11-11 19:07:44 +00001148 void EmitRex64(const Operand& operand);
Ian Rogersdd7624d2014-03-14 17:43:00 -07001149 void EmitRex64(CpuRegister dst, CpuRegister src);
1150 void EmitRex64(CpuRegister dst, const Operand& operand);
Mark Mendell40741f32015-04-20 22:10:34 -04001151 void EmitRex64(XmmRegister dst, const Operand& operand);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001152 void EmitRex64(XmmRegister dst, CpuRegister src);
Roland Levillain624279f2014-12-04 11:54:28 +00001153 void EmitRex64(CpuRegister dst, XmmRegister src);
Ian Rogersdd7624d2014-03-14 17:43:00 -07001154
1155 // Emit a REX prefix to normalize byte registers plus necessary register bit encodings.
Ulya Trafimovichcd8286f2021-07-12 16:40:16 +01001156 // `normalize_both` parameter controls if the REX prefix is checked only for the `src` register
1157 // (which is the case for instructions like `movzxb rax, bpl`), or for both `src` and `dst`
1158 // registers (which is the case of instructions like `xchg bpl, al`). By default only `src` is
1159 // used to decide if REX is needed.
1160 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst,
1161 CpuRegister src,
1162 bool normalize_both = false);
Ian Rogersdd7624d2014-03-14 17:43:00 -07001163 void EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand);
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001164
jaishank20d1c942019-03-08 15:08:17 +05301165 uint8_t EmitVexPrefixByteZero(bool is_twobyte_form);
1166 uint8_t EmitVexPrefixByteOne(bool R, bool X, bool B, int SET_VEX_M);
1167 uint8_t EmitVexPrefixByteOne(bool R,
1168 X86_64ManagedRegister operand,
1169 int SET_VEX_L,
1170 int SET_VEX_PP);
1171 uint8_t EmitVexPrefixByteTwo(bool W,
1172 X86_64ManagedRegister operand,
1173 int SET_VEX_L,
1174 int SET_VEX_PP);
1175 uint8_t EmitVexPrefixByteTwo(bool W,
1176 int SET_VEX_L,
1177 int SET_VEX_PP);
Ulya Trafimovichcd8286f2021-07-12 16:40:16 +01001178
1179 // Helper function to emit a shorter variant of XCHG if at least one operand is RAX/EAX/AX.
1180 bool try_xchg_rax(CpuRegister dst,
1181 CpuRegister src,
1182 void (X86_64Assembler::*prefix_fn)(CpuRegister));
1183
Mark Mendellf55c3e02015-03-26 21:07:46 -04001184 ConstantArea constant_area_;
jaishank20d1c942019-03-08 15:08:17 +05301185 bool has_AVX_; // x86 256bit SIMD AVX.
1186 bool has_AVX2_; // x86 256bit SIMD AVX 2.0.
Mark Mendellf55c3e02015-03-26 21:07:46 -04001187
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001188 DISALLOW_COPY_AND_ASSIGN(X86_64Assembler);
1189};
1190
1191inline void X86_64Assembler::EmitUint8(uint8_t value) {
1192 buffer_.Emit<uint8_t>(value);
1193}
1194
1195inline void X86_64Assembler::EmitInt32(int32_t value) {
1196 buffer_.Emit<int32_t>(value);
1197}
1198
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001199inline void X86_64Assembler::EmitInt64(int64_t value) {
Roland Levillain55dcfb52014-10-24 18:09:09 +01001200 // Write this 64-bit value as two 32-bit words for alignment reasons
1201 // (this is essentially when running on ARM, which does not allow
1202 // 64-bit unaligned accesses). We assume little-endianness here.
1203 EmitInt32(Low32Bits(value));
1204 EmitInt32(High32Bits(value));
Andreas Gampe5a4fa822014-03-31 16:50:12 -07001205}
1206
Ian Rogersdd7624d2014-03-14 17:43:00 -07001207inline void X86_64Assembler::EmitRegisterOperand(uint8_t rm, uint8_t reg) {
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001208 CHECK_GE(rm, 0);
1209 CHECK_LT(rm, 8);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +01001210 buffer_.Emit<uint8_t>((0xC0 | (reg & 7)) + (rm << 3));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001211}
1212
Ian Rogersdd7624d2014-03-14 17:43:00 -07001213inline void X86_64Assembler::EmitXmmRegisterOperand(uint8_t rm, XmmRegister reg) {
1214 EmitRegisterOperand(rm, static_cast<uint8_t>(reg.AsFloatRegister()));
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001215}
1216
1217inline void X86_64Assembler::EmitFixup(AssemblerFixup* fixup) {
1218 buffer_.EmitFixup(fixup);
1219}
1220
1221inline void X86_64Assembler::EmitOperandSizeOverride() {
1222 EmitUint8(0x66);
1223}
1224
Dmitry Petrochenkofca82202014-03-21 11:21:37 +07001225} // namespace x86_64
1226} // namespace art
1227
1228#endif // ART_COMPILER_UTILS_X86_64_ASSEMBLER_X86_64_H_