blob: e48f3586d3ea3a40f2d2e94618cbf5d68934bd0d [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// - Neither the name of Sun Microsystems or the names of contributors may
16// be used to endorse or promote products derived from this software without
17// specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// The original source code covered by the above license above has been
32// modified significantly by Google Inc.
Ben Murdoch3ef787d2012-04-12 10:51:47 +010033// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +000034
35// A lightweight X64 Assembler.
36
37#ifndef V8_X64_ASSEMBLER_X64_H_
38#define V8_X64_ASSEMBLER_X64_H_
39
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040#include <deque>
41
42#include "src/assembler.h"
Steve Blockd0582a62009-12-15 09:54:21 +000043
Steve Blocka7e24c12009-10-30 11:49:00 +000044namespace v8 {
45namespace internal {
46
47// Utility functions
48
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049#define GENERAL_REGISTERS(V) \
50 V(rax) \
51 V(rcx) \
52 V(rdx) \
53 V(rbx) \
54 V(rsp) \
55 V(rbp) \
56 V(rsi) \
57 V(rdi) \
58 V(r8) \
59 V(r9) \
60 V(r10) \
61 V(r11) \
62 V(r12) \
63 V(r13) \
64 V(r14) \
65 V(r15)
66
67#define ALLOCATABLE_GENERAL_REGISTERS(V) \
68 V(rax) \
69 V(rbx) \
70 V(rdx) \
71 V(rcx) \
72 V(rsi) \
73 V(rdi) \
74 V(r8) \
75 V(r9) \
76 V(r11) \
77 V(r12) \
78 V(r14) \
79 V(r15)
80
81
Steve Blocka7e24c12009-10-30 11:49:00 +000082// CPU Registers.
83//
84// 1) We would prefer to use an enum, but enum values are assignment-
85// compatible with int, which has caused code-generation bugs.
86//
87// 2) We would prefer to use a class instead of a struct but we don't like
88// the register initialization to depend on the particular initialization
89// order (which appears to be different on OS X, Linux, and Windows for the
90// installed versions of C++ we tried). Using a struct permits C-style
91// "initialization". Also, the Register objects cannot be const as this
92// forces initialization stubs in MSVC, making us dependent on initialization
93// order.
94//
95// 3) By not using an enum, we are possibly preventing the compiler from
96// doing certain constant folds, which may significantly reduce the
97// code generated for some assembly instructions (because they boil down
98// to a few constants). If this is a problem, we could change the code
99// such that we use an enum in optimized mode, and the struct in debug
100// mode. This way we get the compile-time error checking in debug mode
101// and best performance in optimized code.
102//
Steve Blocka7e24c12009-10-30 11:49:00 +0000103struct Register {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104 enum Code {
105#define REGISTER_CODE(R) kCode_##R,
106 GENERAL_REGISTERS(REGISTER_CODE)
107#undef REGISTER_CODE
108 kAfterLast,
109 kCode_no_reg = -1
110 };
Ben Murdochb0fe1622011-05-05 13:52:32 +0100111
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 static const int kNumRegisters = Code::kAfterLast;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100113
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000114 static Register from_code(int code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 DCHECK(code >= 0);
116 DCHECK(code < kNumRegisters);
117 Register r = {code};
Steve Blocka7e24c12009-10-30 11:49:00 +0000118 return r;
119 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120 const char* ToString();
121 bool IsAllocatable() const;
122 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
123 bool is(Register reg) const { return reg_code == reg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100124 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 return reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000127 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100128 int bit() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 DCHECK(is_valid());
130 return 1 << reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000131 }
132
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 bool is_byte_register() const { return reg_code <= 3; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000134 // Return the high bit of the register code as a 0 or 1. Used often
135 // when constructing the REX prefix byte.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136 int high_bit() const { return reg_code >> 3; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 // Return the 3 low bits of the register code. Used when encoding registers
138 // in modR/M, SIB, and opcode bytes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 int low_bits() const { return reg_code & 0x7; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000140
Andrei Popescu31002712010-02-23 13:46:05 +0000141 // Unfortunately we can't make this private in a struct when initializing
142 // by assignment.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 int reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000144};
145
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100146
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
148GENERAL_REGISTERS(DECLARE_REGISTER)
149#undef DECLARE_REGISTER
150const Register no_reg = {Register::kCode_no_reg};
151
Steve Blocka7e24c12009-10-30 11:49:00 +0000152
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153#ifdef _WIN64
154 // Windows calling convention
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155const Register arg_reg_1 = {Register::kCode_rcx};
156const Register arg_reg_2 = {Register::kCode_rdx};
157const Register arg_reg_3 = {Register::kCode_r8};
158const Register arg_reg_4 = {Register::kCode_r9};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000159#else
160 // AMD64 calling convention
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161const Register arg_reg_1 = {Register::kCode_rdi};
162const Register arg_reg_2 = {Register::kCode_rsi};
163const Register arg_reg_3 = {Register::kCode_rdx};
164const Register arg_reg_4 = {Register::kCode_rcx};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165#endif // _WIN64
Steve Blocka7e24c12009-10-30 11:49:00 +0000166
Ben Murdochb0fe1622011-05-05 13:52:32 +0100167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168#define DOUBLE_REGISTERS(V) \
169 V(xmm0) \
170 V(xmm1) \
171 V(xmm2) \
172 V(xmm3) \
173 V(xmm4) \
174 V(xmm5) \
175 V(xmm6) \
176 V(xmm7) \
177 V(xmm8) \
178 V(xmm9) \
179 V(xmm10) \
180 V(xmm11) \
181 V(xmm12) \
182 V(xmm13) \
183 V(xmm14) \
184 V(xmm15)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
187 V(xmm1) \
188 V(xmm2) \
189 V(xmm3) \
190 V(xmm4) \
191 V(xmm5) \
192 V(xmm6) \
193 V(xmm7) \
194 V(xmm8) \
195 V(xmm9) \
196 V(xmm10) \
197 V(xmm11) \
198 V(xmm12) \
199 V(xmm13) \
200 V(xmm14) \
201 V(xmm15)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203
204struct DoubleRegister {
205 enum Code {
206#define REGISTER_CODE(R) kCode_##R,
207 DOUBLE_REGISTERS(REGISTER_CODE)
208#undef REGISTER_CODE
209 kAfterLast,
210 kCode_no_reg = -1
211 };
212
213 static const int kMaxNumRegisters = Code::kAfterLast;
214
215 static DoubleRegister from_code(int code) {
216 DoubleRegister result = {code};
Ben Murdochb8e0da22011-05-16 14:20:40 +0100217 return result;
218 }
219
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 const char* ToString();
221 bool IsAllocatable() const;
222 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
223 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100224 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000226 return reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000227 }
228
229 // Return the high bit of the register code as a 0 or 1. Used often
230 // when constructing the REX prefix byte.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 int high_bit() const { return reg_code >> 3; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000232 // Return the 3 low bits of the register code. Used when encoding registers
233 // in modR/M, SIB, and opcode bytes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 int low_bits() const { return reg_code & 0x7; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000235
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 // Unfortunately we can't make this private in a struct when initializing
237 // by assignment.
238 int reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000239};
240
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241
242#define DECLARE_REGISTER(R) \
243 const DoubleRegister R = {DoubleRegister::kCode_##R};
244DOUBLE_REGISTERS(DECLARE_REGISTER)
245#undef DECLARE_REGISTER
246const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
Steve Blocka7e24c12009-10-30 11:49:00 +0000247
Ben Murdochb0fe1622011-05-05 13:52:32 +0100248
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249typedef DoubleRegister XMMRegister;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100250
Ben Murdoch097c5b22016-05-18 11:27:45 +0100251typedef DoubleRegister Simd128Register;
252
Steve Blocka7e24c12009-10-30 11:49:00 +0000253enum Condition {
254 // any value < 0 is considered no_condition
255 no_condition = -1,
256
257 overflow = 0,
258 no_overflow = 1,
259 below = 2,
260 above_equal = 3,
261 equal = 4,
262 not_equal = 5,
263 below_equal = 6,
264 above = 7,
265 negative = 8,
266 positive = 9,
267 parity_even = 10,
268 parity_odd = 11,
269 less = 12,
270 greater_equal = 13,
271 less_equal = 14,
272 greater = 15,
273
Steve Block3ce2e202009-11-05 08:53:23 +0000274 // Fake conditions that are handled by the
275 // opcodes using them.
276 always = 16,
277 never = 17,
Steve Blocka7e24c12009-10-30 11:49:00 +0000278 // aliases
279 carry = below,
280 not_carry = above_equal,
281 zero = equal,
282 not_zero = not_equal,
283 sign = negative,
Steve Block3ce2e202009-11-05 08:53:23 +0000284 not_sign = positive,
285 last_condition = greater
Steve Blocka7e24c12009-10-30 11:49:00 +0000286};
287
288
289// Returns the equivalent of !cc.
290// Negation of the default no_condition (-1) results in a non-default
291// no_condition value (-2). As long as tests for no_condition check
292// for condition < 0, this will work as expected.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100293inline Condition NegateCondition(Condition cc) {
294 return static_cast<Condition>(cc ^ 1);
295}
296
Steve Blocka7e24c12009-10-30 11:49:00 +0000297
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298// Commute a condition such that {a cond b == b cond' a}.
299inline Condition CommuteCondition(Condition cc) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000300 switch (cc) {
301 case below:
302 return above;
303 case above:
304 return below;
305 case above_equal:
306 return below_equal;
307 case below_equal:
308 return above_equal;
309 case less:
310 return greater;
311 case greater:
312 return less;
313 case greater_equal:
314 return less_equal;
315 case less_equal:
316 return greater_equal;
317 default:
318 return cc;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000319 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000320}
321
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100322
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323enum RoundingMode {
324 kRoundToNearest = 0x0,
325 kRoundDown = 0x1,
326 kRoundUp = 0x2,
327 kRoundToZero = 0x3
328};
329
330
Steve Blocka7e24c12009-10-30 11:49:00 +0000331// -----------------------------------------------------------------------------
332// Machine instruction Immediates
333
334class Immediate BASE_EMBEDDED {
335 public:
336 explicit Immediate(int32_t value) : value_(value) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337 explicit Immediate(Smi* value) {
338 DCHECK(SmiValuesAre31Bits()); // Only available for 31-bit SMI.
339 value_ = static_cast<int32_t>(reinterpret_cast<intptr_t>(value));
340 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000341
342 private:
343 int32_t value_;
344
345 friend class Assembler;
346};
347
348
349// -----------------------------------------------------------------------------
350// Machine instruction Operands
351
352enum ScaleFactor {
353 times_1 = 0,
354 times_2 = 1,
355 times_4 = 2,
356 times_8 = 3,
357 times_int_size = times_4,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358 times_pointer_size = (kPointerSize == 8) ? times_8 : times_4
Steve Blocka7e24c12009-10-30 11:49:00 +0000359};
360
361
362class Operand BASE_EMBEDDED {
363 public:
364 // [base + disp/r]
365 Operand(Register base, int32_t disp);
366
367 // [base + index*scale + disp/r]
368 Operand(Register base,
369 Register index,
370 ScaleFactor scale,
371 int32_t disp);
372
373 // [index*scale + disp/r]
374 Operand(Register index,
375 ScaleFactor scale,
376 int32_t disp);
377
Leon Clarkef7060e22010-06-03 12:02:55 +0100378 // Offset from existing memory operand.
379 // Offset is added to existing displacement as 32-bit signed values and
380 // this must not overflow.
381 Operand(const Operand& base, int32_t offset);
382
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 // [rip + disp/r]
384 explicit Operand(Label* label);
385
Steve Block1e0659c2011-05-24 12:43:12 +0100386 // Checks whether either base or index register is the given register.
387 // Does not check the "reg" part of the Operand.
388 bool AddressUsesRegister(Register reg) const;
389
Steve Block44f0eee2011-05-26 01:26:41 +0100390 // Queries related to the size of the generated instruction.
391 // Whether the generated instruction will have a REX prefix.
392 bool requires_rex() const { return rex_ != 0; }
393 // Size of the ModR/M, SIB and displacement parts of the generated
394 // instruction.
395 int operand_size() const { return len_; }
396
Steve Blocka7e24c12009-10-30 11:49:00 +0000397 private:
398 byte rex_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 byte buf_[9];
Steve Block1e0659c2011-05-24 12:43:12 +0100400 // The number of bytes of buf_ in use.
401 byte len_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000402
403 // Set the ModR/M byte without an encoded 'reg' register. The
404 // register is encoded later as part of the emit_operand operation.
405 // set_modrm can be called before or after set_sib and set_disp*.
406 inline void set_modrm(int mod, Register rm);
407
408 // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
409 inline void set_sib(ScaleFactor scale, Register index, Register base);
410
411 // Adds operand displacement fields (offsets added to the memory address).
412 // Needs to be called after set_sib, not before it.
413 inline void set_disp8(int disp);
414 inline void set_disp32(int disp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415 inline void set_disp64(int64_t disp); // for labels.
Steve Blocka7e24c12009-10-30 11:49:00 +0000416
417 friend class Assembler;
418};
419
420
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000421#define ASSEMBLER_INSTRUCTION_LIST(V) \
422 V(add) \
423 V(and) \
424 V(cmp) \
425 V(dec) \
426 V(idiv) \
427 V(div) \
428 V(imul) \
429 V(inc) \
430 V(lea) \
431 V(mov) \
432 V(movzxb) \
433 V(movzxw) \
434 V(neg) \
435 V(not) \
436 V(or) \
437 V(repmovs) \
438 V(sbb) \
439 V(sub) \
440 V(test) \
441 V(xchg) \
442 V(xor)
Steve Block44f0eee2011-05-26 01:26:41 +0100443
Ben Murdoch8b112d22011-06-08 16:22:53 +0100444
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000445// Shift instructions on operands/registers with kPointerSize, kInt32Size and
446// kInt64Size.
447#define SHIFT_INSTRUCTION_LIST(V) \
448 V(rol, 0x0) \
449 V(ror, 0x1) \
450 V(rcl, 0x2) \
451 V(rcr, 0x3) \
452 V(shl, 0x4) \
453 V(shr, 0x5) \
454 V(sar, 0x7) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000455
456
Steve Block44f0eee2011-05-26 01:26:41 +0100457class Assembler : public AssemblerBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 private:
459 // We check before assembling an instruction that there is sufficient
460 // space to write an instruction and its relocation information.
461 // The relocation writer's position must be kGap bytes above the end of
462 // the generated instructions. This leaves enough space for the
463 // longest possible x64 instruction, 15 bytes, and the longest possible
464 // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
465 // (There is a 15 byte limit on x64 instruction length that rules out some
466 // otherwise valid instructions.)
467 // This allows for a single, fast space check per instruction.
468 static const int kGap = 32;
469
470 public:
471 // Create an assembler. Instructions and relocation information are emitted
472 // into a buffer, with the instructions starting from the beginning and the
473 // relocation information starting from the end of the buffer. See CodeDesc
474 // for a detailed comment on the layout (globals.h).
475 //
476 // If the provided buffer is NULL, the assembler allocates and grows its own
477 // buffer, and buffer_size determines the initial buffer size. The buffer is
478 // owned by the assembler and deallocated upon destruction of the assembler.
479 //
480 // If the provided buffer is not NULL, the assembler uses the provided buffer
481 // for code generation and assumes its size to be buffer_size. If the buffer
482 // is too small, a fatal error occurs. No deallocation of the buffer is done
483 // upon destruction of the assembler.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100484 Assembler(Isolate* isolate, void* buffer, int buffer_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000485 virtual ~Assembler() { }
Steve Block44f0eee2011-05-26 01:26:41 +0100486
Steve Blocka7e24c12009-10-30 11:49:00 +0000487 // GetCode emits any pending (non-emitted) code and fills the descriptor
488 // desc. GetCode() is idempotent; it returns the same result if no other
489 // Assembler functions are invoked in between GetCode() calls.
490 void GetCode(CodeDesc* desc);
491
Steve Block3ce2e202009-11-05 08:53:23 +0000492 // Read/Modify the code target in the relative branch/call instruction at pc.
493 // On the x64 architecture, we use relative jumps with a 32-bit displacement
494 // to jump to other Code objects in the Code space in the heap.
495 // Jumps to C functions are done indirectly through a 64-bit register holding
496 // the absolute address of the target.
497 // These functions convert between absolute Addresses of Code objects and
498 // the relative displacements stored in the code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 static inline Address target_address_at(Address pc, Address constant_pool);
500 static inline void set_target_address_at(
501 Isolate* isolate, Address pc, Address constant_pool, Address target,
502 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 static inline Address target_address_at(Address pc, Code* code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504 Address constant_pool = code ? code->constant_pool() : NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000505 return target_address_at(pc, constant_pool);
506 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000507 static inline void set_target_address_at(
508 Isolate* isolate, Address pc, Code* code, Address target,
509 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED) {
510 Address constant_pool = code ? code->constant_pool() : NULL;
511 set_target_address_at(isolate, pc, constant_pool, target,
512 icache_flush_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000513 }
514
515 // Return the code target address at a call site from the return address
516 // of that call in the instruction stream.
517 static inline Address target_address_from_return_address(Address pc);
518
Steve Blockd0582a62009-12-15 09:54:21 +0000519 // This sets the branch destination (which is in the instruction on x64).
520 // This is for calls and branches within generated code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100521 inline static void deserialization_set_special_target_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000522 Isolate* isolate, Address instruction_payload, Code* code,
523 Address target) {
524 set_target_address_at(isolate, instruction_payload, code, target);
Steve Blockd0582a62009-12-15 09:54:21 +0000525 }
526
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 // This sets the internal reference at the pc.
528 inline static void deserialization_set_target_internal_reference_at(
529 Isolate* isolate, Address pc, Address target,
530 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
531
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 static inline RelocInfo::Mode RelocInfoNone() {
533 if (kPointerSize == kInt64Size) {
534 return RelocInfo::NONE64;
535 } else {
536 DCHECK(kPointerSize == kInt32Size);
537 return RelocInfo::NONE32;
538 }
Steve Blockd0582a62009-12-15 09:54:21 +0000539 }
540
Steve Block3ce2e202009-11-05 08:53:23 +0000541 inline Handle<Object> code_target_object_handle_at(Address pc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000542 inline Address runtime_entry_at(Address pc);
Steve Blockd0582a62009-12-15 09:54:21 +0000543 // Number of bytes taken up by the branch target in the code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100544 static const int kSpecialTargetSize = 4; // Use 32-bit displacement.
Steve Blocka7e24c12009-10-30 11:49:00 +0000545 // Distance between the address of the code target in the call instruction
Steve Block3ce2e202009-11-05 08:53:23 +0000546 // and the return address pushed on the stack.
547 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000548 // The length of call(kScratchRegister).
549 static const int kCallScratchRegisterInstructionLength = 3;
550 // The length of call(Immediate32).
Steve Block1e0659c2011-05-24 12:43:12 +0100551 static const int kShortCallInstructionLength = 5;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 // The length of movq(kScratchRegister, address).
553 static const int kMoveAddressIntoScratchRegisterInstructionLength =
554 2 + kPointerSize;
555 // The length of movq(kScratchRegister, address) and call(kScratchRegister).
556 static const int kCallSequenceLength =
557 kMoveAddressIntoScratchRegisterInstructionLength +
558 kCallScratchRegisterInstructionLength;
Steve Blockd0582a62009-12-15 09:54:21 +0000559
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 // The debug break slot must be able to contain an indirect call sequence.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000561 static const int kDebugBreakSlotLength = kCallSequenceLength;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562 // Distance between start of patched debug break slot and the emitted address
563 // to jump to.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564 static const int kPatchDebugBreakSlotAddressOffset =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000565 kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100566
Steve Block9fac8402011-05-12 15:51:54 +0100567 // One byte opcode for test eax,0xXXXXXXXX.
568 static const byte kTestEaxByte = 0xA9;
Steve Block1e0659c2011-05-24 12:43:12 +0100569 // One byte opcode for test al, 0xXX.
570 static const byte kTestAlByte = 0xA8;
571 // One byte opcode for nop.
572 static const byte kNopByte = 0x90;
573
574 // One byte prefix for a short conditional jump.
575 static const byte kJccShortPrefix = 0x70;
576 static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
577 static const byte kJcShortOpcode = kJccShortPrefix | carry;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000578 static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
579 static const byte kJzShortOpcode = kJccShortPrefix | zero;
Steve Block1e0659c2011-05-24 12:43:12 +0100580
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000581 // VEX prefix encodings.
582 enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 };
583 enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128, kLZ = kL128 };
584 enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 };
585 enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x3 };
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100586
Steve Blocka7e24c12009-10-30 11:49:00 +0000587 // ---------------------------------------------------------------------------
588 // Code generation
589 //
590 // Function names correspond one-to-one to x64 instruction mnemonics.
591 // Unless specified otherwise, instructions operate on 64-bit operands.
592 //
593 // If we need versions of an assembly instruction that operate on different
594 // width arguments, we add a single-letter suffix specifying the width.
595 // This is done for the following instructions: mov, cmp, inc, dec,
596 // add, sub, and test.
597 // There are no versions of these instructions without the suffix.
598 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
599 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
600 // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
601 // - Instructions on 64-bit (quadword) operands/registers use 'q'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000602 // - Instructions on operands/registers with pointer size use 'p'.
603
604 STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
605
606#define DECLARE_INSTRUCTION(instruction) \
607 template<class P1> \
608 void instruction##p(P1 p1) { \
609 emit_##instruction(p1, kPointerSize); \
610 } \
611 \
612 template<class P1> \
613 void instruction##l(P1 p1) { \
614 emit_##instruction(p1, kInt32Size); \
615 } \
616 \
617 template<class P1> \
618 void instruction##q(P1 p1) { \
619 emit_##instruction(p1, kInt64Size); \
620 } \
621 \
622 template<class P1, class P2> \
623 void instruction##p(P1 p1, P2 p2) { \
624 emit_##instruction(p1, p2, kPointerSize); \
625 } \
626 \
627 template<class P1, class P2> \
628 void instruction##l(P1 p1, P2 p2) { \
629 emit_##instruction(p1, p2, kInt32Size); \
630 } \
631 \
632 template<class P1, class P2> \
633 void instruction##q(P1 p1, P2 p2) { \
634 emit_##instruction(p1, p2, kInt64Size); \
635 } \
636 \
637 template<class P1, class P2, class P3> \
638 void instruction##p(P1 p1, P2 p2, P3 p3) { \
639 emit_##instruction(p1, p2, p3, kPointerSize); \
640 } \
641 \
642 template<class P1, class P2, class P3> \
643 void instruction##l(P1 p1, P2 p2, P3 p3) { \
644 emit_##instruction(p1, p2, p3, kInt32Size); \
645 } \
646 \
647 template<class P1, class P2, class P3> \
648 void instruction##q(P1 p1, P2 p2, P3 p3) { \
649 emit_##instruction(p1, p2, p3, kInt64Size); \
650 }
651 ASSEMBLER_INSTRUCTION_LIST(DECLARE_INSTRUCTION)
652#undef DECLARE_INSTRUCTION
Steve Blocka7e24c12009-10-30 11:49:00 +0000653
654 // Insert the smallest number of nop instructions
655 // possible to align the pc offset to a multiple
Steve Block1e0659c2011-05-24 12:43:12 +0100656 // of m, where m must be a power of 2.
Steve Blocka7e24c12009-10-30 11:49:00 +0000657 void Align(int m);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000658 // Insert the smallest number of zero bytes possible to align the pc offset
659 // to a mulitple of m. m must be a power of 2 (>= 2).
660 void DataAlign(int m);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100661 void Nop(int bytes = 1);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100662 // Aligns code to something that's optimal for a jump target for the platform.
663 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000664
665 // Stack
666 void pushfq();
667 void popfq();
668
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669 void pushq(Immediate value);
Steve Block1e0659c2011-05-24 12:43:12 +0100670 // Push a 32 bit integer, and guarantee that it is actually pushed as a
671 // 32 bit value, the normal push will optimize the 8 bit case.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000672 void pushq_imm32(int32_t imm32);
673 void pushq(Register src);
674 void pushq(const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000675
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000676 void popq(Register dst);
677 void popq(const Operand& dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000678
679 void enter(Immediate size);
680 void leave();
681
682 // Moves
683 void movb(Register dst, const Operand& src);
684 void movb(Register dst, Immediate imm);
685 void movb(const Operand& dst, Register src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000686 void movb(const Operand& dst, Immediate imm);
Steve Blocka7e24c12009-10-30 11:49:00 +0000687
Steve Block3ce2e202009-11-05 08:53:23 +0000688 // Move the low 16 bits of a 64-bit register value to a 16-bit
689 // memory location.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690 void movw(Register dst, const Operand& src);
Steve Block3ce2e202009-11-05 08:53:23 +0000691 void movw(const Operand& dst, Register src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000692 void movw(const Operand& dst, Immediate imm);
Steve Block3ce2e202009-11-05 08:53:23 +0000693
Steve Blocka7e24c12009-10-30 11:49:00 +0000694 // Move the offset of the label location relative to the current
695 // position (after the move) to the destination.
696 void movl(const Operand& dst, Label* src);
697
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000698 // Loads a pointer into a register with a relocation mode.
699 void movp(Register dst, void* ptr, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000700
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000701 // Loads a 64-bit immediate into a register.
Ben Murdochda12d292016-06-02 14:46:10 +0100702 void movq(Register dst, int64_t value,
703 RelocInfo::Mode rmode = RelocInfo::NONE64);
704 void movq(Register dst, uint64_t value,
705 RelocInfo::Mode rmode = RelocInfo::NONE64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000706
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400707 void movsxbl(Register dst, Register src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000708 void movsxbl(Register dst, const Operand& src);
Steve Block3ce2e202009-11-05 08:53:23 +0000709 void movsxbq(Register dst, const Operand& src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400710 void movsxwl(Register dst, Register src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000711 void movsxwl(Register dst, const Operand& src);
Steve Block3ce2e202009-11-05 08:53:23 +0000712 void movsxwq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000713 void movsxlq(Register dst, Register src);
714 void movsxlq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000715
Leon Clarked91b9f72010-01-27 17:25:45 +0000716 // Repeated moves.
717
718 void repmovsb();
719 void repmovsw();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720 void repmovsp() { emit_repmovs(kPointerSize); }
721 void repmovsl() { emit_repmovs(kInt32Size); }
722 void repmovsq() { emit_repmovs(kInt64Size); }
Leon Clarked91b9f72010-01-27 17:25:45 +0000723
Steve Block44f0eee2011-05-26 01:26:41 +0100724 // Instruction to load from an immediate 64-bit pointer into RAX.
Steve Blocka7e24c12009-10-30 11:49:00 +0000725 void load_rax(void* ptr, RelocInfo::Mode rmode);
726 void load_rax(ExternalReference ext);
727
728 // Conditional moves.
729 void cmovq(Condition cc, Register dst, Register src);
730 void cmovq(Condition cc, Register dst, const Operand& src);
731 void cmovl(Condition cc, Register dst, Register src);
732 void cmovl(Condition cc, Register dst, const Operand& src);
733
Steve Blocka7e24c12009-10-30 11:49:00 +0000734 void cmpb(Register dst, Immediate src) {
735 immediate_arithmetic_op_8(0x7, dst, src);
736 }
737
738 void cmpb_al(Immediate src);
739
740 void cmpb(Register dst, Register src) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000741 arithmetic_op_8(0x3A, dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000742 }
743
744 void cmpb(Register dst, const Operand& src) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745 arithmetic_op_8(0x3A, dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000746 }
747
748 void cmpb(const Operand& dst, Register src) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000749 arithmetic_op_8(0x38, src, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000750 }
751
752 void cmpb(const Operand& dst, Immediate src) {
753 immediate_arithmetic_op_8(0x7, dst, src);
754 }
755
756 void cmpw(const Operand& dst, Immediate src) {
757 immediate_arithmetic_op_16(0x7, dst, src);
758 }
759
760 void cmpw(Register dst, Immediate src) {
761 immediate_arithmetic_op_16(0x7, dst, src);
762 }
763
764 void cmpw(Register dst, const Operand& src) {
765 arithmetic_op_16(0x3B, dst, src);
766 }
767
768 void cmpw(Register dst, Register src) {
769 arithmetic_op_16(0x3B, dst, src);
770 }
771
772 void cmpw(const Operand& dst, Register src) {
773 arithmetic_op_16(0x39, src, dst);
774 }
775
Ben Murdochda12d292016-06-02 14:46:10 +0100776 void testb(Register reg, const Operand& op) { testb(op, reg); }
777
778 void testw(Register reg, const Operand& op) { testw(op, reg); }
779
Leon Clarke4515c472010-02-03 11:58:03 +0000780 void andb(Register dst, Immediate src) {
781 immediate_arithmetic_op_8(0x4, dst, src);
782 }
Steve Block3ce2e202009-11-05 08:53:23 +0000783
Steve Block3ce2e202009-11-05 08:53:23 +0000784 void decb(Register dst);
785 void decb(const Operand& dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000786
787 // Sign-extends rax into rdx:rax.
788 void cqo();
789 // Sign-extends eax into edx:eax.
790 void cdq();
791
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400792 // Multiply eax by src, put the result in edx:eax.
793 void mull(Register src);
794 void mull(const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000795 // Multiply rax by src, put the result in rdx:rax.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400796 void mulq(Register src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000797
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400798#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode) \
799 void instruction##p(Register dst, Immediate imm8) { \
800 shift(dst, imm8, subcode, kPointerSize); \
801 } \
802 \
803 void instruction##l(Register dst, Immediate imm8) { \
804 shift(dst, imm8, subcode, kInt32Size); \
805 } \
806 \
807 void instruction##q(Register dst, Immediate imm8) { \
808 shift(dst, imm8, subcode, kInt64Size); \
809 } \
810 \
811 void instruction##p(Operand dst, Immediate imm8) { \
812 shift(dst, imm8, subcode, kPointerSize); \
813 } \
814 \
815 void instruction##l(Operand dst, Immediate imm8) { \
816 shift(dst, imm8, subcode, kInt32Size); \
817 } \
818 \
819 void instruction##q(Operand dst, Immediate imm8) { \
820 shift(dst, imm8, subcode, kInt64Size); \
821 } \
822 \
823 void instruction##p_cl(Register dst) { shift(dst, subcode, kPointerSize); } \
824 \
825 void instruction##l_cl(Register dst) { shift(dst, subcode, kInt32Size); } \
826 \
827 void instruction##q_cl(Register dst) { shift(dst, subcode, kInt64Size); } \
828 \
829 void instruction##p_cl(Operand dst) { shift(dst, subcode, kPointerSize); } \
830 \
831 void instruction##l_cl(Operand dst) { shift(dst, subcode, kInt32Size); } \
832 \
833 void instruction##q_cl(Operand dst) { shift(dst, subcode, kInt64Size); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000834 SHIFT_INSTRUCTION_LIST(DECLARE_SHIFT_INSTRUCTION)
835#undef DECLARE_SHIFT_INSTRUCTION
Steve Blocka7e24c12009-10-30 11:49:00 +0000836
837 // Shifts dst:src left by cl bits, affecting only dst.
838 void shld(Register dst, Register src);
839
840 // Shifts src:dst right by cl bits, affecting only dst.
841 void shrd(Register dst, Register src);
842
Steve Blocka7e24c12009-10-30 11:49:00 +0000843 void store_rax(void* dst, RelocInfo::Mode mode);
844 void store_rax(ExternalReference ref);
845
Steve Blocka7e24c12009-10-30 11:49:00 +0000846 void subb(Register dst, Immediate src) {
847 immediate_arithmetic_op_8(0x5, dst, src);
848 }
849
Steve Block3ce2e202009-11-05 08:53:23 +0000850 void testb(Register dst, Register src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000851 void testb(Register reg, Immediate mask);
852 void testb(const Operand& op, Immediate mask);
Leon Clarkee46be812010-01-19 14:06:41 +0000853 void testb(const Operand& op, Register reg);
Steve Blocka7e24c12009-10-30 11:49:00 +0000854
Ben Murdochda12d292016-06-02 14:46:10 +0100855 void testw(Register dst, Register src);
856 void testw(Register reg, Immediate mask);
857 void testw(const Operand& op, Immediate mask);
858 void testw(const Operand& op, Register reg);
859
Steve Blocka7e24c12009-10-30 11:49:00 +0000860 // Bit operations.
861 void bt(const Operand& dst, Register src);
862 void bts(const Operand& dst, Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000863 void bsrq(Register dst, Register src);
864 void bsrq(Register dst, const Operand& src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000865 void bsrl(Register dst, Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 void bsrl(Register dst, const Operand& src);
867 void bsfq(Register dst, Register src);
868 void bsfq(Register dst, const Operand& src);
869 void bsfl(Register dst, Register src);
870 void bsfl(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000871
872 // Miscellaneous
Steve Block3ce2e202009-11-05 08:53:23 +0000873 void clc();
Steve Block44f0eee2011-05-26 01:26:41 +0100874 void cld();
Steve Blocka7e24c12009-10-30 11:49:00 +0000875 void cpuid();
876 void hlt();
877 void int3();
878 void nop();
Steve Blocka7e24c12009-10-30 11:49:00 +0000879 void ret(int imm16);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 void ud2();
Steve Blocka7e24c12009-10-30 11:49:00 +0000881 void setcc(Condition cc, Register reg);
882
883 // Label operations & relative jumps (PPUM Appendix D)
884 //
885 // Takes a branch opcode (cc) and a label (L) and generates
886 // either a backward branch or a forward branch and links it
887 // to the label fixup chain. Usage:
888 //
889 // Label L; // unbound label
890 // j(cc, &L); // forward branch to unbound label
891 // bind(&L); // bind label to the current pc
892 // j(cc, &L); // backward branch to bound label
893 // bind(&L); // illegal: a label may be bound only once
894 //
895 // Note: The same Label can be used for forward and backward branches
896 // but it may be bound only once.
897
898 void bind(Label* L); // binds an unbound label L to the current code position
899
900 // Calls
901 // Call near relative 32-bit displacement, relative to next instruction.
902 void call(Label* L);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000903 void call(Address entry, RelocInfo::Mode rmode);
Ben Murdoch257744e2011-11-30 15:57:28 +0000904 void call(Handle<Code> target,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000905 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906 TypeFeedbackId ast_id = TypeFeedbackId::None());
Steve Blocka7e24c12009-10-30 11:49:00 +0000907
Steve Block1e0659c2011-05-24 12:43:12 +0100908 // Calls directly to the given address using a relative offset.
909 // Should only ever be used in Code objects for calls within the
910 // same Code object. Should not be used when generating new code (use labels),
911 // but only when patching existing code.
912 void call(Address target);
913
Steve Blocka7e24c12009-10-30 11:49:00 +0000914 // Call near absolute indirect, address in register
915 void call(Register adr);
916
Steve Blocka7e24c12009-10-30 11:49:00 +0000917 // Jumps
918 // Jump short or near relative.
Steve Block3ce2e202009-11-05 08:53:23 +0000919 // Use a 32-bit signed displacement.
Ben Murdoch257744e2011-11-30 15:57:28 +0000920 // Unconditional jump to L
921 void jmp(Label* L, Label::Distance distance = Label::kFar);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000922 void jmp(Address entry, RelocInfo::Mode rmode);
Steve Block3ce2e202009-11-05 08:53:23 +0000923 void jmp(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000924
925 // Jump near absolute indirect (r64)
926 void jmp(Register adr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000927 void jmp(const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000928
Steve Blocka7e24c12009-10-30 11:49:00 +0000929 // Conditional jumps
Ben Murdoch257744e2011-11-30 15:57:28 +0000930 void j(Condition cc,
931 Label* L,
932 Label::Distance distance = Label::kFar);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000933 void j(Condition cc, Address entry, RelocInfo::Mode rmode);
Steve Block3ce2e202009-11-05 08:53:23 +0000934 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000935
936 // Floating-point operations
937 void fld(int i);
938
939 void fld1();
940 void fldz();
Steve Block6ded16b2010-05-10 14:33:55 +0100941 void fldpi();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100942 void fldln2();
Steve Blocka7e24c12009-10-30 11:49:00 +0000943
944 void fld_s(const Operand& adr);
945 void fld_d(const Operand& adr);
946
947 void fstp_s(const Operand& adr);
948 void fstp_d(const Operand& adr);
Steve Block3ce2e202009-11-05 08:53:23 +0000949 void fstp(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000950
951 void fild_s(const Operand& adr);
952 void fild_d(const Operand& adr);
953
954 void fist_s(const Operand& adr);
955
956 void fistp_s(const Operand& adr);
957 void fistp_d(const Operand& adr);
958
959 void fisttp_s(const Operand& adr);
Leon Clarked91b9f72010-01-27 17:25:45 +0000960 void fisttp_d(const Operand& adr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000961
962 void fabs();
963 void fchs();
964
965 void fadd(int i);
966 void fsub(int i);
967 void fmul(int i);
968 void fdiv(int i);
969
970 void fisub_s(const Operand& adr);
971
972 void faddp(int i = 1);
973 void fsubp(int i = 1);
974 void fsubrp(int i = 1);
975 void fmulp(int i = 1);
976 void fdivp(int i = 1);
977 void fprem();
978 void fprem1();
979
980 void fxch(int i = 1);
981 void fincstp();
982 void ffree(int i = 0);
983
984 void ftst();
985 void fucomp(int i);
986 void fucompp();
Steve Block3ce2e202009-11-05 08:53:23 +0000987 void fucomi(int i);
988 void fucomip();
989
Steve Blocka7e24c12009-10-30 11:49:00 +0000990 void fcompp();
991 void fnstsw_ax();
992 void fwait();
993 void fnclex();
994
995 void fsin();
996 void fcos();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100997 void fptan();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100998 void fyl2x();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100999 void f2xm1();
1000 void fscale();
1001 void fninit();
Steve Blocka7e24c12009-10-30 11:49:00 +00001002
1003 void frndint();
1004
1005 void sahf();
1006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001007 // SSE instructions
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001008 void addss(XMMRegister dst, XMMRegister src);
1009 void addss(XMMRegister dst, const Operand& src);
1010 void subss(XMMRegister dst, XMMRegister src);
1011 void subss(XMMRegister dst, const Operand& src);
1012 void mulss(XMMRegister dst, XMMRegister src);
1013 void mulss(XMMRegister dst, const Operand& src);
1014 void divss(XMMRegister dst, XMMRegister src);
1015 void divss(XMMRegister dst, const Operand& src);
1016
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 void maxss(XMMRegister dst, XMMRegister src);
1018 void maxss(XMMRegister dst, const Operand& src);
1019 void minss(XMMRegister dst, XMMRegister src);
1020 void minss(XMMRegister dst, const Operand& src);
1021
1022 void sqrtss(XMMRegister dst, XMMRegister src);
1023 void sqrtss(XMMRegister dst, const Operand& src);
1024
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001025 void ucomiss(XMMRegister dst, XMMRegister src);
1026 void ucomiss(XMMRegister dst, const Operand& src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001027 void movaps(XMMRegister dst, XMMRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001028
1029 // Don't use this unless it's important to keep the
1030 // top half of the destination register unchanged.
1031 // Use movaps when moving float values and movd for integer
1032 // values in xmm registers.
1033 void movss(XMMRegister dst, XMMRegister src);
1034
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001035 void movss(XMMRegister dst, const Operand& src);
1036 void movss(const Operand& dst, XMMRegister src);
1037 void shufps(XMMRegister dst, XMMRegister src, byte imm8);
1038
1039 void cvttss2si(Register dst, const Operand& src);
1040 void cvttss2si(Register dst, XMMRegister src);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001041 void cvtlsi2ss(XMMRegister dst, const Operand& src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042 void cvtlsi2ss(XMMRegister dst, Register src);
1043
1044 void andps(XMMRegister dst, XMMRegister src);
1045 void andps(XMMRegister dst, const Operand& src);
1046 void orps(XMMRegister dst, XMMRegister src);
1047 void orps(XMMRegister dst, const Operand& src);
1048 void xorps(XMMRegister dst, XMMRegister src);
1049 void xorps(XMMRegister dst, const Operand& src);
1050
1051 void addps(XMMRegister dst, XMMRegister src);
1052 void addps(XMMRegister dst, const Operand& src);
1053 void subps(XMMRegister dst, XMMRegister src);
1054 void subps(XMMRegister dst, const Operand& src);
1055 void mulps(XMMRegister dst, XMMRegister src);
1056 void mulps(XMMRegister dst, const Operand& src);
1057 void divps(XMMRegister dst, XMMRegister src);
1058 void divps(XMMRegister dst, const Operand& src);
1059
1060 void movmskps(Register dst, XMMRegister src);
1061
Steve Blocka7e24c12009-10-30 11:49:00 +00001062 // SSE2 instructions
Steve Block6ded16b2010-05-10 14:33:55 +01001063 void movd(XMMRegister dst, Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001064 void movd(XMMRegister dst, const Operand& src);
Steve Block6ded16b2010-05-10 14:33:55 +01001065 void movd(Register dst, XMMRegister src);
1066 void movq(XMMRegister dst, Register src);
1067 void movq(Register dst, XMMRegister src);
Ben Murdoch257744e2011-11-30 15:57:28 +00001068 void movq(XMMRegister dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001069
Ben Murdoch257744e2011-11-30 15:57:28 +00001070 // Don't use this unless it's important to keep the
1071 // top half of the destination register unchanged.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001072 // Use movapd when moving double values and movq for integer
Ben Murdoch257744e2011-11-30 15:57:28 +00001073 // values in xmm registers.
Steve Block053d10c2011-06-13 19:13:29 +01001074 void movsd(XMMRegister dst, XMMRegister src);
Ben Murdoch257744e2011-11-30 15:57:28 +00001075
1076 void movsd(const Operand& dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001077 void movsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001078
Steve Block1e0659c2011-05-24 12:43:12 +01001079 void movdqa(const Operand& dst, XMMRegister src);
1080 void movdqa(XMMRegister dst, const Operand& src);
1081
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001082 void movdqu(const Operand& dst, XMMRegister src);
1083 void movdqu(XMMRegister dst, const Operand& src);
1084
Ben Murdoch257744e2011-11-30 15:57:28 +00001085 void movapd(XMMRegister dst, XMMRegister src);
Ben Murdoch257744e2011-11-30 15:57:28 +00001086
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087 void psllq(XMMRegister reg, byte imm8);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001088 void psrlq(XMMRegister reg, byte imm8);
1089 void pslld(XMMRegister reg, byte imm8);
1090 void psrld(XMMRegister reg, byte imm8);
Steve Block8defd9f2010-07-08 12:39:36 +01001091
Steve Blocka7e24c12009-10-30 11:49:00 +00001092 void cvttsd2si(Register dst, const Operand& src);
Steve Block1e0659c2011-05-24 12:43:12 +01001093 void cvttsd2si(Register dst, XMMRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 void cvttss2siq(Register dst, XMMRegister src);
1095 void cvttss2siq(Register dst, const Operand& src);
Kristian Monsen25f61362010-05-21 11:50:48 +01001096 void cvttsd2siq(Register dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001097 void cvttsd2siq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001098
1099 void cvtlsi2sd(XMMRegister dst, const Operand& src);
1100 void cvtlsi2sd(XMMRegister dst, Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101
1102 void cvtqsi2ss(XMMRegister dst, const Operand& src);
1103 void cvtqsi2ss(XMMRegister dst, Register src);
1104
Steve Blocka7e24c12009-10-30 11:49:00 +00001105 void cvtqsi2sd(XMMRegister dst, const Operand& src);
1106 void cvtqsi2sd(XMMRegister dst, Register src);
1107
Steve Block8defd9f2010-07-08 12:39:36 +01001108
Steve Block6ded16b2010-05-10 14:33:55 +01001109 void cvtss2sd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001110 void cvtss2sd(XMMRegister dst, const Operand& src);
1111 void cvtsd2ss(XMMRegister dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001112 void cvtsd2ss(XMMRegister dst, const Operand& src);
Steve Block8defd9f2010-07-08 12:39:36 +01001113
1114 void cvtsd2si(Register dst, XMMRegister src);
1115 void cvtsd2siq(Register dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001116
Steve Blocka7e24c12009-10-30 11:49:00 +00001117 void addsd(XMMRegister dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118 void addsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001119 void subsd(XMMRegister dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001120 void subsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001121 void mulsd(XMMRegister dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001122 void mulsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001123 void divsd(XMMRegister dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001124 void divsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001125
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001126 void maxsd(XMMRegister dst, XMMRegister src);
1127 void maxsd(XMMRegister dst, const Operand& src);
1128 void minsd(XMMRegister dst, XMMRegister src);
1129 void minsd(XMMRegister dst, const Operand& src);
1130
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001131 void andpd(XMMRegister dst, XMMRegister src);
1132 void orpd(XMMRegister dst, XMMRegister src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001133 void xorpd(XMMRegister dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001134 void sqrtsd(XMMRegister dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001135 void sqrtsd(XMMRegister dst, const Operand& src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001136
Andrei Popescu402d9372010-02-26 13:31:12 +00001137 void ucomisd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001138 void ucomisd(XMMRegister dst, const Operand& src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001139 void cmpltsd(XMMRegister dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001140 void pcmpeqd(XMMRegister dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001141
1142 void movmskpd(Register dst, XMMRegister src);
1143
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001144 void punpckldq(XMMRegister dst, XMMRegister src);
1145 void punpckhdq(XMMRegister dst, XMMRegister src);
1146
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001147 // SSE 4.1 instruction
1148 void extractps(Register dst, XMMRegister src, byte imm8);
Steve Blocka7e24c12009-10-30 11:49:00 +00001149
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150 void pextrd(Register dst, XMMRegister src, int8_t imm8);
Ben Murdoch257744e2011-11-30 15:57:28 +00001151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001152 void pinsrd(XMMRegister dst, Register src, int8_t imm8);
1153 void pinsrd(XMMRegister dst, const Operand& src, int8_t imm8);
1154
1155 void roundss(XMMRegister dst, XMMRegister src, RoundingMode mode);
Ben Murdoch257744e2011-11-30 15:57:28 +00001156 void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1157
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001158 // AVX instruction
1159 void vfmadd132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1160 vfmasd(0x99, dst, src1, src2);
1161 }
1162 void vfmadd213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1163 vfmasd(0xa9, dst, src1, src2);
1164 }
1165 void vfmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1166 vfmasd(0xb9, dst, src1, src2);
1167 }
1168 void vfmadd132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1169 vfmasd(0x99, dst, src1, src2);
1170 }
1171 void vfmadd213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1172 vfmasd(0xa9, dst, src1, src2);
1173 }
1174 void vfmadd231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1175 vfmasd(0xb9, dst, src1, src2);
1176 }
1177 void vfmsub132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1178 vfmasd(0x9b, dst, src1, src2);
1179 }
1180 void vfmsub213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1181 vfmasd(0xab, dst, src1, src2);
1182 }
1183 void vfmsub231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1184 vfmasd(0xbb, dst, src1, src2);
1185 }
1186 void vfmsub132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1187 vfmasd(0x9b, dst, src1, src2);
1188 }
1189 void vfmsub213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1190 vfmasd(0xab, dst, src1, src2);
1191 }
1192 void vfmsub231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1193 vfmasd(0xbb, dst, src1, src2);
1194 }
1195 void vfnmadd132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1196 vfmasd(0x9d, dst, src1, src2);
1197 }
1198 void vfnmadd213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1199 vfmasd(0xad, dst, src1, src2);
1200 }
1201 void vfnmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1202 vfmasd(0xbd, dst, src1, src2);
1203 }
1204 void vfnmadd132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1205 vfmasd(0x9d, dst, src1, src2);
1206 }
1207 void vfnmadd213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1208 vfmasd(0xad, dst, src1, src2);
1209 }
1210 void vfnmadd231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1211 vfmasd(0xbd, dst, src1, src2);
1212 }
1213 void vfnmsub132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1214 vfmasd(0x9f, dst, src1, src2);
1215 }
1216 void vfnmsub213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1217 vfmasd(0xaf, dst, src1, src2);
1218 }
1219 void vfnmsub231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1220 vfmasd(0xbf, dst, src1, src2);
1221 }
1222 void vfnmsub132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1223 vfmasd(0x9f, dst, src1, src2);
1224 }
1225 void vfnmsub213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1226 vfmasd(0xaf, dst, src1, src2);
1227 }
1228 void vfnmsub231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1229 vfmasd(0xbf, dst, src1, src2);
1230 }
1231 void vfmasd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1232 void vfmasd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1233
1234 void vfmadd132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1235 vfmass(0x99, dst, src1, src2);
1236 }
1237 void vfmadd213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1238 vfmass(0xa9, dst, src1, src2);
1239 }
1240 void vfmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1241 vfmass(0xb9, dst, src1, src2);
1242 }
1243 void vfmadd132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1244 vfmass(0x99, dst, src1, src2);
1245 }
1246 void vfmadd213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1247 vfmass(0xa9, dst, src1, src2);
1248 }
1249 void vfmadd231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1250 vfmass(0xb9, dst, src1, src2);
1251 }
1252 void vfmsub132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1253 vfmass(0x9b, dst, src1, src2);
1254 }
1255 void vfmsub213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1256 vfmass(0xab, dst, src1, src2);
1257 }
1258 void vfmsub231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1259 vfmass(0xbb, dst, src1, src2);
1260 }
1261 void vfmsub132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1262 vfmass(0x9b, dst, src1, src2);
1263 }
1264 void vfmsub213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1265 vfmass(0xab, dst, src1, src2);
1266 }
1267 void vfmsub231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1268 vfmass(0xbb, dst, src1, src2);
1269 }
1270 void vfnmadd132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1271 vfmass(0x9d, dst, src1, src2);
1272 }
1273 void vfnmadd213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1274 vfmass(0xad, dst, src1, src2);
1275 }
1276 void vfnmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1277 vfmass(0xbd, dst, src1, src2);
1278 }
1279 void vfnmadd132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1280 vfmass(0x9d, dst, src1, src2);
1281 }
1282 void vfnmadd213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1283 vfmass(0xad, dst, src1, src2);
1284 }
1285 void vfnmadd231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1286 vfmass(0xbd, dst, src1, src2);
1287 }
1288 void vfnmsub132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1289 vfmass(0x9f, dst, src1, src2);
1290 }
1291 void vfnmsub213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1292 vfmass(0xaf, dst, src1, src2);
1293 }
1294 void vfnmsub231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1295 vfmass(0xbf, dst, src1, src2);
1296 }
1297 void vfnmsub132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1298 vfmass(0x9f, dst, src1, src2);
1299 }
1300 void vfnmsub213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1301 vfmass(0xaf, dst, src1, src2);
1302 }
1303 void vfnmsub231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1304 vfmass(0xbf, dst, src1, src2);
1305 }
1306 void vfmass(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1307 void vfmass(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001309 void vmovd(XMMRegister dst, Register src);
1310 void vmovd(XMMRegister dst, const Operand& src);
1311 void vmovd(Register dst, XMMRegister src);
1312 void vmovq(XMMRegister dst, Register src);
1313 void vmovq(XMMRegister dst, const Operand& src);
1314 void vmovq(Register dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001315
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 void vmovsd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1317 vsd(0x10, dst, src1, src2);
1318 }
1319 void vmovsd(XMMRegister dst, const Operand& src) {
1320 vsd(0x10, dst, xmm0, src);
1321 }
1322 void vmovsd(const Operand& dst, XMMRegister src) {
1323 vsd(0x11, src, xmm0, dst);
1324 }
1325
1326#define AVX_SP_3(instr, opcode) \
1327 AVX_S_3(instr, opcode) \
1328 AVX_P_3(instr, opcode)
1329
1330#define AVX_S_3(instr, opcode) \
1331 AVX_3(instr##ss, opcode, vss) \
1332 AVX_3(instr##sd, opcode, vsd)
1333
1334#define AVX_P_3(instr, opcode) \
1335 AVX_3(instr##ps, opcode, vps) \
1336 AVX_3(instr##pd, opcode, vpd)
1337
1338#define AVX_3(instr, opcode, impl) \
1339 void instr(XMMRegister dst, XMMRegister src1, XMMRegister src2) { \
1340 impl(opcode, dst, src1, src2); \
1341 } \
1342 void instr(XMMRegister dst, XMMRegister src1, const Operand& src2) { \
1343 impl(opcode, dst, src1, src2); \
1344 }
1345
1346 AVX_SP_3(vsqrt, 0x51);
1347 AVX_SP_3(vadd, 0x58);
1348 AVX_SP_3(vsub, 0x5c);
1349 AVX_SP_3(vmul, 0x59);
1350 AVX_SP_3(vdiv, 0x5e);
1351 AVX_SP_3(vmin, 0x5d);
1352 AVX_SP_3(vmax, 0x5f);
1353 AVX_P_3(vand, 0x54);
1354 AVX_P_3(vor, 0x56);
1355 AVX_P_3(vxor, 0x57);
1356 AVX_3(vpcmpeqd, 0x76, vpd);
1357 AVX_3(vcvtsd2ss, 0x5a, vsd);
1358
1359#undef AVX_3
1360#undef AVX_S_3
1361#undef AVX_P_3
1362#undef AVX_SP_3
1363
1364 void vpsrlq(XMMRegister dst, XMMRegister src, byte imm8) {
1365 XMMRegister iop = {2};
1366 vpd(0x73, iop, dst, src);
1367 emit(imm8);
1368 }
1369 void vpsllq(XMMRegister dst, XMMRegister src, byte imm8) {
1370 XMMRegister iop = {6};
1371 vpd(0x73, iop, dst, src);
1372 emit(imm8);
1373 }
1374 void vcvtss2sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1375 vsd(0x5a, dst, src1, src2, kF3, k0F, kWIG);
1376 }
1377 void vcvtss2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1378 vsd(0x5a, dst, src1, src2, kF3, k0F, kWIG);
1379 }
1380 void vcvtlsi2sd(XMMRegister dst, XMMRegister src1, Register src2) {
1381 XMMRegister isrc2 = {src2.code()};
1382 vsd(0x2a, dst, src1, isrc2, kF2, k0F, kW0);
1383 }
1384 void vcvtlsi2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1385 vsd(0x2a, dst, src1, src2, kF2, k0F, kW0);
1386 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001387 void vcvtlsi2ss(XMMRegister dst, XMMRegister src1, Register src2) {
1388 XMMRegister isrc2 = {src2.code()};
1389 vsd(0x2a, dst, src1, isrc2, kF3, k0F, kW0);
1390 }
1391 void vcvtlsi2ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1392 vsd(0x2a, dst, src1, src2, kF3, k0F, kW0);
1393 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001394 void vcvtqsi2ss(XMMRegister dst, XMMRegister src1, Register src2) {
1395 XMMRegister isrc2 = {src2.code()};
1396 vsd(0x2a, dst, src1, isrc2, kF3, k0F, kW1);
1397 }
1398 void vcvtqsi2ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1399 vsd(0x2a, dst, src1, src2, kF3, k0F, kW1);
1400 }
1401 void vcvtqsi2sd(XMMRegister dst, XMMRegister src1, Register src2) {
1402 XMMRegister isrc2 = {src2.code()};
1403 vsd(0x2a, dst, src1, isrc2, kF2, k0F, kW1);
1404 }
1405 void vcvtqsi2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1406 vsd(0x2a, dst, src1, src2, kF2, k0F, kW1);
1407 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001408 void vcvttss2si(Register dst, XMMRegister src) {
1409 XMMRegister idst = {dst.code()};
1410 vsd(0x2c, idst, xmm0, src, kF3, k0F, kW0);
1411 }
1412 void vcvttss2si(Register dst, const Operand& src) {
1413 XMMRegister idst = {dst.code()};
1414 vsd(0x2c, idst, xmm0, src, kF3, k0F, kW0);
1415 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001416 void vcvttsd2si(Register dst, XMMRegister src) {
1417 XMMRegister idst = {dst.code()};
1418 vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
1419 }
1420 void vcvttsd2si(Register dst, const Operand& src) {
1421 XMMRegister idst = {dst.code()};
1422 vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
1423 }
1424 void vcvttss2siq(Register dst, XMMRegister src) {
1425 XMMRegister idst = {dst.code()};
1426 vsd(0x2c, idst, xmm0, src, kF3, k0F, kW1);
1427 }
1428 void vcvttss2siq(Register dst, const Operand& src) {
1429 XMMRegister idst = {dst.code()};
1430 vsd(0x2c, idst, xmm0, src, kF3, k0F, kW1);
1431 }
1432 void vcvttsd2siq(Register dst, XMMRegister src) {
1433 XMMRegister idst = {dst.code()};
1434 vsd(0x2c, idst, xmm0, src, kF2, k0F, kW1);
1435 }
1436 void vcvttsd2siq(Register dst, const Operand& src) {
1437 XMMRegister idst = {dst.code()};
1438 vsd(0x2c, idst, xmm0, src, kF2, k0F, kW1);
1439 }
1440 void vcvtsd2si(Register dst, XMMRegister src) {
1441 XMMRegister idst = {dst.code()};
1442 vsd(0x2d, idst, xmm0, src, kF2, k0F, kW0);
1443 }
1444 void vucomisd(XMMRegister dst, XMMRegister src) {
1445 vsd(0x2e, dst, xmm0, src, k66, k0F, kWIG);
1446 }
1447 void vucomisd(XMMRegister dst, const Operand& src) {
1448 vsd(0x2e, dst, xmm0, src, k66, k0F, kWIG);
1449 }
1450 void vroundss(XMMRegister dst, XMMRegister src1, XMMRegister src2,
1451 RoundingMode mode) {
1452 vsd(0x0a, dst, src1, src2, k66, k0F3A, kWIG);
1453 emit(static_cast<byte>(mode) | 0x8); // Mask precision exception.
1454 }
1455 void vroundsd(XMMRegister dst, XMMRegister src1, XMMRegister src2,
1456 RoundingMode mode) {
1457 vsd(0x0b, dst, src1, src2, k66, k0F3A, kWIG);
1458 emit(static_cast<byte>(mode) | 0x8); // Mask precision exception.
1459 }
1460
1461 void vsd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1462 vsd(op, dst, src1, src2, kF2, k0F, kWIG);
1463 }
1464 void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2) {
1465 vsd(op, dst, src1, src2, kF2, k0F, kWIG);
1466 }
1467 void vsd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2,
1468 SIMDPrefix pp, LeadingOpcode m, VexW w);
1469 void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2,
1470 SIMDPrefix pp, LeadingOpcode m, VexW w);
1471
1472 void vmovss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1473 vss(0x10, dst, src1, src2);
1474 }
1475 void vmovss(XMMRegister dst, const Operand& src) {
1476 vss(0x10, dst, xmm0, src);
1477 }
1478 void vmovss(const Operand& dst, XMMRegister src) {
1479 vss(0x11, src, xmm0, dst);
1480 }
1481 void vucomiss(XMMRegister dst, XMMRegister src);
1482 void vucomiss(XMMRegister dst, const Operand& src);
1483 void vss(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1484 void vss(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1485
1486 void vmovaps(XMMRegister dst, XMMRegister src) { vps(0x28, dst, xmm0, src); }
1487 void vmovapd(XMMRegister dst, XMMRegister src) { vpd(0x28, dst, xmm0, src); }
1488 void vmovmskpd(Register dst, XMMRegister src) {
1489 XMMRegister idst = {dst.code()};
1490 vpd(0x50, idst, xmm0, src);
1491 }
1492
1493 void vps(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1494 void vps(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1495 void vpd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1496 void vpd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1497
1498 // BMI instruction
1499 void andnq(Register dst, Register src1, Register src2) {
1500 bmi1q(0xf2, dst, src1, src2);
1501 }
1502 void andnq(Register dst, Register src1, const Operand& src2) {
1503 bmi1q(0xf2, dst, src1, src2);
1504 }
1505 void andnl(Register dst, Register src1, Register src2) {
1506 bmi1l(0xf2, dst, src1, src2);
1507 }
1508 void andnl(Register dst, Register src1, const Operand& src2) {
1509 bmi1l(0xf2, dst, src1, src2);
1510 }
1511 void bextrq(Register dst, Register src1, Register src2) {
1512 bmi1q(0xf7, dst, src2, src1);
1513 }
1514 void bextrq(Register dst, const Operand& src1, Register src2) {
1515 bmi1q(0xf7, dst, src2, src1);
1516 }
1517 void bextrl(Register dst, Register src1, Register src2) {
1518 bmi1l(0xf7, dst, src2, src1);
1519 }
1520 void bextrl(Register dst, const Operand& src1, Register src2) {
1521 bmi1l(0xf7, dst, src2, src1);
1522 }
1523 void blsiq(Register dst, Register src) {
1524 Register ireg = {3};
1525 bmi1q(0xf3, ireg, dst, src);
1526 }
1527 void blsiq(Register dst, const Operand& src) {
1528 Register ireg = {3};
1529 bmi1q(0xf3, ireg, dst, src);
1530 }
1531 void blsil(Register dst, Register src) {
1532 Register ireg = {3};
1533 bmi1l(0xf3, ireg, dst, src);
1534 }
1535 void blsil(Register dst, const Operand& src) {
1536 Register ireg = {3};
1537 bmi1l(0xf3, ireg, dst, src);
1538 }
1539 void blsmskq(Register dst, Register src) {
1540 Register ireg = {2};
1541 bmi1q(0xf3, ireg, dst, src);
1542 }
1543 void blsmskq(Register dst, const Operand& src) {
1544 Register ireg = {2};
1545 bmi1q(0xf3, ireg, dst, src);
1546 }
1547 void blsmskl(Register dst, Register src) {
1548 Register ireg = {2};
1549 bmi1l(0xf3, ireg, dst, src);
1550 }
1551 void blsmskl(Register dst, const Operand& src) {
1552 Register ireg = {2};
1553 bmi1l(0xf3, ireg, dst, src);
1554 }
1555 void blsrq(Register dst, Register src) {
1556 Register ireg = {1};
1557 bmi1q(0xf3, ireg, dst, src);
1558 }
1559 void blsrq(Register dst, const Operand& src) {
1560 Register ireg = {1};
1561 bmi1q(0xf3, ireg, dst, src);
1562 }
1563 void blsrl(Register dst, Register src) {
1564 Register ireg = {1};
1565 bmi1l(0xf3, ireg, dst, src);
1566 }
1567 void blsrl(Register dst, const Operand& src) {
1568 Register ireg = {1};
1569 bmi1l(0xf3, ireg, dst, src);
1570 }
1571 void tzcntq(Register dst, Register src);
1572 void tzcntq(Register dst, const Operand& src);
1573 void tzcntl(Register dst, Register src);
1574 void tzcntl(Register dst, const Operand& src);
1575
1576 void lzcntq(Register dst, Register src);
1577 void lzcntq(Register dst, const Operand& src);
1578 void lzcntl(Register dst, Register src);
1579 void lzcntl(Register dst, const Operand& src);
1580
1581 void popcntq(Register dst, Register src);
1582 void popcntq(Register dst, const Operand& src);
1583 void popcntl(Register dst, Register src);
1584 void popcntl(Register dst, const Operand& src);
1585
1586 void bzhiq(Register dst, Register src1, Register src2) {
1587 bmi2q(kNone, 0xf5, dst, src2, src1);
1588 }
1589 void bzhiq(Register dst, const Operand& src1, Register src2) {
1590 bmi2q(kNone, 0xf5, dst, src2, src1);
1591 }
1592 void bzhil(Register dst, Register src1, Register src2) {
1593 bmi2l(kNone, 0xf5, dst, src2, src1);
1594 }
1595 void bzhil(Register dst, const Operand& src1, Register src2) {
1596 bmi2l(kNone, 0xf5, dst, src2, src1);
1597 }
1598 void mulxq(Register dst1, Register dst2, Register src) {
1599 bmi2q(kF2, 0xf6, dst1, dst2, src);
1600 }
1601 void mulxq(Register dst1, Register dst2, const Operand& src) {
1602 bmi2q(kF2, 0xf6, dst1, dst2, src);
1603 }
1604 void mulxl(Register dst1, Register dst2, Register src) {
1605 bmi2l(kF2, 0xf6, dst1, dst2, src);
1606 }
1607 void mulxl(Register dst1, Register dst2, const Operand& src) {
1608 bmi2l(kF2, 0xf6, dst1, dst2, src);
1609 }
1610 void pdepq(Register dst, Register src1, Register src2) {
1611 bmi2q(kF2, 0xf5, dst, src1, src2);
1612 }
1613 void pdepq(Register dst, Register src1, const Operand& src2) {
1614 bmi2q(kF2, 0xf5, dst, src1, src2);
1615 }
1616 void pdepl(Register dst, Register src1, Register src2) {
1617 bmi2l(kF2, 0xf5, dst, src1, src2);
1618 }
1619 void pdepl(Register dst, Register src1, const Operand& src2) {
1620 bmi2l(kF2, 0xf5, dst, src1, src2);
1621 }
1622 void pextq(Register dst, Register src1, Register src2) {
1623 bmi2q(kF3, 0xf5, dst, src1, src2);
1624 }
1625 void pextq(Register dst, Register src1, const Operand& src2) {
1626 bmi2q(kF3, 0xf5, dst, src1, src2);
1627 }
1628 void pextl(Register dst, Register src1, Register src2) {
1629 bmi2l(kF3, 0xf5, dst, src1, src2);
1630 }
1631 void pextl(Register dst, Register src1, const Operand& src2) {
1632 bmi2l(kF3, 0xf5, dst, src1, src2);
1633 }
1634 void sarxq(Register dst, Register src1, Register src2) {
1635 bmi2q(kF3, 0xf7, dst, src2, src1);
1636 }
1637 void sarxq(Register dst, const Operand& src1, Register src2) {
1638 bmi2q(kF3, 0xf7, dst, src2, src1);
1639 }
1640 void sarxl(Register dst, Register src1, Register src2) {
1641 bmi2l(kF3, 0xf7, dst, src2, src1);
1642 }
1643 void sarxl(Register dst, const Operand& src1, Register src2) {
1644 bmi2l(kF3, 0xf7, dst, src2, src1);
1645 }
1646 void shlxq(Register dst, Register src1, Register src2) {
1647 bmi2q(k66, 0xf7, dst, src2, src1);
1648 }
1649 void shlxq(Register dst, const Operand& src1, Register src2) {
1650 bmi2q(k66, 0xf7, dst, src2, src1);
1651 }
1652 void shlxl(Register dst, Register src1, Register src2) {
1653 bmi2l(k66, 0xf7, dst, src2, src1);
1654 }
1655 void shlxl(Register dst, const Operand& src1, Register src2) {
1656 bmi2l(k66, 0xf7, dst, src2, src1);
1657 }
1658 void shrxq(Register dst, Register src1, Register src2) {
1659 bmi2q(kF2, 0xf7, dst, src2, src1);
1660 }
1661 void shrxq(Register dst, const Operand& src1, Register src2) {
1662 bmi2q(kF2, 0xf7, dst, src2, src1);
1663 }
1664 void shrxl(Register dst, Register src1, Register src2) {
1665 bmi2l(kF2, 0xf7, dst, src2, src1);
1666 }
1667 void shrxl(Register dst, const Operand& src1, Register src2) {
1668 bmi2l(kF2, 0xf7, dst, src2, src1);
1669 }
1670 void rorxq(Register dst, Register src, byte imm8);
1671 void rorxq(Register dst, const Operand& src, byte imm8);
1672 void rorxl(Register dst, Register src, byte imm8);
1673 void rorxl(Register dst, const Operand& src, byte imm8);
Steve Blocka7e24c12009-10-30 11:49:00 +00001674
1675 // Check the code size generated from label to here.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001676 int SizeOfCodeGeneratedSince(Label* label) {
1677 return pc_offset() - label->pos();
1678 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001679
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001680 // Mark generator continuation.
1681 void RecordGeneratorContinuation();
Steve Blocka7e24c12009-10-30 11:49:00 +00001682
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001683 // Mark address of a debug break slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001684 void RecordDebugBreakSlot(RelocInfo::Mode mode);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001685
Steve Blocka7e24c12009-10-30 11:49:00 +00001686 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001687 // Use --code-comments to enable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001688 void RecordComment(const char* msg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001689
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001690 // Record a deoptimization reason that can be used by a log or cpu profiler.
1691 // Use --trace-deopt to enable.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001692 void RecordDeoptReason(const int reason, int raw_position);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001693
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001694 void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1695 ConstantPoolEntry::Access access,
1696 ConstantPoolEntry::Type type) {
1697 // No embedded constant pool support.
1698 UNREACHABLE();
1699 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001700
Ben Murdochb0fe1622011-05-05 13:52:32 +01001701 // Writes a single word of data in the code stream.
1702 // Used for inline tables, e.g., jump-tables.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001703 void db(uint8_t data);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001704 void dd(uint32_t data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001705 void dq(uint64_t data);
1706 void dp(uintptr_t data) { dq(data); }
1707 void dq(Label* label);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001708
Ben Murdochda12d292016-06-02 14:46:10 +01001709 AssemblerPositionsRecorder* positions_recorder() {
1710 return &positions_recorder_;
1711 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001712
1713 // Check if there is less than kGap bytes available in the buffer.
1714 // If this is the case, we need to grow the buffer before emitting
1715 // an instruction or relocation information.
1716 inline bool buffer_overflow() const {
1717 return pc_ >= reloc_info_writer.pos() - kGap;
1718 }
1719
1720 // Get the number of bytes available in the buffer.
Steve Blockd0582a62009-12-15 09:54:21 +00001721 inline int available_space() const {
1722 return static_cast<int>(reloc_info_writer.pos() - pc_);
1723 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001724
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001725 static bool IsNop(Address addr);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001726
Steve Blocka7e24c12009-10-30 11:49:00 +00001727 // Avoid overflows for displacements etc.
1728 static const int kMaximalBufferSize = 512*MB;
Steve Blocka7e24c12009-10-30 11:49:00 +00001729
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001730 byte byte_at(int pos) { return buffer_[pos]; }
1731 void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1732
Steve Block44f0eee2011-05-26 01:26:41 +01001733 protected:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001734 // Call near indirect
1735 void call(const Operand& operand);
1736
Steve Blocka7e24c12009-10-30 11:49:00 +00001737 private:
1738 byte* addr_at(int pos) { return buffer_ + pos; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001739 uint32_t long_at(int pos) {
1740 return *reinterpret_cast<uint32_t*>(addr_at(pos));
1741 }
1742 void long_at_put(int pos, uint32_t x) {
1743 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1744 }
1745
1746 // code emission
1747 void GrowBuffer();
1748
1749 void emit(byte x) { *pc_++ = x; }
1750 inline void emitl(uint32_t x);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001751 inline void emitp(void* x, RelocInfo::Mode rmode);
1752 inline void emitq(uint64_t x);
Steve Blocka7e24c12009-10-30 11:49:00 +00001753 inline void emitw(uint16_t x);
Ben Murdoch257744e2011-11-30 15:57:28 +00001754 inline void emit_code_target(Handle<Code> target,
1755 RelocInfo::Mode rmode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001756 TypeFeedbackId ast_id = TypeFeedbackId::None());
1757 inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001758 void emit(Immediate x) { emitl(x.value_); }
1759
1760 // Emits a REX prefix that encodes a 64-bit operand size and
1761 // the top bit of both register codes.
1762 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1763 // REX.W is set.
Steve Blocka7e24c12009-10-30 11:49:00 +00001764 inline void emit_rex_64(XMMRegister reg, Register rm_reg);
Steve Block6ded16b2010-05-10 14:33:55 +01001765 inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1766 inline void emit_rex_64(Register reg, Register rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001767
1768 // Emits a REX prefix that encodes a 64-bit operand size and
1769 // the top bit of the destination, index, and base register codes.
1770 // The high bit of reg is used for REX.R, the high bit of op's base
1771 // register is used for REX.B, and the high bit of op's index register
1772 // is used for REX.X. REX.W is set.
1773 inline void emit_rex_64(Register reg, const Operand& op);
1774 inline void emit_rex_64(XMMRegister reg, const Operand& op);
1775
1776 // Emits a REX prefix that encodes a 64-bit operand size and
1777 // the top bit of the register code.
1778 // The high bit of register is used for REX.B.
1779 // REX.W is set and REX.R and REX.X are clear.
1780 inline void emit_rex_64(Register rm_reg);
1781
1782 // Emits a REX prefix that encodes a 64-bit operand size and
1783 // the top bit of the index and base register codes.
1784 // The high bit of op's base register is used for REX.B, and the high
1785 // bit of op's index register is used for REX.X.
1786 // REX.W is set and REX.R clear.
1787 inline void emit_rex_64(const Operand& op);
1788
1789 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1790 void emit_rex_64() { emit(0x48); }
1791
1792 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1793 // REX.W is clear.
1794 inline void emit_rex_32(Register reg, Register rm_reg);
1795
1796 // The high bit of reg is used for REX.R, the high bit of op's base
1797 // register is used for REX.B, and the high bit of op's index register
1798 // is used for REX.X. REX.W is cleared.
1799 inline void emit_rex_32(Register reg, const Operand& op);
1800
1801 // High bit of rm_reg goes to REX.B.
1802 // REX.W, REX.R and REX.X are clear.
1803 inline void emit_rex_32(Register rm_reg);
1804
1805 // High bit of base goes to REX.B and high bit of index to REX.X.
1806 // REX.W and REX.R are clear.
1807 inline void emit_rex_32(const Operand& op);
1808
1809 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1810 // REX.W is cleared. If no REX bits are set, no byte is emitted.
1811 inline void emit_optional_rex_32(Register reg, Register rm_reg);
1812
1813 // The high bit of reg is used for REX.R, the high bit of op's base
1814 // register is used for REX.B, and the high bit of op's index register
1815 // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
1816 // is emitted.
1817 inline void emit_optional_rex_32(Register reg, const Operand& op);
1818
1819 // As for emit_optional_rex_32(Register, Register), except that
1820 // the registers are XMM registers.
1821 inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1822
1823 // As for emit_optional_rex_32(Register, Register), except that
Steve Block6ded16b2010-05-10 14:33:55 +01001824 // one of the registers is an XMM registers.
Steve Blocka7e24c12009-10-30 11:49:00 +00001825 inline void emit_optional_rex_32(XMMRegister reg, Register base);
1826
Steve Block6ded16b2010-05-10 14:33:55 +01001827 // As for emit_optional_rex_32(Register, Register), except that
1828 // one of the registers is an XMM registers.
1829 inline void emit_optional_rex_32(Register reg, XMMRegister base);
1830
Steve Blocka7e24c12009-10-30 11:49:00 +00001831 // As for emit_optional_rex_32(Register, const Operand&), except that
1832 // the register is an XMM register.
1833 inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1834
1835 // Optionally do as emit_rex_32(Register) if the register number has
1836 // the high bit set.
1837 inline void emit_optional_rex_32(Register rm_reg);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001838 inline void emit_optional_rex_32(XMMRegister rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001839
1840 // Optionally do as emit_rex_32(const Operand&) if the operand register
1841 // numbers have a high bit set.
1842 inline void emit_optional_rex_32(const Operand& op);
1843
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001844 void emit_rex(int size) {
1845 if (size == kInt64Size) {
1846 emit_rex_64();
1847 } else {
1848 DCHECK(size == kInt32Size);
1849 }
1850 }
1851
1852 template<class P1>
1853 void emit_rex(P1 p1, int size) {
1854 if (size == kInt64Size) {
1855 emit_rex_64(p1);
1856 } else {
1857 DCHECK(size == kInt32Size);
1858 emit_optional_rex_32(p1);
1859 }
1860 }
1861
1862 template<class P1, class P2>
1863 void emit_rex(P1 p1, P2 p2, int size) {
1864 if (size == kInt64Size) {
1865 emit_rex_64(p1, p2);
1866 } else {
1867 DCHECK(size == kInt32Size);
1868 emit_optional_rex_32(p1, p2);
1869 }
1870 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001871
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001872 // Emit vex prefix
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001873 void emit_vex2_byte0() { emit(0xc5); }
1874 inline void emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
1875 SIMDPrefix pp);
1876 void emit_vex3_byte0() { emit(0xc4); }
1877 inline void emit_vex3_byte1(XMMRegister reg, XMMRegister rm, LeadingOpcode m);
1878 inline void emit_vex3_byte1(XMMRegister reg, const Operand& rm,
1879 LeadingOpcode m);
1880 inline void emit_vex3_byte2(VexW w, XMMRegister v, VectorLength l,
1881 SIMDPrefix pp);
1882 inline void emit_vex_prefix(XMMRegister reg, XMMRegister v, XMMRegister rm,
1883 VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1884 VexW w);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001885 inline void emit_vex_prefix(Register reg, Register v, Register rm,
1886 VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1887 VexW w);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001888 inline void emit_vex_prefix(XMMRegister reg, XMMRegister v, const Operand& rm,
1889 VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1890 VexW w);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001891 inline void emit_vex_prefix(Register reg, Register v, const Operand& rm,
1892 VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1893 VexW w);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001894
Steve Blocka7e24c12009-10-30 11:49:00 +00001895 // Emit the ModR/M byte, and optionally the SIB byte and
1896 // 1- or 4-byte offset for a memory operand. Also encodes
1897 // the second operand of the operation, a register or operation
1898 // subcode, into the reg field of the ModR/M byte.
1899 void emit_operand(Register reg, const Operand& adr) {
1900 emit_operand(reg.low_bits(), adr);
1901 }
1902
1903 // Emit the ModR/M byte, and optionally the SIB byte and
1904 // 1- or 4-byte offset for a memory operand. Also used to encode
1905 // a three-bit opcode extension into the ModR/M byte.
1906 void emit_operand(int rm, const Operand& adr);
1907
1908 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1909 void emit_modrm(Register reg, Register rm_reg) {
1910 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1911 }
1912
1913 // Emit a ModR/M byte with an operation subcode in the reg field and
1914 // a register in the rm_reg field.
1915 void emit_modrm(int code, Register rm_reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001916 DCHECK(is_uint3(code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001917 emit(0xC0 | code << 3 | rm_reg.low_bits());
1918 }
1919
1920 // Emit the code-object-relative offset of the label's position
1921 inline void emit_code_relative_offset(Label* label);
1922
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001923 // The first argument is the reg field, the second argument is the r/m field.
1924 void emit_sse_operand(XMMRegister dst, XMMRegister src);
1925 void emit_sse_operand(XMMRegister reg, const Operand& adr);
1926 void emit_sse_operand(Register reg, const Operand& adr);
1927 void emit_sse_operand(XMMRegister dst, Register src);
1928 void emit_sse_operand(Register dst, XMMRegister src);
1929
Steve Blocka7e24c12009-10-30 11:49:00 +00001930 // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1931 // AND, OR, XOR, or CMP. The encodings of these operations are all
1932 // similar, differing just in the opcode or in the reg field of the
1933 // ModR/M byte.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001934 void arithmetic_op_8(byte opcode, Register reg, Register rm_reg);
1935 void arithmetic_op_8(byte opcode, Register reg, const Operand& rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001936 void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1937 void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001938 // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
1939 void arithmetic_op(byte opcode, Register reg, Register rm_reg, int size);
1940 void arithmetic_op(byte opcode,
1941 Register reg,
1942 const Operand& rm_reg,
1943 int size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001944 // Operate on a byte in memory or register.
1945 void immediate_arithmetic_op_8(byte subcode,
1946 Register dst,
1947 Immediate src);
1948 void immediate_arithmetic_op_8(byte subcode,
1949 const Operand& dst,
1950 Immediate src);
1951 // Operate on a word in memory or register.
1952 void immediate_arithmetic_op_16(byte subcode,
1953 Register dst,
1954 Immediate src);
1955 void immediate_arithmetic_op_16(byte subcode,
1956 const Operand& dst,
1957 Immediate src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001958 // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
1959 void immediate_arithmetic_op(byte subcode,
1960 Register dst,
1961 Immediate src,
1962 int size);
1963 void immediate_arithmetic_op(byte subcode,
1964 const Operand& dst,
1965 Immediate src,
1966 int size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001967
1968 // Emit machine code for a shift operation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001969 void shift(Operand dst, Immediate shift_amount, int subcode, int size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001970 void shift(Register dst, Immediate shift_amount, int subcode, int size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001971 // Shift dst by cl % 64 bits.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001972 void shift(Register dst, int subcode, int size);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001973 void shift(Operand dst, int subcode, int size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001974
1975 void emit_farith(int b1, int b2, int i);
1976
1977 // labels
1978 // void print(Label* L);
1979 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001980
1981 // record reloc info for current pc_
1982 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1983
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001984 // Arithmetics
1985 void emit_add(Register dst, Register src, int size) {
1986 arithmetic_op(0x03, dst, src, size);
1987 }
1988
1989 void emit_add(Register dst, Immediate src, int size) {
1990 immediate_arithmetic_op(0x0, dst, src, size);
1991 }
1992
1993 void emit_add(Register dst, const Operand& src, int size) {
1994 arithmetic_op(0x03, dst, src, size);
1995 }
1996
1997 void emit_add(const Operand& dst, Register src, int size) {
1998 arithmetic_op(0x1, src, dst, size);
1999 }
2000
2001 void emit_add(const Operand& dst, Immediate src, int size) {
2002 immediate_arithmetic_op(0x0, dst, src, size);
2003 }
2004
2005 void emit_and(Register dst, Register src, int size) {
2006 arithmetic_op(0x23, dst, src, size);
2007 }
2008
2009 void emit_and(Register dst, const Operand& src, int size) {
2010 arithmetic_op(0x23, dst, src, size);
2011 }
2012
2013 void emit_and(const Operand& dst, Register src, int size) {
2014 arithmetic_op(0x21, src, dst, size);
2015 }
2016
2017 void emit_and(Register dst, Immediate src, int size) {
2018 immediate_arithmetic_op(0x4, dst, src, size);
2019 }
2020
2021 void emit_and(const Operand& dst, Immediate src, int size) {
2022 immediate_arithmetic_op(0x4, dst, src, size);
2023 }
2024
2025 void emit_cmp(Register dst, Register src, int size) {
2026 arithmetic_op(0x3B, dst, src, size);
2027 }
2028
2029 void emit_cmp(Register dst, const Operand& src, int size) {
2030 arithmetic_op(0x3B, dst, src, size);
2031 }
2032
2033 void emit_cmp(const Operand& dst, Register src, int size) {
2034 arithmetic_op(0x39, src, dst, size);
2035 }
2036
2037 void emit_cmp(Register dst, Immediate src, int size) {
2038 immediate_arithmetic_op(0x7, dst, src, size);
2039 }
2040
2041 void emit_cmp(const Operand& dst, Immediate src, int size) {
2042 immediate_arithmetic_op(0x7, dst, src, size);
2043 }
2044
2045 void emit_dec(Register dst, int size);
2046 void emit_dec(const Operand& dst, int size);
2047
2048 // Divide rdx:rax by src. Quotient in rax, remainder in rdx when size is 64.
2049 // Divide edx:eax by lower 32 bits of src. Quotient in eax, remainder in edx
2050 // when size is 32.
2051 void emit_idiv(Register src, int size);
2052 void emit_div(Register src, int size);
2053
2054 // Signed multiply instructions.
2055 // rdx:rax = rax * src when size is 64 or edx:eax = eax * src when size is 32.
2056 void emit_imul(Register src, int size);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002057 void emit_imul(const Operand& src, int size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002058 void emit_imul(Register dst, Register src, int size);
2059 void emit_imul(Register dst, const Operand& src, int size);
2060 void emit_imul(Register dst, Register src, Immediate imm, int size);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002061 void emit_imul(Register dst, const Operand& src, Immediate imm, int size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002062
2063 void emit_inc(Register dst, int size);
2064 void emit_inc(const Operand& dst, int size);
2065
2066 void emit_lea(Register dst, const Operand& src, int size);
2067
2068 void emit_mov(Register dst, const Operand& src, int size);
2069 void emit_mov(Register dst, Register src, int size);
2070 void emit_mov(const Operand& dst, Register src, int size);
2071 void emit_mov(Register dst, Immediate value, int size);
2072 void emit_mov(const Operand& dst, Immediate value, int size);
2073
2074 void emit_movzxb(Register dst, const Operand& src, int size);
2075 void emit_movzxb(Register dst, Register src, int size);
2076 void emit_movzxw(Register dst, const Operand& src, int size);
2077 void emit_movzxw(Register dst, Register src, int size);
2078
2079 void emit_neg(Register dst, int size);
2080 void emit_neg(const Operand& dst, int size);
2081
2082 void emit_not(Register dst, int size);
2083 void emit_not(const Operand& dst, int size);
2084
2085 void emit_or(Register dst, Register src, int size) {
2086 arithmetic_op(0x0B, dst, src, size);
2087 }
2088
2089 void emit_or(Register dst, const Operand& src, int size) {
2090 arithmetic_op(0x0B, dst, src, size);
2091 }
2092
2093 void emit_or(const Operand& dst, Register src, int size) {
2094 arithmetic_op(0x9, src, dst, size);
2095 }
2096
2097 void emit_or(Register dst, Immediate src, int size) {
2098 immediate_arithmetic_op(0x1, dst, src, size);
2099 }
2100
2101 void emit_or(const Operand& dst, Immediate src, int size) {
2102 immediate_arithmetic_op(0x1, dst, src, size);
2103 }
2104
2105 void emit_repmovs(int size);
2106
2107 void emit_sbb(Register dst, Register src, int size) {
2108 arithmetic_op(0x1b, dst, src, size);
2109 }
2110
2111 void emit_sub(Register dst, Register src, int size) {
2112 arithmetic_op(0x2B, dst, src, size);
2113 }
2114
2115 void emit_sub(Register dst, Immediate src, int size) {
2116 immediate_arithmetic_op(0x5, dst, src, size);
2117 }
2118
2119 void emit_sub(Register dst, const Operand& src, int size) {
2120 arithmetic_op(0x2B, dst, src, size);
2121 }
2122
2123 void emit_sub(const Operand& dst, Register src, int size) {
2124 arithmetic_op(0x29, src, dst, size);
2125 }
2126
2127 void emit_sub(const Operand& dst, Immediate src, int size) {
2128 immediate_arithmetic_op(0x5, dst, src, size);
2129 }
2130
2131 void emit_test(Register dst, Register src, int size);
2132 void emit_test(Register reg, Immediate mask, int size);
2133 void emit_test(const Operand& op, Register reg, int size);
2134 void emit_test(const Operand& op, Immediate mask, int size);
2135 void emit_test(Register reg, const Operand& op, int size) {
2136 return emit_test(op, reg, size);
2137 }
2138
2139 void emit_xchg(Register dst, Register src, int size);
2140 void emit_xchg(Register dst, const Operand& src, int size);
2141
2142 void emit_xor(Register dst, Register src, int size) {
2143 if (size == kInt64Size && dst.code() == src.code()) {
2144 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
2145 // there is no need to make this a 64 bit operation.
2146 arithmetic_op(0x33, dst, src, kInt32Size);
2147 } else {
2148 arithmetic_op(0x33, dst, src, size);
2149 }
2150 }
2151
2152 void emit_xor(Register dst, const Operand& src, int size) {
2153 arithmetic_op(0x33, dst, src, size);
2154 }
2155
2156 void emit_xor(Register dst, Immediate src, int size) {
2157 immediate_arithmetic_op(0x6, dst, src, size);
2158 }
2159
2160 void emit_xor(const Operand& dst, Immediate src, int size) {
2161 immediate_arithmetic_op(0x6, dst, src, size);
2162 }
2163
2164 void emit_xor(const Operand& dst, Register src, int size) {
2165 arithmetic_op(0x31, src, dst, size);
2166 }
2167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002168 // Most BMI instructions are similiar.
2169 void bmi1q(byte op, Register reg, Register vreg, Register rm);
2170 void bmi1q(byte op, Register reg, Register vreg, const Operand& rm);
2171 void bmi1l(byte op, Register reg, Register vreg, Register rm);
2172 void bmi1l(byte op, Register reg, Register vreg, const Operand& rm);
2173 void bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg, Register rm);
2174 void bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg,
2175 const Operand& rm);
2176 void bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg, Register rm);
2177 void bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg,
2178 const Operand& rm);
2179
Steve Blocka7e24c12009-10-30 11:49:00 +00002180 friend class CodePatcher;
2181 friend class EnsureSpace;
2182 friend class RegExpMacroAssemblerX64;
2183
Steve Blocka7e24c12009-10-30 11:49:00 +00002184 // code generation
Steve Blocka7e24c12009-10-30 11:49:00 +00002185 RelocInfoWriter reloc_info_writer;
2186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002187 // Internal reference positions, required for (potential) patching in
2188 // GrowBuffer(); contains only those internal references whose labels
2189 // are already bound.
2190 std::deque<int> internal_reference_positions_;
2191
Steve Block3ce2e202009-11-05 08:53:23 +00002192 List< Handle<Code> > code_targets_;
Steve Blocka7e24c12009-10-30 11:49:00 +00002193
Ben Murdochda12d292016-06-02 14:46:10 +01002194 AssemblerPositionsRecorder positions_recorder_;
2195 friend class AssemblerPositionsRecorder;
Steve Blocka7e24c12009-10-30 11:49:00 +00002196};
2197
2198
2199// Helper class that ensures that there is enough space for generating
2200// instructions and relocation information. The constructor makes
2201// sure that there is enough space and (in debug mode) the destructor
2202// checks that we did not generate too much.
2203class EnsureSpace BASE_EMBEDDED {
2204 public:
2205 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
2206 if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
2207#ifdef DEBUG
2208 space_before_ = assembler_->available_space();
2209#endif
2210 }
2211
2212#ifdef DEBUG
2213 ~EnsureSpace() {
2214 int bytes_generated = space_before_ - assembler_->available_space();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002215 DCHECK(bytes_generated < assembler_->kGap);
Steve Blocka7e24c12009-10-30 11:49:00 +00002216 }
2217#endif
2218
2219 private:
2220 Assembler* assembler_;
2221#ifdef DEBUG
2222 int space_before_;
2223#endif
2224};
2225
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002226} // namespace internal
2227} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +00002228
2229#endif // V8_X64_ASSEMBLER_X64_H_