blob: 799fa6fe9d773c6654126aefc145182a8ae01d3a [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
Steve Blocka7e24c12009-10-30 11:49:00 +0000251enum Condition {
252 // any value < 0 is considered no_condition
253 no_condition = -1,
254
255 overflow = 0,
256 no_overflow = 1,
257 below = 2,
258 above_equal = 3,
259 equal = 4,
260 not_equal = 5,
261 below_equal = 6,
262 above = 7,
263 negative = 8,
264 positive = 9,
265 parity_even = 10,
266 parity_odd = 11,
267 less = 12,
268 greater_equal = 13,
269 less_equal = 14,
270 greater = 15,
271
Steve Block3ce2e202009-11-05 08:53:23 +0000272 // Fake conditions that are handled by the
273 // opcodes using them.
274 always = 16,
275 never = 17,
Steve Blocka7e24c12009-10-30 11:49:00 +0000276 // aliases
277 carry = below,
278 not_carry = above_equal,
279 zero = equal,
280 not_zero = not_equal,
281 sign = negative,
Steve Block3ce2e202009-11-05 08:53:23 +0000282 not_sign = positive,
283 last_condition = greater
Steve Blocka7e24c12009-10-30 11:49:00 +0000284};
285
286
287// Returns the equivalent of !cc.
288// Negation of the default no_condition (-1) results in a non-default
289// no_condition value (-2). As long as tests for no_condition check
290// for condition < 0, this will work as expected.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100291inline Condition NegateCondition(Condition cc) {
292 return static_cast<Condition>(cc ^ 1);
293}
294
Steve Blocka7e24c12009-10-30 11:49:00 +0000295
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296// Commute a condition such that {a cond b == b cond' a}.
297inline Condition CommuteCondition(Condition cc) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000298 switch (cc) {
299 case below:
300 return above;
301 case above:
302 return below;
303 case above_equal:
304 return below_equal;
305 case below_equal:
306 return above_equal;
307 case less:
308 return greater;
309 case greater:
310 return less;
311 case greater_equal:
312 return less_equal;
313 case less_equal:
314 return greater_equal;
315 default:
316 return cc;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000317 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000318}
319
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100320
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321enum RoundingMode {
322 kRoundToNearest = 0x0,
323 kRoundDown = 0x1,
324 kRoundUp = 0x2,
325 kRoundToZero = 0x3
326};
327
328
Steve Blocka7e24c12009-10-30 11:49:00 +0000329// -----------------------------------------------------------------------------
330// Machine instruction Immediates
331
332class Immediate BASE_EMBEDDED {
333 public:
334 explicit Immediate(int32_t value) : value_(value) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 explicit Immediate(Smi* value) {
336 DCHECK(SmiValuesAre31Bits()); // Only available for 31-bit SMI.
337 value_ = static_cast<int32_t>(reinterpret_cast<intptr_t>(value));
338 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000339
340 private:
341 int32_t value_;
342
343 friend class Assembler;
344};
345
346
347// -----------------------------------------------------------------------------
348// Machine instruction Operands
349
350enum ScaleFactor {
351 times_1 = 0,
352 times_2 = 1,
353 times_4 = 2,
354 times_8 = 3,
355 times_int_size = times_4,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356 times_pointer_size = (kPointerSize == 8) ? times_8 : times_4
Steve Blocka7e24c12009-10-30 11:49:00 +0000357};
358
359
360class Operand BASE_EMBEDDED {
361 public:
362 // [base + disp/r]
363 Operand(Register base, int32_t disp);
364
365 // [base + index*scale + disp/r]
366 Operand(Register base,
367 Register index,
368 ScaleFactor scale,
369 int32_t disp);
370
371 // [index*scale + disp/r]
372 Operand(Register index,
373 ScaleFactor scale,
374 int32_t disp);
375
Leon Clarkef7060e22010-06-03 12:02:55 +0100376 // Offset from existing memory operand.
377 // Offset is added to existing displacement as 32-bit signed values and
378 // this must not overflow.
379 Operand(const Operand& base, int32_t offset);
380
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 // [rip + disp/r]
382 explicit Operand(Label* label);
383
Steve Block1e0659c2011-05-24 12:43:12 +0100384 // Checks whether either base or index register is the given register.
385 // Does not check the "reg" part of the Operand.
386 bool AddressUsesRegister(Register reg) const;
387
Steve Block44f0eee2011-05-26 01:26:41 +0100388 // Queries related to the size of the generated instruction.
389 // Whether the generated instruction will have a REX prefix.
390 bool requires_rex() const { return rex_ != 0; }
391 // Size of the ModR/M, SIB and displacement parts of the generated
392 // instruction.
393 int operand_size() const { return len_; }
394
Steve Blocka7e24c12009-10-30 11:49:00 +0000395 private:
396 byte rex_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000397 byte buf_[9];
Steve Block1e0659c2011-05-24 12:43:12 +0100398 // The number of bytes of buf_ in use.
399 byte len_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000400
401 // Set the ModR/M byte without an encoded 'reg' register. The
402 // register is encoded later as part of the emit_operand operation.
403 // set_modrm can be called before or after set_sib and set_disp*.
404 inline void set_modrm(int mod, Register rm);
405
406 // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
407 inline void set_sib(ScaleFactor scale, Register index, Register base);
408
409 // Adds operand displacement fields (offsets added to the memory address).
410 // Needs to be called after set_sib, not before it.
411 inline void set_disp8(int disp);
412 inline void set_disp32(int disp);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000413 inline void set_disp64(int64_t disp); // for labels.
Steve Blocka7e24c12009-10-30 11:49:00 +0000414
415 friend class Assembler;
416};
417
418
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000419#define ASSEMBLER_INSTRUCTION_LIST(V) \
420 V(add) \
421 V(and) \
422 V(cmp) \
423 V(dec) \
424 V(idiv) \
425 V(div) \
426 V(imul) \
427 V(inc) \
428 V(lea) \
429 V(mov) \
430 V(movzxb) \
431 V(movzxw) \
432 V(neg) \
433 V(not) \
434 V(or) \
435 V(repmovs) \
436 V(sbb) \
437 V(sub) \
438 V(test) \
439 V(xchg) \
440 V(xor)
Steve Block44f0eee2011-05-26 01:26:41 +0100441
Ben Murdoch8b112d22011-06-08 16:22:53 +0100442
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443// Shift instructions on operands/registers with kPointerSize, kInt32Size and
444// kInt64Size.
445#define SHIFT_INSTRUCTION_LIST(V) \
446 V(rol, 0x0) \
447 V(ror, 0x1) \
448 V(rcl, 0x2) \
449 V(rcr, 0x3) \
450 V(shl, 0x4) \
451 V(shr, 0x5) \
452 V(sar, 0x7) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000453
454
Steve Block44f0eee2011-05-26 01:26:41 +0100455class Assembler : public AssemblerBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000456 private:
457 // We check before assembling an instruction that there is sufficient
458 // space to write an instruction and its relocation information.
459 // The relocation writer's position must be kGap bytes above the end of
460 // the generated instructions. This leaves enough space for the
461 // longest possible x64 instruction, 15 bytes, and the longest possible
462 // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
463 // (There is a 15 byte limit on x64 instruction length that rules out some
464 // otherwise valid instructions.)
465 // This allows for a single, fast space check per instruction.
466 static const int kGap = 32;
467
468 public:
469 // Create an assembler. Instructions and relocation information are emitted
470 // into a buffer, with the instructions starting from the beginning and the
471 // relocation information starting from the end of the buffer. See CodeDesc
472 // for a detailed comment on the layout (globals.h).
473 //
474 // If the provided buffer is NULL, the assembler allocates and grows its own
475 // buffer, and buffer_size determines the initial buffer size. The buffer is
476 // owned by the assembler and deallocated upon destruction of the assembler.
477 //
478 // If the provided buffer is not NULL, the assembler uses the provided buffer
479 // for code generation and assumes its size to be buffer_size. If the buffer
480 // is too small, a fatal error occurs. No deallocation of the buffer is done
481 // upon destruction of the assembler.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100482 Assembler(Isolate* isolate, void* buffer, int buffer_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000483 virtual ~Assembler() { }
Steve Block44f0eee2011-05-26 01:26:41 +0100484
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 // GetCode emits any pending (non-emitted) code and fills the descriptor
486 // desc. GetCode() is idempotent; it returns the same result if no other
487 // Assembler functions are invoked in between GetCode() calls.
488 void GetCode(CodeDesc* desc);
489
Steve Block3ce2e202009-11-05 08:53:23 +0000490 // Read/Modify the code target in the relative branch/call instruction at pc.
491 // On the x64 architecture, we use relative jumps with a 32-bit displacement
492 // to jump to other Code objects in the Code space in the heap.
493 // Jumps to C functions are done indirectly through a 64-bit register holding
494 // the absolute address of the target.
495 // These functions convert between absolute Addresses of Code objects and
496 // the relative displacements stored in the code.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000497 static inline Address target_address_at(Address pc, Address constant_pool);
498 static inline void set_target_address_at(
499 Isolate* isolate, Address pc, Address constant_pool, Address target,
500 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 static inline Address target_address_at(Address pc, Code* code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000502 Address constant_pool = code ? code->constant_pool() : NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 return target_address_at(pc, constant_pool);
504 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505 static inline void set_target_address_at(
506 Isolate* isolate, Address pc, Code* code, Address target,
507 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED) {
508 Address constant_pool = code ? code->constant_pool() : NULL;
509 set_target_address_at(isolate, pc, constant_pool, target,
510 icache_flush_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 }
512
513 // Return the code target address at a call site from the return address
514 // of that call in the instruction stream.
515 static inline Address target_address_from_return_address(Address pc);
516
Steve Blockd0582a62009-12-15 09:54:21 +0000517 // This sets the branch destination (which is in the instruction on x64).
518 // This is for calls and branches within generated code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100519 inline static void deserialization_set_special_target_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520 Isolate* isolate, Address instruction_payload, Code* code,
521 Address target) {
522 set_target_address_at(isolate, instruction_payload, code, target);
Steve Blockd0582a62009-12-15 09:54:21 +0000523 }
524
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525 // This sets the internal reference at the pc.
526 inline static void deserialization_set_target_internal_reference_at(
527 Isolate* isolate, Address pc, Address target,
528 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
529
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000530 static inline RelocInfo::Mode RelocInfoNone() {
531 if (kPointerSize == kInt64Size) {
532 return RelocInfo::NONE64;
533 } else {
534 DCHECK(kPointerSize == kInt32Size);
535 return RelocInfo::NONE32;
536 }
Steve Blockd0582a62009-12-15 09:54:21 +0000537 }
538
Steve Block3ce2e202009-11-05 08:53:23 +0000539 inline Handle<Object> code_target_object_handle_at(Address pc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000540 inline Address runtime_entry_at(Address pc);
Steve Blockd0582a62009-12-15 09:54:21 +0000541 // Number of bytes taken up by the branch target in the code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100542 static const int kSpecialTargetSize = 4; // Use 32-bit displacement.
Steve Blocka7e24c12009-10-30 11:49:00 +0000543 // Distance between the address of the code target in the call instruction
Steve Block3ce2e202009-11-05 08:53:23 +0000544 // and the return address pushed on the stack.
545 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000546 // The length of call(kScratchRegister).
547 static const int kCallScratchRegisterInstructionLength = 3;
548 // The length of call(Immediate32).
Steve Block1e0659c2011-05-24 12:43:12 +0100549 static const int kShortCallInstructionLength = 5;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000550 // The length of movq(kScratchRegister, address).
551 static const int kMoveAddressIntoScratchRegisterInstructionLength =
552 2 + kPointerSize;
553 // The length of movq(kScratchRegister, address) and call(kScratchRegister).
554 static const int kCallSequenceLength =
555 kMoveAddressIntoScratchRegisterInstructionLength +
556 kCallScratchRegisterInstructionLength;
Steve Blockd0582a62009-12-15 09:54:21 +0000557
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 // The debug break slot must be able to contain an indirect call sequence.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 static const int kDebugBreakSlotLength = kCallSequenceLength;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 // Distance between start of patched debug break slot and the emitted address
561 // to jump to.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000562 static const int kPatchDebugBreakSlotAddressOffset =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000563 kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100564
Steve Block9fac8402011-05-12 15:51:54 +0100565 // One byte opcode for test eax,0xXXXXXXXX.
566 static const byte kTestEaxByte = 0xA9;
Steve Block1e0659c2011-05-24 12:43:12 +0100567 // One byte opcode for test al, 0xXX.
568 static const byte kTestAlByte = 0xA8;
569 // One byte opcode for nop.
570 static const byte kNopByte = 0x90;
571
572 // One byte prefix for a short conditional jump.
573 static const byte kJccShortPrefix = 0x70;
574 static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
575 static const byte kJcShortOpcode = kJccShortPrefix | carry;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576 static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
577 static const byte kJzShortOpcode = kJccShortPrefix | zero;
Steve Block1e0659c2011-05-24 12:43:12 +0100578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 // VEX prefix encodings.
580 enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 };
581 enum VectorLength { kL128 = 0x0, kL256 = 0x4, kLIG = kL128, kLZ = kL128 };
582 enum VexW { kW0 = 0x0, kW1 = 0x80, kWIG = kW0 };
583 enum LeadingOpcode { k0F = 0x1, k0F38 = 0x2, k0F3A = 0x3 };
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100584
Steve Blocka7e24c12009-10-30 11:49:00 +0000585 // ---------------------------------------------------------------------------
586 // Code generation
587 //
588 // Function names correspond one-to-one to x64 instruction mnemonics.
589 // Unless specified otherwise, instructions operate on 64-bit operands.
590 //
591 // If we need versions of an assembly instruction that operate on different
592 // width arguments, we add a single-letter suffix specifying the width.
593 // This is done for the following instructions: mov, cmp, inc, dec,
594 // add, sub, and test.
595 // There are no versions of these instructions without the suffix.
596 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
597 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
598 // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
599 // - Instructions on 64-bit (quadword) operands/registers use 'q'.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 // - Instructions on operands/registers with pointer size use 'p'.
601
602 STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
603
604#define DECLARE_INSTRUCTION(instruction) \
605 template<class P1> \
606 void instruction##p(P1 p1) { \
607 emit_##instruction(p1, kPointerSize); \
608 } \
609 \
610 template<class P1> \
611 void instruction##l(P1 p1) { \
612 emit_##instruction(p1, kInt32Size); \
613 } \
614 \
615 template<class P1> \
616 void instruction##q(P1 p1) { \
617 emit_##instruction(p1, kInt64Size); \
618 } \
619 \
620 template<class P1, class P2> \
621 void instruction##p(P1 p1, P2 p2) { \
622 emit_##instruction(p1, p2, kPointerSize); \
623 } \
624 \
625 template<class P1, class P2> \
626 void instruction##l(P1 p1, P2 p2) { \
627 emit_##instruction(p1, p2, kInt32Size); \
628 } \
629 \
630 template<class P1, class P2> \
631 void instruction##q(P1 p1, P2 p2) { \
632 emit_##instruction(p1, p2, kInt64Size); \
633 } \
634 \
635 template<class P1, class P2, class P3> \
636 void instruction##p(P1 p1, P2 p2, P3 p3) { \
637 emit_##instruction(p1, p2, p3, kPointerSize); \
638 } \
639 \
640 template<class P1, class P2, class P3> \
641 void instruction##l(P1 p1, P2 p2, P3 p3) { \
642 emit_##instruction(p1, p2, p3, kInt32Size); \
643 } \
644 \
645 template<class P1, class P2, class P3> \
646 void instruction##q(P1 p1, P2 p2, P3 p3) { \
647 emit_##instruction(p1, p2, p3, kInt64Size); \
648 }
649 ASSEMBLER_INSTRUCTION_LIST(DECLARE_INSTRUCTION)
650#undef DECLARE_INSTRUCTION
Steve Blocka7e24c12009-10-30 11:49:00 +0000651
652 // Insert the smallest number of nop instructions
653 // possible to align the pc offset to a multiple
Steve Block1e0659c2011-05-24 12:43:12 +0100654 // of m, where m must be a power of 2.
Steve Blocka7e24c12009-10-30 11:49:00 +0000655 void Align(int m);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656 // Insert the smallest number of zero bytes possible to align the pc offset
657 // to a mulitple of m. m must be a power of 2 (>= 2).
658 void DataAlign(int m);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100659 void Nop(int bytes = 1);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100660 // Aligns code to something that's optimal for a jump target for the platform.
661 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000662
663 // Stack
664 void pushfq();
665 void popfq();
666
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667 void pushq(Immediate value);
Steve Block1e0659c2011-05-24 12:43:12 +0100668 // Push a 32 bit integer, and guarantee that it is actually pushed as a
669 // 32 bit value, the normal push will optimize the 8 bit case.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670 void pushq_imm32(int32_t imm32);
671 void pushq(Register src);
672 void pushq(const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000673
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000674 void popq(Register dst);
675 void popq(const Operand& dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000676
677 void enter(Immediate size);
678 void leave();
679
680 // Moves
681 void movb(Register dst, const Operand& src);
682 void movb(Register dst, Immediate imm);
683 void movb(const Operand& dst, Register src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684 void movb(const Operand& dst, Immediate imm);
Steve Blocka7e24c12009-10-30 11:49:00 +0000685
Steve Block3ce2e202009-11-05 08:53:23 +0000686 // Move the low 16 bits of a 64-bit register value to a 16-bit
687 // memory location.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000688 void movw(Register dst, const Operand& src);
Steve Block3ce2e202009-11-05 08:53:23 +0000689 void movw(const Operand& dst, Register src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690 void movw(const Operand& dst, Immediate imm);
Steve Block3ce2e202009-11-05 08:53:23 +0000691
Steve Blocka7e24c12009-10-30 11:49:00 +0000692 // Move the offset of the label location relative to the current
693 // position (after the move) to the destination.
694 void movl(const Operand& dst, Label* src);
695
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000696 // Loads a pointer into a register with a relocation mode.
697 void movp(Register dst, void* ptr, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000698
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 // Loads a 64-bit immediate into a register.
700 void movq(Register dst, int64_t value);
701 void movq(Register dst, uint64_t value);
702
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703 void movsxbl(Register dst, Register src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000704 void movsxbl(Register dst, const Operand& src);
Steve Block3ce2e202009-11-05 08:53:23 +0000705 void movsxbq(Register dst, const Operand& src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400706 void movsxwl(Register dst, Register src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 void movsxwl(Register dst, const Operand& src);
Steve Block3ce2e202009-11-05 08:53:23 +0000708 void movsxwq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000709 void movsxlq(Register dst, Register src);
710 void movsxlq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000711
Leon Clarked91b9f72010-01-27 17:25:45 +0000712 // Repeated moves.
713
714 void repmovsb();
715 void repmovsw();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716 void repmovsp() { emit_repmovs(kPointerSize); }
717 void repmovsl() { emit_repmovs(kInt32Size); }
718 void repmovsq() { emit_repmovs(kInt64Size); }
Leon Clarked91b9f72010-01-27 17:25:45 +0000719
Steve Block44f0eee2011-05-26 01:26:41 +0100720 // Instruction to load from an immediate 64-bit pointer into RAX.
Steve Blocka7e24c12009-10-30 11:49:00 +0000721 void load_rax(void* ptr, RelocInfo::Mode rmode);
722 void load_rax(ExternalReference ext);
723
724 // Conditional moves.
725 void cmovq(Condition cc, Register dst, Register src);
726 void cmovq(Condition cc, Register dst, const Operand& src);
727 void cmovl(Condition cc, Register dst, Register src);
728 void cmovl(Condition cc, Register dst, const Operand& src);
729
Steve Blocka7e24c12009-10-30 11:49:00 +0000730 void cmpb(Register dst, Immediate src) {
731 immediate_arithmetic_op_8(0x7, dst, src);
732 }
733
734 void cmpb_al(Immediate src);
735
736 void cmpb(Register dst, Register src) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 arithmetic_op_8(0x3A, dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000738 }
739
740 void cmpb(Register dst, const Operand& 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(const Operand& dst, Register src) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000745 arithmetic_op_8(0x38, src, dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000746 }
747
748 void cmpb(const Operand& dst, Immediate src) {
749 immediate_arithmetic_op_8(0x7, dst, src);
750 }
751
752 void cmpw(const Operand& dst, Immediate src) {
753 immediate_arithmetic_op_16(0x7, dst, src);
754 }
755
756 void cmpw(Register dst, Immediate src) {
757 immediate_arithmetic_op_16(0x7, dst, src);
758 }
759
760 void cmpw(Register dst, const Operand& src) {
761 arithmetic_op_16(0x3B, dst, src);
762 }
763
764 void cmpw(Register dst, Register src) {
765 arithmetic_op_16(0x3B, dst, src);
766 }
767
768 void cmpw(const Operand& dst, Register src) {
769 arithmetic_op_16(0x39, src, dst);
770 }
771
Leon Clarke4515c472010-02-03 11:58:03 +0000772 void andb(Register dst, Immediate src) {
773 immediate_arithmetic_op_8(0x4, dst, src);
774 }
Steve Block3ce2e202009-11-05 08:53:23 +0000775
Steve Block3ce2e202009-11-05 08:53:23 +0000776 void decb(Register dst);
777 void decb(const Operand& dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000778
779 // Sign-extends rax into rdx:rax.
780 void cqo();
781 // Sign-extends eax into edx:eax.
782 void cdq();
783
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400784 // Multiply eax by src, put the result in edx:eax.
785 void mull(Register src);
786 void mull(const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000787 // Multiply rax by src, put the result in rdx:rax.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400788 void mulq(Register src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000789
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400790#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode) \
791 void instruction##p(Register dst, Immediate imm8) { \
792 shift(dst, imm8, subcode, kPointerSize); \
793 } \
794 \
795 void instruction##l(Register dst, Immediate imm8) { \
796 shift(dst, imm8, subcode, kInt32Size); \
797 } \
798 \
799 void instruction##q(Register dst, Immediate imm8) { \
800 shift(dst, imm8, subcode, kInt64Size); \
801 } \
802 \
803 void instruction##p(Operand dst, Immediate imm8) { \
804 shift(dst, imm8, subcode, kPointerSize); \
805 } \
806 \
807 void instruction##l(Operand dst, Immediate imm8) { \
808 shift(dst, imm8, subcode, kInt32Size); \
809 } \
810 \
811 void instruction##q(Operand dst, Immediate imm8) { \
812 shift(dst, imm8, subcode, kInt64Size); \
813 } \
814 \
815 void instruction##p_cl(Register dst) { shift(dst, subcode, kPointerSize); } \
816 \
817 void instruction##l_cl(Register dst) { shift(dst, subcode, kInt32Size); } \
818 \
819 void instruction##q_cl(Register dst) { shift(dst, subcode, kInt64Size); } \
820 \
821 void instruction##p_cl(Operand dst) { shift(dst, subcode, kPointerSize); } \
822 \
823 void instruction##l_cl(Operand dst) { shift(dst, subcode, kInt32Size); } \
824 \
825 void instruction##q_cl(Operand dst) { shift(dst, subcode, kInt64Size); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000826 SHIFT_INSTRUCTION_LIST(DECLARE_SHIFT_INSTRUCTION)
827#undef DECLARE_SHIFT_INSTRUCTION
Steve Blocka7e24c12009-10-30 11:49:00 +0000828
829 // Shifts dst:src left by cl bits, affecting only dst.
830 void shld(Register dst, Register src);
831
832 // Shifts src:dst right by cl bits, affecting only dst.
833 void shrd(Register dst, Register src);
834
Steve Blocka7e24c12009-10-30 11:49:00 +0000835 void store_rax(void* dst, RelocInfo::Mode mode);
836 void store_rax(ExternalReference ref);
837
Steve Blocka7e24c12009-10-30 11:49:00 +0000838 void subb(Register dst, Immediate src) {
839 immediate_arithmetic_op_8(0x5, dst, src);
840 }
841
Steve Block3ce2e202009-11-05 08:53:23 +0000842 void testb(Register dst, Register src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000843 void testb(Register reg, Immediate mask);
844 void testb(const Operand& op, Immediate mask);
Leon Clarkee46be812010-01-19 14:06:41 +0000845 void testb(const Operand& op, Register reg);
Steve Blocka7e24c12009-10-30 11:49:00 +0000846
847 // Bit operations.
848 void bt(const Operand& dst, Register src);
849 void bts(const Operand& dst, Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000850 void bsrq(Register dst, Register src);
851 void bsrq(Register dst, const Operand& src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000852 void bsrl(Register dst, Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 void bsrl(Register dst, const Operand& src);
854 void bsfq(Register dst, Register src);
855 void bsfq(Register dst, const Operand& src);
856 void bsfl(Register dst, Register src);
857 void bsfl(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000858
859 // Miscellaneous
Steve Block3ce2e202009-11-05 08:53:23 +0000860 void clc();
Steve Block44f0eee2011-05-26 01:26:41 +0100861 void cld();
Steve Blocka7e24c12009-10-30 11:49:00 +0000862 void cpuid();
863 void hlt();
864 void int3();
865 void nop();
Steve Blocka7e24c12009-10-30 11:49:00 +0000866 void ret(int imm16);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000867 void ud2();
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 void setcc(Condition cc, Register reg);
869
870 // Label operations & relative jumps (PPUM Appendix D)
871 //
872 // Takes a branch opcode (cc) and a label (L) and generates
873 // either a backward branch or a forward branch and links it
874 // to the label fixup chain. Usage:
875 //
876 // Label L; // unbound label
877 // j(cc, &L); // forward branch to unbound label
878 // bind(&L); // bind label to the current pc
879 // j(cc, &L); // backward branch to bound label
880 // bind(&L); // illegal: a label may be bound only once
881 //
882 // Note: The same Label can be used for forward and backward branches
883 // but it may be bound only once.
884
885 void bind(Label* L); // binds an unbound label L to the current code position
886
887 // Calls
888 // Call near relative 32-bit displacement, relative to next instruction.
889 void call(Label* L);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000890 void call(Address entry, RelocInfo::Mode rmode);
Ben Murdoch257744e2011-11-30 15:57:28 +0000891 void call(Handle<Code> target,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000892 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893 TypeFeedbackId ast_id = TypeFeedbackId::None());
Steve Blocka7e24c12009-10-30 11:49:00 +0000894
Steve Block1e0659c2011-05-24 12:43:12 +0100895 // Calls directly to the given address using a relative offset.
896 // Should only ever be used in Code objects for calls within the
897 // same Code object. Should not be used when generating new code (use labels),
898 // but only when patching existing code.
899 void call(Address target);
900
Steve Blocka7e24c12009-10-30 11:49:00 +0000901 // Call near absolute indirect, address in register
902 void call(Register adr);
903
Steve Blocka7e24c12009-10-30 11:49:00 +0000904 // Jumps
905 // Jump short or near relative.
Steve Block3ce2e202009-11-05 08:53:23 +0000906 // Use a 32-bit signed displacement.
Ben Murdoch257744e2011-11-30 15:57:28 +0000907 // Unconditional jump to L
908 void jmp(Label* L, Label::Distance distance = Label::kFar);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909 void jmp(Address entry, RelocInfo::Mode rmode);
Steve Block3ce2e202009-11-05 08:53:23 +0000910 void jmp(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000911
912 // Jump near absolute indirect (r64)
913 void jmp(Register adr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000914 void jmp(const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000915
Steve Blocka7e24c12009-10-30 11:49:00 +0000916 // Conditional jumps
Ben Murdoch257744e2011-11-30 15:57:28 +0000917 void j(Condition cc,
918 Label* L,
919 Label::Distance distance = Label::kFar);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920 void j(Condition cc, Address entry, RelocInfo::Mode rmode);
Steve Block3ce2e202009-11-05 08:53:23 +0000921 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000922
923 // Floating-point operations
924 void fld(int i);
925
926 void fld1();
927 void fldz();
Steve Block6ded16b2010-05-10 14:33:55 +0100928 void fldpi();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100929 void fldln2();
Steve Blocka7e24c12009-10-30 11:49:00 +0000930
931 void fld_s(const Operand& adr);
932 void fld_d(const Operand& adr);
933
934 void fstp_s(const Operand& adr);
935 void fstp_d(const Operand& adr);
Steve Block3ce2e202009-11-05 08:53:23 +0000936 void fstp(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000937
938 void fild_s(const Operand& adr);
939 void fild_d(const Operand& adr);
940
941 void fist_s(const Operand& adr);
942
943 void fistp_s(const Operand& adr);
944 void fistp_d(const Operand& adr);
945
946 void fisttp_s(const Operand& adr);
Leon Clarked91b9f72010-01-27 17:25:45 +0000947 void fisttp_d(const Operand& adr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000948
949 void fabs();
950 void fchs();
951
952 void fadd(int i);
953 void fsub(int i);
954 void fmul(int i);
955 void fdiv(int i);
956
957 void fisub_s(const Operand& adr);
958
959 void faddp(int i = 1);
960 void fsubp(int i = 1);
961 void fsubrp(int i = 1);
962 void fmulp(int i = 1);
963 void fdivp(int i = 1);
964 void fprem();
965 void fprem1();
966
967 void fxch(int i = 1);
968 void fincstp();
969 void ffree(int i = 0);
970
971 void ftst();
972 void fucomp(int i);
973 void fucompp();
Steve Block3ce2e202009-11-05 08:53:23 +0000974 void fucomi(int i);
975 void fucomip();
976
Steve Blocka7e24c12009-10-30 11:49:00 +0000977 void fcompp();
978 void fnstsw_ax();
979 void fwait();
980 void fnclex();
981
982 void fsin();
983 void fcos();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100984 void fptan();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100985 void fyl2x();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100986 void f2xm1();
987 void fscale();
988 void fninit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000989
990 void frndint();
991
992 void sahf();
993
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000994 // SSE instructions
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400995 void addss(XMMRegister dst, XMMRegister src);
996 void addss(XMMRegister dst, const Operand& src);
997 void subss(XMMRegister dst, XMMRegister src);
998 void subss(XMMRegister dst, const Operand& src);
999 void mulss(XMMRegister dst, XMMRegister src);
1000 void mulss(XMMRegister dst, const Operand& src);
1001 void divss(XMMRegister dst, XMMRegister src);
1002 void divss(XMMRegister dst, const Operand& src);
1003
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001004 void maxss(XMMRegister dst, XMMRegister src);
1005 void maxss(XMMRegister dst, const Operand& src);
1006 void minss(XMMRegister dst, XMMRegister src);
1007 void minss(XMMRegister dst, const Operand& src);
1008
1009 void sqrtss(XMMRegister dst, XMMRegister src);
1010 void sqrtss(XMMRegister dst, const Operand& src);
1011
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001012 void ucomiss(XMMRegister dst, XMMRegister src);
1013 void ucomiss(XMMRegister dst, const Operand& src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 void movaps(XMMRegister dst, XMMRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001015
1016 // Don't use this unless it's important to keep the
1017 // top half of the destination register unchanged.
1018 // Use movaps when moving float values and movd for integer
1019 // values in xmm registers.
1020 void movss(XMMRegister dst, XMMRegister src);
1021
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001022 void movss(XMMRegister dst, const Operand& src);
1023 void movss(const Operand& dst, XMMRegister src);
1024 void shufps(XMMRegister dst, XMMRegister src, byte imm8);
1025
1026 void cvttss2si(Register dst, const Operand& src);
1027 void cvttss2si(Register dst, XMMRegister src);
1028 void cvtlsi2ss(XMMRegister dst, Register src);
1029
1030 void andps(XMMRegister dst, XMMRegister src);
1031 void andps(XMMRegister dst, const Operand& src);
1032 void orps(XMMRegister dst, XMMRegister src);
1033 void orps(XMMRegister dst, const Operand& src);
1034 void xorps(XMMRegister dst, XMMRegister src);
1035 void xorps(XMMRegister dst, const Operand& src);
1036
1037 void addps(XMMRegister dst, XMMRegister src);
1038 void addps(XMMRegister dst, const Operand& src);
1039 void subps(XMMRegister dst, XMMRegister src);
1040 void subps(XMMRegister dst, const Operand& src);
1041 void mulps(XMMRegister dst, XMMRegister src);
1042 void mulps(XMMRegister dst, const Operand& src);
1043 void divps(XMMRegister dst, XMMRegister src);
1044 void divps(XMMRegister dst, const Operand& src);
1045
1046 void movmskps(Register dst, XMMRegister src);
1047
Steve Blocka7e24c12009-10-30 11:49:00 +00001048 // SSE2 instructions
Steve Block6ded16b2010-05-10 14:33:55 +01001049 void movd(XMMRegister dst, Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001050 void movd(XMMRegister dst, const Operand& src);
Steve Block6ded16b2010-05-10 14:33:55 +01001051 void movd(Register dst, XMMRegister src);
1052 void movq(XMMRegister dst, Register src);
1053 void movq(Register dst, XMMRegister src);
Ben Murdoch257744e2011-11-30 15:57:28 +00001054 void movq(XMMRegister dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001055
Ben Murdoch257744e2011-11-30 15:57:28 +00001056 // Don't use this unless it's important to keep the
1057 // top half of the destination register unchanged.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001058 // Use movapd when moving double values and movq for integer
Ben Murdoch257744e2011-11-30 15:57:28 +00001059 // values in xmm registers.
Steve Block053d10c2011-06-13 19:13:29 +01001060 void movsd(XMMRegister dst, XMMRegister src);
Ben Murdoch257744e2011-11-30 15:57:28 +00001061
1062 void movsd(const Operand& dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001063 void movsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001064
Steve Block1e0659c2011-05-24 12:43:12 +01001065 void movdqa(const Operand& dst, XMMRegister src);
1066 void movdqa(XMMRegister dst, const Operand& src);
1067
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001068 void movdqu(const Operand& dst, XMMRegister src);
1069 void movdqu(XMMRegister dst, const Operand& src);
1070
Ben Murdoch257744e2011-11-30 15:57:28 +00001071 void movapd(XMMRegister dst, XMMRegister src);
Ben Murdoch257744e2011-11-30 15:57:28 +00001072
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001073 void psllq(XMMRegister reg, byte imm8);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001074 void psrlq(XMMRegister reg, byte imm8);
1075 void pslld(XMMRegister reg, byte imm8);
1076 void psrld(XMMRegister reg, byte imm8);
Steve Block8defd9f2010-07-08 12:39:36 +01001077
Steve Blocka7e24c12009-10-30 11:49:00 +00001078 void cvttsd2si(Register dst, const Operand& src);
Steve Block1e0659c2011-05-24 12:43:12 +01001079 void cvttsd2si(Register dst, XMMRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 void cvttss2siq(Register dst, XMMRegister src);
1081 void cvttss2siq(Register dst, const Operand& src);
Kristian Monsen25f61362010-05-21 11:50:48 +01001082 void cvttsd2siq(Register dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083 void cvttsd2siq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001084
1085 void cvtlsi2sd(XMMRegister dst, const Operand& src);
1086 void cvtlsi2sd(XMMRegister dst, Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001087
1088 void cvtqsi2ss(XMMRegister dst, const Operand& src);
1089 void cvtqsi2ss(XMMRegister dst, Register src);
1090
Steve Blocka7e24c12009-10-30 11:49:00 +00001091 void cvtqsi2sd(XMMRegister dst, const Operand& src);
1092 void cvtqsi2sd(XMMRegister dst, Register src);
1093
Steve Block8defd9f2010-07-08 12:39:36 +01001094
Steve Block6ded16b2010-05-10 14:33:55 +01001095 void cvtss2sd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001096 void cvtss2sd(XMMRegister dst, const Operand& src);
1097 void cvtsd2ss(XMMRegister dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001098 void cvtsd2ss(XMMRegister dst, const Operand& src);
Steve Block8defd9f2010-07-08 12:39:36 +01001099
1100 void cvtsd2si(Register dst, XMMRegister src);
1101 void cvtsd2siq(Register dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001102
Steve Blocka7e24c12009-10-30 11:49:00 +00001103 void addsd(XMMRegister dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001104 void addsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001105 void subsd(XMMRegister dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001106 void subsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001107 void mulsd(XMMRegister dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001108 void mulsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001109 void divsd(XMMRegister dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001110 void divsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001111
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001112 void maxsd(XMMRegister dst, XMMRegister src);
1113 void maxsd(XMMRegister dst, const Operand& src);
1114 void minsd(XMMRegister dst, XMMRegister src);
1115 void minsd(XMMRegister dst, const Operand& src);
1116
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001117 void andpd(XMMRegister dst, XMMRegister src);
1118 void orpd(XMMRegister dst, XMMRegister src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001119 void xorpd(XMMRegister dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001120 void sqrtsd(XMMRegister dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121 void sqrtsd(XMMRegister dst, const Operand& src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001122
Andrei Popescu402d9372010-02-26 13:31:12 +00001123 void ucomisd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001124 void ucomisd(XMMRegister dst, const Operand& src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001125 void cmpltsd(XMMRegister dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001126 void pcmpeqd(XMMRegister dst, XMMRegister src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001127
1128 void movmskpd(Register dst, XMMRegister src);
1129
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001130 void punpckldq(XMMRegister dst, XMMRegister src);
1131 void punpckhdq(XMMRegister dst, XMMRegister src);
1132
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133 // SSE 4.1 instruction
1134 void extractps(Register dst, XMMRegister src, byte imm8);
Steve Blocka7e24c12009-10-30 11:49:00 +00001135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001136 void pextrd(Register dst, XMMRegister src, int8_t imm8);
Ben Murdoch257744e2011-11-30 15:57:28 +00001137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001138 void pinsrd(XMMRegister dst, Register src, int8_t imm8);
1139 void pinsrd(XMMRegister dst, const Operand& src, int8_t imm8);
1140
1141 void roundss(XMMRegister dst, XMMRegister src, RoundingMode mode);
Ben Murdoch257744e2011-11-30 15:57:28 +00001142 void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1143
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001144 // AVX instruction
1145 void vfmadd132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1146 vfmasd(0x99, dst, src1, src2);
1147 }
1148 void vfmadd213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1149 vfmasd(0xa9, dst, src1, src2);
1150 }
1151 void vfmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1152 vfmasd(0xb9, dst, src1, src2);
1153 }
1154 void vfmadd132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1155 vfmasd(0x99, dst, src1, src2);
1156 }
1157 void vfmadd213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1158 vfmasd(0xa9, dst, src1, src2);
1159 }
1160 void vfmadd231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1161 vfmasd(0xb9, dst, src1, src2);
1162 }
1163 void vfmsub132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1164 vfmasd(0x9b, dst, src1, src2);
1165 }
1166 void vfmsub213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1167 vfmasd(0xab, dst, src1, src2);
1168 }
1169 void vfmsub231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1170 vfmasd(0xbb, dst, src1, src2);
1171 }
1172 void vfmsub132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1173 vfmasd(0x9b, dst, src1, src2);
1174 }
1175 void vfmsub213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1176 vfmasd(0xab, dst, src1, src2);
1177 }
1178 void vfmsub231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1179 vfmasd(0xbb, dst, src1, src2);
1180 }
1181 void vfnmadd132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1182 vfmasd(0x9d, dst, src1, src2);
1183 }
1184 void vfnmadd213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1185 vfmasd(0xad, dst, src1, src2);
1186 }
1187 void vfnmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1188 vfmasd(0xbd, dst, src1, src2);
1189 }
1190 void vfnmadd132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1191 vfmasd(0x9d, dst, src1, src2);
1192 }
1193 void vfnmadd213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1194 vfmasd(0xad, dst, src1, src2);
1195 }
1196 void vfnmadd231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1197 vfmasd(0xbd, dst, src1, src2);
1198 }
1199 void vfnmsub132sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1200 vfmasd(0x9f, dst, src1, src2);
1201 }
1202 void vfnmsub213sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1203 vfmasd(0xaf, dst, src1, src2);
1204 }
1205 void vfnmsub231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1206 vfmasd(0xbf, dst, src1, src2);
1207 }
1208 void vfnmsub132sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1209 vfmasd(0x9f, dst, src1, src2);
1210 }
1211 void vfnmsub213sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1212 vfmasd(0xaf, dst, src1, src2);
1213 }
1214 void vfnmsub231sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1215 vfmasd(0xbf, dst, src1, src2);
1216 }
1217 void vfmasd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1218 void vfmasd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1219
1220 void vfmadd132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1221 vfmass(0x99, dst, src1, src2);
1222 }
1223 void vfmadd213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1224 vfmass(0xa9, dst, src1, src2);
1225 }
1226 void vfmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1227 vfmass(0xb9, dst, src1, src2);
1228 }
1229 void vfmadd132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1230 vfmass(0x99, dst, src1, src2);
1231 }
1232 void vfmadd213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1233 vfmass(0xa9, dst, src1, src2);
1234 }
1235 void vfmadd231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1236 vfmass(0xb9, dst, src1, src2);
1237 }
1238 void vfmsub132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1239 vfmass(0x9b, dst, src1, src2);
1240 }
1241 void vfmsub213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1242 vfmass(0xab, dst, src1, src2);
1243 }
1244 void vfmsub231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1245 vfmass(0xbb, dst, src1, src2);
1246 }
1247 void vfmsub132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1248 vfmass(0x9b, dst, src1, src2);
1249 }
1250 void vfmsub213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1251 vfmass(0xab, dst, src1, src2);
1252 }
1253 void vfmsub231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1254 vfmass(0xbb, dst, src1, src2);
1255 }
1256 void vfnmadd132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1257 vfmass(0x9d, dst, src1, src2);
1258 }
1259 void vfnmadd213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1260 vfmass(0xad, dst, src1, src2);
1261 }
1262 void vfnmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1263 vfmass(0xbd, dst, src1, src2);
1264 }
1265 void vfnmadd132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1266 vfmass(0x9d, dst, src1, src2);
1267 }
1268 void vfnmadd213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1269 vfmass(0xad, dst, src1, src2);
1270 }
1271 void vfnmadd231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1272 vfmass(0xbd, dst, src1, src2);
1273 }
1274 void vfnmsub132ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1275 vfmass(0x9f, dst, src1, src2);
1276 }
1277 void vfnmsub213ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1278 vfmass(0xaf, dst, src1, src2);
1279 }
1280 void vfnmsub231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1281 vfmass(0xbf, dst, src1, src2);
1282 }
1283 void vfnmsub132ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1284 vfmass(0x9f, dst, src1, src2);
1285 }
1286 void vfnmsub213ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1287 vfmass(0xaf, dst, src1, src2);
1288 }
1289 void vfnmsub231ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1290 vfmass(0xbf, dst, src1, src2);
1291 }
1292 void vfmass(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1293 void vfmass(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1294
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001295 void vmovd(XMMRegister dst, Register src);
1296 void vmovd(XMMRegister dst, const Operand& src);
1297 void vmovd(Register dst, XMMRegister src);
1298 void vmovq(XMMRegister dst, Register src);
1299 void vmovq(XMMRegister dst, const Operand& src);
1300 void vmovq(Register dst, XMMRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001301
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001302 void vmovsd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1303 vsd(0x10, dst, src1, src2);
1304 }
1305 void vmovsd(XMMRegister dst, const Operand& src) {
1306 vsd(0x10, dst, xmm0, src);
1307 }
1308 void vmovsd(const Operand& dst, XMMRegister src) {
1309 vsd(0x11, src, xmm0, dst);
1310 }
1311
1312#define AVX_SP_3(instr, opcode) \
1313 AVX_S_3(instr, opcode) \
1314 AVX_P_3(instr, opcode)
1315
1316#define AVX_S_3(instr, opcode) \
1317 AVX_3(instr##ss, opcode, vss) \
1318 AVX_3(instr##sd, opcode, vsd)
1319
1320#define AVX_P_3(instr, opcode) \
1321 AVX_3(instr##ps, opcode, vps) \
1322 AVX_3(instr##pd, opcode, vpd)
1323
1324#define AVX_3(instr, opcode, impl) \
1325 void instr(XMMRegister dst, XMMRegister src1, XMMRegister src2) { \
1326 impl(opcode, dst, src1, src2); \
1327 } \
1328 void instr(XMMRegister dst, XMMRegister src1, const Operand& src2) { \
1329 impl(opcode, dst, src1, src2); \
1330 }
1331
1332 AVX_SP_3(vsqrt, 0x51);
1333 AVX_SP_3(vadd, 0x58);
1334 AVX_SP_3(vsub, 0x5c);
1335 AVX_SP_3(vmul, 0x59);
1336 AVX_SP_3(vdiv, 0x5e);
1337 AVX_SP_3(vmin, 0x5d);
1338 AVX_SP_3(vmax, 0x5f);
1339 AVX_P_3(vand, 0x54);
1340 AVX_P_3(vor, 0x56);
1341 AVX_P_3(vxor, 0x57);
1342 AVX_3(vpcmpeqd, 0x76, vpd);
1343 AVX_3(vcvtsd2ss, 0x5a, vsd);
1344
1345#undef AVX_3
1346#undef AVX_S_3
1347#undef AVX_P_3
1348#undef AVX_SP_3
1349
1350 void vpsrlq(XMMRegister dst, XMMRegister src, byte imm8) {
1351 XMMRegister iop = {2};
1352 vpd(0x73, iop, dst, src);
1353 emit(imm8);
1354 }
1355 void vpsllq(XMMRegister dst, XMMRegister src, byte imm8) {
1356 XMMRegister iop = {6};
1357 vpd(0x73, iop, dst, src);
1358 emit(imm8);
1359 }
1360 void vcvtss2sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1361 vsd(0x5a, dst, src1, src2, kF3, k0F, kWIG);
1362 }
1363 void vcvtss2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1364 vsd(0x5a, dst, src1, src2, kF3, k0F, kWIG);
1365 }
1366 void vcvtlsi2sd(XMMRegister dst, XMMRegister src1, Register src2) {
1367 XMMRegister isrc2 = {src2.code()};
1368 vsd(0x2a, dst, src1, isrc2, kF2, k0F, kW0);
1369 }
1370 void vcvtlsi2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1371 vsd(0x2a, dst, src1, src2, kF2, k0F, kW0);
1372 }
1373 void vcvtqsi2ss(XMMRegister dst, XMMRegister src1, Register src2) {
1374 XMMRegister isrc2 = {src2.code()};
1375 vsd(0x2a, dst, src1, isrc2, kF3, k0F, kW1);
1376 }
1377 void vcvtqsi2ss(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1378 vsd(0x2a, dst, src1, src2, kF3, k0F, kW1);
1379 }
1380 void vcvtqsi2sd(XMMRegister dst, XMMRegister src1, Register src2) {
1381 XMMRegister isrc2 = {src2.code()};
1382 vsd(0x2a, dst, src1, isrc2, kF2, k0F, kW1);
1383 }
1384 void vcvtqsi2sd(XMMRegister dst, XMMRegister src1, const Operand& src2) {
1385 vsd(0x2a, dst, src1, src2, kF2, k0F, kW1);
1386 }
1387 void vcvttsd2si(Register dst, XMMRegister src) {
1388 XMMRegister idst = {dst.code()};
1389 vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
1390 }
1391 void vcvttsd2si(Register dst, const Operand& src) {
1392 XMMRegister idst = {dst.code()};
1393 vsd(0x2c, idst, xmm0, src, kF2, k0F, kW0);
1394 }
1395 void vcvttss2siq(Register dst, XMMRegister src) {
1396 XMMRegister idst = {dst.code()};
1397 vsd(0x2c, idst, xmm0, src, kF3, k0F, kW1);
1398 }
1399 void vcvttss2siq(Register dst, const Operand& src) {
1400 XMMRegister idst = {dst.code()};
1401 vsd(0x2c, idst, xmm0, src, kF3, k0F, kW1);
1402 }
1403 void vcvttsd2siq(Register dst, XMMRegister src) {
1404 XMMRegister idst = {dst.code()};
1405 vsd(0x2c, idst, xmm0, src, kF2, k0F, kW1);
1406 }
1407 void vcvttsd2siq(Register dst, const Operand& src) {
1408 XMMRegister idst = {dst.code()};
1409 vsd(0x2c, idst, xmm0, src, kF2, k0F, kW1);
1410 }
1411 void vcvtsd2si(Register dst, XMMRegister src) {
1412 XMMRegister idst = {dst.code()};
1413 vsd(0x2d, idst, xmm0, src, kF2, k0F, kW0);
1414 }
1415 void vucomisd(XMMRegister dst, XMMRegister src) {
1416 vsd(0x2e, dst, xmm0, src, k66, k0F, kWIG);
1417 }
1418 void vucomisd(XMMRegister dst, const Operand& src) {
1419 vsd(0x2e, dst, xmm0, src, k66, k0F, kWIG);
1420 }
1421 void vroundss(XMMRegister dst, XMMRegister src1, XMMRegister src2,
1422 RoundingMode mode) {
1423 vsd(0x0a, dst, src1, src2, k66, k0F3A, kWIG);
1424 emit(static_cast<byte>(mode) | 0x8); // Mask precision exception.
1425 }
1426 void vroundsd(XMMRegister dst, XMMRegister src1, XMMRegister src2,
1427 RoundingMode mode) {
1428 vsd(0x0b, dst, src1, src2, k66, k0F3A, kWIG);
1429 emit(static_cast<byte>(mode) | 0x8); // Mask precision exception.
1430 }
1431
1432 void vsd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1433 vsd(op, dst, src1, src2, kF2, k0F, kWIG);
1434 }
1435 void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2) {
1436 vsd(op, dst, src1, src2, kF2, k0F, kWIG);
1437 }
1438 void vsd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2,
1439 SIMDPrefix pp, LeadingOpcode m, VexW w);
1440 void vsd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2,
1441 SIMDPrefix pp, LeadingOpcode m, VexW w);
1442
1443 void vmovss(XMMRegister dst, XMMRegister src1, XMMRegister src2) {
1444 vss(0x10, dst, src1, src2);
1445 }
1446 void vmovss(XMMRegister dst, const Operand& src) {
1447 vss(0x10, dst, xmm0, src);
1448 }
1449 void vmovss(const Operand& dst, XMMRegister src) {
1450 vss(0x11, src, xmm0, dst);
1451 }
1452 void vucomiss(XMMRegister dst, XMMRegister src);
1453 void vucomiss(XMMRegister dst, const Operand& src);
1454 void vss(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1455 void vss(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1456
1457 void vmovaps(XMMRegister dst, XMMRegister src) { vps(0x28, dst, xmm0, src); }
1458 void vmovapd(XMMRegister dst, XMMRegister src) { vpd(0x28, dst, xmm0, src); }
1459 void vmovmskpd(Register dst, XMMRegister src) {
1460 XMMRegister idst = {dst.code()};
1461 vpd(0x50, idst, xmm0, src);
1462 }
1463
1464 void vps(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1465 void vps(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1466 void vpd(byte op, XMMRegister dst, XMMRegister src1, XMMRegister src2);
1467 void vpd(byte op, XMMRegister dst, XMMRegister src1, const Operand& src2);
1468
1469 // BMI instruction
1470 void andnq(Register dst, Register src1, Register src2) {
1471 bmi1q(0xf2, dst, src1, src2);
1472 }
1473 void andnq(Register dst, Register src1, const Operand& src2) {
1474 bmi1q(0xf2, dst, src1, src2);
1475 }
1476 void andnl(Register dst, Register src1, Register src2) {
1477 bmi1l(0xf2, dst, src1, src2);
1478 }
1479 void andnl(Register dst, Register src1, const Operand& src2) {
1480 bmi1l(0xf2, dst, src1, src2);
1481 }
1482 void bextrq(Register dst, Register src1, Register src2) {
1483 bmi1q(0xf7, dst, src2, src1);
1484 }
1485 void bextrq(Register dst, const Operand& src1, Register src2) {
1486 bmi1q(0xf7, dst, src2, src1);
1487 }
1488 void bextrl(Register dst, Register src1, Register src2) {
1489 bmi1l(0xf7, dst, src2, src1);
1490 }
1491 void bextrl(Register dst, const Operand& src1, Register src2) {
1492 bmi1l(0xf7, dst, src2, src1);
1493 }
1494 void blsiq(Register dst, Register src) {
1495 Register ireg = {3};
1496 bmi1q(0xf3, ireg, dst, src);
1497 }
1498 void blsiq(Register dst, const Operand& src) {
1499 Register ireg = {3};
1500 bmi1q(0xf3, ireg, dst, src);
1501 }
1502 void blsil(Register dst, Register src) {
1503 Register ireg = {3};
1504 bmi1l(0xf3, ireg, dst, src);
1505 }
1506 void blsil(Register dst, const Operand& src) {
1507 Register ireg = {3};
1508 bmi1l(0xf3, ireg, dst, src);
1509 }
1510 void blsmskq(Register dst, Register src) {
1511 Register ireg = {2};
1512 bmi1q(0xf3, ireg, dst, src);
1513 }
1514 void blsmskq(Register dst, const Operand& src) {
1515 Register ireg = {2};
1516 bmi1q(0xf3, ireg, dst, src);
1517 }
1518 void blsmskl(Register dst, Register src) {
1519 Register ireg = {2};
1520 bmi1l(0xf3, ireg, dst, src);
1521 }
1522 void blsmskl(Register dst, const Operand& src) {
1523 Register ireg = {2};
1524 bmi1l(0xf3, ireg, dst, src);
1525 }
1526 void blsrq(Register dst, Register src) {
1527 Register ireg = {1};
1528 bmi1q(0xf3, ireg, dst, src);
1529 }
1530 void blsrq(Register dst, const Operand& src) {
1531 Register ireg = {1};
1532 bmi1q(0xf3, ireg, dst, src);
1533 }
1534 void blsrl(Register dst, Register src) {
1535 Register ireg = {1};
1536 bmi1l(0xf3, ireg, dst, src);
1537 }
1538 void blsrl(Register dst, const Operand& src) {
1539 Register ireg = {1};
1540 bmi1l(0xf3, ireg, dst, src);
1541 }
1542 void tzcntq(Register dst, Register src);
1543 void tzcntq(Register dst, const Operand& src);
1544 void tzcntl(Register dst, Register src);
1545 void tzcntl(Register dst, const Operand& src);
1546
1547 void lzcntq(Register dst, Register src);
1548 void lzcntq(Register dst, const Operand& src);
1549 void lzcntl(Register dst, Register src);
1550 void lzcntl(Register dst, const Operand& src);
1551
1552 void popcntq(Register dst, Register src);
1553 void popcntq(Register dst, const Operand& src);
1554 void popcntl(Register dst, Register src);
1555 void popcntl(Register dst, const Operand& src);
1556
1557 void bzhiq(Register dst, Register src1, Register src2) {
1558 bmi2q(kNone, 0xf5, dst, src2, src1);
1559 }
1560 void bzhiq(Register dst, const Operand& src1, Register src2) {
1561 bmi2q(kNone, 0xf5, dst, src2, src1);
1562 }
1563 void bzhil(Register dst, Register src1, Register src2) {
1564 bmi2l(kNone, 0xf5, dst, src2, src1);
1565 }
1566 void bzhil(Register dst, const Operand& src1, Register src2) {
1567 bmi2l(kNone, 0xf5, dst, src2, src1);
1568 }
1569 void mulxq(Register dst1, Register dst2, Register src) {
1570 bmi2q(kF2, 0xf6, dst1, dst2, src);
1571 }
1572 void mulxq(Register dst1, Register dst2, const Operand& src) {
1573 bmi2q(kF2, 0xf6, dst1, dst2, src);
1574 }
1575 void mulxl(Register dst1, Register dst2, Register src) {
1576 bmi2l(kF2, 0xf6, dst1, dst2, src);
1577 }
1578 void mulxl(Register dst1, Register dst2, const Operand& src) {
1579 bmi2l(kF2, 0xf6, dst1, dst2, src);
1580 }
1581 void pdepq(Register dst, Register src1, Register src2) {
1582 bmi2q(kF2, 0xf5, dst, src1, src2);
1583 }
1584 void pdepq(Register dst, Register src1, const Operand& src2) {
1585 bmi2q(kF2, 0xf5, dst, src1, src2);
1586 }
1587 void pdepl(Register dst, Register src1, Register src2) {
1588 bmi2l(kF2, 0xf5, dst, src1, src2);
1589 }
1590 void pdepl(Register dst, Register src1, const Operand& src2) {
1591 bmi2l(kF2, 0xf5, dst, src1, src2);
1592 }
1593 void pextq(Register dst, Register src1, Register src2) {
1594 bmi2q(kF3, 0xf5, dst, src1, src2);
1595 }
1596 void pextq(Register dst, Register src1, const Operand& src2) {
1597 bmi2q(kF3, 0xf5, dst, src1, src2);
1598 }
1599 void pextl(Register dst, Register src1, Register src2) {
1600 bmi2l(kF3, 0xf5, dst, src1, src2);
1601 }
1602 void pextl(Register dst, Register src1, const Operand& src2) {
1603 bmi2l(kF3, 0xf5, dst, src1, src2);
1604 }
1605 void sarxq(Register dst, Register src1, Register src2) {
1606 bmi2q(kF3, 0xf7, dst, src2, src1);
1607 }
1608 void sarxq(Register dst, const Operand& src1, Register src2) {
1609 bmi2q(kF3, 0xf7, dst, src2, src1);
1610 }
1611 void sarxl(Register dst, Register src1, Register src2) {
1612 bmi2l(kF3, 0xf7, dst, src2, src1);
1613 }
1614 void sarxl(Register dst, const Operand& src1, Register src2) {
1615 bmi2l(kF3, 0xf7, dst, src2, src1);
1616 }
1617 void shlxq(Register dst, Register src1, Register src2) {
1618 bmi2q(k66, 0xf7, dst, src2, src1);
1619 }
1620 void shlxq(Register dst, const Operand& src1, Register src2) {
1621 bmi2q(k66, 0xf7, dst, src2, src1);
1622 }
1623 void shlxl(Register dst, Register src1, Register src2) {
1624 bmi2l(k66, 0xf7, dst, src2, src1);
1625 }
1626 void shlxl(Register dst, const Operand& src1, Register src2) {
1627 bmi2l(k66, 0xf7, dst, src2, src1);
1628 }
1629 void shrxq(Register dst, Register src1, Register src2) {
1630 bmi2q(kF2, 0xf7, dst, src2, src1);
1631 }
1632 void shrxq(Register dst, const Operand& src1, Register src2) {
1633 bmi2q(kF2, 0xf7, dst, src2, src1);
1634 }
1635 void shrxl(Register dst, Register src1, Register src2) {
1636 bmi2l(kF2, 0xf7, dst, src2, src1);
1637 }
1638 void shrxl(Register dst, const Operand& src1, Register src2) {
1639 bmi2l(kF2, 0xf7, dst, src2, src1);
1640 }
1641 void rorxq(Register dst, Register src, byte imm8);
1642 void rorxq(Register dst, const Operand& src, byte imm8);
1643 void rorxl(Register dst, Register src, byte imm8);
1644 void rorxl(Register dst, const Operand& src, byte imm8);
Steve Blocka7e24c12009-10-30 11:49:00 +00001645
1646 // Check the code size generated from label to here.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001647 int SizeOfCodeGeneratedSince(Label* label) {
1648 return pc_offset() - label->pos();
1649 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001650
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001651 // Mark generator continuation.
1652 void RecordGeneratorContinuation();
Steve Blocka7e24c12009-10-30 11:49:00 +00001653
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001654 // Mark address of a debug break slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001655 void RecordDebugBreakSlot(RelocInfo::Mode mode);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001656
Steve Blocka7e24c12009-10-30 11:49:00 +00001657 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001658 // Use --code-comments to enable.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001659 void RecordComment(const char* msg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001660
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001661 // Record a deoptimization reason that can be used by a log or cpu profiler.
1662 // Use --trace-deopt to enable.
1663 void RecordDeoptReason(const int reason, const SourcePosition position);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001664
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001665 void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1666 ConstantPoolEntry::Access access,
1667 ConstantPoolEntry::Type type) {
1668 // No embedded constant pool support.
1669 UNREACHABLE();
1670 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001671
Ben Murdochb0fe1622011-05-05 13:52:32 +01001672 // Writes a single word of data in the code stream.
1673 // Used for inline tables, e.g., jump-tables.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001674 void db(uint8_t data);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001675 void dd(uint32_t data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001676 void dq(uint64_t data);
1677 void dp(uintptr_t data) { dq(data); }
1678 void dq(Label* label);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001679
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001680 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001681
1682 // Check if there is less than kGap bytes available in the buffer.
1683 // If this is the case, we need to grow the buffer before emitting
1684 // an instruction or relocation information.
1685 inline bool buffer_overflow() const {
1686 return pc_ >= reloc_info_writer.pos() - kGap;
1687 }
1688
1689 // Get the number of bytes available in the buffer.
Steve Blockd0582a62009-12-15 09:54:21 +00001690 inline int available_space() const {
1691 return static_cast<int>(reloc_info_writer.pos() - pc_);
1692 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001693
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001694 static bool IsNop(Address addr);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001695
Steve Blocka7e24c12009-10-30 11:49:00 +00001696 // Avoid overflows for displacements etc.
1697 static const int kMaximalBufferSize = 512*MB;
Steve Blocka7e24c12009-10-30 11:49:00 +00001698
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001699 byte byte_at(int pos) { return buffer_[pos]; }
1700 void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1701
Steve Block44f0eee2011-05-26 01:26:41 +01001702 protected:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001703 // Call near indirect
1704 void call(const Operand& operand);
1705
Steve Blocka7e24c12009-10-30 11:49:00 +00001706 private:
1707 byte* addr_at(int pos) { return buffer_ + pos; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001708 uint32_t long_at(int pos) {
1709 return *reinterpret_cast<uint32_t*>(addr_at(pos));
1710 }
1711 void long_at_put(int pos, uint32_t x) {
1712 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1713 }
1714
1715 // code emission
1716 void GrowBuffer();
1717
1718 void emit(byte x) { *pc_++ = x; }
1719 inline void emitl(uint32_t x);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001720 inline void emitp(void* x, RelocInfo::Mode rmode);
1721 inline void emitq(uint64_t x);
Steve Blocka7e24c12009-10-30 11:49:00 +00001722 inline void emitw(uint16_t x);
Ben Murdoch257744e2011-11-30 15:57:28 +00001723 inline void emit_code_target(Handle<Code> target,
1724 RelocInfo::Mode rmode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001725 TypeFeedbackId ast_id = TypeFeedbackId::None());
1726 inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001727 void emit(Immediate x) { emitl(x.value_); }
1728
1729 // Emits a REX prefix that encodes a 64-bit operand size and
1730 // the top bit of both register codes.
1731 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1732 // REX.W is set.
Steve Blocka7e24c12009-10-30 11:49:00 +00001733 inline void emit_rex_64(XMMRegister reg, Register rm_reg);
Steve Block6ded16b2010-05-10 14:33:55 +01001734 inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1735 inline void emit_rex_64(Register reg, Register rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001736
1737 // Emits a REX prefix that encodes a 64-bit operand size and
1738 // the top bit of the destination, index, and base register codes.
1739 // The high bit of reg is used for REX.R, the high bit of op's base
1740 // register is used for REX.B, and the high bit of op's index register
1741 // is used for REX.X. REX.W is set.
1742 inline void emit_rex_64(Register reg, const Operand& op);
1743 inline void emit_rex_64(XMMRegister reg, const Operand& op);
1744
1745 // Emits a REX prefix that encodes a 64-bit operand size and
1746 // the top bit of the register code.
1747 // The high bit of register is used for REX.B.
1748 // REX.W is set and REX.R and REX.X are clear.
1749 inline void emit_rex_64(Register rm_reg);
1750
1751 // Emits a REX prefix that encodes a 64-bit operand size and
1752 // the top bit of the index and base register codes.
1753 // The high bit of op's base register is used for REX.B, and the high
1754 // bit of op's index register is used for REX.X.
1755 // REX.W is set and REX.R clear.
1756 inline void emit_rex_64(const Operand& op);
1757
1758 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1759 void emit_rex_64() { emit(0x48); }
1760
1761 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1762 // REX.W is clear.
1763 inline void emit_rex_32(Register reg, Register rm_reg);
1764
1765 // The high bit of reg is used for REX.R, the high bit of op's base
1766 // register is used for REX.B, and the high bit of op's index register
1767 // is used for REX.X. REX.W is cleared.
1768 inline void emit_rex_32(Register reg, const Operand& op);
1769
1770 // High bit of rm_reg goes to REX.B.
1771 // REX.W, REX.R and REX.X are clear.
1772 inline void emit_rex_32(Register rm_reg);
1773
1774 // High bit of base goes to REX.B and high bit of index to REX.X.
1775 // REX.W and REX.R are clear.
1776 inline void emit_rex_32(const Operand& op);
1777
1778 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1779 // REX.W is cleared. If no REX bits are set, no byte is emitted.
1780 inline void emit_optional_rex_32(Register reg, Register rm_reg);
1781
1782 // The high bit of reg is used for REX.R, the high bit of op's base
1783 // register is used for REX.B, and the high bit of op's index register
1784 // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
1785 // is emitted.
1786 inline void emit_optional_rex_32(Register reg, const Operand& op);
1787
1788 // As for emit_optional_rex_32(Register, Register), except that
1789 // the registers are XMM registers.
1790 inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1791
1792 // As for emit_optional_rex_32(Register, Register), except that
Steve Block6ded16b2010-05-10 14:33:55 +01001793 // one of the registers is an XMM registers.
Steve Blocka7e24c12009-10-30 11:49:00 +00001794 inline void emit_optional_rex_32(XMMRegister reg, Register base);
1795
Steve Block6ded16b2010-05-10 14:33:55 +01001796 // As for emit_optional_rex_32(Register, Register), except that
1797 // one of the registers is an XMM registers.
1798 inline void emit_optional_rex_32(Register reg, XMMRegister base);
1799
Steve Blocka7e24c12009-10-30 11:49:00 +00001800 // As for emit_optional_rex_32(Register, const Operand&), except that
1801 // the register is an XMM register.
1802 inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1803
1804 // Optionally do as emit_rex_32(Register) if the register number has
1805 // the high bit set.
1806 inline void emit_optional_rex_32(Register rm_reg);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001807 inline void emit_optional_rex_32(XMMRegister rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001808
1809 // Optionally do as emit_rex_32(const Operand&) if the operand register
1810 // numbers have a high bit set.
1811 inline void emit_optional_rex_32(const Operand& op);
1812
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001813 void emit_rex(int size) {
1814 if (size == kInt64Size) {
1815 emit_rex_64();
1816 } else {
1817 DCHECK(size == kInt32Size);
1818 }
1819 }
1820
1821 template<class P1>
1822 void emit_rex(P1 p1, int size) {
1823 if (size == kInt64Size) {
1824 emit_rex_64(p1);
1825 } else {
1826 DCHECK(size == kInt32Size);
1827 emit_optional_rex_32(p1);
1828 }
1829 }
1830
1831 template<class P1, class P2>
1832 void emit_rex(P1 p1, P2 p2, int size) {
1833 if (size == kInt64Size) {
1834 emit_rex_64(p1, p2);
1835 } else {
1836 DCHECK(size == kInt32Size);
1837 emit_optional_rex_32(p1, p2);
1838 }
1839 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001840
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001841 // Emit vex prefix
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001842 void emit_vex2_byte0() { emit(0xc5); }
1843 inline void emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
1844 SIMDPrefix pp);
1845 void emit_vex3_byte0() { emit(0xc4); }
1846 inline void emit_vex3_byte1(XMMRegister reg, XMMRegister rm, LeadingOpcode m);
1847 inline void emit_vex3_byte1(XMMRegister reg, const Operand& rm,
1848 LeadingOpcode m);
1849 inline void emit_vex3_byte2(VexW w, XMMRegister v, VectorLength l,
1850 SIMDPrefix pp);
1851 inline void emit_vex_prefix(XMMRegister reg, XMMRegister v, XMMRegister rm,
1852 VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1853 VexW w);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001854 inline void emit_vex_prefix(Register reg, Register v, Register rm,
1855 VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1856 VexW w);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001857 inline void emit_vex_prefix(XMMRegister reg, XMMRegister v, const Operand& rm,
1858 VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1859 VexW w);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001860 inline void emit_vex_prefix(Register reg, Register v, const Operand& rm,
1861 VectorLength l, SIMDPrefix pp, LeadingOpcode m,
1862 VexW w);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001863
Steve Blocka7e24c12009-10-30 11:49:00 +00001864 // Emit the ModR/M byte, and optionally the SIB byte and
1865 // 1- or 4-byte offset for a memory operand. Also encodes
1866 // the second operand of the operation, a register or operation
1867 // subcode, into the reg field of the ModR/M byte.
1868 void emit_operand(Register reg, const Operand& adr) {
1869 emit_operand(reg.low_bits(), adr);
1870 }
1871
1872 // Emit the ModR/M byte, and optionally the SIB byte and
1873 // 1- or 4-byte offset for a memory operand. Also used to encode
1874 // a three-bit opcode extension into the ModR/M byte.
1875 void emit_operand(int rm, const Operand& adr);
1876
1877 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1878 void emit_modrm(Register reg, Register rm_reg) {
1879 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1880 }
1881
1882 // Emit a ModR/M byte with an operation subcode in the reg field and
1883 // a register in the rm_reg field.
1884 void emit_modrm(int code, Register rm_reg) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001885 DCHECK(is_uint3(code));
Steve Blocka7e24c12009-10-30 11:49:00 +00001886 emit(0xC0 | code << 3 | rm_reg.low_bits());
1887 }
1888
1889 // Emit the code-object-relative offset of the label's position
1890 inline void emit_code_relative_offset(Label* label);
1891
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001892 // The first argument is the reg field, the second argument is the r/m field.
1893 void emit_sse_operand(XMMRegister dst, XMMRegister src);
1894 void emit_sse_operand(XMMRegister reg, const Operand& adr);
1895 void emit_sse_operand(Register reg, const Operand& adr);
1896 void emit_sse_operand(XMMRegister dst, Register src);
1897 void emit_sse_operand(Register dst, XMMRegister src);
1898
Steve Blocka7e24c12009-10-30 11:49:00 +00001899 // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1900 // AND, OR, XOR, or CMP. The encodings of these operations are all
1901 // similar, differing just in the opcode or in the reg field of the
1902 // ModR/M byte.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001903 void arithmetic_op_8(byte opcode, Register reg, Register rm_reg);
1904 void arithmetic_op_8(byte opcode, Register reg, const Operand& rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001905 void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1906 void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001907 // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
1908 void arithmetic_op(byte opcode, Register reg, Register rm_reg, int size);
1909 void arithmetic_op(byte opcode,
1910 Register reg,
1911 const Operand& rm_reg,
1912 int size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001913 // Operate on a byte in memory or register.
1914 void immediate_arithmetic_op_8(byte subcode,
1915 Register dst,
1916 Immediate src);
1917 void immediate_arithmetic_op_8(byte subcode,
1918 const Operand& dst,
1919 Immediate src);
1920 // Operate on a word in memory or register.
1921 void immediate_arithmetic_op_16(byte subcode,
1922 Register dst,
1923 Immediate src);
1924 void immediate_arithmetic_op_16(byte subcode,
1925 const Operand& dst,
1926 Immediate src);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001927 // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
1928 void immediate_arithmetic_op(byte subcode,
1929 Register dst,
1930 Immediate src,
1931 int size);
1932 void immediate_arithmetic_op(byte subcode,
1933 const Operand& dst,
1934 Immediate src,
1935 int size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001936
1937 // Emit machine code for a shift operation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001938 void shift(Operand dst, Immediate shift_amount, int subcode, int size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001939 void shift(Register dst, Immediate shift_amount, int subcode, int size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001940 // Shift dst by cl % 64 bits.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001941 void shift(Register dst, int subcode, int size);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001942 void shift(Operand dst, int subcode, int size);
Steve Blocka7e24c12009-10-30 11:49:00 +00001943
1944 void emit_farith(int b1, int b2, int i);
1945
1946 // labels
1947 // void print(Label* L);
1948 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001949
1950 // record reloc info for current pc_
1951 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1952
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001953 // Arithmetics
1954 void emit_add(Register dst, Register src, int size) {
1955 arithmetic_op(0x03, dst, src, size);
1956 }
1957
1958 void emit_add(Register dst, Immediate src, int size) {
1959 immediate_arithmetic_op(0x0, dst, src, size);
1960 }
1961
1962 void emit_add(Register dst, const Operand& src, int size) {
1963 arithmetic_op(0x03, dst, src, size);
1964 }
1965
1966 void emit_add(const Operand& dst, Register src, int size) {
1967 arithmetic_op(0x1, src, dst, size);
1968 }
1969
1970 void emit_add(const Operand& dst, Immediate src, int size) {
1971 immediate_arithmetic_op(0x0, dst, src, size);
1972 }
1973
1974 void emit_and(Register dst, Register src, int size) {
1975 arithmetic_op(0x23, dst, src, size);
1976 }
1977
1978 void emit_and(Register dst, const Operand& src, int size) {
1979 arithmetic_op(0x23, dst, src, size);
1980 }
1981
1982 void emit_and(const Operand& dst, Register src, int size) {
1983 arithmetic_op(0x21, src, dst, size);
1984 }
1985
1986 void emit_and(Register dst, Immediate src, int size) {
1987 immediate_arithmetic_op(0x4, dst, src, size);
1988 }
1989
1990 void emit_and(const Operand& dst, Immediate src, int size) {
1991 immediate_arithmetic_op(0x4, dst, src, size);
1992 }
1993
1994 void emit_cmp(Register dst, Register src, int size) {
1995 arithmetic_op(0x3B, dst, src, size);
1996 }
1997
1998 void emit_cmp(Register dst, const Operand& src, int size) {
1999 arithmetic_op(0x3B, dst, src, size);
2000 }
2001
2002 void emit_cmp(const Operand& dst, Register src, int size) {
2003 arithmetic_op(0x39, src, dst, size);
2004 }
2005
2006 void emit_cmp(Register dst, Immediate src, int size) {
2007 immediate_arithmetic_op(0x7, dst, src, size);
2008 }
2009
2010 void emit_cmp(const Operand& dst, Immediate src, int size) {
2011 immediate_arithmetic_op(0x7, dst, src, size);
2012 }
2013
2014 void emit_dec(Register dst, int size);
2015 void emit_dec(const Operand& dst, int size);
2016
2017 // Divide rdx:rax by src. Quotient in rax, remainder in rdx when size is 64.
2018 // Divide edx:eax by lower 32 bits of src. Quotient in eax, remainder in edx
2019 // when size is 32.
2020 void emit_idiv(Register src, int size);
2021 void emit_div(Register src, int size);
2022
2023 // Signed multiply instructions.
2024 // rdx:rax = rax * src when size is 64 or edx:eax = eax * src when size is 32.
2025 void emit_imul(Register src, int size);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002026 void emit_imul(const Operand& src, int size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002027 void emit_imul(Register dst, Register src, int size);
2028 void emit_imul(Register dst, const Operand& src, int size);
2029 void emit_imul(Register dst, Register src, Immediate imm, int size);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002030 void emit_imul(Register dst, const Operand& src, Immediate imm, int size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002031
2032 void emit_inc(Register dst, int size);
2033 void emit_inc(const Operand& dst, int size);
2034
2035 void emit_lea(Register dst, const Operand& src, int size);
2036
2037 void emit_mov(Register dst, const Operand& src, int size);
2038 void emit_mov(Register dst, Register src, int size);
2039 void emit_mov(const Operand& dst, Register src, int size);
2040 void emit_mov(Register dst, Immediate value, int size);
2041 void emit_mov(const Operand& dst, Immediate value, int size);
2042
2043 void emit_movzxb(Register dst, const Operand& src, int size);
2044 void emit_movzxb(Register dst, Register src, int size);
2045 void emit_movzxw(Register dst, const Operand& src, int size);
2046 void emit_movzxw(Register dst, Register src, int size);
2047
2048 void emit_neg(Register dst, int size);
2049 void emit_neg(const Operand& dst, int size);
2050
2051 void emit_not(Register dst, int size);
2052 void emit_not(const Operand& dst, int size);
2053
2054 void emit_or(Register dst, Register src, int size) {
2055 arithmetic_op(0x0B, dst, src, size);
2056 }
2057
2058 void emit_or(Register dst, const Operand& src, int size) {
2059 arithmetic_op(0x0B, dst, src, size);
2060 }
2061
2062 void emit_or(const Operand& dst, Register src, int size) {
2063 arithmetic_op(0x9, src, dst, size);
2064 }
2065
2066 void emit_or(Register dst, Immediate src, int size) {
2067 immediate_arithmetic_op(0x1, dst, src, size);
2068 }
2069
2070 void emit_or(const Operand& dst, Immediate src, int size) {
2071 immediate_arithmetic_op(0x1, dst, src, size);
2072 }
2073
2074 void emit_repmovs(int size);
2075
2076 void emit_sbb(Register dst, Register src, int size) {
2077 arithmetic_op(0x1b, dst, src, size);
2078 }
2079
2080 void emit_sub(Register dst, Register src, int size) {
2081 arithmetic_op(0x2B, dst, src, size);
2082 }
2083
2084 void emit_sub(Register dst, Immediate src, int size) {
2085 immediate_arithmetic_op(0x5, dst, src, size);
2086 }
2087
2088 void emit_sub(Register dst, const Operand& src, int size) {
2089 arithmetic_op(0x2B, dst, src, size);
2090 }
2091
2092 void emit_sub(const Operand& dst, Register src, int size) {
2093 arithmetic_op(0x29, src, dst, size);
2094 }
2095
2096 void emit_sub(const Operand& dst, Immediate src, int size) {
2097 immediate_arithmetic_op(0x5, dst, src, size);
2098 }
2099
2100 void emit_test(Register dst, Register src, int size);
2101 void emit_test(Register reg, Immediate mask, int size);
2102 void emit_test(const Operand& op, Register reg, int size);
2103 void emit_test(const Operand& op, Immediate mask, int size);
2104 void emit_test(Register reg, const Operand& op, int size) {
2105 return emit_test(op, reg, size);
2106 }
2107
2108 void emit_xchg(Register dst, Register src, int size);
2109 void emit_xchg(Register dst, const Operand& src, int size);
2110
2111 void emit_xor(Register dst, Register src, int size) {
2112 if (size == kInt64Size && dst.code() == src.code()) {
2113 // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
2114 // there is no need to make this a 64 bit operation.
2115 arithmetic_op(0x33, dst, src, kInt32Size);
2116 } else {
2117 arithmetic_op(0x33, dst, src, size);
2118 }
2119 }
2120
2121 void emit_xor(Register dst, const Operand& src, int size) {
2122 arithmetic_op(0x33, dst, src, size);
2123 }
2124
2125 void emit_xor(Register dst, Immediate src, int size) {
2126 immediate_arithmetic_op(0x6, dst, src, size);
2127 }
2128
2129 void emit_xor(const Operand& dst, Immediate src, int size) {
2130 immediate_arithmetic_op(0x6, dst, src, size);
2131 }
2132
2133 void emit_xor(const Operand& dst, Register src, int size) {
2134 arithmetic_op(0x31, src, dst, size);
2135 }
2136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002137 // Most BMI instructions are similiar.
2138 void bmi1q(byte op, Register reg, Register vreg, Register rm);
2139 void bmi1q(byte op, Register reg, Register vreg, const Operand& rm);
2140 void bmi1l(byte op, Register reg, Register vreg, Register rm);
2141 void bmi1l(byte op, Register reg, Register vreg, const Operand& rm);
2142 void bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg, Register rm);
2143 void bmi2q(SIMDPrefix pp, byte op, Register reg, Register vreg,
2144 const Operand& rm);
2145 void bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg, Register rm);
2146 void bmi2l(SIMDPrefix pp, byte op, Register reg, Register vreg,
2147 const Operand& rm);
2148
Steve Blocka7e24c12009-10-30 11:49:00 +00002149 friend class CodePatcher;
2150 friend class EnsureSpace;
2151 friend class RegExpMacroAssemblerX64;
2152
Steve Blocka7e24c12009-10-30 11:49:00 +00002153 // code generation
Steve Blocka7e24c12009-10-30 11:49:00 +00002154 RelocInfoWriter reloc_info_writer;
2155
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002156 // Internal reference positions, required for (potential) patching in
2157 // GrowBuffer(); contains only those internal references whose labels
2158 // are already bound.
2159 std::deque<int> internal_reference_positions_;
2160
Steve Block3ce2e202009-11-05 08:53:23 +00002161 List< Handle<Code> > code_targets_;
Steve Blocka7e24c12009-10-30 11:49:00 +00002162
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08002163 PositionsRecorder positions_recorder_;
2164 friend class PositionsRecorder;
Steve Blocka7e24c12009-10-30 11:49:00 +00002165};
2166
2167
2168// Helper class that ensures that there is enough space for generating
2169// instructions and relocation information. The constructor makes
2170// sure that there is enough space and (in debug mode) the destructor
2171// checks that we did not generate too much.
2172class EnsureSpace BASE_EMBEDDED {
2173 public:
2174 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
2175 if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
2176#ifdef DEBUG
2177 space_before_ = assembler_->available_space();
2178#endif
2179 }
2180
2181#ifdef DEBUG
2182 ~EnsureSpace() {
2183 int bytes_generated = space_before_ - assembler_->available_space();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002184 DCHECK(bytes_generated < assembler_->kGap);
Steve Blocka7e24c12009-10-30 11:49:00 +00002185 }
2186#endif
2187
2188 private:
2189 Assembler* assembler_;
2190#ifdef DEBUG
2191 int space_before_;
2192#endif
2193};
2194
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002195} // namespace internal
2196} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +00002197
2198#endif // V8_X64_ASSEMBLER_X64_H_