blob: 55e6f9ab2393e910b8bfc212ae4bc0e364a0ea84 [file] [log] [blame]
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003//
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the
14// distribution.
15//
16// - Neither the name of Sun Microsystems or the names of contributors may
17// be used to endorse or promote products derived from this software without
18// specific prior written permission.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000019//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000022// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31// OF THE POSSIBILITY OF SUCH DAMAGE.
32
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000033// The original source code covered by the above license above has been
34// modified significantly by Google Inc.
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +000035// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
37// A light-weight ARM Assembler
38// Generates user mode instructions for the ARM architecture up to version 5
39
ager@chromium.org5ec48922009-05-05 07:25:34 +000040#ifndef V8_ARM_ASSEMBLER_ARM_H_
41#define V8_ARM_ASSEMBLER_ARM_H_
ager@chromium.org18ad94b2009-09-02 08:22:29 +000042#include <stdio.h>
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043#include "assembler.h"
ager@chromium.org378b34e2011-01-28 08:04:38 +000044#include "constants-arm.h"
ager@chromium.orgc4c92722009-11-18 14:12:51 +000045#include "serialize.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046
kasperl@chromium.org71affb52009-05-26 05:44:31 +000047namespace v8 {
48namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049
yangguo@chromium.org003650e2013-01-24 16:31:08 +000050// CpuFeatures keeps track of which features are supported by the target CPU.
ulan@chromium.org750145a2013-03-07 15:14:13 +000051// Supported features must be enabled by a CpuFeatureScope before use.
yangguo@chromium.org003650e2013-01-24 16:31:08 +000052class CpuFeatures : public AllStatic {
53 public:
54 // Detect features of the target CPU. Set safe defaults if the serializer
55 // is enabled (snapshots must be portable).
56 static void Probe();
57
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000058 // Display target use when compiling.
59 static void PrintTarget();
60
61 // Display features.
62 static void PrintFeatures();
63
yangguo@chromium.org003650e2013-01-24 16:31:08 +000064 // Check whether a feature is supported by the target CPU.
65 static bool IsSupported(CpuFeature f) {
66 ASSERT(initialized_);
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +000067 return Check(f, supported_);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000068 }
69
ulan@chromium.org750145a2013-03-07 15:14:13 +000070 static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
yangguo@chromium.org003650e2013-01-24 16:31:08 +000071 ASSERT(initialized_);
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +000072 return Check(f, found_by_runtime_probing_only_);
yangguo@chromium.org003650e2013-01-24 16:31:08 +000073 }
yangguo@chromium.org003650e2013-01-24 16:31:08 +000074
ulan@chromium.org750145a2013-03-07 15:14:13 +000075 static bool IsSafeForSnapshot(CpuFeature f) {
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +000076 return Check(f, cross_compile_) ||
77 (IsSupported(f) &&
ulan@chromium.org750145a2013-03-07 15:14:13 +000078 (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
79 }
yangguo@chromium.org003650e2013-01-24 16:31:08 +000080
danno@chromium.org169691d2013-07-15 08:01:13 +000081 static unsigned cache_line_size() { return cache_line_size_; }
82
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +000083 static bool VerifyCrossCompiling() {
84 return cross_compile_ == 0;
85 }
86
87 static bool VerifyCrossCompiling(CpuFeature f) {
88 unsigned mask = flag2set(f);
89 return cross_compile_ == 0 ||
90 (cross_compile_ & mask) == mask;
91 }
92
yangguo@chromium.org003650e2013-01-24 16:31:08 +000093 private:
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +000094 static bool Check(CpuFeature f, unsigned set) {
95 return (set & flag2set(f)) != 0;
96 }
97
98 static unsigned flag2set(CpuFeature f) {
99 return 1u << f;
100 }
101
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000102#ifdef DEBUG
103 static bool initialized_;
104#endif
105 static unsigned supported_;
ulan@chromium.org750145a2013-03-07 15:14:13 +0000106 static unsigned found_by_runtime_probing_only_;
danno@chromium.org169691d2013-07-15 08:01:13 +0000107 static unsigned cache_line_size_;
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000108
mvstanton@chromium.org63ea3d22013-10-10 09:24:12 +0000109 static unsigned cross_compile_;
110
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000111 friend class ExternalReference;
machenbach@chromium.org528ce022013-09-23 14:09:36 +0000112 friend class PlatformFeatureScope;
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000113 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
114};
115
116
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000117// CPU Registers.
118//
119// 1) We would prefer to use an enum, but enum values are assignment-
120// compatible with int, which has caused code-generation bugs.
121//
122// 2) We would prefer to use a class instead of a struct but we don't like
123// the register initialization to depend on the particular initialization
124// order (which appears to be different on OS X, Linux, and Windows for the
125// installed versions of C++ we tried). Using a struct permits C-style
126// "initialization". Also, the Register objects cannot be const as this
127// forces initialization stubs in MSVC, making us dependent on initialization
128// order.
129//
130// 3) By not using an enum, we are possibly preventing the compiler from
131// doing certain constant folds, which may significantly reduce the
132// code generated for some assembly instructions (because they boil down
133// to a few constants). If this is a problem, we could change the code
134// such that we use an enum in optimized mode, and the struct in debug
135// mode. This way we get the compile-time error checking in debug mode
136// and best performance in optimized code.
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000137
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000138// These constants are used in several locations, including static initializers
139const int kRegister_no_reg_Code = -1;
140const int kRegister_r0_Code = 0;
141const int kRegister_r1_Code = 1;
142const int kRegister_r2_Code = 2;
143const int kRegister_r3_Code = 3;
144const int kRegister_r4_Code = 4;
145const int kRegister_r5_Code = 5;
146const int kRegister_r6_Code = 6;
147const int kRegister_r7_Code = 7;
148const int kRegister_r8_Code = 8;
149const int kRegister_r9_Code = 9;
150const int kRegister_r10_Code = 10;
151const int kRegister_fp_Code = 11;
152const int kRegister_ip_Code = 12;
153const int kRegister_sp_Code = 13;
154const int kRegister_lr_Code = 14;
155const int kRegister_pc_Code = 15;
156
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000157// Core register
158struct Register {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000159 static const int kNumRegisters = 16;
machenbach@chromium.org3d079fe2013-09-25 08:19:55 +0000160 static const int kMaxNumAllocatableRegisters =
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000161 FLAG_enable_ool_constant_pool ? 8 : 9;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +0000162 static const int kSizeInBytes = 4;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000163
164 inline static int NumAllocatableRegisters();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000165
166 static int ToAllocationIndex(Register reg) {
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000167 if (FLAG_enable_ool_constant_pool && (reg.code() >= kRegister_r8_Code)) {
168 return reg.code() - 1;
169 }
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000170 ASSERT(reg.code() < kMaxNumAllocatableRegisters);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000171 return reg.code();
172 }
173
174 static Register FromAllocationIndex(int index) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000175 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000176 if (FLAG_enable_ool_constant_pool && (index >= 7)) {
177 return from_code(index + 1);
178 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000179 return from_code(index);
180 }
181
182 static const char* AllocationIndexToString(int index) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000183 ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000184 const char* const names[] = {
185 "r0",
186 "r1",
187 "r2",
188 "r3",
189 "r4",
190 "r5",
191 "r6",
192 "r7",
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000193 "r8",
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000194 };
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000195 if (FLAG_enable_ool_constant_pool && (index >= 7)) {
196 return names[index + 1];
197 }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000198 return names[index];
199 }
200
201 static Register from_code(int code) {
202 Register r = { code };
203 return r;
204 }
205
206 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000207 bool is(Register reg) const { return code_ == reg.code_; }
208 int code() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000209 ASSERT(is_valid());
210 return code_;
211 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000212 int bit() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000213 ASSERT(is_valid());
214 return 1 << code_;
215 }
216
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000217 void set_code(int code) {
218 code_ = code;
219 ASSERT(is_valid());
220 }
221
ager@chromium.org5c838252010-02-19 08:53:10 +0000222 // Unfortunately we can't make this private in a struct.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223 int code_;
224};
225
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000226const Register no_reg = { kRegister_no_reg_Code };
227
228const Register r0 = { kRegister_r0_Code };
229const Register r1 = { kRegister_r1_Code };
230const Register r2 = { kRegister_r2_Code };
231const Register r3 = { kRegister_r3_Code };
232const Register r4 = { kRegister_r4_Code };
233const Register r5 = { kRegister_r5_Code };
234const Register r6 = { kRegister_r6_Code };
jkummerow@chromium.orgc3669762013-09-30 13:42:25 +0000235// Used as constant pool pointer register if FLAG_enable_ool_constant_pool.
jkummerow@chromium.org1456e702012-03-30 08:38:13 +0000236const Register r7 = { kRegister_r7_Code };
237// Used as context register.
238const Register r8 = { kRegister_r8_Code };
239// Used as lithium codegen scratch register.
240const Register r9 = { kRegister_r9_Code };
241// Used as roots register.
242const Register r10 = { kRegister_r10_Code };
243const Register fp = { kRegister_fp_Code };
244const Register ip = { kRegister_ip_Code };
245const Register sp = { kRegister_sp_Code };
246const Register lr = { kRegister_lr_Code };
247const Register pc = { kRegister_pc_Code };
248
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000249// Single word VFP register.
250struct SwVfpRegister {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000251 static const int kSizeInBytes = 4;
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000252 bool is_valid() const { return 0 <= code_ && code_ < 32; }
253 bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
254 int code() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000255 ASSERT(is_valid());
256 return code_;
257 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000258 int bit() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000259 ASSERT(is_valid());
260 return 1 << code_;
261 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000262 void split_code(int* vm, int* m) const {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000263 ASSERT(is_valid());
264 *m = code_ & 0x1;
265 *vm = code_ >> 1;
266 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000267
268 int code_;
269};
270
271
272// Double word VFP register.
273struct DwVfpRegister {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000274 static const int kMaxNumRegisters = 32;
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000275 // A few double registers are reserved: one as a scratch register and one to
276 // hold 0.0, that does not fit in the immediate field of vmov instructions.
277 // d14: 0.0
278 // d15: scratch register.
279 static const int kNumReservedRegisters = 2;
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000280 static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
vegorov@chromium.org3cf47312011-06-29 13:20:01 +0000281 kNumReservedRegisters;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000282 static const int kSizeInBytes = 8;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000283
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000284 // Note: the number of registers can be different at snapshot and run-time.
285 // Any code included in the snapshot must be able to run both with 16 or 32
286 // registers.
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000287 inline static int NumRegisters();
288 inline static int NumAllocatableRegisters();
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000289
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000290 inline static int ToAllocationIndex(DwVfpRegister reg);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000291 static const char* AllocationIndexToString(int index);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000292 inline static DwVfpRegister FromAllocationIndex(int index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000293
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000294 static DwVfpRegister from_code(int code) {
295 DwVfpRegister r = { code };
296 return r;
297 }
298
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000299 bool is_valid() const {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000300 return 0 <= code_ && code_ < kMaxNumRegisters;
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000301 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000302 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000303 int code() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000304 ASSERT(is_valid());
305 return code_;
306 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000307 int bit() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000308 ASSERT(is_valid());
309 return 1 << code_;
310 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000311 void split_code(int* vm, int* m) const {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000312 ASSERT(is_valid());
313 *m = (code_ & 0x10) >> 4;
314 *vm = code_ & 0x0F;
315 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000316
317 int code_;
318};
319
320
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000321typedef DwVfpRegister DoubleRegister;
322
323
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000324// Double word VFP register d0-15.
325struct LowDwVfpRegister {
326 public:
327 static const int kMaxNumLowRegisters = 16;
328 operator DwVfpRegister() const {
329 DwVfpRegister r = { code_ };
330 return r;
331 }
332 static LowDwVfpRegister from_code(int code) {
333 LowDwVfpRegister r = { code };
334 return r;
335 }
336
337 bool is_valid() const {
338 return 0 <= code_ && code_ < kMaxNumLowRegisters;
339 }
340 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
341 bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
342 int code() const {
343 ASSERT(is_valid());
344 return code_;
345 }
346 SwVfpRegister low() const {
347 SwVfpRegister reg;
348 reg.code_ = code_ * 2;
349
350 ASSERT(reg.is_valid());
351 return reg;
352 }
353 SwVfpRegister high() const {
354 SwVfpRegister reg;
355 reg.code_ = (code_ * 2) + 1;
356
357 ASSERT(reg.is_valid());
358 return reg;
359 }
360
361 int code_;
362};
363
364
danno@chromium.org169691d2013-07-15 08:01:13 +0000365// Quad word NEON register.
366struct QwNeonRegister {
367 static const int kMaxNumRegisters = 16;
368
369 static QwNeonRegister from_code(int code) {
370 QwNeonRegister r = { code };
371 return r;
372 }
373
374 bool is_valid() const {
375 return (0 <= code_) && (code_ < kMaxNumRegisters);
376 }
377 bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
378 int code() const {
379 ASSERT(is_valid());
380 return code_;
381 }
382 void split_code(int* vm, int* m) const {
383 ASSERT(is_valid());
384 *m = (code_ & 0x10) >> 4;
385 *vm = code_ & 0x0F;
386 }
387
388 int code_;
389};
390
391
392typedef QwNeonRegister QuadRegister;
393
394
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000395// Support for the VFP registers s0 to s31 (d0 to d15).
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000396// Note that "s(N):s(N+1)" is the same as "d(N/2)".
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000397const SwVfpRegister s0 = { 0 };
398const SwVfpRegister s1 = { 1 };
399const SwVfpRegister s2 = { 2 };
400const SwVfpRegister s3 = { 3 };
401const SwVfpRegister s4 = { 4 };
402const SwVfpRegister s5 = { 5 };
403const SwVfpRegister s6 = { 6 };
404const SwVfpRegister s7 = { 7 };
405const SwVfpRegister s8 = { 8 };
406const SwVfpRegister s9 = { 9 };
407const SwVfpRegister s10 = { 10 };
408const SwVfpRegister s11 = { 11 };
409const SwVfpRegister s12 = { 12 };
410const SwVfpRegister s13 = { 13 };
411const SwVfpRegister s14 = { 14 };
412const SwVfpRegister s15 = { 15 };
413const SwVfpRegister s16 = { 16 };
414const SwVfpRegister s17 = { 17 };
415const SwVfpRegister s18 = { 18 };
416const SwVfpRegister s19 = { 19 };
417const SwVfpRegister s20 = { 20 };
418const SwVfpRegister s21 = { 21 };
419const SwVfpRegister s22 = { 22 };
420const SwVfpRegister s23 = { 23 };
421const SwVfpRegister s24 = { 24 };
422const SwVfpRegister s25 = { 25 };
423const SwVfpRegister s26 = { 26 };
424const SwVfpRegister s27 = { 27 };
425const SwVfpRegister s28 = { 28 };
426const SwVfpRegister s29 = { 29 };
427const SwVfpRegister s30 = { 30 };
428const SwVfpRegister s31 = { 31 };
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000429
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000430const DwVfpRegister no_dreg = { -1 };
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000431const LowDwVfpRegister d0 = { 0 };
432const LowDwVfpRegister d1 = { 1 };
433const LowDwVfpRegister d2 = { 2 };
434const LowDwVfpRegister d3 = { 3 };
435const LowDwVfpRegister d4 = { 4 };
436const LowDwVfpRegister d5 = { 5 };
437const LowDwVfpRegister d6 = { 6 };
438const LowDwVfpRegister d7 = { 7 };
439const LowDwVfpRegister d8 = { 8 };
440const LowDwVfpRegister d9 = { 9 };
441const LowDwVfpRegister d10 = { 10 };
442const LowDwVfpRegister d11 = { 11 };
443const LowDwVfpRegister d12 = { 12 };
444const LowDwVfpRegister d13 = { 13 };
445const LowDwVfpRegister d14 = { 14 };
446const LowDwVfpRegister d15 = { 15 };
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000447const DwVfpRegister d16 = { 16 };
448const DwVfpRegister d17 = { 17 };
449const DwVfpRegister d18 = { 18 };
450const DwVfpRegister d19 = { 19 };
451const DwVfpRegister d20 = { 20 };
452const DwVfpRegister d21 = { 21 };
453const DwVfpRegister d22 = { 22 };
454const DwVfpRegister d23 = { 23 };
455const DwVfpRegister d24 = { 24 };
456const DwVfpRegister d25 = { 25 };
457const DwVfpRegister d26 = { 26 };
458const DwVfpRegister d27 = { 27 };
459const DwVfpRegister d28 = { 28 };
460const DwVfpRegister d29 = { 29 };
461const DwVfpRegister d30 = { 30 };
462const DwVfpRegister d31 = { 31 };
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000463
danno@chromium.org169691d2013-07-15 08:01:13 +0000464const QwNeonRegister q0 = { 0 };
465const QwNeonRegister q1 = { 1 };
466const QwNeonRegister q2 = { 2 };
467const QwNeonRegister q3 = { 3 };
468const QwNeonRegister q4 = { 4 };
469const QwNeonRegister q5 = { 5 };
470const QwNeonRegister q6 = { 6 };
471const QwNeonRegister q7 = { 7 };
472const QwNeonRegister q8 = { 8 };
473const QwNeonRegister q9 = { 9 };
474const QwNeonRegister q10 = { 10 };
475const QwNeonRegister q11 = { 11 };
476const QwNeonRegister q12 = { 12 };
477const QwNeonRegister q13 = { 13 };
478const QwNeonRegister q14 = { 14 };
479const QwNeonRegister q15 = { 15 };
480
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000481
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000482// Aliases for double registers. Defined using #define instead of
483// "static const DwVfpRegister&" because Clang complains otherwise when a
484// compilation unit that includes this header doesn't use the variables.
485#define kFirstCalleeSavedDoubleReg d8
486#define kLastCalleeSavedDoubleReg d15
487#define kDoubleRegZero d14
488#define kScratchDoubleReg d15
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000489
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490
491// Coprocessor register
492struct CRegister {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000493 bool is_valid() const { return 0 <= code_ && code_ < 16; }
494 bool is(CRegister creg) const { return code_ == creg.code_; }
495 int code() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000496 ASSERT(is_valid());
497 return code_;
498 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000499 int bit() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000500 ASSERT(is_valid());
501 return 1 << code_;
502 }
503
ager@chromium.org5c838252010-02-19 08:53:10 +0000504 // Unfortunately we can't make this private in a struct.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000505 int code_;
506};
507
508
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000509const CRegister no_creg = { -1 };
510
511const CRegister cr0 = { 0 };
512const CRegister cr1 = { 1 };
513const CRegister cr2 = { 2 };
514const CRegister cr3 = { 3 };
515const CRegister cr4 = { 4 };
516const CRegister cr5 = { 5 };
517const CRegister cr6 = { 6 };
518const CRegister cr7 = { 7 };
519const CRegister cr8 = { 8 };
520const CRegister cr9 = { 9 };
521const CRegister cr10 = { 10 };
522const CRegister cr11 = { 11 };
523const CRegister cr12 = { 12 };
524const CRegister cr13 = { 13 };
525const CRegister cr14 = { 14 };
526const CRegister cr15 = { 15 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000527
528
529// Coprocessor number
530enum Coprocessor {
531 p0 = 0,
532 p1 = 1,
533 p2 = 2,
534 p3 = 3,
535 p4 = 4,
536 p5 = 5,
537 p6 = 6,
538 p7 = 7,
539 p8 = 8,
540 p9 = 9,
541 p10 = 10,
542 p11 = 11,
543 p12 = 12,
544 p13 = 13,
545 p14 = 14,
546 p15 = 15
547};
548
549
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000550// -----------------------------------------------------------------------------
551// Machine instruction Operands
552
553// Class Operand represents a shifter operand in data processing instructions
554class Operand BASE_EMBEDDED {
555 public:
556 // immediate
ager@chromium.org236ad962008-09-25 09:45:57 +0000557 INLINE(explicit Operand(int32_t immediate,
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000558 RelocInfo::Mode rmode = RelocInfo::NONE32));
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000559 INLINE(static Operand Zero()) {
560 return Operand(static_cast<int32_t>(0));
561 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000562 INLINE(explicit Operand(const ExternalReference& f));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000563 explicit Operand(Handle<Object> handle);
564 INLINE(explicit Operand(Smi* value));
565
566 // rm
567 INLINE(explicit Operand(Register rm));
568
569 // rm <shift_op> shift_imm
570 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000571 INLINE(static Operand SmiUntag(Register rm)) {
572 return Operand(rm, ASR, kSmiTagSize);
573 }
574 INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
575 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
576 return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
577 }
578 INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
579 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
580 return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
581 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000582
583 // rm <shift_op> rs
584 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
585
mads.s.ager31e71382008-08-13 09:32:07 +0000586 // Return true if this is a register operand.
587 INLINE(bool is_reg() const);
588
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000589 // Return true if this operand fits in one instruction so that no
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000590 // 2-instruction solution with a load into the ip register is necessary. If
591 // the instruction this operand is used for is a MOV or MVN instruction the
592 // actual instruction to use is required for this calculation. For other
593 // instructions instr is ignored.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000594 bool is_single_instruction(const Assembler* assembler, Instr instr = 0) const;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000595 bool must_output_reloc_info(const Assembler* assembler) const;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000596
597 inline int32_t immediate() const {
598 ASSERT(!rm_.is_valid());
599 return imm32_;
600 }
601
mads.s.ager31e71382008-08-13 09:32:07 +0000602 Register rm() const { return rm_; }
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000603 Register rs() const { return rs_; }
604 ShiftOp shift_op() const { return shift_op_; }
mads.s.ager31e71382008-08-13 09:32:07 +0000605
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000606 private:
607 Register rm_;
608 Register rs_;
609 ShiftOp shift_op_;
610 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
611 int32_t imm32_; // valid if rm_ == no_reg
ager@chromium.org236ad962008-09-25 09:45:57 +0000612 RelocInfo::Mode rmode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000613
614 friend class Assembler;
615};
616
617
618// Class MemOperand represents a memory operand in load and store instructions
619class MemOperand BASE_EMBEDDED {
620 public:
621 // [rn +/- offset] Offset/NegOffset
622 // [rn +/- offset]! PreIndex/NegPreIndex
623 // [rn], +/- offset PostIndex/NegPostIndex
624 // offset is any signed 32-bit value; offset is first loaded to register ip if
625 // it does not fit the addressing mode (12-bit unsigned and sign bit)
626 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
627
628 // [rn +/- rm] Offset/NegOffset
629 // [rn +/- rm]! PreIndex/NegPreIndex
630 // [rn], +/- rm PostIndex/NegPostIndex
631 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
632
633 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
634 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
635 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
636 explicit MemOperand(Register rn, Register rm,
637 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000638 INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
639 Register key,
640 AddrMode am = Offset)) {
641 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
642 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
643 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000644
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000645 void set_offset(int32_t offset) {
646 ASSERT(rm_.is(no_reg));
647 offset_ = offset;
648 }
649
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000650 uint32_t offset() const {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000651 ASSERT(rm_.is(no_reg));
652 return offset_;
653 }
654
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000655 Register rn() const { return rn_; }
656 Register rm() const { return rm_; }
ager@chromium.org04921a82011-06-27 13:21:41 +0000657 AddrMode am() const { return am_; }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000658
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000659 bool OffsetIsUint12Encodable() const {
660 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
661 }
662
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000663 private:
664 Register rn_; // base
665 Register rm_; // register offset
666 int32_t offset_; // valid if rm_ == no_reg
667 ShiftOp shift_op_;
668 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
669 AddrMode am_; // bits P, U, and W
670
671 friend class Assembler;
672};
673
danno@chromium.org169691d2013-07-15 08:01:13 +0000674
675// Class NeonMemOperand represents a memory operand in load and
676// store NEON instructions
677class NeonMemOperand BASE_EMBEDDED {
678 public:
679 // [rn {:align}] Offset
680 // [rn {:align}]! PostIndex
681 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
682
683 // [rn {:align}], rm PostIndex
684 explicit NeonMemOperand(Register rn, Register rm, int align = 0);
685
686 Register rn() const { return rn_; }
687 Register rm() const { return rm_; }
688 int align() const { return align_; }
689
690 private:
691 void SetAlignment(int align);
692
693 Register rn_; // base
694 Register rm_; // register increment
695 int align_;
696};
697
698
699// Class NeonListOperand represents a list of NEON registers
700class NeonListOperand BASE_EMBEDDED {
701 public:
702 explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
703 DoubleRegister base() const { return base_; }
704 NeonListType type() const { return type_; }
705 private:
706 DoubleRegister base_;
707 NeonListType type_;
708};
709
ager@chromium.org4af710e2009-09-15 12:20:11 +0000710extern const Instr kMovLrPc;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000711extern const Instr kLdrPCMask;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000712extern const Instr kLdrPCPattern;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000713extern const Instr kBlxRegMask;
714extern const Instr kBlxRegPattern;
danno@chromium.org88aa0582012-03-23 15:11:57 +0000715extern const Instr kBlxIp;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000716
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000717extern const Instr kMovMvnMask;
718extern const Instr kMovMvnPattern;
719extern const Instr kMovMvnFlip;
720
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000721extern const Instr kMovLeaveCCMask;
722extern const Instr kMovLeaveCCPattern;
723extern const Instr kMovwMask;
724extern const Instr kMovwPattern;
725extern const Instr kMovwLeaveCCFlip;
726
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000727extern const Instr kCmpCmnMask;
728extern const Instr kCmpCmnPattern;
729extern const Instr kCmpCmnFlip;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000730extern const Instr kAddSubFlip;
731extern const Instr kAndBicFlip;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000732
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +0000733struct VmovIndex {
734 unsigned char index;
735};
736const VmovIndex VmovIndexLo = { 0 };
737const VmovIndex VmovIndexHi = { 1 };
ager@chromium.org378b34e2011-01-28 08:04:38 +0000738
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000739class Assembler : public AssemblerBase {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000740 public:
741 // Create an assembler. Instructions and relocation information are emitted
742 // into a buffer, with the instructions starting from the beginning and the
743 // relocation information starting from the end of the buffer. See CodeDesc
744 // for a detailed comment on the layout (globals.h).
745 //
746 // If the provided buffer is NULL, the assembler allocates and grows its own
747 // buffer, and buffer_size determines the initial buffer size. The buffer is
748 // owned by the assembler and deallocated upon destruction of the assembler.
749 //
750 // If the provided buffer is not NULL, the assembler uses the provided buffer
751 // for code generation and assumes its size to be buffer_size. If the buffer
752 // is too small, a fatal error occurs. No deallocation of the buffer is done
753 // upon destruction of the assembler.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000754 Assembler(Isolate* isolate, void* buffer, int buffer_size);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000755 virtual ~Assembler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756
757 // GetCode emits any pending (non-emitted) code and fills the descriptor
758 // desc. GetCode() is idempotent; it returns the same result if no other
ager@chromium.org32912102009-01-16 10:38:43 +0000759 // Assembler functions are invoked in between GetCode() calls.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000760 void GetCode(CodeDesc* desc);
761
762 // Label operations & relative jumps (PPUM Appendix D)
763 //
764 // Takes a branch opcode (cc) and a label (L) and generates
765 // either a backward branch or a forward branch and links it
766 // to the label fixup chain. Usage:
767 //
768 // Label L; // unbound label
769 // j(cc, &L); // forward branch to unbound label
770 // bind(&L); // bind label to the current pc
771 // j(cc, &L); // backward branch to bound label
772 // bind(&L); // illegal: a label may be bound only once
773 //
774 // Note: The same Label can be used for forward and backward branches
775 // but it may be bound only once.
776
777 void bind(Label* L); // binds an unbound label L to the current code position
778
779 // Returns the branch offset to the given label from the current code position
780 // Links the label to the current position if it is still unbound
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000781 // Manages the jump elimination optimization if the second parameter is true.
782 int branch_offset(Label* L, bool jump_elimination_allowed);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000783
784 // Return the address in the constant pool of the code target address used by
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000785 // the branch/call instruction at pc, or the object in a mov.
786 INLINE(static Address target_pointer_address_at(Address pc));
787
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000788 // Read/Modify the code target address in the branch/call instruction at pc.
789 INLINE(static Address target_address_at(Address pc));
790 INLINE(static void set_target_address_at(Address pc, Address target));
791
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000792 // Return the code target address at a call site from the return address
793 // of that call in the instruction stream.
794 INLINE(static Address target_address_from_return_address(Address pc));
795
796 // Given the address of the beginning of a call, return the address
797 // in the instruction stream that the call will return from.
798 INLINE(static Address return_address_from_call_start(Address pc));
799
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000800 // This sets the branch destination (which is in the constant pool on ARM).
801 // This is for calls and branches within generated code.
danno@chromium.org88aa0582012-03-23 15:11:57 +0000802 inline static void deserialization_set_special_target_at(
803 Address constant_pool_entry, Address target);
ager@chromium.org3811b432009-10-28 14:53:37 +0000804
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000805 // This sets the branch destination (which is in the constant pool on ARM).
806 // This is for calls and branches to runtime code.
807 inline static void set_external_target_at(Address constant_pool_entry,
danno@chromium.org88aa0582012-03-23 15:11:57 +0000808 Address target);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000809
ager@chromium.org3811b432009-10-28 14:53:37 +0000810 // Here we are patching the address in the constant pool, not the actual call
811 // instruction. The address in the constant pool is the same size as a
812 // pointer.
danno@chromium.org88aa0582012-03-23 15:11:57 +0000813 static const int kSpecialTargetSize = kPointerSize;
ager@chromium.org3811b432009-10-28 14:53:37 +0000814
ager@chromium.org4af710e2009-09-15 12:20:11 +0000815 // Size of an instruction.
816 static const int kInstrSize = sizeof(Instr);
817
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000818 // Distance between start of patched return sequence and the emitted address
819 // to jump to.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000820 // Patched return sequence is:
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000821 // ldr ip, [pc, #0] @ emited address and start
822 // blx ip
823 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000824
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000825 // Distance between start of patched debug break slot and the emitted address
826 // to jump to.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000827 // Patched debug break slot code is:
828 // ldr ip, [pc, #0] @ emited address and start
829 // blx ip
830 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000831
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000832 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000833
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000834 // Difference between address of current opcode and value read from pc
835 // register.
836 static const int kPcLoadDelta = 8;
837
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000838 static const int kJSReturnSequenceInstructions = 4;
839 static const int kDebugBreakSlotInstructions = 3;
840 static const int kDebugBreakSlotLength =
841 kDebugBreakSlotInstructions * kInstrSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000842
843 // ---------------------------------------------------------------------------
844 // Code generation
845
846 // Insert the smallest number of nop instructions
847 // possible to align the pc offset to a multiple
848 // of m. m must be a power of 2 (>= 4).
849 void Align(int m);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000850 // Aligns code to something that's optimal for a jump target for the platform.
851 void CodeTargetAlign();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000852
853 // Branch instructions
854 void b(int branch_offset, Condition cond = al);
855 void bl(int branch_offset, Condition cond = al);
856 void blx(int branch_offset); // v5 and above
857 void blx(Register target, Condition cond = al); // v5 and above
858 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
859
860 // Convenience branch instructions using labels
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000861 void b(Label* L, Condition cond = al) {
862 b(branch_offset(L, cond == al), cond);
863 }
864 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
865 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
866 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
867 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000868
869 // Data-processing instructions
ager@chromium.org5c838252010-02-19 08:53:10 +0000870
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000871 void and_(Register dst, Register src1, const Operand& src2,
872 SBit s = LeaveCC, Condition cond = al);
873
874 void eor(Register dst, Register src1, const Operand& src2,
875 SBit s = LeaveCC, Condition cond = al);
876
877 void sub(Register dst, Register src1, const Operand& src2,
878 SBit s = LeaveCC, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000879 void sub(Register dst, Register src1, Register src2,
880 SBit s = LeaveCC, Condition cond = al) {
881 sub(dst, src1, Operand(src2), s, cond);
882 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000883
884 void rsb(Register dst, Register src1, const Operand& src2,
885 SBit s = LeaveCC, Condition cond = al);
886
887 void add(Register dst, Register src1, const Operand& src2,
888 SBit s = LeaveCC, Condition cond = al);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000889 void add(Register dst, Register src1, Register src2,
890 SBit s = LeaveCC, Condition cond = al) {
891 add(dst, src1, Operand(src2), s, cond);
892 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000893
894 void adc(Register dst, Register src1, const Operand& src2,
895 SBit s = LeaveCC, Condition cond = al);
896
897 void sbc(Register dst, Register src1, const Operand& src2,
898 SBit s = LeaveCC, Condition cond = al);
899
900 void rsc(Register dst, Register src1, const Operand& src2,
901 SBit s = LeaveCC, Condition cond = al);
902
903 void tst(Register src1, const Operand& src2, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000904 void tst(Register src1, Register src2, Condition cond = al) {
905 tst(src1, Operand(src2), cond);
906 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000907
908 void teq(Register src1, const Operand& src2, Condition cond = al);
909
910 void cmp(Register src1, const Operand& src2, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000911 void cmp(Register src1, Register src2, Condition cond = al) {
912 cmp(src1, Operand(src2), cond);
913 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000914 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000915
916 void cmn(Register src1, const Operand& src2, Condition cond = al);
917
918 void orr(Register dst, Register src1, const Operand& src2,
919 SBit s = LeaveCC, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000920 void orr(Register dst, Register src1, Register src2,
921 SBit s = LeaveCC, Condition cond = al) {
922 orr(dst, src1, Operand(src2), s, cond);
923 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000924
925 void mov(Register dst, const Operand& src,
926 SBit s = LeaveCC, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000927 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
928 mov(dst, Operand(src), s, cond);
929 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000930
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000931 // Load the position of the label relative to the generated code object
932 // pointer in a register.
933 void mov_label_offset(Register dst, Label* label);
934
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000935 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
936 // This may actually emit a different mov instruction, but on an ARMv7 it
937 // is guaranteed to only emit one instruction.
938 void movw(Register reg, uint32_t immediate, Condition cond = al);
939 // The constant for movt should be in the range 0-0xffff.
940 void movt(Register reg, uint32_t immediate, Condition cond = al);
941
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000942 void bic(Register dst, Register src1, const Operand& src2,
943 SBit s = LeaveCC, Condition cond = al);
944
945 void mvn(Register dst, const Operand& src,
946 SBit s = LeaveCC, Condition cond = al);
947
948 // Multiply instructions
949
950 void mla(Register dst, Register src1, Register src2, Register srcA,
951 SBit s = LeaveCC, Condition cond = al);
952
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000953 void mls(Register dst, Register src1, Register src2, Register srcA,
954 Condition cond = al);
955
956 void sdiv(Register dst, Register src1, Register src2,
957 Condition cond = al);
958
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000959 void mul(Register dst, Register src1, Register src2,
960 SBit s = LeaveCC, Condition cond = al);
961
962 void smlal(Register dstL, Register dstH, Register src1, Register src2,
963 SBit s = LeaveCC, Condition cond = al);
964
965 void smull(Register dstL, Register dstH, Register src1, Register src2,
966 SBit s = LeaveCC, Condition cond = al);
967
968 void umlal(Register dstL, Register dstH, Register src1, Register src2,
969 SBit s = LeaveCC, Condition cond = al);
970
971 void umull(Register dstL, Register dstH, Register src1, Register src2,
972 SBit s = LeaveCC, Condition cond = al);
973
974 // Miscellaneous arithmetic instructions
975
976 void clz(Register dst, Register src, Condition cond = al); // v5 and above
977
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000978 // Saturating instructions. v6 and above.
979
980 // Unsigned saturate.
981 //
982 // Saturate an optionally shifted signed value to an unsigned range.
983 //
984 // usat dst, #satpos, src
985 // usat dst, #satpos, src, lsl #sh
986 // usat dst, #satpos, src, asr #sh
987 //
988 // Register dst will contain:
989 //
990 // 0, if s < 0
991 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
992 // s, otherwise
993 //
994 // where s is the contents of src after shifting (if used.)
995 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
996
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000997 // Bitfield manipulation instructions. v7 and above.
998
999 void ubfx(Register dst, Register src, int lsb, int width,
1000 Condition cond = al);
1001
1002 void sbfx(Register dst, Register src, int lsb, int width,
1003 Condition cond = al);
1004
1005 void bfc(Register dst, int lsb, int width, Condition cond = al);
1006
1007 void bfi(Register dst, Register src, int lsb, int width,
1008 Condition cond = al);
1009
danno@chromium.org169691d2013-07-15 08:01:13 +00001010 void pkhbt(Register dst, Register src1, const Operand& src2,
1011 Condition cond = al);
1012
1013 void pkhtb(Register dst, Register src1, const Operand& src2,
1014 Condition cond = al);
1015
1016 void uxtb(Register dst, const Operand& src, Condition cond = al);
1017
1018 void uxtab(Register dst, Register src1, const Operand& src2,
1019 Condition cond = al);
1020
1021 void uxtb16(Register dst, const Operand& src, Condition cond = al);
1022
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001023 // Status register access instructions
1024
1025 void mrs(Register dst, SRegister s, Condition cond = al);
1026 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
1027
1028 // Load/Store instructions
1029 void ldr(Register dst, const MemOperand& src, Condition cond = al);
1030 void str(Register src, const MemOperand& dst, Condition cond = al);
1031 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
1032 void strb(Register src, const MemOperand& dst, Condition cond = al);
1033 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
1034 void strh(Register src, const MemOperand& dst, Condition cond = al);
1035 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
1036 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00001037 void ldrd(Register dst1,
1038 Register dst2,
1039 const MemOperand& src, Condition cond = al);
1040 void strd(Register src1,
1041 Register src2,
1042 const MemOperand& dst, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001043
danno@chromium.org169691d2013-07-15 08:01:13 +00001044 // Preload instructions
1045 void pld(const MemOperand& address);
1046
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001047 // Load/Store multiple instructions
1048 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
1049 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
1050
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001051 // Exception-generating instructions and debugging support
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001052 void stop(const char* msg,
1053 Condition cond = al,
1054 int32_t code = kDefaultStopCode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001055
1056 void bkpt(uint32_t imm16); // v5 and above
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001057 void svc(uint32_t imm24, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001058
1059 // Coprocessor instructions
1060
1061 void cdp(Coprocessor coproc, int opcode_1,
1062 CRegister crd, CRegister crn, CRegister crm,
1063 int opcode_2, Condition cond = al);
1064
1065 void cdp2(Coprocessor coproc, int opcode_1,
1066 CRegister crd, CRegister crn, CRegister crm,
1067 int opcode_2); // v5 and above
1068
1069 void mcr(Coprocessor coproc, int opcode_1,
1070 Register rd, CRegister crn, CRegister crm,
1071 int opcode_2 = 0, Condition cond = al);
1072
1073 void mcr2(Coprocessor coproc, int opcode_1,
1074 Register rd, CRegister crn, CRegister crm,
1075 int opcode_2 = 0); // v5 and above
1076
1077 void mrc(Coprocessor coproc, int opcode_1,
1078 Register rd, CRegister crn, CRegister crm,
1079 int opcode_2 = 0, Condition cond = al);
1080
1081 void mrc2(Coprocessor coproc, int opcode_1,
1082 Register rd, CRegister crn, CRegister crm,
1083 int opcode_2 = 0); // v5 and above
1084
1085 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1086 LFlag l = Short, Condition cond = al);
1087 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1088 LFlag l = Short, Condition cond = al);
1089
1090 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1091 LFlag l = Short); // v5 and above
1092 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1093 LFlag l = Short); // v5 and above
1094
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001095 // Support for VFP.
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001096 // All these APIs support S0 to S31 and D0 to D31.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001097
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001098 void vldr(const DwVfpRegister dst,
1099 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001100 int offset,
1101 const Condition cond = al);
1102 void vldr(const DwVfpRegister dst,
1103 const MemOperand& src,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001104 const Condition cond = al);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001105
1106 void vldr(const SwVfpRegister dst,
1107 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001108 int offset,
1109 const Condition cond = al);
1110 void vldr(const SwVfpRegister dst,
1111 const MemOperand& src,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001112 const Condition cond = al);
1113
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001114 void vstr(const DwVfpRegister src,
1115 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001116 int offset,
1117 const Condition cond = al);
1118 void vstr(const DwVfpRegister src,
1119 const MemOperand& dst,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001120 const Condition cond = al);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001121
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001122 void vstr(const SwVfpRegister src,
1123 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001124 int offset,
1125 const Condition cond = al);
1126 void vstr(const SwVfpRegister src,
1127 const MemOperand& dst,
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001128 const Condition cond = al);
1129
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001130 void vldm(BlockAddrMode am,
1131 Register base,
1132 DwVfpRegister first,
1133 DwVfpRegister last,
1134 Condition cond = al);
1135
1136 void vstm(BlockAddrMode am,
1137 Register base,
1138 DwVfpRegister first,
1139 DwVfpRegister last,
1140 Condition cond = al);
1141
1142 void vldm(BlockAddrMode am,
1143 Register base,
1144 SwVfpRegister first,
1145 SwVfpRegister last,
1146 Condition cond = al);
1147
1148 void vstm(BlockAddrMode am,
1149 Register base,
1150 SwVfpRegister first,
1151 SwVfpRegister last,
1152 Condition cond = al);
1153
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001154 void vmov(const DwVfpRegister dst,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001155 double imm,
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001156 const Register scratch = no_reg);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001157 void vmov(const SwVfpRegister dst,
1158 const SwVfpRegister src,
1159 const Condition cond = al);
1160 void vmov(const DwVfpRegister dst,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001161 const DwVfpRegister src,
1162 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001163 void vmov(const DwVfpRegister dst,
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +00001164 const VmovIndex index,
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001165 const Register src,
1166 const Condition cond = al);
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001167 void vmov(const Register dst,
1168 const VmovIndex index,
1169 const DwVfpRegister src,
1170 const Condition cond = al);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001171 void vmov(const DwVfpRegister dst,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001172 const Register src1,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001173 const Register src2,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001174 const Condition cond = al);
1175 void vmov(const Register dst1,
1176 const Register dst2,
1177 const DwVfpRegister src,
1178 const Condition cond = al);
1179 void vmov(const SwVfpRegister dst,
1180 const Register src,
1181 const Condition cond = al);
1182 void vmov(const Register dst,
1183 const SwVfpRegister src,
1184 const Condition cond = al);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001185 void vcvt_f64_s32(const DwVfpRegister dst,
1186 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001187 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001188 const Condition cond = al);
1189 void vcvt_f32_s32(const SwVfpRegister dst,
1190 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001191 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001192 const Condition cond = al);
1193 void vcvt_f64_u32(const DwVfpRegister dst,
1194 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001195 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001196 const Condition cond = al);
1197 void vcvt_s32_f64(const SwVfpRegister dst,
1198 const DwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001199 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001200 const Condition cond = al);
1201 void vcvt_u32_f64(const SwVfpRegister dst,
1202 const DwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001203 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001204 const Condition cond = al);
1205 void vcvt_f64_f32(const DwVfpRegister dst,
1206 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001207 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001208 const Condition cond = al);
1209 void vcvt_f32_f64(const SwVfpRegister dst,
1210 const DwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001211 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001212 const Condition cond = al);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001213 void vcvt_f64_s32(const DwVfpRegister dst,
1214 int fraction_bits,
1215 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001216
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001217 void vneg(const DwVfpRegister dst,
1218 const DwVfpRegister src,
1219 const Condition cond = al);
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001220 void vabs(const DwVfpRegister dst,
1221 const DwVfpRegister src,
1222 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001223 void vadd(const DwVfpRegister dst,
1224 const DwVfpRegister src1,
1225 const DwVfpRegister src2,
1226 const Condition cond = al);
1227 void vsub(const DwVfpRegister dst,
1228 const DwVfpRegister src1,
1229 const DwVfpRegister src2,
1230 const Condition cond = al);
1231 void vmul(const DwVfpRegister dst,
1232 const DwVfpRegister src1,
1233 const DwVfpRegister src2,
1234 const Condition cond = al);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001235 void vmla(const DwVfpRegister dst,
1236 const DwVfpRegister src1,
1237 const DwVfpRegister src2,
1238 const Condition cond = al);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001239 void vmls(const DwVfpRegister dst,
1240 const DwVfpRegister src1,
1241 const DwVfpRegister src2,
1242 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001243 void vdiv(const DwVfpRegister dst,
1244 const DwVfpRegister src1,
1245 const DwVfpRegister src2,
1246 const Condition cond = al);
1247 void vcmp(const DwVfpRegister src1,
1248 const DwVfpRegister src2,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001249 const Condition cond = al);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001250 void vcmp(const DwVfpRegister src1,
1251 const double src2,
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001252 const Condition cond = al);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001253 void vmrs(const Register dst,
1254 const Condition cond = al);
ager@chromium.org01fe7df2010-11-10 11:59:11 +00001255 void vmsr(const Register dst,
1256 const Condition cond = al);
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001257 void vsqrt(const DwVfpRegister dst,
1258 const DwVfpRegister src,
1259 const Condition cond = al);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001260
danno@chromium.org169691d2013-07-15 08:01:13 +00001261 // Support for NEON.
1262 // All these APIs support D0 to D31 and Q0 to Q15.
1263
1264 void vld1(NeonSize size,
1265 const NeonListOperand& dst,
1266 const NeonMemOperand& src);
1267 void vst1(NeonSize size,
1268 const NeonListOperand& src,
1269 const NeonMemOperand& dst);
1270 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1271
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001272 // Pseudo instructions
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001273
1274 // Different nop operations are used by the code generator to detect certain
1275 // states of the generated code.
1276 enum NopMarkerTypes {
1277 NON_MARKING_NOP = 0,
1278 DEBUG_BREAK_NOP,
1279 // IC markers.
1280 PROPERTY_ACCESS_INLINED,
1281 PROPERTY_ACCESS_INLINED_CONTEXT,
1282 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1283 // Helper values.
1284 LAST_CODE_MARKER,
1285 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1286 };
1287
1288 void nop(int type = 0); // 0 is the default non-marking type.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001289
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001290 void push(Register src, Condition cond = al) {
1291 str(src, MemOperand(sp, 4, NegPreIndex), cond);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001292 }
1293
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001294 void pop(Register dst, Condition cond = al) {
1295 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
mads.s.ager31e71382008-08-13 09:32:07 +00001296 }
1297
1298 void pop() {
1299 add(sp, sp, Operand(kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001300 }
1301
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001302 // Jump unconditionally to given label.
1303 void jmp(Label* L) { b(L, al); }
1304
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001305 static bool use_immediate_embedded_pointer_loads(
1306 const Assembler* assembler) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001307 return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
1308 (assembler == NULL || !assembler->predictable_code_size());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001309 }
1310
ager@chromium.org4af710e2009-09-15 12:20:11 +00001311 // Check the code size generated from label to here.
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001312 int SizeOfCodeGeneratedSince(Label* label) {
1313 return pc_offset() - label->pos();
1314 }
1315
1316 // Check the number of instructions generated from label to here.
1317 int InstructionsGeneratedSince(Label* label) {
1318 return SizeOfCodeGeneratedSince(label) / kInstrSize;
ager@chromium.org4af710e2009-09-15 12:20:11 +00001319 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001320
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001321 // Check whether an immediate fits an addressing mode 1 instruction.
1322 bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1323
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001324 // Class for scoping postponing the constant pool generation.
1325 class BlockConstPoolScope {
1326 public:
1327 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1328 assem_->StartBlockConstPool();
1329 }
1330 ~BlockConstPoolScope() {
1331 assem_->EndBlockConstPool();
1332 }
1333
1334 private:
1335 Assembler* assem_;
1336
1337 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1338 };
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001339
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001340 // Debugging
1341
ager@chromium.org4af710e2009-09-15 12:20:11 +00001342 // Mark address of the ExitJSFrame code.
1343 void RecordJSReturn();
1344
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001345 // Mark address of a debug break slot.
1346 void RecordDebugBreakSlot();
1347
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001348 // Record the AST id of the CallIC being compiled, so that it can be placed
1349 // in the relocation information.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001350 void SetRecordedAstId(TypeFeedbackId ast_id) {
1351 ASSERT(recorded_ast_id_.IsNone());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001352 recorded_ast_id_ = ast_id;
1353 }
1354
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001355 TypeFeedbackId RecordedAstId() {
1356 ASSERT(!recorded_ast_id_.IsNone());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001357 return recorded_ast_id_;
1358 }
1359
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001360 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001361
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001362 // Record a comment relocation entry that can be used by a disassembler.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001363 // Use --code-comments to enable.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001364 void RecordComment(const char* msg);
1365
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001366 // Record the emission of a constant pool.
1367 //
1368 // The emission of constant pool depends on the size of the code generated and
1369 // the number of RelocInfo recorded.
1370 // The Debug mechanism needs to map code offsets between two versions of a
1371 // function, compiled with and without debugger support (see for example
1372 // Debug::PrepareForBreakPoints()).
1373 // Compiling functions with debugger support generates additional code
1374 // (Debug::GenerateSlot()). This may affect the emission of the constant
1375 // pools and cause the version of the code with debugger support to have
1376 // constant pools generated in different places.
1377 // Recording the position and size of emitted constant pools allows to
1378 // correctly compute the offset mappings between the different versions of a
1379 // function in all situations.
1380 //
1381 // The parameter indicates the size of the constant pool (in bytes), including
1382 // the marker and branch over the data.
1383 void RecordConstPool(int size);
1384
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001385 // Writes a single byte or word of data in the code stream. Used
1386 // for inline tables, e.g., jump-tables. The constant pool should be
1387 // emitted before any use of db and dd to ensure that constant pools
1388 // are not emitted as part of the tables generated.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001389 void db(uint8_t data);
1390 void dd(uint32_t data);
1391
verwaest@chromium.org057bd502013-11-06 12:03:29 +00001392 // Emits the address of the code stub's first instruction.
1393 void emit_code_stub_address(Code* stub);
1394
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001395 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001396
1397 // Read/patch instructions
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001398 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1399 void instr_at_put(int pos, Instr instr) {
1400 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1401 }
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001402 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1403 static void instr_at_put(byte* pc, Instr instr) {
1404 *reinterpret_cast<Instr*>(pc) = instr;
1405 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001406 static Condition GetCondition(Instr instr);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001407 static bool IsBranch(Instr instr);
1408 static int GetBranchOffset(Instr instr);
1409 static bool IsLdrRegisterImmediate(Instr instr);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001410 static bool IsVldrDRegisterImmediate(Instr instr);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001411 static int GetLdrRegisterImmediateOffset(Instr instr);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001412 static int GetVldrDRegisterImmediateOffset(Instr instr);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001413 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001414 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
whesse@chromium.orgba5a61b2010-07-26 11:44:40 +00001415 static bool IsStrRegisterImmediate(Instr instr);
1416 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1417 static bool IsAddRegisterImmediate(Instr instr);
1418 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001419 static Register GetRd(Instr instr);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001420 static Register GetRn(Instr instr);
1421 static Register GetRm(Instr instr);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001422 static bool IsPush(Instr instr);
1423 static bool IsPop(Instr instr);
1424 static bool IsStrRegFpOffset(Instr instr);
1425 static bool IsLdrRegFpOffset(Instr instr);
1426 static bool IsStrRegFpNegOffset(Instr instr);
1427 static bool IsLdrRegFpNegOffset(Instr instr);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001428 static bool IsLdrPcImmediateOffset(Instr instr);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001429 static bool IsVldrDPcImmediateOffset(Instr instr);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001430 static bool IsTstImmediate(Instr instr);
1431 static bool IsCmpRegister(Instr instr);
1432 static bool IsCmpImmediate(Instr instr);
1433 static Register GetCmpImmediateRegister(Instr instr);
1434 static int GetCmpImmediateRawImmediate(Instr instr);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001435 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001436 static bool IsMovT(Instr instr);
1437 static bool IsMovW(Instr instr);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001438
danno@chromium.org40cb8782011-05-25 07:58:50 +00001439 // Constants in pools are accessed via pc relative addressing, which can
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001440 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1441 // PC-relative loads, thereby defining a maximum distance between the
1442 // instruction and the accessed constant.
1443 static const int kMaxDistToIntPool = 4*KB;
1444 static const int kMaxDistToFPPool = 1*KB;
1445 // All relocations could be integer, it therefore acts as the limit.
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001446 static const int kMaxNumPending32RelocInfo = kMaxDistToIntPool/kInstrSize;
1447 static const int kMaxNumPending64RelocInfo = kMaxDistToFPPool/kInstrSize;
danno@chromium.org40cb8782011-05-25 07:58:50 +00001448
whesse@chromium.org7b260152011-06-20 15:33:18 +00001449 // Postpone the generation of the constant pool for the specified number of
1450 // instructions.
1451 void BlockConstPoolFor(int instructions);
1452
1453 // Check if is time to emit a constant pool.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001454 void CheckConstPool(bool force_emit, bool require_jump);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001455
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001456 protected:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001457 // Relocation for a type-recording IC has the AST id added to it. This
1458 // member variable is a way to pass the information from the call site to
1459 // the relocation info.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001460 TypeFeedbackId recorded_ast_id_;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001461
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001462 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1463
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001464 // Decode branch instruction at pos and return branch target pos
1465 int target_at(int pos);
1466
1467 // Patch branch instruction at pos to branch to given branch target pos
1468 void target_at_put(int pos, int target_pos);
1469
whesse@chromium.org7b260152011-06-20 15:33:18 +00001470 // Prevent contant pool emission until EndBlockConstPool is called.
1471 // Call to this function can be nested but must be followed by an equal
1472 // number of call to EndBlockConstpool.
1473 void StartBlockConstPool() {
1474 if (const_pool_blocked_nesting_++ == 0) {
1475 // Prevent constant pool checks happening by setting the next check to
1476 // the biggest possible offset.
1477 next_buffer_check_ = kMaxInt;
1478 }
ager@chromium.org8bb60582008-12-11 12:02:20 +00001479 }
1480
whesse@chromium.org7b260152011-06-20 15:33:18 +00001481 // Resume constant pool emission. Need to be called as many time as
1482 // StartBlockConstPool to have an effect.
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001483 void EndBlockConstPool() {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001484 if (--const_pool_blocked_nesting_ == 0) {
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001485#ifdef DEBUG
1486 // Max pool start (if we need a jump and an alignment).
1487 int start = pc_offset() + kInstrSize + 2 * kPointerSize;
whesse@chromium.org7b260152011-06-20 15:33:18 +00001488 // Check the constant pool hasn't been blocked for too long.
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001489 ASSERT((num_pending_32_bit_reloc_info_ == 0) ||
1490 (start + num_pending_64_bit_reloc_info_ * kDoubleSize <
1491 (first_const_pool_32_use_ + kMaxDistToIntPool)));
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001492 ASSERT((num_pending_64_bit_reloc_info_ == 0) ||
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001493 (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
1494#endif
whesse@chromium.org7b260152011-06-20 15:33:18 +00001495 // Two cases:
1496 // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1497 // still blocked
1498 // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1499 // trigger a check.
1500 next_buffer_check_ = no_const_pool_before_;
1501 }
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001502 }
whesse@chromium.org7b260152011-06-20 15:33:18 +00001503
1504 bool is_const_pool_blocked() const {
1505 return (const_pool_blocked_nesting_ > 0) ||
1506 (pc_offset() < no_const_pool_before_);
1507 }
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001508
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001509 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001510 int next_buffer_check_; // pc offset of next buffer check
1511
1512 // Code generation
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001513 // The relocation writer's position is at least kGap bytes below the end of
1514 // the generated instructions. This is so that multi-instruction sequences do
1515 // not have to check for overflow. The same is true for writes of large
1516 // relocation info entries.
1517 static const int kGap = 32;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001518
1519 // Constant pool generation
1520 // Pools are emitted in the instruction stream, preferably after unconditional
1521 // jumps or after returns from functions (in dead code locations).
1522 // If a long code sequence does not contain unconditional jumps, it is
1523 // necessary to emit the constant pool before the pool gets too far from the
1524 // location it is accessed from. In this case, we emit a jump over the emitted
1525 // constant pool.
1526 // Constants in the pool may be addresses of functions that gets relocated;
1527 // if so, a relocation info entry is associated to the constant pool entry.
1528
1529 // Repeated checking whether the constant pool should be emitted is rather
1530 // expensive. By default we only check again once a number of instructions
1531 // has been generated. That also means that the sizing of the buffers is not
1532 // an exact science, and that we rely on some slop to not overrun buffers.
whesse@chromium.org7b260152011-06-20 15:33:18 +00001533 static const int kCheckPoolIntervalInst = 32;
1534 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001535
1536
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001537 // Emission of the constant pool may be blocked in some code sequences.
1538 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1539 int no_const_pool_before_; // Block emission before this pc offset.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001540
whesse@chromium.org7b260152011-06-20 15:33:18 +00001541 // Keep track of the first instruction requiring a constant pool entry
1542 // since the previous constant pool was emitted.
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001543 int first_const_pool_32_use_;
1544 int first_const_pool_64_use_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001545
1546 // Relocation info generation
1547 // Each relocation is encoded as a variable size value
1548 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1549 RelocInfoWriter reloc_info_writer;
whesse@chromium.org7b260152011-06-20 15:33:18 +00001550
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001551 // Relocation info records are also used during code generation as temporary
1552 // containers for constants and code target addresses until they are emitted
1553 // to the constant pool. These pending relocation info records are temporarily
1554 // stored in a separate buffer until a constant pool is emitted.
1555 // If every instruction in a long sequence is accessing the pool, we need one
1556 // pending relocation entry per instruction.
whesse@chromium.org7b260152011-06-20 15:33:18 +00001557
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001558 // The buffers of pending relocation info.
1559 RelocInfo pending_32_bit_reloc_info_[kMaxNumPending32RelocInfo];
1560 RelocInfo pending_64_bit_reloc_info_[kMaxNumPending64RelocInfo];
1561 // Number of pending reloc info entries in the 32 bits buffer.
1562 int num_pending_32_bit_reloc_info_;
1563 // Number of pending reloc info entries in the 64 bits buffer.
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001564 int num_pending_64_bit_reloc_info_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001565
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001566 // The bound position, before this we cannot do instruction elimination.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001567 int last_bound_pos_;
1568
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001569 // Code emission
1570 inline void CheckBuffer();
1571 void GrowBuffer();
1572 inline void emit(Instr x);
1573
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001574 // 32-bit immediate values
1575 void move_32_bit_immediate(Condition cond,
1576 Register rd,
1577 SBit s,
1578 const Operand& x);
1579
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001580 // Instruction generation
1581 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1582 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1583 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1584 void addrmod4(Instr instr, Register rn, RegList rl);
1585 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1586
1587 // Labels
1588 void print(Label* L);
1589 void bind_to(Label* L, int pos);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001590 void next(Label* L);
1591
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001592 enum UseConstantPoolMode {
1593 USE_CONSTANT_POOL,
1594 DONT_USE_CONSTANT_POOL
1595 };
1596
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001597 // Record reloc info for current pc_
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001598 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0,
1599 UseConstantPoolMode mode = USE_CONSTANT_POOL);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001600 void RecordRelocInfo(double data);
1601 void RecordRelocInfoConstantPoolEntryHelper(const RelocInfo& rinfo);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001602
ager@chromium.org4af710e2009-09-15 12:20:11 +00001603 friend class RelocInfo;
1604 friend class CodePatcher;
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001605 friend class BlockConstPoolScope;
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001606
1607 PositionsRecorder positions_recorder_;
1608 friend class PositionsRecorder;
1609 friend class EnsureSpace;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001610};
1611
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001612
1613class EnsureSpace BASE_EMBEDDED {
1614 public:
1615 explicit EnsureSpace(Assembler* assembler) {
1616 assembler->CheckBuffer();
1617 }
1618};
1619
1620
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001621} } // namespace v8::internal
1622
ager@chromium.org5ec48922009-05-05 07:25:34 +00001623#endif // V8_ARM_ASSEMBLER_ARM_H_