blob: 137dd73e992549c5b3069b218b5ef8a2f5480fc7 [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();
machenbach@chromium.orgaf9cfcb2013-11-19 11:05:18 +0000288 inline static int NumReservedRegisters();
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000289 inline static int NumAllocatableRegisters();
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000290
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000291 inline static int ToAllocationIndex(DwVfpRegister reg);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000292 static const char* AllocationIndexToString(int index);
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000293 inline static DwVfpRegister FromAllocationIndex(int index);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000294
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000295 static DwVfpRegister from_code(int code) {
296 DwVfpRegister r = { code };
297 return r;
298 }
299
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000300 bool is_valid() const {
danno@chromium.org94b0d6f2013-02-04 13:33:20 +0000301 return 0 <= code_ && code_ < kMaxNumRegisters;
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000302 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000303 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000304 int code() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000305 ASSERT(is_valid());
306 return code_;
307 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000308 int bit() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000309 ASSERT(is_valid());
310 return 1 << code_;
311 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000312 void split_code(int* vm, int* m) const {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000313 ASSERT(is_valid());
314 *m = (code_ & 0x10) >> 4;
315 *vm = code_ & 0x0F;
316 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000317
318 int code_;
319};
320
321
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000322typedef DwVfpRegister DoubleRegister;
323
324
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000325// Double word VFP register d0-15.
326struct LowDwVfpRegister {
327 public:
328 static const int kMaxNumLowRegisters = 16;
329 operator DwVfpRegister() const {
330 DwVfpRegister r = { code_ };
331 return r;
332 }
333 static LowDwVfpRegister from_code(int code) {
334 LowDwVfpRegister r = { code };
335 return r;
336 }
337
338 bool is_valid() const {
339 return 0 <= code_ && code_ < kMaxNumLowRegisters;
340 }
341 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
342 bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
343 int code() const {
344 ASSERT(is_valid());
345 return code_;
346 }
347 SwVfpRegister low() const {
348 SwVfpRegister reg;
349 reg.code_ = code_ * 2;
350
351 ASSERT(reg.is_valid());
352 return reg;
353 }
354 SwVfpRegister high() const {
355 SwVfpRegister reg;
356 reg.code_ = (code_ * 2) + 1;
357
358 ASSERT(reg.is_valid());
359 return reg;
360 }
361
362 int code_;
363};
364
365
danno@chromium.org169691d2013-07-15 08:01:13 +0000366// Quad word NEON register.
367struct QwNeonRegister {
368 static const int kMaxNumRegisters = 16;
369
370 static QwNeonRegister from_code(int code) {
371 QwNeonRegister r = { code };
372 return r;
373 }
374
375 bool is_valid() const {
376 return (0 <= code_) && (code_ < kMaxNumRegisters);
377 }
378 bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
379 int code() const {
380 ASSERT(is_valid());
381 return code_;
382 }
383 void split_code(int* vm, int* m) const {
384 ASSERT(is_valid());
385 *m = (code_ & 0x10) >> 4;
386 *vm = code_ & 0x0F;
387 }
388
389 int code_;
390};
391
392
393typedef QwNeonRegister QuadRegister;
394
395
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000396// Support for the VFP registers s0 to s31 (d0 to d15).
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000397// Note that "s(N):s(N+1)" is the same as "d(N/2)".
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000398const SwVfpRegister s0 = { 0 };
399const SwVfpRegister s1 = { 1 };
400const SwVfpRegister s2 = { 2 };
401const SwVfpRegister s3 = { 3 };
402const SwVfpRegister s4 = { 4 };
403const SwVfpRegister s5 = { 5 };
404const SwVfpRegister s6 = { 6 };
405const SwVfpRegister s7 = { 7 };
406const SwVfpRegister s8 = { 8 };
407const SwVfpRegister s9 = { 9 };
408const SwVfpRegister s10 = { 10 };
409const SwVfpRegister s11 = { 11 };
410const SwVfpRegister s12 = { 12 };
411const SwVfpRegister s13 = { 13 };
412const SwVfpRegister s14 = { 14 };
413const SwVfpRegister s15 = { 15 };
414const SwVfpRegister s16 = { 16 };
415const SwVfpRegister s17 = { 17 };
416const SwVfpRegister s18 = { 18 };
417const SwVfpRegister s19 = { 19 };
418const SwVfpRegister s20 = { 20 };
419const SwVfpRegister s21 = { 21 };
420const SwVfpRegister s22 = { 22 };
421const SwVfpRegister s23 = { 23 };
422const SwVfpRegister s24 = { 24 };
423const SwVfpRegister s25 = { 25 };
424const SwVfpRegister s26 = { 26 };
425const SwVfpRegister s27 = { 27 };
426const SwVfpRegister s28 = { 28 };
427const SwVfpRegister s29 = { 29 };
428const SwVfpRegister s30 = { 30 };
429const SwVfpRegister s31 = { 31 };
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000430
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000431const DwVfpRegister no_dreg = { -1 };
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000432const LowDwVfpRegister d0 = { 0 };
433const LowDwVfpRegister d1 = { 1 };
434const LowDwVfpRegister d2 = { 2 };
435const LowDwVfpRegister d3 = { 3 };
436const LowDwVfpRegister d4 = { 4 };
437const LowDwVfpRegister d5 = { 5 };
438const LowDwVfpRegister d6 = { 6 };
439const LowDwVfpRegister d7 = { 7 };
440const LowDwVfpRegister d8 = { 8 };
441const LowDwVfpRegister d9 = { 9 };
442const LowDwVfpRegister d10 = { 10 };
443const LowDwVfpRegister d11 = { 11 };
444const LowDwVfpRegister d12 = { 12 };
445const LowDwVfpRegister d13 = { 13 };
446const LowDwVfpRegister d14 = { 14 };
447const LowDwVfpRegister d15 = { 15 };
yangguo@chromium.org003650e2013-01-24 16:31:08 +0000448const DwVfpRegister d16 = { 16 };
449const DwVfpRegister d17 = { 17 };
450const DwVfpRegister d18 = { 18 };
451const DwVfpRegister d19 = { 19 };
452const DwVfpRegister d20 = { 20 };
453const DwVfpRegister d21 = { 21 };
454const DwVfpRegister d22 = { 22 };
455const DwVfpRegister d23 = { 23 };
456const DwVfpRegister d24 = { 24 };
457const DwVfpRegister d25 = { 25 };
458const DwVfpRegister d26 = { 26 };
459const DwVfpRegister d27 = { 27 };
460const DwVfpRegister d28 = { 28 };
461const DwVfpRegister d29 = { 29 };
462const DwVfpRegister d30 = { 30 };
463const DwVfpRegister d31 = { 31 };
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000464
danno@chromium.org169691d2013-07-15 08:01:13 +0000465const QwNeonRegister q0 = { 0 };
466const QwNeonRegister q1 = { 1 };
467const QwNeonRegister q2 = { 2 };
468const QwNeonRegister q3 = { 3 };
469const QwNeonRegister q4 = { 4 };
470const QwNeonRegister q5 = { 5 };
471const QwNeonRegister q6 = { 6 };
472const QwNeonRegister q7 = { 7 };
473const QwNeonRegister q8 = { 8 };
474const QwNeonRegister q9 = { 9 };
475const QwNeonRegister q10 = { 10 };
476const QwNeonRegister q11 = { 11 };
477const QwNeonRegister q12 = { 12 };
478const QwNeonRegister q13 = { 13 };
479const QwNeonRegister q14 = { 14 };
480const QwNeonRegister q15 = { 15 };
481
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +0000482
yangguo@chromium.org659ceec2012-01-26 07:37:54 +0000483// Aliases for double registers. Defined using #define instead of
484// "static const DwVfpRegister&" because Clang complains otherwise when a
485// compilation unit that includes this header doesn't use the variables.
486#define kFirstCalleeSavedDoubleReg d8
487#define kLastCalleeSavedDoubleReg d15
488#define kDoubleRegZero d14
489#define kScratchDoubleReg d15
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000490
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000491
492// Coprocessor register
493struct CRegister {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000494 bool is_valid() const { return 0 <= code_ && code_ < 16; }
495 bool is(CRegister creg) const { return code_ == creg.code_; }
496 int code() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000497 ASSERT(is_valid());
498 return code_;
499 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000500 int bit() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501 ASSERT(is_valid());
502 return 1 << code_;
503 }
504
ager@chromium.org5c838252010-02-19 08:53:10 +0000505 // Unfortunately we can't make this private in a struct.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000506 int code_;
507};
508
509
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000510const CRegister no_creg = { -1 };
511
512const CRegister cr0 = { 0 };
513const CRegister cr1 = { 1 };
514const CRegister cr2 = { 2 };
515const CRegister cr3 = { 3 };
516const CRegister cr4 = { 4 };
517const CRegister cr5 = { 5 };
518const CRegister cr6 = { 6 };
519const CRegister cr7 = { 7 };
520const CRegister cr8 = { 8 };
521const CRegister cr9 = { 9 };
522const CRegister cr10 = { 10 };
523const CRegister cr11 = { 11 };
524const CRegister cr12 = { 12 };
525const CRegister cr13 = { 13 };
526const CRegister cr14 = { 14 };
527const CRegister cr15 = { 15 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528
529
530// Coprocessor number
531enum Coprocessor {
532 p0 = 0,
533 p1 = 1,
534 p2 = 2,
535 p3 = 3,
536 p4 = 4,
537 p5 = 5,
538 p6 = 6,
539 p7 = 7,
540 p8 = 8,
541 p9 = 9,
542 p10 = 10,
543 p11 = 11,
544 p12 = 12,
545 p13 = 13,
546 p14 = 14,
547 p15 = 15
548};
549
550
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000551// -----------------------------------------------------------------------------
552// Machine instruction Operands
553
554// Class Operand represents a shifter operand in data processing instructions
555class Operand BASE_EMBEDDED {
556 public:
557 // immediate
ager@chromium.org236ad962008-09-25 09:45:57 +0000558 INLINE(explicit Operand(int32_t immediate,
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000559 RelocInfo::Mode rmode = RelocInfo::NONE32));
ricow@chromium.orgddd545c2011-08-24 12:02:41 +0000560 INLINE(static Operand Zero()) {
561 return Operand(static_cast<int32_t>(0));
562 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000563 INLINE(explicit Operand(const ExternalReference& f));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000564 explicit Operand(Handle<Object> handle);
565 INLINE(explicit Operand(Smi* value));
566
567 // rm
568 INLINE(explicit Operand(Register rm));
569
570 // rm <shift_op> shift_imm
571 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000572 INLINE(static Operand SmiUntag(Register rm)) {
573 return Operand(rm, ASR, kSmiTagSize);
574 }
575 INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
576 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
577 return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
578 }
579 INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
580 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
581 return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
582 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000583
584 // rm <shift_op> rs
585 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
586
mads.s.ager31e71382008-08-13 09:32:07 +0000587 // Return true if this is a register operand.
588 INLINE(bool is_reg() const);
589
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000590 // Return true if this operand fits in one instruction so that no
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000591 // 2-instruction solution with a load into the ip register is necessary. If
592 // the instruction this operand is used for is a MOV or MVN instruction the
593 // actual instruction to use is required for this calculation. For other
594 // instructions instr is ignored.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +0000595 bool is_single_instruction(const Assembler* assembler, Instr instr = 0) const;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000596 bool must_output_reloc_info(const Assembler* assembler) const;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000597
598 inline int32_t immediate() const {
599 ASSERT(!rm_.is_valid());
600 return imm32_;
601 }
602
mads.s.ager31e71382008-08-13 09:32:07 +0000603 Register rm() const { return rm_; }
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000604 Register rs() const { return rs_; }
605 ShiftOp shift_op() const { return shift_op_; }
mads.s.ager31e71382008-08-13 09:32:07 +0000606
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000607 private:
608 Register rm_;
609 Register rs_;
610 ShiftOp shift_op_;
611 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
612 int32_t imm32_; // valid if rm_ == no_reg
ager@chromium.org236ad962008-09-25 09:45:57 +0000613 RelocInfo::Mode rmode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000614
615 friend class Assembler;
616};
617
618
619// Class MemOperand represents a memory operand in load and store instructions
620class MemOperand BASE_EMBEDDED {
621 public:
622 // [rn +/- offset] Offset/NegOffset
623 // [rn +/- offset]! PreIndex/NegPreIndex
624 // [rn], +/- offset PostIndex/NegPostIndex
625 // offset is any signed 32-bit value; offset is first loaded to register ip if
626 // it does not fit the addressing mode (12-bit unsigned and sign bit)
627 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
628
629 // [rn +/- rm] Offset/NegOffset
630 // [rn +/- rm]! PreIndex/NegPreIndex
631 // [rn], +/- rm PostIndex/NegPostIndex
632 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
633
634 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
635 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
636 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
637 explicit MemOperand(Register rn, Register rm,
638 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +0000639 INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
640 Register key,
641 AddrMode am = Offset)) {
642 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
643 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
644 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000645
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000646 void set_offset(int32_t offset) {
647 ASSERT(rm_.is(no_reg));
648 offset_ = offset;
649 }
650
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000651 uint32_t offset() const {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000652 ASSERT(rm_.is(no_reg));
653 return offset_;
654 }
655
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000656 Register rn() const { return rn_; }
657 Register rm() const { return rm_; }
ager@chromium.org04921a82011-06-27 13:21:41 +0000658 AddrMode am() const { return am_; }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000659
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000660 bool OffsetIsUint12Encodable() const {
661 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
662 }
663
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000664 private:
665 Register rn_; // base
666 Register rm_; // register offset
667 int32_t offset_; // valid if rm_ == no_reg
668 ShiftOp shift_op_;
669 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
670 AddrMode am_; // bits P, U, and W
671
672 friend class Assembler;
673};
674
danno@chromium.org169691d2013-07-15 08:01:13 +0000675
676// Class NeonMemOperand represents a memory operand in load and
677// store NEON instructions
678class NeonMemOperand BASE_EMBEDDED {
679 public:
680 // [rn {:align}] Offset
681 // [rn {:align}]! PostIndex
682 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
683
684 // [rn {:align}], rm PostIndex
685 explicit NeonMemOperand(Register rn, Register rm, int align = 0);
686
687 Register rn() const { return rn_; }
688 Register rm() const { return rm_; }
689 int align() const { return align_; }
690
691 private:
692 void SetAlignment(int align);
693
694 Register rn_; // base
695 Register rm_; // register increment
696 int align_;
697};
698
699
700// Class NeonListOperand represents a list of NEON registers
701class NeonListOperand BASE_EMBEDDED {
702 public:
703 explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
704 DoubleRegister base() const { return base_; }
705 NeonListType type() const { return type_; }
706 private:
707 DoubleRegister base_;
708 NeonListType type_;
709};
710
ager@chromium.org4af710e2009-09-15 12:20:11 +0000711extern const Instr kMovLrPc;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000712extern const Instr kLdrPCMask;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000713extern const Instr kLdrPCPattern;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000714extern const Instr kBlxRegMask;
715extern const Instr kBlxRegPattern;
danno@chromium.org88aa0582012-03-23 15:11:57 +0000716extern const Instr kBlxIp;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000717
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000718extern const Instr kMovMvnMask;
719extern const Instr kMovMvnPattern;
720extern const Instr kMovMvnFlip;
721
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000722extern const Instr kMovLeaveCCMask;
723extern const Instr kMovLeaveCCPattern;
724extern const Instr kMovwMask;
725extern const Instr kMovwPattern;
726extern const Instr kMovwLeaveCCFlip;
727
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000728extern const Instr kCmpCmnMask;
729extern const Instr kCmpCmnPattern;
730extern const Instr kCmpCmnFlip;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000731extern const Instr kAddSubFlip;
732extern const Instr kAndBicFlip;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000733
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +0000734struct VmovIndex {
735 unsigned char index;
736};
737const VmovIndex VmovIndexLo = { 0 };
738const VmovIndex VmovIndexHi = { 1 };
ager@chromium.org378b34e2011-01-28 08:04:38 +0000739
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000740class Assembler : public AssemblerBase {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000741 public:
742 // Create an assembler. Instructions and relocation information are emitted
743 // into a buffer, with the instructions starting from the beginning and the
744 // relocation information starting from the end of the buffer. See CodeDesc
745 // for a detailed comment on the layout (globals.h).
746 //
747 // If the provided buffer is NULL, the assembler allocates and grows its own
748 // buffer, and buffer_size determines the initial buffer size. The buffer is
749 // owned by the assembler and deallocated upon destruction of the assembler.
750 //
751 // If the provided buffer is not NULL, the assembler uses the provided buffer
752 // for code generation and assumes its size to be buffer_size. If the buffer
753 // is too small, a fatal error occurs. No deallocation of the buffer is done
754 // upon destruction of the assembler.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000755 Assembler(Isolate* isolate, void* buffer, int buffer_size);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000756 virtual ~Assembler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000757
758 // GetCode emits any pending (non-emitted) code and fills the descriptor
759 // desc. GetCode() is idempotent; it returns the same result if no other
ager@chromium.org32912102009-01-16 10:38:43 +0000760 // Assembler functions are invoked in between GetCode() calls.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000761 void GetCode(CodeDesc* desc);
762
763 // Label operations & relative jumps (PPUM Appendix D)
764 //
765 // Takes a branch opcode (cc) and a label (L) and generates
766 // either a backward branch or a forward branch and links it
767 // to the label fixup chain. Usage:
768 //
769 // Label L; // unbound label
770 // j(cc, &L); // forward branch to unbound label
771 // bind(&L); // bind label to the current pc
772 // j(cc, &L); // backward branch to bound label
773 // bind(&L); // illegal: a label may be bound only once
774 //
775 // Note: The same Label can be used for forward and backward branches
776 // but it may be bound only once.
777
778 void bind(Label* L); // binds an unbound label L to the current code position
779
780 // Returns the branch offset to the given label from the current code position
781 // Links the label to the current position if it is still unbound
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000782 // Manages the jump elimination optimization if the second parameter is true.
783 int branch_offset(Label* L, bool jump_elimination_allowed);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000784
785 // Return the address in the constant pool of the code target address used by
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000786 // the branch/call instruction at pc, or the object in a mov.
787 INLINE(static Address target_pointer_address_at(Address pc));
788
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000789 // Read/Modify the code target address in the branch/call instruction at pc.
790 INLINE(static Address target_address_at(Address pc));
791 INLINE(static void set_target_address_at(Address pc, Address target));
792
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000793 // Return the code target address at a call site from the return address
794 // of that call in the instruction stream.
795 INLINE(static Address target_address_from_return_address(Address pc));
796
797 // Given the address of the beginning of a call, return the address
798 // in the instruction stream that the call will return from.
799 INLINE(static Address return_address_from_call_start(Address pc));
800
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000801 // This sets the branch destination (which is in the constant pool on ARM).
802 // This is for calls and branches within generated code.
danno@chromium.org88aa0582012-03-23 15:11:57 +0000803 inline static void deserialization_set_special_target_at(
804 Address constant_pool_entry, Address target);
ager@chromium.org3811b432009-10-28 14:53:37 +0000805
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000806 // This sets the branch destination (which is in the constant pool on ARM).
807 // This is for calls and branches to runtime code.
808 inline static void set_external_target_at(Address constant_pool_entry,
danno@chromium.org88aa0582012-03-23 15:11:57 +0000809 Address target);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000810
ager@chromium.org3811b432009-10-28 14:53:37 +0000811 // Here we are patching the address in the constant pool, not the actual call
812 // instruction. The address in the constant pool is the same size as a
813 // pointer.
danno@chromium.org88aa0582012-03-23 15:11:57 +0000814 static const int kSpecialTargetSize = kPointerSize;
ager@chromium.org3811b432009-10-28 14:53:37 +0000815
ager@chromium.org4af710e2009-09-15 12:20:11 +0000816 // Size of an instruction.
817 static const int kInstrSize = sizeof(Instr);
818
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000819 // Distance between start of patched return sequence and the emitted address
820 // to jump to.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000821 // Patched return sequence is:
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000822 // ldr ip, [pc, #0] @ emited address and start
823 // blx ip
824 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000825
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000826 // Distance between start of patched debug break slot and the emitted address
827 // to jump to.
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000828 // Patched debug break slot code is:
829 // ldr ip, [pc, #0] @ emited address and start
830 // blx ip
831 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000832
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000833 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize;
rossberg@chromium.org89e18f52012-10-22 13:09:53 +0000834
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000835 // Difference between address of current opcode and value read from pc
836 // register.
837 static const int kPcLoadDelta = 8;
838
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000839 static const int kJSReturnSequenceInstructions = 4;
840 static const int kDebugBreakSlotInstructions = 3;
841 static const int kDebugBreakSlotLength =
842 kDebugBreakSlotInstructions * kInstrSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000843
844 // ---------------------------------------------------------------------------
845 // Code generation
846
847 // Insert the smallest number of nop instructions
848 // possible to align the pc offset to a multiple
849 // of m. m must be a power of 2 (>= 4).
850 void Align(int m);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000851 // Aligns code to something that's optimal for a jump target for the platform.
852 void CodeTargetAlign();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000853
854 // Branch instructions
855 void b(int branch_offset, Condition cond = al);
856 void bl(int branch_offset, Condition cond = al);
857 void blx(int branch_offset); // v5 and above
858 void blx(Register target, Condition cond = al); // v5 and above
859 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
860
861 // Convenience branch instructions using labels
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000862 void b(Label* L, Condition cond = al) {
863 b(branch_offset(L, cond == al), cond);
864 }
865 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
866 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
867 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
868 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000869
870 // Data-processing instructions
ager@chromium.org5c838252010-02-19 08:53:10 +0000871
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000872 void and_(Register dst, Register src1, const Operand& src2,
873 SBit s = LeaveCC, Condition cond = al);
874
875 void eor(Register dst, Register src1, const Operand& src2,
876 SBit s = LeaveCC, Condition cond = al);
877
878 void sub(Register dst, Register src1, const Operand& src2,
879 SBit s = LeaveCC, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000880 void sub(Register dst, Register src1, Register src2,
881 SBit s = LeaveCC, Condition cond = al) {
882 sub(dst, src1, Operand(src2), s, cond);
883 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000884
885 void rsb(Register dst, Register src1, const Operand& src2,
886 SBit s = LeaveCC, Condition cond = al);
887
888 void add(Register dst, Register src1, const Operand& src2,
889 SBit s = LeaveCC, Condition cond = al);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000890 void add(Register dst, Register src1, Register src2,
891 SBit s = LeaveCC, Condition cond = al) {
892 add(dst, src1, Operand(src2), s, cond);
893 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000894
895 void adc(Register dst, Register src1, const Operand& src2,
896 SBit s = LeaveCC, Condition cond = al);
897
898 void sbc(Register dst, Register src1, const Operand& src2,
899 SBit s = LeaveCC, Condition cond = al);
900
901 void rsc(Register dst, Register src1, const Operand& src2,
902 SBit s = LeaveCC, Condition cond = al);
903
904 void tst(Register src1, const Operand& src2, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000905 void tst(Register src1, Register src2, Condition cond = al) {
906 tst(src1, Operand(src2), cond);
907 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000908
909 void teq(Register src1, const Operand& src2, Condition cond = al);
910
911 void cmp(Register src1, const Operand& src2, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000912 void cmp(Register src1, Register src2, Condition cond = al) {
913 cmp(src1, Operand(src2), cond);
914 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000915 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000916
917 void cmn(Register src1, const Operand& src2, Condition cond = al);
918
919 void orr(Register dst, Register src1, const Operand& src2,
920 SBit s = LeaveCC, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000921 void orr(Register dst, Register src1, Register src2,
922 SBit s = LeaveCC, Condition cond = al) {
923 orr(dst, src1, Operand(src2), s, cond);
924 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000925
926 void mov(Register dst, const Operand& src,
927 SBit s = LeaveCC, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000928 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
929 mov(dst, Operand(src), s, cond);
930 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000931
dslomov@chromium.org4a35c5a2013-09-13 07:28:52 +0000932 // Load the position of the label relative to the generated code object
933 // pointer in a register.
934 void mov_label_offset(Register dst, Label* label);
935
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000936 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
937 // This may actually emit a different mov instruction, but on an ARMv7 it
938 // is guaranteed to only emit one instruction.
939 void movw(Register reg, uint32_t immediate, Condition cond = al);
940 // The constant for movt should be in the range 0-0xffff.
941 void movt(Register reg, uint32_t immediate, Condition cond = al);
942
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000943 void bic(Register dst, Register src1, const Operand& src2,
944 SBit s = LeaveCC, Condition cond = al);
945
946 void mvn(Register dst, const Operand& src,
947 SBit s = LeaveCC, Condition cond = al);
948
949 // Multiply instructions
950
951 void mla(Register dst, Register src1, Register src2, Register srcA,
952 SBit s = LeaveCC, Condition cond = al);
953
verwaest@chromium.org33e09c82012-10-10 17:07:22 +0000954 void mls(Register dst, Register src1, Register src2, Register srcA,
955 Condition cond = al);
956
957 void sdiv(Register dst, Register src1, Register src2,
958 Condition cond = al);
959
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000960 void mul(Register dst, Register src1, Register src2,
961 SBit s = LeaveCC, Condition cond = al);
962
963 void smlal(Register dstL, Register dstH, Register src1, Register src2,
964 SBit s = LeaveCC, Condition cond = al);
965
966 void smull(Register dstL, Register dstH, Register src1, Register src2,
967 SBit s = LeaveCC, Condition cond = al);
968
969 void umlal(Register dstL, Register dstH, Register src1, Register src2,
970 SBit s = LeaveCC, Condition cond = al);
971
972 void umull(Register dstL, Register dstH, Register src1, Register src2,
973 SBit s = LeaveCC, Condition cond = al);
974
975 // Miscellaneous arithmetic instructions
976
977 void clz(Register dst, Register src, Condition cond = al); // v5 and above
978
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000979 // Saturating instructions. v6 and above.
980
981 // Unsigned saturate.
982 //
983 // Saturate an optionally shifted signed value to an unsigned range.
984 //
985 // usat dst, #satpos, src
986 // usat dst, #satpos, src, lsl #sh
987 // usat dst, #satpos, src, asr #sh
988 //
989 // Register dst will contain:
990 //
991 // 0, if s < 0
992 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
993 // s, otherwise
994 //
995 // where s is the contents of src after shifting (if used.)
996 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
997
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000998 // Bitfield manipulation instructions. v7 and above.
999
1000 void ubfx(Register dst, Register src, int lsb, int width,
1001 Condition cond = al);
1002
1003 void sbfx(Register dst, Register src, int lsb, int width,
1004 Condition cond = al);
1005
1006 void bfc(Register dst, int lsb, int width, Condition cond = al);
1007
1008 void bfi(Register dst, Register src, int lsb, int width,
1009 Condition cond = al);
1010
danno@chromium.org169691d2013-07-15 08:01:13 +00001011 void pkhbt(Register dst, Register src1, const Operand& src2,
1012 Condition cond = al);
1013
1014 void pkhtb(Register dst, Register src1, const Operand& src2,
1015 Condition cond = al);
1016
1017 void uxtb(Register dst, const Operand& src, Condition cond = al);
1018
1019 void uxtab(Register dst, Register src1, const Operand& src2,
1020 Condition cond = al);
1021
1022 void uxtb16(Register dst, const Operand& src, Condition cond = al);
1023
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001024 // Status register access instructions
1025
1026 void mrs(Register dst, SRegister s, Condition cond = al);
1027 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
1028
1029 // Load/Store instructions
1030 void ldr(Register dst, const MemOperand& src, Condition cond = al);
1031 void str(Register src, const MemOperand& dst, Condition cond = al);
1032 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
1033 void strb(Register src, const MemOperand& dst, Condition cond = al);
1034 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
1035 void strh(Register src, const MemOperand& dst, Condition cond = al);
1036 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
1037 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00001038 void ldrd(Register dst1,
1039 Register dst2,
1040 const MemOperand& src, Condition cond = al);
1041 void strd(Register src1,
1042 Register src2,
1043 const MemOperand& dst, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001044
danno@chromium.org169691d2013-07-15 08:01:13 +00001045 // Preload instructions
1046 void pld(const MemOperand& address);
1047
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001048 // Load/Store multiple instructions
1049 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
1050 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
1051
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001052 // Exception-generating instructions and debugging support
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001053 void stop(const char* msg,
1054 Condition cond = al,
1055 int32_t code = kDefaultStopCode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001056
1057 void bkpt(uint32_t imm16); // v5 and above
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001058 void svc(uint32_t imm24, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001059
1060 // Coprocessor instructions
1061
1062 void cdp(Coprocessor coproc, int opcode_1,
1063 CRegister crd, CRegister crn, CRegister crm,
1064 int opcode_2, Condition cond = al);
1065
1066 void cdp2(Coprocessor coproc, int opcode_1,
1067 CRegister crd, CRegister crn, CRegister crm,
1068 int opcode_2); // v5 and above
1069
1070 void mcr(Coprocessor coproc, int opcode_1,
1071 Register rd, CRegister crn, CRegister crm,
1072 int opcode_2 = 0, Condition cond = al);
1073
1074 void mcr2(Coprocessor coproc, int opcode_1,
1075 Register rd, CRegister crn, CRegister crm,
1076 int opcode_2 = 0); // v5 and above
1077
1078 void mrc(Coprocessor coproc, int opcode_1,
1079 Register rd, CRegister crn, CRegister crm,
1080 int opcode_2 = 0, Condition cond = al);
1081
1082 void mrc2(Coprocessor coproc, int opcode_1,
1083 Register rd, CRegister crn, CRegister crm,
1084 int opcode_2 = 0); // v5 and above
1085
1086 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1087 LFlag l = Short, Condition cond = al);
1088 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1089 LFlag l = Short, Condition cond = al);
1090
1091 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1092 LFlag l = Short); // v5 and above
1093 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1094 LFlag l = Short); // v5 and above
1095
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001096 // Support for VFP.
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001097 // All these APIs support S0 to S31 and D0 to D31.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001098
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001099 void vldr(const DwVfpRegister dst,
1100 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001101 int offset,
1102 const Condition cond = al);
1103 void vldr(const DwVfpRegister dst,
1104 const MemOperand& src,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001105 const Condition cond = al);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001106
1107 void vldr(const SwVfpRegister dst,
1108 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001109 int offset,
1110 const Condition cond = al);
1111 void vldr(const SwVfpRegister dst,
1112 const MemOperand& src,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001113 const Condition cond = al);
1114
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001115 void vstr(const DwVfpRegister src,
1116 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001117 int offset,
1118 const Condition cond = al);
1119 void vstr(const DwVfpRegister src,
1120 const MemOperand& dst,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001121 const Condition cond = al);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001122
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001123 void vstr(const SwVfpRegister src,
1124 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +00001125 int offset,
1126 const Condition cond = al);
1127 void vstr(const SwVfpRegister src,
1128 const MemOperand& dst,
ricow@chromium.org0b9f8502010-08-18 07:45:01 +00001129 const Condition cond = al);
1130
vegorov@chromium.org74f333b2011-04-06 11:17:46 +00001131 void vldm(BlockAddrMode am,
1132 Register base,
1133 DwVfpRegister first,
1134 DwVfpRegister last,
1135 Condition cond = al);
1136
1137 void vstm(BlockAddrMode am,
1138 Register base,
1139 DwVfpRegister first,
1140 DwVfpRegister last,
1141 Condition cond = al);
1142
1143 void vldm(BlockAddrMode am,
1144 Register base,
1145 SwVfpRegister first,
1146 SwVfpRegister last,
1147 Condition cond = al);
1148
1149 void vstm(BlockAddrMode am,
1150 Register base,
1151 SwVfpRegister first,
1152 SwVfpRegister last,
1153 Condition cond = al);
1154
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001155 void vmov(const DwVfpRegister dst,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001156 double imm,
mstarzinger@chromium.org71fc3462013-02-27 09:34:27 +00001157 const Register scratch = no_reg);
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001158 void vmov(const SwVfpRegister dst,
1159 const SwVfpRegister src,
1160 const Condition cond = al);
1161 void vmov(const DwVfpRegister dst,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001162 const DwVfpRegister src,
1163 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001164 void vmov(const DwVfpRegister dst,
ulan@chromium.org6ba1fd02013-02-14 14:56:11 +00001165 const VmovIndex index,
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001166 const Register src,
1167 const Condition cond = al);
jkummerow@chromium.orgfb732b12013-07-26 10:27:09 +00001168 void vmov(const Register dst,
1169 const VmovIndex index,
1170 const DwVfpRegister src,
1171 const Condition cond = al);
yangguo@chromium.org003650e2013-01-24 16:31:08 +00001172 void vmov(const DwVfpRegister dst,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001173 const Register src1,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001174 const Register src2,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001175 const Condition cond = al);
1176 void vmov(const Register dst1,
1177 const Register dst2,
1178 const DwVfpRegister src,
1179 const Condition cond = al);
1180 void vmov(const SwVfpRegister dst,
1181 const Register src,
1182 const Condition cond = al);
1183 void vmov(const Register dst,
1184 const SwVfpRegister src,
1185 const Condition cond = al);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001186 void vcvt_f64_s32(const DwVfpRegister dst,
1187 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001188 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001189 const Condition cond = al);
1190 void vcvt_f32_s32(const SwVfpRegister dst,
1191 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001192 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001193 const Condition cond = al);
1194 void vcvt_f64_u32(const DwVfpRegister dst,
1195 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001196 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001197 const Condition cond = al);
1198 void vcvt_s32_f64(const SwVfpRegister dst,
1199 const DwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001200 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001201 const Condition cond = al);
1202 void vcvt_u32_f64(const SwVfpRegister dst,
1203 const DwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001204 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001205 const Condition cond = al);
1206 void vcvt_f64_f32(const DwVfpRegister dst,
1207 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001208 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001209 const Condition cond = al);
1210 void vcvt_f32_f64(const SwVfpRegister dst,
1211 const DwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001212 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001213 const Condition cond = al);
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001214 void vcvt_f64_s32(const DwVfpRegister dst,
1215 int fraction_bits,
1216 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001217
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001218 void vneg(const DwVfpRegister dst,
1219 const DwVfpRegister src,
1220 const Condition cond = al);
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001221 void vabs(const DwVfpRegister dst,
1222 const DwVfpRegister src,
1223 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001224 void vadd(const DwVfpRegister dst,
1225 const DwVfpRegister src1,
1226 const DwVfpRegister src2,
1227 const Condition cond = al);
1228 void vsub(const DwVfpRegister dst,
1229 const DwVfpRegister src1,
1230 const DwVfpRegister src2,
1231 const Condition cond = al);
1232 void vmul(const DwVfpRegister dst,
1233 const DwVfpRegister src1,
1234 const DwVfpRegister src2,
1235 const Condition cond = al);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001236 void vmla(const DwVfpRegister dst,
1237 const DwVfpRegister src1,
1238 const DwVfpRegister src2,
1239 const Condition cond = al);
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001240 void vmls(const DwVfpRegister dst,
1241 const DwVfpRegister src1,
1242 const DwVfpRegister src2,
1243 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001244 void vdiv(const DwVfpRegister dst,
1245 const DwVfpRegister src1,
1246 const DwVfpRegister src2,
1247 const Condition cond = al);
1248 void vcmp(const DwVfpRegister src1,
1249 const DwVfpRegister src2,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001250 const Condition cond = al);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001251 void vcmp(const DwVfpRegister src1,
1252 const double src2,
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001253 const Condition cond = al);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001254 void vmrs(const Register dst,
1255 const Condition cond = al);
ager@chromium.org01fe7df2010-11-10 11:59:11 +00001256 void vmsr(const Register dst,
1257 const Condition cond = al);
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001258 void vsqrt(const DwVfpRegister dst,
1259 const DwVfpRegister src,
1260 const Condition cond = al);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001261
danno@chromium.org169691d2013-07-15 08:01:13 +00001262 // Support for NEON.
1263 // All these APIs support D0 to D31 and Q0 to Q15.
1264
1265 void vld1(NeonSize size,
1266 const NeonListOperand& dst,
1267 const NeonMemOperand& src);
1268 void vst1(NeonSize size,
1269 const NeonListOperand& src,
1270 const NeonMemOperand& dst);
1271 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1272
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001273 // Pseudo instructions
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001274
1275 // Different nop operations are used by the code generator to detect certain
1276 // states of the generated code.
1277 enum NopMarkerTypes {
1278 NON_MARKING_NOP = 0,
1279 DEBUG_BREAK_NOP,
1280 // IC markers.
1281 PROPERTY_ACCESS_INLINED,
1282 PROPERTY_ACCESS_INLINED_CONTEXT,
1283 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1284 // Helper values.
1285 LAST_CODE_MARKER,
1286 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1287 };
1288
1289 void nop(int type = 0); // 0 is the default non-marking type.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001290
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001291 void push(Register src, Condition cond = al) {
1292 str(src, MemOperand(sp, 4, NegPreIndex), cond);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001293 }
1294
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001295 void pop(Register dst, Condition cond = al) {
1296 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
mads.s.ager31e71382008-08-13 09:32:07 +00001297 }
1298
1299 void pop() {
1300 add(sp, sp, Operand(kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001301 }
1302
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001303 // Jump unconditionally to given label.
1304 void jmp(Label* L) { b(L, al); }
1305
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001306 static bool use_immediate_embedded_pointer_loads(
1307 const Assembler* assembler) {
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001308 return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
1309 (assembler == NULL || !assembler->predictable_code_size());
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001310 }
1311
ager@chromium.org4af710e2009-09-15 12:20:11 +00001312 // Check the code size generated from label to here.
ricow@chromium.org4f693d62011-07-04 14:01:31 +00001313 int SizeOfCodeGeneratedSince(Label* label) {
1314 return pc_offset() - label->pos();
1315 }
1316
1317 // Check the number of instructions generated from label to here.
1318 int InstructionsGeneratedSince(Label* label) {
1319 return SizeOfCodeGeneratedSince(label) / kInstrSize;
ager@chromium.org4af710e2009-09-15 12:20:11 +00001320 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001321
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001322 // Check whether an immediate fits an addressing mode 1 instruction.
1323 bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1324
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001325 // Class for scoping postponing the constant pool generation.
1326 class BlockConstPoolScope {
1327 public:
1328 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1329 assem_->StartBlockConstPool();
1330 }
1331 ~BlockConstPoolScope() {
1332 assem_->EndBlockConstPool();
1333 }
1334
1335 private:
1336 Assembler* assem_;
1337
1338 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1339 };
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001340
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001341 // Debugging
1342
ager@chromium.org4af710e2009-09-15 12:20:11 +00001343 // Mark address of the ExitJSFrame code.
1344 void RecordJSReturn();
1345
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001346 // Mark address of a debug break slot.
1347 void RecordDebugBreakSlot();
1348
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001349 // Record the AST id of the CallIC being compiled, so that it can be placed
1350 // in the relocation information.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001351 void SetRecordedAstId(TypeFeedbackId ast_id) {
1352 ASSERT(recorded_ast_id_.IsNone());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001353 recorded_ast_id_ = ast_id;
1354 }
1355
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001356 TypeFeedbackId RecordedAstId() {
1357 ASSERT(!recorded_ast_id_.IsNone());
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001358 return recorded_ast_id_;
1359 }
1360
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001361 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001362
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001363 // Record a comment relocation entry that can be used by a disassembler.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001364 // Use --code-comments to enable.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001365 void RecordComment(const char* msg);
1366
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +00001367 // Record the emission of a constant pool.
1368 //
1369 // The emission of constant pool depends on the size of the code generated and
1370 // the number of RelocInfo recorded.
1371 // The Debug mechanism needs to map code offsets between two versions of a
1372 // function, compiled with and without debugger support (see for example
1373 // Debug::PrepareForBreakPoints()).
1374 // Compiling functions with debugger support generates additional code
1375 // (Debug::GenerateSlot()). This may affect the emission of the constant
1376 // pools and cause the version of the code with debugger support to have
1377 // constant pools generated in different places.
1378 // Recording the position and size of emitted constant pools allows to
1379 // correctly compute the offset mappings between the different versions of a
1380 // function in all situations.
1381 //
1382 // The parameter indicates the size of the constant pool (in bytes), including
1383 // the marker and branch over the data.
1384 void RecordConstPool(int size);
1385
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001386 // Writes a single byte or word of data in the code stream. Used
1387 // for inline tables, e.g., jump-tables. The constant pool should be
1388 // emitted before any use of db and dd to ensure that constant pools
1389 // are not emitted as part of the tables generated.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001390 void db(uint8_t data);
1391 void dd(uint32_t data);
1392
verwaest@chromium.org057bd502013-11-06 12:03:29 +00001393 // Emits the address of the code stub's first instruction.
1394 void emit_code_stub_address(Code* stub);
1395
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001396 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001397
1398 // Read/patch instructions
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001399 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1400 void instr_at_put(int pos, Instr instr) {
1401 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1402 }
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001403 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1404 static void instr_at_put(byte* pc, Instr instr) {
1405 *reinterpret_cast<Instr*>(pc) = instr;
1406 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001407 static Condition GetCondition(Instr instr);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001408 static bool IsBranch(Instr instr);
1409 static int GetBranchOffset(Instr instr);
1410 static bool IsLdrRegisterImmediate(Instr instr);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001411 static bool IsVldrDRegisterImmediate(Instr instr);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001412 static int GetLdrRegisterImmediateOffset(Instr instr);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001413 static int GetVldrDRegisterImmediateOffset(Instr instr);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001414 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001415 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
whesse@chromium.orgba5a61b2010-07-26 11:44:40 +00001416 static bool IsStrRegisterImmediate(Instr instr);
1417 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1418 static bool IsAddRegisterImmediate(Instr instr);
1419 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001420 static Register GetRd(Instr instr);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001421 static Register GetRn(Instr instr);
1422 static Register GetRm(Instr instr);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001423 static bool IsPush(Instr instr);
1424 static bool IsPop(Instr instr);
1425 static bool IsStrRegFpOffset(Instr instr);
1426 static bool IsLdrRegFpOffset(Instr instr);
1427 static bool IsStrRegFpNegOffset(Instr instr);
1428 static bool IsLdrRegFpNegOffset(Instr instr);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001429 static bool IsLdrPcImmediateOffset(Instr instr);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001430 static bool IsVldrDPcImmediateOffset(Instr instr);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001431 static bool IsTstImmediate(Instr instr);
1432 static bool IsCmpRegister(Instr instr);
1433 static bool IsCmpImmediate(Instr instr);
1434 static Register GetCmpImmediateRegister(Instr instr);
1435 static int GetCmpImmediateRawImmediate(Instr instr);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001436 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001437 static bool IsMovT(Instr instr);
1438 static bool IsMovW(Instr instr);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001439
danno@chromium.org40cb8782011-05-25 07:58:50 +00001440 // Constants in pools are accessed via pc relative addressing, which can
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001441 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1442 // PC-relative loads, thereby defining a maximum distance between the
1443 // instruction and the accessed constant.
1444 static const int kMaxDistToIntPool = 4*KB;
1445 static const int kMaxDistToFPPool = 1*KB;
1446 // All relocations could be integer, it therefore acts as the limit.
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001447 static const int kMaxNumPending32RelocInfo = kMaxDistToIntPool/kInstrSize;
1448 static const int kMaxNumPending64RelocInfo = kMaxDistToFPPool/kInstrSize;
danno@chromium.org40cb8782011-05-25 07:58:50 +00001449
whesse@chromium.org7b260152011-06-20 15:33:18 +00001450 // Postpone the generation of the constant pool for the specified number of
1451 // instructions.
1452 void BlockConstPoolFor(int instructions);
1453
1454 // Check if is time to emit a constant pool.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001455 void CheckConstPool(bool force_emit, bool require_jump);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001456
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001457 protected:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001458 // Relocation for a type-recording IC has the AST id added to it. This
1459 // member variable is a way to pass the information from the call site to
1460 // the relocation info.
mstarzinger@chromium.org471f2f12012-08-10 14:46:33 +00001461 TypeFeedbackId recorded_ast_id_;
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001462
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001463 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1464
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001465 // Decode branch instruction at pos and return branch target pos
1466 int target_at(int pos);
1467
1468 // Patch branch instruction at pos to branch to given branch target pos
1469 void target_at_put(int pos, int target_pos);
1470
whesse@chromium.org7b260152011-06-20 15:33:18 +00001471 // Prevent contant pool emission until EndBlockConstPool is called.
1472 // Call to this function can be nested but must be followed by an equal
1473 // number of call to EndBlockConstpool.
1474 void StartBlockConstPool() {
1475 if (const_pool_blocked_nesting_++ == 0) {
1476 // Prevent constant pool checks happening by setting the next check to
1477 // the biggest possible offset.
1478 next_buffer_check_ = kMaxInt;
1479 }
ager@chromium.org8bb60582008-12-11 12:02:20 +00001480 }
1481
whesse@chromium.org7b260152011-06-20 15:33:18 +00001482 // Resume constant pool emission. Need to be called as many time as
1483 // StartBlockConstPool to have an effect.
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001484 void EndBlockConstPool() {
whesse@chromium.org7b260152011-06-20 15:33:18 +00001485 if (--const_pool_blocked_nesting_ == 0) {
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001486#ifdef DEBUG
1487 // Max pool start (if we need a jump and an alignment).
1488 int start = pc_offset() + kInstrSize + 2 * kPointerSize;
whesse@chromium.org7b260152011-06-20 15:33:18 +00001489 // Check the constant pool hasn't been blocked for too long.
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001490 ASSERT((num_pending_32_bit_reloc_info_ == 0) ||
1491 (start + num_pending_64_bit_reloc_info_ * kDoubleSize <
1492 (first_const_pool_32_use_ + kMaxDistToIntPool)));
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001493 ASSERT((num_pending_64_bit_reloc_info_ == 0) ||
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001494 (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
1495#endif
whesse@chromium.org7b260152011-06-20 15:33:18 +00001496 // Two cases:
1497 // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1498 // still blocked
1499 // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1500 // trigger a check.
1501 next_buffer_check_ = no_const_pool_before_;
1502 }
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001503 }
whesse@chromium.org7b260152011-06-20 15:33:18 +00001504
1505 bool is_const_pool_blocked() const {
1506 return (const_pool_blocked_nesting_ > 0) ||
1507 (pc_offset() < no_const_pool_before_);
1508 }
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001509
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001510 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001511 int next_buffer_check_; // pc offset of next buffer check
1512
1513 // Code generation
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001514 // The relocation writer's position is at least kGap bytes below the end of
1515 // the generated instructions. This is so that multi-instruction sequences do
1516 // not have to check for overflow. The same is true for writes of large
1517 // relocation info entries.
1518 static const int kGap = 32;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001519
1520 // Constant pool generation
1521 // Pools are emitted in the instruction stream, preferably after unconditional
1522 // jumps or after returns from functions (in dead code locations).
1523 // If a long code sequence does not contain unconditional jumps, it is
1524 // necessary to emit the constant pool before the pool gets too far from the
1525 // location it is accessed from. In this case, we emit a jump over the emitted
1526 // constant pool.
1527 // Constants in the pool may be addresses of functions that gets relocated;
1528 // if so, a relocation info entry is associated to the constant pool entry.
1529
1530 // Repeated checking whether the constant pool should be emitted is rather
1531 // expensive. By default we only check again once a number of instructions
1532 // has been generated. That also means that the sizing of the buffers is not
1533 // an exact science, and that we rely on some slop to not overrun buffers.
whesse@chromium.org7b260152011-06-20 15:33:18 +00001534 static const int kCheckPoolIntervalInst = 32;
1535 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001536
1537
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001538 // Emission of the constant pool may be blocked in some code sequences.
1539 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1540 int no_const_pool_before_; // Block emission before this pc offset.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001541
whesse@chromium.org7b260152011-06-20 15:33:18 +00001542 // Keep track of the first instruction requiring a constant pool entry
1543 // since the previous constant pool was emitted.
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001544 int first_const_pool_32_use_;
1545 int first_const_pool_64_use_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001546
1547 // Relocation info generation
1548 // Each relocation is encoded as a variable size value
1549 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1550 RelocInfoWriter reloc_info_writer;
whesse@chromium.org7b260152011-06-20 15:33:18 +00001551
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001552 // Relocation info records are also used during code generation as temporary
1553 // containers for constants and code target addresses until they are emitted
1554 // to the constant pool. These pending relocation info records are temporarily
1555 // stored in a separate buffer until a constant pool is emitted.
1556 // If every instruction in a long sequence is accessing the pool, we need one
1557 // pending relocation entry per instruction.
whesse@chromium.org7b260152011-06-20 15:33:18 +00001558
machenbach@chromium.orgea468882013-11-18 08:53:19 +00001559 // The buffers of pending relocation info.
1560 RelocInfo pending_32_bit_reloc_info_[kMaxNumPending32RelocInfo];
1561 RelocInfo pending_64_bit_reloc_info_[kMaxNumPending64RelocInfo];
1562 // Number of pending reloc info entries in the 32 bits buffer.
1563 int num_pending_32_bit_reloc_info_;
1564 // Number of pending reloc info entries in the 64 bits buffer.
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001565 int num_pending_64_bit_reloc_info_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001566
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001567 // The bound position, before this we cannot do instruction elimination.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001568 int last_bound_pos_;
1569
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001570 // Code emission
1571 inline void CheckBuffer();
1572 void GrowBuffer();
1573 inline void emit(Instr x);
1574
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001575 // 32-bit immediate values
1576 void move_32_bit_immediate(Condition cond,
1577 Register rd,
1578 SBit s,
1579 const Operand& x);
1580
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001581 // Instruction generation
1582 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1583 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1584 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1585 void addrmod4(Instr instr, Register rn, RegList rl);
1586 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1587
1588 // Labels
1589 void print(Label* L);
1590 void bind_to(Label* L, int pos);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001591 void next(Label* L);
1592
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001593 enum UseConstantPoolMode {
1594 USE_CONSTANT_POOL,
1595 DONT_USE_CONSTANT_POOL
1596 };
1597
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001598 // Record reloc info for current pc_
rossberg@chromium.org89e18f52012-10-22 13:09:53 +00001599 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0,
1600 UseConstantPoolMode mode = USE_CONSTANT_POOL);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001601 void RecordRelocInfo(double data);
1602 void RecordRelocInfoConstantPoolEntryHelper(const RelocInfo& rinfo);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001603
ager@chromium.org4af710e2009-09-15 12:20:11 +00001604 friend class RelocInfo;
1605 friend class CodePatcher;
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001606 friend class BlockConstPoolScope;
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001607
1608 PositionsRecorder positions_recorder_;
1609 friend class PositionsRecorder;
1610 friend class EnsureSpace;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001611};
1612
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001613
1614class EnsureSpace BASE_EMBEDDED {
1615 public:
1616 explicit EnsureSpace(Assembler* assembler) {
1617 assembler->CheckBuffer();
1618 }
1619};
1620
1621
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001622} } // namespace v8::internal
1623
ager@chromium.org5ec48922009-05-05 07:25:34 +00001624#endif // V8_ARM_ASSEMBLER_ARM_H_