blob: 52aca637785f45b16ba67e701fce1ce20a30557a [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 Murdoche0cee9b2011-05-25 10:26:03 +010033// Copyright 2011 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
Steve Block44f0eee2011-05-26 01:26:41 +010096 // r12 - smi constant register
Ben Murdochb0fe1622011-05-05 13:52:32 +010097 // r13 - root register
Ben Murdochb0fe1622011-05-05 13:52:32 +010098 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) {
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100102 return kAllocationIndexByRegisterCode[reg.code()];
Ben Murdochb8e0da22011-05-16 14:20:40 +0100103 }
104
105 static Register FromAllocationIndex(int index) {
106 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100107 Register result = { kRegisterCodeByAllocationIndex[index] };
Ben Murdochb8e0da22011-05-16 14:20:40 +0100108 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",
Steve Block44f0eee2011-05-26 01:26:41 +0100123 "r15"
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_;
Steve Block1e0659c2011-05-24 12:43:12 +0100156
Ben Murdochb8e0da22011-05-16 14:20:40 +0100157 private:
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100158 static const int kRegisterCodeByAllocationIndex[kNumAllocatableRegisters];
159 static const int kAllocationIndexByRegisterCode[kNumRegisters];
Steve Blocka7e24c12009-10-30 11:49:00 +0000160};
161
Andrei Popescu402d9372010-02-26 13:31:12 +0000162const Register rax = { 0 };
163const Register rcx = { 1 };
164const Register rdx = { 2 };
165const Register rbx = { 3 };
166const Register rsp = { 4 };
167const Register rbp = { 5 };
168const Register rsi = { 6 };
169const Register rdi = { 7 };
170const Register r8 = { 8 };
171const Register r9 = { 9 };
172const Register r10 = { 10 };
173const Register r11 = { 11 };
174const Register r12 = { 12 };
175const Register r13 = { 13 };
176const Register r14 = { 14 };
177const Register r15 = { 15 };
178const Register no_reg = { -1 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000179
180
181struct XMMRegister {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100182 static const int kNumRegisters = 16;
183 static const int kNumAllocatableRegisters = 15;
184
185 static int ToAllocationIndex(XMMRegister reg) {
186 ASSERT(reg.code() != 0);
187 return reg.code() - 1;
188 }
189
Ben Murdochb8e0da22011-05-16 14:20:40 +0100190 static XMMRegister FromAllocationIndex(int index) {
191 ASSERT(0 <= index && index < kNumAllocatableRegisters);
192 XMMRegister result = { index + 1 };
193 return result;
194 }
195
Ben Murdochb0fe1622011-05-05 13:52:32 +0100196 static const char* AllocationIndexToString(int index) {
197 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
198 const char* const names[] = {
199 "xmm1",
200 "xmm2",
201 "xmm3",
202 "xmm4",
203 "xmm5",
204 "xmm6",
205 "xmm7",
206 "xmm8",
207 "xmm9",
208 "xmm10",
209 "xmm11",
210 "xmm12",
211 "xmm13",
212 "xmm14",
213 "xmm15"
214 };
215 return names[index];
216 }
217
218 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
Ben Murdochb8e0da22011-05-16 14:20:40 +0100219 bool is(XMMRegister reg) const { return code_ == reg.code_; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100220 int code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000221 ASSERT(is_valid());
222 return code_;
223 }
224
225 // Return the high bit of the register code as a 0 or 1. Used often
226 // when constructing the REX prefix byte.
227 int high_bit() const {
228 return code_ >> 3;
229 }
230 // Return the 3 low bits of the register code. Used when encoding registers
231 // in modR/M, SIB, and opcode bytes.
232 int low_bits() const {
233 return code_ & 0x7;
234 }
235
236 int code_;
237};
238
Andrei Popescu402d9372010-02-26 13:31:12 +0000239const XMMRegister xmm0 = { 0 };
240const XMMRegister xmm1 = { 1 };
241const XMMRegister xmm2 = { 2 };
242const XMMRegister xmm3 = { 3 };
243const XMMRegister xmm4 = { 4 };
244const XMMRegister xmm5 = { 5 };
245const XMMRegister xmm6 = { 6 };
246const XMMRegister xmm7 = { 7 };
247const XMMRegister xmm8 = { 8 };
248const XMMRegister xmm9 = { 9 };
249const XMMRegister xmm10 = { 10 };
250const XMMRegister xmm11 = { 11 };
251const XMMRegister xmm12 = { 12 };
252const XMMRegister xmm13 = { 13 };
253const XMMRegister xmm14 = { 14 };
254const XMMRegister xmm15 = { 15 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000255
Ben Murdochb0fe1622011-05-05 13:52:32 +0100256
257typedef XMMRegister DoubleRegister;
258
259
Steve Blocka7e24c12009-10-30 11:49:00 +0000260enum Condition {
261 // any value < 0 is considered no_condition
262 no_condition = -1,
263
264 overflow = 0,
265 no_overflow = 1,
266 below = 2,
267 above_equal = 3,
268 equal = 4,
269 not_equal = 5,
270 below_equal = 6,
271 above = 7,
272 negative = 8,
273 positive = 9,
274 parity_even = 10,
275 parity_odd = 11,
276 less = 12,
277 greater_equal = 13,
278 less_equal = 14,
279 greater = 15,
280
Steve Block3ce2e202009-11-05 08:53:23 +0000281 // Fake conditions that are handled by the
282 // opcodes using them.
283 always = 16,
284 never = 17,
Steve Blocka7e24c12009-10-30 11:49:00 +0000285 // aliases
286 carry = below,
287 not_carry = above_equal,
288 zero = equal,
289 not_zero = not_equal,
290 sign = negative,
Steve Block3ce2e202009-11-05 08:53:23 +0000291 not_sign = positive,
292 last_condition = greater
Steve Blocka7e24c12009-10-30 11:49:00 +0000293};
294
295
296// Returns the equivalent of !cc.
297// Negation of the default no_condition (-1) results in a non-default
298// no_condition value (-2). As long as tests for no_condition check
299// for condition < 0, this will work as expected.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100300inline Condition NegateCondition(Condition cc) {
301 return static_cast<Condition>(cc ^ 1);
302}
303
Steve Blocka7e24c12009-10-30 11:49:00 +0000304
305// Corresponds to transposing the operands of a comparison.
306inline Condition ReverseCondition(Condition cc) {
307 switch (cc) {
308 case below:
309 return above;
310 case above:
311 return below;
312 case above_equal:
313 return below_equal;
314 case below_equal:
315 return above_equal;
316 case less:
317 return greater;
318 case greater:
319 return less;
320 case greater_equal:
321 return less_equal;
322 case less_equal:
323 return greater_equal;
324 default:
325 return cc;
326 };
327}
328
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100329
Steve Blocka7e24c12009-10-30 11:49:00 +0000330enum Hint {
331 no_hint = 0,
332 not_taken = 0x2e,
333 taken = 0x3e
334};
335
336// The result of negating a hint is as if the corresponding condition
337// were negated by NegateCondition. That is, no_hint is mapped to
338// itself and not_taken and taken are mapped to each other.
339inline Hint NegateHint(Hint hint) {
340 return (hint == no_hint)
341 ? no_hint
342 : ((hint == not_taken) ? taken : not_taken);
343}
344
345
346// -----------------------------------------------------------------------------
347// Machine instruction Immediates
348
349class Immediate BASE_EMBEDDED {
350 public:
351 explicit Immediate(int32_t value) : value_(value) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000352
353 private:
354 int32_t value_;
355
356 friend class Assembler;
357};
358
359
360// -----------------------------------------------------------------------------
361// Machine instruction Operands
362
363enum ScaleFactor {
364 times_1 = 0,
365 times_2 = 1,
366 times_4 = 2,
367 times_8 = 3,
368 times_int_size = times_4,
Steve Blocka7e24c12009-10-30 11:49:00 +0000369 times_pointer_size = times_8
370};
371
372
373class Operand BASE_EMBEDDED {
374 public:
375 // [base + disp/r]
376 Operand(Register base, int32_t disp);
377
378 // [base + index*scale + disp/r]
379 Operand(Register base,
380 Register index,
381 ScaleFactor scale,
382 int32_t disp);
383
384 // [index*scale + disp/r]
385 Operand(Register index,
386 ScaleFactor scale,
387 int32_t disp);
388
Leon Clarkef7060e22010-06-03 12:02:55 +0100389 // Offset from existing memory operand.
390 // Offset is added to existing displacement as 32-bit signed values and
391 // this must not overflow.
392 Operand(const Operand& base, int32_t offset);
393
Steve Block1e0659c2011-05-24 12:43:12 +0100394 // Checks whether either base or index register is the given register.
395 // Does not check the "reg" part of the Operand.
396 bool AddressUsesRegister(Register reg) const;
397
Steve Block44f0eee2011-05-26 01:26:41 +0100398 // Queries related to the size of the generated instruction.
399 // Whether the generated instruction will have a REX prefix.
400 bool requires_rex() const { return rex_ != 0; }
401 // Size of the ModR/M, SIB and displacement parts of the generated
402 // instruction.
403 int operand_size() const { return len_; }
404
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 private:
406 byte rex_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100407 byte buf_[6];
Steve Block1e0659c2011-05-24 12:43:12 +0100408 // The number of bytes of buf_ in use.
409 byte len_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000410
411 // Set the ModR/M byte without an encoded 'reg' register. The
412 // register is encoded later as part of the emit_operand operation.
413 // set_modrm can be called before or after set_sib and set_disp*.
414 inline void set_modrm(int mod, Register rm);
415
416 // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
417 inline void set_sib(ScaleFactor scale, Register index, Register base);
418
419 // Adds operand displacement fields (offsets added to the memory address).
420 // Needs to be called after set_sib, not before it.
421 inline void set_disp8(int disp);
422 inline void set_disp32(int disp);
423
424 friend class Assembler;
425};
426
427
428// CpuFeatures keeps track of which features are supported by the target CPU.
429// Supported features must be enabled by a Scope before use.
430// Example:
431// if (CpuFeatures::IsSupported(SSE3)) {
432// CpuFeatures::Scope fscope(SSE3);
433// // Generate SSE3 floating point code.
434// } else {
435// // Generate standard x87 or SSE2 floating point code.
436// }
Steve Block44f0eee2011-05-26 01:26:41 +0100437class CpuFeatures {
Steve Blocka7e24c12009-10-30 11:49:00 +0000438 public:
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 // Detect features of the target CPU. Set safe defaults if the serializer
440 // is enabled (snapshots must be portable).
Steve Block44f0eee2011-05-26 01:26:41 +0100441 void Probe(bool portable);
442
Steve Blocka7e24c12009-10-30 11:49:00 +0000443 // Check whether a feature is supported by the target CPU.
Steve Block44f0eee2011-05-26 01:26:41 +0100444 bool IsSupported(CpuFeature f) const {
Steve Block3ce2e202009-11-05 08:53:23 +0000445 if (f == SSE2 && !FLAG_enable_sse2) return false;
446 if (f == SSE3 && !FLAG_enable_sse3) return false;
447 if (f == CMOV && !FLAG_enable_cmov) return false;
448 if (f == RDTSC && !FLAG_enable_rdtsc) return false;
449 if (f == SAHF && !FLAG_enable_sahf) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000450 return (supported_ & (V8_UINT64_C(1) << f)) != 0;
451 }
452 // Check whether a feature is currently enabled.
Steve Block44f0eee2011-05-26 01:26:41 +0100453 bool IsEnabled(CpuFeature f) const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000454 return (enabled_ & (V8_UINT64_C(1) << f)) != 0;
455 }
456 // Enable a specified feature within a scope.
457 class Scope BASE_EMBEDDED {
458#ifdef DEBUG
459 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100460 explicit Scope(CpuFeature f)
461 : cpu_features_(Isolate::Current()->cpu_features()),
462 isolate_(Isolate::Current()) {
Steve Blockd0582a62009-12-15 09:54:21 +0000463 uint64_t mask = (V8_UINT64_C(1) << f);
Steve Block44f0eee2011-05-26 01:26:41 +0100464 ASSERT(cpu_features_->IsSupported(f));
465 ASSERT(!Serializer::enabled() ||
466 (cpu_features_->found_by_runtime_probing_ & mask) == 0);
467 old_enabled_ = cpu_features_->enabled_;
468 cpu_features_->enabled_ |= mask;
Steve Blocka7e24c12009-10-30 11:49:00 +0000469 }
Steve Block44f0eee2011-05-26 01:26:41 +0100470 ~Scope() {
471 ASSERT_EQ(Isolate::Current(), isolate_);
472 cpu_features_->enabled_ = old_enabled_;
473 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000474 private:
475 uint64_t old_enabled_;
Steve Block44f0eee2011-05-26 01:26:41 +0100476 CpuFeatures* cpu_features_;
477 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000478#else
479 public:
Steve Blockd0582a62009-12-15 09:54:21 +0000480 explicit Scope(CpuFeature f) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000481#endif
482 };
483 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100484 CpuFeatures();
485
Steve Blocka7e24c12009-10-30 11:49:00 +0000486 // Safe defaults include SSE2 and CMOV for X64. It is always available, if
487 // anyone checks, but they shouldn't need to check.
Steve Block44f0eee2011-05-26 01:26:41 +0100488 // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
489 // fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
Steve Blockd0582a62009-12-15 09:54:21 +0000490 static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
Steve Block44f0eee2011-05-26 01:26:41 +0100491
492 uint64_t supported_;
493 uint64_t enabled_;
494 uint64_t found_by_runtime_probing_;
495
496 friend class Isolate;
497
498 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
Steve Blocka7e24c12009-10-30 11:49:00 +0000499};
500
501
Steve Block44f0eee2011-05-26 01:26:41 +0100502class Assembler : public AssemblerBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000503 private:
504 // We check before assembling an instruction that there is sufficient
505 // space to write an instruction and its relocation information.
506 // The relocation writer's position must be kGap bytes above the end of
507 // the generated instructions. This leaves enough space for the
508 // longest possible x64 instruction, 15 bytes, and the longest possible
509 // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
510 // (There is a 15 byte limit on x64 instruction length that rules out some
511 // otherwise valid instructions.)
512 // This allows for a single, fast space check per instruction.
513 static const int kGap = 32;
514
515 public:
516 // Create an assembler. Instructions and relocation information are emitted
517 // into a buffer, with the instructions starting from the beginning and the
518 // relocation information starting from the end of the buffer. See CodeDesc
519 // for a detailed comment on the layout (globals.h).
520 //
521 // If the provided buffer is NULL, the assembler allocates and grows its own
522 // buffer, and buffer_size determines the initial buffer size. The buffer is
523 // owned by the assembler and deallocated upon destruction of the assembler.
524 //
525 // If the provided buffer is not NULL, the assembler uses the provided buffer
526 // for code generation and assumes its size to be buffer_size. If the buffer
527 // is too small, a fatal error occurs. No deallocation of the buffer is done
528 // upon destruction of the assembler.
529 Assembler(void* buffer, int buffer_size);
530 ~Assembler();
531
Steve Block44f0eee2011-05-26 01:26:41 +0100532 // Overrides the default provided by FLAG_debug_code.
533 void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
534
Steve Blocka7e24c12009-10-30 11:49:00 +0000535 // GetCode emits any pending (non-emitted) code and fills the descriptor
536 // desc. GetCode() is idempotent; it returns the same result if no other
537 // Assembler functions are invoked in between GetCode() calls.
538 void GetCode(CodeDesc* desc);
539
Steve Block3ce2e202009-11-05 08:53:23 +0000540 // Read/Modify the code target in the relative branch/call instruction at pc.
541 // On the x64 architecture, we use relative jumps with a 32-bit displacement
542 // to jump to other Code objects in the Code space in the heap.
543 // Jumps to C functions are done indirectly through a 64-bit register holding
544 // the absolute address of the target.
545 // These functions convert between absolute Addresses of Code objects and
546 // the relative displacements stored in the code.
Steve Blocka7e24c12009-10-30 11:49:00 +0000547 static inline Address target_address_at(Address pc);
548 static inline void set_target_address_at(Address pc, Address target);
Steve Blockd0582a62009-12-15 09:54:21 +0000549
550 // This sets the branch destination (which is in the instruction on x64).
551 // This is for calls and branches within generated code.
552 inline static void set_target_at(Address instruction_payload,
553 Address target) {
554 set_target_address_at(instruction_payload, target);
555 }
556
557 // This sets the branch destination (which is a load instruction on x64).
558 // This is for calls and branches to runtime code.
559 inline static void set_external_target_at(Address instruction_payload,
560 Address target) {
561 *reinterpret_cast<Address*>(instruction_payload) = target;
562 }
563
Steve Block3ce2e202009-11-05 08:53:23 +0000564 inline Handle<Object> code_target_object_handle_at(Address pc);
Steve Blockd0582a62009-12-15 09:54:21 +0000565 // Number of bytes taken up by the branch target in the code.
566 static const int kCallTargetSize = 4; // Use 32-bit displacement.
567 static const int kExternalTargetSize = 8; // Use 64-bit absolute.
Steve Blocka7e24c12009-10-30 11:49:00 +0000568 // Distance between the address of the code target in the call instruction
Steve Block3ce2e202009-11-05 08:53:23 +0000569 // and the return address pushed on the stack.
570 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
571 // Distance between the start of the JS return sequence and where the
572 // 32-bit displacement of a near call would be, relative to the pushed
573 // return address. TODO: Use return sequence length instead.
574 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
575 static const int kPatchReturnSequenceAddressOffset = 13 - 4;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100576 // Distance between start of patched debug break slot and where the
577 // 32-bit displacement of a near call would be, relative to the pushed
578 // return address. TODO: Use return sequence length instead.
579 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
580 static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
Steve Block3ce2e202009-11-05 08:53:23 +0000581 // TODO(X64): Rename this, removing the "Real", after changing the above.
582 static const int kRealPatchReturnSequenceAddressOffset = 2;
Steve Blockd0582a62009-12-15 09:54:21 +0000583
Steve Block1e0659c2011-05-24 12:43:12 +0100584 // Some x64 JS code is padded with int3 to make it large
585 // enough to hold an instruction when the debugger patches it.
586 static const int kJumpInstructionLength = 13;
Steve Blockd0582a62009-12-15 09:54:21 +0000587 static const int kCallInstructionLength = 13;
588 static const int kJSReturnSequenceLength = 13;
Steve Block1e0659c2011-05-24 12:43:12 +0100589 static const int kShortCallInstructionLength = 5;
Steve Blockd0582a62009-12-15 09:54:21 +0000590
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100591 // The debug break slot must be able to contain a call instruction.
592 static const int kDebugBreakSlotLength = kCallInstructionLength;
593
Steve Block9fac8402011-05-12 15:51:54 +0100594 // One byte opcode for test eax,0xXXXXXXXX.
595 static const byte kTestEaxByte = 0xA9;
Steve Block1e0659c2011-05-24 12:43:12 +0100596 // One byte opcode for test al, 0xXX.
597 static const byte kTestAlByte = 0xA8;
598 // One byte opcode for nop.
599 static const byte kNopByte = 0x90;
600
601 // One byte prefix for a short conditional jump.
602 static const byte kJccShortPrefix = 0x70;
603 static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
604 static const byte kJcShortOpcode = kJccShortPrefix | carry;
605
606
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100607
Steve Blocka7e24c12009-10-30 11:49:00 +0000608 // ---------------------------------------------------------------------------
609 // Code generation
610 //
611 // Function names correspond one-to-one to x64 instruction mnemonics.
612 // Unless specified otherwise, instructions operate on 64-bit operands.
613 //
614 // If we need versions of an assembly instruction that operate on different
615 // width arguments, we add a single-letter suffix specifying the width.
616 // This is done for the following instructions: mov, cmp, inc, dec,
617 // add, sub, and test.
618 // There are no versions of these instructions without the suffix.
619 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
620 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
621 // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
622 // - Instructions on 64-bit (quadword) operands/registers use 'q'.
623 //
624 // Some mnemonics, such as "and", are the same as C++ keywords.
625 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
626
627 // Insert the smallest number of nop instructions
628 // possible to align the pc offset to a multiple
Steve Block1e0659c2011-05-24 12:43:12 +0100629 // of m, where m must be a power of 2.
Steve Blocka7e24c12009-10-30 11:49:00 +0000630 void Align(int m);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100631 // Aligns code to something that's optimal for a jump target for the platform.
632 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000633
634 // Stack
635 void pushfq();
636 void popfq();
637
638 void push(Immediate value);
Steve Block1e0659c2011-05-24 12:43:12 +0100639 // Push a 32 bit integer, and guarantee that it is actually pushed as a
640 // 32 bit value, the normal push will optimize the 8 bit case.
641 void push_imm32(int32_t imm32);
Steve Blocka7e24c12009-10-30 11:49:00 +0000642 void push(Register src);
643 void push(const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000644
645 void pop(Register dst);
646 void pop(const Operand& dst);
647
648 void enter(Immediate size);
649 void leave();
650
651 // Moves
652 void movb(Register dst, const Operand& src);
653 void movb(Register dst, Immediate imm);
654 void movb(const Operand& dst, Register src);
655
Steve Block3ce2e202009-11-05 08:53:23 +0000656 // Move the low 16 bits of a 64-bit register value to a 16-bit
657 // memory location.
658 void movw(const Operand& dst, Register src);
659
Steve Blocka7e24c12009-10-30 11:49:00 +0000660 void movl(Register dst, Register src);
661 void movl(Register dst, const Operand& src);
662 void movl(const Operand& dst, Register src);
663 void movl(const Operand& dst, Immediate imm);
664 // Load a 32-bit immediate value, zero-extended to 64 bits.
665 void movl(Register dst, Immediate imm32);
666
667 // Move 64 bit register value to 64-bit memory location.
668 void movq(const Operand& dst, Register src);
669 // Move 64 bit memory location to 64-bit register value.
670 void movq(Register dst, const Operand& src);
671 void movq(Register dst, Register src);
672 // Sign extends immediate 32-bit value to 64 bits.
673 void movq(Register dst, Immediate x);
674 // Move the offset of the label location relative to the current
675 // position (after the move) to the destination.
676 void movl(const Operand& dst, Label* src);
677
678 // Move sign extended immediate to memory location.
679 void movq(const Operand& dst, Immediate value);
Steve Block44f0eee2011-05-26 01:26:41 +0100680 // Instructions to load a 64-bit immediate into a register.
Steve Blocka7e24c12009-10-30 11:49:00 +0000681 // All 64-bit immediates must have a relocation mode.
682 void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
683 void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
684 void movq(Register dst, const char* s, RelocInfo::Mode rmode);
685 // Moves the address of the external reference into the register.
686 void movq(Register dst, ExternalReference ext);
687 void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
688
Steve Block3ce2e202009-11-05 08:53:23 +0000689 void movsxbq(Register dst, const Operand& src);
690 void movsxwq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000691 void movsxlq(Register dst, Register src);
692 void movsxlq(Register dst, const Operand& src);
693 void movzxbq(Register dst, const Operand& src);
694 void movzxbl(Register dst, const Operand& src);
Steve Block3ce2e202009-11-05 08:53:23 +0000695 void movzxwq(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000696 void movzxwl(Register dst, const Operand& src);
697
Leon Clarked91b9f72010-01-27 17:25:45 +0000698 // Repeated moves.
699
700 void repmovsb();
701 void repmovsw();
702 void repmovsl();
703 void repmovsq();
704
Steve Block44f0eee2011-05-26 01:26:41 +0100705 // Instruction to load from an immediate 64-bit pointer into RAX.
Steve Blocka7e24c12009-10-30 11:49:00 +0000706 void load_rax(void* ptr, RelocInfo::Mode rmode);
707 void load_rax(ExternalReference ext);
708
709 // Conditional moves.
710 void cmovq(Condition cc, Register dst, Register src);
711 void cmovq(Condition cc, Register dst, const Operand& src);
712 void cmovl(Condition cc, Register dst, Register src);
713 void cmovl(Condition cc, Register dst, const Operand& src);
714
715 // Exchange two registers
716 void xchg(Register dst, Register src);
717
718 // Arithmetics
719 void addl(Register dst, Register src) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100720 arithmetic_op_32(0x03, dst, src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000721 }
722
723 void addl(Register dst, Immediate src) {
724 immediate_arithmetic_op_32(0x0, dst, src);
725 }
726
727 void addl(Register dst, const Operand& src) {
728 arithmetic_op_32(0x03, dst, src);
729 }
730
731 void addl(const Operand& dst, Immediate src) {
732 immediate_arithmetic_op_32(0x0, dst, src);
733 }
734
735 void addq(Register dst, Register src) {
736 arithmetic_op(0x03, dst, src);
737 }
738
739 void addq(Register dst, const Operand& src) {
740 arithmetic_op(0x03, dst, src);
741 }
742
743 void addq(const Operand& dst, Register src) {
744 arithmetic_op(0x01, src, dst);
745 }
746
747 void addq(Register dst, Immediate src) {
748 immediate_arithmetic_op(0x0, dst, src);
749 }
750
751 void addq(const Operand& dst, Immediate src) {
752 immediate_arithmetic_op(0x0, dst, src);
753 }
754
Kristian Monsen25f61362010-05-21 11:50:48 +0100755 void sbbl(Register dst, Register src) {
Leon Clarkef7060e22010-06-03 12:02:55 +0100756 arithmetic_op_32(0x1b, dst, src);
Kristian Monsen25f61362010-05-21 11:50:48 +0100757 }
758
Steve Block1e0659c2011-05-24 12:43:12 +0100759 void sbbq(Register dst, Register src) {
760 arithmetic_op(0x1b, dst, src);
761 }
762
Steve Blocka7e24c12009-10-30 11:49:00 +0000763 void cmpb(Register dst, Immediate src) {
764 immediate_arithmetic_op_8(0x7, dst, src);
765 }
766
767 void cmpb_al(Immediate src);
768
769 void cmpb(Register dst, Register src) {
770 arithmetic_op(0x3A, dst, src);
771 }
772
773 void cmpb(Register dst, const Operand& src) {
774 arithmetic_op(0x3A, dst, src);
775 }
776
777 void cmpb(const Operand& dst, Register src) {
778 arithmetic_op(0x38, src, dst);
779 }
780
781 void cmpb(const Operand& dst, Immediate src) {
782 immediate_arithmetic_op_8(0x7, dst, src);
783 }
784
785 void cmpw(const Operand& dst, Immediate src) {
786 immediate_arithmetic_op_16(0x7, dst, src);
787 }
788
789 void cmpw(Register dst, Immediate src) {
790 immediate_arithmetic_op_16(0x7, dst, src);
791 }
792
793 void cmpw(Register dst, const Operand& src) {
794 arithmetic_op_16(0x3B, dst, src);
795 }
796
797 void cmpw(Register dst, Register src) {
798 arithmetic_op_16(0x3B, dst, src);
799 }
800
801 void cmpw(const Operand& dst, Register src) {
802 arithmetic_op_16(0x39, src, dst);
803 }
804
805 void cmpl(Register dst, Register src) {
806 arithmetic_op_32(0x3B, dst, src);
807 }
808
809 void cmpl(Register dst, const Operand& src) {
810 arithmetic_op_32(0x3B, dst, src);
811 }
812
813 void cmpl(const Operand& dst, Register src) {
814 arithmetic_op_32(0x39, src, dst);
815 }
816
817 void cmpl(Register dst, Immediate src) {
818 immediate_arithmetic_op_32(0x7, dst, src);
819 }
820
821 void cmpl(const Operand& dst, Immediate src) {
822 immediate_arithmetic_op_32(0x7, dst, src);
823 }
824
825 void cmpq(Register dst, Register src) {
826 arithmetic_op(0x3B, dst, src);
827 }
828
829 void cmpq(Register dst, const Operand& src) {
830 arithmetic_op(0x3B, dst, src);
831 }
832
833 void cmpq(const Operand& dst, Register src) {
834 arithmetic_op(0x39, src, dst);
835 }
836
837 void cmpq(Register dst, Immediate src) {
838 immediate_arithmetic_op(0x7, dst, src);
839 }
840
841 void cmpq(const Operand& dst, Immediate src) {
842 immediate_arithmetic_op(0x7, dst, src);
843 }
844
845 void and_(Register dst, Register src) {
846 arithmetic_op(0x23, dst, src);
847 }
848
849 void and_(Register dst, const Operand& src) {
850 arithmetic_op(0x23, dst, src);
851 }
852
853 void and_(const Operand& dst, Register src) {
854 arithmetic_op(0x21, src, dst);
855 }
856
857 void and_(Register dst, Immediate src) {
858 immediate_arithmetic_op(0x4, dst, src);
859 }
860
861 void and_(const Operand& dst, Immediate src) {
862 immediate_arithmetic_op(0x4, dst, src);
863 }
864
865 void andl(Register dst, Immediate src) {
866 immediate_arithmetic_op_32(0x4, dst, src);
867 }
868
Steve Block3ce2e202009-11-05 08:53:23 +0000869 void andl(Register dst, Register src) {
870 arithmetic_op_32(0x23, dst, src);
871 }
872
Steve Block1e0659c2011-05-24 12:43:12 +0100873 void andl(Register dst, const Operand& src) {
874 arithmetic_op_32(0x23, dst, src);
875 }
876
Leon Clarke4515c472010-02-03 11:58:03 +0000877 void andb(Register dst, Immediate src) {
878 immediate_arithmetic_op_8(0x4, dst, src);
879 }
Steve Block3ce2e202009-11-05 08:53:23 +0000880
Steve Blocka7e24c12009-10-30 11:49:00 +0000881 void decq(Register dst);
882 void decq(const Operand& dst);
883 void decl(Register dst);
884 void decl(const Operand& dst);
Steve Block3ce2e202009-11-05 08:53:23 +0000885 void decb(Register dst);
886 void decb(const Operand& dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000887
888 // Sign-extends rax into rdx:rax.
889 void cqo();
890 // Sign-extends eax into edx:eax.
891 void cdq();
892
893 // Divide rdx:rax by src. Quotient in rax, remainder in rdx.
894 void idivq(Register src);
895 // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx.
896 void idivl(Register src);
897
898 // Signed multiply instructions.
899 void imul(Register src); // rdx:rax = rax * src.
900 void imul(Register dst, Register src); // dst = dst * src.
901 void imul(Register dst, const Operand& src); // dst = dst * src.
902 void imul(Register dst, Register src, Immediate imm); // dst = src * imm.
Steve Block6ded16b2010-05-10 14:33:55 +0100903 // Signed 32-bit multiply instructions.
904 void imull(Register dst, Register src); // dst = dst * src.
Steve Block1e0659c2011-05-24 12:43:12 +0100905 void imull(Register dst, const Operand& src); // dst = dst * src.
Steve Block6ded16b2010-05-10 14:33:55 +0100906 void imull(Register dst, Register src, Immediate imm); // dst = src * imm.
Steve Blocka7e24c12009-10-30 11:49:00 +0000907
908 void incq(Register dst);
909 void incq(const Operand& dst);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100910 void incl(Register dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000911 void incl(const Operand& dst);
912
913 void lea(Register dst, const Operand& src);
Steve Block6ded16b2010-05-10 14:33:55 +0100914 void leal(Register dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +0000915
916 // Multiply rax by src, put the result in rdx:rax.
917 void mul(Register src);
918
919 void neg(Register dst);
920 void neg(const Operand& dst);
921 void negl(Register dst);
922
923 void not_(Register dst);
924 void not_(const Operand& dst);
Steve Block6ded16b2010-05-10 14:33:55 +0100925 void notl(Register dst);
Steve Blocka7e24c12009-10-30 11:49:00 +0000926
927 void or_(Register dst, Register src) {
928 arithmetic_op(0x0B, dst, src);
929 }
930
931 void orl(Register dst, Register src) {
932 arithmetic_op_32(0x0B, dst, src);
933 }
934
935 void or_(Register dst, const Operand& src) {
936 arithmetic_op(0x0B, dst, src);
937 }
938
Steve Block1e0659c2011-05-24 12:43:12 +0100939 void orl(Register dst, const Operand& src) {
940 arithmetic_op_32(0x0B, dst, src);
941 }
942
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 void or_(const Operand& dst, Register src) {
944 arithmetic_op(0x09, src, dst);
945 }
946
947 void or_(Register dst, Immediate src) {
948 immediate_arithmetic_op(0x1, dst, src);
949 }
950
Steve Block3ce2e202009-11-05 08:53:23 +0000951 void orl(Register dst, Immediate src) {
952 immediate_arithmetic_op_32(0x1, dst, src);
953 }
954
Steve Blocka7e24c12009-10-30 11:49:00 +0000955 void or_(const Operand& dst, Immediate src) {
956 immediate_arithmetic_op(0x1, dst, src);
957 }
958
Steve Block3ce2e202009-11-05 08:53:23 +0000959 void orl(const Operand& dst, Immediate src) {
960 immediate_arithmetic_op_32(0x1, dst, src);
961 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000962
Steve Block3ce2e202009-11-05 08:53:23 +0000963
964 void rcl(Register dst, Immediate imm8) {
965 shift(dst, imm8, 0x2);
966 }
967
968 void rol(Register dst, Immediate imm8) {
969 shift(dst, imm8, 0x0);
970 }
971
972 void rcr(Register dst, Immediate imm8) {
973 shift(dst, imm8, 0x3);
974 }
975
976 void ror(Register dst, Immediate imm8) {
977 shift(dst, imm8, 0x1);
978 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000979
980 // Shifts dst:src left by cl bits, affecting only dst.
981 void shld(Register dst, Register src);
982
983 // Shifts src:dst right by cl bits, affecting only dst.
984 void shrd(Register dst, Register src);
985
986 // Shifts dst right, duplicating sign bit, by shift_amount bits.
987 // Shifting by 1 is handled efficiently.
988 void sar(Register dst, Immediate shift_amount) {
989 shift(dst, shift_amount, 0x7);
990 }
991
992 // Shifts dst right, duplicating sign bit, by shift_amount bits.
993 // Shifting by 1 is handled efficiently.
994 void sarl(Register dst, Immediate shift_amount) {
995 shift_32(dst, shift_amount, 0x7);
996 }
997
998 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
Steve Blockd0582a62009-12-15 09:54:21 +0000999 void sar_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001000 shift(dst, 0x7);
1001 }
1002
1003 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
Steve Blockd0582a62009-12-15 09:54:21 +00001004 void sarl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001005 shift_32(dst, 0x7);
1006 }
1007
1008 void shl(Register dst, Immediate shift_amount) {
1009 shift(dst, shift_amount, 0x4);
1010 }
1011
Steve Blockd0582a62009-12-15 09:54:21 +00001012 void shl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001013 shift(dst, 0x4);
1014 }
1015
Steve Blockd0582a62009-12-15 09:54:21 +00001016 void shll_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001017 shift_32(dst, 0x4);
1018 }
1019
1020 void shll(Register dst, Immediate shift_amount) {
1021 shift_32(dst, shift_amount, 0x4);
1022 }
1023
1024 void shr(Register dst, Immediate shift_amount) {
1025 shift(dst, shift_amount, 0x5);
1026 }
1027
Steve Blockd0582a62009-12-15 09:54:21 +00001028 void shr_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001029 shift(dst, 0x5);
1030 }
1031
Steve Blockd0582a62009-12-15 09:54:21 +00001032 void shrl_cl(Register dst) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001033 shift_32(dst, 0x5);
1034 }
1035
1036 void shrl(Register dst, Immediate shift_amount) {
1037 shift_32(dst, shift_amount, 0x5);
1038 }
1039
1040 void store_rax(void* dst, RelocInfo::Mode mode);
1041 void store_rax(ExternalReference ref);
1042
1043 void subq(Register dst, Register src) {
1044 arithmetic_op(0x2B, dst, src);
1045 }
1046
1047 void subq(Register dst, const Operand& src) {
1048 arithmetic_op(0x2B, dst, src);
1049 }
1050
1051 void subq(const Operand& dst, Register src) {
1052 arithmetic_op(0x29, src, dst);
1053 }
1054
1055 void subq(Register dst, Immediate src) {
1056 immediate_arithmetic_op(0x5, dst, src);
1057 }
1058
1059 void subq(const Operand& dst, Immediate src) {
1060 immediate_arithmetic_op(0x5, dst, src);
1061 }
1062
1063 void subl(Register dst, Register src) {
1064 arithmetic_op_32(0x2B, dst, src);
1065 }
1066
Leon Clarkee46be812010-01-19 14:06:41 +00001067 void subl(Register dst, const Operand& src) {
1068 arithmetic_op_32(0x2B, dst, src);
1069 }
1070
Steve Blocka7e24c12009-10-30 11:49:00 +00001071 void subl(const Operand& dst, Immediate src) {
1072 immediate_arithmetic_op_32(0x5, dst, src);
1073 }
1074
1075 void subl(Register dst, Immediate src) {
1076 immediate_arithmetic_op_32(0x5, dst, src);
1077 }
1078
1079 void subb(Register dst, Immediate src) {
1080 immediate_arithmetic_op_8(0x5, dst, src);
1081 }
1082
Steve Block3ce2e202009-11-05 08:53:23 +00001083 void testb(Register dst, Register src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001084 void testb(Register reg, Immediate mask);
1085 void testb(const Operand& op, Immediate mask);
Leon Clarkee46be812010-01-19 14:06:41 +00001086 void testb(const Operand& op, Register reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001087 void testl(Register dst, Register src);
1088 void testl(Register reg, Immediate mask);
1089 void testl(const Operand& op, Immediate mask);
1090 void testq(const Operand& op, Register reg);
1091 void testq(Register dst, Register src);
1092 void testq(Register dst, Immediate mask);
1093
1094 void xor_(Register dst, Register src) {
Steve Blockd0582a62009-12-15 09:54:21 +00001095 if (dst.code() == src.code()) {
1096 arithmetic_op_32(0x33, dst, src);
1097 } else {
1098 arithmetic_op(0x33, dst, src);
1099 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001100 }
1101
1102 void xorl(Register dst, Register src) {
1103 arithmetic_op_32(0x33, dst, src);
1104 }
1105
Steve Block1e0659c2011-05-24 12:43:12 +01001106 void xorl(Register dst, const Operand& src) {
1107 arithmetic_op_32(0x33, dst, src);
1108 }
1109
1110 void xorl(Register dst, Immediate src) {
1111 immediate_arithmetic_op_32(0x6, dst, src);
1112 }
1113
1114 void xorl(const Operand& dst, Immediate src) {
1115 immediate_arithmetic_op_32(0x6, dst, src);
1116 }
1117
Steve Blocka7e24c12009-10-30 11:49:00 +00001118 void xor_(Register dst, const Operand& src) {
1119 arithmetic_op(0x33, dst, src);
1120 }
1121
1122 void xor_(const Operand& dst, Register src) {
1123 arithmetic_op(0x31, src, dst);
1124 }
1125
1126 void xor_(Register dst, Immediate src) {
1127 immediate_arithmetic_op(0x6, dst, src);
1128 }
1129
1130 void xor_(const Operand& dst, Immediate src) {
1131 immediate_arithmetic_op(0x6, dst, src);
1132 }
1133
1134 // Bit operations.
1135 void bt(const Operand& dst, Register src);
1136 void bts(const Operand& dst, Register src);
1137
1138 // Miscellaneous
Steve Block3ce2e202009-11-05 08:53:23 +00001139 void clc();
Steve Block44f0eee2011-05-26 01:26:41 +01001140 void cld();
Steve Blocka7e24c12009-10-30 11:49:00 +00001141 void cpuid();
1142 void hlt();
1143 void int3();
1144 void nop();
1145 void nop(int n);
1146 void rdtsc();
1147 void ret(int imm16);
1148 void setcc(Condition cc, Register reg);
1149
1150 // Label operations & relative jumps (PPUM Appendix D)
1151 //
1152 // Takes a branch opcode (cc) and a label (L) and generates
1153 // either a backward branch or a forward branch and links it
1154 // to the label fixup chain. Usage:
1155 //
1156 // Label L; // unbound label
1157 // j(cc, &L); // forward branch to unbound label
1158 // bind(&L); // bind label to the current pc
1159 // j(cc, &L); // backward branch to bound label
1160 // bind(&L); // illegal: a label may be bound only once
1161 //
1162 // Note: The same Label can be used for forward and backward branches
1163 // but it may be bound only once.
1164
1165 void bind(Label* L); // binds an unbound label L to the current code position
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001166 void bind(NearLabel* L);
Steve Blocka7e24c12009-10-30 11:49:00 +00001167
1168 // Calls
1169 // Call near relative 32-bit displacement, relative to next instruction.
1170 void call(Label* L);
Steve Block3ce2e202009-11-05 08:53:23 +00001171 void call(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001172
Steve Block1e0659c2011-05-24 12:43:12 +01001173 // Calls directly to the given address using a relative offset.
1174 // Should only ever be used in Code objects for calls within the
1175 // same Code object. Should not be used when generating new code (use labels),
1176 // but only when patching existing code.
1177 void call(Address target);
1178
Steve Blocka7e24c12009-10-30 11:49:00 +00001179 // Call near absolute indirect, address in register
1180 void call(Register adr);
1181
1182 // Call near indirect
1183 void call(const Operand& operand);
1184
1185 // Jumps
1186 // Jump short or near relative.
Steve Block3ce2e202009-11-05 08:53:23 +00001187 // Use a 32-bit signed displacement.
Steve Blocka7e24c12009-10-30 11:49:00 +00001188 void jmp(Label* L); // unconditional jump to L
Steve Block3ce2e202009-11-05 08:53:23 +00001189 void jmp(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001190
1191 // Jump near absolute indirect (r64)
1192 void jmp(Register adr);
1193
1194 // Jump near absolute indirect (m64)
1195 void jmp(const Operand& src);
1196
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001197 // Short jump
1198 void jmp(NearLabel* L);
1199
Steve Blocka7e24c12009-10-30 11:49:00 +00001200 // Conditional jumps
1201 void j(Condition cc, Label* L);
Steve Block3ce2e202009-11-05 08:53:23 +00001202 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001203
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001204 // Conditional short jump
1205 void j(Condition cc, NearLabel* L, Hint hint = no_hint);
1206
Steve Blocka7e24c12009-10-30 11:49:00 +00001207 // Floating-point operations
1208 void fld(int i);
1209
1210 void fld1();
1211 void fldz();
Steve Block6ded16b2010-05-10 14:33:55 +01001212 void fldpi();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001213 void fldln2();
Steve Blocka7e24c12009-10-30 11:49:00 +00001214
1215 void fld_s(const Operand& adr);
1216 void fld_d(const Operand& adr);
1217
1218 void fstp_s(const Operand& adr);
1219 void fstp_d(const Operand& adr);
Steve Block3ce2e202009-11-05 08:53:23 +00001220 void fstp(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001221
1222 void fild_s(const Operand& adr);
1223 void fild_d(const Operand& adr);
1224
1225 void fist_s(const Operand& adr);
1226
1227 void fistp_s(const Operand& adr);
1228 void fistp_d(const Operand& adr);
1229
1230 void fisttp_s(const Operand& adr);
Leon Clarked91b9f72010-01-27 17:25:45 +00001231 void fisttp_d(const Operand& adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001232
1233 void fabs();
1234 void fchs();
1235
1236 void fadd(int i);
1237 void fsub(int i);
1238 void fmul(int i);
1239 void fdiv(int i);
1240
1241 void fisub_s(const Operand& adr);
1242
1243 void faddp(int i = 1);
1244 void fsubp(int i = 1);
1245 void fsubrp(int i = 1);
1246 void fmulp(int i = 1);
1247 void fdivp(int i = 1);
1248 void fprem();
1249 void fprem1();
1250
1251 void fxch(int i = 1);
1252 void fincstp();
1253 void ffree(int i = 0);
1254
1255 void ftst();
1256 void fucomp(int i);
1257 void fucompp();
Steve Block3ce2e202009-11-05 08:53:23 +00001258 void fucomi(int i);
1259 void fucomip();
1260
Steve Blocka7e24c12009-10-30 11:49:00 +00001261 void fcompp();
1262 void fnstsw_ax();
1263 void fwait();
1264 void fnclex();
1265
1266 void fsin();
1267 void fcos();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001268 void fyl2x();
Steve Blocka7e24c12009-10-30 11:49:00 +00001269
1270 void frndint();
1271
1272 void sahf();
1273
1274 // SSE2 instructions
Steve Block6ded16b2010-05-10 14:33:55 +01001275 void movd(XMMRegister dst, Register src);
1276 void movd(Register dst, XMMRegister src);
1277 void movq(XMMRegister dst, Register src);
1278 void movq(Register dst, XMMRegister src);
1279 void extractps(Register dst, XMMRegister src, byte imm8);
1280
Steve Blocka7e24c12009-10-30 11:49:00 +00001281 void movsd(const Operand& dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001282 void movsd(XMMRegister dst, XMMRegister src);
1283 void movsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001284
Steve Block1e0659c2011-05-24 12:43:12 +01001285 void movdqa(const Operand& dst, XMMRegister src);
1286 void movdqa(XMMRegister dst, const Operand& src);
1287
Steve Block8defd9f2010-07-08 12:39:36 +01001288 void movss(XMMRegister dst, const Operand& src);
1289 void movss(const Operand& dst, XMMRegister src);
1290
Steve Blocka7e24c12009-10-30 11:49:00 +00001291 void cvttss2si(Register dst, const Operand& src);
Steve Block1e0659c2011-05-24 12:43:12 +01001292 void cvttss2si(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001293 void cvttsd2si(Register dst, const Operand& src);
Steve Block1e0659c2011-05-24 12:43:12 +01001294 void cvttsd2si(Register dst, XMMRegister src);
Kristian Monsen25f61362010-05-21 11:50:48 +01001295 void cvttsd2siq(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001296
1297 void cvtlsi2sd(XMMRegister dst, const Operand& src);
1298 void cvtlsi2sd(XMMRegister dst, Register src);
1299 void cvtqsi2sd(XMMRegister dst, const Operand& src);
1300 void cvtqsi2sd(XMMRegister dst, Register src);
1301
Steve Block8defd9f2010-07-08 12:39:36 +01001302 void cvtlsi2ss(XMMRegister dst, Register src);
1303
Steve Block6ded16b2010-05-10 14:33:55 +01001304 void cvtss2sd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001305 void cvtss2sd(XMMRegister dst, const Operand& src);
1306 void cvtsd2ss(XMMRegister dst, XMMRegister src);
1307
1308 void cvtsd2si(Register dst, XMMRegister src);
1309 void cvtsd2siq(Register dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001310
Steve Blocka7e24c12009-10-30 11:49:00 +00001311 void addsd(XMMRegister dst, XMMRegister src);
1312 void subsd(XMMRegister dst, XMMRegister src);
1313 void mulsd(XMMRegister dst, XMMRegister src);
1314 void divsd(XMMRegister dst, XMMRegister src);
1315
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001316 void andpd(XMMRegister dst, XMMRegister src);
1317 void orpd(XMMRegister dst, XMMRegister src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001318 void xorpd(XMMRegister dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001319 void sqrtsd(XMMRegister dst, XMMRegister src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001320
Andrei Popescu402d9372010-02-26 13:31:12 +00001321 void ucomisd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001322 void ucomisd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001323
Steve Block1e0659c2011-05-24 12:43:12 +01001324 void movmskpd(Register dst, XMMRegister src);
1325
Steve Block6ded16b2010-05-10 14:33:55 +01001326 // The first argument is the reg field, the second argument is the r/m field.
Steve Blocka7e24c12009-10-30 11:49:00 +00001327 void emit_sse_operand(XMMRegister dst, XMMRegister src);
1328 void emit_sse_operand(XMMRegister reg, const Operand& adr);
1329 void emit_sse_operand(XMMRegister dst, Register src);
Steve Block6ded16b2010-05-10 14:33:55 +01001330 void emit_sse_operand(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001331
Steve Blocka7e24c12009-10-30 11:49:00 +00001332 // Debugging
1333 void Print();
1334
1335 // Check the code size generated from label to here.
1336 int SizeOfCodeGeneratedSince(Label* l) { return pc_offset() - l->pos(); }
1337
1338 // Mark address of the ExitJSFrame code.
1339 void RecordJSReturn();
1340
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001341 // Mark address of a debug break slot.
1342 void RecordDebugBreakSlot();
1343
Steve Blocka7e24c12009-10-30 11:49:00 +00001344 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001345 // Use --code-comments to enable.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001346 void RecordComment(const char* msg, bool force = false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001347
Ben Murdochb0fe1622011-05-05 13:52:32 +01001348 // Writes a single word of data in the code stream.
1349 // Used for inline tables, e.g., jump-tables.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001350 void db(uint8_t data);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001351 void dd(uint32_t data);
1352
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001353 int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001354
1355 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001356
1357 // Check if there is less than kGap bytes available in the buffer.
1358 // If this is the case, we need to grow the buffer before emitting
1359 // an instruction or relocation information.
1360 inline bool buffer_overflow() const {
1361 return pc_ >= reloc_info_writer.pos() - kGap;
1362 }
1363
1364 // Get the number of bytes available in the buffer.
Steve Blockd0582a62009-12-15 09:54:21 +00001365 inline int available_space() const {
1366 return static_cast<int>(reloc_info_writer.pos() - pc_);
1367 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001368
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001369 static bool IsNop(Address addr) { return *addr == 0x90; }
1370
Steve Blocka7e24c12009-10-30 11:49:00 +00001371 // Avoid overflows for displacements etc.
1372 static const int kMaximalBufferSize = 512*MB;
1373 static const int kMinimalBufferSize = 4*KB;
1374
Steve Block44f0eee2011-05-26 01:26:41 +01001375 protected:
1376 bool emit_debug_code() const { return emit_debug_code_; }
1377
Steve Blocka7e24c12009-10-30 11:49:00 +00001378 private:
1379 byte* addr_at(int pos) { return buffer_ + pos; }
1380 byte byte_at(int pos) { return buffer_[pos]; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001381 void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001382 uint32_t long_at(int pos) {
1383 return *reinterpret_cast<uint32_t*>(addr_at(pos));
1384 }
1385 void long_at_put(int pos, uint32_t x) {
1386 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1387 }
1388
1389 // code emission
1390 void GrowBuffer();
1391
1392 void emit(byte x) { *pc_++ = x; }
1393 inline void emitl(uint32_t x);
Steve Blocka7e24c12009-10-30 11:49:00 +00001394 inline void emitq(uint64_t x, RelocInfo::Mode rmode);
1395 inline void emitw(uint16_t x);
Steve Block3ce2e202009-11-05 08:53:23 +00001396 inline void emit_code_target(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001397 void emit(Immediate x) { emitl(x.value_); }
1398
1399 // Emits a REX prefix that encodes a 64-bit operand size and
1400 // the top bit of both register codes.
1401 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1402 // REX.W is set.
Steve Blocka7e24c12009-10-30 11:49:00 +00001403 inline void emit_rex_64(XMMRegister reg, Register rm_reg);
Steve Block6ded16b2010-05-10 14:33:55 +01001404 inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1405 inline void emit_rex_64(Register reg, Register rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001406
1407 // Emits a REX prefix that encodes a 64-bit operand size and
1408 // the top bit of the destination, index, and base register codes.
1409 // The high bit of reg is used for REX.R, the high bit of op's base
1410 // register is used for REX.B, and the high bit of op's index register
1411 // is used for REX.X. REX.W is set.
1412 inline void emit_rex_64(Register reg, const Operand& op);
1413 inline void emit_rex_64(XMMRegister reg, const Operand& op);
1414
1415 // Emits a REX prefix that encodes a 64-bit operand size and
1416 // the top bit of the register code.
1417 // The high bit of register is used for REX.B.
1418 // REX.W is set and REX.R and REX.X are clear.
1419 inline void emit_rex_64(Register rm_reg);
1420
1421 // Emits a REX prefix that encodes a 64-bit operand size and
1422 // the top bit of the index and base register codes.
1423 // The high bit of op's base register is used for REX.B, and the high
1424 // bit of op's index register is used for REX.X.
1425 // REX.W is set and REX.R clear.
1426 inline void emit_rex_64(const Operand& op);
1427
1428 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1429 void emit_rex_64() { emit(0x48); }
1430
1431 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1432 // REX.W is clear.
1433 inline void emit_rex_32(Register reg, Register rm_reg);
1434
1435 // The high bit of reg is used for REX.R, the high bit of op's base
1436 // register is used for REX.B, and the high bit of op's index register
1437 // is used for REX.X. REX.W is cleared.
1438 inline void emit_rex_32(Register reg, const Operand& op);
1439
1440 // High bit of rm_reg goes to REX.B.
1441 // REX.W, REX.R and REX.X are clear.
1442 inline void emit_rex_32(Register rm_reg);
1443
1444 // High bit of base goes to REX.B and high bit of index to REX.X.
1445 // REX.W and REX.R are clear.
1446 inline void emit_rex_32(const Operand& op);
1447
1448 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1449 // REX.W is cleared. If no REX bits are set, no byte is emitted.
1450 inline void emit_optional_rex_32(Register reg, Register rm_reg);
1451
1452 // The high bit of reg is used for REX.R, the high bit of op's base
1453 // register is used for REX.B, and the high bit of op's index register
1454 // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
1455 // is emitted.
1456 inline void emit_optional_rex_32(Register reg, const Operand& op);
1457
1458 // As for emit_optional_rex_32(Register, Register), except that
1459 // the registers are XMM registers.
1460 inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1461
1462 // As for emit_optional_rex_32(Register, Register), except that
Steve Block6ded16b2010-05-10 14:33:55 +01001463 // one of the registers is an XMM registers.
Steve Blocka7e24c12009-10-30 11:49:00 +00001464 inline void emit_optional_rex_32(XMMRegister reg, Register base);
1465
Steve Block6ded16b2010-05-10 14:33:55 +01001466 // As for emit_optional_rex_32(Register, Register), except that
1467 // one of the registers is an XMM registers.
1468 inline void emit_optional_rex_32(Register reg, XMMRegister base);
1469
Steve Blocka7e24c12009-10-30 11:49:00 +00001470 // As for emit_optional_rex_32(Register, const Operand&), except that
1471 // the register is an XMM register.
1472 inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1473
1474 // Optionally do as emit_rex_32(Register) if the register number has
1475 // the high bit set.
1476 inline void emit_optional_rex_32(Register rm_reg);
1477
1478 // Optionally do as emit_rex_32(const Operand&) if the operand register
1479 // numbers have a high bit set.
1480 inline void emit_optional_rex_32(const Operand& op);
1481
1482
1483 // Emit the ModR/M byte, and optionally the SIB byte and
1484 // 1- or 4-byte offset for a memory operand. Also encodes
1485 // the second operand of the operation, a register or operation
1486 // subcode, into the reg field of the ModR/M byte.
1487 void emit_operand(Register reg, const Operand& adr) {
1488 emit_operand(reg.low_bits(), adr);
1489 }
1490
1491 // Emit the ModR/M byte, and optionally the SIB byte and
1492 // 1- or 4-byte offset for a memory operand. Also used to encode
1493 // a three-bit opcode extension into the ModR/M byte.
1494 void emit_operand(int rm, const Operand& adr);
1495
1496 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1497 void emit_modrm(Register reg, Register rm_reg) {
1498 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1499 }
1500
1501 // Emit a ModR/M byte with an operation subcode in the reg field and
1502 // a register in the rm_reg field.
1503 void emit_modrm(int code, Register rm_reg) {
1504 ASSERT(is_uint3(code));
1505 emit(0xC0 | code << 3 | rm_reg.low_bits());
1506 }
1507
1508 // Emit the code-object-relative offset of the label's position
1509 inline void emit_code_relative_offset(Label* label);
1510
1511 // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1512 // AND, OR, XOR, or CMP. The encodings of these operations are all
1513 // similar, differing just in the opcode or in the reg field of the
1514 // ModR/M byte.
1515 void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1516 void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1517 void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
1518 void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
1519 void arithmetic_op(byte opcode, Register reg, Register rm_reg);
1520 void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
1521 void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1522 void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
1523 // Operate on a byte in memory or register.
1524 void immediate_arithmetic_op_8(byte subcode,
1525 Register dst,
1526 Immediate src);
1527 void immediate_arithmetic_op_8(byte subcode,
1528 const Operand& dst,
1529 Immediate src);
1530 // Operate on a word in memory or register.
1531 void immediate_arithmetic_op_16(byte subcode,
1532 Register dst,
1533 Immediate src);
1534 void immediate_arithmetic_op_16(byte subcode,
1535 const Operand& dst,
1536 Immediate src);
1537 // Operate on a 32-bit word in memory or register.
1538 void immediate_arithmetic_op_32(byte subcode,
1539 Register dst,
1540 Immediate src);
1541 void immediate_arithmetic_op_32(byte subcode,
1542 const Operand& dst,
1543 Immediate src);
1544
1545 // Emit machine code for a shift operation.
1546 void shift(Register dst, Immediate shift_amount, int subcode);
1547 void shift_32(Register dst, Immediate shift_amount, int subcode);
1548 // Shift dst by cl % 64 bits.
1549 void shift(Register dst, int subcode);
1550 void shift_32(Register dst, int subcode);
1551
1552 void emit_farith(int b1, int b2, int i);
1553
1554 // labels
1555 // void print(Label* L);
1556 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001557
1558 // record reloc info for current pc_
1559 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1560
1561 friend class CodePatcher;
1562 friend class EnsureSpace;
1563 friend class RegExpMacroAssemblerX64;
1564
1565 // Code buffer:
1566 // The buffer into which code and relocation info are generated.
1567 byte* buffer_;
1568 int buffer_size_;
1569 // True if the assembler owns the buffer, false if buffer is external.
1570 bool own_buffer_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001571
1572 // code generation
1573 byte* pc_; // the program counter; moves forward
1574 RelocInfoWriter reloc_info_writer;
1575
Steve Block3ce2e202009-11-05 08:53:23 +00001576 List< Handle<Code> > code_targets_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001577 // push-pop elimination
1578 byte* last_pc_;
1579
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001580 PositionsRecorder positions_recorder_;
Steve Block44f0eee2011-05-26 01:26:41 +01001581
1582 bool emit_debug_code_;
1583
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001584 friend class PositionsRecorder;
Steve Blocka7e24c12009-10-30 11:49:00 +00001585};
1586
1587
1588// Helper class that ensures that there is enough space for generating
1589// instructions and relocation information. The constructor makes
1590// sure that there is enough space and (in debug mode) the destructor
1591// checks that we did not generate too much.
1592class EnsureSpace BASE_EMBEDDED {
1593 public:
1594 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1595 if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1596#ifdef DEBUG
1597 space_before_ = assembler_->available_space();
1598#endif
1599 }
1600
1601#ifdef DEBUG
1602 ~EnsureSpace() {
1603 int bytes_generated = space_before_ - assembler_->available_space();
1604 ASSERT(bytes_generated < assembler_->kGap);
1605 }
1606#endif
1607
1608 private:
1609 Assembler* assembler_;
1610#ifdef DEBUG
1611 int space_before_;
1612#endif
1613};
1614
1615} } // namespace v8::internal
1616
1617#endif // V8_X64_ASSEMBLER_X64_H_