blob: aec50c911068e6624d06cb1567ba0a2ee875a512 [file] [log] [blame]
ager@chromium.org9085a012009-05-11 19:22:57 +00001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
ager@chromium.org5ec48922009-05-05 07:25:34 +00004// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
ager@chromium.org9085a012009-05-11 19:22:57 +00008// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
ager@chromium.org5ec48922009-05-05 07:25:34 +000010//
ager@chromium.org9085a012009-05-11 19:22:57 +000011// - 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.
ager@chromium.org5ec48922009-05-05 07:25:34 +000030
ager@chromium.org9085a012009-05-11 19:22:57 +000031// The original source code covered by the above license above has been
32// modified significantly by Google Inc.
yangguo@chromium.org56454712012-02-16 15:33:53 +000033// Copyright 2012 the V8 project authors. All rights reserved.
ager@chromium.org9085a012009-05-11 19:22:57 +000034
35// A lightweight X64 Assembler.
36
37#ifndef V8_X64_ASSEMBLER_X64_H_
38#define V8_X64_ASSEMBLER_X64_H_
39
ager@chromium.orgc4c92722009-11-18 14:12:51 +000040#include "serialize.h"
41
kasperl@chromium.org71affb52009-05-26 05:44:31 +000042namespace v8 {
43namespace internal {
ager@chromium.org9085a012009-05-11 19:22:57 +000044
ager@chromium.orge2902be2009-06-08 12:21:35 +000045// Utility functions
46
47// Test whether a 64-bit value is in a specific range.
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000048inline bool is_uint32(int64_t x) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +000049 static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
50 return static_cast<uint64_t>(x) <= kMaxUInt32;
ager@chromium.orge2902be2009-06-08 12:21:35 +000051}
52
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000053inline bool is_int32(int64_t x) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +000054 static const int64_t kMinInt32 = -V8_INT64_C(0x80000000);
55 return is_uint32(x - kMinInt32);
ager@chromium.orge2902be2009-06-08 12:21:35 +000056}
57
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000058inline bool uint_is_int32(uint64_t x) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +000059 static const uint64_t kMaxInt32 = V8_UINT64_C(0x7fffffff);
60 return x <= kMaxInt32;
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +000061}
62
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +000063inline bool is_uint32(uint64_t x) {
fschneider@chromium.org40b9da32010-06-28 11:29:21 +000064 static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
65 return x <= kMaxUInt32;
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +000066}
67
ager@chromium.org9085a012009-05-11 19:22:57 +000068// 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//
ager@chromium.org9085a012009-05-11 19:22:57 +000089
90struct Register {
kasperl@chromium.orga5551262010-12-07 12:49:48 +000091 // The non-allocatable registers are:
92 // rsp - stack pointer
93 // rbp - frame pointer
94 // rsi - context register
95 // r10 - fixed scratch register
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000096 // r12 - smi constant register
kasperl@chromium.orga5551262010-12-07 12:49:48 +000097 // r13 - root register
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000098 static const int kMaxNumAllocatableRegisters = 10;
99 static int NumAllocatableRegisters() {
100 return kMaxNumAllocatableRegisters;
101 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102 static const int kNumRegisters = 16;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000103
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000104 static int ToAllocationIndex(Register reg) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000105 return kAllocationIndexByRegisterCode[reg.code()];
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000106 }
107
108 static Register FromAllocationIndex(int index) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000109 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000110 Register result = { kRegisterCodeByAllocationIndex[index] };
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000111 return result;
112 }
113
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000114 static const char* AllocationIndexToString(int index) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000115 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000116 const char* const names[] = {
117 "rax",
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000118 "rbx",
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000119 "rdx",
120 "rcx",
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000121 "rdi",
122 "r8",
123 "r9",
124 "r11",
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000125 "r14",
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000126 "r15"
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000127 };
128 return names[index];
129 }
130
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000131 static Register from_code(int code) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000132 Register r = { code };
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000133 return r;
134 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000135 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000136 bool is(Register reg) const { return code_ == reg.code_; }
yangguo@chromium.org56454712012-02-16 15:33:53 +0000137 // rax, rbx, rcx and rdx are byte registers, the rest are not.
138 bool is_byte_register() const { return code_ <= 3; }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000139 int code() const {
ager@chromium.org9085a012009-05-11 19:22:57 +0000140 ASSERT(is_valid());
141 return code_;
142 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000143 int bit() const {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000144 return 1 << code_;
ager@chromium.org9085a012009-05-11 19:22:57 +0000145 }
146
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000147 // Return the high bit of the register code as a 0 or 1. Used often
148 // when constructing the REX prefix byte.
149 int high_bit() const {
150 return code_ >> 3;
151 }
152 // Return the 3 low bits of the register code. Used when encoding registers
153 // in modR/M, SIB, and opcode bytes.
154 int low_bits() const {
155 return code_ & 0x7;
156 }
157
ager@chromium.org5c838252010-02-19 08:53:10 +0000158 // Unfortunately we can't make this private in a struct when initializing
159 // by assignment.
ager@chromium.org9085a012009-05-11 19:22:57 +0000160 int code_;
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000161
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000162 private:
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000163 static const int kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters];
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000164 static const int kAllocationIndexByRegisterCode[kNumRegisters];
ager@chromium.org9085a012009-05-11 19:22:57 +0000165};
166
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000167const int kRegister_rax_Code = 0;
168const int kRegister_rcx_Code = 1;
169const int kRegister_rdx_Code = 2;
170const int kRegister_rbx_Code = 3;
171const int kRegister_rsp_Code = 4;
172const int kRegister_rbp_Code = 5;
173const int kRegister_rsi_Code = 6;
174const int kRegister_rdi_Code = 7;
175const int kRegister_r8_Code = 8;
176const int kRegister_r9_Code = 9;
177const int kRegister_r10_Code = 10;
178const int kRegister_r11_Code = 11;
179const int kRegister_r12_Code = 12;
180const int kRegister_r13_Code = 13;
181const int kRegister_r14_Code = 14;
182const int kRegister_r15_Code = 15;
183const int kRegister_no_reg_Code = -1;
184
185const Register rax = { kRegister_rax_Code };
186const Register rcx = { kRegister_rcx_Code };
187const Register rdx = { kRegister_rdx_Code };
188const Register rbx = { kRegister_rbx_Code };
189const Register rsp = { kRegister_rsp_Code };
190const Register rbp = { kRegister_rbp_Code };
191const Register rsi = { kRegister_rsi_Code };
192const Register rdi = { kRegister_rdi_Code };
193const Register r8 = { kRegister_r8_Code };
194const Register r9 = { kRegister_r9_Code };
195const Register r10 = { kRegister_r10_Code };
196const Register r11 = { kRegister_r11_Code };
197const Register r12 = { kRegister_r12_Code };
198const Register r13 = { kRegister_r13_Code };
199const Register r14 = { kRegister_r14_Code };
200const Register r15 = { kRegister_r15_Code };
201const Register no_reg = { kRegister_no_reg_Code };
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000202
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000203#ifdef _WIN64
204 // Windows calling convention
danno@chromium.org6b0169a2013-04-26 15:48:26 +0000205 const Register arg_reg_1 = { kRegister_rcx_Code };
206 const Register arg_reg_2 = { kRegister_rdx_Code };
207 const Register arg_reg_3 = { kRegister_r8_Code };
208 const Register arg_reg_4 = { kRegister_r9_Code };
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000209#else
210 // AMD64 calling convention
danno@chromium.org6b0169a2013-04-26 15:48:26 +0000211 const Register arg_reg_1 = { kRegister_rdi_Code };
212 const Register arg_reg_2 = { kRegister_rsi_Code };
213 const Register arg_reg_3 = { kRegister_rdx_Code };
214 const Register arg_reg_4 = { kRegister_rcx_Code };
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000215#endif // _WIN64
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000216
ager@chromium.org9085a012009-05-11 19:22:57 +0000217struct XMMRegister {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000218 static const int kMaxNumRegisters = 16;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000219 static const int kMaxNumAllocatableRegisters = 15;
220 static int NumAllocatableRegisters() {
221 return kMaxNumAllocatableRegisters;
222 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000223
224 static int ToAllocationIndex(XMMRegister reg) {
225 ASSERT(reg.code() != 0);
226 return reg.code() - 1;
227 }
228
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000229 static XMMRegister FromAllocationIndex(int index) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000230 ASSERT(0 <= index && index < kMaxNumAllocatableRegisters);
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000231 XMMRegister result = { index + 1 };
232 return result;
233 }
234
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000235 static const char* AllocationIndexToString(int index) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000236 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000237 const char* const names[] = {
238 "xmm1",
239 "xmm2",
240 "xmm3",
241 "xmm4",
242 "xmm5",
243 "xmm6",
244 "xmm7",
245 "xmm8",
246 "xmm9",
247 "xmm10",
248 "xmm11",
249 "xmm12",
250 "xmm13",
251 "xmm14",
252 "xmm15"
253 };
254 return names[index];
255 }
256
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000257 static XMMRegister from_code(int code) {
258 ASSERT(code >= 0);
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000259 ASSERT(code < kMaxNumRegisters);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000260 XMMRegister r = { code };
261 return r;
262 }
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000263 bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; }
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000264 bool is(XMMRegister reg) const { return code_ == reg.code_; }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000265 int code() const {
ager@chromium.org9085a012009-05-11 19:22:57 +0000266 ASSERT(is_valid());
267 return code_;
268 }
269
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000270 // Return the high bit of the register code as a 0 or 1. Used often
271 // when constructing the REX prefix byte.
272 int high_bit() const {
273 return code_ >> 3;
274 }
275 // Return the 3 low bits of the register code. Used when encoding registers
276 // in modR/M, SIB, and opcode bytes.
277 int low_bits() const {
278 return code_ & 0x7;
279 }
280
ager@chromium.org9085a012009-05-11 19:22:57 +0000281 int code_;
282};
283
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +0000284const XMMRegister xmm0 = { 0 };
285const XMMRegister xmm1 = { 1 };
286const XMMRegister xmm2 = { 2 };
287const XMMRegister xmm3 = { 3 };
288const XMMRegister xmm4 = { 4 };
289const XMMRegister xmm5 = { 5 };
290const XMMRegister xmm6 = { 6 };
291const XMMRegister xmm7 = { 7 };
292const XMMRegister xmm8 = { 8 };
293const XMMRegister xmm9 = { 9 };
294const XMMRegister xmm10 = { 10 };
295const XMMRegister xmm11 = { 11 };
296const XMMRegister xmm12 = { 12 };
297const XMMRegister xmm13 = { 13 };
298const XMMRegister xmm14 = { 14 };
299const XMMRegister xmm15 = { 15 };
ager@chromium.org9085a012009-05-11 19:22:57 +0000300
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000301
302typedef XMMRegister DoubleRegister;
303
304
ager@chromium.org9085a012009-05-11 19:22:57 +0000305enum Condition {
306 // any value < 0 is considered no_condition
307 no_condition = -1,
308
309 overflow = 0,
310 no_overflow = 1,
311 below = 2,
312 above_equal = 3,
313 equal = 4,
314 not_equal = 5,
315 below_equal = 6,
316 above = 7,
317 negative = 8,
318 positive = 9,
319 parity_even = 10,
320 parity_odd = 11,
321 less = 12,
322 greater_equal = 13,
323 less_equal = 14,
324 greater = 15,
325
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000326 // Fake conditions that are handled by the
327 // opcodes using them.
328 always = 16,
329 never = 17,
ager@chromium.org9085a012009-05-11 19:22:57 +0000330 // aliases
331 carry = below,
332 not_carry = above_equal,
333 zero = equal,
334 not_zero = not_equal,
335 sign = negative,
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000336 not_sign = positive,
337 last_condition = greater
ager@chromium.org9085a012009-05-11 19:22:57 +0000338};
339
340
341// Returns the equivalent of !cc.
342// Negation of the default no_condition (-1) results in a non-default
343// no_condition value (-2). As long as tests for no_condition check
344// for condition < 0, this will work as expected.
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000345inline Condition NegateCondition(Condition cc) {
346 return static_cast<Condition>(cc ^ 1);
347}
348
ager@chromium.org9085a012009-05-11 19:22:57 +0000349
350// Corresponds to transposing the operands of a comparison.
351inline Condition ReverseCondition(Condition cc) {
352 switch (cc) {
353 case below:
354 return above;
355 case above:
356 return below;
357 case above_equal:
358 return below_equal;
359 case below_equal:
360 return above_equal;
361 case less:
362 return greater;
363 case greater:
364 return less;
365 case greater_equal:
366 return less_equal;
367 case less_equal:
368 return greater_equal;
369 default:
370 return cc;
371 };
372}
373
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000374
ager@chromium.org9085a012009-05-11 19:22:57 +0000375// -----------------------------------------------------------------------------
376// Machine instruction Immediates
377
378class Immediate BASE_EMBEDDED {
379 public:
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000380 explicit Immediate(int32_t value) : value_(value) {}
ager@chromium.org9085a012009-05-11 19:22:57 +0000381
ager@chromium.org9085a012009-05-11 19:22:57 +0000382 private:
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000383 int32_t value_;
ager@chromium.org9085a012009-05-11 19:22:57 +0000384
385 friend class Assembler;
386};
387
388
389// -----------------------------------------------------------------------------
390// Machine instruction Operands
391
392enum ScaleFactor {
ager@chromium.org3e875802009-06-29 08:26:34 +0000393 times_1 = 0,
394 times_2 = 1,
395 times_4 = 2,
396 times_8 = 3,
397 times_int_size = times_4,
398 times_pointer_size = times_8
ager@chromium.org9085a012009-05-11 19:22:57 +0000399};
400
401
402class Operand BASE_EMBEDDED {
403 public:
ager@chromium.org9085a012009-05-11 19:22:57 +0000404 // [base + disp/r]
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000405 Operand(Register base, int32_t disp);
ager@chromium.org9085a012009-05-11 19:22:57 +0000406
407 // [base + index*scale + disp/r]
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000408 Operand(Register base,
409 Register index,
410 ScaleFactor scale,
411 int32_t disp);
ager@chromium.org9085a012009-05-11 19:22:57 +0000412
413 // [index*scale + disp/r]
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000414 Operand(Register index,
415 ScaleFactor scale,
416 int32_t disp);
ager@chromium.org9085a012009-05-11 19:22:57 +0000417
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000418 // Offset from existing memory operand.
419 // Offset is added to existing displacement as 32-bit signed values and
420 // this must not overflow.
421 Operand(const Operand& base, int32_t offset);
422
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000423 // Checks whether either base or index register is the given register.
424 // Does not check the "reg" part of the Operand.
425 bool AddressUsesRegister(Register reg) const;
426
ricow@chromium.orgeb96f4f2011-03-09 13:41:48 +0000427 // Queries related to the size of the generated instruction.
428 // Whether the generated instruction will have a REX prefix.
429 bool requires_rex() const { return rex_ != 0; }
430 // Size of the ModR/M, SIB and displacement parts of the generated
431 // instruction.
432 int operand_size() const { return len_; }
433
ager@chromium.org9085a012009-05-11 19:22:57 +0000434 private:
435 byte rex_;
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000436 byte buf_[6];
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000437 // The number of bytes of buf_ in use.
438 byte len_;
ager@chromium.org9085a012009-05-11 19:22:57 +0000439
ager@chromium.orge2902be2009-06-08 12:21:35 +0000440 // Set the ModR/M byte without an encoded 'reg' register. The
ager@chromium.org9085a012009-05-11 19:22:57 +0000441 // register is encoded later as part of the emit_operand operation.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000442 // set_modrm can be called before or after set_sib and set_disp*.
ager@chromium.org9085a012009-05-11 19:22:57 +0000443 inline void set_modrm(int mod, Register rm);
444
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000445 // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
ager@chromium.org9085a012009-05-11 19:22:57 +0000446 inline void set_sib(ScaleFactor scale, Register index, Register base);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000447
448 // Adds operand displacement fields (offsets added to the memory address).
449 // Needs to be called after set_sib, not before it.
450 inline void set_disp8(int disp);
451 inline void set_disp32(int disp);
ager@chromium.org9085a012009-05-11 19:22:57 +0000452
453 friend class Assembler;
454};
455
ager@chromium.org9085a012009-05-11 19:22:57 +0000456
457// CpuFeatures keeps track of which features are supported by the target CPU.
ulan@chromium.org750145a2013-03-07 15:14:13 +0000458// Supported features must be enabled by a CpuFeatureScope before use.
ager@chromium.org9085a012009-05-11 19:22:57 +0000459// Example:
ulan@chromium.org750145a2013-03-07 15:14:13 +0000460// if (assembler->IsSupported(SSE3)) {
461// CpuFeatureScope fscope(assembler, SSE3);
ager@chromium.org3e875802009-06-29 08:26:34 +0000462// // Generate SSE3 floating point code.
ager@chromium.org9085a012009-05-11 19:22:57 +0000463// } else {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000464// // Generate standard SSE2 floating point code.
ager@chromium.org9085a012009-05-11 19:22:57 +0000465// }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000466class CpuFeatures : public AllStatic {
ager@chromium.org9085a012009-05-11 19:22:57 +0000467 public:
ager@chromium.org9085a012009-05-11 19:22:57 +0000468 // Detect features of the target CPU. Set safe defaults if the serializer
469 // is enabled (snapshots must be portable).
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000470 static void Probe();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000471
ager@chromium.org9085a012009-05-11 19:22:57 +0000472 // Check whether a feature is supported by the target CPU.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000473 static bool IsSupported(CpuFeature f) {
474 ASSERT(initialized_);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000475 if (f == SSE3 && !FLAG_enable_sse3) return false;
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000476 if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000477 if (f == CMOV && !FLAG_enable_cmov) return false;
478 if (f == RDTSC && !FLAG_enable_rdtsc) return false;
479 if (f == SAHF && !FLAG_enable_sahf) return false;
ulan@chromium.org750145a2013-03-07 15:14:13 +0000480 return (supported_ & (static_cast<uint64_t>(1) << f)) != 0;
ager@chromium.org9085a012009-05-11 19:22:57 +0000481 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000482
ulan@chromium.org750145a2013-03-07 15:14:13 +0000483 static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000484 ASSERT(initialized_);
ulan@chromium.org750145a2013-03-07 15:14:13 +0000485 return (found_by_runtime_probing_only_ &
486 (static_cast<uint64_t>(1) << f)) != 0;
ager@chromium.org9085a012009-05-11 19:22:57 +0000487 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000488
ulan@chromium.org750145a2013-03-07 15:14:13 +0000489 static bool IsSafeForSnapshot(CpuFeature f) {
490 return (IsSupported(f) &&
491 (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
492 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000493
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000494 private:
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000495 // Safe defaults include CMOV for X64. It is always available, if
ager@chromium.org3e875802009-06-29 08:26:34 +0000496 // anyone checks, but they shouldn't need to check.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000497 // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
498 // fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000499 static const uint64_t kDefaultCpuFeatures = (1 << CMOV);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000500
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000501#ifdef DEBUG
502 static bool initialized_;
503#endif
504 static uint64_t supported_;
ulan@chromium.org750145a2013-03-07 15:14:13 +0000505 static uint64_t found_by_runtime_probing_only_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000506
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000507 friend class ExternalReference;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000508 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
ager@chromium.org9085a012009-05-11 19:22:57 +0000509};
510
511
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000512class Assembler : public AssemblerBase {
ager@chromium.org9085a012009-05-11 19:22:57 +0000513 private:
ager@chromium.org3e875802009-06-29 08:26:34 +0000514 // We check before assembling an instruction that there is sufficient
515 // space to write an instruction and its relocation information.
516 // The relocation writer's position must be kGap bytes above the end of
ager@chromium.org9085a012009-05-11 19:22:57 +0000517 // the generated instructions. This leaves enough space for the
ager@chromium.org3e875802009-06-29 08:26:34 +0000518 // longest possible x64 instruction, 15 bytes, and the longest possible
519 // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
520 // (There is a 15 byte limit on x64 instruction length that rules out some
521 // otherwise valid instructions.)
522 // This allows for a single, fast space check per instruction.
ager@chromium.org9085a012009-05-11 19:22:57 +0000523 static const int kGap = 32;
524
525 public:
526 // Create an assembler. Instructions and relocation information are emitted
527 // into a buffer, with the instructions starting from the beginning and the
528 // relocation information starting from the end of the buffer. See CodeDesc
529 // for a detailed comment on the layout (globals.h).
530 //
531 // If the provided buffer is NULL, the assembler allocates and grows its own
532 // buffer, and buffer_size determines the initial buffer size. The buffer is
533 // owned by the assembler and deallocated upon destruction of the assembler.
534 //
535 // If the provided buffer is not NULL, the assembler uses the provided buffer
536 // for code generation and assumes its size to be buffer_size. If the buffer
537 // is too small, a fatal error occurs. No deallocation of the buffer is done
538 // upon destruction of the assembler.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000539 Assembler(Isolate* isolate, void* buffer, int buffer_size);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000540 virtual ~Assembler() { }
ager@chromium.org9085a012009-05-11 19:22:57 +0000541
542 // GetCode emits any pending (non-emitted) code and fills the descriptor
543 // desc. GetCode() is idempotent; it returns the same result if no other
544 // Assembler functions are invoked in between GetCode() calls.
545 void GetCode(CodeDesc* desc);
546
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000547 // Read/Modify the code target in the relative branch/call instruction at pc.
548 // On the x64 architecture, we use relative jumps with a 32-bit displacement
549 // to jump to other Code objects in the Code space in the heap.
550 // Jumps to C functions are done indirectly through a 64-bit register holding
551 // the absolute address of the target.
552 // These functions convert between absolute Addresses of Code objects and
553 // the relative displacements stored in the code.
ager@chromium.orge2902be2009-06-08 12:21:35 +0000554 static inline Address target_address_at(Address pc);
555 static inline void set_target_address_at(Address pc, Address target);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000556
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000557 // Return the code target address at a call site from the return address
558 // of that call in the instruction stream.
559 static inline Address target_address_from_return_address(Address pc);
560
ager@chromium.org3811b432009-10-28 14:53:37 +0000561 // This sets the branch destination (which is in the instruction on x64).
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000562 // This is for calls and branches within generated code.
danno@chromium.org88aa0582012-03-23 15:11:57 +0000563 inline static void deserialization_set_special_target_at(
564 Address instruction_payload, Address target) {
ager@chromium.org3811b432009-10-28 14:53:37 +0000565 set_target_address_at(instruction_payload, target);
566 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000567
568 // This sets the branch destination (which is a load instruction on x64).
569 // This is for calls and branches to runtime code.
570 inline static void set_external_target_at(Address instruction_payload,
571 Address target) {
572 *reinterpret_cast<Address*>(instruction_payload) = target;
573 }
574
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000575 inline Handle<Object> code_target_object_handle_at(Address pc);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000576 inline Address runtime_entry_at(Address pc);
ager@chromium.org3811b432009-10-28 14:53:37 +0000577 // Number of bytes taken up by the branch target in the code.
danno@chromium.org88aa0582012-03-23 15:11:57 +0000578 static const int kSpecialTargetSize = 4; // Use 32-bit displacement.
ager@chromium.org9085a012009-05-11 19:22:57 +0000579 // Distance between the address of the code target in the call instruction
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000580 // and the return address pushed on the stack.
581 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
582 // Distance between the start of the JS return sequence and where the
583 // 32-bit displacement of a near call would be, relative to the pushed
584 // return address. TODO: Use return sequence length instead.
585 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
586 static const int kPatchReturnSequenceAddressOffset = 13 - 4;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000587 // Distance between start of patched debug break slot and where the
588 // 32-bit displacement of a near call would be, relative to the pushed
589 // return address. TODO: Use return sequence length instead.
590 // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
591 static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000592 // TODO(X64): Rename this, removing the "Real", after changing the above.
593 static const int kRealPatchReturnSequenceAddressOffset = 2;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000594
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000595 // Some x64 JS code is padded with int3 to make it large
596 // enough to hold an instruction when the debugger patches it.
597 static const int kJumpInstructionLength = 13;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000598 static const int kCallInstructionLength = 13;
599 static const int kJSReturnSequenceLength = 13;
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000600 static const int kShortCallInstructionLength = 5;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000601 static const int kPatchDebugBreakSlotReturnOffset = 4;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000602
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000603 // The debug break slot must be able to contain a call instruction.
604 static const int kDebugBreakSlotLength = kCallInstructionLength;
605
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000606 // One byte opcode for test eax,0xXXXXXXXX.
607 static const byte kTestEaxByte = 0xA9;
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000608 // One byte opcode for test al, 0xXX.
609 static const byte kTestAlByte = 0xA8;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000610 // One byte opcode for nop.
611 static const byte kNopByte = 0x90;
612
613 // One byte prefix for a short conditional jump.
614 static const byte kJccShortPrefix = 0x70;
615 static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
616 static const byte kJcShortOpcode = kJccShortPrefix | carry;
jkummerow@chromium.org212d9642012-05-11 15:02:09 +0000617 static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
618 static const byte kJzShortOpcode = kJccShortPrefix | zero;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000619
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000620
ager@chromium.org9085a012009-05-11 19:22:57 +0000621 // ---------------------------------------------------------------------------
622 // Code generation
623 //
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000624 // Function names correspond one-to-one to x64 instruction mnemonics.
625 // Unless specified otherwise, instructions operate on 64-bit operands.
626 //
627 // If we need versions of an assembly instruction that operate on different
628 // width arguments, we add a single-letter suffix specifying the width.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000629 // This is done for the following instructions: mov, cmp, inc, dec,
630 // add, sub, and test.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000631 // There are no versions of these instructions without the suffix.
632 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
633 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
634 // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
635 // - Instructions on 64-bit (quadword) operands/registers use 'q'.
636 //
637 // Some mnemonics, such as "and", are the same as C++ keywords.
638 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
ager@chromium.org9085a012009-05-11 19:22:57 +0000639
640 // Insert the smallest number of nop instructions
641 // possible to align the pc offset to a multiple
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000642 // of m, where m must be a power of 2.
ager@chromium.org9085a012009-05-11 19:22:57 +0000643 void Align(int m);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000644 void Nop(int bytes = 1);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000645 // Aligns code to something that's optimal for a jump target for the platform.
646 void CodeTargetAlign();
ager@chromium.org9085a012009-05-11 19:22:57 +0000647
648 // Stack
ager@chromium.orge2902be2009-06-08 12:21:35 +0000649 void pushfq();
650 void popfq();
ager@chromium.org9085a012009-05-11 19:22:57 +0000651
ager@chromium.orge2902be2009-06-08 12:21:35 +0000652 void push(Immediate value);
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000653 // Push a 32 bit integer, and guarantee that it is actually pushed as a
654 // 32 bit value, the normal push will optimize the 8 bit case.
655 void push_imm32(int32_t imm32);
ager@chromium.org9085a012009-05-11 19:22:57 +0000656 void push(Register src);
657 void push(const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000658
659 void pop(Register dst);
660 void pop(const Operand& dst);
661
ager@chromium.orge2902be2009-06-08 12:21:35 +0000662 void enter(Immediate size);
ager@chromium.org9085a012009-05-11 19:22:57 +0000663 void leave();
664
665 // Moves
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000666 void movb(Register dst, const Operand& src);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000667 void movb(Register dst, Immediate imm);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000668 void movb(const Operand& dst, Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000669
ager@chromium.org3811b432009-10-28 14:53:37 +0000670 // Move the low 16 bits of a 64-bit register value to a 16-bit
671 // memory location.
672 void movw(const Operand& dst, Register src);
673
ager@chromium.orge2902be2009-06-08 12:21:35 +0000674 void movl(Register dst, Register src);
675 void movl(Register dst, const Operand& src);
676 void movl(const Operand& dst, Register src);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000677 void movl(const Operand& dst, Immediate imm);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000678 // Load a 32-bit immediate value, zero-extended to 64 bits.
679 void movl(Register dst, Immediate imm32);
680
ager@chromium.orge2902be2009-06-08 12:21:35 +0000681 // Move 64 bit register value to 64-bit memory location.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000682 void movq(const Operand& dst, Register src);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000683 // Move 64 bit memory location to 64-bit register value.
684 void movq(Register dst, const Operand& src);
685 void movq(Register dst, Register src);
686 // Sign extends immediate 32-bit value to 64 bits.
687 void movq(Register dst, Immediate x);
688 // Move the offset of the label location relative to the current
689 // position (after the move) to the destination.
690 void movl(const Operand& dst, Label* src);
691
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000692 // Move sign extended immediate to memory location.
693 void movq(const Operand& dst, Immediate value);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000694 // Instructions to load a 64-bit immediate into a register.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000695 // All 64-bit immediates must have a relocation mode.
696 void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
697 void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
698 void movq(Register dst, const char* s, RelocInfo::Mode rmode);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000699 // Moves the address of the external reference into the register.
700 void movq(Register dst, ExternalReference ext);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000701 void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
702
ager@chromium.org3811b432009-10-28 14:53:37 +0000703 void movsxbq(Register dst, const Operand& src);
704 void movsxwq(Register dst, const Operand& src);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000705 void movsxlq(Register dst, Register src);
ager@chromium.org3e875802009-06-29 08:26:34 +0000706 void movsxlq(Register dst, const Operand& src);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000707 void movzxbq(Register dst, const Operand& src);
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000708 void movzxbl(Register dst, const Operand& src);
ager@chromium.org3811b432009-10-28 14:53:37 +0000709 void movzxwq(Register dst, const Operand& src);
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000710 void movzxwl(Register dst, const Operand& src);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000711 void movzxwl(Register dst, Register src);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000712
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000713 // Repeated moves.
714
715 void repmovsb();
716 void repmovsw();
717 void repmovsl();
718 void repmovsq();
719
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000720 // Instruction to load from an immediate 64-bit pointer into RAX.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000721 void load_rax(void* ptr, RelocInfo::Mode rmode);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000722 void load_rax(ExternalReference ext);
ager@chromium.org9085a012009-05-11 19:22:57 +0000723
ager@chromium.org3e875802009-06-29 08:26:34 +0000724 // Conditional moves.
725 void cmovq(Condition cc, Register dst, Register src);
726 void cmovq(Condition cc, Register dst, const Operand& src);
727 void cmovl(Condition cc, Register dst, Register src);
728 void cmovl(Condition cc, Register dst, const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000729
730 // Exchange two registers
731 void xchg(Register dst, Register src);
732
733 // Arithmetics
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000734 void addl(Register dst, Register src) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000735 arithmetic_op_32(0x03, dst, src);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000736 }
737
ager@chromium.org3e875802009-06-29 08:26:34 +0000738 void addl(Register dst, Immediate src) {
739 immediate_arithmetic_op_32(0x0, dst, src);
740 }
741
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000742 void addl(Register dst, const Operand& src) {
743 arithmetic_op_32(0x03, dst, src);
744 }
745
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000746 void addl(const Operand& dst, Immediate src) {
747 immediate_arithmetic_op_32(0x0, dst, src);
748 }
749
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000750 void addl(const Operand& dst, Register src) {
751 arithmetic_op_32(0x01, src, dst);
752 }
753
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000754 void addq(Register dst, Register src) {
755 arithmetic_op(0x03, dst, src);
756 }
757
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000758 void addq(Register dst, const Operand& src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000759 arithmetic_op(0x03, dst, src);
760 }
ager@chromium.org9085a012009-05-11 19:22:57 +0000761
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000762 void addq(const Operand& dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000763 arithmetic_op(0x01, src, dst);
764 }
765
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000766 void addq(Register dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000767 immediate_arithmetic_op(0x0, dst, src);
768 }
769
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000770 void addq(const Operand& dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000771 immediate_arithmetic_op(0x0, dst, src);
772 }
773
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000774 void sbbl(Register dst, Register src) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000775 arithmetic_op_32(0x1b, dst, src);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000776 }
777
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000778 void sbbq(Register dst, Register src) {
779 arithmetic_op(0x1b, dst, src);
780 }
781
ager@chromium.org3e875802009-06-29 08:26:34 +0000782 void cmpb(Register dst, Immediate src) {
783 immediate_arithmetic_op_8(0x7, dst, src);
784 }
785
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000786 void cmpb_al(Immediate src);
787
788 void cmpb(Register dst, Register src) {
789 arithmetic_op(0x3A, dst, src);
790 }
791
792 void cmpb(Register dst, const Operand& src) {
793 arithmetic_op(0x3A, dst, src);
794 }
795
796 void cmpb(const Operand& dst, Register src) {
797 arithmetic_op(0x38, src, dst);
798 }
799
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000800 void cmpb(const Operand& dst, Immediate src) {
801 immediate_arithmetic_op_8(0x7, dst, src);
802 }
803
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000804 void cmpw(const Operand& dst, Immediate src) {
805 immediate_arithmetic_op_16(0x7, dst, src);
806 }
807
808 void cmpw(Register dst, Immediate src) {
809 immediate_arithmetic_op_16(0x7, dst, src);
810 }
811
812 void cmpw(Register dst, const Operand& src) {
813 arithmetic_op_16(0x3B, dst, src);
814 }
815
816 void cmpw(Register dst, Register src) {
817 arithmetic_op_16(0x3B, dst, src);
818 }
819
820 void cmpw(const Operand& dst, Register src) {
821 arithmetic_op_16(0x39, src, dst);
822 }
823
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000824 void cmpl(Register dst, Register src) {
825 arithmetic_op_32(0x3B, dst, src);
826 }
827
828 void cmpl(Register dst, const Operand& src) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000829 arithmetic_op_32(0x3B, dst, src);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000830 }
831
832 void cmpl(const Operand& dst, Register src) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000833 arithmetic_op_32(0x39, src, dst);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000834 }
835
836 void cmpl(Register dst, Immediate src) {
837 immediate_arithmetic_op_32(0x7, dst, src);
838 }
839
840 void cmpl(const Operand& dst, Immediate src) {
841 immediate_arithmetic_op_32(0x7, dst, src);
842 }
843
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000844 void cmpq(Register dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000845 arithmetic_op(0x3B, dst, src);
846 }
847
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000848 void cmpq(Register dst, const Operand& src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000849 arithmetic_op(0x3B, dst, src);
850 }
851
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000852 void cmpq(const Operand& dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000853 arithmetic_op(0x39, src, dst);
854 }
855
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000856 void cmpq(Register dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000857 immediate_arithmetic_op(0x7, dst, src);
858 }
859
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000860 void cmpq(const Operand& dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000861 immediate_arithmetic_op(0x7, dst, src);
862 }
863
864 void and_(Register dst, Register src) {
865 arithmetic_op(0x23, dst, src);
866 }
867
868 void and_(Register dst, const Operand& src) {
869 arithmetic_op(0x23, dst, src);
870 }
871
872 void and_(const Operand& dst, Register src) {
873 arithmetic_op(0x21, src, dst);
874 }
875
876 void and_(Register dst, Immediate src) {
877 immediate_arithmetic_op(0x4, dst, src);
878 }
879
880 void and_(const Operand& dst, Immediate src) {
881 immediate_arithmetic_op(0x4, dst, src);
882 }
ager@chromium.org9085a012009-05-11 19:22:57 +0000883
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000884 void andl(Register dst, Immediate src) {
885 immediate_arithmetic_op_32(0x4, dst, src);
886 }
887
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000888 void andl(Register dst, Register src) {
889 arithmetic_op_32(0x23, dst, src);
890 }
891
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000892 void andl(Register dst, const Operand& src) {
893 arithmetic_op_32(0x23, dst, src);
894 }
895
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000896 void andb(Register dst, Immediate src) {
897 immediate_arithmetic_op_8(0x4, dst, src);
898 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000899
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000900 void decq(Register dst);
901 void decq(const Operand& dst);
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000902 void decl(Register dst);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000903 void decl(const Operand& dst);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000904 void decb(Register dst);
905 void decb(const Operand& dst);
ager@chromium.org9085a012009-05-11 19:22:57 +0000906
ager@chromium.orge2902be2009-06-08 12:21:35 +0000907 // Sign-extends rax into rdx:rax.
908 void cqo();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000909 // Sign-extends eax into edx:eax.
910 void cdq();
ager@chromium.org9085a012009-05-11 19:22:57 +0000911
ager@chromium.orge2902be2009-06-08 12:21:35 +0000912 // Divide rdx:rax by src. Quotient in rax, remainder in rdx.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000913 void idivq(Register src);
914 // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx.
915 void idivl(Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000916
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000917 // Signed multiply instructions.
918 void imul(Register src); // rdx:rax = rax * src.
919 void imul(Register dst, Register src); // dst = dst * src.
920 void imul(Register dst, const Operand& src); // dst = dst * src.
921 void imul(Register dst, Register src, Immediate imm); // dst = src * imm.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000922 // Signed 32-bit multiply instructions.
923 void imull(Register dst, Register src); // dst = dst * src.
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000924 void imull(Register dst, const Operand& src); // dst = dst * src.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000925 void imull(Register dst, Register src, Immediate imm); // dst = src * imm.
ager@chromium.org9085a012009-05-11 19:22:57 +0000926
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000927 void incq(Register dst);
928 void incq(const Operand& dst);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000929 void incl(Register dst);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000930 void incl(const Operand& dst);
ager@chromium.org9085a012009-05-11 19:22:57 +0000931
932 void lea(Register dst, const Operand& src);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000933 void leal(Register dst, const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000934
ager@chromium.orge2902be2009-06-08 12:21:35 +0000935 // Multiply rax by src, put the result in rdx:rax.
ager@chromium.org9085a012009-05-11 19:22:57 +0000936 void mul(Register src);
937
938 void neg(Register dst);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000939 void neg(const Operand& dst);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000940 void negl(Register dst);
ager@chromium.org9085a012009-05-11 19:22:57 +0000941
942 void not_(Register dst);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000943 void not_(const Operand& dst);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000944 void notl(Register dst);
ager@chromium.org9085a012009-05-11 19:22:57 +0000945
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000946 void or_(Register dst, Register src) {
947 arithmetic_op(0x0B, dst, src);
948 }
949
ager@chromium.org4af710e2009-09-15 12:20:11 +0000950 void orl(Register dst, Register src) {
951 arithmetic_op_32(0x0B, dst, src);
952 }
953
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000954 void or_(Register dst, const Operand& src) {
955 arithmetic_op(0x0B, dst, src);
956 }
957
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000958 void orl(Register dst, const Operand& src) {
959 arithmetic_op_32(0x0B, dst, src);
960 }
961
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000962 void or_(const Operand& dst, Register src) {
963 arithmetic_op(0x09, src, dst);
964 }
965
966 void or_(Register dst, Immediate src) {
967 immediate_arithmetic_op(0x1, dst, src);
968 }
969
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000970 void orl(Register dst, Immediate src) {
971 immediate_arithmetic_op_32(0x1, dst, src);
972 }
973
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000974 void or_(const Operand& dst, Immediate src) {
975 immediate_arithmetic_op(0x1, dst, src);
976 }
977
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000978 void orl(const Operand& dst, Immediate src) {
979 immediate_arithmetic_op_32(0x1, dst, src);
980 }
ager@chromium.org9085a012009-05-11 19:22:57 +0000981
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000982
983 void rcl(Register dst, Immediate imm8) {
984 shift(dst, imm8, 0x2);
985 }
986
987 void rol(Register dst, Immediate imm8) {
988 shift(dst, imm8, 0x0);
989 }
990
991 void rcr(Register dst, Immediate imm8) {
992 shift(dst, imm8, 0x3);
993 }
994
995 void ror(Register dst, Immediate imm8) {
996 shift(dst, imm8, 0x1);
997 }
ager@chromium.org9085a012009-05-11 19:22:57 +0000998
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +0000999 void rorl(Register dst, Immediate imm8) {
1000 shift_32(dst, imm8, 0x1);
1001 }
1002
1003 void rorl_cl(Register dst) {
1004 shift_32(dst, 0x1);
1005 }
1006
ager@chromium.orge2902be2009-06-08 12:21:35 +00001007 // Shifts dst:src left by cl bits, affecting only dst.
1008 void shld(Register dst, Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001009
ager@chromium.orge2902be2009-06-08 12:21:35 +00001010 // Shifts src:dst right by cl bits, affecting only dst.
1011 void shrd(Register dst, Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001012
ager@chromium.orge2902be2009-06-08 12:21:35 +00001013 // Shifts dst right, duplicating sign bit, by shift_amount bits.
1014 // Shifting by 1 is handled efficiently.
1015 void sar(Register dst, Immediate shift_amount) {
1016 shift(dst, shift_amount, 0x7);
1017 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001018
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001019 // Shifts dst right, duplicating sign bit, by shift_amount bits.
1020 // Shifting by 1 is handled efficiently.
1021 void sarl(Register dst, Immediate shift_amount) {
1022 shift_32(dst, shift_amount, 0x7);
1023 }
1024
ager@chromium.orge2902be2009-06-08 12:21:35 +00001025 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001026 void sar_cl(Register dst) {
ager@chromium.orge2902be2009-06-08 12:21:35 +00001027 shift(dst, 0x7);
1028 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001029
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001030 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001031 void sarl_cl(Register dst) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001032 shift_32(dst, 0x7);
1033 }
1034
ager@chromium.orge2902be2009-06-08 12:21:35 +00001035 void shl(Register dst, Immediate shift_amount) {
1036 shift(dst, shift_amount, 0x4);
1037 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001038
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001039 void shl_cl(Register dst) {
ager@chromium.orge2902be2009-06-08 12:21:35 +00001040 shift(dst, 0x4);
1041 }
1042
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001043 void shll_cl(Register dst) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001044 shift_32(dst, 0x4);
1045 }
1046
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001047 void shll(Register dst, Immediate shift_amount) {
1048 shift_32(dst, shift_amount, 0x4);
1049 }
1050
ager@chromium.orge2902be2009-06-08 12:21:35 +00001051 void shr(Register dst, Immediate shift_amount) {
1052 shift(dst, shift_amount, 0x5);
1053 }
1054
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001055 void shr_cl(Register dst) {
ager@chromium.orge2902be2009-06-08 12:21:35 +00001056 shift(dst, 0x5);
1057 }
1058
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001059 void shrl_cl(Register dst) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001060 shift_32(dst, 0x5);
1061 }
1062
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001063 void shrl(Register dst, Immediate shift_amount) {
1064 shift_32(dst, shift_amount, 0x5);
1065 }
1066
ager@chromium.orge2902be2009-06-08 12:21:35 +00001067 void store_rax(void* dst, RelocInfo::Mode mode);
1068 void store_rax(ExternalReference ref);
ager@chromium.org9085a012009-05-11 19:22:57 +00001069
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001070 void subq(Register dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001071 arithmetic_op(0x2B, dst, src);
1072 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001073
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001074 void subq(Register dst, const Operand& src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001075 arithmetic_op(0x2B, dst, src);
1076 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001077
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001078 void subq(const Operand& dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001079 arithmetic_op(0x29, src, dst);
1080 }
1081
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001082 void subq(Register dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001083 immediate_arithmetic_op(0x5, dst, src);
1084 }
1085
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001086 void subq(const Operand& dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001087 immediate_arithmetic_op(0x5, dst, src);
1088 }
1089
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001090 void subl(Register dst, Register src) {
1091 arithmetic_op_32(0x2B, dst, src);
1092 }
1093
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001094 void subl(Register dst, const Operand& src) {
1095 arithmetic_op_32(0x2B, dst, src);
1096 }
1097
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001098 void subl(const Operand& dst, Immediate src) {
1099 immediate_arithmetic_op_32(0x5, dst, src);
1100 }
1101
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001102 void subl(Register dst, Immediate src) {
1103 immediate_arithmetic_op_32(0x5, dst, src);
1104 }
1105
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001106 void subb(Register dst, Immediate src) {
1107 immediate_arithmetic_op_8(0x5, dst, src);
1108 }
1109
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001110 void testb(Register dst, Register src);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001111 void testb(Register reg, Immediate mask);
1112 void testb(const Operand& op, Immediate mask);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001113 void testb(const Operand& op, Register reg);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001114 void testl(Register dst, Register src);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001115 void testl(Register reg, Immediate mask);
1116 void testl(const Operand& op, Immediate mask);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001117 void testq(const Operand& op, Register reg);
1118 void testq(Register dst, Register src);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001119 void testq(Register dst, Immediate mask);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001120
1121 void xor_(Register dst, Register src) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001122 if (dst.code() == src.code()) {
1123 arithmetic_op_32(0x33, dst, src);
1124 } else {
1125 arithmetic_op(0x33, dst, src);
1126 }
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001127 }
1128
ager@chromium.org4af710e2009-09-15 12:20:11 +00001129 void xorl(Register dst, Register src) {
1130 arithmetic_op_32(0x33, dst, src);
1131 }
1132
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001133 void xorl(Register dst, const Operand& src) {
1134 arithmetic_op_32(0x33, dst, src);
1135 }
1136
1137 void xorl(Register dst, Immediate src) {
1138 immediate_arithmetic_op_32(0x6, dst, src);
1139 }
1140
1141 void xorl(const Operand& dst, Immediate src) {
1142 immediate_arithmetic_op_32(0x6, dst, src);
1143 }
1144
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001145 void xor_(Register dst, const Operand& src) {
1146 arithmetic_op(0x33, dst, src);
1147 }
1148
1149 void xor_(const Operand& dst, Register src) {
1150 arithmetic_op(0x31, src, dst);
1151 }
1152
1153 void xor_(Register dst, Immediate src) {
1154 immediate_arithmetic_op(0x6, dst, src);
1155 }
1156
1157 void xor_(const Operand& dst, Immediate src) {
1158 immediate_arithmetic_op(0x6, dst, src);
1159 }
1160
ager@chromium.org9085a012009-05-11 19:22:57 +00001161 // Bit operations.
1162 void bt(const Operand& dst, Register src);
1163 void bts(const Operand& dst, Register src);
1164
1165 // Miscellaneous
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001166 void clc();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001167 void cld();
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001168 void cpuid();
ager@chromium.org9085a012009-05-11 19:22:57 +00001169 void hlt();
1170 void int3();
1171 void nop();
1172 void rdtsc();
1173 void ret(int imm16);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001174 void setcc(Condition cc, Register reg);
ager@chromium.org9085a012009-05-11 19:22:57 +00001175
1176 // Label operations & relative jumps (PPUM Appendix D)
1177 //
1178 // Takes a branch opcode (cc) and a label (L) and generates
1179 // either a backward branch or a forward branch and links it
1180 // to the label fixup chain. Usage:
1181 //
1182 // Label L; // unbound label
1183 // j(cc, &L); // forward branch to unbound label
1184 // bind(&L); // bind label to the current pc
1185 // j(cc, &L); // backward branch to bound label
1186 // bind(&L); // illegal: a label may be bound only once
1187 //
1188 // Note: The same Label can be used for forward and backward branches
1189 // but it may be bound only once.
1190
1191 void bind(Label* L); // binds an unbound label L to the current code position
1192
1193 // Calls
ager@chromium.orge2902be2009-06-08 12:21:35 +00001194 // Call near relative 32-bit displacement, relative to next instruction.
ager@chromium.org9085a012009-05-11 19:22:57 +00001195 void call(Label* L);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001196 void call(Address entry, RelocInfo::Mode rmode);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001197 void call(Handle<Code> target,
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001198 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001199 TypeFeedbackId ast_id = TypeFeedbackId::None());
ager@chromium.orge2902be2009-06-08 12:21:35 +00001200
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001201 // Calls directly to the given address using a relative offset.
1202 // Should only ever be used in Code objects for calls within the
1203 // same Code object. Should not be used when generating new code (use labels),
1204 // but only when patching existing code.
1205 void call(Address target);
1206
ager@chromium.orge2902be2009-06-08 12:21:35 +00001207 // Call near absolute indirect, address in register
1208 void call(Register adr);
1209
1210 // Call near indirect
1211 void call(const Operand& operand);
ager@chromium.org9085a012009-05-11 19:22:57 +00001212
1213 // Jumps
ager@chromium.orge2902be2009-06-08 12:21:35 +00001214 // Jump short or near relative.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001215 // Use a 32-bit signed displacement.
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001216 // Unconditional jump to L
1217 void jmp(Label* L, Label::Distance distance = Label::kFar);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001218 void jmp(Address entry, RelocInfo::Mode rmode);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001219 void jmp(Handle<Code> target, RelocInfo::Mode rmode);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001220
1221 // Jump near absolute indirect (r64)
1222 void jmp(Register adr);
ager@chromium.org9085a012009-05-11 19:22:57 +00001223
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001224 // Jump near absolute indirect (m64)
1225 void jmp(const Operand& src);
1226
ager@chromium.org9085a012009-05-11 19:22:57 +00001227 // Conditional jumps
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001228 void j(Condition cc,
1229 Label* L,
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001230 Label::Distance distance = Label::kFar);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001231 void j(Condition cc, Address entry, RelocInfo::Mode rmode);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001232 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
ager@chromium.org9085a012009-05-11 19:22:57 +00001233
1234 // Floating-point operations
1235 void fld(int i);
1236
1237 void fld1();
1238 void fldz();
ager@chromium.orgac091b72010-05-05 07:34:42 +00001239 void fldpi();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001240 void fldln2();
ager@chromium.org9085a012009-05-11 19:22:57 +00001241
1242 void fld_s(const Operand& adr);
1243 void fld_d(const Operand& adr);
1244
1245 void fstp_s(const Operand& adr);
1246 void fstp_d(const Operand& adr);
ager@chromium.org3811b432009-10-28 14:53:37 +00001247 void fstp(int index);
ager@chromium.org9085a012009-05-11 19:22:57 +00001248
1249 void fild_s(const Operand& adr);
1250 void fild_d(const Operand& adr);
1251
1252 void fist_s(const Operand& adr);
1253
1254 void fistp_s(const Operand& adr);
1255 void fistp_d(const Operand& adr);
1256
1257 void fisttp_s(const Operand& adr);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001258 void fisttp_d(const Operand& adr);
ager@chromium.org9085a012009-05-11 19:22:57 +00001259
1260 void fabs();
1261 void fchs();
1262
1263 void fadd(int i);
1264 void fsub(int i);
1265 void fmul(int i);
1266 void fdiv(int i);
1267
1268 void fisub_s(const Operand& adr);
1269
1270 void faddp(int i = 1);
1271 void fsubp(int i = 1);
1272 void fsubrp(int i = 1);
1273 void fmulp(int i = 1);
1274 void fdivp(int i = 1);
1275 void fprem();
1276 void fprem1();
1277
1278 void fxch(int i = 1);
1279 void fincstp();
1280 void ffree(int i = 0);
1281
1282 void ftst();
1283 void fucomp(int i);
1284 void fucompp();
ager@chromium.org3811b432009-10-28 14:53:37 +00001285 void fucomi(int i);
1286 void fucomip();
1287
ager@chromium.org9085a012009-05-11 19:22:57 +00001288 void fcompp();
1289 void fnstsw_ax();
1290 void fwait();
1291 void fnclex();
1292
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001293 void fsin();
1294 void fcos();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001295 void fptan();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001296 void fyl2x();
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001297 void f2xm1();
1298 void fscale();
1299 void fninit();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001300
ager@chromium.org9085a012009-05-11 19:22:57 +00001301 void frndint();
1302
ager@chromium.org3e875802009-06-29 08:26:34 +00001303 void sahf();
1304
1305 // SSE2 instructions
ager@chromium.org357bf652010-04-12 11:30:10 +00001306 void movd(XMMRegister dst, Register src);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001307 void movd(Register dst, XMMRegister src);
1308 void movq(XMMRegister dst, Register src);
1309 void movq(Register dst, XMMRegister src);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001310 void movq(XMMRegister dst, XMMRegister src);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001311 void extractps(Register dst, XMMRegister src, byte imm8);
ager@chromium.org357bf652010-04-12 11:30:10 +00001312
danno@chromium.org160a7b02011-04-18 15:51:38 +00001313 // Don't use this unless it's important to keep the
1314 // top half of the destination register unchanged.
1315 // Used movaps when moving double values and movq for integer
1316 // values in xmm registers.
ager@chromium.org357bf652010-04-12 11:30:10 +00001317 void movsd(XMMRegister dst, XMMRegister src);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001318
1319 void movsd(const Operand& dst, XMMRegister src);
ager@chromium.org357bf652010-04-12 11:30:10 +00001320 void movsd(XMMRegister dst, const Operand& src);
ager@chromium.org3e875802009-06-29 08:26:34 +00001321
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001322 void movdqa(const Operand& dst, XMMRegister src);
1323 void movdqa(XMMRegister dst, const Operand& src);
1324
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001325 void movdqu(const Operand& dst, XMMRegister src);
1326 void movdqu(XMMRegister dst, const Operand& src);
1327
danno@chromium.org160a7b02011-04-18 15:51:38 +00001328 void movapd(XMMRegister dst, XMMRegister src);
1329 void movaps(XMMRegister dst, XMMRegister src);
1330
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001331 void movss(XMMRegister dst, const Operand& src);
1332 void movss(const Operand& dst, XMMRegister src);
1333
ager@chromium.org9085a012009-05-11 19:22:57 +00001334 void cvttss2si(Register dst, const Operand& src);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001335 void cvttss2si(Register dst, XMMRegister src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001336 void cvttsd2si(Register dst, const Operand& src);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001337 void cvttsd2si(Register dst, XMMRegister src);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001338 void cvttsd2siq(Register dst, XMMRegister src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001339
ager@chromium.org3e875802009-06-29 08:26:34 +00001340 void cvtlsi2sd(XMMRegister dst, const Operand& src);
1341 void cvtlsi2sd(XMMRegister dst, Register src);
1342 void cvtqsi2sd(XMMRegister dst, const Operand& src);
1343 void cvtqsi2sd(XMMRegister dst, Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001344
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001345 void cvtlsi2ss(XMMRegister dst, Register src);
1346
ager@chromium.org357bf652010-04-12 11:30:10 +00001347 void cvtss2sd(XMMRegister dst, XMMRegister src);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001348 void cvtss2sd(XMMRegister dst, const Operand& src);
1349 void cvtsd2ss(XMMRegister dst, XMMRegister src);
1350
1351 void cvtsd2si(Register dst, XMMRegister src);
1352 void cvtsd2siq(Register dst, XMMRegister src);
ager@chromium.org357bf652010-04-12 11:30:10 +00001353
ager@chromium.org9085a012009-05-11 19:22:57 +00001354 void addsd(XMMRegister dst, XMMRegister src);
danno@chromium.org1f34ad32012-11-26 14:53:56 +00001355 void addsd(XMMRegister dst, const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001356 void subsd(XMMRegister dst, XMMRegister src);
1357 void mulsd(XMMRegister dst, XMMRegister src);
danno@chromium.org1f34ad32012-11-26 14:53:56 +00001358 void mulsd(XMMRegister dst, const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001359 void divsd(XMMRegister dst, XMMRegister src);
1360
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001361 void andpd(XMMRegister dst, XMMRegister src);
1362 void orpd(XMMRegister dst, XMMRegister src);
ager@chromium.org5c838252010-02-19 08:53:10 +00001363 void xorpd(XMMRegister dst, XMMRegister src);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001364 void xorps(XMMRegister dst, XMMRegister src);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001365 void sqrtsd(XMMRegister dst, XMMRegister src);
ager@chromium.org5c838252010-02-19 08:53:10 +00001366
ager@chromium.org5c838252010-02-19 08:53:10 +00001367 void ucomisd(XMMRegister dst, XMMRegister src);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001368 void ucomisd(XMMRegister dst, const Operand& src);
ager@chromium.org3e875802009-06-29 08:26:34 +00001369
danno@chromium.org160a7b02011-04-18 15:51:38 +00001370 enum RoundingMode {
1371 kRoundToNearest = 0x0,
1372 kRoundDown = 0x1,
1373 kRoundUp = 0x2,
1374 kRoundToZero = 0x3
1375 };
1376
1377 void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1378
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001379 void movmskpd(Register dst, XMMRegister src);
ulan@chromium.org4121f232012-12-27 15:57:11 +00001380 void movmskps(Register dst, XMMRegister src);
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001381
ager@chromium.org357bf652010-04-12 11:30:10 +00001382 // The first argument is the reg field, the second argument is the r/m field.
ager@chromium.org3e875802009-06-29 08:26:34 +00001383 void emit_sse_operand(XMMRegister dst, XMMRegister src);
1384 void emit_sse_operand(XMMRegister reg, const Operand& adr);
1385 void emit_sse_operand(XMMRegister dst, Register src);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001386 void emit_sse_operand(Register dst, XMMRegister src);
ager@chromium.org3e875802009-06-29 08:26:34 +00001387
ager@chromium.org9085a012009-05-11 19:22:57 +00001388 // Debugging
1389 void Print();
1390
1391 // Check the code size generated from label to here.
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001392 int SizeOfCodeGeneratedSince(Label* label) {
1393 return pc_offset() - label->pos();
1394 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001395
1396 // Mark address of the ExitJSFrame code.
1397 void RecordJSReturn();
1398
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001399 // Mark address of a debug break slot.
1400 void RecordDebugBreakSlot();
1401
ager@chromium.org9085a012009-05-11 19:22:57 +00001402 // Record a comment relocation entry that can be used by a disassembler.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001403 // Use --code-comments to enable.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001404 void RecordComment(const char* msg, bool force = false);
ager@chromium.org9085a012009-05-11 19:22:57 +00001405
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001406 // Writes a single word of data in the code stream.
1407 // Used for inline tables, e.g., jump-tables.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001408 void db(uint8_t data);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001409 void dd(uint32_t data);
1410
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001411 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
ager@chromium.org9085a012009-05-11 19:22:57 +00001412
1413 // Check if there is less than kGap bytes available in the buffer.
1414 // If this is the case, we need to grow the buffer before emitting
1415 // an instruction or relocation information.
ager@chromium.org4af710e2009-09-15 12:20:11 +00001416 inline bool buffer_overflow() const {
1417 return pc_ >= reloc_info_writer.pos() - kGap;
1418 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001419
1420 // Get the number of bytes available in the buffer.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001421 inline int available_space() const {
1422 return static_cast<int>(reloc_info_writer.pos() - pc_);
1423 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001424
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001425 static bool IsNop(Address addr);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001426
ager@chromium.org9085a012009-05-11 19:22:57 +00001427 // Avoid overflows for displacements etc.
1428 static const int kMaximalBufferSize = 512*MB;
ager@chromium.org9085a012009-05-11 19:22:57 +00001429
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001430 byte byte_at(int pos) { return buffer_[pos]; }
1431 void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1432
ager@chromium.org9085a012009-05-11 19:22:57 +00001433 private:
1434 byte* addr_at(int pos) { return buffer_ + pos; }
ager@chromium.org9085a012009-05-11 19:22:57 +00001435 uint32_t long_at(int pos) {
1436 return *reinterpret_cast<uint32_t*>(addr_at(pos));
1437 }
1438 void long_at_put(int pos, uint32_t x) {
1439 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1440 }
1441
1442 // code emission
1443 void GrowBuffer();
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001444
1445 void emit(byte x) { *pc_++ = x; }
1446 inline void emitl(uint32_t x);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001447 inline void emitq(uint64_t x, RelocInfo::Mode rmode);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001448 inline void emitw(uint16_t x);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001449 inline void emit_code_target(Handle<Code> target,
1450 RelocInfo::Mode rmode,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001451 TypeFeedbackId ast_id = TypeFeedbackId::None());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001452 inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001453 void emit(Immediate x) { emitl(x.value_); }
ager@chromium.org9085a012009-05-11 19:22:57 +00001454
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001455 // Emits a REX prefix that encodes a 64-bit operand size and
1456 // the top bit of both register codes.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001457 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1458 // REX.W is set.
ager@chromium.org3e875802009-06-29 08:26:34 +00001459 inline void emit_rex_64(XMMRegister reg, Register rm_reg);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001460 inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1461 inline void emit_rex_64(Register reg, Register rm_reg);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001462
1463 // Emits a REX prefix that encodes a 64-bit operand size and
1464 // the top bit of the destination, index, and base register codes.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001465 // The high bit of reg is used for REX.R, the high bit of op's base
1466 // register is used for REX.B, and the high bit of op's index register
1467 // is used for REX.X. REX.W is set.
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001468 inline void emit_rex_64(Register reg, const Operand& op);
ager@chromium.org3e875802009-06-29 08:26:34 +00001469 inline void emit_rex_64(XMMRegister reg, const Operand& op);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001470
1471 // Emits a REX prefix that encodes a 64-bit operand size and
1472 // the top bit of the register code.
1473 // The high bit of register is used for REX.B.
1474 // REX.W is set and REX.R and REX.X are clear.
1475 inline void emit_rex_64(Register rm_reg);
1476
1477 // Emits a REX prefix that encodes a 64-bit operand size and
1478 // the top bit of the index and base register codes.
1479 // The high bit of op's base register is used for REX.B, and the high
1480 // bit of op's index register is used for REX.X.
1481 // REX.W is set and REX.R clear.
1482 inline void emit_rex_64(const Operand& op);
1483
1484 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1485 void emit_rex_64() { emit(0x48); }
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001486
1487 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
ager@chromium.orge2902be2009-06-08 12:21:35 +00001488 // REX.W is clear.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001489 inline void emit_rex_32(Register reg, Register rm_reg);
1490
1491 // The high bit of reg is used for REX.R, the high bit of op's base
1492 // register is used for REX.B, and the high bit of op's index register
1493 // is used for REX.X. REX.W is cleared.
1494 inline void emit_rex_32(Register reg, const Operand& op);
1495
ager@chromium.orge2902be2009-06-08 12:21:35 +00001496 // High bit of rm_reg goes to REX.B.
1497 // REX.W, REX.R and REX.X are clear.
1498 inline void emit_rex_32(Register rm_reg);
1499
1500 // High bit of base goes to REX.B and high bit of index to REX.X.
1501 // REX.W and REX.R are clear.
1502 inline void emit_rex_32(const Operand& op);
1503
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001504 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1505 // REX.W is cleared. If no REX bits are set, no byte is emitted.
1506 inline void emit_optional_rex_32(Register reg, Register rm_reg);
1507
1508 // The high bit of reg is used for REX.R, the high bit of op's base
1509 // register is used for REX.B, and the high bit of op's index register
1510 // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
1511 // is emitted.
1512 inline void emit_optional_rex_32(Register reg, const Operand& op);
1513
ager@chromium.org3e875802009-06-29 08:26:34 +00001514 // As for emit_optional_rex_32(Register, Register), except that
1515 // the registers are XMM registers.
1516 inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1517
1518 // As for emit_optional_rex_32(Register, Register), except that
ager@chromium.orgac091b72010-05-05 07:34:42 +00001519 // one of the registers is an XMM registers.
ager@chromium.org3e875802009-06-29 08:26:34 +00001520 inline void emit_optional_rex_32(XMMRegister reg, Register base);
1521
ager@chromium.orgac091b72010-05-05 07:34:42 +00001522 // As for emit_optional_rex_32(Register, Register), except that
1523 // one of the registers is an XMM registers.
1524 inline void emit_optional_rex_32(Register reg, XMMRegister base);
1525
ager@chromium.org3e875802009-06-29 08:26:34 +00001526 // As for emit_optional_rex_32(Register, const Operand&), except that
1527 // the register is an XMM register.
1528 inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1529
ager@chromium.orge2902be2009-06-08 12:21:35 +00001530 // Optionally do as emit_rex_32(Register) if the register number has
1531 // the high bit set.
1532 inline void emit_optional_rex_32(Register rm_reg);
1533
1534 // Optionally do as emit_rex_32(const Operand&) if the operand register
1535 // numbers have a high bit set.
1536 inline void emit_optional_rex_32(const Operand& op);
1537
1538
1539 // Emit the ModR/M byte, and optionally the SIB byte and
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001540 // 1- or 4-byte offset for a memory operand. Also encodes
1541 // the second operand of the operation, a register or operation
ager@chromium.orge2902be2009-06-08 12:21:35 +00001542 // subcode, into the reg field of the ModR/M byte.
1543 void emit_operand(Register reg, const Operand& adr) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001544 emit_operand(reg.low_bits(), adr);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001545 }
1546
1547 // Emit the ModR/M byte, and optionally the SIB byte and
1548 // 1- or 4-byte offset for a memory operand. Also used to encode
1549 // a three-bit opcode extension into the ModR/M byte.
1550 void emit_operand(int rm, const Operand& adr);
1551
1552 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1553 void emit_modrm(Register reg, Register rm_reg) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001554 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
ager@chromium.orge2902be2009-06-08 12:21:35 +00001555 }
1556
1557 // Emit a ModR/M byte with an operation subcode in the reg field and
1558 // a register in the rm_reg field.
1559 void emit_modrm(int code, Register rm_reg) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001560 ASSERT(is_uint3(code));
1561 emit(0xC0 | code << 3 | rm_reg.low_bits());
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001562 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001563
ager@chromium.org9085a012009-05-11 19:22:57 +00001564 // Emit the code-object-relative offset of the label's position
1565 inline void emit_code_relative_offset(Label* label);
1566
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001567 // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1568 // AND, OR, XOR, or CMP. The encodings of these operations are all
1569 // similar, differing just in the opcode or in the reg field of the
ager@chromium.orge2902be2009-06-08 12:21:35 +00001570 // ModR/M byte.
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001571 void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1572 void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1573 void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001574 void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001575 void arithmetic_op(byte opcode, Register reg, Register rm_reg);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001576 void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001577 void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1578 void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
ager@chromium.org3e875802009-06-29 08:26:34 +00001579 // Operate on a byte in memory or register.
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001580 void immediate_arithmetic_op_8(byte subcode,
ager@chromium.org3e875802009-06-29 08:26:34 +00001581 Register dst,
1582 Immediate src);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001583 void immediate_arithmetic_op_8(byte subcode,
1584 const Operand& dst,
1585 Immediate src);
1586 // Operate on a word in memory or register.
1587 void immediate_arithmetic_op_16(byte subcode,
1588 Register dst,
1589 Immediate src);
1590 void immediate_arithmetic_op_16(byte subcode,
1591 const Operand& dst,
1592 Immediate src);
1593 // Operate on a 32-bit word in memory or register.
1594 void immediate_arithmetic_op_32(byte subcode,
1595 Register dst,
1596 Immediate src);
1597 void immediate_arithmetic_op_32(byte subcode,
1598 const Operand& dst,
1599 Immediate src);
1600
ager@chromium.orge2902be2009-06-08 12:21:35 +00001601 // Emit machine code for a shift operation.
1602 void shift(Register dst, Immediate shift_amount, int subcode);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001603 void shift_32(Register dst, Immediate shift_amount, int subcode);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001604 // Shift dst by cl % 64 bits.
1605 void shift(Register dst, int subcode);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001606 void shift_32(Register dst, int subcode);
ager@chromium.org9085a012009-05-11 19:22:57 +00001607
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001608 void emit_farith(int b1, int b2, int i);
ager@chromium.org9085a012009-05-11 19:22:57 +00001609
1610 // labels
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001611 // void print(Label* L);
ager@chromium.org9085a012009-05-11 19:22:57 +00001612 void bind_to(Label* L, int pos);
ager@chromium.org9085a012009-05-11 19:22:57 +00001613
ager@chromium.org9085a012009-05-11 19:22:57 +00001614 // record reloc info for current pc_
1615 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1616
1617 friend class CodePatcher;
1618 friend class EnsureSpace;
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001619 friend class RegExpMacroAssemblerX64;
ager@chromium.org9085a012009-05-11 19:22:57 +00001620
ager@chromium.org9085a012009-05-11 19:22:57 +00001621 // code generation
ager@chromium.org9085a012009-05-11 19:22:57 +00001622 RelocInfoWriter reloc_info_writer;
1623
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001624 List< Handle<Code> > code_targets_;
ager@chromium.org9085a012009-05-11 19:22:57 +00001625
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001626 PositionsRecorder positions_recorder_;
1627 friend class PositionsRecorder;
ager@chromium.org9085a012009-05-11 19:22:57 +00001628};
1629
1630
1631// Helper class that ensures that there is enough space for generating
1632// instructions and relocation information. The constructor makes
1633// sure that there is enough space and (in debug mode) the destructor
1634// checks that we did not generate too much.
1635class EnsureSpace BASE_EMBEDDED {
1636 public:
1637 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
ager@chromium.org4af710e2009-09-15 12:20:11 +00001638 if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
ager@chromium.org9085a012009-05-11 19:22:57 +00001639#ifdef DEBUG
1640 space_before_ = assembler_->available_space();
1641#endif
1642 }
1643
1644#ifdef DEBUG
1645 ~EnsureSpace() {
1646 int bytes_generated = space_before_ - assembler_->available_space();
1647 ASSERT(bytes_generated < assembler_->kGap);
1648 }
1649#endif
1650
1651 private:
1652 Assembler* assembler_;
1653#ifdef DEBUG
1654 int space_before_;
1655#endif
1656};
1657
1658} } // namespace v8::internal
1659
1660#endif // V8_X64_ASSEMBLER_X64_H_