blob: c23eb168978a1438032776cb1b453ce5a91e0b46 [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
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000128 static Register from_code(int code) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000129 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 +0000330// -----------------------------------------------------------------------------
331// Machine instruction Immediates
332
333class Immediate BASE_EMBEDDED {
334 public:
335 explicit Immediate(int32_t value) : value_(value) {}
Steve Blocka7e24c12009-10-30 11:49:00 +0000336
337 private:
338 int32_t value_;
339
340 friend class Assembler;
341};
342
343
344// -----------------------------------------------------------------------------
345// Machine instruction Operands
346
347enum ScaleFactor {
348 times_1 = 0,
349 times_2 = 1,
350 times_4 = 2,
351 times_8 = 3,
352 times_int_size = times_4,
Steve Blocka7e24c12009-10-30 11:49:00 +0000353 times_pointer_size = times_8
354};
355
356
357class Operand BASE_EMBEDDED {
358 public:
359 // [base + disp/r]
360 Operand(Register base, int32_t disp);
361
362 // [base + index*scale + disp/r]
363 Operand(Register base,
364 Register index,
365 ScaleFactor scale,
366 int32_t disp);
367
368 // [index*scale + disp/r]
369 Operand(Register index,
370 ScaleFactor scale,
371 int32_t disp);
372
Leon Clarkef7060e22010-06-03 12:02:55 +0100373 // Offset from existing memory operand.
374 // Offset is added to existing displacement as 32-bit signed values and
375 // this must not overflow.
376 Operand(const Operand& base, int32_t offset);
377
Steve Block1e0659c2011-05-24 12:43:12 +0100378 // Checks whether either base or index register is the given register.
379 // Does not check the "reg" part of the Operand.
380 bool AddressUsesRegister(Register reg) const;
381
Steve Block44f0eee2011-05-26 01:26:41 +0100382 // Queries related to the size of the generated instruction.
383 // Whether the generated instruction will have a REX prefix.
384 bool requires_rex() const { return rex_ != 0; }
385 // Size of the ModR/M, SIB and displacement parts of the generated
386 // instruction.
387 int operand_size() const { return len_; }
388
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 private:
390 byte rex_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100391 byte buf_[6];
Steve Block1e0659c2011-05-24 12:43:12 +0100392 // The number of bytes of buf_ in use.
393 byte len_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000394
395 // Set the ModR/M byte without an encoded 'reg' register. The
396 // register is encoded later as part of the emit_operand operation.
397 // set_modrm can be called before or after set_sib and set_disp*.
398 inline void set_modrm(int mod, Register rm);
399
400 // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
401 inline void set_sib(ScaleFactor scale, Register index, Register base);
402
403 // Adds operand displacement fields (offsets added to the memory address).
404 // Needs to be called after set_sib, not before it.
405 inline void set_disp8(int disp);
406 inline void set_disp32(int disp);
407
408 friend class Assembler;
409};
410
411
412// CpuFeatures keeps track of which features are supported by the target CPU.
413// Supported features must be enabled by a Scope before use.
414// Example:
415// if (CpuFeatures::IsSupported(SSE3)) {
416// CpuFeatures::Scope fscope(SSE3);
417// // Generate SSE3 floating point code.
418// } else {
419// // Generate standard x87 or SSE2 floating point code.
420// }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100421class CpuFeatures : public AllStatic {
Steve Blocka7e24c12009-10-30 11:49:00 +0000422 public:
Steve Blocka7e24c12009-10-30 11:49:00 +0000423 // Detect features of the target CPU. Set safe defaults if the serializer
424 // is enabled (snapshots must be portable).
Ben Murdoch8b112d22011-06-08 16:22:53 +0100425 static void Probe();
Steve Block44f0eee2011-05-26 01:26:41 +0100426
Steve Blocka7e24c12009-10-30 11:49:00 +0000427 // Check whether a feature is supported by the target CPU.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100428 static bool IsSupported(CpuFeature f) {
429 ASSERT(initialized_);
Steve Block3ce2e202009-11-05 08:53:23 +0000430 if (f == SSE2 && !FLAG_enable_sse2) return false;
431 if (f == SSE3 && !FLAG_enable_sse3) return false;
432 if (f == CMOV && !FLAG_enable_cmov) return false;
433 if (f == RDTSC && !FLAG_enable_rdtsc) return false;
434 if (f == SAHF && !FLAG_enable_sahf) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 return (supported_ & (V8_UINT64_C(1) << f)) != 0;
436 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100437
438#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +0000439 // Check whether a feature is currently enabled.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100440 static bool IsEnabled(CpuFeature f) {
441 ASSERT(initialized_);
442 Isolate* isolate = Isolate::UncheckedCurrent();
443 if (isolate == NULL) {
444 // When no isolate is available, work as if we're running in
445 // release mode.
446 return IsSupported(f);
447 }
448 uint64_t enabled = isolate->enabled_cpu_features();
449 return (enabled & (V8_UINT64_C(1) << f)) != 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000450 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100451#endif
452
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 // Enable a specified feature within a scope.
454 class Scope BASE_EMBEDDED {
455#ifdef DEBUG
456 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100457 explicit Scope(CpuFeature f) {
458 uint64_t mask = V8_UINT64_C(1) << f;
459 ASSERT(CpuFeatures::IsSupported(f));
Steve Block44f0eee2011-05-26 01:26:41 +0100460 ASSERT(!Serializer::enabled() ||
Ben Murdoch8b112d22011-06-08 16:22:53 +0100461 (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
462 isolate_ = Isolate::UncheckedCurrent();
463 old_enabled_ = 0;
464 if (isolate_ != NULL) {
465 old_enabled_ = isolate_->enabled_cpu_features();
466 isolate_->set_enabled_cpu_features(old_enabled_ | mask);
467 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 }
Steve Block44f0eee2011-05-26 01:26:41 +0100469 ~Scope() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100470 ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
471 if (isolate_ != NULL) {
472 isolate_->set_enabled_cpu_features(old_enabled_);
473 }
Steve Block44f0eee2011-05-26 01:26:41 +0100474 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000475 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100476 Isolate* isolate_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100477 uint64_t old_enabled_;
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 };
Steve Block44f0eee2011-05-26 01:26:41 +0100483
Ben Murdoch8b112d22011-06-08 16:22:53 +0100484 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 // Safe defaults include SSE2 and CMOV for X64. It is always available, if
486 // anyone checks, but they shouldn't need to check.
Steve Block44f0eee2011-05-26 01:26:41 +0100487 // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
488 // fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
Steve Blockd0582a62009-12-15 09:54:21 +0000489 static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
Steve Block44f0eee2011-05-26 01:26:41 +0100490
Ben Murdoch8b112d22011-06-08 16:22:53 +0100491#ifdef DEBUG
492 static bool initialized_;
493#endif
494 static uint64_t supported_;
495 static uint64_t found_by_runtime_probing_;
Steve Block44f0eee2011-05-26 01:26:41 +0100496
497 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
Steve Blocka7e24c12009-10-30 11:49:00 +0000498};
499
500
Steve Block44f0eee2011-05-26 01:26:41 +0100501class Assembler : public AssemblerBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000502 private:
503 // We check before assembling an instruction that there is sufficient
504 // space to write an instruction and its relocation information.
505 // The relocation writer's position must be kGap bytes above the end of
506 // the generated instructions. This leaves enough space for the
507 // longest possible x64 instruction, 15 bytes, and the longest possible
508 // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
509 // (There is a 15 byte limit on x64 instruction length that rules out some
510 // otherwise valid instructions.)
511 // This allows for a single, fast space check per instruction.
512 static const int kGap = 32;
513
514 public:
515 // Create an assembler. Instructions and relocation information are emitted
516 // into a buffer, with the instructions starting from the beginning and the
517 // relocation information starting from the end of the buffer. See CodeDesc
518 // for a detailed comment on the layout (globals.h).
519 //
520 // If the provided buffer is NULL, the assembler allocates and grows its own
521 // buffer, and buffer_size determines the initial buffer size. The buffer is
522 // owned by the assembler and deallocated upon destruction of the assembler.
523 //
524 // If the provided buffer is not NULL, the assembler uses the provided buffer
525 // for code generation and assumes its size to be buffer_size. If the buffer
526 // is too small, a fatal error occurs. No deallocation of the buffer is done
527 // upon destruction of the assembler.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100528 Assembler(Isolate* isolate, void* buffer, int buffer_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000529 ~Assembler();
530
Steve Block44f0eee2011-05-26 01:26:41 +0100531 // Overrides the default provided by FLAG_debug_code.
532 void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
533
Steve Blocka7e24c12009-10-30 11:49:00 +0000534 // GetCode emits any pending (non-emitted) code and fills the descriptor
535 // desc. GetCode() is idempotent; it returns the same result if no other
536 // Assembler functions are invoked in between GetCode() calls.
537 void GetCode(CodeDesc* desc);
538
Steve Block3ce2e202009-11-05 08:53:23 +0000539 // Read/Modify the code target in the relative branch/call instruction at pc.
540 // On the x64 architecture, we use relative jumps with a 32-bit displacement
541 // to jump to other Code objects in the Code space in the heap.
542 // Jumps to C functions are done indirectly through a 64-bit register holding
543 // the absolute address of the target.
544 // These functions convert between absolute Addresses of Code objects and
545 // the relative displacements stored in the code.
Steve Blocka7e24c12009-10-30 11:49:00 +0000546 static inline Address target_address_at(Address pc);
547 static inline void set_target_address_at(Address pc, Address target);
Steve Blockd0582a62009-12-15 09:54:21 +0000548
549 // This sets the branch destination (which is in the instruction on x64).
550 // This is for calls and branches within generated code.
551 inline static void set_target_at(Address instruction_payload,
552 Address target) {
553 set_target_address_at(instruction_payload, target);
554 }
555
556 // This sets the branch destination (which is a load instruction on x64).
557 // This is for calls and branches to runtime code.
558 inline static void set_external_target_at(Address instruction_payload,
559 Address target) {
560 *reinterpret_cast<Address*>(instruction_payload) = target;
561 }
562
Steve Block3ce2e202009-11-05 08:53:23 +0000563 inline Handle<Object> code_target_object_handle_at(Address pc);
Steve Blockd0582a62009-12-15 09:54:21 +0000564 // Number of bytes taken up by the branch target in the code.
565 static const int kCallTargetSize = 4; // Use 32-bit displacement.
566 static const int kExternalTargetSize = 8; // Use 64-bit absolute.
Steve Blocka7e24c12009-10-30 11:49:00 +0000567 // Distance between the address of the code target in the call instruction
Steve Block3ce2e202009-11-05 08:53:23 +0000568 // and the return address pushed on the stack.
569 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
570 // Distance between the start of the JS return sequence and where the
571 // 32-bit displacement of a near call would be, relative to the pushed
572 // return address. TODO: Use return sequence length instead.
573 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
574 static const int kPatchReturnSequenceAddressOffset = 13 - 4;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100575 // Distance between start of patched debug break slot and where the
576 // 32-bit displacement of a near call would be, relative to the pushed
577 // return address. TODO: Use return sequence length instead.
578 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
579 static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
Steve Block3ce2e202009-11-05 08:53:23 +0000580 // TODO(X64): Rename this, removing the "Real", after changing the above.
581 static const int kRealPatchReturnSequenceAddressOffset = 2;
Steve Blockd0582a62009-12-15 09:54:21 +0000582
Steve Block1e0659c2011-05-24 12:43:12 +0100583 // Some x64 JS code is padded with int3 to make it large
584 // enough to hold an instruction when the debugger patches it.
585 static const int kJumpInstructionLength = 13;
Steve Blockd0582a62009-12-15 09:54:21 +0000586 static const int kCallInstructionLength = 13;
587 static const int kJSReturnSequenceLength = 13;
Steve Block1e0659c2011-05-24 12:43:12 +0100588 static const int kShortCallInstructionLength = 5;
Steve Blockd0582a62009-12-15 09:54:21 +0000589
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100590 // The debug break slot must be able to contain a call instruction.
591 static const int kDebugBreakSlotLength = kCallInstructionLength;
592
Steve Block9fac8402011-05-12 15:51:54 +0100593 // One byte opcode for test eax,0xXXXXXXXX.
594 static const byte kTestEaxByte = 0xA9;
Steve Block1e0659c2011-05-24 12:43:12 +0100595 // One byte opcode for test al, 0xXX.
596 static const byte kTestAlByte = 0xA8;
597 // One byte opcode for nop.
598 static const byte kNopByte = 0x90;
599
600 // One byte prefix for a short conditional jump.
601 static const byte kJccShortPrefix = 0x70;
602 static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
603 static const byte kJcShortOpcode = kJccShortPrefix | carry;
604
605
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100606
Steve Blocka7e24c12009-10-30 11:49:00 +0000607 // ---------------------------------------------------------------------------
608 // Code generation
609 //
610 // Function names correspond one-to-one to x64 instruction mnemonics.
611 // Unless specified otherwise, instructions operate on 64-bit operands.
612 //
613 // If we need versions of an assembly instruction that operate on different
614 // width arguments, we add a single-letter suffix specifying the width.
615 // This is done for the following instructions: mov, cmp, inc, dec,
616 // add, sub, and test.
617 // There are no versions of these instructions without the suffix.
618 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
619 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
620 // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
621 // - Instructions on 64-bit (quadword) operands/registers use 'q'.
622 //
623 // Some mnemonics, such as "and", are the same as C++ keywords.
624 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
625
626 // Insert the smallest number of nop instructions
627 // possible to align the pc offset to a multiple
Steve Block1e0659c2011-05-24 12:43:12 +0100628 // of m, where m must be a power of 2.
Steve Blocka7e24c12009-10-30 11:49:00 +0000629 void Align(int m);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100630 // Aligns code to something that's optimal for a jump target for the platform.
631 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000632
633 // Stack
634 void pushfq();
635 void popfq();
636
637 void push(Immediate value);
Steve Block1e0659c2011-05-24 12:43:12 +0100638 // Push a 32 bit integer, and guarantee that it is actually pushed as a
639 // 32 bit value, the normal push will optimize the 8 bit case.
640 void push_imm32(int32_t imm32);
Steve Blocka7e24c12009-10-30 11:49:00 +0000641 void push(Register src);
642 void push(const Operand& src);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000643 void push(Handle<Object> handle);
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
1166
1167 // Calls
1168 // Call near relative 32-bit displacement, relative to next instruction.
1169 void call(Label* L);
Ben Murdoch257744e2011-11-30 15:57:28 +00001170 void call(Handle<Code> target,
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001171 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
Ben Murdoch257744e2011-11-30 15:57:28 +00001172 unsigned ast_id = kNoASTId);
Steve Blocka7e24c12009-10-30 11:49:00 +00001173
Steve Block1e0659c2011-05-24 12:43:12 +01001174 // Calls directly to the given address using a relative offset.
1175 // Should only ever be used in Code objects for calls within the
1176 // same Code object. Should not be used when generating new code (use labels),
1177 // but only when patching existing code.
1178 void call(Address target);
1179
Steve Blocka7e24c12009-10-30 11:49:00 +00001180 // Call near absolute indirect, address in register
1181 void call(Register adr);
1182
1183 // Call near indirect
1184 void call(const Operand& operand);
1185
1186 // Jumps
1187 // Jump short or near relative.
Steve Block3ce2e202009-11-05 08:53:23 +00001188 // Use a 32-bit signed displacement.
Ben Murdoch257744e2011-11-30 15:57:28 +00001189 // Unconditional jump to L
1190 void jmp(Label* L, Label::Distance distance = Label::kFar);
Steve Block3ce2e202009-11-05 08:53:23 +00001191 void jmp(Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001192
1193 // Jump near absolute indirect (r64)
1194 void jmp(Register adr);
1195
1196 // Jump near absolute indirect (m64)
1197 void jmp(const Operand& src);
1198
1199 // Conditional jumps
Ben Murdoch257744e2011-11-30 15:57:28 +00001200 void j(Condition cc,
1201 Label* L,
1202 Label::Distance distance = Label::kFar);
Steve Block3ce2e202009-11-05 08:53:23 +00001203 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001204
1205 // Floating-point operations
1206 void fld(int i);
1207
1208 void fld1();
1209 void fldz();
Steve Block6ded16b2010-05-10 14:33:55 +01001210 void fldpi();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001211 void fldln2();
Steve Blocka7e24c12009-10-30 11:49:00 +00001212
1213 void fld_s(const Operand& adr);
1214 void fld_d(const Operand& adr);
1215
1216 void fstp_s(const Operand& adr);
1217 void fstp_d(const Operand& adr);
Steve Block3ce2e202009-11-05 08:53:23 +00001218 void fstp(int index);
Steve Blocka7e24c12009-10-30 11:49:00 +00001219
1220 void fild_s(const Operand& adr);
1221 void fild_d(const Operand& adr);
1222
1223 void fist_s(const Operand& adr);
1224
1225 void fistp_s(const Operand& adr);
1226 void fistp_d(const Operand& adr);
1227
1228 void fisttp_s(const Operand& adr);
Leon Clarked91b9f72010-01-27 17:25:45 +00001229 void fisttp_d(const Operand& adr);
Steve Blocka7e24c12009-10-30 11:49:00 +00001230
1231 void fabs();
1232 void fchs();
1233
1234 void fadd(int i);
1235 void fsub(int i);
1236 void fmul(int i);
1237 void fdiv(int i);
1238
1239 void fisub_s(const Operand& adr);
1240
1241 void faddp(int i = 1);
1242 void fsubp(int i = 1);
1243 void fsubrp(int i = 1);
1244 void fmulp(int i = 1);
1245 void fdivp(int i = 1);
1246 void fprem();
1247 void fprem1();
1248
1249 void fxch(int i = 1);
1250 void fincstp();
1251 void ffree(int i = 0);
1252
1253 void ftst();
1254 void fucomp(int i);
1255 void fucompp();
Steve Block3ce2e202009-11-05 08:53:23 +00001256 void fucomi(int i);
1257 void fucomip();
1258
Steve Blocka7e24c12009-10-30 11:49:00 +00001259 void fcompp();
1260 void fnstsw_ax();
1261 void fwait();
1262 void fnclex();
1263
1264 void fsin();
1265 void fcos();
Ben Murdochb0fe1622011-05-05 13:52:32 +01001266 void fyl2x();
Steve Blocka7e24c12009-10-30 11:49:00 +00001267
1268 void frndint();
1269
1270 void sahf();
1271
1272 // SSE2 instructions
Steve Block6ded16b2010-05-10 14:33:55 +01001273 void movd(XMMRegister dst, Register src);
1274 void movd(Register dst, XMMRegister src);
1275 void movq(XMMRegister dst, Register src);
1276 void movq(Register dst, XMMRegister src);
Ben Murdoch257744e2011-11-30 15:57:28 +00001277 void movq(XMMRegister dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001278 void extractps(Register dst, XMMRegister src, byte imm8);
1279
Ben Murdoch257744e2011-11-30 15:57:28 +00001280 // Don't use this unless it's important to keep the
1281 // top half of the destination register unchanged.
1282 // Used movaps when moving double values and movq for integer
1283 // values in xmm registers.
Steve Block053d10c2011-06-13 19:13:29 +01001284 void movsd(XMMRegister dst, XMMRegister src);
Ben Murdoch257744e2011-11-30 15:57:28 +00001285
1286 void movsd(const Operand& dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001287 void movsd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001288
Steve Block1e0659c2011-05-24 12:43:12 +01001289 void movdqa(const Operand& dst, XMMRegister src);
1290 void movdqa(XMMRegister dst, const Operand& src);
1291
Ben Murdoch257744e2011-11-30 15:57:28 +00001292 void movapd(XMMRegister dst, XMMRegister src);
1293 void movaps(XMMRegister dst, XMMRegister src);
1294
Steve Block8defd9f2010-07-08 12:39:36 +01001295 void movss(XMMRegister dst, const Operand& src);
1296 void movss(const Operand& dst, XMMRegister src);
1297
Steve Blocka7e24c12009-10-30 11:49:00 +00001298 void cvttss2si(Register dst, const Operand& src);
Steve Block1e0659c2011-05-24 12:43:12 +01001299 void cvttss2si(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001300 void cvttsd2si(Register dst, const Operand& src);
Steve Block1e0659c2011-05-24 12:43:12 +01001301 void cvttsd2si(Register dst, XMMRegister src);
Kristian Monsen25f61362010-05-21 11:50:48 +01001302 void cvttsd2siq(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001303
1304 void cvtlsi2sd(XMMRegister dst, const Operand& src);
1305 void cvtlsi2sd(XMMRegister dst, Register src);
1306 void cvtqsi2sd(XMMRegister dst, const Operand& src);
1307 void cvtqsi2sd(XMMRegister dst, Register src);
1308
Steve Block8defd9f2010-07-08 12:39:36 +01001309 void cvtlsi2ss(XMMRegister dst, Register src);
1310
Steve Block6ded16b2010-05-10 14:33:55 +01001311 void cvtss2sd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001312 void cvtss2sd(XMMRegister dst, const Operand& src);
1313 void cvtsd2ss(XMMRegister dst, XMMRegister src);
1314
1315 void cvtsd2si(Register dst, XMMRegister src);
1316 void cvtsd2siq(Register dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001317
Steve Blocka7e24c12009-10-30 11:49:00 +00001318 void addsd(XMMRegister dst, XMMRegister src);
1319 void subsd(XMMRegister dst, XMMRegister src);
1320 void mulsd(XMMRegister dst, XMMRegister src);
1321 void divsd(XMMRegister dst, XMMRegister src);
1322
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001323 void andpd(XMMRegister dst, XMMRegister src);
1324 void orpd(XMMRegister dst, XMMRegister src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001325 void xorpd(XMMRegister dst, XMMRegister src);
Ben Murdoch257744e2011-11-30 15:57:28 +00001326 void xorps(XMMRegister dst, XMMRegister src);
Steve Block6ded16b2010-05-10 14:33:55 +01001327 void sqrtsd(XMMRegister dst, XMMRegister src);
Andrei Popescu402d9372010-02-26 13:31:12 +00001328
Andrei Popescu402d9372010-02-26 13:31:12 +00001329 void ucomisd(XMMRegister dst, XMMRegister src);
Steve Block8defd9f2010-07-08 12:39:36 +01001330 void ucomisd(XMMRegister dst, const Operand& src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001331
Ben Murdoch257744e2011-11-30 15:57:28 +00001332 enum RoundingMode {
1333 kRoundToNearest = 0x0,
1334 kRoundDown = 0x1,
1335 kRoundUp = 0x2,
1336 kRoundToZero = 0x3
1337 };
1338
1339 void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1340
Steve Block1e0659c2011-05-24 12:43:12 +01001341 void movmskpd(Register dst, XMMRegister src);
1342
Steve Block6ded16b2010-05-10 14:33:55 +01001343 // The first argument is the reg field, the second argument is the r/m field.
Steve Blocka7e24c12009-10-30 11:49:00 +00001344 void emit_sse_operand(XMMRegister dst, XMMRegister src);
1345 void emit_sse_operand(XMMRegister reg, const Operand& adr);
1346 void emit_sse_operand(XMMRegister dst, Register src);
Steve Block6ded16b2010-05-10 14:33:55 +01001347 void emit_sse_operand(Register dst, XMMRegister src);
Steve Blocka7e24c12009-10-30 11:49:00 +00001348
Steve Blocka7e24c12009-10-30 11:49:00 +00001349 // Debugging
1350 void Print();
1351
1352 // Check the code size generated from label to here.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001353 int SizeOfCodeGeneratedSince(Label* label) {
1354 return pc_offset() - label->pos();
1355 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001356
1357 // Mark address of the ExitJSFrame code.
1358 void RecordJSReturn();
1359
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001360 // Mark address of a debug break slot.
1361 void RecordDebugBreakSlot();
1362
Steve Blocka7e24c12009-10-30 11:49:00 +00001363 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001364 // Use --code-comments to enable.
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001365 void RecordComment(const char* msg, bool force = false);
Steve Blocka7e24c12009-10-30 11:49:00 +00001366
Ben Murdochb0fe1622011-05-05 13:52:32 +01001367 // Writes a single word of data in the code stream.
1368 // Used for inline tables, e.g., jump-tables.
Ben Murdochb8e0da22011-05-16 14:20:40 +01001369 void db(uint8_t data);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001370 void dd(uint32_t data);
1371
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001372 int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001373
1374 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001375
1376 // Check if there is less than kGap bytes available in the buffer.
1377 // If this is the case, we need to grow the buffer before emitting
1378 // an instruction or relocation information.
1379 inline bool buffer_overflow() const {
1380 return pc_ >= reloc_info_writer.pos() - kGap;
1381 }
1382
1383 // Get the number of bytes available in the buffer.
Steve Blockd0582a62009-12-15 09:54:21 +00001384 inline int available_space() const {
1385 return static_cast<int>(reloc_info_writer.pos() - pc_);
1386 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001387
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001388 static bool IsNop(Address addr) { return *addr == 0x90; }
1389
Steve Blocka7e24c12009-10-30 11:49:00 +00001390 // Avoid overflows for displacements etc.
1391 static const int kMaximalBufferSize = 512*MB;
1392 static const int kMinimalBufferSize = 4*KB;
1393
Steve Block44f0eee2011-05-26 01:26:41 +01001394 protected:
1395 bool emit_debug_code() const { return emit_debug_code_; }
1396
Steve Blocka7e24c12009-10-30 11:49:00 +00001397 private:
1398 byte* addr_at(int pos) { return buffer_ + pos; }
1399 byte byte_at(int pos) { return buffer_[pos]; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001400 void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
Steve Blocka7e24c12009-10-30 11:49:00 +00001401 uint32_t long_at(int pos) {
1402 return *reinterpret_cast<uint32_t*>(addr_at(pos));
1403 }
1404 void long_at_put(int pos, uint32_t x) {
1405 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1406 }
1407
1408 // code emission
1409 void GrowBuffer();
1410
1411 void emit(byte x) { *pc_++ = x; }
1412 inline void emitl(uint32_t x);
Steve Blocka7e24c12009-10-30 11:49:00 +00001413 inline void emitq(uint64_t x, RelocInfo::Mode rmode);
1414 inline void emitw(uint16_t x);
Ben Murdoch257744e2011-11-30 15:57:28 +00001415 inline void emit_code_target(Handle<Code> target,
1416 RelocInfo::Mode rmode,
1417 unsigned ast_id = kNoASTId);
Steve Blocka7e24c12009-10-30 11:49:00 +00001418 void emit(Immediate x) { emitl(x.value_); }
1419
1420 // Emits a REX prefix that encodes a 64-bit operand size and
1421 // the top bit of both register codes.
1422 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1423 // REX.W is set.
Steve Blocka7e24c12009-10-30 11:49:00 +00001424 inline void emit_rex_64(XMMRegister reg, Register rm_reg);
Steve Block6ded16b2010-05-10 14:33:55 +01001425 inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1426 inline void emit_rex_64(Register reg, Register rm_reg);
Steve Blocka7e24c12009-10-30 11:49:00 +00001427
1428 // Emits a REX prefix that encodes a 64-bit operand size and
1429 // the top bit of the destination, index, and base register codes.
1430 // The high bit of reg is used for REX.R, the high bit of op's base
1431 // register is used for REX.B, and the high bit of op's index register
1432 // is used for REX.X. REX.W is set.
1433 inline void emit_rex_64(Register reg, const Operand& op);
1434 inline void emit_rex_64(XMMRegister reg, const Operand& op);
1435
1436 // Emits a REX prefix that encodes a 64-bit operand size and
1437 // the top bit of the register code.
1438 // The high bit of register is used for REX.B.
1439 // REX.W is set and REX.R and REX.X are clear.
1440 inline void emit_rex_64(Register rm_reg);
1441
1442 // Emits a REX prefix that encodes a 64-bit operand size and
1443 // the top bit of the index and base register codes.
1444 // The high bit of op's base register is used for REX.B, and the high
1445 // bit of op's index register is used for REX.X.
1446 // REX.W is set and REX.R clear.
1447 inline void emit_rex_64(const Operand& op);
1448
1449 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1450 void emit_rex_64() { emit(0x48); }
1451
1452 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1453 // REX.W is clear.
1454 inline void emit_rex_32(Register reg, Register rm_reg);
1455
1456 // The high bit of reg is used for REX.R, the high bit of op's base
1457 // register is used for REX.B, and the high bit of op's index register
1458 // is used for REX.X. REX.W is cleared.
1459 inline void emit_rex_32(Register reg, const Operand& op);
1460
1461 // High bit of rm_reg goes to REX.B.
1462 // REX.W, REX.R and REX.X are clear.
1463 inline void emit_rex_32(Register rm_reg);
1464
1465 // High bit of base goes to REX.B and high bit of index to REX.X.
1466 // REX.W and REX.R are clear.
1467 inline void emit_rex_32(const Operand& op);
1468
1469 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1470 // REX.W is cleared. If no REX bits are set, no byte is emitted.
1471 inline void emit_optional_rex_32(Register reg, Register rm_reg);
1472
1473 // The high bit of reg is used for REX.R, the high bit of op's base
1474 // register is used for REX.B, and the high bit of op's index register
1475 // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
1476 // is emitted.
1477 inline void emit_optional_rex_32(Register reg, const Operand& op);
1478
1479 // As for emit_optional_rex_32(Register, Register), except that
1480 // the registers are XMM registers.
1481 inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1482
1483 // As for emit_optional_rex_32(Register, Register), except that
Steve Block6ded16b2010-05-10 14:33:55 +01001484 // one of the registers is an XMM registers.
Steve Blocka7e24c12009-10-30 11:49:00 +00001485 inline void emit_optional_rex_32(XMMRegister reg, Register base);
1486
Steve Block6ded16b2010-05-10 14:33:55 +01001487 // As for emit_optional_rex_32(Register, Register), except that
1488 // one of the registers is an XMM registers.
1489 inline void emit_optional_rex_32(Register reg, XMMRegister base);
1490
Steve Blocka7e24c12009-10-30 11:49:00 +00001491 // As for emit_optional_rex_32(Register, const Operand&), except that
1492 // the register is an XMM register.
1493 inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1494
1495 // Optionally do as emit_rex_32(Register) if the register number has
1496 // the high bit set.
1497 inline void emit_optional_rex_32(Register rm_reg);
1498
1499 // Optionally do as emit_rex_32(const Operand&) if the operand register
1500 // numbers have a high bit set.
1501 inline void emit_optional_rex_32(const Operand& op);
1502
1503
1504 // Emit the ModR/M byte, and optionally the SIB byte and
1505 // 1- or 4-byte offset for a memory operand. Also encodes
1506 // the second operand of the operation, a register or operation
1507 // subcode, into the reg field of the ModR/M byte.
1508 void emit_operand(Register reg, const Operand& adr) {
1509 emit_operand(reg.low_bits(), adr);
1510 }
1511
1512 // Emit the ModR/M byte, and optionally the SIB byte and
1513 // 1- or 4-byte offset for a memory operand. Also used to encode
1514 // a three-bit opcode extension into the ModR/M byte.
1515 void emit_operand(int rm, const Operand& adr);
1516
1517 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1518 void emit_modrm(Register reg, Register rm_reg) {
1519 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1520 }
1521
1522 // Emit a ModR/M byte with an operation subcode in the reg field and
1523 // a register in the rm_reg field.
1524 void emit_modrm(int code, Register rm_reg) {
1525 ASSERT(is_uint3(code));
1526 emit(0xC0 | code << 3 | rm_reg.low_bits());
1527 }
1528
1529 // Emit the code-object-relative offset of the label's position
1530 inline void emit_code_relative_offset(Label* label);
1531
1532 // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1533 // AND, OR, XOR, or CMP. The encodings of these operations are all
1534 // similar, differing just in the opcode or in the reg field of the
1535 // ModR/M byte.
1536 void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1537 void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1538 void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
1539 void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
1540 void arithmetic_op(byte opcode, Register reg, Register rm_reg);
1541 void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
1542 void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1543 void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
1544 // Operate on a byte in memory or register.
1545 void immediate_arithmetic_op_8(byte subcode,
1546 Register dst,
1547 Immediate src);
1548 void immediate_arithmetic_op_8(byte subcode,
1549 const Operand& dst,
1550 Immediate src);
1551 // Operate on a word in memory or register.
1552 void immediate_arithmetic_op_16(byte subcode,
1553 Register dst,
1554 Immediate src);
1555 void immediate_arithmetic_op_16(byte subcode,
1556 const Operand& dst,
1557 Immediate src);
1558 // Operate on a 32-bit word in memory or register.
1559 void immediate_arithmetic_op_32(byte subcode,
1560 Register dst,
1561 Immediate src);
1562 void immediate_arithmetic_op_32(byte subcode,
1563 const Operand& dst,
1564 Immediate src);
1565
1566 // Emit machine code for a shift operation.
1567 void shift(Register dst, Immediate shift_amount, int subcode);
1568 void shift_32(Register dst, Immediate shift_amount, int subcode);
1569 // Shift dst by cl % 64 bits.
1570 void shift(Register dst, int subcode);
1571 void shift_32(Register dst, int subcode);
1572
1573 void emit_farith(int b1, int b2, int i);
1574
1575 // labels
1576 // void print(Label* L);
1577 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001578
1579 // record reloc info for current pc_
1580 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1581
1582 friend class CodePatcher;
1583 friend class EnsureSpace;
1584 friend class RegExpMacroAssemblerX64;
1585
1586 // Code buffer:
1587 // The buffer into which code and relocation info are generated.
1588 byte* buffer_;
1589 int buffer_size_;
1590 // True if the assembler owns the buffer, false if buffer is external.
1591 bool own_buffer_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001592
1593 // code generation
1594 byte* pc_; // the program counter; moves forward
1595 RelocInfoWriter reloc_info_writer;
1596
Steve Block3ce2e202009-11-05 08:53:23 +00001597 List< Handle<Code> > code_targets_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001598
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001599 PositionsRecorder positions_recorder_;
Steve Block44f0eee2011-05-26 01:26:41 +01001600
1601 bool emit_debug_code_;
1602
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001603 friend class PositionsRecorder;
Steve Blocka7e24c12009-10-30 11:49:00 +00001604};
1605
1606
1607// Helper class that ensures that there is enough space for generating
1608// instructions and relocation information. The constructor makes
1609// sure that there is enough space and (in debug mode) the destructor
1610// checks that we did not generate too much.
1611class EnsureSpace BASE_EMBEDDED {
1612 public:
1613 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1614 if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1615#ifdef DEBUG
1616 space_before_ = assembler_->available_space();
1617#endif
1618 }
1619
1620#ifdef DEBUG
1621 ~EnsureSpace() {
1622 int bytes_generated = space_before_ - assembler_->available_space();
1623 ASSERT(bytes_generated < assembler_->kGap);
1624 }
1625#endif
1626
1627 private:
1628 Assembler* assembler_;
1629#ifdef DEBUG
1630 int space_before_;
1631#endif
1632};
1633
1634} } // namespace v8::internal
1635
1636#endif // V8_X64_ASSEMBLER_X64_H_