blob: 7bcc7c56dd873786c6e86deb1c190a24303b9686 [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
101 static const char* AllocationIndexToString(int index) {
102 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
103 const char* const names[] = {
104 "rax",
105 "rcx",
106 "rdx",
107 "rbx",
108 "rdi",
109 "r8",
110 "r9",
111 "r11",
112 "r12",
113 "r14"
114 };
115 return names[index];
116 }
117
Steve Blocka7e24c12009-10-30 11:49:00 +0000118 static Register toRegister(int code) {
119 Register r = { code };
120 return r;
121 }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100122 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100123 bool is(Register reg) const { return code_ == reg.code_; }
124 int code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000125 ASSERT(is_valid());
126 return code_;
127 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100128 int bit() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000129 return 1 << code_;
130 }
131
132 // Return the high bit of the register code as a 0 or 1. Used often
133 // when constructing the REX prefix byte.
134 int high_bit() const {
135 return code_ >> 3;
136 }
137 // Return the 3 low bits of the register code. Used when encoding registers
138 // in modR/M, SIB, and opcode bytes.
139 int low_bits() const {
140 return code_ & 0x7;
141 }
142
Andrei Popescu31002712010-02-23 13:46:05 +0000143 // Unfortunately we can't make this private in a struct when initializing
144 // by assignment.
Steve Blocka7e24c12009-10-30 11:49:00 +0000145 int code_;
146};
147
Andrei Popescu402d9372010-02-26 13:31:12 +0000148const Register rax = { 0 };
149const Register rcx = { 1 };
150const Register rdx = { 2 };
151const Register rbx = { 3 };
152const Register rsp = { 4 };
153const Register rbp = { 5 };
154const Register rsi = { 6 };
155const Register rdi = { 7 };
156const Register r8 = { 8 };
157const Register r9 = { 9 };
158const Register r10 = { 10 };
159const Register r11 = { 11 };
160const Register r12 = { 12 };
161const Register r13 = { 13 };
162const Register r14 = { 14 };
163const Register r15 = { 15 };
164const Register no_reg = { -1 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000165
166
167struct XMMRegister {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100168 static const int kNumRegisters = 16;
169 static const int kNumAllocatableRegisters = 15;
170
171 static int ToAllocationIndex(XMMRegister reg) {
172 ASSERT(reg.code() != 0);
173 return reg.code() - 1;
174 }
175
176 static const char* AllocationIndexToString(int index) {
177 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
178 const char* const names[] = {
179 "xmm1",
180 "xmm2",
181 "xmm3",
182 "xmm4",
183 "xmm5",
184 "xmm6",
185 "xmm7",
186 "xmm8",
187 "xmm9",
188 "xmm10",
189 "xmm11",
190 "xmm12",
191 "xmm13",
192 "xmm14",
193 "xmm15"
194 };
195 return names[index];
196 }
197
198 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100199 int code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000200 ASSERT(is_valid());
201 return code_;
202 }
203
204 // Return the high bit of the register code as a 0 or 1. Used often
205 // when constructing the REX prefix byte.
206 int high_bit() const {
207 return code_ >> 3;
208 }
209 // Return the 3 low bits of the register code. Used when encoding registers
210 // in modR/M, SIB, and opcode bytes.
211 int low_bits() const {
212 return code_ & 0x7;
213 }
214
215 int code_;
216};
217
Andrei Popescu402d9372010-02-26 13:31:12 +0000218const XMMRegister xmm0 = { 0 };
219const XMMRegister xmm1 = { 1 };
220const XMMRegister xmm2 = { 2 };
221const XMMRegister xmm3 = { 3 };
222const XMMRegister xmm4 = { 4 };
223const XMMRegister xmm5 = { 5 };
224const XMMRegister xmm6 = { 6 };
225const XMMRegister xmm7 = { 7 };
226const XMMRegister xmm8 = { 8 };
227const XMMRegister xmm9 = { 9 };
228const XMMRegister xmm10 = { 10 };
229const XMMRegister xmm11 = { 11 };
230const XMMRegister xmm12 = { 12 };
231const XMMRegister xmm13 = { 13 };
232const XMMRegister xmm14 = { 14 };
233const XMMRegister xmm15 = { 15 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000234
Ben Murdochb0fe1622011-05-05 13:52:32 +0100235
236typedef XMMRegister DoubleRegister;
237
238
Steve Blocka7e24c12009-10-30 11:49:00 +0000239enum Condition {
240 // any value < 0 is considered no_condition
241 no_condition = -1,
242
243 overflow = 0,
244 no_overflow = 1,
245 below = 2,
246 above_equal = 3,
247 equal = 4,
248 not_equal = 5,
249 below_equal = 6,
250 above = 7,
251 negative = 8,
252 positive = 9,
253 parity_even = 10,
254 parity_odd = 11,
255 less = 12,
256 greater_equal = 13,
257 less_equal = 14,
258 greater = 15,
259
Steve Block3ce2e202009-11-05 08:53:23 +0000260 // Fake conditions that are handled by the
261 // opcodes using them.
262 always = 16,
263 never = 17,
Steve Blocka7e24c12009-10-30 11:49:00 +0000264 // aliases
265 carry = below,
266 not_carry = above_equal,
267 zero = equal,
268 not_zero = not_equal,
269 sign = negative,
Steve Block3ce2e202009-11-05 08:53:23 +0000270 not_sign = positive,
271 last_condition = greater
Steve Blocka7e24c12009-10-30 11:49:00 +0000272};
273
274
275// Returns the equivalent of !cc.
276// Negation of the default no_condition (-1) results in a non-default
277// no_condition value (-2). As long as tests for no_condition check
278// for condition < 0, this will work as expected.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100279inline Condition NegateCondition(Condition cc) {
280 return static_cast<Condition>(cc ^ 1);
281}
282
Steve Blocka7e24c12009-10-30 11:49:00 +0000283
284// Corresponds to transposing the operands of a comparison.
285inline Condition ReverseCondition(Condition cc) {
286 switch (cc) {
287 case below:
288 return above;
289 case above:
290 return below;
291 case above_equal:
292 return below_equal;
293 case below_equal:
294 return above_equal;
295 case less:
296 return greater;
297 case greater:
298 return less;
299 case greater_equal:
300 return less_equal;
301 case less_equal:
302 return greater_equal;
303 default:
304 return cc;
305 };
306}
307
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100308
Steve Blocka7e24c12009-10-30 11:49:00 +0000309enum Hint {
310 no_hint = 0,
311 not_taken = 0x2e,
312 taken = 0x3e
313};
314
315// The result of negating a hint is as if the corresponding condition
316// were negated by NegateCondition. That is, no_hint is mapped to
317// itself and not_taken and taken are mapped to each other.
318inline Hint NegateHint(Hint hint) {
319 return (hint == no_hint)
320 ? no_hint
321 : ((hint == not_taken) ? taken : not_taken);
322}
323
324
325// -----------------------------------------------------------------------------
326// Machine instruction Immediates
327
328class Immediate BASE_EMBEDDED {
329 public:
330 explicit Immediate(int32_t value) : value_(value) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000331
332 private:
333 int32_t value_;
334
335 friend class Assembler;
336};
337
338
339// -----------------------------------------------------------------------------
340// Machine instruction Operands
341
342enum ScaleFactor {
343 times_1 = 0,
344 times_2 = 1,
345 times_4 = 2,
346 times_8 = 3,
347 times_int_size = times_4,
Steve Blocka7e24c12009-10-30 11:49:00 +0000348 times_pointer_size = times_8
349};
350
351
352class Operand BASE_EMBEDDED {
353 public:
354 // [base + disp/r]
355 Operand(Register base, int32_t disp);
356
357 // [base + index*scale + disp/r]
358 Operand(Register base,
359 Register index,
360 ScaleFactor scale,
361 int32_t disp);
362
363 // [index*scale + disp/r]
364 Operand(Register index,
365 ScaleFactor scale,
366 int32_t disp);
367
Leon Clarkef7060e22010-06-03 12:02:55 +0100368 // Offset from existing memory operand.
369 // Offset is added to existing displacement as 32-bit signed values and
370 // this must not overflow.
371 Operand(const Operand& base, int32_t offset);
372
Steve Blocka7e24c12009-10-30 11:49:00 +0000373 private:
374 byte rex_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100375 byte buf_[6];
Steve Blocka7e24c12009-10-30 11:49:00 +0000376 // The number of bytes in buf_.
377 unsigned int len_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000378
379 // Set the ModR/M byte without an encoded 'reg' register. The
380 // register is encoded later as part of the emit_operand operation.
381 // set_modrm can be called before or after set_sib and set_disp*.
382 inline void set_modrm(int mod, Register rm);
383
384 // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
385 inline void set_sib(ScaleFactor scale, Register index, Register base);
386
387 // Adds operand displacement fields (offsets added to the memory address).
388 // Needs to be called after set_sib, not before it.
389 inline void set_disp8(int disp);
390 inline void set_disp32(int disp);
391
392 friend class Assembler;
393};
394
395
396// CpuFeatures keeps track of which features are supported by the target CPU.
397// Supported features must be enabled by a Scope before use.
398// Example:
399// if (CpuFeatures::IsSupported(SSE3)) {
400// CpuFeatures::Scope fscope(SSE3);
401// // Generate SSE3 floating point code.
402// } else {
403// // Generate standard x87 or SSE2 floating point code.
404// }
405class CpuFeatures : public AllStatic {
406 public:
Steve Blocka7e24c12009-10-30 11:49:00 +0000407 // Detect features of the target CPU. Set safe defaults if the serializer
408 // is enabled (snapshots must be portable).
Ben Murdochb0fe1622011-05-05 13:52:32 +0100409 static void Probe(bool portable);
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 // Check whether a feature is supported by the target CPU.
Steve Blockd0582a62009-12-15 09:54:21 +0000411 static bool IsSupported(CpuFeature f) {
Steve Block3ce2e202009-11-05 08:53:23 +0000412 if (f == SSE2 && !FLAG_enable_sse2) return false;
413 if (f == SSE3 && !FLAG_enable_sse3) return false;
414 if (f == CMOV && !FLAG_enable_cmov) return false;
415 if (f == RDTSC && !FLAG_enable_rdtsc) return false;
416 if (f == SAHF && !FLAG_enable_sahf) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000417 return (supported_ & (V8_UINT64_C(1) << f)) != 0;
418 }
419 // Check whether a feature is currently enabled.
Steve Blockd0582a62009-12-15 09:54:21 +0000420 static bool IsEnabled(CpuFeature f) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000421 return (enabled_ & (V8_UINT64_C(1) << f)) != 0;
422 }
423 // Enable a specified feature within a scope.
424 class Scope BASE_EMBEDDED {
425#ifdef DEBUG
426 public:
Steve Blockd0582a62009-12-15 09:54:21 +0000427 explicit Scope(CpuFeature f) {
428 uint64_t mask = (V8_UINT64_C(1) << f);
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 ASSERT(CpuFeatures::IsSupported(f));
Steve Blockd0582a62009-12-15 09:54:21 +0000430 ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000431 old_enabled_ = CpuFeatures::enabled_;
Steve Blockd0582a62009-12-15 09:54:21 +0000432 CpuFeatures::enabled_ |= mask;
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 }
434 ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
435 private:
436 uint64_t old_enabled_;
437#else
438 public:
Steve Blockd0582a62009-12-15 09:54:21 +0000439 explicit Scope(CpuFeature f) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000440#endif
441 };
442 private:
443 // Safe defaults include SSE2 and CMOV for X64. It is always available, if
444 // anyone checks, but they shouldn't need to check.
Steve Blockd0582a62009-12-15 09:54:21 +0000445 static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
Steve Blocka7e24c12009-10-30 11:49:00 +0000446 static uint64_t supported_;
447 static uint64_t enabled_;
Steve Blockd0582a62009-12-15 09:54:21 +0000448 static uint64_t found_by_runtime_probing_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000449};
450
451
452class Assembler : public Malloced {
453 private:
454 // We check before assembling an instruction that there is sufficient
455 // space to write an instruction and its relocation information.
456 // The relocation writer's position must be kGap bytes above the end of
457 // the generated instructions. This leaves enough space for the
458 // longest possible x64 instruction, 15 bytes, and the longest possible
459 // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
460 // (There is a 15 byte limit on x64 instruction length that rules out some
461 // otherwise valid instructions.)
462 // This allows for a single, fast space check per instruction.
463 static const int kGap = 32;
464
465 public:
466 // Create an assembler. Instructions and relocation information are emitted
467 // into a buffer, with the instructions starting from the beginning and the
468 // relocation information starting from the end of the buffer. See CodeDesc
469 // for a detailed comment on the layout (globals.h).
470 //
471 // If the provided buffer is NULL, the assembler allocates and grows its own
472 // buffer, and buffer_size determines the initial buffer size. The buffer is
473 // owned by the assembler and deallocated upon destruction of the assembler.
474 //
475 // If the provided buffer is not NULL, the assembler uses the provided buffer
476 // for code generation and assumes its size to be buffer_size. If the buffer
477 // is too small, a fatal error occurs. No deallocation of the buffer is done
478 // upon destruction of the assembler.
479 Assembler(void* buffer, int buffer_size);
480 ~Assembler();
481
482 // GetCode emits any pending (non-emitted) code and fills the descriptor
483 // desc. GetCode() is idempotent; it returns the same result if no other
484 // Assembler functions are invoked in between GetCode() calls.
485 void GetCode(CodeDesc* desc);
486
Steve Block3ce2e202009-11-05 08:53:23 +0000487 // Read/Modify the code target in the relative branch/call instruction at pc.
488 // On the x64 architecture, we use relative jumps with a 32-bit displacement
489 // to jump to other Code objects in the Code space in the heap.
490 // Jumps to C functions are done indirectly through a 64-bit register holding
491 // the absolute address of the target.
492 // These functions convert between absolute Addresses of Code objects and
493 // the relative displacements stored in the code.
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 static inline Address target_address_at(Address pc);
495 static inline void set_target_address_at(Address pc, Address target);
Steve Blockd0582a62009-12-15 09:54:21 +0000496
497 // This sets the branch destination (which is in the instruction on x64).
498 // This is for calls and branches within generated code.
499 inline static void set_target_at(Address instruction_payload,
500 Address target) {
501 set_target_address_at(instruction_payload, target);
502 }
503
504 // This sets the branch destination (which is a load instruction on x64).
505 // This is for calls and branches to runtime code.
506 inline static void set_external_target_at(Address instruction_payload,
507 Address target) {
508 *reinterpret_cast<Address*>(instruction_payload) = target;
509 }
510
Steve Block3ce2e202009-11-05 08:53:23 +0000511 inline Handle<Object> code_target_object_handle_at(Address pc);
Steve Blockd0582a62009-12-15 09:54:21 +0000512 // Number of bytes taken up by the branch target in the code.
513 static const int kCallTargetSize = 4; // Use 32-bit displacement.
514 static const int kExternalTargetSize = 8; // Use 64-bit absolute.
Steve Blocka7e24c12009-10-30 11:49:00 +0000515 // Distance between the address of the code target in the call instruction
Steve Block3ce2e202009-11-05 08:53:23 +0000516 // and the return address pushed on the stack.
517 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
518 // Distance between the start of the JS return sequence and where the
519 // 32-bit displacement of a near call would be, relative to the pushed
520 // return address. TODO: Use return sequence length instead.
521 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
522 static const int kPatchReturnSequenceAddressOffset = 13 - 4;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100523 // Distance between start of patched debug break slot and where the
524 // 32-bit displacement of a near call would be, relative to the pushed
525 // return address. TODO: Use return sequence length instead.
526 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
527 static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
Steve Block3ce2e202009-11-05 08:53:23 +0000528 // TODO(X64): Rename this, removing the "Real", after changing the above.
529 static const int kRealPatchReturnSequenceAddressOffset = 2;
Steve Blockd0582a62009-12-15 09:54:21 +0000530
531 // The x64 JS return sequence is padded with int3 to make it large
532 // enough to hold a call instruction when the debugger patches it.
533 static const int kCallInstructionLength = 13;
534 static const int kJSReturnSequenceLength = 13;
535
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100536 // The debug break slot must be able to contain a call instruction.
537 static const int kDebugBreakSlotLength = kCallInstructionLength;
538
Steve Block9fac8402011-05-12 15:51:54 +0100539 // One byte opcode for test eax,0xXXXXXXXX.
540 static const byte kTestEaxByte = 0xA9;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100541
Steve Blocka7e24c12009-10-30 11:49:00 +0000542 // ---------------------------------------------------------------------------
543 // Code generation
544 //
545 // Function names correspond one-to-one to x64 instruction mnemonics.
546 // Unless specified otherwise, instructions operate on 64-bit operands.
547 //
548 // If we need versions of an assembly instruction that operate on different
549 // width arguments, we add a single-letter suffix specifying the width.
550 // This is done for the following instructions: mov, cmp, inc, dec,
551 // add, sub, and test.
552 // There are no versions of these instructions without the suffix.
553 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
554 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
555 // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
556 // - Instructions on 64-bit (quadword) operands/registers use 'q'.
557 //
558 // Some mnemonics, such as "and", are the same as C++ keywords.
559 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
560
561 // Insert the smallest number of nop instructions
562 // possible to align the pc offset to a multiple
563 // of m. m must be a power of 2.
564 void Align(int m);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100565 // Aligns code to something that's optimal for a jump target for the platform.
566 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000567
568 // Stack
569 void pushfq();
570 void popfq();
571
572 void push(Immediate value);
573 void push(Register src);
574 void push(const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000575
576 void pop(Register dst);
577 void pop(const Operand& dst);
578
579 void enter(Immediate size);
580 void leave();
581
582 // Moves
583 void movb(Register dst, const Operand& src);
584 void movb(Register dst, Immediate imm);
585 void movb(const Operand& dst, Register src);
586
Steve Block3ce2e202009-11-05 08:53:23 +0000587 // Move the low 16 bits of a 64-bit register value to a 16-bit
588 // memory location.
589 void movw(const Operand& dst, Register src);
590
Steve Blocka7e24c12009-10-30 11:49:00 +0000591 void movl(Register dst, Register src);
592 void movl(Register dst, const Operand& src);
593 void movl(const Operand& dst, Register src);
594 void movl(const Operand& dst, Immediate imm);
595 // Load a 32-bit immediate value, zero-extended to 64 bits.
596 void movl(Register dst, Immediate imm32);
597
598 // Move 64 bit register value to 64-bit memory location.
599 void movq(const Operand& dst, Register src);
600 // Move 64 bit memory location to 64-bit register value.
601 void movq(Register dst, const Operand& src);
602 void movq(Register dst, Register src);
603 // Sign extends immediate 32-bit value to 64 bits.
604 void movq(Register dst, Immediate x);
605 // Move the offset of the label location relative to the current
606 // position (after the move) to the destination.
607 void movl(const Operand& dst, Label* src);
608
609 // Move sign extended immediate to memory location.
610 void movq(const Operand& dst, Immediate value);
611 // New x64 instructions to load a 64-bit immediate into a register.
612 // All 64-bit immediates must have a relocation mode.
613 void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
614 void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
615 void movq(Register dst, const char* s, RelocInfo::Mode rmode);
616 // Moves the address of the external reference into the register.
617 void movq(Register dst, ExternalReference ext);
618 void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
619
Steve Block3ce2e202009-11-05 08:53:23 +0000620 void movsxbq(Register dst, const Operand& src);
621 void movsxwq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000622 void movsxlq(Register dst, Register src);
623 void movsxlq(Register dst, const Operand& src);
624 void movzxbq(Register dst, const Operand& src);
625 void movzxbl(Register dst, const Operand& src);
Steve Block3ce2e202009-11-05 08:53:23 +0000626 void movzxwq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000627 void movzxwl(Register dst, const Operand& src);
628
Leon Clarked91b9f72010-01-27 17:25:45 +0000629 // Repeated moves.
630
631 void repmovsb();
632 void repmovsw();
633 void repmovsl();
634 void repmovsq();
635
Steve Blocka7e24c12009-10-30 11:49:00 +0000636 // New x64 instruction to load from an immediate 64-bit pointer into RAX.
637 void load_rax(void* ptr, RelocInfo::Mode rmode);
638 void load_rax(ExternalReference ext);
639
640 // Conditional moves.
641 void cmovq(Condition cc, Register dst, Register src);
642 void cmovq(Condition cc, Register dst, const Operand& src);
643 void cmovl(Condition cc, Register dst, Register src);
644 void cmovl(Condition cc, Register dst, const Operand& src);
645
646 // Exchange two registers
647 void xchg(Register dst, Register src);
648
649 // Arithmetics
650 void addl(Register dst, Register src) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100651 arithmetic_op_32(0x03, dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000652 }
653
654 void addl(Register dst, Immediate src) {
655 immediate_arithmetic_op_32(0x0, dst, src);
656 }
657
658 void addl(Register dst, const Operand& src) {
659 arithmetic_op_32(0x03, dst, src);
660 }
661
662 void addl(const Operand& dst, Immediate src) {
663 immediate_arithmetic_op_32(0x0, dst, src);
664 }
665
666 void addq(Register dst, Register src) {
667 arithmetic_op(0x03, dst, src);
668 }
669
670 void addq(Register dst, const Operand& src) {
671 arithmetic_op(0x03, dst, src);
672 }
673
674 void addq(const Operand& dst, Register src) {
675 arithmetic_op(0x01, src, dst);
676 }
677
678 void addq(Register dst, Immediate src) {
679 immediate_arithmetic_op(0x0, dst, src);
680 }
681
682 void addq(const Operand& dst, Immediate src) {
683 immediate_arithmetic_op(0x0, dst, src);
684 }
685
Kristian Monsen25f61362010-05-21 11:50:48 +0100686 void sbbl(Register dst, Register src) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100687 arithmetic_op_32(0x1b, dst, src);
Kristian Monsen25f61362010-05-21 11:50:48 +0100688 }
689
Steve Blocka7e24c12009-10-30 11:49:00 +0000690 void cmpb(Register dst, Immediate src) {
691 immediate_arithmetic_op_8(0x7, dst, src);
692 }
693
694 void cmpb_al(Immediate src);
695
696 void cmpb(Register dst, Register src) {
697 arithmetic_op(0x3A, dst, src);
698 }
699
700 void cmpb(Register dst, const Operand& src) {
701 arithmetic_op(0x3A, dst, src);
702 }
703
704 void cmpb(const Operand& dst, Register src) {
705 arithmetic_op(0x38, src, dst);
706 }
707
708 void cmpb(const Operand& dst, Immediate src) {
709 immediate_arithmetic_op_8(0x7, dst, src);
710 }
711
712 void cmpw(const Operand& dst, Immediate src) {
713 immediate_arithmetic_op_16(0x7, dst, src);
714 }
715
716 void cmpw(Register dst, Immediate src) {
717 immediate_arithmetic_op_16(0x7, dst, src);
718 }
719
720 void cmpw(Register dst, const Operand& src) {
721 arithmetic_op_16(0x3B, dst, src);
722 }
723
724 void cmpw(Register dst, Register src) {
725 arithmetic_op_16(0x3B, dst, src);
726 }
727
728 void cmpw(const Operand& dst, Register src) {
729 arithmetic_op_16(0x39, src, dst);
730 }
731
732 void cmpl(Register dst, Register src) {
733 arithmetic_op_32(0x3B, dst, src);
734 }
735
736 void cmpl(Register dst, const Operand& src) {
737 arithmetic_op_32(0x3B, dst, src);
738 }
739
740 void cmpl(const Operand& dst, Register src) {
741 arithmetic_op_32(0x39, src, dst);
742 }
743
744 void cmpl(Register dst, Immediate src) {
745 immediate_arithmetic_op_32(0x7, dst, src);
746 }
747
748 void cmpl(const Operand& dst, Immediate src) {
749 immediate_arithmetic_op_32(0x7, dst, src);
750 }
751
752 void cmpq(Register dst, Register src) {
753 arithmetic_op(0x3B, dst, src);
754 }
755
756 void cmpq(Register dst, const Operand& src) {
757 arithmetic_op(0x3B, dst, src);
758 }
759
760 void cmpq(const Operand& dst, Register src) {
761 arithmetic_op(0x39, src, dst);
762 }
763
764 void cmpq(Register dst, Immediate src) {
765 immediate_arithmetic_op(0x7, dst, src);
766 }
767
768 void cmpq(const Operand& dst, Immediate src) {
769 immediate_arithmetic_op(0x7, dst, src);
770 }
771
772 void and_(Register dst, Register src) {
773 arithmetic_op(0x23, dst, src);
774 }
775
776 void and_(Register dst, const Operand& src) {
777 arithmetic_op(0x23, dst, src);
778 }
779
780 void and_(const Operand& dst, Register src) {
781 arithmetic_op(0x21, src, dst);
782 }
783
784 void and_(Register dst, Immediate src) {
785 immediate_arithmetic_op(0x4, dst, src);
786 }
787
788 void and_(const Operand& dst, Immediate src) {
789 immediate_arithmetic_op(0x4, dst, src);
790 }
791
792 void andl(Register dst, Immediate src) {
793 immediate_arithmetic_op_32(0x4, dst, src);
794 }
795
Steve Block3ce2e202009-11-05 08:53:23 +0000796 void andl(Register dst, Register src) {
797 arithmetic_op_32(0x23, dst, src);
798 }
799
Leon Clarke4515c472010-02-03 11:58:03 +0000800 void andb(Register dst, Immediate src) {
801 immediate_arithmetic_op_8(0x4, dst, src);
802 }
Steve Block3ce2e202009-11-05 08:53:23 +0000803
Steve Blocka7e24c12009-10-30 11:49:00 +0000804 void decq(Register dst);
805 void decq(const Operand& dst);
806 void decl(Register dst);
807 void decl(const Operand& dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000808 void decb(Register dst);
809 void decb(const Operand& dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000810
811 // Sign-extends rax into rdx:rax.
812 void cqo();
813 // Sign-extends eax into edx:eax.
814 void cdq();
815
816 // Divide rdx:rax by src. Quotient in rax, remainder in rdx.
817 void idivq(Register src);
818 // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx.
819 void idivl(Register src);
820
821 // Signed multiply instructions.
822 void imul(Register src); // rdx:rax = rax * src.
823 void imul(Register dst, Register src); // dst = dst * src.
824 void imul(Register dst, const Operand& src); // dst = dst * src.
825 void imul(Register dst, Register src, Immediate imm); // dst = src * imm.
Steve Block6ded16b2010-05-10 14:33:55 +0100826 // Signed 32-bit multiply instructions.
827 void imull(Register dst, Register src); // dst = dst * src.
828 void imull(Register dst, Register src, Immediate imm); // dst = src * imm.
Steve Blocka7e24c12009-10-30 11:49:00 +0000829
830 void incq(Register dst);
831 void incq(const Operand& dst);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100832 void incl(Register dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000833 void incl(const Operand& dst);
834
835 void lea(Register dst, const Operand& src);
Steve Block6ded16b2010-05-10 14:33:55 +0100836 void leal(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000837
838 // Multiply rax by src, put the result in rdx:rax.
839 void mul(Register src);
840
841 void neg(Register dst);
842 void neg(const Operand& dst);
843 void negl(Register dst);
844
845 void not_(Register dst);
846 void not_(const Operand& dst);
Steve Block6ded16b2010-05-10 14:33:55 +0100847 void notl(Register dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000848
849 void or_(Register dst, Register src) {
850 arithmetic_op(0x0B, dst, src);
851 }
852
853 void orl(Register dst, Register src) {
854 arithmetic_op_32(0x0B, dst, src);
855 }
856
857 void or_(Register dst, const Operand& src) {
858 arithmetic_op(0x0B, dst, src);
859 }
860
861 void or_(const Operand& dst, Register src) {
862 arithmetic_op(0x09, src, dst);
863 }
864
865 void or_(Register dst, Immediate src) {
866 immediate_arithmetic_op(0x1, dst, src);
867 }
868
Steve Block3ce2e202009-11-05 08:53:23 +0000869 void orl(Register dst, Immediate src) {
870 immediate_arithmetic_op_32(0x1, dst, src);
871 }
872
Steve Blocka7e24c12009-10-30 11:49:00 +0000873 void or_(const Operand& dst, Immediate src) {
874 immediate_arithmetic_op(0x1, dst, src);
875 }
876
Steve Block3ce2e202009-11-05 08:53:23 +0000877 void orl(const Operand& dst, Immediate src) {
878 immediate_arithmetic_op_32(0x1, dst, src);
879 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000880
Steve Block3ce2e202009-11-05 08:53:23 +0000881
882 void rcl(Register dst, Immediate imm8) {
883 shift(dst, imm8, 0x2);
884 }
885
886 void rol(Register dst, Immediate imm8) {
887 shift(dst, imm8, 0x0);
888 }
889
890 void rcr(Register dst, Immediate imm8) {
891 shift(dst, imm8, 0x3);
892 }
893
894 void ror(Register dst, Immediate imm8) {
895 shift(dst, imm8, 0x1);
896 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000897
898 // Shifts dst:src left by cl bits, affecting only dst.
899 void shld(Register dst, Register src);
900
901 // Shifts src:dst right by cl bits, affecting only dst.
902 void shrd(Register dst, Register src);
903
904 // Shifts dst right, duplicating sign bit, by shift_amount bits.
905 // Shifting by 1 is handled efficiently.
906 void sar(Register dst, Immediate shift_amount) {
907 shift(dst, shift_amount, 0x7);
908 }
909
910 // Shifts dst right, duplicating sign bit, by shift_amount bits.
911 // Shifting by 1 is handled efficiently.
912 void sarl(Register dst, Immediate shift_amount) {
913 shift_32(dst, shift_amount, 0x7);
914 }
915
916 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
Steve Blockd0582a62009-12-15 09:54:21 +0000917 void sar_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000918 shift(dst, 0x7);
919 }
920
921 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
Steve Blockd0582a62009-12-15 09:54:21 +0000922 void sarl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000923 shift_32(dst, 0x7);
924 }
925
926 void shl(Register dst, Immediate shift_amount) {
927 shift(dst, shift_amount, 0x4);
928 }
929
Steve Blockd0582a62009-12-15 09:54:21 +0000930 void shl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000931 shift(dst, 0x4);
932 }
933
Steve Blockd0582a62009-12-15 09:54:21 +0000934 void shll_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000935 shift_32(dst, 0x4);
936 }
937
938 void shll(Register dst, Immediate shift_amount) {
939 shift_32(dst, shift_amount, 0x4);
940 }
941
942 void shr(Register dst, Immediate shift_amount) {
943 shift(dst, shift_amount, 0x5);
944 }
945
Steve Blockd0582a62009-12-15 09:54:21 +0000946 void shr_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000947 shift(dst, 0x5);
948 }
949
Steve Blockd0582a62009-12-15 09:54:21 +0000950 void shrl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000951 shift_32(dst, 0x5);
952 }
953
954 void shrl(Register dst, Immediate shift_amount) {
955 shift_32(dst, shift_amount, 0x5);
956 }
957
958 void store_rax(void* dst, RelocInfo::Mode mode);
959 void store_rax(ExternalReference ref);
960
961 void subq(Register dst, Register src) {
962 arithmetic_op(0x2B, dst, src);
963 }
964
965 void subq(Register dst, const Operand& src) {
966 arithmetic_op(0x2B, dst, src);
967 }
968
969 void subq(const Operand& dst, Register src) {
970 arithmetic_op(0x29, src, dst);
971 }
972
973 void subq(Register dst, Immediate src) {
974 immediate_arithmetic_op(0x5, dst, src);
975 }
976
977 void subq(const Operand& dst, Immediate src) {
978 immediate_arithmetic_op(0x5, dst, src);
979 }
980
981 void subl(Register dst, Register src) {
982 arithmetic_op_32(0x2B, dst, src);
983 }
984
Leon Clarkee46be812010-01-19 14:06:41 +0000985 void subl(Register dst, const Operand& src) {
986 arithmetic_op_32(0x2B, dst, src);
987 }
988
Steve Blocka7e24c12009-10-30 11:49:00 +0000989 void subl(const Operand& dst, Immediate src) {
990 immediate_arithmetic_op_32(0x5, dst, src);
991 }
992
993 void subl(Register dst, Immediate src) {
994 immediate_arithmetic_op_32(0x5, dst, src);
995 }
996
997 void subb(Register dst, Immediate src) {
998 immediate_arithmetic_op_8(0x5, dst, src);
999 }
1000
Steve Block3ce2e202009-11-05 08:53:23 +00001001 void testb(Register dst, Register src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001002 void testb(Register reg, Immediate mask);
1003 void testb(const Operand& op, Immediate mask);
Leon Clarkee46be812010-01-19 14:06:41 +00001004 void testb(const Operand& op, Register reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001005 void testl(Register dst, Register src);
1006 void testl(Register reg, Immediate mask);
1007 void testl(const Operand& op, Immediate mask);
1008 void testq(const Operand& op, Register reg);
1009 void testq(Register dst, Register src);
1010 void testq(Register dst, Immediate mask);
1011
1012 void xor_(Register dst, Register src) {
Steve Blockd0582a62009-12-15 09:54:21 +00001013 if (dst.code() == src.code()) {
1014 arithmetic_op_32(0x33, dst, src);
1015 } else {
1016 arithmetic_op(0x33, dst, src);
1017 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001018 }
1019
1020 void xorl(Register dst, Register src) {
1021 arithmetic_op_32(0x33, dst, src);
1022 }
1023
1024 void xor_(Register dst, const Operand& src) {
1025 arithmetic_op(0x33, dst, src);
1026 }
1027
1028 void xor_(const Operand& dst, Register src) {
1029 arithmetic_op(0x31, src, dst);
1030 }
1031
1032 void xor_(Register dst, Immediate src) {
1033 immediate_arithmetic_op(0x6, dst, src);
1034 }
1035
1036 void xor_(const Operand& dst, Immediate src) {
1037 immediate_arithmetic_op(0x6, dst, src);
1038 }
1039
1040 // Bit operations.
1041 void bt(const Operand& dst, Register src);
1042 void bts(const Operand& dst, Register src);
1043
1044 // Miscellaneous
Steve Block3ce2e202009-11-05 08:53:23 +00001045 void clc();
Steve Blocka7e24c12009-10-30 11:49:00 +00001046 void cpuid();
1047 void hlt();
1048 void int3();
1049 void nop();
1050 void nop(int n);
1051 void rdtsc();
1052 void ret(int imm16);
1053 void setcc(Condition cc, Register reg);
1054
1055 // Label operations & relative jumps (PPUM Appendix D)
1056 //
1057 // Takes a branch opcode (cc) and a label (L) and generates
1058 // either a backward branch or a forward branch and links it
1059 // to the label fixup chain. Usage:
1060 //
1061 // Label L; // unbound label
1062 // j(cc, &L); // forward branch to unbound label
1063 // bind(&L); // bind label to the current pc
1064 // j(cc, &L); // backward branch to bound label
1065 // bind(&L); // illegal: a label may be bound only once
1066 //
1067 // Note: The same Label can be used for forward and backward branches
1068 // but it may be bound only once.
1069
1070 void bind(Label* L); // binds an unbound label L to the current code position
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001071 void bind(NearLabel* L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001072
1073 // Calls
1074 // Call near relative 32-bit displacement, relative to next instruction.
1075 void call(Label* L);
Steve Block3ce2e202009-11-05 08:53:23 +00001076 void call(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001077
1078 // Call near absolute indirect, address in register
1079 void call(Register adr);
1080
1081 // Call near indirect
1082 void call(const Operand& operand);
1083
1084 // Jumps
1085 // Jump short or near relative.
Steve Block3ce2e202009-11-05 08:53:23 +00001086 // Use a 32-bit signed displacement.
Steve Blocka7e24c12009-10-30 11:49:00 +00001087 void jmp(Label* L); // unconditional jump to L
Steve Block3ce2e202009-11-05 08:53:23 +00001088 void jmp(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001089
1090 // Jump near absolute indirect (r64)
1091 void jmp(Register adr);
1092
1093 // Jump near absolute indirect (m64)
1094 void jmp(const Operand& src);
1095
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001096 // Short jump
1097 void jmp(NearLabel* L);
1098
Steve Blocka7e24c12009-10-30 11:49:00 +00001099 // Conditional jumps
1100 void j(Condition cc, Label* L);
Steve Block3ce2e202009-11-05 08:53:23 +00001101 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001102
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001103 // Conditional short jump
1104 void j(Condition cc, NearLabel* L, Hint hint = no_hint);
1105
Steve Blocka7e24c12009-10-30 11:49:00 +00001106 // Floating-point operations
1107 void fld(int i);
1108
1109 void fld1();
1110 void fldz();
Steve Block6ded16b2010-05-10 14:33:55 +01001111 void fldpi();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001112 void fldln2();
Steve Blocka7e24c12009-10-30 11:49:00 +00001113
1114 void fld_s(const Operand& adr);
1115 void fld_d(const Operand& adr);
1116
1117 void fstp_s(const Operand& adr);
1118 void fstp_d(const Operand& adr);
Steve Block3ce2e202009-11-05 08:53:23 +00001119 void fstp(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001120
1121 void fild_s(const Operand& adr);
1122 void fild_d(const Operand& adr);
1123
1124 void fist_s(const Operand& adr);
1125
1126 void fistp_s(const Operand& adr);
1127 void fistp_d(const Operand& adr);
1128
1129 void fisttp_s(const Operand& adr);
Leon Clarked91b9f72010-01-27 17:25:45 +00001130 void fisttp_d(const Operand& adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001131
1132 void fabs();
1133 void fchs();
1134
1135 void fadd(int i);
1136 void fsub(int i);
1137 void fmul(int i);
1138 void fdiv(int i);
1139
1140 void fisub_s(const Operand& adr);
1141
1142 void faddp(int i = 1);
1143 void fsubp(int i = 1);
1144 void fsubrp(int i = 1);
1145 void fmulp(int i = 1);
1146 void fdivp(int i = 1);
1147 void fprem();
1148 void fprem1();
1149
1150 void fxch(int i = 1);
1151 void fincstp();
1152 void ffree(int i = 0);
1153
1154 void ftst();
1155 void fucomp(int i);
1156 void fucompp();
Steve Block3ce2e202009-11-05 08:53:23 +00001157 void fucomi(int i);
1158 void fucomip();
1159
Steve Blocka7e24c12009-10-30 11:49:00 +00001160 void fcompp();
1161 void fnstsw_ax();
1162 void fwait();
1163 void fnclex();
1164
1165 void fsin();
1166 void fcos();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001167 void fyl2x();
Steve Blocka7e24c12009-10-30 11:49:00 +00001168
1169 void frndint();
1170
1171 void sahf();
1172
1173 // SSE2 instructions
Steve Block6ded16b2010-05-10 14:33:55 +01001174 void movd(XMMRegister dst, Register src);
1175 void movd(Register dst, XMMRegister src);
1176 void movq(XMMRegister dst, Register src);
1177 void movq(Register dst, XMMRegister src);
1178 void extractps(Register dst, XMMRegister src, byte imm8);
1179
Steve Blocka7e24c12009-10-30 11:49:00 +00001180 void movsd(const Operand& dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001181 void movsd(XMMRegister dst, XMMRegister src);
1182 void movsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001183
Steve Block8defd9f2010-07-08 12:39:36 +01001184 void movss(XMMRegister dst, const Operand& src);
1185 void movss(const Operand& dst, XMMRegister src);
1186
Steve Blocka7e24c12009-10-30 11:49:00 +00001187 void cvttss2si(Register dst, const Operand& src);
1188 void cvttsd2si(Register dst, const Operand& src);
Kristian Monsen25f61362010-05-21 11:50:48 +01001189 void cvttsd2siq(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001190
1191 void cvtlsi2sd(XMMRegister dst, const Operand& src);
1192 void cvtlsi2sd(XMMRegister dst, Register src);
1193 void cvtqsi2sd(XMMRegister dst, const Operand& src);
1194 void cvtqsi2sd(XMMRegister dst, Register src);
1195
Steve Block8defd9f2010-07-08 12:39:36 +01001196 void cvtlsi2ss(XMMRegister dst, Register src);
1197
Steve Block6ded16b2010-05-10 14:33:55 +01001198 void cvtss2sd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001199 void cvtss2sd(XMMRegister dst, const Operand& src);
1200 void cvtsd2ss(XMMRegister dst, XMMRegister src);
1201
1202 void cvtsd2si(Register dst, XMMRegister src);
1203 void cvtsd2siq(Register dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001204
Steve Blocka7e24c12009-10-30 11:49:00 +00001205 void addsd(XMMRegister dst, XMMRegister src);
1206 void subsd(XMMRegister dst, XMMRegister src);
1207 void mulsd(XMMRegister dst, XMMRegister src);
1208 void divsd(XMMRegister dst, XMMRegister src);
1209
Andrei Popescu402d9372010-02-26 13:31:12 +00001210 void xorpd(XMMRegister dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001211 void sqrtsd(XMMRegister dst, XMMRegister src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001212
Andrei Popescu402d9372010-02-26 13:31:12 +00001213 void ucomisd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001214 void ucomisd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001215
Steve Block6ded16b2010-05-10 14:33:55 +01001216 // The first argument is the reg field, the second argument is the r/m field.
Steve Blocka7e24c12009-10-30 11:49:00 +00001217 void emit_sse_operand(XMMRegister dst, XMMRegister src);
1218 void emit_sse_operand(XMMRegister reg, const Operand& adr);
1219 void emit_sse_operand(XMMRegister dst, Register src);
Steve Block6ded16b2010-05-10 14:33:55 +01001220 void emit_sse_operand(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001221
1222 // Use either movsd or movlpd.
1223 // void movdbl(XMMRegister dst, const Operand& src);
1224 // void movdbl(const Operand& dst, XMMRegister src);
1225
1226 // Debugging
1227 void Print();
1228
1229 // Check the code size generated from label to here.
1230 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); }
1231
1232 // Mark address of the ExitJSFrame code.
1233 void RecordJSReturn();
1234
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001235 // Mark address of a debug break slot.
1236 void RecordDebugBreakSlot();
1237
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001239 // Use --code-comments to enable.
Steve Blocka7e24c12009-10-30 11:49:00 +00001240 void RecordComment(const char* msg);
1241
Ben Murdochb0fe1622011-05-05 13:52:32 +01001242 // Writes a single word of data in the code stream.
1243 // Used for inline tables, e.g., jump-tables.
1244 void db(uint8_t data) { UNIMPLEMENTED(); }
1245 void dd(uint32_t data);
1246
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001247 int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001248
1249 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001250
1251 // Check if there is less than kGap bytes available in the buffer.
1252 // If this is the case, we need to grow the buffer before emitting
1253 // an instruction or relocation information.
1254 inline bool buffer_overflow() const {
1255 return pc_ >= reloc_info_writer.pos() - kGap;
1256 }
1257
1258 // Get the number of bytes available in the buffer.
Steve Blockd0582a62009-12-15 09:54:21 +00001259 inline int available_space() const {
1260 return static_cast<int>(reloc_info_writer.pos() - pc_);
1261 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001262
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001263 static bool IsNop(Address addr) { return *addr == 0x90; }
1264
Steve Blocka7e24c12009-10-30 11:49:00 +00001265 // Avoid overflows for displacements etc.
1266 static const int kMaximalBufferSize = 512*MB;
1267 static const int kMinimalBufferSize = 4*KB;
1268
Steve Blocka7e24c12009-10-30 11:49:00 +00001269 private:
1270 byte* addr_at(int pos) { return buffer_ + pos; }
1271 byte byte_at(int pos) { return buffer_[pos]; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001272 void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001273 uint32_t long_at(int pos) {
1274 return *reinterpret_cast<uint32_t*>(addr_at(pos));
1275 }
1276 void long_at_put(int pos, uint32_t x) {
1277 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1278 }
1279
1280 // code emission
1281 void GrowBuffer();
1282
1283 void emit(byte x) { *pc_++ = x; }
1284 inline void emitl(uint32_t x);
Steve Blocka7e24c12009-10-30 11:49:00 +00001285 inline void emitq(uint64_t x, RelocInfo::Mode rmode);
1286 inline void emitw(uint16_t x);
Steve Block3ce2e202009-11-05 08:53:23 +00001287 inline void emit_code_target(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001288 void emit(Immediate x) { emitl(x.value_); }
1289
1290 // Emits a REX prefix that encodes a 64-bit operand size and
1291 // the top bit of both register codes.
1292 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1293 // REX.W is set.
Steve Blocka7e24c12009-10-30 11:49:00 +00001294 inline void emit_rex_64(XMMRegister reg, Register rm_reg);
Steve Block6ded16b2010-05-10 14:33:55 +01001295 inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1296 inline void emit_rex_64(Register reg, Register rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001297
1298 // Emits a REX prefix that encodes a 64-bit operand size and
1299 // the top bit of the destination, index, and base register codes.
1300 // The high bit of reg is used for REX.R, the high bit of op's base
1301 // register is used for REX.B, and the high bit of op's index register
1302 // is used for REX.X. REX.W is set.
1303 inline void emit_rex_64(Register reg, const Operand& op);
1304 inline void emit_rex_64(XMMRegister reg, const Operand& op);
1305
1306 // Emits a REX prefix that encodes a 64-bit operand size and
1307 // the top bit of the register code.
1308 // The high bit of register is used for REX.B.
1309 // REX.W is set and REX.R and REX.X are clear.
1310 inline void emit_rex_64(Register rm_reg);
1311
1312 // Emits a REX prefix that encodes a 64-bit operand size and
1313 // the top bit of the index and base register codes.
1314 // The high bit of op's base register is used for REX.B, and the high
1315 // bit of op's index register is used for REX.X.
1316 // REX.W is set and REX.R clear.
1317 inline void emit_rex_64(const Operand& op);
1318
1319 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1320 void emit_rex_64() { emit(0x48); }
1321
1322 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1323 // REX.W is clear.
1324 inline void emit_rex_32(Register reg, Register rm_reg);
1325
1326 // The high bit of reg is used for REX.R, the high bit of op's base
1327 // register is used for REX.B, and the high bit of op's index register
1328 // is used for REX.X. REX.W is cleared.
1329 inline void emit_rex_32(Register reg, const Operand& op);
1330
1331 // High bit of rm_reg goes to REX.B.
1332 // REX.W, REX.R and REX.X are clear.
1333 inline void emit_rex_32(Register rm_reg);
1334
1335 // High bit of base goes to REX.B and high bit of index to REX.X.
1336 // REX.W and REX.R are clear.
1337 inline void emit_rex_32(const Operand& op);
1338
1339 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1340 // REX.W is cleared. If no REX bits are set, no byte is emitted.
1341 inline void emit_optional_rex_32(Register reg, Register rm_reg);
1342
1343 // The high bit of reg is used for REX.R, the high bit of op's base
1344 // register is used for REX.B, and the high bit of op's index register
1345 // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
1346 // is emitted.
1347 inline void emit_optional_rex_32(Register reg, const Operand& op);
1348
1349 // As for emit_optional_rex_32(Register, Register), except that
1350 // the registers are XMM registers.
1351 inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1352
1353 // As for emit_optional_rex_32(Register, Register), except that
Steve Block6ded16b2010-05-10 14:33:55 +01001354 // one of the registers is an XMM registers.
Steve Blocka7e24c12009-10-30 11:49:00 +00001355 inline void emit_optional_rex_32(XMMRegister reg, Register base);
1356
Steve Block6ded16b2010-05-10 14:33:55 +01001357 // As for emit_optional_rex_32(Register, Register), except that
1358 // one of the registers is an XMM registers.
1359 inline void emit_optional_rex_32(Register reg, XMMRegister base);
1360
Steve Blocka7e24c12009-10-30 11:49:00 +00001361 // As for emit_optional_rex_32(Register, const Operand&), except that
1362 // the register is an XMM register.
1363 inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1364
1365 // Optionally do as emit_rex_32(Register) if the register number has
1366 // the high bit set.
1367 inline void emit_optional_rex_32(Register rm_reg);
1368
1369 // Optionally do as emit_rex_32(const Operand&) if the operand register
1370 // numbers have a high bit set.
1371 inline void emit_optional_rex_32(const Operand& op);
1372
1373
1374 // Emit the ModR/M byte, and optionally the SIB byte and
1375 // 1- or 4-byte offset for a memory operand. Also encodes
1376 // the second operand of the operation, a register or operation
1377 // subcode, into the reg field of the ModR/M byte.
1378 void emit_operand(Register reg, const Operand& adr) {
1379 emit_operand(reg.low_bits(), adr);
1380 }
1381
1382 // Emit the ModR/M byte, and optionally the SIB byte and
1383 // 1- or 4-byte offset for a memory operand. Also used to encode
1384 // a three-bit opcode extension into the ModR/M byte.
1385 void emit_operand(int rm, const Operand& adr);
1386
1387 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1388 void emit_modrm(Register reg, Register rm_reg) {
1389 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1390 }
1391
1392 // Emit a ModR/M byte with an operation subcode in the reg field and
1393 // a register in the rm_reg field.
1394 void emit_modrm(int code, Register rm_reg) {
1395 ASSERT(is_uint3(code));
1396 emit(0xC0 | code << 3 | rm_reg.low_bits());
1397 }
1398
1399 // Emit the code-object-relative offset of the label's position
1400 inline void emit_code_relative_offset(Label* label);
1401
1402 // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1403 // AND, OR, XOR, or CMP. The encodings of these operations are all
1404 // similar, differing just in the opcode or in the reg field of the
1405 // ModR/M byte.
1406 void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1407 void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1408 void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
1409 void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
1410 void arithmetic_op(byte opcode, Register reg, Register rm_reg);
1411 void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
1412 void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1413 void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
1414 // Operate on a byte in memory or register.
1415 void immediate_arithmetic_op_8(byte subcode,
1416 Register dst,
1417 Immediate src);
1418 void immediate_arithmetic_op_8(byte subcode,
1419 const Operand& dst,
1420 Immediate src);
1421 // Operate on a word in memory or register.
1422 void immediate_arithmetic_op_16(byte subcode,
1423 Register dst,
1424 Immediate src);
1425 void immediate_arithmetic_op_16(byte subcode,
1426 const Operand& dst,
1427 Immediate src);
1428 // Operate on a 32-bit word in memory or register.
1429 void immediate_arithmetic_op_32(byte subcode,
1430 Register dst,
1431 Immediate src);
1432 void immediate_arithmetic_op_32(byte subcode,
1433 const Operand& dst,
1434 Immediate src);
1435
1436 // Emit machine code for a shift operation.
1437 void shift(Register dst, Immediate shift_amount, int subcode);
1438 void shift_32(Register dst, Immediate shift_amount, int subcode);
1439 // Shift dst by cl % 64 bits.
1440 void shift(Register dst, int subcode);
1441 void shift_32(Register dst, int subcode);
1442
1443 void emit_farith(int b1, int b2, int i);
1444
1445 // labels
1446 // void print(Label* L);
1447 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001448
1449 // record reloc info for current pc_
1450 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1451
1452 friend class CodePatcher;
1453 friend class EnsureSpace;
1454 friend class RegExpMacroAssemblerX64;
1455
1456 // Code buffer:
1457 // The buffer into which code and relocation info are generated.
1458 byte* buffer_;
1459 int buffer_size_;
1460 // True if the assembler owns the buffer, false if buffer is external.
1461 bool own_buffer_;
1462 // A previously allocated buffer of kMinimalBufferSize bytes, or NULL.
1463 static byte* spare_buffer_;
1464
1465 // code generation
1466 byte* pc_; // the program counter; moves forward
1467 RelocInfoWriter reloc_info_writer;
1468
Steve Block3ce2e202009-11-05 08:53:23 +00001469 List< Handle<Code> > code_targets_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001470 // push-pop elimination
1471 byte* last_pc_;
1472
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001473 PositionsRecorder positions_recorder_;
1474 friend class PositionsRecorder;
Steve Blocka7e24c12009-10-30 11:49:00 +00001475};
1476
1477
1478// Helper class that ensures that there is enough space for generating
1479// instructions and relocation information. The constructor makes
1480// sure that there is enough space and (in debug mode) the destructor
1481// checks that we did not generate too much.
1482class EnsureSpace BASE_EMBEDDED {
1483 public:
1484 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1485 if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1486#ifdef DEBUG
1487 space_before_ = assembler_->available_space();
1488#endif
1489 }
1490
1491#ifdef DEBUG
1492 ~EnsureSpace() {
1493 int bytes_generated = space_before_ - assembler_->available_space();
1494 ASSERT(bytes_generated < assembler_->kGap);
1495 }
1496#endif
1497
1498 private:
1499 Assembler* assembler_;
1500#ifdef DEBUG
1501 int space_before_;
1502#endif
1503};
1504
1505} } // namespace v8::internal
1506
1507#endif // V8_X64_ASSEMBLER_X64_H_