blob: ac69a240cc1e842ce7de4018469fd237f506f6e8 [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
kasperl@chromium.orga5551262010-12-07 12:49:48 +000094 // r10 - fixed scratch register
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000095 // r12 - smi constant register
kasperl@chromium.orga5551262010-12-07 12:49:48 +000096 // r13 - root register
machenbach@chromium.org935a7792013-11-12 09:05:18 +000097 static const int kMaxNumAllocatableRegisters = 11;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000098 static int NumAllocatableRegisters() {
99 return kMaxNumAllocatableRegisters;
100 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000101 static const int kNumRegisters = 16;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000102
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000103 static int ToAllocationIndex(Register reg) {
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000104 return kAllocationIndexByRegisterCode[reg.code()];
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000105 }
106
107 static Register FromAllocationIndex(int index) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000108 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000109 Register result = { kRegisterCodeByAllocationIndex[index] };
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000110 return result;
111 }
112
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000113 static const char* AllocationIndexToString(int index) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000114 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000115 const char* const names[] = {
116 "rax",
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000117 "rbx",
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000118 "rdx",
119 "rcx",
machenbach@chromium.org935a7792013-11-12 09:05:18 +0000120 "rsi",
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) {
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000474 if (Check(f, cross_compile_)) return true;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000475 ASSERT(initialized_);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000476 if (f == SSE3 && !FLAG_enable_sse3) return false;
jkummerow@chromium.org7a6fc812012-06-27 11:12:38 +0000477 if (f == SSE4_1 && !FLAG_enable_sse4_1) return false;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000478 if (f == CMOV && !FLAG_enable_cmov) return false;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000479 if (f == SAHF && !FLAG_enable_sahf) return false;
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000480 return Check(f, supported_);
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_);
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000485 return Check(f, found_by_runtime_probing_only_);
ager@chromium.org9085a012009-05-11 19:22:57 +0000486 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000487
ulan@chromium.org750145a2013-03-07 15:14:13 +0000488 static bool IsSafeForSnapshot(CpuFeature f) {
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000489 return Check(f, cross_compile_) ||
490 (IsSupported(f) &&
ulan@chromium.org750145a2013-03-07 15:14:13 +0000491 (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
492 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000493
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000494 static bool VerifyCrossCompiling() {
495 return cross_compile_ == 0;
496 }
497
498 static bool VerifyCrossCompiling(CpuFeature f) {
499 uint64_t mask = flag2set(f);
500 return cross_compile_ == 0 ||
501 (cross_compile_ & mask) == mask;
502 }
503
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000504 private:
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000505 static bool Check(CpuFeature f, uint64_t set) {
506 return (set & flag2set(f)) != 0;
507 }
508
509 static uint64_t flag2set(CpuFeature f) {
510 return static_cast<uint64_t>(1) << f;
511 }
512
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000513 // Safe defaults include CMOV for X64. It is always available, if
ager@chromium.org3e875802009-06-29 08:26:34 +0000514 // anyone checks, but they shouldn't need to check.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000515 // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
516 // fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000517 static const uint64_t kDefaultCpuFeatures = (1 << CMOV);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000518
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000519#ifdef DEBUG
520 static bool initialized_;
521#endif
522 static uint64_t supported_;
ulan@chromium.org750145a2013-03-07 15:14:13 +0000523 static uint64_t found_by_runtime_probing_only_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000524
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000525 static uint64_t cross_compile_;
526
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000527 friend class ExternalReference;
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000528 friend class PlatformFeatureScope;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000529 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
ager@chromium.org9085a012009-05-11 19:22:57 +0000530};
531
532
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000533class Assembler : public AssemblerBase {
ager@chromium.org9085a012009-05-11 19:22:57 +0000534 private:
ager@chromium.org3e875802009-06-29 08:26:34 +0000535 // We check before assembling an instruction that there is sufficient
536 // space to write an instruction and its relocation information.
537 // The relocation writer's position must be kGap bytes above the end of
ager@chromium.org9085a012009-05-11 19:22:57 +0000538 // the generated instructions. This leaves enough space for the
ager@chromium.org3e875802009-06-29 08:26:34 +0000539 // longest possible x64 instruction, 15 bytes, and the longest possible
540 // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
541 // (There is a 15 byte limit on x64 instruction length that rules out some
542 // otherwise valid instructions.)
543 // This allows for a single, fast space check per instruction.
ager@chromium.org9085a012009-05-11 19:22:57 +0000544 static const int kGap = 32;
545
546 public:
547 // Create an assembler. Instructions and relocation information are emitted
548 // into a buffer, with the instructions starting from the beginning and the
549 // relocation information starting from the end of the buffer. See CodeDesc
550 // for a detailed comment on the layout (globals.h).
551 //
552 // If the provided buffer is NULL, the assembler allocates and grows its own
553 // buffer, and buffer_size determines the initial buffer size. The buffer is
554 // owned by the assembler and deallocated upon destruction of the assembler.
555 //
556 // If the provided buffer is not NULL, the assembler uses the provided buffer
557 // for code generation and assumes its size to be buffer_size. If the buffer
558 // is too small, a fatal error occurs. No deallocation of the buffer is done
559 // upon destruction of the assembler.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000560 Assembler(Isolate* isolate, void* buffer, int buffer_size);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000561 virtual ~Assembler() { }
ager@chromium.org9085a012009-05-11 19:22:57 +0000562
563 // GetCode emits any pending (non-emitted) code and fills the descriptor
564 // desc. GetCode() is idempotent; it returns the same result if no other
565 // Assembler functions are invoked in between GetCode() calls.
566 void GetCode(CodeDesc* desc);
567
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000568 // Read/Modify the code target in the relative branch/call instruction at pc.
569 // On the x64 architecture, we use relative jumps with a 32-bit displacement
570 // to jump to other Code objects in the Code space in the heap.
571 // Jumps to C functions are done indirectly through a 64-bit register holding
572 // the absolute address of the target.
573 // These functions convert between absolute Addresses of Code objects and
574 // the relative displacements stored in the code.
ager@chromium.orge2902be2009-06-08 12:21:35 +0000575 static inline Address target_address_at(Address pc);
576 static inline void set_target_address_at(Address pc, Address target);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000577
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000578 // Return the code target address at a call site from the return address
579 // of that call in the instruction stream.
580 static inline Address target_address_from_return_address(Address pc);
581
ager@chromium.org3811b432009-10-28 14:53:37 +0000582 // This sets the branch destination (which is in the instruction on x64).
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000583 // This is for calls and branches within generated code.
danno@chromium.org88aa0582012-03-23 15:11:57 +0000584 inline static void deserialization_set_special_target_at(
585 Address instruction_payload, Address target) {
ager@chromium.org3811b432009-10-28 14:53:37 +0000586 set_target_address_at(instruction_payload, target);
587 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000588
589 // This sets the branch destination (which is a load instruction on x64).
590 // This is for calls and branches to runtime code.
591 inline static void set_external_target_at(Address instruction_payload,
592 Address target) {
593 *reinterpret_cast<Address*>(instruction_payload) = target;
594 }
595
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000596 inline Handle<Object> code_target_object_handle_at(Address pc);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000597 inline Address runtime_entry_at(Address pc);
ager@chromium.org3811b432009-10-28 14:53:37 +0000598 // Number of bytes taken up by the branch target in the code.
danno@chromium.org88aa0582012-03-23 15:11:57 +0000599 static const int kSpecialTargetSize = 4; // Use 32-bit displacement.
ager@chromium.org9085a012009-05-11 19:22:57 +0000600 // Distance between the address of the code target in the call instruction
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000601 // and the return address pushed on the stack.
602 static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
danno@chromium.org59400602013-08-13 17:09:37 +0000603 // The length of call(kScratchRegister).
604 static const int kCallScratchRegisterInstructionLength = 3;
605 // The length of call(Immediate32).
danno@chromium.orgabafe3d2013-08-09 20:02:11 +0000606 static const int kShortCallInstructionLength = 5;
danno@chromium.org59400602013-08-13 17:09:37 +0000607 // The length of movq(kScratchRegister, address).
608 static const int kMoveAddressIntoScratchRegisterInstructionLength =
609 2 + kPointerSize;
610 // The length of movq(kScratchRegister, address) and call(kScratchRegister).
611 static const int kCallSequenceLength =
612 kMoveAddressIntoScratchRegisterInstructionLength +
613 kCallScratchRegisterInstructionLength;
danno@chromium.orgabafe3d2013-08-09 20:02:11 +0000614
danno@chromium.org59400602013-08-13 17:09:37 +0000615 // The js return and debug break slot must be able to contain an indirect
616 // call sequence, some x64 JS code is padded with int3 to make it large
617 // enough to hold an instruction when the debugger patches it.
618 static const int kJSReturnSequenceLength = kCallSequenceLength;
619 static const int kDebugBreakSlotLength = kCallSequenceLength;
620 static const int kPatchDebugBreakSlotReturnOffset = kCallTargetAddressOffset;
621 // Distance between the start of the JS return sequence and where the
622 // 32-bit displacement of a short call would be. The short call is from
623 // SetDebugBreakAtIC from debug-x64.cc.
624 static const int kPatchReturnSequenceAddressOffset =
625 kJSReturnSequenceLength - kPatchDebugBreakSlotReturnOffset;
626 // Distance between the start of the JS return sequence and where the
627 // 32-bit displacement of a short call would be. The short call is from
628 // SetDebugBreakAtIC from debug-x64.cc.
629 static const int kPatchDebugBreakSlotAddressOffset =
630 kDebugBreakSlotLength - kPatchDebugBreakSlotReturnOffset;
631 static const int kRealPatchReturnSequenceAddressOffset =
632 kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000633
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000634 // One byte opcode for test eax,0xXXXXXXXX.
635 static const byte kTestEaxByte = 0xA9;
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000636 // One byte opcode for test al, 0xXX.
637 static const byte kTestAlByte = 0xA8;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000638 // One byte opcode for nop.
639 static const byte kNopByte = 0x90;
640
641 // One byte prefix for a short conditional jump.
642 static const byte kJccShortPrefix = 0x70;
643 static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
644 static const byte kJcShortOpcode = kJccShortPrefix | carry;
jkummerow@chromium.org212d9642012-05-11 15:02:09 +0000645 static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
646 static const byte kJzShortOpcode = kJccShortPrefix | zero;
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000647
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000648
ager@chromium.org9085a012009-05-11 19:22:57 +0000649 // ---------------------------------------------------------------------------
650 // Code generation
651 //
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000652 // Function names correspond one-to-one to x64 instruction mnemonics.
653 // Unless specified otherwise, instructions operate on 64-bit operands.
654 //
655 // If we need versions of an assembly instruction that operate on different
656 // width arguments, we add a single-letter suffix specifying the width.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000657 // This is done for the following instructions: mov, cmp, inc, dec,
658 // add, sub, and test.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000659 // There are no versions of these instructions without the suffix.
660 // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
661 // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
662 // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
663 // - Instructions on 64-bit (quadword) operands/registers use 'q'.
664 //
665 // Some mnemonics, such as "and", are the same as C++ keywords.
666 // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
ager@chromium.org9085a012009-05-11 19:22:57 +0000667
668 // Insert the smallest number of nop instructions
669 // possible to align the pc offset to a multiple
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000670 // of m, where m must be a power of 2.
ager@chromium.org9085a012009-05-11 19:22:57 +0000671 void Align(int m);
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000672 void Nop(int bytes = 1);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000673 // Aligns code to something that's optimal for a jump target for the platform.
674 void CodeTargetAlign();
ager@chromium.org9085a012009-05-11 19:22:57 +0000675
676 // Stack
ager@chromium.orge2902be2009-06-08 12:21:35 +0000677 void pushfq();
678 void popfq();
ager@chromium.org9085a012009-05-11 19:22:57 +0000679
ager@chromium.orge2902be2009-06-08 12:21:35 +0000680 void push(Immediate value);
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000681 // Push a 32 bit integer, and guarantee that it is actually pushed as a
682 // 32 bit value, the normal push will optimize the 8 bit case.
683 void push_imm32(int32_t imm32);
ager@chromium.org9085a012009-05-11 19:22:57 +0000684 void push(Register src);
685 void push(const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000686
687 void pop(Register dst);
688 void pop(const Operand& dst);
689
ager@chromium.orge2902be2009-06-08 12:21:35 +0000690 void enter(Immediate size);
ager@chromium.org9085a012009-05-11 19:22:57 +0000691 void leave();
692
693 // Moves
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000694 void movb(Register dst, const Operand& src);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000695 void movb(Register dst, Immediate imm);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000696 void movb(const Operand& dst, Register src);
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000697 void movb(const Operand& dst, Immediate imm);
ager@chromium.org9085a012009-05-11 19:22:57 +0000698
ager@chromium.org3811b432009-10-28 14:53:37 +0000699 // Move the low 16 bits of a 64-bit register value to a 16-bit
700 // memory location.
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000701 void movw(Register dst, const Operand& src);
ager@chromium.org3811b432009-10-28 14:53:37 +0000702 void movw(const Operand& dst, Register src);
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000703 void movw(const Operand& dst, Immediate imm);
ager@chromium.org3811b432009-10-28 14:53:37 +0000704
ager@chromium.orge2902be2009-06-08 12:21:35 +0000705 void movl(Register dst, Register src);
706 void movl(Register dst, const Operand& src);
707 void movl(const Operand& dst, Register src);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000708 void movl(const Operand& dst, Immediate imm);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000709 // Load a 32-bit immediate value, zero-extended to 64 bits.
710 void movl(Register dst, Immediate imm32);
711
ager@chromium.orge2902be2009-06-08 12:21:35 +0000712 // Move 64 bit register value to 64-bit memory location.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000713 void movq(const Operand& dst, Register src);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000714 // Move 64 bit memory location to 64-bit register value.
715 void movq(Register dst, const Operand& src);
716 void movq(Register dst, Register src);
717 // Sign extends immediate 32-bit value to 64 bits.
718 void movq(Register dst, Immediate x);
719 // Move the offset of the label location relative to the current
720 // position (after the move) to the destination.
721 void movl(const Operand& dst, Label* src);
722
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000723 // Move sign extended immediate to memory location.
724 void movq(const Operand& dst, Immediate value);
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000725 // Loads a pointer into a register with a relocation mode.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000726 void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
machenbach@chromium.orge8412be2013-11-08 10:23:52 +0000727 // Loads a 64-bit immediate into a register.
728 void movq(Register dst, int64_t value);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000729 void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
730
ager@chromium.org3811b432009-10-28 14:53:37 +0000731 void movsxbq(Register dst, const Operand& src);
732 void movsxwq(Register dst, const Operand& src);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000733 void movsxlq(Register dst, Register src);
ager@chromium.org3e875802009-06-29 08:26:34 +0000734 void movsxlq(Register dst, const Operand& src);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000735 void movzxbq(Register dst, const Operand& src);
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000736 void movzxbl(Register dst, const Operand& src);
ager@chromium.org3811b432009-10-28 14:53:37 +0000737 void movzxwq(Register dst, const Operand& src);
christian.plesner.hansen@gmail.com5a6af922009-08-12 14:20:51 +0000738 void movzxwl(Register dst, const Operand& src);
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000739 void movzxwl(Register dst, Register src);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000740
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000741 // Repeated moves.
742
743 void repmovsb();
744 void repmovsw();
745 void repmovsl();
746 void repmovsq();
747
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000748 // Instruction to load from an immediate 64-bit pointer into RAX.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000749 void load_rax(void* ptr, RelocInfo::Mode rmode);
ager@chromium.orge2902be2009-06-08 12:21:35 +0000750 void load_rax(ExternalReference ext);
ager@chromium.org9085a012009-05-11 19:22:57 +0000751
ager@chromium.org3e875802009-06-29 08:26:34 +0000752 // Conditional moves.
753 void cmovq(Condition cc, Register dst, Register src);
754 void cmovq(Condition cc, Register dst, const Operand& src);
755 void cmovl(Condition cc, Register dst, Register src);
756 void cmovl(Condition cc, Register dst, const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000757
758 // Exchange two registers
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +0000759 void xchgq(Register dst, Register src);
760 void xchgl(Register dst, Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000761
762 // Arithmetics
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000763 void addl(Register dst, Register src) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000764 arithmetic_op_32(0x03, dst, src);
ager@chromium.org5aa501c2009-06-23 07:57:28 +0000765 }
766
ager@chromium.org3e875802009-06-29 08:26:34 +0000767 void addl(Register dst, Immediate src) {
768 immediate_arithmetic_op_32(0x0, dst, src);
769 }
770
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000771 void addl(Register dst, const Operand& src) {
772 arithmetic_op_32(0x03, dst, src);
773 }
774
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000775 void addl(const Operand& dst, Immediate src) {
776 immediate_arithmetic_op_32(0x0, dst, src);
777 }
778
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000779 void addl(const Operand& dst, Register src) {
780 arithmetic_op_32(0x01, src, dst);
781 }
782
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000783 void addq(Register dst, Register src) {
784 arithmetic_op(0x03, dst, src);
785 }
786
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000787 void addq(Register dst, const Operand& src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000788 arithmetic_op(0x03, dst, src);
789 }
ager@chromium.org9085a012009-05-11 19:22:57 +0000790
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000791 void addq(const Operand& dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000792 arithmetic_op(0x01, src, dst);
793 }
794
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000795 void addq(Register dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000796 immediate_arithmetic_op(0x0, dst, src);
797 }
798
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000799 void addq(const Operand& dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000800 immediate_arithmetic_op(0x0, dst, src);
801 }
802
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000803 void sbbl(Register dst, Register src) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000804 arithmetic_op_32(0x1b, dst, src);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000805 }
806
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000807 void sbbq(Register dst, Register src) {
808 arithmetic_op(0x1b, dst, src);
809 }
810
ager@chromium.org3e875802009-06-29 08:26:34 +0000811 void cmpb(Register dst, Immediate src) {
812 immediate_arithmetic_op_8(0x7, dst, src);
813 }
814
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000815 void cmpb_al(Immediate src);
816
817 void cmpb(Register dst, Register src) {
818 arithmetic_op(0x3A, dst, src);
819 }
820
821 void cmpb(Register dst, const Operand& src) {
822 arithmetic_op(0x3A, dst, src);
823 }
824
825 void cmpb(const Operand& dst, Register src) {
826 arithmetic_op(0x38, src, dst);
827 }
828
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000829 void cmpb(const Operand& dst, Immediate src) {
830 immediate_arithmetic_op_8(0x7, dst, src);
831 }
832
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000833 void cmpw(const Operand& dst, Immediate src) {
834 immediate_arithmetic_op_16(0x7, dst, src);
835 }
836
837 void cmpw(Register dst, Immediate src) {
838 immediate_arithmetic_op_16(0x7, dst, src);
839 }
840
841 void cmpw(Register dst, const Operand& src) {
842 arithmetic_op_16(0x3B, dst, src);
843 }
844
845 void cmpw(Register dst, Register src) {
846 arithmetic_op_16(0x3B, dst, src);
847 }
848
849 void cmpw(const Operand& dst, Register src) {
850 arithmetic_op_16(0x39, src, dst);
851 }
852
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000853 void cmpl(Register dst, Register src) {
854 arithmetic_op_32(0x3B, dst, src);
855 }
856
857 void cmpl(Register dst, const Operand& src) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000858 arithmetic_op_32(0x3B, dst, src);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000859 }
860
861 void cmpl(const Operand& dst, Register src) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000862 arithmetic_op_32(0x39, src, dst);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000863 }
864
865 void cmpl(Register dst, Immediate src) {
866 immediate_arithmetic_op_32(0x7, dst, src);
867 }
868
869 void cmpl(const Operand& dst, Immediate src) {
870 immediate_arithmetic_op_32(0x7, dst, src);
871 }
872
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000873 void cmpq(Register dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000874 arithmetic_op(0x3B, dst, src);
875 }
876
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000877 void cmpq(Register dst, const Operand& src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000878 arithmetic_op(0x3B, dst, src);
879 }
880
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000881 void cmpq(const Operand& dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000882 arithmetic_op(0x39, src, dst);
883 }
884
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000885 void cmpq(Register dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000886 immediate_arithmetic_op(0x7, dst, src);
887 }
888
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000889 void cmpq(const Operand& dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000890 immediate_arithmetic_op(0x7, dst, src);
891 }
892
893 void and_(Register dst, Register src) {
894 arithmetic_op(0x23, dst, src);
895 }
896
897 void and_(Register dst, const Operand& src) {
898 arithmetic_op(0x23, dst, src);
899 }
900
901 void and_(const Operand& dst, Register src) {
902 arithmetic_op(0x21, src, dst);
903 }
904
905 void and_(Register dst, Immediate src) {
906 immediate_arithmetic_op(0x4, dst, src);
907 }
908
909 void and_(const Operand& dst, Immediate src) {
910 immediate_arithmetic_op(0x4, dst, src);
911 }
ager@chromium.org9085a012009-05-11 19:22:57 +0000912
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000913 void andl(Register dst, Immediate src) {
914 immediate_arithmetic_op_32(0x4, dst, src);
915 }
916
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000917 void andl(Register dst, Register src) {
918 arithmetic_op_32(0x23, dst, src);
919 }
920
ager@chromium.org0ee099b2011-01-25 14:06:47 +0000921 void andl(Register dst, const Operand& src) {
922 arithmetic_op_32(0x23, dst, src);
923 }
924
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000925 void andb(Register dst, Immediate src) {
926 immediate_arithmetic_op_8(0x4, dst, src);
927 }
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000928
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000929 void decq(Register dst);
930 void decq(const Operand& dst);
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000931 void decl(Register dst);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000932 void decl(const Operand& dst);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000933 void decb(Register dst);
934 void decb(const Operand& dst);
ager@chromium.org9085a012009-05-11 19:22:57 +0000935
ager@chromium.orge2902be2009-06-08 12:21:35 +0000936 // Sign-extends rax into rdx:rax.
937 void cqo();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000938 // Sign-extends eax into edx:eax.
939 void cdq();
ager@chromium.org9085a012009-05-11 19:22:57 +0000940
ager@chromium.orge2902be2009-06-08 12:21:35 +0000941 // Divide rdx:rax by src. Quotient in rax, remainder in rdx.
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000942 void idivq(Register src);
943 // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx.
944 void idivl(Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000945
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000946 // Signed multiply instructions.
947 void imul(Register src); // rdx:rax = rax * src.
948 void imul(Register dst, Register src); // dst = dst * src.
949 void imul(Register dst, const Operand& src); // dst = dst * src.
950 void imul(Register dst, Register src, Immediate imm); // dst = src * imm.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000951 // Signed 32-bit multiply instructions.
952 void imull(Register dst, Register src); // dst = dst * src.
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000953 void imull(Register dst, const Operand& src); // dst = dst * src.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000954 void imull(Register dst, Register src, Immediate imm); // dst = src * imm.
ager@chromium.org9085a012009-05-11 19:22:57 +0000955
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000956 void incq(Register dst);
957 void incq(const Operand& dst);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000958 void incl(Register dst);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000959 void incl(const Operand& dst);
ager@chromium.org9085a012009-05-11 19:22:57 +0000960
961 void lea(Register dst, const Operand& src);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000962 void leal(Register dst, const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +0000963
ager@chromium.orge2902be2009-06-08 12:21:35 +0000964 // Multiply rax by src, put the result in rdx:rax.
ager@chromium.org9085a012009-05-11 19:22:57 +0000965 void mul(Register src);
966
967 void neg(Register dst);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000968 void neg(const Operand& dst);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000969 void negl(Register dst);
ager@chromium.org9085a012009-05-11 19:22:57 +0000970
971 void not_(Register dst);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000972 void not_(const Operand& dst);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000973 void notl(Register dst);
ager@chromium.org9085a012009-05-11 19:22:57 +0000974
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000975 void or_(Register dst, Register src) {
976 arithmetic_op(0x0B, dst, src);
977 }
978
ager@chromium.org4af710e2009-09-15 12:20:11 +0000979 void orl(Register dst, Register src) {
980 arithmetic_op_32(0x0B, dst, src);
981 }
982
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000983 void or_(Register dst, const Operand& src) {
984 arithmetic_op(0x0B, dst, src);
985 }
986
ricow@chromium.org83aa5492011-02-07 12:42:56 +0000987 void orl(Register dst, const Operand& src) {
988 arithmetic_op_32(0x0B, dst, src);
989 }
990
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000991 void or_(const Operand& dst, Register src) {
992 arithmetic_op(0x09, src, dst);
993 }
994
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +0000995 void orl(const Operand& dst, Register src) {
996 arithmetic_op_32(0x09, src, dst);
997 }
998
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +0000999 void or_(Register dst, Immediate src) {
1000 immediate_arithmetic_op(0x1, dst, src);
1001 }
1002
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001003 void orl(Register dst, Immediate src) {
1004 immediate_arithmetic_op_32(0x1, dst, src);
1005 }
1006
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001007 void or_(const Operand& dst, Immediate src) {
1008 immediate_arithmetic_op(0x1, dst, src);
1009 }
1010
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001011 void orl(const Operand& dst, Immediate src) {
1012 immediate_arithmetic_op_32(0x1, dst, src);
1013 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001014
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001015
1016 void rcl(Register dst, Immediate imm8) {
1017 shift(dst, imm8, 0x2);
1018 }
1019
1020 void rol(Register dst, Immediate imm8) {
1021 shift(dst, imm8, 0x0);
1022 }
1023
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +00001024 void roll(Register dst, Immediate imm8) {
1025 shift_32(dst, imm8, 0x0);
1026 }
1027
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001028 void rcr(Register dst, Immediate imm8) {
1029 shift(dst, imm8, 0x3);
1030 }
1031
1032 void ror(Register dst, Immediate imm8) {
1033 shift(dst, imm8, 0x1);
1034 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001035
verwaest@chromium.orge4ee6de2012-11-06 12:13:00 +00001036 void rorl(Register dst, Immediate imm8) {
1037 shift_32(dst, imm8, 0x1);
1038 }
1039
1040 void rorl_cl(Register dst) {
1041 shift_32(dst, 0x1);
1042 }
1043
ager@chromium.orge2902be2009-06-08 12:21:35 +00001044 // Shifts dst:src left by cl bits, affecting only dst.
1045 void shld(Register dst, Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001046
ager@chromium.orge2902be2009-06-08 12:21:35 +00001047 // Shifts src:dst right by cl bits, affecting only dst.
1048 void shrd(Register dst, Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001049
ager@chromium.orge2902be2009-06-08 12:21:35 +00001050 // Shifts dst right, duplicating sign bit, by shift_amount bits.
1051 // Shifting by 1 is handled efficiently.
1052 void sar(Register dst, Immediate shift_amount) {
1053 shift(dst, shift_amount, 0x7);
1054 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001055
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001056 // Shifts dst right, duplicating sign bit, by shift_amount bits.
1057 // Shifting by 1 is handled efficiently.
1058 void sarl(Register dst, Immediate shift_amount) {
1059 shift_32(dst, shift_amount, 0x7);
1060 }
1061
ager@chromium.orge2902be2009-06-08 12:21:35 +00001062 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001063 void sar_cl(Register dst) {
ager@chromium.orge2902be2009-06-08 12:21:35 +00001064 shift(dst, 0x7);
1065 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001066
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001067 // Shifts dst right, duplicating sign bit, by cl % 64 bits.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001068 void sarl_cl(Register dst) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001069 shift_32(dst, 0x7);
1070 }
1071
ager@chromium.orge2902be2009-06-08 12:21:35 +00001072 void shl(Register dst, Immediate shift_amount) {
1073 shift(dst, shift_amount, 0x4);
1074 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001075
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001076 void shl_cl(Register dst) {
ager@chromium.orge2902be2009-06-08 12:21:35 +00001077 shift(dst, 0x4);
1078 }
1079
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001080 void shll_cl(Register dst) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001081 shift_32(dst, 0x4);
1082 }
1083
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001084 void shll(Register dst, Immediate shift_amount) {
1085 shift_32(dst, shift_amount, 0x4);
1086 }
1087
ager@chromium.orge2902be2009-06-08 12:21:35 +00001088 void shr(Register dst, Immediate shift_amount) {
1089 shift(dst, shift_amount, 0x5);
1090 }
1091
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001092 void shr_cl(Register dst) {
ager@chromium.orge2902be2009-06-08 12:21:35 +00001093 shift(dst, 0x5);
1094 }
1095
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001096 void shrl_cl(Register dst) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001097 shift_32(dst, 0x5);
1098 }
1099
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001100 void shrl(Register dst, Immediate shift_amount) {
1101 shift_32(dst, shift_amount, 0x5);
1102 }
1103
ager@chromium.orge2902be2009-06-08 12:21:35 +00001104 void store_rax(void* dst, RelocInfo::Mode mode);
1105 void store_rax(ExternalReference ref);
ager@chromium.org9085a012009-05-11 19:22:57 +00001106
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001107 void subq(Register dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001108 arithmetic_op(0x2B, dst, src);
1109 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001110
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001111 void subq(Register dst, const Operand& src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001112 arithmetic_op(0x2B, dst, src);
1113 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001114
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001115 void subq(const Operand& dst, Register src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001116 arithmetic_op(0x29, src, dst);
1117 }
1118
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001119 void subq(Register dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001120 immediate_arithmetic_op(0x5, dst, src);
1121 }
1122
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001123 void subq(const Operand& dst, Immediate src) {
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001124 immediate_arithmetic_op(0x5, dst, src);
1125 }
1126
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001127 void subl(Register dst, Register src) {
1128 arithmetic_op_32(0x2B, dst, src);
1129 }
1130
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001131 void subl(Register dst, const Operand& src) {
1132 arithmetic_op_32(0x2B, dst, src);
1133 }
1134
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +00001135 void subl(const Operand& dst, Register src) {
1136 arithmetic_op_32(0x29, src, dst);
1137 }
1138
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001139 void subl(const Operand& dst, Immediate src) {
1140 immediate_arithmetic_op_32(0x5, dst, src);
1141 }
1142
kasperl@chromium.org86f77b72009-07-06 08:21:57 +00001143 void subl(Register dst, Immediate src) {
1144 immediate_arithmetic_op_32(0x5, dst, src);
1145 }
1146
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001147 void subb(Register dst, Immediate src) {
1148 immediate_arithmetic_op_8(0x5, dst, src);
1149 }
1150
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001151 void testb(Register dst, Register src);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001152 void testb(Register reg, Immediate mask);
1153 void testb(const Operand& op, Immediate mask);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001154 void testb(const Operand& op, Register reg);
kasperl@chromium.org68ac0092009-07-09 06:00:35 +00001155 void testl(Register dst, Register src);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001156 void testl(Register reg, Immediate mask);
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +00001157 void testl(const Operand& op, Register reg);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001158 void testl(const Operand& op, Immediate mask);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001159 void testq(const Operand& op, Register reg);
1160 void testq(Register dst, Register src);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001161 void testq(Register dst, Immediate mask);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001162
1163 void xor_(Register dst, Register src) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001164 if (dst.code() == src.code()) {
1165 arithmetic_op_32(0x33, dst, src);
1166 } else {
1167 arithmetic_op(0x33, dst, src);
1168 }
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001169 }
1170
ager@chromium.org4af710e2009-09-15 12:20:11 +00001171 void xorl(Register dst, Register src) {
1172 arithmetic_op_32(0x33, dst, src);
1173 }
1174
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001175 void xorl(Register dst, const Operand& src) {
1176 arithmetic_op_32(0x33, dst, src);
1177 }
1178
1179 void xorl(Register dst, Immediate src) {
1180 immediate_arithmetic_op_32(0x6, dst, src);
1181 }
1182
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +00001183 void xorl(const Operand& dst, Register src) {
1184 arithmetic_op_32(0x31, src, dst);
1185 }
1186
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001187 void xorl(const Operand& dst, Immediate src) {
1188 immediate_arithmetic_op_32(0x6, dst, src);
1189 }
1190
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001191 void xor_(Register dst, const Operand& src) {
1192 arithmetic_op(0x33, dst, src);
1193 }
1194
1195 void xor_(const Operand& dst, Register src) {
1196 arithmetic_op(0x31, src, dst);
1197 }
1198
1199 void xor_(Register dst, Immediate src) {
1200 immediate_arithmetic_op(0x6, dst, src);
1201 }
1202
1203 void xor_(const Operand& dst, Immediate src) {
1204 immediate_arithmetic_op(0x6, dst, src);
1205 }
1206
ager@chromium.org9085a012009-05-11 19:22:57 +00001207 // Bit operations.
1208 void bt(const Operand& dst, Register src);
1209 void bts(const Operand& dst, Register src);
1210
1211 // Miscellaneous
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001212 void clc();
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001213 void cld();
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001214 void cpuid();
ager@chromium.org9085a012009-05-11 19:22:57 +00001215 void hlt();
1216 void int3();
1217 void nop();
ager@chromium.org9085a012009-05-11 19:22:57 +00001218 void ret(int imm16);
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001219 void setcc(Condition cc, Register reg);
ager@chromium.org9085a012009-05-11 19:22:57 +00001220
1221 // Label operations & relative jumps (PPUM Appendix D)
1222 //
1223 // Takes a branch opcode (cc) and a label (L) and generates
1224 // either a backward branch or a forward branch and links it
1225 // to the label fixup chain. Usage:
1226 //
1227 // Label L; // unbound label
1228 // j(cc, &L); // forward branch to unbound label
1229 // bind(&L); // bind label to the current pc
1230 // j(cc, &L); // backward branch to bound label
1231 // bind(&L); // illegal: a label may be bound only once
1232 //
1233 // Note: The same Label can be used for forward and backward branches
1234 // but it may be bound only once.
1235
1236 void bind(Label* L); // binds an unbound label L to the current code position
1237
1238 // Calls
ager@chromium.orge2902be2009-06-08 12:21:35 +00001239 // Call near relative 32-bit displacement, relative to next instruction.
ager@chromium.org9085a012009-05-11 19:22:57 +00001240 void call(Label* L);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001241 void call(Address entry, RelocInfo::Mode rmode);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001242 void call(Handle<Code> target,
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001243 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001244 TypeFeedbackId ast_id = TypeFeedbackId::None());
ager@chromium.orge2902be2009-06-08 12:21:35 +00001245
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001246 // Calls directly to the given address using a relative offset.
1247 // Should only ever be used in Code objects for calls within the
1248 // same Code object. Should not be used when generating new code (use labels),
1249 // but only when patching existing code.
1250 void call(Address target);
1251
ager@chromium.orge2902be2009-06-08 12:21:35 +00001252 // Call near absolute indirect, address in register
1253 void call(Register adr);
1254
1255 // Call near indirect
1256 void call(const Operand& operand);
ager@chromium.org9085a012009-05-11 19:22:57 +00001257
1258 // Jumps
ager@chromium.orge2902be2009-06-08 12:21:35 +00001259 // Jump short or near relative.
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001260 // Use a 32-bit signed displacement.
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001261 // Unconditional jump to L
1262 void jmp(Label* L, Label::Distance distance = Label::kFar);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001263 void jmp(Address entry, RelocInfo::Mode rmode);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001264 void jmp(Handle<Code> target, RelocInfo::Mode rmode);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001265
1266 // Jump near absolute indirect (r64)
1267 void jmp(Register adr);
ager@chromium.org9085a012009-05-11 19:22:57 +00001268
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001269 // Jump near absolute indirect (m64)
1270 void jmp(const Operand& src);
1271
ager@chromium.org9085a012009-05-11 19:22:57 +00001272 // Conditional jumps
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001273 void j(Condition cc,
1274 Label* L,
karlklose@chromium.org83a47282011-05-11 11:54:09 +00001275 Label::Distance distance = Label::kFar);
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001276 void j(Condition cc, Address entry, RelocInfo::Mode rmode);
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001277 void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
ager@chromium.org9085a012009-05-11 19:22:57 +00001278
1279 // Floating-point operations
1280 void fld(int i);
1281
1282 void fld1();
1283 void fldz();
ager@chromium.orgac091b72010-05-05 07:34:42 +00001284 void fldpi();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001285 void fldln2();
ager@chromium.org9085a012009-05-11 19:22:57 +00001286
1287 void fld_s(const Operand& adr);
1288 void fld_d(const Operand& adr);
1289
1290 void fstp_s(const Operand& adr);
1291 void fstp_d(const Operand& adr);
ager@chromium.org3811b432009-10-28 14:53:37 +00001292 void fstp(int index);
ager@chromium.org9085a012009-05-11 19:22:57 +00001293
1294 void fild_s(const Operand& adr);
1295 void fild_d(const Operand& adr);
1296
1297 void fist_s(const Operand& adr);
1298
1299 void fistp_s(const Operand& adr);
1300 void fistp_d(const Operand& adr);
1301
1302 void fisttp_s(const Operand& adr);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001303 void fisttp_d(const Operand& adr);
ager@chromium.org9085a012009-05-11 19:22:57 +00001304
1305 void fabs();
1306 void fchs();
1307
1308 void fadd(int i);
1309 void fsub(int i);
1310 void fmul(int i);
1311 void fdiv(int i);
1312
1313 void fisub_s(const Operand& adr);
1314
1315 void faddp(int i = 1);
1316 void fsubp(int i = 1);
1317 void fsubrp(int i = 1);
1318 void fmulp(int i = 1);
1319 void fdivp(int i = 1);
1320 void fprem();
1321 void fprem1();
1322
1323 void fxch(int i = 1);
1324 void fincstp();
1325 void ffree(int i = 0);
1326
1327 void ftst();
1328 void fucomp(int i);
1329 void fucompp();
ager@chromium.org3811b432009-10-28 14:53:37 +00001330 void fucomi(int i);
1331 void fucomip();
1332
ager@chromium.org9085a012009-05-11 19:22:57 +00001333 void fcompp();
1334 void fnstsw_ax();
1335 void fwait();
1336 void fnclex();
1337
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001338 void fsin();
1339 void fcos();
mstarzinger@chromium.org1b3afd12011-11-29 14:28:56 +00001340 void fptan();
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001341 void fyl2x();
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001342 void f2xm1();
1343 void fscale();
1344 void fninit();
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001345
ager@chromium.org9085a012009-05-11 19:22:57 +00001346 void frndint();
1347
ager@chromium.org3e875802009-06-29 08:26:34 +00001348 void sahf();
1349
jkummerow@chromium.orgef33a542013-10-28 18:03:37 +00001350 // SSE instructions
1351 void movaps(XMMRegister dst, XMMRegister src);
1352 void movss(XMMRegister dst, const Operand& src);
1353 void movss(const Operand& dst, XMMRegister src);
machenbach@chromium.orgaf9cfcb2013-11-19 11:05:18 +00001354 void shufps(XMMRegister dst, XMMRegister src, byte imm8);
jkummerow@chromium.orgef33a542013-10-28 18:03:37 +00001355
1356 void cvttss2si(Register dst, const Operand& src);
1357 void cvttss2si(Register dst, XMMRegister src);
1358 void cvtlsi2ss(XMMRegister dst, Register src);
1359
jkummerow@chromium.orgef33a542013-10-28 18:03:37 +00001360 void andps(XMMRegister dst, XMMRegister src);
machenbach@chromium.orgaf9cfcb2013-11-19 11:05:18 +00001361 void andps(XMMRegister dst, const Operand& src);
verwaest@chromium.org057bd502013-11-06 12:03:29 +00001362 void orps(XMMRegister dst, XMMRegister src);
machenbach@chromium.orgaf9cfcb2013-11-19 11:05:18 +00001363 void orps(XMMRegister dst, const Operand& src);
verwaest@chromium.org057bd502013-11-06 12:03:29 +00001364 void xorps(XMMRegister dst, XMMRegister src);
machenbach@chromium.orgaf9cfcb2013-11-19 11:05:18 +00001365 void xorps(XMMRegister dst, const Operand& src);
1366
1367 void addps(XMMRegister dst, XMMRegister src);
1368 void addps(XMMRegister dst, const Operand& src);
1369 void subps(XMMRegister dst, XMMRegister src);
1370 void subps(XMMRegister dst, const Operand& src);
1371 void mulps(XMMRegister dst, XMMRegister src);
1372 void mulps(XMMRegister dst, const Operand& src);
1373 void divps(XMMRegister dst, XMMRegister src);
1374 void divps(XMMRegister dst, const Operand& src);
jkummerow@chromium.orgef33a542013-10-28 18:03:37 +00001375
1376 void movmskps(Register dst, XMMRegister src);
1377
ager@chromium.org3e875802009-06-29 08:26:34 +00001378 // SSE2 instructions
ager@chromium.org357bf652010-04-12 11:30:10 +00001379 void movd(XMMRegister dst, Register src);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001380 void movd(Register dst, XMMRegister src);
1381 void movq(XMMRegister dst, Register src);
1382 void movq(Register dst, XMMRegister src);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001383 void movq(XMMRegister dst, XMMRegister src);
ager@chromium.org357bf652010-04-12 11:30:10 +00001384
danno@chromium.org160a7b02011-04-18 15:51:38 +00001385 // Don't use this unless it's important to keep the
1386 // top half of the destination register unchanged.
1387 // Used movaps when moving double values and movq for integer
1388 // values in xmm registers.
ager@chromium.org357bf652010-04-12 11:30:10 +00001389 void movsd(XMMRegister dst, XMMRegister src);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001390
1391 void movsd(const Operand& dst, XMMRegister src);
ager@chromium.org357bf652010-04-12 11:30:10 +00001392 void movsd(XMMRegister dst, const Operand& src);
ager@chromium.org3e875802009-06-29 08:26:34 +00001393
ager@chromium.org0ee099b2011-01-25 14:06:47 +00001394 void movdqa(const Operand& dst, XMMRegister src);
1395 void movdqa(XMMRegister dst, const Operand& src);
1396
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +00001397 void movdqu(const Operand& dst, XMMRegister src);
1398 void movdqu(XMMRegister dst, const Operand& src);
1399
danno@chromium.org160a7b02011-04-18 15:51:38 +00001400 void movapd(XMMRegister dst, XMMRegister src);
danno@chromium.org160a7b02011-04-18 15:51:38 +00001401
ager@chromium.org9085a012009-05-11 19:22:57 +00001402 void cvttsd2si(Register dst, const Operand& src);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +00001403 void cvttsd2si(Register dst, XMMRegister src);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +00001404 void cvttsd2siq(Register dst, XMMRegister src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001405
ager@chromium.org3e875802009-06-29 08:26:34 +00001406 void cvtlsi2sd(XMMRegister dst, const Operand& src);
1407 void cvtlsi2sd(XMMRegister dst, Register src);
1408 void cvtqsi2sd(XMMRegister dst, const Operand& src);
1409 void cvtqsi2sd(XMMRegister dst, Register src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001410
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001411
ager@chromium.org357bf652010-04-12 11:30:10 +00001412 void cvtss2sd(XMMRegister dst, XMMRegister src);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001413 void cvtss2sd(XMMRegister dst, const Operand& src);
1414 void cvtsd2ss(XMMRegister dst, XMMRegister src);
1415
1416 void cvtsd2si(Register dst, XMMRegister src);
1417 void cvtsd2siq(Register dst, XMMRegister src);
ager@chromium.org357bf652010-04-12 11:30:10 +00001418
ager@chromium.org9085a012009-05-11 19:22:57 +00001419 void addsd(XMMRegister dst, XMMRegister src);
danno@chromium.org1f34ad32012-11-26 14:53:56 +00001420 void addsd(XMMRegister dst, const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001421 void subsd(XMMRegister dst, XMMRegister src);
1422 void mulsd(XMMRegister dst, XMMRegister src);
danno@chromium.org1f34ad32012-11-26 14:53:56 +00001423 void mulsd(XMMRegister dst, const Operand& src);
ager@chromium.org9085a012009-05-11 19:22:57 +00001424 void divsd(XMMRegister dst, XMMRegister src);
1425
vegorov@chromium.org5d6c1f52011-02-28 13:13:38 +00001426 void andpd(XMMRegister dst, XMMRegister src);
1427 void orpd(XMMRegister dst, XMMRegister src);
ager@chromium.org5c838252010-02-19 08:53:10 +00001428 void xorpd(XMMRegister dst, XMMRegister src);
kmillikin@chromium.org4111b802010-05-03 10:34:42 +00001429 void sqrtsd(XMMRegister dst, XMMRegister src);
ager@chromium.org5c838252010-02-19 08:53:10 +00001430
ager@chromium.org5c838252010-02-19 08:53:10 +00001431 void ucomisd(XMMRegister dst, XMMRegister src);
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001432 void ucomisd(XMMRegister dst, const Operand& src);
jkummerow@chromium.orgef33a542013-10-28 18:03:37 +00001433 void cmpltsd(XMMRegister dst, XMMRegister src);
1434
1435 void movmskpd(Register dst, XMMRegister src);
1436
1437 // SSE 4.1 instruction
1438 void extractps(Register dst, XMMRegister src, byte imm8);
ager@chromium.org3e875802009-06-29 08:26:34 +00001439
danno@chromium.org160a7b02011-04-18 15:51:38 +00001440 enum RoundingMode {
1441 kRoundToNearest = 0x0,
1442 kRoundDown = 0x1,
1443 kRoundUp = 0x2,
1444 kRoundToZero = 0x3
1445 };
1446
1447 void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1448
ager@chromium.org9085a012009-05-11 19:22:57 +00001449 // Debugging
1450 void Print();
1451
1452 // Check the code size generated from label to here.
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001453 int SizeOfCodeGeneratedSince(Label* label) {
1454 return pc_offset() - label->pos();
1455 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001456
1457 // Mark address of the ExitJSFrame code.
1458 void RecordJSReturn();
1459
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001460 // Mark address of a debug break slot.
1461 void RecordDebugBreakSlot();
1462
ager@chromium.org9085a012009-05-11 19:22:57 +00001463 // Record a comment relocation entry that can be used by a disassembler.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001464 // Use --code-comments to enable.
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001465 void RecordComment(const char* msg, bool force = false);
ager@chromium.org9085a012009-05-11 19:22:57 +00001466
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001467 // Writes a single word of data in the code stream.
1468 // Used for inline tables, e.g., jump-tables.
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001469 void db(uint8_t data);
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001470 void dd(uint32_t data);
1471
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001472 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
ager@chromium.org9085a012009-05-11 19:22:57 +00001473
1474 // Check if there is less than kGap bytes available in the buffer.
1475 // If this is the case, we need to grow the buffer before emitting
1476 // an instruction or relocation information.
ager@chromium.org4af710e2009-09-15 12:20:11 +00001477 inline bool buffer_overflow() const {
1478 return pc_ >= reloc_info_writer.pos() - kGap;
1479 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001480
1481 // Get the number of bytes available in the buffer.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001482 inline int available_space() const {
1483 return static_cast<int>(reloc_info_writer.pos() - pc_);
1484 }
ager@chromium.org9085a012009-05-11 19:22:57 +00001485
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +00001486 static bool IsNop(Address addr);
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001487
ager@chromium.org9085a012009-05-11 19:22:57 +00001488 // Avoid overflows for displacements etc.
1489 static const int kMaximalBufferSize = 512*MB;
ager@chromium.org9085a012009-05-11 19:22:57 +00001490
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001491 byte byte_at(int pos) { return buffer_[pos]; }
1492 void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1493
ager@chromium.org9085a012009-05-11 19:22:57 +00001494 private:
1495 byte* addr_at(int pos) { return buffer_ + pos; }
ager@chromium.org9085a012009-05-11 19:22:57 +00001496 uint32_t long_at(int pos) {
1497 return *reinterpret_cast<uint32_t*>(addr_at(pos));
1498 }
1499 void long_at_put(int pos, uint32_t x) {
1500 *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1501 }
1502
1503 // code emission
1504 void GrowBuffer();
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001505
1506 void emit(byte x) { *pc_++ = x; }
1507 inline void emitl(uint32_t x);
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001508 inline void emitp(void* x, RelocInfo::Mode rmode);
bmeurer@chromium.orgc9913f02013-10-24 06:31:36 +00001509 inline void emitq(uint64_t x);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001510 inline void emitw(uint16_t x);
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001511 inline void emit_code_target(Handle<Code> target,
1512 RelocInfo::Mode rmode,
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001513 TypeFeedbackId ast_id = TypeFeedbackId::None());
ulan@chromium.org6e196bf2013-03-13 09:38:22 +00001514 inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001515 void emit(Immediate x) { emitl(x.value_); }
ager@chromium.org9085a012009-05-11 19:22:57 +00001516
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001517 // Emits a REX prefix that encodes a 64-bit operand size and
1518 // the top bit of both register codes.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001519 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1520 // REX.W is set.
ager@chromium.org3e875802009-06-29 08:26:34 +00001521 inline void emit_rex_64(XMMRegister reg, Register rm_reg);
ager@chromium.orgac091b72010-05-05 07:34:42 +00001522 inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1523 inline void emit_rex_64(Register reg, Register rm_reg);
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001524
1525 // Emits a REX prefix that encodes a 64-bit operand size and
1526 // the top bit of the destination, index, and base register codes.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001527 // The high bit of reg is used for REX.R, the high bit of op's base
1528 // register is used for REX.B, and the high bit of op's index register
1529 // is used for REX.X. REX.W is set.
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001530 inline void emit_rex_64(Register reg, const Operand& op);
ager@chromium.org3e875802009-06-29 08:26:34 +00001531 inline void emit_rex_64(XMMRegister reg, const Operand& op);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001532
1533 // Emits a REX prefix that encodes a 64-bit operand size and
1534 // the top bit of the register code.
1535 // The high bit of register is used for REX.B.
1536 // REX.W is set and REX.R and REX.X are clear.
1537 inline void emit_rex_64(Register rm_reg);
1538
1539 // Emits a REX prefix that encodes a 64-bit operand size and
1540 // the top bit of the index and base register codes.
1541 // The high bit of op's base register is used for REX.B, and the high
1542 // bit of op's index register is used for REX.X.
1543 // REX.W is set and REX.R clear.
1544 inline void emit_rex_64(const Operand& op);
1545
1546 // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1547 void emit_rex_64() { emit(0x48); }
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001548
1549 // 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 +00001550 // REX.W is clear.
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001551 inline void emit_rex_32(Register reg, Register rm_reg);
1552
1553 // The high bit of reg is used for REX.R, the high bit of op's base
1554 // register is used for REX.B, and the high bit of op's index register
1555 // is used for REX.X. REX.W is cleared.
1556 inline void emit_rex_32(Register reg, const Operand& op);
1557
ager@chromium.orge2902be2009-06-08 12:21:35 +00001558 // High bit of rm_reg goes to REX.B.
1559 // REX.W, REX.R and REX.X are clear.
1560 inline void emit_rex_32(Register rm_reg);
1561
1562 // High bit of base goes to REX.B and high bit of index to REX.X.
1563 // REX.W and REX.R are clear.
1564 inline void emit_rex_32(const Operand& op);
1565
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001566 // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1567 // REX.W is cleared. If no REX bits are set, no byte is emitted.
1568 inline void emit_optional_rex_32(Register reg, Register rm_reg);
1569
1570 // The high bit of reg is used for REX.R, the high bit of op's base
1571 // register is used for REX.B, and the high bit of op's index register
1572 // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
1573 // is emitted.
1574 inline void emit_optional_rex_32(Register reg, const Operand& op);
1575
ager@chromium.org3e875802009-06-29 08:26:34 +00001576 // As for emit_optional_rex_32(Register, Register), except that
1577 // the registers are XMM registers.
1578 inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1579
1580 // As for emit_optional_rex_32(Register, Register), except that
ager@chromium.orgac091b72010-05-05 07:34:42 +00001581 // one of the registers is an XMM registers.
ager@chromium.org3e875802009-06-29 08:26:34 +00001582 inline void emit_optional_rex_32(XMMRegister reg, Register base);
1583
ager@chromium.orgac091b72010-05-05 07:34:42 +00001584 // As for emit_optional_rex_32(Register, Register), except that
1585 // one of the registers is an XMM registers.
1586 inline void emit_optional_rex_32(Register reg, XMMRegister base);
1587
ager@chromium.org3e875802009-06-29 08:26:34 +00001588 // As for emit_optional_rex_32(Register, const Operand&), except that
1589 // the register is an XMM register.
1590 inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1591
ager@chromium.orge2902be2009-06-08 12:21:35 +00001592 // Optionally do as emit_rex_32(Register) if the register number has
1593 // the high bit set.
1594 inline void emit_optional_rex_32(Register rm_reg);
1595
1596 // Optionally do as emit_rex_32(const Operand&) if the operand register
1597 // numbers have a high bit set.
1598 inline void emit_optional_rex_32(const Operand& op);
1599
1600
1601 // Emit the ModR/M byte, and optionally the SIB byte and
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001602 // 1- or 4-byte offset for a memory operand. Also encodes
1603 // the second operand of the operation, a register or operation
ager@chromium.orge2902be2009-06-08 12:21:35 +00001604 // subcode, into the reg field of the ModR/M byte.
1605 void emit_operand(Register reg, const Operand& adr) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001606 emit_operand(reg.low_bits(), adr);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001607 }
1608
1609 // Emit the ModR/M byte, and optionally the SIB byte and
1610 // 1- or 4-byte offset for a memory operand. Also used to encode
1611 // a three-bit opcode extension into the ModR/M byte.
1612 void emit_operand(int rm, const Operand& adr);
1613
1614 // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1615 void emit_modrm(Register reg, Register rm_reg) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001616 emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
ager@chromium.orge2902be2009-06-08 12:21:35 +00001617 }
1618
1619 // Emit a ModR/M byte with an operation subcode in the reg field and
1620 // a register in the rm_reg field.
1621 void emit_modrm(int code, Register rm_reg) {
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001622 ASSERT(is_uint3(code));
1623 emit(0xC0 | code << 3 | rm_reg.low_bits());
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001624 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +00001625
ager@chromium.org9085a012009-05-11 19:22:57 +00001626 // Emit the code-object-relative offset of the label's position
1627 inline void emit_code_relative_offset(Label* label);
1628
jkummerow@chromium.orgef33a542013-10-28 18:03:37 +00001629 // The first argument is the reg field, the second argument is the r/m field.
1630 void emit_sse_operand(XMMRegister dst, XMMRegister src);
1631 void emit_sse_operand(XMMRegister reg, const Operand& adr);
1632 void emit_sse_operand(XMMRegister dst, Register src);
1633 void emit_sse_operand(Register dst, XMMRegister src);
1634
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001635 // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1636 // AND, OR, XOR, or CMP. The encodings of these operations are all
1637 // similar, differing just in the opcode or in the reg field of the
ager@chromium.orge2902be2009-06-08 12:21:35 +00001638 // ModR/M byte.
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001639 void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1640 void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1641 void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001642 void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001643 void arithmetic_op(byte opcode, Register reg, Register rm_reg);
kasperl@chromium.orge959c182009-07-27 08:59:04 +00001644 void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
sgjesse@chromium.org755c5b12009-05-29 11:04:38 +00001645 void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1646 void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
ager@chromium.org3e875802009-06-29 08:26:34 +00001647 // Operate on a byte in memory or register.
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001648 void immediate_arithmetic_op_8(byte subcode,
ager@chromium.org3e875802009-06-29 08:26:34 +00001649 Register dst,
1650 Immediate src);
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001651 void immediate_arithmetic_op_8(byte subcode,
1652 const Operand& dst,
1653 Immediate src);
1654 // Operate on a word in memory or register.
1655 void immediate_arithmetic_op_16(byte subcode,
1656 Register dst,
1657 Immediate src);
1658 void immediate_arithmetic_op_16(byte subcode,
1659 const Operand& dst,
1660 Immediate src);
1661 // Operate on a 32-bit word in memory or register.
1662 void immediate_arithmetic_op_32(byte subcode,
1663 Register dst,
1664 Immediate src);
1665 void immediate_arithmetic_op_32(byte subcode,
1666 const Operand& dst,
1667 Immediate src);
1668
ager@chromium.orge2902be2009-06-08 12:21:35 +00001669 // Emit machine code for a shift operation.
1670 void shift(Register dst, Immediate shift_amount, int subcode);
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +00001671 void shift_32(Register dst, Immediate shift_amount, int subcode);
ager@chromium.orge2902be2009-06-08 12:21:35 +00001672 // Shift dst by cl % 64 bits.
1673 void shift(Register dst, int subcode);
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001674 void shift_32(Register dst, int subcode);
ager@chromium.org9085a012009-05-11 19:22:57 +00001675
ager@chromium.org5aa501c2009-06-23 07:57:28 +00001676 void emit_farith(int b1, int b2, int i);
ager@chromium.org9085a012009-05-11 19:22:57 +00001677
1678 // labels
ager@chromium.orgeadaf222009-06-16 09:43:10 +00001679 // void print(Label* L);
ager@chromium.org9085a012009-05-11 19:22:57 +00001680 void bind_to(Label* L, int pos);
ager@chromium.org9085a012009-05-11 19:22:57 +00001681
ager@chromium.org9085a012009-05-11 19:22:57 +00001682 // record reloc info for current pc_
1683 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1684
1685 friend class CodePatcher;
1686 friend class EnsureSpace;
sgjesse@chromium.org911335c2009-08-19 12:59:44 +00001687 friend class RegExpMacroAssemblerX64;
ager@chromium.org9085a012009-05-11 19:22:57 +00001688
ager@chromium.org9085a012009-05-11 19:22:57 +00001689 // code generation
ager@chromium.org9085a012009-05-11 19:22:57 +00001690 RelocInfoWriter reloc_info_writer;
1691
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001692 List< Handle<Code> > code_targets_;
ager@chromium.org9085a012009-05-11 19:22:57 +00001693
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001694 PositionsRecorder positions_recorder_;
1695 friend class PositionsRecorder;
ager@chromium.org9085a012009-05-11 19:22:57 +00001696};
1697
1698
1699// Helper class that ensures that there is enough space for generating
1700// instructions and relocation information. The constructor makes
1701// sure that there is enough space and (in debug mode) the destructor
1702// checks that we did not generate too much.
1703class EnsureSpace BASE_EMBEDDED {
1704 public:
1705 explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
ager@chromium.org4af710e2009-09-15 12:20:11 +00001706 if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
ager@chromium.org9085a012009-05-11 19:22:57 +00001707#ifdef DEBUG
1708 space_before_ = assembler_->available_space();
1709#endif
1710 }
1711
1712#ifdef DEBUG
1713 ~EnsureSpace() {
1714 int bytes_generated = space_before_ - assembler_->available_space();
1715 ASSERT(bytes_generated < assembler_->kGap);
1716 }
1717#endif
1718
1719 private:
1720 Assembler* assembler_;
1721#ifdef DEBUG
1722 int space_before_;
1723#endif
1724};
1725
1726} } // namespace v8::internal
1727
1728#endif // V8_X64_ASSEMBLER_X64_H_