blob: be837f0448716f105cdb557d60ef6e7444005696 [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 Murdochb0fe1622011-05-05 13:52:32 +010033// Copyright 2010 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
Steve Blockd0582a62009-12-15 09:54:21 +000040#include "serialize.h"
41
Steve Blocka7e24c12009-10-30 11:49:00 +000042namespace v8 {
43namespace internal {
44
45// Utility functions
46
47// Test whether a 64-bit value is in a specific range.
48static inline bool is_uint32(int64_t x) {
Steve Block8defd9f2010-07-08 12:39:36 +010049 static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
50 return static_cast<uint64_t>(x) <= kMaxUInt32;
Steve Blocka7e24c12009-10-30 11:49:00 +000051}
52
53static inline bool is_int32(int64_t x) {
Steve Block8defd9f2010-07-08 12:39:36 +010054 static const int64_t kMinInt32 = -V8_INT64_C(0x80000000);
55 return is_uint32(x - kMinInt32);
Steve Blocka7e24c12009-10-30 11:49:00 +000056}
57
58static inline bool uint_is_int32(uint64_t x) {
Steve Block8defd9f2010-07-08 12:39:36 +010059 static const uint64_t kMaxInt32 = V8_UINT64_C(0x7fffffff);
60 return x <= kMaxInt32;
Steve Blocka7e24c12009-10-30 11:49:00 +000061}
62
63static inline bool is_uint32(uint64_t x) {
Steve Block8defd9f2010-07-08 12:39:36 +010064 static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
65 return x <= kMaxUInt32;
Steve Blocka7e24c12009-10-30 11:49:00 +000066}
67
68// CPU Registers.
69//
70// 1) We would prefer to use an enum, but enum values are assignment-
71// compatible with int, which has caused code-generation bugs.
72//
73// 2) We would prefer to use a class instead of a struct but we don't like
74// the register initialization to depend on the particular initialization
75// order (which appears to be different on OS X, Linux, and Windows for the
76// installed versions of C++ we tried). Using a struct permits C-style
77// "initialization". Also, the Register objects cannot be const as this
78// forces initialization stubs in MSVC, making us dependent on initialization
79// order.
80//
81// 3) By not using an enum, we are possibly preventing the compiler from
82// doing certain constant folds, which may significantly reduce the
83// code generated for some assembly instructions (because they boil down
84// to a few constants). If this is a problem, we could change the code
85// such that we use an enum in optimized mode, and the struct in debug
86// mode. This way we get the compile-time error checking in debug mode
87// and best performance in optimized code.
88//
89
90struct Register {
Ben Murdochb0fe1622011-05-05 13:52:32 +010091 // The non-allocatable registers are:
92 // rsp - stack pointer
93 // rbp - frame pointer
94 // rsi - context register
95 // r10 - fixed scratch register
96 // r13 - root register
97 // r15 - smi constant register
98 static const int kNumRegisters = 16;
99 static const int kNumAllocatableRegisters = 10;
100
Ben Murdochb8e0da22011-05-16 14:20:40 +0100101 static int ToAllocationIndex(Register reg) {
102 return allocationIndexByRegisterCode[reg.code()];
103 }
104
105 static Register FromAllocationIndex(int index) {
106 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
107 Register result = { registerCodeByAllocationIndex[index] };
108 return result;
109 }
110
Ben Murdochb0fe1622011-05-05 13:52:32 +0100111 static const char* AllocationIndexToString(int index) {
112 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
113 const char* const names[] = {
114 "rax",
Ben Murdochb0fe1622011-05-05 13:52:32 +0100115 "rbx",
Ben Murdochb8e0da22011-05-16 14:20:40 +0100116 "rdx",
117 "rcx",
Ben Murdochb0fe1622011-05-05 13:52:32 +0100118 "rdi",
119 "r8",
120 "r9",
121 "r11",
Ben Murdochb8e0da22011-05-16 14:20:40 +0100122 "r14",
123 "r12"
Ben Murdochb0fe1622011-05-05 13:52:32 +0100124 };
125 return names[index];
126 }
127
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 static Register toRegister(int code) {
129 Register r = { code };
130 return r;
131 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100132 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100133 bool is(Register reg) const { return code_ == reg.code_; }
134 int code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000135 ASSERT(is_valid());
136 return code_;
137 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100138 int bit() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000139 return 1 << code_;
140 }
141
142 // Return the high bit of the register code as a 0 or 1. Used often
143 // when constructing the REX prefix byte.
144 int high_bit() const {
145 return code_ >> 3;
146 }
147 // Return the 3 low bits of the register code. Used when encoding registers
148 // in modR/M, SIB, and opcode bytes.
149 int low_bits() const {
150 return code_ & 0x7;
151 }
152
Andrei Popescu31002712010-02-23 13:46:05 +0000153 // Unfortunately we can't make this private in a struct when initializing
154 // by assignment.
Steve Blocka7e24c12009-10-30 11:49:00 +0000155 int code_;
Ben Murdochb8e0da22011-05-16 14:20:40 +0100156 private:
157 static const int registerCodeByAllocationIndex[kNumAllocatableRegisters];
158 static const int allocationIndexByRegisterCode[kNumRegisters];
Steve Blocka7e24c12009-10-30 11:49:00 +0000159};
160
Andrei Popescu402d9372010-02-26 13:31:12 +0000161const Register rax = { 0 };
162const Register rcx = { 1 };
163const Register rdx = { 2 };
164const Register rbx = { 3 };
165const Register rsp = { 4 };
166const Register rbp = { 5 };
167const Register rsi = { 6 };
168const Register rdi = { 7 };
169const Register r8 = { 8 };
170const Register r9 = { 9 };
171const Register r10 = { 10 };
172const Register r11 = { 11 };
173const Register r12 = { 12 };
174const Register r13 = { 13 };
175const Register r14 = { 14 };
176const Register r15 = { 15 };
177const Register no_reg = { -1 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000178
179
180struct XMMRegister {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100181 static const int kNumRegisters = 16;
182 static const int kNumAllocatableRegisters = 15;
183
184 static int ToAllocationIndex(XMMRegister reg) {
185 ASSERT(reg.code() != 0);
186 return reg.code() - 1;
187 }
188
Ben Murdochb8e0da22011-05-16 14:20:40 +0100189 static XMMRegister FromAllocationIndex(int index) {
190 ASSERT(0 <= index && index < kNumAllocatableRegisters);
191 XMMRegister result = { index + 1 };
192 return result;
193 }
194
Ben Murdochb0fe1622011-05-05 13:52:32 +0100195 static const char* AllocationIndexToString(int index) {
196 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
197 const char* const names[] = {
198 "xmm1",
199 "xmm2",
200 "xmm3",
201 "xmm4",
202 "xmm5",
203 "xmm6",
204 "xmm7",
205 "xmm8",
206 "xmm9",
207 "xmm10",
208 "xmm11",
209 "xmm12",
210 "xmm13",
211 "xmm14",
212 "xmm15"
213 };
214 return names[index];
215 }
216
217 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100218 bool is(XMMRegister reg) const { return code_ == reg.code_; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100219 int code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 ASSERT(is_valid());
221 return code_;
222 }
223
224 // Return the high bit of the register code as a 0 or 1. Used often
225 // when constructing the REX prefix byte.
226 int high_bit() const {
227 return code_ >> 3;
228 }
229 // Return the 3 low bits of the register code. Used when encoding registers
230 // in modR/M, SIB, and opcode bytes.
231 int low_bits() const {
232 return code_ & 0x7;
233 }
234
235 int code_;
236};
237
Andrei Popescu402d9372010-02-26 13:31:12 +0000238const XMMRegister xmm0 = { 0 };
239const XMMRegister xmm1 = { 1 };
240const XMMRegister xmm2 = { 2 };
241const XMMRegister xmm3 = { 3 };
242const XMMRegister xmm4 = { 4 };
243const XMMRegister xmm5 = { 5 };
244const XMMRegister xmm6 = { 6 };
245const XMMRegister xmm7 = { 7 };
246const XMMRegister xmm8 = { 8 };
247const XMMRegister xmm9 = { 9 };
248const XMMRegister xmm10 = { 10 };
249const XMMRegister xmm11 = { 11 };
250const XMMRegister xmm12 = { 12 };
251const XMMRegister xmm13 = { 13 };
252const XMMRegister xmm14 = { 14 };
253const XMMRegister xmm15 = { 15 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000254
Ben Murdochb0fe1622011-05-05 13:52:32 +0100255
256typedef XMMRegister DoubleRegister;
257
258
Steve Blocka7e24c12009-10-30 11:49:00 +0000259enum Condition {
260 // any value < 0 is considered no_condition
261 no_condition = -1,
262
263 overflow = 0,
264 no_overflow = 1,
265 below = 2,
266 above_equal = 3,
267 equal = 4,
268 not_equal = 5,
269 below_equal = 6,
270 above = 7,
271 negative = 8,
272 positive = 9,
273 parity_even = 10,
274 parity_odd = 11,
275 less = 12,
276 greater_equal = 13,
277 less_equal = 14,
278 greater = 15,
279
Steve Block3ce2e202009-11-05 08:53:23 +0000280 // Fake conditions that are handled by the
281 // opcodes using them.
282 always = 16,
283 never = 17,
Steve Blocka7e24c12009-10-30 11:49:00 +0000284 // aliases
285 carry = below,
286 not_carry = above_equal,
287 zero = equal,
288 not_zero = not_equal,
289 sign = negative,
Steve Block3ce2e202009-11-05 08:53:23 +0000290 not_sign = positive,
291 last_condition = greater
Steve Blocka7e24c12009-10-30 11:49:00 +0000292};
293
294
295// Returns the equivalent of !cc.
296// Negation of the default no_condition (-1) results in a non-default
297// no_condition value (-2). As long as tests for no_condition check
298// for condition < 0, this will work as expected.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100299inline Condition NegateCondition(Condition cc) {
300 return static_cast<Condition>(cc ^ 1);
301}
302
Steve Blocka7e24c12009-10-30 11:49:00 +0000303
304// Corresponds to transposing the operands of a comparison.
305inline Condition ReverseCondition(Condition cc) {
306 switch (cc) {
307 case below:
308 return above;
309 case above:
310 return below;
311 case above_equal:
312 return below_equal;
313 case below_equal:
314 return above_equal;
315 case less:
316 return greater;
317 case greater:
318 return less;
319 case greater_equal:
320 return less_equal;
321 case less_equal:
322 return greater_equal;
323 default:
324 return cc;
325 };
326}
327
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100328
Steve Blocka7e24c12009-10-30 11:49:00 +0000329enum Hint {
330 no_hint = 0,
331 not_taken = 0x2e,
332 taken = 0x3e
333};
334
335// The result of negating a hint is as if the corresponding condition
336// were negated by NegateCondition. That is, no_hint is mapped to
337// itself and not_taken and taken are mapped to each other.
338inline Hint NegateHint(Hint hint) {
339 return (hint == no_hint)
340 ? no_hint
341 : ((hint == not_taken) ? taken : not_taken);
342}
343
344
345// -----------------------------------------------------------------------------
346// Machine instruction Immediates
347
348class Immediate BASE_EMBEDDED {
349 public:
350 explicit Immediate(int32_t value) : value_(value) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000351
352 private:
353 int32_t value_;
354
355 friend class Assembler;
356};
357
358
359// -----------------------------------------------------------------------------
360// Machine instruction Operands
361
362enum ScaleFactor {
363 times_1 = 0,
364 times_2 = 1,
365 times_4 = 2,
366 times_8 = 3,
367 times_int_size = times_4,
Steve Blocka7e24c12009-10-30 11:49:00 +0000368 times_pointer_size = times_8
369};
370
371
372class Operand BASE_EMBEDDED {
373 public:
374 // [base + disp/r]
375 Operand(Register base, int32_t disp);
376
377 // [base + index*scale + disp/r]
378 Operand(Register base,
379 Register index,
380 ScaleFactor scale,
381 int32_t disp);
382
383 // [index*scale + disp/r]
384 Operand(Register index,
385 ScaleFactor scale,
386 int32_t disp);
387
Leon Clarkef7060e22010-06-03 12:02:55 +0100388 // Offset from existing memory operand.
389 // Offset is added to existing displacement as 32-bit signed values and
390 // this must not overflow.
391 Operand(const Operand& base, int32_t offset);
392
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 private:
394 byte rex_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100395 byte buf_[6];
Steve Blocka7e24c12009-10-30 11:49:00 +0000396 // The number of bytes in buf_.
397 unsigned int len_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000398
399 // Set the ModR/M byte without an encoded 'reg' register. The
400 // register is encoded later as part of the emit_operand operation.
401 // set_modrm can be called before or after set_sib and set_disp*.
402 inline void set_modrm(int mod, Register rm);
403
404 // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
405 inline void set_sib(ScaleFactor scale, Register index, Register base);
406
407 // Adds operand displacement fields (offsets added to the memory address).
408 // Needs to be called after set_sib, not before it.
409 inline void set_disp8(int disp);
410 inline void set_disp32(int disp);
411
412 friend class Assembler;
413};
414
415
416// CpuFeatures keeps track of which features are supported by the target CPU.
417// Supported features must be enabled by a Scope before use.
418// Example:
419// if (CpuFeatures::IsSupported(SSE3)) {
420// CpuFeatures::Scope fscope(SSE3);
421// // Generate SSE3 floating point code.
422// } else {
423// // Generate standard x87 or SSE2 floating point code.
424// }
425class CpuFeatures : public AllStatic {
426 public:
Steve Blocka7e24c12009-10-30 11:49:00 +0000427 // Detect features of the target CPU. Set safe defaults if the serializer
428 // is enabled (snapshots must be portable).
Ben Murdochb0fe1622011-05-05 13:52:32 +0100429 static void Probe(bool portable);
Steve Blocka7e24c12009-10-30 11:49:00 +0000430 // Check whether a feature is supported by the target CPU.
Steve Blockd0582a62009-12-15 09:54:21 +0000431 static bool IsSupported(CpuFeature f) {
Steve Block3ce2e202009-11-05 08:53:23 +0000432 if (f == SSE2 && !FLAG_enable_sse2) return false;
433 if (f == SSE3 && !FLAG_enable_sse3) return false;
434 if (f == CMOV && !FLAG_enable_cmov) return false;
435 if (f == RDTSC && !FLAG_enable_rdtsc) return false;
436 if (f == SAHF && !FLAG_enable_sahf) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000437 return (supported_ & (V8_UINT64_C(1) << f)) != 0;
438 }
439 // Check whether a feature is currently enabled.
Steve Blockd0582a62009-12-15 09:54:21 +0000440 static bool IsEnabled(CpuFeature f) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 return (enabled_ & (V8_UINT64_C(1) << f)) != 0;
442 }
443 // Enable a specified feature within a scope.
444 class Scope BASE_EMBEDDED {
445#ifdef DEBUG
446 public:
Steve Blockd0582a62009-12-15 09:54:21 +0000447 explicit Scope(CpuFeature f) {
448 uint64_t mask = (V8_UINT64_C(1) << f);
Steve Blocka7e24c12009-10-30 11:49:00 +0000449 ASSERT(CpuFeatures::IsSupported(f));
Steve Blockd0582a62009-12-15 09:54:21 +0000450 ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000451 old_enabled_ = CpuFeatures::enabled_;
Steve Blockd0582a62009-12-15 09:54:21 +0000452 CpuFeatures::enabled_ |= mask;
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 }
454 ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
455 private:
456 uint64_t old_enabled_;
457#else
458 public:
Steve Blockd0582a62009-12-15 09:54:21 +0000459 explicit Scope(CpuFeature f) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000460#endif
461 };
462 private:
463 // Safe defaults include SSE2 and CMOV for X64. It is always available, if
464 // anyone checks, but they shouldn't need to check.
Steve Blockd0582a62009-12-15 09:54:21 +0000465 static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
Steve Blocka7e24c12009-10-30 11:49:00 +0000466 static uint64_t supported_;
467 static uint64_t enabled_;
Steve Blockd0582a62009-12-15 09:54:21 +0000468 static uint64_t found_by_runtime_probing_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000469};
470
471
472class Assembler : public Malloced {
473 private:
474 // We check before assembling an instruction that there is sufficient
475 // space to write an instruction and its relocation information.
476 // The relocation writer's position must be kGap bytes above the end of
477 // the generated instructions. This leaves enough space for the
478 // longest possible x64 instruction, 15 bytes, and the longest possible
479 // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
480 // (There is a 15 byte limit on x64 instruction length that rules out some
481 // otherwise valid instructions.)
482 // This allows for a single, fast space check per instruction.
483 static const int kGap = 32;
484
485 public:
486 // Create an assembler. Instructions and relocation information are emitted
487 // into a buffer, with the instructions starting from the beginning and the
488 // relocation information starting from the end of the buffer. See CodeDesc
489 // for a detailed comment on the layout (globals.h).
490 //
491 // If the provided buffer is NULL, the assembler allocates and grows its own
492 // buffer, and buffer_size determines the initial buffer size. The buffer is
493 // owned by the assembler and deallocated upon destruction of the assembler.
494 //
495 // If the provided buffer is not NULL, the assembler uses the provided buffer
496 // for code generation and assumes its size to be buffer_size. If the buffer
497 // is too small, a fatal error occurs. No deallocation of the buffer is done
498 // upon destruction of the assembler.
499 Assembler(void* buffer, int buffer_size);
500 ~Assembler();
501
502 // GetCode emits any pending (non-emitted) code and fills the descriptor
503 // desc. GetCode() is idempotent; it returns the same result if no other
504 // Assembler functions are invoked in between GetCode() calls.
505 void GetCode(CodeDesc* desc);
506
Steve Block3ce2e202009-11-05 08:53:23 +0000507 // Read/Modify the code target in the relative branch/call instruction at pc.
508 // On the x64 architecture, we use relative jumps with a 32-bit displacement
509 // to jump to other Code objects in the Code space in the heap.
510 // Jumps to C functions are done indirectly through a 64-bit register holding
511 // the absolute address of the target.
512 // These functions convert between absolute Addresses of Code objects and
513 // the relative displacements stored in the code.
Steve Blocka7e24c12009-10-30 11:49:00 +0000514 static inline Address target_address_at(Address pc);
515 static inline void set_target_address_at(Address pc, Address target);
Steve Blockd0582a62009-12-15 09:54:21 +0000516
517 // This sets the branch destination (which is in the instruction on x64).
518 // This is for calls and branches within generated code.
519 inline static void set_target_at(Address instruction_payload,
520 Address target) {
521 set_target_address_at(instruction_payload, target);
522 }
523
524 // This sets the branch destination (which is a load instruction on x64).
525 // This is for calls and branches to runtime code.
526 inline static void set_external_target_at(Address instruction_payload,
527 Address target) {
528 *reinterpret_cast<Address*>(instruction_payload) = target;
529 }
530
Steve Block3ce2e202009-11-05 08:53:23 +0000531 inline Handle<Object> code_target_object_handle_at(Address pc);
Steve Blockd0582a62009-12-15 09:54:21 +0000532 // Number of bytes taken up by the branch target in the code.
533 static const int kCallTargetSize = 4; // Use 32-bit displacement.
534 static const int kExternalTargetSize = 8; // Use 64-bit absolute.
Steve Blocka7e24c12009-10-30 11:49:00 +0000535 // Distance between the address of the code target in the call instruction
Steve Block3ce2e202009-11-05 08:53:23 +0000536 // and the return address pushed on the stack.
537 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
538 // Distance between the start of the JS return sequence and where the
539 // 32-bit displacement of a near call would be, relative to the pushed
540 // return address. TODO: Use return sequence length instead.
541 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
542 static const int kPatchReturnSequenceAddressOffset = 13 - 4;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100543 // Distance between start of patched debug break slot and where the
544 // 32-bit displacement of a near call would be, relative to the pushed
545 // return address. TODO: Use return sequence length instead.
546 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
547 static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
Steve Block3ce2e202009-11-05 08:53:23 +0000548 // TODO(X64): Rename this, removing the "Real", after changing the above.
549 static const int kRealPatchReturnSequenceAddressOffset = 2;
Steve Blockd0582a62009-12-15 09:54:21 +0000550
551 // The x64 JS return sequence is padded with int3 to make it large
552 // enough to hold a call instruction when the debugger patches it.
553 static const int kCallInstructionLength = 13;
554 static const int kJSReturnSequenceLength = 13;
555
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100556 // The debug break slot must be able to contain a call instruction.
557 static const int kDebugBreakSlotLength = kCallInstructionLength;
558
Steve Block9fac8402011-05-12 15:51:54 +0100559 // One byte opcode for test eax,0xXXXXXXXX.
560 static const byte kTestEaxByte = 0xA9;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100561
Steve Blocka7e24c12009-10-30 11:49:00 +0000562 // ---------------------------------------------------------------------------
563 // Code generation
564 //
565 // Function names correspond one-to-one to x64 instruction mnemonics.
566 // Unless specified otherwise, instructions operate on 64-bit operands.
567 //
568 // If we need versions of an assembly instruction that operate on different
569 // width arguments, we add a single-letter suffix specifying the width.
570 // This is done for the following instructions: mov, cmp, inc, dec,
571 // add, sub, and test.
572 // There are no versions of these instructions without the suffix.
573 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
574 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
575 // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
576 // - Instructions on 64-bit (quadword) operands/registers use 'q'.
577 //
578 // Some mnemonics, such as "and", are the same as C++ keywords.
579 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
580
581 // Insert the smallest number of nop instructions
582 // possible to align the pc offset to a multiple
583 // of m. m must be a power of 2.
584 void Align(int m);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100585 // Aligns code to something that's optimal for a jump target for the platform.
586 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000587
588 // Stack
589 void pushfq();
590 void popfq();
591
592 void push(Immediate value);
593 void push(Register src);
594 void push(const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000595
596 void pop(Register dst);
597 void pop(const Operand& dst);
598
599 void enter(Immediate size);
600 void leave();
601
602 // Moves
603 void movb(Register dst, const Operand& src);
604 void movb(Register dst, Immediate imm);
605 void movb(const Operand& dst, Register src);
606
Steve Block3ce2e202009-11-05 08:53:23 +0000607 // Move the low 16 bits of a 64-bit register value to a 16-bit
608 // memory location.
609 void movw(const Operand& dst, Register src);
610
Steve Blocka7e24c12009-10-30 11:49:00 +0000611 void movl(Register dst, Register src);
612 void movl(Register dst, const Operand& src);
613 void movl(const Operand& dst, Register src);
614 void movl(const Operand& dst, Immediate imm);
615 // Load a 32-bit immediate value, zero-extended to 64 bits.
616 void movl(Register dst, Immediate imm32);
617
618 // Move 64 bit register value to 64-bit memory location.
619 void movq(const Operand& dst, Register src);
620 // Move 64 bit memory location to 64-bit register value.
621 void movq(Register dst, const Operand& src);
622 void movq(Register dst, Register src);
623 // Sign extends immediate 32-bit value to 64 bits.
624 void movq(Register dst, Immediate x);
625 // Move the offset of the label location relative to the current
626 // position (after the move) to the destination.
627 void movl(const Operand& dst, Label* src);
628
629 // Move sign extended immediate to memory location.
630 void movq(const Operand& dst, Immediate value);
631 // New x64 instructions to load a 64-bit immediate into a register.
632 // All 64-bit immediates must have a relocation mode.
633 void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
634 void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
635 void movq(Register dst, const char* s, RelocInfo::Mode rmode);
636 // Moves the address of the external reference into the register.
637 void movq(Register dst, ExternalReference ext);
638 void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
639
Steve Block3ce2e202009-11-05 08:53:23 +0000640 void movsxbq(Register dst, const Operand& src);
641 void movsxwq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000642 void movsxlq(Register dst, Register src);
643 void movsxlq(Register dst, const Operand& src);
644 void movzxbq(Register dst, const Operand& src);
645 void movzxbl(Register dst, const Operand& src);
Steve Block3ce2e202009-11-05 08:53:23 +0000646 void movzxwq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000647 void movzxwl(Register dst, const Operand& src);
648
Leon Clarked91b9f72010-01-27 17:25:45 +0000649 // Repeated moves.
650
651 void repmovsb();
652 void repmovsw();
653 void repmovsl();
654 void repmovsq();
655
Steve Blocka7e24c12009-10-30 11:49:00 +0000656 // New x64 instruction to load from an immediate 64-bit pointer into RAX.
657 void load_rax(void* ptr, RelocInfo::Mode rmode);
658 void load_rax(ExternalReference ext);
659
660 // Conditional moves.
661 void cmovq(Condition cc, Register dst, Register src);
662 void cmovq(Condition cc, Register dst, const Operand& src);
663 void cmovl(Condition cc, Register dst, Register src);
664 void cmovl(Condition cc, Register dst, const Operand& src);
665
666 // Exchange two registers
667 void xchg(Register dst, Register src);
668
669 // Arithmetics
670 void addl(Register dst, Register src) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100671 arithmetic_op_32(0x03, dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000672 }
673
674 void addl(Register dst, Immediate src) {
675 immediate_arithmetic_op_32(0x0, dst, src);
676 }
677
678 void addl(Register dst, const Operand& src) {
679 arithmetic_op_32(0x03, dst, src);
680 }
681
682 void addl(const Operand& dst, Immediate src) {
683 immediate_arithmetic_op_32(0x0, dst, src);
684 }
685
686 void addq(Register dst, Register src) {
687 arithmetic_op(0x03, dst, src);
688 }
689
690 void addq(Register dst, const Operand& src) {
691 arithmetic_op(0x03, dst, src);
692 }
693
694 void addq(const Operand& dst, Register src) {
695 arithmetic_op(0x01, src, dst);
696 }
697
698 void addq(Register dst, Immediate src) {
699 immediate_arithmetic_op(0x0, dst, src);
700 }
701
702 void addq(const Operand& dst, Immediate src) {
703 immediate_arithmetic_op(0x0, dst, src);
704 }
705
Kristian Monsen25f61362010-05-21 11:50:48 +0100706 void sbbl(Register dst, Register src) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100707 arithmetic_op_32(0x1b, dst, src);
Kristian Monsen25f61362010-05-21 11:50:48 +0100708 }
709
Steve Blocka7e24c12009-10-30 11:49:00 +0000710 void cmpb(Register dst, Immediate src) {
711 immediate_arithmetic_op_8(0x7, dst, src);
712 }
713
714 void cmpb_al(Immediate src);
715
716 void cmpb(Register dst, Register src) {
717 arithmetic_op(0x3A, dst, src);
718 }
719
720 void cmpb(Register dst, const Operand& src) {
721 arithmetic_op(0x3A, dst, src);
722 }
723
724 void cmpb(const Operand& dst, Register src) {
725 arithmetic_op(0x38, src, dst);
726 }
727
728 void cmpb(const Operand& dst, Immediate src) {
729 immediate_arithmetic_op_8(0x7, dst, src);
730 }
731
732 void cmpw(const Operand& dst, Immediate src) {
733 immediate_arithmetic_op_16(0x7, dst, src);
734 }
735
736 void cmpw(Register dst, Immediate src) {
737 immediate_arithmetic_op_16(0x7, dst, src);
738 }
739
740 void cmpw(Register dst, const Operand& src) {
741 arithmetic_op_16(0x3B, dst, src);
742 }
743
744 void cmpw(Register dst, Register src) {
745 arithmetic_op_16(0x3B, dst, src);
746 }
747
748 void cmpw(const Operand& dst, Register src) {
749 arithmetic_op_16(0x39, src, dst);
750 }
751
752 void cmpl(Register dst, Register src) {
753 arithmetic_op_32(0x3B, dst, src);
754 }
755
756 void cmpl(Register dst, const Operand& src) {
757 arithmetic_op_32(0x3B, dst, src);
758 }
759
760 void cmpl(const Operand& dst, Register src) {
761 arithmetic_op_32(0x39, src, dst);
762 }
763
764 void cmpl(Register dst, Immediate src) {
765 immediate_arithmetic_op_32(0x7, dst, src);
766 }
767
768 void cmpl(const Operand& dst, Immediate src) {
769 immediate_arithmetic_op_32(0x7, dst, src);
770 }
771
772 void cmpq(Register dst, Register src) {
773 arithmetic_op(0x3B, dst, src);
774 }
775
776 void cmpq(Register dst, const Operand& src) {
777 arithmetic_op(0x3B, dst, src);
778 }
779
780 void cmpq(const Operand& dst, Register src) {
781 arithmetic_op(0x39, src, dst);
782 }
783
784 void cmpq(Register dst, Immediate src) {
785 immediate_arithmetic_op(0x7, dst, src);
786 }
787
788 void cmpq(const Operand& dst, Immediate src) {
789 immediate_arithmetic_op(0x7, dst, src);
790 }
791
792 void and_(Register dst, Register src) {
793 arithmetic_op(0x23, dst, src);
794 }
795
796 void and_(Register dst, const Operand& src) {
797 arithmetic_op(0x23, dst, src);
798 }
799
800 void and_(const Operand& dst, Register src) {
801 arithmetic_op(0x21, src, dst);
802 }
803
804 void and_(Register dst, Immediate src) {
805 immediate_arithmetic_op(0x4, dst, src);
806 }
807
808 void and_(const Operand& dst, Immediate src) {
809 immediate_arithmetic_op(0x4, dst, src);
810 }
811
812 void andl(Register dst, Immediate src) {
813 immediate_arithmetic_op_32(0x4, dst, src);
814 }
815
Steve Block3ce2e202009-11-05 08:53:23 +0000816 void andl(Register dst, Register src) {
817 arithmetic_op_32(0x23, dst, src);
818 }
819
Leon Clarke4515c472010-02-03 11:58:03 +0000820 void andb(Register dst, Immediate src) {
821 immediate_arithmetic_op_8(0x4, dst, src);
822 }
Steve Block3ce2e202009-11-05 08:53:23 +0000823
Steve Blocka7e24c12009-10-30 11:49:00 +0000824 void decq(Register dst);
825 void decq(const Operand& dst);
826 void decl(Register dst);
827 void decl(const Operand& dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000828 void decb(Register dst);
829 void decb(const Operand& dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000830
831 // Sign-extends rax into rdx:rax.
832 void cqo();
833 // Sign-extends eax into edx:eax.
834 void cdq();
835
836 // Divide rdx:rax by src. Quotient in rax, remainder in rdx.
837 void idivq(Register src);
838 // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx.
839 void idivl(Register src);
840
841 // Signed multiply instructions.
842 void imul(Register src); // rdx:rax = rax * src.
843 void imul(Register dst, Register src); // dst = dst * src.
844 void imul(Register dst, const Operand& src); // dst = dst * src.
845 void imul(Register dst, Register src, Immediate imm); // dst = src * imm.
Steve Block6ded16b2010-05-10 14:33:55 +0100846 // Signed 32-bit multiply instructions.
847 void imull(Register dst, Register src); // dst = dst * src.
848 void imull(Register dst, Register src, Immediate imm); // dst = src * imm.
Steve Blocka7e24c12009-10-30 11:49:00 +0000849
850 void incq(Register dst);
851 void incq(const Operand& dst);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100852 void incl(Register dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000853 void incl(const Operand& dst);
854
855 void lea(Register dst, const Operand& src);
Steve Block6ded16b2010-05-10 14:33:55 +0100856 void leal(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000857
858 // Multiply rax by src, put the result in rdx:rax.
859 void mul(Register src);
860
861 void neg(Register dst);
862 void neg(const Operand& dst);
863 void negl(Register dst);
864
865 void not_(Register dst);
866 void not_(const Operand& dst);
Steve Block6ded16b2010-05-10 14:33:55 +0100867 void notl(Register dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000868
869 void or_(Register dst, Register src) {
870 arithmetic_op(0x0B, dst, src);
871 }
872
873 void orl(Register dst, Register src) {
874 arithmetic_op_32(0x0B, dst, src);
875 }
876
877 void or_(Register dst, const Operand& src) {
878 arithmetic_op(0x0B, dst, src);
879 }
880
881 void or_(const Operand& dst, Register src) {
882 arithmetic_op(0x09, src, dst);
883 }
884
885 void or_(Register dst, Immediate src) {
886 immediate_arithmetic_op(0x1, dst, src);
887 }
888
Steve Block3ce2e202009-11-05 08:53:23 +0000889 void orl(Register dst, Immediate src) {
890 immediate_arithmetic_op_32(0x1, dst, src);
891 }
892
Steve Blocka7e24c12009-10-30 11:49:00 +0000893 void or_(const Operand& dst, Immediate src) {
894 immediate_arithmetic_op(0x1, dst, src);
895 }
896
Steve Block3ce2e202009-11-05 08:53:23 +0000897 void orl(const Operand& dst, Immediate src) {
898 immediate_arithmetic_op_32(0x1, dst, src);
899 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000900
Steve Block3ce2e202009-11-05 08:53:23 +0000901
902 void rcl(Register dst, Immediate imm8) {
903 shift(dst, imm8, 0x2);
904 }
905
906 void rol(Register dst, Immediate imm8) {
907 shift(dst, imm8, 0x0);
908 }
909
910 void rcr(Register dst, Immediate imm8) {
911 shift(dst, imm8, 0x3);
912 }
913
914 void ror(Register dst, Immediate imm8) {
915 shift(dst, imm8, 0x1);
916 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000917
918 // Shifts dst:src left by cl bits, affecting only dst.
919 void shld(Register dst, Register src);
920
921 // Shifts src:dst right by cl bits, affecting only dst.
922 void shrd(Register dst, Register src);
923
924 // Shifts dst right, duplicating sign bit, by shift_amount bits.
925 // Shifting by 1 is handled efficiently.
926 void sar(Register dst, Immediate shift_amount) {
927 shift(dst, shift_amount, 0x7);
928 }
929
930 // Shifts dst right, duplicating sign bit, by shift_amount bits.
931 // Shifting by 1 is handled efficiently.
932 void sarl(Register dst, Immediate shift_amount) {
933 shift_32(dst, shift_amount, 0x7);
934 }
935
936 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
Steve Blockd0582a62009-12-15 09:54:21 +0000937 void sar_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000938 shift(dst, 0x7);
939 }
940
941 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
Steve Blockd0582a62009-12-15 09:54:21 +0000942 void sarl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 shift_32(dst, 0x7);
944 }
945
946 void shl(Register dst, Immediate shift_amount) {
947 shift(dst, shift_amount, 0x4);
948 }
949
Steve Blockd0582a62009-12-15 09:54:21 +0000950 void shl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000951 shift(dst, 0x4);
952 }
953
Steve Blockd0582a62009-12-15 09:54:21 +0000954 void shll_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000955 shift_32(dst, 0x4);
956 }
957
958 void shll(Register dst, Immediate shift_amount) {
959 shift_32(dst, shift_amount, 0x4);
960 }
961
962 void shr(Register dst, Immediate shift_amount) {
963 shift(dst, shift_amount, 0x5);
964 }
965
Steve Blockd0582a62009-12-15 09:54:21 +0000966 void shr_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000967 shift(dst, 0x5);
968 }
969
Steve Blockd0582a62009-12-15 09:54:21 +0000970 void shrl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000971 shift_32(dst, 0x5);
972 }
973
974 void shrl(Register dst, Immediate shift_amount) {
975 shift_32(dst, shift_amount, 0x5);
976 }
977
978 void store_rax(void* dst, RelocInfo::Mode mode);
979 void store_rax(ExternalReference ref);
980
981 void subq(Register dst, Register src) {
982 arithmetic_op(0x2B, dst, src);
983 }
984
985 void subq(Register dst, const Operand& src) {
986 arithmetic_op(0x2B, dst, src);
987 }
988
989 void subq(const Operand& dst, Register src) {
990 arithmetic_op(0x29, src, dst);
991 }
992
993 void subq(Register dst, Immediate src) {
994 immediate_arithmetic_op(0x5, dst, src);
995 }
996
997 void subq(const Operand& dst, Immediate src) {
998 immediate_arithmetic_op(0x5, dst, src);
999 }
1000
1001 void subl(Register dst, Register src) {
1002 arithmetic_op_32(0x2B, dst, src);
1003 }
1004
Leon Clarkee46be812010-01-19 14:06:41 +00001005 void subl(Register dst, const Operand& src) {
1006 arithmetic_op_32(0x2B, dst, src);
1007 }
1008
Steve Blocka7e24c12009-10-30 11:49:00 +00001009 void subl(const Operand& dst, Immediate src) {
1010 immediate_arithmetic_op_32(0x5, dst, src);
1011 }
1012
1013 void subl(Register dst, Immediate src) {
1014 immediate_arithmetic_op_32(0x5, dst, src);
1015 }
1016
1017 void subb(Register dst, Immediate src) {
1018 immediate_arithmetic_op_8(0x5, dst, src);
1019 }
1020
Steve Block3ce2e202009-11-05 08:53:23 +00001021 void testb(Register dst, Register src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001022 void testb(Register reg, Immediate mask);
1023 void testb(const Operand& op, Immediate mask);
Leon Clarkee46be812010-01-19 14:06:41 +00001024 void testb(const Operand& op, Register reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001025 void testl(Register dst, Register src);
1026 void testl(Register reg, Immediate mask);
1027 void testl(const Operand& op, Immediate mask);
1028 void testq(const Operand& op, Register reg);
1029 void testq(Register dst, Register src);
1030 void testq(Register dst, Immediate mask);
1031
1032 void xor_(Register dst, Register src) {
Steve Blockd0582a62009-12-15 09:54:21 +00001033 if (dst.code() == src.code()) {
1034 arithmetic_op_32(0x33, dst, src);
1035 } else {
1036 arithmetic_op(0x33, dst, src);
1037 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001038 }
1039
1040 void xorl(Register dst, Register src) {
1041 arithmetic_op_32(0x33, dst, src);
1042 }
1043
1044 void xor_(Register dst, const Operand& src) {
1045 arithmetic_op(0x33, dst, src);
1046 }
1047
1048 void xor_(const Operand& dst, Register src) {
1049 arithmetic_op(0x31, src, dst);
1050 }
1051
1052 void xor_(Register dst, Immediate src) {
1053 immediate_arithmetic_op(0x6, dst, src);
1054 }
1055
1056 void xor_(const Operand& dst, Immediate src) {
1057 immediate_arithmetic_op(0x6, dst, src);
1058 }
1059
1060 // Bit operations.
1061 void bt(const Operand& dst, Register src);
1062 void bts(const Operand& dst, Register src);
1063
1064 // Miscellaneous
Steve Block3ce2e202009-11-05 08:53:23 +00001065 void clc();
Steve Blocka7e24c12009-10-30 11:49:00 +00001066 void cpuid();
1067 void hlt();
1068 void int3();
1069 void nop();
1070 void nop(int n);
1071 void rdtsc();
1072 void ret(int imm16);
1073 void setcc(Condition cc, Register reg);
1074
1075 // Label operations & relative jumps (PPUM Appendix D)
1076 //
1077 // Takes a branch opcode (cc) and a label (L) and generates
1078 // either a backward branch or a forward branch and links it
1079 // to the label fixup chain. Usage:
1080 //
1081 // Label L; // unbound label
1082 // j(cc, &L); // forward branch to unbound label
1083 // bind(&L); // bind label to the current pc
1084 // j(cc, &L); // backward branch to bound label
1085 // bind(&L); // illegal: a label may be bound only once
1086 //
1087 // Note: The same Label can be used for forward and backward branches
1088 // but it may be bound only once.
1089
1090 void bind(Label* L); // binds an unbound label L to the current code position
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001091 void bind(NearLabel* L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001092
1093 // Calls
1094 // Call near relative 32-bit displacement, relative to next instruction.
1095 void call(Label* L);
Steve Block3ce2e202009-11-05 08:53:23 +00001096 void call(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001097
1098 // Call near absolute indirect, address in register
1099 void call(Register adr);
1100
1101 // Call near indirect
1102 void call(const Operand& operand);
1103
1104 // Jumps
1105 // Jump short or near relative.
Steve Block3ce2e202009-11-05 08:53:23 +00001106 // Use a 32-bit signed displacement.
Steve Blocka7e24c12009-10-30 11:49:00 +00001107 void jmp(Label* L); // unconditional jump to L
Steve Block3ce2e202009-11-05 08:53:23 +00001108 void jmp(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001109
1110 // Jump near absolute indirect (r64)
1111 void jmp(Register adr);
1112
1113 // Jump near absolute indirect (m64)
1114 void jmp(const Operand& src);
1115
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001116 // Short jump
1117 void jmp(NearLabel* L);
1118
Steve Blocka7e24c12009-10-30 11:49:00 +00001119 // Conditional jumps
1120 void j(Condition cc, Label* L);
Steve Block3ce2e202009-11-05 08:53:23 +00001121 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001122
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001123 // Conditional short jump
1124 void j(Condition cc, NearLabel* L, Hint hint = no_hint);
1125
Steve Blocka7e24c12009-10-30 11:49:00 +00001126 // Floating-point operations
1127 void fld(int i);
1128
1129 void fld1();
1130 void fldz();
Steve Block6ded16b2010-05-10 14:33:55 +01001131 void fldpi();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001132 void fldln2();
Steve Blocka7e24c12009-10-30 11:49:00 +00001133
1134 void fld_s(const Operand& adr);
1135 void fld_d(const Operand& adr);
1136
1137 void fstp_s(const Operand& adr);
1138 void fstp_d(const Operand& adr);
Steve Block3ce2e202009-11-05 08:53:23 +00001139 void fstp(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001140
1141 void fild_s(const Operand& adr);
1142 void fild_d(const Operand& adr);
1143
1144 void fist_s(const Operand& adr);
1145
1146 void fistp_s(const Operand& adr);
1147 void fistp_d(const Operand& adr);
1148
1149 void fisttp_s(const Operand& adr);
Leon Clarked91b9f72010-01-27 17:25:45 +00001150 void fisttp_d(const Operand& adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001151
1152 void fabs();
1153 void fchs();
1154
1155 void fadd(int i);
1156 void fsub(int i);
1157 void fmul(int i);
1158 void fdiv(int i);
1159
1160 void fisub_s(const Operand& adr);
1161
1162 void faddp(int i = 1);
1163 void fsubp(int i = 1);
1164 void fsubrp(int i = 1);
1165 void fmulp(int i = 1);
1166 void fdivp(int i = 1);
1167 void fprem();
1168 void fprem1();
1169
1170 void fxch(int i = 1);
1171 void fincstp();
1172 void ffree(int i = 0);
1173
1174 void ftst();
1175 void fucomp(int i);
1176 void fucompp();
Steve Block3ce2e202009-11-05 08:53:23 +00001177 void fucomi(int i);
1178 void fucomip();
1179
Steve Blocka7e24c12009-10-30 11:49:00 +00001180 void fcompp();
1181 void fnstsw_ax();
1182 void fwait();
1183 void fnclex();
1184
1185 void fsin();
1186 void fcos();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001187 void fyl2x();
Steve Blocka7e24c12009-10-30 11:49:00 +00001188
1189 void frndint();
1190
1191 void sahf();
1192
1193 // SSE2 instructions
Steve Block6ded16b2010-05-10 14:33:55 +01001194 void movd(XMMRegister dst, Register src);
1195 void movd(Register dst, XMMRegister src);
1196 void movq(XMMRegister dst, Register src);
1197 void movq(Register dst, XMMRegister src);
1198 void extractps(Register dst, XMMRegister src, byte imm8);
1199
Steve Blocka7e24c12009-10-30 11:49:00 +00001200 void movsd(const Operand& dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001201 void movsd(XMMRegister dst, XMMRegister src);
1202 void movsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001203
Steve Block8defd9f2010-07-08 12:39:36 +01001204 void movss(XMMRegister dst, const Operand& src);
1205 void movss(const Operand& dst, XMMRegister src);
1206
Steve Blocka7e24c12009-10-30 11:49:00 +00001207 void cvttss2si(Register dst, const Operand& src);
1208 void cvttsd2si(Register dst, const Operand& src);
Kristian Monsen25f61362010-05-21 11:50:48 +01001209 void cvttsd2siq(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001210
1211 void cvtlsi2sd(XMMRegister dst, const Operand& src);
1212 void cvtlsi2sd(XMMRegister dst, Register src);
1213 void cvtqsi2sd(XMMRegister dst, const Operand& src);
1214 void cvtqsi2sd(XMMRegister dst, Register src);
1215
Steve Block8defd9f2010-07-08 12:39:36 +01001216 void cvtlsi2ss(XMMRegister dst, Register src);
1217
Steve Block6ded16b2010-05-10 14:33:55 +01001218 void cvtss2sd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001219 void cvtss2sd(XMMRegister dst, const Operand& src);
1220 void cvtsd2ss(XMMRegister dst, XMMRegister src);
1221
1222 void cvtsd2si(Register dst, XMMRegister src);
1223 void cvtsd2siq(Register dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001224
Steve Blocka7e24c12009-10-30 11:49:00 +00001225 void addsd(XMMRegister dst, XMMRegister src);
1226 void subsd(XMMRegister dst, XMMRegister src);
1227 void mulsd(XMMRegister dst, XMMRegister src);
1228 void divsd(XMMRegister dst, XMMRegister src);
1229
Andrei Popescu402d9372010-02-26 13:31:12 +00001230 void xorpd(XMMRegister dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001231 void sqrtsd(XMMRegister dst, XMMRegister src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001232
Andrei Popescu402d9372010-02-26 13:31:12 +00001233 void ucomisd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001234 void ucomisd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001235
Steve Block6ded16b2010-05-10 14:33:55 +01001236 // The first argument is the reg field, the second argument is the r/m field.
Steve Blocka7e24c12009-10-30 11:49:00 +00001237 void emit_sse_operand(XMMRegister dst, XMMRegister src);
1238 void emit_sse_operand(XMMRegister reg, const Operand& adr);
1239 void emit_sse_operand(XMMRegister dst, Register src);
Steve Block6ded16b2010-05-10 14:33:55 +01001240 void emit_sse_operand(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001241
1242 // Use either movsd or movlpd.
1243 // void movdbl(XMMRegister dst, const Operand& src);
1244 // void movdbl(const Operand& dst, XMMRegister src);
1245
1246 // Debugging
1247 void Print();
1248
1249 // Check the code size generated from label to here.
1250 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); }
1251
1252 // Mark address of the ExitJSFrame code.
1253 void RecordJSReturn();
1254
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001255 // Mark address of a debug break slot.
1256 void RecordDebugBreakSlot();
1257
Steve Blocka7e24c12009-10-30 11:49:00 +00001258 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001259 // Use --code-comments to enable.
Steve Blocka7e24c12009-10-30 11:49:00 +00001260 void RecordComment(const char* msg);
1261
Ben Murdochb0fe1622011-05-05 13:52:32 +01001262 // Writes a single word of data in the code stream.
1263 // Used for inline tables, e.g., jump-tables.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001264 void db(uint8_t data);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001265 void dd(uint32_t data);
1266
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001267 int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001268
1269 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001270
1271 // Check if there is less than kGap bytes available in the buffer.
1272 // If this is the case, we need to grow the buffer before emitting
1273 // an instruction or relocation information.
1274 inline bool buffer_overflow() const {
1275 return pc_ >= reloc_info_writer.pos() - kGap;
1276 }
1277
1278 // Get the number of bytes available in the buffer.
Steve Blockd0582a62009-12-15 09:54:21 +00001279 inline int available_space() const {
1280 return static_cast<int>(reloc_info_writer.pos() - pc_);
1281 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001282
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001283 static bool IsNop(Address addr) { return *addr == 0x90; }
1284
Steve Blocka7e24c12009-10-30 11:49:00 +00001285 // Avoid overflows for displacements etc.
1286 static const int kMaximalBufferSize = 512*MB;
1287 static const int kMinimalBufferSize = 4*KB;
1288
Steve Blocka7e24c12009-10-30 11:49:00 +00001289 private:
1290 byte* addr_at(int pos) { return buffer_ + pos; }
1291 byte byte_at(int pos) { return buffer_[pos]; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001292 void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001293 uint32_t long_at(int pos) {
1294 return *reinterpret_cast<uint32_t*>(addr_at(pos));
1295 }
1296 void long_at_put(int pos, uint32_t x) {
1297 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1298 }
1299
1300 // code emission
1301 void GrowBuffer();
1302
1303 void emit(byte x) { *pc_++ = x; }
1304 inline void emitl(uint32_t x);
Steve Blocka7e24c12009-10-30 11:49:00 +00001305 inline void emitq(uint64_t x, RelocInfo::Mode rmode);
1306 inline void emitw(uint16_t x);
Steve Block3ce2e202009-11-05 08:53:23 +00001307 inline void emit_code_target(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 void emit(Immediate x) { emitl(x.value_); }
1309
1310 // Emits a REX prefix that encodes a 64-bit operand size and
1311 // the top bit of both register codes.
1312 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1313 // REX.W is set.
Steve Blocka7e24c12009-10-30 11:49:00 +00001314 inline void emit_rex_64(XMMRegister reg, Register rm_reg);
Steve Block6ded16b2010-05-10 14:33:55 +01001315 inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1316 inline void emit_rex_64(Register reg, Register rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001317
1318 // Emits a REX prefix that encodes a 64-bit operand size and
1319 // the top bit of the destination, index, and base register codes.
1320 // The high bit of reg is used for REX.R, the high bit of op's base
1321 // register is used for REX.B, and the high bit of op's index register
1322 // is used for REX.X. REX.W is set.
1323 inline void emit_rex_64(Register reg, const Operand& op);
1324 inline void emit_rex_64(XMMRegister reg, const Operand& op);
1325
1326 // Emits a REX prefix that encodes a 64-bit operand size and
1327 // the top bit of the register code.
1328 // The high bit of register is used for REX.B.
1329 // REX.W is set and REX.R and REX.X are clear.
1330 inline void emit_rex_64(Register rm_reg);
1331
1332 // Emits a REX prefix that encodes a 64-bit operand size and
1333 // the top bit of the index and base register codes.
1334 // The high bit of op's base register is used for REX.B, and the high
1335 // bit of op's index register is used for REX.X.
1336 // REX.W is set and REX.R clear.
1337 inline void emit_rex_64(const Operand& op);
1338
1339 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1340 void emit_rex_64() { emit(0x48); }
1341
1342 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1343 // REX.W is clear.
1344 inline void emit_rex_32(Register reg, Register rm_reg);
1345
1346 // The high bit of reg is used for REX.R, the high bit of op's base
1347 // register is used for REX.B, and the high bit of op's index register
1348 // is used for REX.X. REX.W is cleared.
1349 inline void emit_rex_32(Register reg, const Operand& op);
1350
1351 // High bit of rm_reg goes to REX.B.
1352 // REX.W, REX.R and REX.X are clear.
1353 inline void emit_rex_32(Register rm_reg);
1354
1355 // High bit of base goes to REX.B and high bit of index to REX.X.
1356 // REX.W and REX.R are clear.
1357 inline void emit_rex_32(const Operand& op);
1358
1359 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1360 // REX.W is cleared. If no REX bits are set, no byte is emitted.
1361 inline void emit_optional_rex_32(Register reg, Register rm_reg);
1362
1363 // The high bit of reg is used for REX.R, the high bit of op's base
1364 // register is used for REX.B, and the high bit of op's index register
1365 // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
1366 // is emitted.
1367 inline void emit_optional_rex_32(Register reg, const Operand& op);
1368
1369 // As for emit_optional_rex_32(Register, Register), except that
1370 // the registers are XMM registers.
1371 inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1372
1373 // As for emit_optional_rex_32(Register, Register), except that
Steve Block6ded16b2010-05-10 14:33:55 +01001374 // one of the registers is an XMM registers.
Steve Blocka7e24c12009-10-30 11:49:00 +00001375 inline void emit_optional_rex_32(XMMRegister reg, Register base);
1376
Steve Block6ded16b2010-05-10 14:33:55 +01001377 // As for emit_optional_rex_32(Register, Register), except that
1378 // one of the registers is an XMM registers.
1379 inline void emit_optional_rex_32(Register reg, XMMRegister base);
1380
Steve Blocka7e24c12009-10-30 11:49:00 +00001381 // As for emit_optional_rex_32(Register, const Operand&), except that
1382 // the register is an XMM register.
1383 inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1384
1385 // Optionally do as emit_rex_32(Register) if the register number has
1386 // the high bit set.
1387 inline void emit_optional_rex_32(Register rm_reg);
1388
1389 // Optionally do as emit_rex_32(const Operand&) if the operand register
1390 // numbers have a high bit set.
1391 inline void emit_optional_rex_32(const Operand& op);
1392
1393
1394 // Emit the ModR/M byte, and optionally the SIB byte and
1395 // 1- or 4-byte offset for a memory operand. Also encodes
1396 // the second operand of the operation, a register or operation
1397 // subcode, into the reg field of the ModR/M byte.
1398 void emit_operand(Register reg, const Operand& adr) {
1399 emit_operand(reg.low_bits(), adr);
1400 }
1401
1402 // Emit the ModR/M byte, and optionally the SIB byte and
1403 // 1- or 4-byte offset for a memory operand. Also used to encode
1404 // a three-bit opcode extension into the ModR/M byte.
1405 void emit_operand(int rm, const Operand& adr);
1406
1407 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1408 void emit_modrm(Register reg, Register rm_reg) {
1409 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1410 }
1411
1412 // Emit a ModR/M byte with an operation subcode in the reg field and
1413 // a register in the rm_reg field.
1414 void emit_modrm(int code, Register rm_reg) {
1415 ASSERT(is_uint3(code));
1416 emit(0xC0 | code << 3 | rm_reg.low_bits());
1417 }
1418
1419 // Emit the code-object-relative offset of the label's position
1420 inline void emit_code_relative_offset(Label* label);
1421
1422 // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1423 // AND, OR, XOR, or CMP. The encodings of these operations are all
1424 // similar, differing just in the opcode or in the reg field of the
1425 // ModR/M byte.
1426 void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1427 void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1428 void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
1429 void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
1430 void arithmetic_op(byte opcode, Register reg, Register rm_reg);
1431 void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
1432 void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1433 void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
1434 // Operate on a byte in memory or register.
1435 void immediate_arithmetic_op_8(byte subcode,
1436 Register dst,
1437 Immediate src);
1438 void immediate_arithmetic_op_8(byte subcode,
1439 const Operand& dst,
1440 Immediate src);
1441 // Operate on a word in memory or register.
1442 void immediate_arithmetic_op_16(byte subcode,
1443 Register dst,
1444 Immediate src);
1445 void immediate_arithmetic_op_16(byte subcode,
1446 const Operand& dst,
1447 Immediate src);
1448 // Operate on a 32-bit word in memory or register.
1449 void immediate_arithmetic_op_32(byte subcode,
1450 Register dst,
1451 Immediate src);
1452 void immediate_arithmetic_op_32(byte subcode,
1453 const Operand& dst,
1454 Immediate src);
1455
1456 // Emit machine code for a shift operation.
1457 void shift(Register dst, Immediate shift_amount, int subcode);
1458 void shift_32(Register dst, Immediate shift_amount, int subcode);
1459 // Shift dst by cl % 64 bits.
1460 void shift(Register dst, int subcode);
1461 void shift_32(Register dst, int subcode);
1462
1463 void emit_farith(int b1, int b2, int i);
1464
1465 // labels
1466 // void print(Label* L);
1467 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001468
1469 // record reloc info for current pc_
1470 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1471
1472 friend class CodePatcher;
1473 friend class EnsureSpace;
1474 friend class RegExpMacroAssemblerX64;
1475
1476 // Code buffer:
1477 // The buffer into which code and relocation info are generated.
1478 byte* buffer_;
1479 int buffer_size_;
1480 // True if the assembler owns the buffer, false if buffer is external.
1481 bool own_buffer_;
1482 // A previously allocated buffer of kMinimalBufferSize bytes, or NULL.
1483 static byte* spare_buffer_;
1484
1485 // code generation
1486 byte* pc_; // the program counter; moves forward
1487 RelocInfoWriter reloc_info_writer;
1488
Steve Block3ce2e202009-11-05 08:53:23 +00001489 List< Handle<Code> > code_targets_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001490 // push-pop elimination
1491 byte* last_pc_;
1492
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001493 PositionsRecorder positions_recorder_;
1494 friend class PositionsRecorder;
Steve Blocka7e24c12009-10-30 11:49:00 +00001495};
1496
1497
1498// Helper class that ensures that there is enough space for generating
1499// instructions and relocation information. The constructor makes
1500// sure that there is enough space and (in debug mode) the destructor
1501// checks that we did not generate too much.
1502class EnsureSpace BASE_EMBEDDED {
1503 public:
1504 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1505 if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1506#ifdef DEBUG
1507 space_before_ = assembler_->available_space();
1508#endif
1509 }
1510
1511#ifdef DEBUG
1512 ~EnsureSpace() {
1513 int bytes_generated = space_before_ - assembler_->available_space();
1514 ASSERT(bytes_generated < assembler_->kGap);
1515 }
1516#endif
1517
1518 private:
1519 Assembler* assembler_;
1520#ifdef DEBUG
1521 int space_before_;
1522#endif
1523};
1524
1525} } // namespace v8::internal
1526
1527#endif // V8_X64_ASSEMBLER_X64_H_