blob: 26e062bdf6af3262372a00d1467c1c8adf49eca0 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
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.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// 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
Leon Clarked91b9f72010-01-27 17:25:45 +000033// The original source code covered by the above license above has been
34// modified significantly by Google Inc.
Ben Murdoch692be652012-01-10 18:47:50 +000035// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37// A light-weight ARM Assembler
38// Generates user mode instructions for the ARM architecture up to version 5
39
40#ifndef V8_ARM_ASSEMBLER_ARM_H_
41#define V8_ARM_ASSEMBLER_ARM_H_
Ben Murdochb8a8cc12014-11-26 15:28:44 +000042
Steve Blocka7e24c12009-10-30 11:49:00 +000043#include <stdio.h>
Ben Murdochb8a8cc12014-11-26 15:28:44 +000044#include <vector>
45
46#include "src/arm/constants-arm.h"
47#include "src/assembler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000048
49namespace v8 {
50namespace internal {
51
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000052// clang-format off
53#define GENERAL_REGISTERS(V) \
54 V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
55 V(r8) V(r9) V(r10) V(fp) V(ip) V(sp) V(lr) V(pc)
56
57#define ALLOCATABLE_GENERAL_REGISTERS(V) \
58 V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) V(r8)
59
Ben Murdochc5610432016-08-08 18:44:38 +010060#define FLOAT_REGISTERS(V) \
61 V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) \
62 V(s8) V(s9) V(s10) V(s11) V(s12) V(s13) V(s14) V(s15) \
63 V(s16) V(s17) V(s18) V(s19) V(s20) V(s21) V(s22) V(s23) \
64 V(s24) V(s25) V(s26) V(s27) V(s28) V(s29) V(s30) V(s31)
65
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066#define DOUBLE_REGISTERS(V) \
67 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
68 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
69 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
70 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
71
72#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
73 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
74 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \
75 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
76 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
77
78#define ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(V) \
79 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
80 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \
81// clang-format on
82
Steve Blocka7e24c12009-10-30 11:49:00 +000083// CPU Registers.
84//
85// 1) We would prefer to use an enum, but enum values are assignment-
86// compatible with int, which has caused code-generation bugs.
87//
88// 2) We would prefer to use a class instead of a struct but we don't like
89// the register initialization to depend on the particular initialization
90// order (which appears to be different on OS X, Linux, and Windows for the
91// installed versions of C++ we tried). Using a struct permits C-style
92// "initialization". Also, the Register objects cannot be const as this
93// forces initialization stubs in MSVC, making us dependent on initialization
94// order.
95//
96// 3) By not using an enum, we are possibly preventing the compiler from
97// doing certain constant folds, which may significantly reduce the
98// code generated for some assembly instructions (because they boil down
99// to a few constants). If this is a problem, we could change the code
100// such that we use an enum in optimized mode, and the struct in debug
101// mode. This way we get the compile-time error checking in debug mode
102// and best performance in optimized code.
Steve Block9fac8402011-05-12 15:51:54 +0100103
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104struct Register {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105 enum Code {
106#define REGISTER_CODE(R) kCode_##R,
107 GENERAL_REGISTERS(REGISTER_CODE)
108#undef REGISTER_CODE
109 kAfterLast,
110 kCode_no_reg = -1
111 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000112
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113 static const int kNumRegisters = Code::kAfterLast;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114
115 static Register from_code(int code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 DCHECK(code >= 0);
117 DCHECK(code < kNumRegisters);
118 Register r = {code};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119 return r;
120 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121 const char* ToString();
122 bool IsAllocatable() const;
123 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
124 bool is(Register reg) const { return reg_code == reg.reg_code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000125 int code() const {
126 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 return reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 }
129 int bit() const {
130 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 return 1 << reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000132 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 void set_code(int code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134 reg_code = code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000135 DCHECK(is_valid());
136 }
137
138 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 int reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140};
141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142// r7: context register
143// r8: constant pool pointer register if FLAG_enable_embedded_constant_pool.
144// r9: lithium scratch
145#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
146GENERAL_REGISTERS(DECLARE_REGISTER)
147#undef DECLARE_REGISTER
148const Register no_reg = {Register::kCode_no_reg};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100149
Leon Clarkee46be812010-01-19 14:06:41 +0000150// Single word VFP register.
151struct SwVfpRegister {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152 static const int kSizeInBytes = 4;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153 bool is_valid() const { return 0 <= reg_code && reg_code < 32; }
154 bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100155 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000156 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 return reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000158 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100159 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000160 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 return 1 << reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000162 }
Ben Murdochc5610432016-08-08 18:44:38 +0100163 static SwVfpRegister from_code(int code) {
164 SwVfpRegister r = {code};
165 return r;
166 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100167 void split_code(int* vm, int* m) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 *m = reg_code & 0x1;
170 *vm = reg_code >> 1;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100171 }
Leon Clarkee46be812010-01-19 14:06:41 +0000172
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 int reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000174};
175
Ben Murdochc5610432016-08-08 18:44:38 +0100176typedef SwVfpRegister FloatRegister;
Leon Clarkee46be812010-01-19 14:06:41 +0000177
178// Double word VFP register.
Ben Murdochc5610432016-08-08 18:44:38 +0100179struct DwVfpRegister {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 enum Code {
181#define REGISTER_CODE(R) kCode_##R,
182 DOUBLE_REGISTERS(REGISTER_CODE)
183#undef REGISTER_CODE
184 kAfterLast,
185 kCode_no_reg = -1
186 };
187
188 static const int kMaxNumRegisters = Code::kAfterLast;
189
190 inline static int NumRegisters();
191
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000192 // A few double registers are reserved: one as a scratch register and one to
193 // hold 0.0, that does not fit in the immediate field of vmov instructions.
194 // d14: 0.0
195 // d15: scratch register.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 static const int kSizeInBytes = 8;
197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 const char* ToString();
199 bool IsAllocatable() const;
200 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
Ben Murdochc5610432016-08-08 18:44:38 +0100201 bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100202 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 return reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000205 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100206 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 return 1 << reg_code;
209 }
210
Ben Murdochc5610432016-08-08 18:44:38 +0100211 static DwVfpRegister from_code(int code) {
212 DwVfpRegister r = {code};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213 return r;
Leon Clarkee46be812010-01-19 14:06:41 +0000214 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100215 void split_code(int* vm, int* m) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217 *m = (reg_code & 0x10) >> 4;
218 *vm = reg_code & 0x0F;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100219 }
Leon Clarkee46be812010-01-19 14:06:41 +0000220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 int reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000222};
223
224
Ben Murdochc5610432016-08-08 18:44:38 +0100225typedef DwVfpRegister DoubleRegister;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100226
227
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228// Double word VFP register d0-15.
229struct LowDwVfpRegister {
230 public:
231 static const int kMaxNumLowRegisters = 16;
232 operator DwVfpRegister() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 DwVfpRegister r = { reg_code };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000234 return r;
235 }
236 static LowDwVfpRegister from_code(int code) {
237 LowDwVfpRegister r = { code };
238 return r;
239 }
240
241 bool is_valid() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 return 0 <= reg_code && reg_code < kMaxNumLowRegisters;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
245 bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246 int code() const {
247 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 return reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249 }
250 SwVfpRegister low() const {
251 SwVfpRegister reg;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 reg.reg_code = reg_code * 2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253
254 DCHECK(reg.is_valid());
255 return reg;
256 }
257 SwVfpRegister high() const {
258 SwVfpRegister reg;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 reg.reg_code = (reg_code * 2) + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260
261 DCHECK(reg.is_valid());
262 return reg;
263 }
264
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 int reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266};
267
268
269// Quad word NEON register.
270struct QwNeonRegister {
271 static const int kMaxNumRegisters = 16;
272
273 static QwNeonRegister from_code(int code) {
274 QwNeonRegister r = { code };
275 return r;
276 }
277
278 bool is_valid() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 return (0 <= reg_code) && (reg_code < kMaxNumRegisters);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000280 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 int code() const {
283 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284 return reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000285 }
286 void split_code(int* vm, int* m) const {
287 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 int encoded_code = reg_code << 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 *m = (encoded_code & 0x10) >> 4;
290 *vm = encoded_code & 0x0F;
291 }
292
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 int reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294};
295
296
297typedef QwNeonRegister QuadRegister;
298
Ben Murdoch097c5b22016-05-18 11:27:45 +0100299typedef QwNeonRegister Simd128Register;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000300
Steve Block6ded16b2010-05-10 14:33:55 +0100301// Support for the VFP registers s0 to s31 (d0 to d15).
Leon Clarkee46be812010-01-19 14:06:41 +0000302// Note that "s(N):s(N+1)" is the same as "d(N/2)".
Steve Block6ded16b2010-05-10 14:33:55 +0100303const SwVfpRegister s0 = { 0 };
304const SwVfpRegister s1 = { 1 };
305const SwVfpRegister s2 = { 2 };
306const SwVfpRegister s3 = { 3 };
307const SwVfpRegister s4 = { 4 };
308const SwVfpRegister s5 = { 5 };
309const SwVfpRegister s6 = { 6 };
310const SwVfpRegister s7 = { 7 };
311const SwVfpRegister s8 = { 8 };
312const SwVfpRegister s9 = { 9 };
313const SwVfpRegister s10 = { 10 };
314const SwVfpRegister s11 = { 11 };
315const SwVfpRegister s12 = { 12 };
316const SwVfpRegister s13 = { 13 };
317const SwVfpRegister s14 = { 14 };
318const SwVfpRegister s15 = { 15 };
319const SwVfpRegister s16 = { 16 };
320const SwVfpRegister s17 = { 17 };
321const SwVfpRegister s18 = { 18 };
322const SwVfpRegister s19 = { 19 };
323const SwVfpRegister s20 = { 20 };
324const SwVfpRegister s21 = { 21 };
325const SwVfpRegister s22 = { 22 };
326const SwVfpRegister s23 = { 23 };
327const SwVfpRegister s24 = { 24 };
328const SwVfpRegister s25 = { 25 };
329const SwVfpRegister s26 = { 26 };
330const SwVfpRegister s27 = { 27 };
331const SwVfpRegister s28 = { 28 };
332const SwVfpRegister s29 = { 29 };
333const SwVfpRegister s30 = { 30 };
334const SwVfpRegister s31 = { 31 };
Leon Clarkee46be812010-01-19 14:06:41 +0000335
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100336const DwVfpRegister no_dreg = { -1 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337const LowDwVfpRegister d0 = { 0 };
338const LowDwVfpRegister d1 = { 1 };
339const LowDwVfpRegister d2 = { 2 };
340const LowDwVfpRegister d3 = { 3 };
341const LowDwVfpRegister d4 = { 4 };
342const LowDwVfpRegister d5 = { 5 };
343const LowDwVfpRegister d6 = { 6 };
344const LowDwVfpRegister d7 = { 7 };
345const LowDwVfpRegister d8 = { 8 };
346const LowDwVfpRegister d9 = { 9 };
347const LowDwVfpRegister d10 = { 10 };
348const LowDwVfpRegister d11 = { 11 };
349const LowDwVfpRegister d12 = { 12 };
350const LowDwVfpRegister d13 = { 13 };
351const LowDwVfpRegister d14 = { 14 };
352const LowDwVfpRegister d15 = { 15 };
353const DwVfpRegister d16 = { 16 };
354const DwVfpRegister d17 = { 17 };
355const DwVfpRegister d18 = { 18 };
356const DwVfpRegister d19 = { 19 };
357const DwVfpRegister d20 = { 20 };
358const DwVfpRegister d21 = { 21 };
359const DwVfpRegister d22 = { 22 };
360const DwVfpRegister d23 = { 23 };
361const DwVfpRegister d24 = { 24 };
362const DwVfpRegister d25 = { 25 };
363const DwVfpRegister d26 = { 26 };
364const DwVfpRegister d27 = { 27 };
365const DwVfpRegister d28 = { 28 };
366const DwVfpRegister d29 = { 29 };
367const DwVfpRegister d30 = { 30 };
368const DwVfpRegister d31 = { 31 };
369
370const QwNeonRegister q0 = { 0 };
371const QwNeonRegister q1 = { 1 };
372const QwNeonRegister q2 = { 2 };
373const QwNeonRegister q3 = { 3 };
374const QwNeonRegister q4 = { 4 };
375const QwNeonRegister q5 = { 5 };
376const QwNeonRegister q6 = { 6 };
377const QwNeonRegister q7 = { 7 };
378const QwNeonRegister q8 = { 8 };
379const QwNeonRegister q9 = { 9 };
380const QwNeonRegister q10 = { 10 };
381const QwNeonRegister q11 = { 11 };
382const QwNeonRegister q12 = { 12 };
383const QwNeonRegister q13 = { 13 };
384const QwNeonRegister q14 = { 14 };
385const QwNeonRegister q15 = { 15 };
386
Leon Clarkee46be812010-01-19 14:06:41 +0000387
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100388// Aliases for double registers. Defined using #define instead of
389// "static const DwVfpRegister&" because Clang complains otherwise when a
390// compilation unit that includes this header doesn't use the variables.
391#define kFirstCalleeSavedDoubleReg d8
392#define kLastCalleeSavedDoubleReg d15
393#define kDoubleRegZero d14
394#define kScratchDoubleReg d15
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +0100395
Steve Blocka7e24c12009-10-30 11:49:00 +0000396
397// Coprocessor register
398struct CRegister {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 bool is_valid() const { return 0 <= reg_code && reg_code < 16; }
400 bool is(CRegister creg) const { return reg_code == creg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100401 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000402 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000403 return reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100405 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000407 return 1 << reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000408 }
409
Andrei Popescu31002712010-02-23 13:46:05 +0000410 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000411 int reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000412};
413
414
Steve Block6ded16b2010-05-10 14:33:55 +0100415const CRegister no_creg = { -1 };
416
417const CRegister cr0 = { 0 };
418const CRegister cr1 = { 1 };
419const CRegister cr2 = { 2 };
420const CRegister cr3 = { 3 };
421const CRegister cr4 = { 4 };
422const CRegister cr5 = { 5 };
423const CRegister cr6 = { 6 };
424const CRegister cr7 = { 7 };
425const CRegister cr8 = { 8 };
426const CRegister cr9 = { 9 };
427const CRegister cr10 = { 10 };
428const CRegister cr11 = { 11 };
429const CRegister cr12 = { 12 };
430const CRegister cr13 = { 13 };
431const CRegister cr14 = { 14 };
432const CRegister cr15 = { 15 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000433
434
435// Coprocessor number
436enum Coprocessor {
437 p0 = 0,
438 p1 = 1,
439 p2 = 2,
440 p3 = 3,
441 p4 = 4,
442 p5 = 5,
443 p6 = 6,
444 p7 = 7,
445 p8 = 8,
446 p9 = 9,
447 p10 = 10,
448 p11 = 11,
449 p12 = 12,
450 p13 = 13,
451 p14 = 14,
452 p15 = 15
453};
454
455
Steve Blocka7e24c12009-10-30 11:49:00 +0000456// -----------------------------------------------------------------------------
457// Machine instruction Operands
458
459// Class Operand represents a shifter operand in data processing instructions
460class Operand BASE_EMBEDDED {
461 public:
462 // immediate
463 INLINE(explicit Operand(int32_t immediate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000464 RelocInfo::Mode rmode = RelocInfo::NONE32));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000465 INLINE(static Operand Zero()) {
466 return Operand(static_cast<int32_t>(0));
467 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 INLINE(explicit Operand(const ExternalReference& f));
Steve Blocka7e24c12009-10-30 11:49:00 +0000469 explicit Operand(Handle<Object> handle);
470 INLINE(explicit Operand(Smi* value));
471
472 // rm
473 INLINE(explicit Operand(Register rm));
474
475 // rm <shift_op> shift_imm
476 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000477 INLINE(static Operand SmiUntag(Register rm)) {
478 return Operand(rm, ASR, kSmiTagSize);
479 }
480 INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
481 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
482 return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
483 }
484 INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
485 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
486 return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
487 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000488
489 // rm <shift_op> rs
490 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
491
492 // Return true if this is a register operand.
493 INLINE(bool is_reg() const);
494
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495 // Return the number of actual instructions required to implement the given
496 // instruction for this particular operand. This can be a single instruction,
497 // if no load into the ip register is necessary, or anything between 2 and 4
498 // instructions when we need to load from the constant pool (depending upon
499 // whether the constant pool entry is in the small or extended section). If
Steve Block44f0eee2011-05-26 01:26:41 +0100500 // the instruction this operand is used for is a MOV or MVN instruction the
501 // actual instruction to use is required for this calculation. For other
502 // instructions instr is ignored.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 //
504 // The value returned is only valid as long as no entries are added to the
505 // constant pool between this call and the actual instruction being emitted.
506 int instructions_required(const Assembler* assembler, Instr instr = 0) const;
507 bool must_output_reloc_info(const Assembler* assembler) const;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100508
509 inline int32_t immediate() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 DCHECK(!rm_.is_valid());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100511 return imm32_;
512 }
513
Steve Blocka7e24c12009-10-30 11:49:00 +0000514 Register rm() const { return rm_; }
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100515 Register rs() const { return rs_; }
516 ShiftOp shift_op() const { return shift_op_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000517
518 private:
519 Register rm_;
520 Register rs_;
521 ShiftOp shift_op_;
522 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
523 int32_t imm32_; // valid if rm_ == no_reg
524 RelocInfo::Mode rmode_;
525
526 friend class Assembler;
527};
528
529
530// Class MemOperand represents a memory operand in load and store instructions
531class MemOperand BASE_EMBEDDED {
532 public:
533 // [rn +/- offset] Offset/NegOffset
534 // [rn +/- offset]! PreIndex/NegPreIndex
535 // [rn], +/- offset PostIndex/NegPostIndex
536 // offset is any signed 32-bit value; offset is first loaded to register ip if
537 // it does not fit the addressing mode (12-bit unsigned and sign bit)
538 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
539
540 // [rn +/- rm] Offset/NegOffset
541 // [rn +/- rm]! PreIndex/NegPreIndex
542 // [rn], +/- rm PostIndex/NegPostIndex
543 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
544
545 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
546 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
547 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
548 explicit MemOperand(Register rn, Register rm,
549 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000550 INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
551 Register key,
552 AddrMode am = Offset)) {
553 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
554 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
555 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000556
Kristian Monsen25f61362010-05-21 11:50:48 +0100557 void set_offset(int32_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558 DCHECK(rm_.is(no_reg));
Kristian Monsen25f61362010-05-21 11:50:48 +0100559 offset_ = offset;
560 }
561
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100562 uint32_t offset() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000563 DCHECK(rm_.is(no_reg));
Kristian Monsen25f61362010-05-21 11:50:48 +0100564 return offset_;
565 }
566
Leon Clarkef7060e22010-06-03 12:02:55 +0100567 Register rn() const { return rn_; }
568 Register rm() const { return rm_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000569 AddrMode am() const { return am_; }
Kristian Monsen25f61362010-05-21 11:50:48 +0100570
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100571 bool OffsetIsUint12Encodable() const {
572 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
573 }
574
Steve Blocka7e24c12009-10-30 11:49:00 +0000575 private:
576 Register rn_; // base
577 Register rm_; // register offset
578 int32_t offset_; // valid if rm_ == no_reg
579 ShiftOp shift_op_;
580 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
581 AddrMode am_; // bits P, U, and W
582
583 friend class Assembler;
584};
585
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586
587// Class NeonMemOperand represents a memory operand in load and
588// store NEON instructions
589class NeonMemOperand BASE_EMBEDDED {
Steve Blockd0582a62009-12-15 09:54:21 +0000590 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000591 // [rn {:align}] Offset
592 // [rn {:align}]! PostIndex
593 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
Steve Blockd0582a62009-12-15 09:54:21 +0000594
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595 // [rn {:align}], rm PostIndex
596 explicit NeonMemOperand(Register rn, Register rm, int align = 0);
Steve Blockd0582a62009-12-15 09:54:21 +0000597
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000598 Register rn() const { return rn_; }
599 Register rm() const { return rm_; }
600 int align() const { return align_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100601
Steve Blockd0582a62009-12-15 09:54:21 +0000602 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000603 void SetAlignment(int align);
Steve Block44f0eee2011-05-26 01:26:41 +0100604
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000605 Register rn_; // base
606 Register rm_; // register increment
607 int align_;
Steve Blockd0582a62009-12-15 09:54:21 +0000608};
609
Steve Blocka7e24c12009-10-30 11:49:00 +0000610
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000611// Class NeonListOperand represents a list of NEON registers
612class NeonListOperand BASE_EMBEDDED {
613 public:
614 explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
615 DoubleRegister base() const { return base_; }
616 NeonListType type() const { return type_; }
617 private:
618 DoubleRegister base_;
619 NeonListType type_;
620};
Steve Blocka7e24c12009-10-30 11:49:00 +0000621
Steve Block1e0659c2011-05-24 12:43:12 +0100622
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623struct VmovIndex {
624 unsigned char index;
625};
626const VmovIndex VmovIndexLo = { 0 };
627const VmovIndex VmovIndexHi = { 1 };
Steve Block1e0659c2011-05-24 12:43:12 +0100628
Steve Block44f0eee2011-05-26 01:26:41 +0100629class Assembler : public AssemblerBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000630 public:
631 // Create an assembler. Instructions and relocation information are emitted
632 // into a buffer, with the instructions starting from the beginning and the
633 // relocation information starting from the end of the buffer. See CodeDesc
634 // for a detailed comment on the layout (globals.h).
635 //
636 // If the provided buffer is NULL, the assembler allocates and grows its own
637 // buffer, and buffer_size determines the initial buffer size. The buffer is
638 // owned by the assembler and deallocated upon destruction of the assembler.
639 //
640 // If the provided buffer is not NULL, the assembler uses the provided buffer
641 // for code generation and assumes its size to be buffer_size. If the buffer
642 // is too small, a fatal error occurs. No deallocation of the buffer is done
643 // upon destruction of the assembler.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100644 Assembler(Isolate* isolate, void* buffer, int buffer_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000645 virtual ~Assembler();
Steve Block44f0eee2011-05-26 01:26:41 +0100646
Steve Blocka7e24c12009-10-30 11:49:00 +0000647 // GetCode emits any pending (non-emitted) code and fills the descriptor
648 // desc. GetCode() is idempotent; it returns the same result if no other
649 // Assembler functions are invoked in between GetCode() calls.
650 void GetCode(CodeDesc* desc);
651
652 // Label operations & relative jumps (PPUM Appendix D)
653 //
654 // Takes a branch opcode (cc) and a label (L) and generates
655 // either a backward branch or a forward branch and links it
656 // to the label fixup chain. Usage:
657 //
658 // Label L; // unbound label
659 // j(cc, &L); // forward branch to unbound label
660 // bind(&L); // bind label to the current pc
661 // j(cc, &L); // backward branch to bound label
662 // bind(&L); // illegal: a label may be bound only once
663 //
664 // Note: The same Label can be used for forward and backward branches
665 // but it may be bound only once.
666
667 void bind(Label* L); // binds an unbound label L to the current code position
668
669 // Returns the branch offset to the given label from the current code position
670 // Links the label to the current position if it is still unbound
671 // Manages the jump elimination optimization if the second parameter is true.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000672 int branch_offset(Label* L);
Steve Blocka7e24c12009-10-30 11:49:00 +0000673
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000674 // Returns true if the given pc address is the start of a constant pool load
675 // instruction sequence.
676 INLINE(static bool is_constant_pool_load(Address pc));
Steve Blocka7e24c12009-10-30 11:49:00 +0000677
678 // Return the address in the constant pool of the code target address used by
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679 // the branch/call instruction at pc, or the object in a mov.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000680 INLINE(static Address constant_pool_entry_address(Address pc,
681 Address constant_pool));
Steve Blocka7e24c12009-10-30 11:49:00 +0000682
683 // Read/Modify the code target address in the branch/call instruction at pc.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684 INLINE(static Address target_address_at(Address pc, Address constant_pool));
685 INLINE(static void set_target_address_at(
686 Isolate* isolate, Address pc, Address constant_pool, Address target,
687 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000688 INLINE(static Address target_address_at(Address pc, Code* code)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000689 Address constant_pool = code ? code->constant_pool() : NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690 return target_address_at(pc, constant_pool);
691 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692 INLINE(static void set_target_address_at(
693 Isolate* isolate, Address pc, Code* code, Address target,
694 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
695 Address constant_pool = code ? code->constant_pool() : NULL;
696 set_target_address_at(isolate, pc, constant_pool, target,
697 icache_flush_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000698 }
699
700 // Return the code target address at a call site from the return address
701 // of that call in the instruction stream.
702 INLINE(static Address target_address_from_return_address(Address pc));
703
704 // Given the address of the beginning of a call, return the address
705 // in the instruction stream that the call will return from.
706 INLINE(static Address return_address_from_call_start(Address pc));
707
Steve Blockd0582a62009-12-15 09:54:21 +0000708 // This sets the branch destination (which is in the constant pool on ARM).
709 // This is for calls and branches within generated code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100710 inline static void deserialization_set_special_target_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711 Isolate* isolate, Address constant_pool_entry, Code* code,
712 Address target);
713
714 // This sets the internal reference at the pc.
715 inline static void deserialization_set_target_internal_reference_at(
716 Isolate* isolate, Address pc, Address target,
717 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
Steve Blockd0582a62009-12-15 09:54:21 +0000718
719 // Here we are patching the address in the constant pool, not the actual call
720 // instruction. The address in the constant pool is the same size as a
721 // pointer.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100722 static const int kSpecialTargetSize = kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +0000723
Steve Blocka7e24c12009-10-30 11:49:00 +0000724 // Size of an instruction.
725 static const int kInstrSize = sizeof(Instr);
726
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100727 // Distance between start of patched debug break slot and the emitted address
728 // to jump to.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100729 // Patched debug break slot code is:
730 // ldr ip, [pc, #0] @ emited address and start
731 // blx ip
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000732 static const int kPatchDebugBreakSlotAddressOffset = 2 * kInstrSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100733
Steve Blocka7e24c12009-10-30 11:49:00 +0000734 // Difference between address of current opcode and value read from pc
735 // register.
736 static const int kPcLoadDelta = 8;
737
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 static const int kDebugBreakSlotInstructions = 4;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100739 static const int kDebugBreakSlotLength =
740 kDebugBreakSlotInstructions * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000741
742 // ---------------------------------------------------------------------------
743 // Code generation
744
745 // Insert the smallest number of nop instructions
746 // possible to align the pc offset to a multiple
747 // of m. m must be a power of 2 (>= 4).
748 void Align(int m);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000749 // Insert the smallest number of zero bytes possible to align the pc offset
750 // to a mulitple of m. m must be a power of 2 (>= 2).
751 void DataAlign(int m);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100752 // Aligns code to something that's optimal for a jump target for the platform.
753 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000754
755 // Branch instructions
756 void b(int branch_offset, Condition cond = al);
757 void bl(int branch_offset, Condition cond = al);
758 void blx(int branch_offset); // v5 and above
759 void blx(Register target, Condition cond = al); // v5 and above
760 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
761
762 // Convenience branch instructions using labels
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000763 void b(Label* L, Condition cond = al);
764 void b(Condition cond, Label* L) { b(L, cond); }
765 void bl(Label* L, Condition cond = al);
766 void bl(Condition cond, Label* L) { bl(L, cond); }
767 void blx(Label* L); // v5 and above
Steve Blocka7e24c12009-10-30 11:49:00 +0000768
769 // Data-processing instructions
Andrei Popescu31002712010-02-23 13:46:05 +0000770
Steve Blocka7e24c12009-10-30 11:49:00 +0000771 void and_(Register dst, Register src1, const Operand& src2,
772 SBit s = LeaveCC, Condition cond = al);
773
774 void eor(Register dst, Register src1, const Operand& src2,
775 SBit s = LeaveCC, Condition cond = al);
776
777 void sub(Register dst, Register src1, const Operand& src2,
778 SBit s = LeaveCC, Condition cond = al);
779 void sub(Register dst, Register src1, Register src2,
780 SBit s = LeaveCC, Condition cond = al) {
781 sub(dst, src1, Operand(src2), s, cond);
782 }
783
784 void rsb(Register dst, Register src1, const Operand& src2,
785 SBit s = LeaveCC, Condition cond = al);
786
787 void add(Register dst, Register src1, const Operand& src2,
788 SBit s = LeaveCC, Condition cond = al);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100789 void add(Register dst, Register src1, Register src2,
790 SBit s = LeaveCC, Condition cond = al) {
791 add(dst, src1, Operand(src2), s, cond);
792 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000793
794 void adc(Register dst, Register src1, const Operand& src2,
795 SBit s = LeaveCC, Condition cond = al);
796
797 void sbc(Register dst, Register src1, const Operand& src2,
798 SBit s = LeaveCC, Condition cond = al);
799
800 void rsc(Register dst, Register src1, const Operand& src2,
801 SBit s = LeaveCC, Condition cond = al);
802
803 void tst(Register src1, const Operand& src2, Condition cond = al);
804 void tst(Register src1, Register src2, Condition cond = al) {
805 tst(src1, Operand(src2), cond);
806 }
807
808 void teq(Register src1, const Operand& src2, Condition cond = al);
809
810 void cmp(Register src1, const Operand& src2, Condition cond = al);
811 void cmp(Register src1, Register src2, Condition cond = al) {
812 cmp(src1, Operand(src2), cond);
813 }
Steve Block1e0659c2011-05-24 12:43:12 +0100814 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000815
816 void cmn(Register src1, const Operand& src2, Condition cond = al);
817
818 void orr(Register dst, Register src1, const Operand& src2,
819 SBit s = LeaveCC, Condition cond = al);
820 void orr(Register dst, Register src1, Register src2,
821 SBit s = LeaveCC, Condition cond = al) {
822 orr(dst, src1, Operand(src2), s, cond);
823 }
824
825 void mov(Register dst, const Operand& src,
826 SBit s = LeaveCC, Condition cond = al);
827 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
828 mov(dst, Operand(src), s, cond);
829 }
830
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831 // Load the position of the label relative to the generated code object
832 // pointer in a register.
833 void mov_label_offset(Register dst, Label* label);
834
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100835 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000836 // The constant for movw and movt should be in the range 0-0xffff.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100837 void movw(Register reg, uint32_t immediate, Condition cond = al);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100838 void movt(Register reg, uint32_t immediate, Condition cond = al);
839
Steve Blocka7e24c12009-10-30 11:49:00 +0000840 void bic(Register dst, Register src1, const Operand& src2,
841 SBit s = LeaveCC, Condition cond = al);
842
843 void mvn(Register dst, const Operand& src,
844 SBit s = LeaveCC, Condition cond = al);
845
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000846 // Shift instructions
847
848 void asr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
849 Condition cond = al) {
850 if (src2.is_reg()) {
851 mov(dst, Operand(src1, ASR, src2.rm()), s, cond);
852 } else {
853 mov(dst, Operand(src1, ASR, src2.immediate()), s, cond);
854 }
855 }
856
857 void lsl(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
858 Condition cond = al) {
859 if (src2.is_reg()) {
860 mov(dst, Operand(src1, LSL, src2.rm()), s, cond);
861 } else {
862 mov(dst, Operand(src1, LSL, src2.immediate()), s, cond);
863 }
864 }
865
866 void lsr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
867 Condition cond = al) {
868 if (src2.is_reg()) {
869 mov(dst, Operand(src1, LSR, src2.rm()), s, cond);
870 } else {
871 mov(dst, Operand(src1, LSR, src2.immediate()), s, cond);
872 }
873 }
874
Steve Blocka7e24c12009-10-30 11:49:00 +0000875 // Multiply instructions
876
877 void mla(Register dst, Register src1, Register src2, Register srcA,
878 SBit s = LeaveCC, Condition cond = al);
879
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000880 void mls(Register dst, Register src1, Register src2, Register srcA,
881 Condition cond = al);
882
883 void sdiv(Register dst, Register src1, Register src2,
884 Condition cond = al);
885
886 void udiv(Register dst, Register src1, Register src2, Condition cond = al);
887
Steve Blocka7e24c12009-10-30 11:49:00 +0000888 void mul(Register dst, Register src1, Register src2,
889 SBit s = LeaveCC, Condition cond = al);
890
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400891 void smmla(Register dst, Register src1, Register src2, Register srcA,
892 Condition cond = al);
893
894 void smmul(Register dst, Register src1, Register src2, Condition cond = al);
895
Steve Blocka7e24c12009-10-30 11:49:00 +0000896 void smlal(Register dstL, Register dstH, Register src1, Register src2,
897 SBit s = LeaveCC, Condition cond = al);
898
899 void smull(Register dstL, Register dstH, Register src1, Register src2,
900 SBit s = LeaveCC, Condition cond = al);
901
902 void umlal(Register dstL, Register dstH, Register src1, Register src2,
903 SBit s = LeaveCC, Condition cond = al);
904
905 void umull(Register dstL, Register dstH, Register src1, Register src2,
906 SBit s = LeaveCC, Condition cond = al);
907
908 // Miscellaneous arithmetic instructions
909
910 void clz(Register dst, Register src, Condition cond = al); // v5 and above
911
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100912 // Saturating instructions. v6 and above.
913
914 // Unsigned saturate.
915 //
916 // Saturate an optionally shifted signed value to an unsigned range.
917 //
918 // usat dst, #satpos, src
919 // usat dst, #satpos, src, lsl #sh
920 // usat dst, #satpos, src, asr #sh
921 //
922 // Register dst will contain:
923 //
924 // 0, if s < 0
925 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
926 // s, otherwise
927 //
928 // where s is the contents of src after shifting (if used.)
929 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
930
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100931 // Bitfield manipulation instructions. v7 and above.
932
933 void ubfx(Register dst, Register src, int lsb, int width,
934 Condition cond = al);
935
936 void sbfx(Register dst, Register src, int lsb, int width,
937 Condition cond = al);
938
939 void bfc(Register dst, int lsb, int width, Condition cond = al);
940
941 void bfi(Register dst, Register src, int lsb, int width,
942 Condition cond = al);
943
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000944 void pkhbt(Register dst, Register src1, const Operand& src2,
945 Condition cond = al);
946
947 void pkhtb(Register dst, Register src1, const Operand& src2,
948 Condition cond = al);
949
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400950 void sxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
951 void sxtab(Register dst, Register src1, Register src2, int rotate = 0,
952 Condition cond = al);
953 void sxth(Register dst, Register src, int rotate = 0, Condition cond = al);
954 void sxtah(Register dst, Register src1, Register src2, int rotate = 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000955 Condition cond = al);
956
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400957 void uxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
958 void uxtab(Register dst, Register src1, Register src2, int rotate = 0,
959 Condition cond = al);
960 void uxtb16(Register dst, Register src, int rotate = 0, Condition cond = al);
961 void uxth(Register dst, Register src, int rotate = 0, Condition cond = al);
962 void uxtah(Register dst, Register src1, Register src2, int rotate = 0,
963 Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964
Ben Murdoch097c5b22016-05-18 11:27:45 +0100965 // Reverse the bits in a register.
966 void rbit(Register dst, Register src, Condition cond = al);
967
Steve Blocka7e24c12009-10-30 11:49:00 +0000968 // Status register access instructions
969
970 void mrs(Register dst, SRegister s, Condition cond = al);
971 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
972
973 // Load/Store instructions
974 void ldr(Register dst, const MemOperand& src, Condition cond = al);
975 void str(Register src, const MemOperand& dst, Condition cond = al);
976 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
977 void strb(Register src, const MemOperand& dst, Condition cond = al);
978 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
979 void strh(Register src, const MemOperand& dst, Condition cond = al);
980 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
981 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
Leon Clarkef7060e22010-06-03 12:02:55 +0100982 void ldrd(Register dst1,
983 Register dst2,
984 const MemOperand& src, Condition cond = al);
985 void strd(Register src1,
986 Register src2,
987 const MemOperand& dst, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000988
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000989 // Preload instructions
990 void pld(const MemOperand& address);
991
Steve Blocka7e24c12009-10-30 11:49:00 +0000992 // Load/Store multiple instructions
993 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
994 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
995
Steve Blocka7e24c12009-10-30 11:49:00 +0000996 // Exception-generating instructions and debugging support
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800997 void stop(const char* msg,
998 Condition cond = al,
999 int32_t code = kDefaultStopCode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001000
1001 void bkpt(uint32_t imm16); // v5 and above
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001002 void svc(uint32_t imm24, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +00001003
Ben Murdoch097c5b22016-05-18 11:27:45 +01001004 // Synchronization instructions
1005 void dmb(BarrierOption option);
1006 void dsb(BarrierOption option);
1007 void isb(BarrierOption option);
1008
Steve Blocka7e24c12009-10-30 11:49:00 +00001009 // Coprocessor instructions
1010
1011 void cdp(Coprocessor coproc, int opcode_1,
1012 CRegister crd, CRegister crn, CRegister crm,
1013 int opcode_2, Condition cond = al);
1014
1015 void cdp2(Coprocessor coproc, int opcode_1,
1016 CRegister crd, CRegister crn, CRegister crm,
1017 int opcode_2); // v5 and above
1018
1019 void mcr(Coprocessor coproc, int opcode_1,
1020 Register rd, CRegister crn, CRegister crm,
1021 int opcode_2 = 0, Condition cond = al);
1022
1023 void mcr2(Coprocessor coproc, int opcode_1,
1024 Register rd, CRegister crn, CRegister crm,
1025 int opcode_2 = 0); // v5 and above
1026
1027 void mrc(Coprocessor coproc, int opcode_1,
1028 Register rd, CRegister crn, CRegister crm,
1029 int opcode_2 = 0, Condition cond = al);
1030
1031 void mrc2(Coprocessor coproc, int opcode_1,
1032 Register rd, CRegister crn, CRegister crm,
1033 int opcode_2 = 0); // v5 and above
1034
1035 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1036 LFlag l = Short, Condition cond = al);
1037 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1038 LFlag l = Short, Condition cond = al);
1039
1040 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1041 LFlag l = Short); // v5 and above
1042 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1043 LFlag l = Short); // v5 and above
1044
Steve Blockd0582a62009-12-15 09:54:21 +00001045 // Support for VFP.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001046 // All these APIs support S0 to S31 and D0 to D31.
Steve Blockd0582a62009-12-15 09:54:21 +00001047
Leon Clarked91b9f72010-01-27 17:25:45 +00001048 void vldr(const DwVfpRegister dst,
1049 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001050 int offset,
1051 const Condition cond = al);
1052 void vldr(const DwVfpRegister dst,
1053 const MemOperand& src,
Leon Clarked91b9f72010-01-27 17:25:45 +00001054 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001055
1056 void vldr(const SwVfpRegister dst,
1057 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001058 int offset,
1059 const Condition cond = al);
1060 void vldr(const SwVfpRegister dst,
1061 const MemOperand& src,
Steve Block6ded16b2010-05-10 14:33:55 +01001062 const Condition cond = al);
1063
Leon Clarked91b9f72010-01-27 17:25:45 +00001064 void vstr(const DwVfpRegister src,
1065 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001066 int offset,
1067 const Condition cond = al);
1068 void vstr(const DwVfpRegister src,
1069 const MemOperand& dst,
Leon Clarked91b9f72010-01-27 17:25:45 +00001070 const Condition cond = al);
Steve Block8defd9f2010-07-08 12:39:36 +01001071
Iain Merrick75681382010-08-19 15:07:18 +01001072 void vstr(const SwVfpRegister src,
1073 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001074 int offset,
1075 const Condition cond = al);
1076 void vstr(const SwVfpRegister src,
1077 const MemOperand& dst,
Iain Merrick75681382010-08-19 15:07:18 +01001078 const Condition cond = al);
1079
Ben Murdoch8b112d22011-06-08 16:22:53 +01001080 void vldm(BlockAddrMode am,
1081 Register base,
1082 DwVfpRegister first,
1083 DwVfpRegister last,
1084 Condition cond = al);
1085
1086 void vstm(BlockAddrMode am,
1087 Register base,
1088 DwVfpRegister first,
1089 DwVfpRegister last,
1090 Condition cond = al);
1091
1092 void vldm(BlockAddrMode am,
1093 Register base,
1094 SwVfpRegister first,
1095 SwVfpRegister last,
1096 Condition cond = al);
1097
1098 void vstm(BlockAddrMode am,
1099 Register base,
1100 SwVfpRegister first,
1101 SwVfpRegister last,
1102 Condition cond = al);
1103
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001104 void vmov(const SwVfpRegister dst, float imm);
Steve Block8defd9f2010-07-08 12:39:36 +01001105 void vmov(const DwVfpRegister dst,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001106 double imm,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001107 const Register scratch = no_reg);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001108 void vmov(const SwVfpRegister dst,
1109 const SwVfpRegister src,
1110 const Condition cond = al);
1111 void vmov(const DwVfpRegister dst,
Steve Block8defd9f2010-07-08 12:39:36 +01001112 const DwVfpRegister src,
1113 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001114 void vmov(const DwVfpRegister dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001115 const VmovIndex index,
1116 const Register src,
1117 const Condition cond = al);
1118 void vmov(const Register dst,
1119 const VmovIndex index,
1120 const DwVfpRegister src,
1121 const Condition cond = al);
1122 void vmov(const DwVfpRegister dst,
Leon Clarkee46be812010-01-19 14:06:41 +00001123 const Register src1,
Steve Blockd0582a62009-12-15 09:54:21 +00001124 const Register src2,
Leon Clarkee46be812010-01-19 14:06:41 +00001125 const Condition cond = al);
1126 void vmov(const Register dst1,
1127 const Register dst2,
1128 const DwVfpRegister src,
1129 const Condition cond = al);
1130 void vmov(const SwVfpRegister dst,
1131 const Register src,
1132 const Condition cond = al);
1133 void vmov(const Register dst,
1134 const SwVfpRegister src,
1135 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001136 void vcvt_f64_s32(const DwVfpRegister dst,
1137 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001138 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001139 const Condition cond = al);
1140 void vcvt_f32_s32(const SwVfpRegister dst,
1141 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001142 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001143 const Condition cond = al);
1144 void vcvt_f64_u32(const DwVfpRegister dst,
1145 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001146 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001147 const Condition cond = al);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001148 void vcvt_f32_u32(const SwVfpRegister dst,
1149 const SwVfpRegister src,
1150 VFPConversionMode mode = kDefaultRoundToZero,
1151 const Condition cond = al);
1152 void vcvt_s32_f32(const SwVfpRegister dst,
1153 const SwVfpRegister src,
1154 VFPConversionMode mode = kDefaultRoundToZero,
1155 const Condition cond = al);
1156 void vcvt_u32_f32(const SwVfpRegister dst,
1157 const SwVfpRegister src,
1158 VFPConversionMode mode = kDefaultRoundToZero,
1159 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001160 void vcvt_s32_f64(const SwVfpRegister dst,
1161 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001162 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001163 const Condition cond = al);
1164 void vcvt_u32_f64(const SwVfpRegister dst,
1165 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001166 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001167 const Condition cond = al);
1168 void vcvt_f64_f32(const DwVfpRegister dst,
1169 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001170 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001171 const Condition cond = al);
1172 void vcvt_f32_f64(const SwVfpRegister dst,
1173 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001174 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001175 const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001176 void vcvt_f64_s32(const DwVfpRegister dst,
1177 int fraction_bits,
1178 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180 void vmrs(const Register dst, const Condition cond = al);
1181 void vmsr(const Register dst, const Condition cond = al);
1182
Steve Block44f0eee2011-05-26 01:26:41 +01001183 void vneg(const DwVfpRegister dst,
1184 const DwVfpRegister src,
1185 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001186 void vneg(const SwVfpRegister dst, const SwVfpRegister src,
1187 const Condition cond = al);
Steve Block1e0659c2011-05-24 12:43:12 +01001188 void vabs(const DwVfpRegister dst,
1189 const DwVfpRegister src,
1190 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001191 void vabs(const SwVfpRegister dst, const SwVfpRegister src,
1192 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001193 void vadd(const DwVfpRegister dst,
1194 const DwVfpRegister src1,
1195 const DwVfpRegister src2,
1196 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001197 void vadd(const SwVfpRegister dst, const SwVfpRegister src1,
1198 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001199 void vsub(const DwVfpRegister dst,
1200 const DwVfpRegister src1,
1201 const DwVfpRegister src2,
1202 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001203 void vsub(const SwVfpRegister dst, const SwVfpRegister src1,
1204 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001205 void vmul(const DwVfpRegister dst,
1206 const DwVfpRegister src1,
1207 const DwVfpRegister src2,
1208 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001209 void vmul(const SwVfpRegister dst, const SwVfpRegister src1,
1210 const SwVfpRegister src2, const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001211 void vmla(const DwVfpRegister dst,
1212 const DwVfpRegister src1,
1213 const DwVfpRegister src2,
1214 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001215 void vmla(const SwVfpRegister dst, const SwVfpRegister src1,
1216 const SwVfpRegister src2, const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001217 void vmls(const DwVfpRegister dst,
1218 const DwVfpRegister src1,
1219 const DwVfpRegister src2,
1220 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 void vmls(const SwVfpRegister dst, const SwVfpRegister src1,
1222 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001223 void vdiv(const DwVfpRegister dst,
1224 const DwVfpRegister src1,
1225 const DwVfpRegister src2,
1226 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001227 void vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
1228 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001229 void vcmp(const DwVfpRegister src1,
1230 const DwVfpRegister src2,
Steve Blockd0582a62009-12-15 09:54:21 +00001231 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232 void vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
1233 const Condition cond = al);
Iain Merrick75681382010-08-19 15:07:18 +01001234 void vcmp(const DwVfpRegister src1,
1235 const double src2,
Iain Merrick75681382010-08-19 15:07:18 +01001236 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001237 void vcmp(const SwVfpRegister src1, const float src2,
Russell Brenner90bac252010-11-18 13:33:46 -08001238 const Condition cond = al);
Ben Murdochc5610432016-08-08 18:44:38 +01001239
1240 // VSEL supports cond in {eq, ne, ge, lt, gt, le, vs, vc}.
1241 void vsel(const Condition cond,
1242 const DwVfpRegister dst,
1243 const DwVfpRegister src1,
1244 const DwVfpRegister src2);
1245 void vsel(const Condition cond,
1246 const SwVfpRegister dst,
1247 const SwVfpRegister src1,
1248 const SwVfpRegister src2);
1249
Steve Block8defd9f2010-07-08 12:39:36 +01001250 void vsqrt(const DwVfpRegister dst,
1251 const DwVfpRegister src,
1252 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001253 void vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
1254 const Condition cond = al);
Steve Blockd0582a62009-12-15 09:54:21 +00001255
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001256 // ARMv8 rounding instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001257 void vrinta(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001258 void vrinta(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001259 void vrintn(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001260 void vrintn(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001261 void vrintm(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001262 void vrintm(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001263 void vrintp(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001264 void vrintp(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001265 void vrintz(const SwVfpRegister dst, const SwVfpRegister src,
1266 const Condition cond = al);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001267 void vrintz(const DwVfpRegister dst, const DwVfpRegister src,
1268 const Condition cond = al);
1269
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001270 // Support for NEON.
1271 // All these APIs support D0 to D31 and Q0 to Q15.
1272
1273 void vld1(NeonSize size,
1274 const NeonListOperand& dst,
1275 const NeonMemOperand& src);
1276 void vst1(NeonSize size,
1277 const NeonListOperand& src,
1278 const NeonMemOperand& dst);
1279 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1280
Steve Blocka7e24c12009-10-30 11:49:00 +00001281 // Pseudo instructions
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001282
1283 // Different nop operations are used by the code generator to detect certain
1284 // states of the generated code.
1285 enum NopMarkerTypes {
1286 NON_MARKING_NOP = 0,
1287 DEBUG_BREAK_NOP,
1288 // IC markers.
1289 PROPERTY_ACCESS_INLINED,
1290 PROPERTY_ACCESS_INLINED_CONTEXT,
1291 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1292 // Helper values.
1293 LAST_CODE_MARKER,
1294 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1295 };
1296
1297 void nop(int type = 0); // 0 is the default non-marking type.
Steve Blocka7e24c12009-10-30 11:49:00 +00001298
1299 void push(Register src, Condition cond = al) {
1300 str(src, MemOperand(sp, 4, NegPreIndex), cond);
1301 }
1302
1303 void pop(Register dst, Condition cond = al) {
1304 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1305 }
1306
1307 void pop() {
1308 add(sp, sp, Operand(kPointerSize));
1309 }
1310
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001311 void vpush(DwVfpRegister src, Condition cond = al) {
1312 vstm(db_w, sp, src, src, cond);
1313 }
1314
1315 void vpop(DwVfpRegister dst, Condition cond = al) {
1316 vldm(ia_w, sp, dst, dst, cond);
1317 }
1318
Steve Blocka7e24c12009-10-30 11:49:00 +00001319 // Jump unconditionally to given label.
1320 void jmp(Label* L) { b(L, al); }
1321
1322 // Check the code size generated from label to here.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001323 int SizeOfCodeGeneratedSince(Label* label) {
1324 return pc_offset() - label->pos();
1325 }
1326
1327 // Check the number of instructions generated from label to here.
1328 int InstructionsGeneratedSince(Label* label) {
1329 return SizeOfCodeGeneratedSince(label) / kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001330 }
1331
Steve Blockd0582a62009-12-15 09:54:21 +00001332 // Check whether an immediate fits an addressing mode 1 instruction.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001333 static bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1334
1335 // Check whether an immediate fits an addressing mode 2 instruction.
1336 bool ImmediateFitsAddrMode2Instruction(int32_t imm32);
Steve Blockd0582a62009-12-15 09:54:21 +00001337
Steve Block6ded16b2010-05-10 14:33:55 +01001338 // Class for scoping postponing the constant pool generation.
1339 class BlockConstPoolScope {
1340 public:
1341 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1342 assem_->StartBlockConstPool();
1343 }
1344 ~BlockConstPoolScope() {
1345 assem_->EndBlockConstPool();
1346 }
1347
1348 private:
1349 Assembler* assem_;
1350
1351 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1352 };
1353
Steve Blocka7e24c12009-10-30 11:49:00 +00001354 // Debugging
1355
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001356 // Mark generator continuation.
1357 void RecordGeneratorContinuation();
Steve Blocka7e24c12009-10-30 11:49:00 +00001358
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001359 // Mark address of a debug break slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001360 void RecordDebugBreakSlot(RelocInfo::Mode mode);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001361
Ben Murdoch257744e2011-11-30 15:57:28 +00001362 // Record the AST id of the CallIC being compiled, so that it can be placed
1363 // in the relocation information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001364 void SetRecordedAstId(TypeFeedbackId ast_id) {
1365 DCHECK(recorded_ast_id_.IsNone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001366 recorded_ast_id_ = ast_id;
1367 }
1368
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001369 TypeFeedbackId RecordedAstId() {
1370 DCHECK(!recorded_ast_id_.IsNone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001371 return recorded_ast_id_;
1372 }
1373
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
Ben Murdoch257744e2011-11-30 15:57:28 +00001375
Steve Blocka7e24c12009-10-30 11:49:00 +00001376 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001377 // Use --code-comments to enable.
Steve Blocka7e24c12009-10-30 11:49:00 +00001378 void RecordComment(const char* msg);
1379
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001380 // Record a deoptimization reason that can be used by a log or cpu profiler.
1381 // Use --trace-deopt to enable.
Ben Murdochc5610432016-08-08 18:44:38 +01001382 void RecordDeoptReason(const int reason, int raw_position, int id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001383
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384 // Record the emission of a constant pool.
1385 //
1386 // The emission of constant pool depends on the size of the code generated and
1387 // the number of RelocInfo recorded.
1388 // The Debug mechanism needs to map code offsets between two versions of a
1389 // function, compiled with and without debugger support (see for example
1390 // Debug::PrepareForBreakPoints()).
1391 // Compiling functions with debugger support generates additional code
1392 // (DebugCodegen::GenerateSlot()). This may affect the emission of the
1393 // constant pools and cause the version of the code with debugger support to
1394 // have constant pools generated in different places.
1395 // Recording the position and size of emitted constant pools allows to
1396 // correctly compute the offset mappings between the different versions of a
1397 // function in all situations.
1398 //
1399 // The parameter indicates the size of the constant pool (in bytes), including
1400 // the marker and branch over the data.
1401 void RecordConstPool(int size);
1402
Ben Murdochb8e0da22011-05-16 14:20:40 +01001403 // Writes a single byte or word of data in the code stream. Used
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001404 // for inline tables, e.g., jump-tables. CheckConstantPool() should be
1405 // called before any use of db/dd/dq/dp to ensure that constant pools
Ben Murdochb8e0da22011-05-16 14:20:40 +01001406 // are not emitted as part of the tables generated.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001407 void db(uint8_t data);
1408 void dd(uint32_t data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001409 void dq(uint64_t data);
1410 void dp(uintptr_t data) { dd(data); }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001411
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001412 // Emits the address of the code stub's first instruction.
1413 void emit_code_stub_address(Code* stub);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001414
Ben Murdochda12d292016-06-02 14:46:10 +01001415 AssemblerPositionsRecorder* positions_recorder() {
1416 return &positions_recorder_;
1417 }
Steve Block6ded16b2010-05-10 14:33:55 +01001418
1419 // Read/patch instructions
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001420 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1421 void instr_at_put(int pos, Instr instr) {
1422 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1423 }
Steve Block6ded16b2010-05-10 14:33:55 +01001424 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1425 static void instr_at_put(byte* pc, Instr instr) {
1426 *reinterpret_cast<Instr*>(pc) = instr;
1427 }
Steve Block1e0659c2011-05-24 12:43:12 +01001428 static Condition GetCondition(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001429 static bool IsBranch(Instr instr);
1430 static int GetBranchOffset(Instr instr);
1431 static bool IsLdrRegisterImmediate(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001432 static bool IsVldrDRegisterImmediate(Instr instr);
1433 static Instr GetConsantPoolLoadPattern();
1434 static Instr GetConsantPoolLoadMask();
1435 static bool IsLdrPpRegOffset(Instr instr);
1436 static Instr GetLdrPpRegOffsetPattern();
1437 static bool IsLdrPpImmediateOffset(Instr instr);
1438 static bool IsVldrDPpImmediateOffset(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001439 static int GetLdrRegisterImmediateOffset(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001440 static int GetVldrDRegisterImmediateOffset(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001441 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001442 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
Kristian Monsen50ef84f2010-07-29 15:18:00 +01001443 static bool IsStrRegisterImmediate(Instr instr);
1444 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1445 static bool IsAddRegisterImmediate(Instr instr);
1446 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
Leon Clarkef7060e22010-06-03 12:02:55 +01001447 static Register GetRd(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001448 static Register GetRn(Instr instr);
1449 static Register GetRm(Instr instr);
Leon Clarkef7060e22010-06-03 12:02:55 +01001450 static bool IsPush(Instr instr);
1451 static bool IsPop(Instr instr);
1452 static bool IsStrRegFpOffset(Instr instr);
1453 static bool IsLdrRegFpOffset(Instr instr);
1454 static bool IsStrRegFpNegOffset(Instr instr);
1455 static bool IsLdrRegFpNegOffset(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001456 static bool IsLdrPcImmediateOffset(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001457 static bool IsVldrDPcImmediateOffset(Instr instr);
1458 static bool IsBlxReg(Instr instr);
1459 static bool IsBlxIp(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001460 static bool IsTstImmediate(Instr instr);
1461 static bool IsCmpRegister(Instr instr);
1462 static bool IsCmpImmediate(Instr instr);
1463 static Register GetCmpImmediateRegister(Instr instr);
1464 static int GetCmpImmediateRawImmediate(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001465 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001466 static bool IsMovImmed(Instr instr);
1467 static bool IsOrrImmed(Instr instr);
1468 static bool IsMovT(Instr instr);
1469 static Instr GetMovTPattern();
1470 static bool IsMovW(Instr instr);
1471 static Instr GetMovWPattern();
1472 static Instr EncodeMovwImmediate(uint32_t immediate);
1473 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate);
1474 static int DecodeShiftImm(Instr instr);
1475 static Instr PatchShiftImm(Instr instr, int immed);
Steve Block6ded16b2010-05-10 14:33:55 +01001476
Ben Murdoch257744e2011-11-30 15:57:28 +00001477 // Constants in pools are accessed via pc relative addressing, which can
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001478 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1479 // PC-relative loads, thereby defining a maximum distance between the
1480 // instruction and the accessed constant.
1481 static const int kMaxDistToIntPool = 4*KB;
1482 static const int kMaxDistToFPPool = 1*KB;
1483 // All relocations could be integer, it therefore acts as the limit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001484 static const int kMinNumPendingConstants = 4;
1485 static const int kMaxNumPending32Constants = kMaxDistToIntPool / kInstrSize;
1486 static const int kMaxNumPending64Constants = kMaxDistToFPPool / kInstrSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00001487
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001488 // Postpone the generation of the constant pool for the specified number of
1489 // instructions.
1490 void BlockConstPoolFor(int instructions);
1491
1492 // Check if is time to emit a constant pool.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001493 void CheckConstPool(bool force_emit, bool require_jump);
Steve Blocka7e24c12009-10-30 11:49:00 +00001494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001495 void MaybeCheckConstPool() {
1496 if (pc_offset() >= next_buffer_check_) {
1497 CheckConstPool(false, true);
1498 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 }
1500
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001501 int EmitEmbeddedConstantPool() {
1502 DCHECK(FLAG_enable_embedded_constant_pool);
1503 return constant_pool_builder_.Emit(this);
1504 }
1505
1506 bool ConstantPoolAccessIsInOverflow() const {
1507 return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1508 ConstantPoolEntry::OVERFLOWED;
1509 }
1510
1511 void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1512 ConstantPoolEntry::Access access,
1513 ConstantPoolEntry::Type type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001514
Steve Blocka7e24c12009-10-30 11:49:00 +00001515 protected:
Ben Murdoch257744e2011-11-30 15:57:28 +00001516 // Relocation for a type-recording IC has the AST id added to it. This
1517 // member variable is a way to pass the information from the call site to
1518 // the relocation info.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001519 TypeFeedbackId recorded_ast_id_;
Steve Block44f0eee2011-05-26 01:26:41 +01001520
Steve Blocka7e24c12009-10-30 11:49:00 +00001521 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1522
Steve Blocka7e24c12009-10-30 11:49:00 +00001523 // Decode branch instruction at pos and return branch target pos
1524 int target_at(int pos);
1525
1526 // Patch branch instruction at pos to branch to given branch target pos
1527 void target_at_put(int pos, int target_pos);
1528
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001529 // Prevent contant pool emission until EndBlockConstPool is called.
1530 // Call to this function can be nested but must be followed by an equal
1531 // number of call to EndBlockConstpool.
1532 void StartBlockConstPool() {
1533 if (const_pool_blocked_nesting_++ == 0) {
1534 // Prevent constant pool checks happening by setting the next check to
1535 // the biggest possible offset.
1536 next_buffer_check_ = kMaxInt;
1537 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001538 }
1539
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001540 // Resume constant pool emission. Need to be called as many time as
1541 // StartBlockConstPool to have an effect.
Steve Block6ded16b2010-05-10 14:33:55 +01001542 void EndBlockConstPool() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001543 if (--const_pool_blocked_nesting_ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001544#ifdef DEBUG
1545 // Max pool start (if we need a jump and an alignment).
1546 int start = pc_offset() + kInstrSize + 2 * kPointerSize;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001547 // Check the constant pool hasn't been blocked for too long.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001548 DCHECK((num_pending_32_bit_constants_ == 0) ||
1549 (start + num_pending_64_bit_constants_ * kDoubleSize <
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001550 (first_const_pool_32_use_ + kMaxDistToIntPool)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001551 DCHECK((num_pending_64_bit_constants_ == 0) ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001552 (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
1553#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001554 // Two cases:
1555 // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1556 // still blocked
1557 // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1558 // trigger a check.
1559 next_buffer_check_ = no_const_pool_before_;
1560 }
Steve Block6ded16b2010-05-10 14:33:55 +01001561 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001562
1563 bool is_const_pool_blocked() const {
1564 return (const_pool_blocked_nesting_ > 0) ||
1565 (pc_offset() < no_const_pool_before_);
1566 }
Steve Block6ded16b2010-05-10 14:33:55 +01001567
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001568 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00001569 int next_buffer_check_; // pc offset of next buffer check
1570
1571 // Code generation
1572 // The relocation writer's position is at least kGap bytes below the end of
1573 // the generated instructions. This is so that multi-instruction sequences do
1574 // not have to check for overflow. The same is true for writes of large
1575 // relocation info entries.
1576 static const int kGap = 32;
Steve Blocka7e24c12009-10-30 11:49:00 +00001577
1578 // Constant pool generation
1579 // Pools are emitted in the instruction stream, preferably after unconditional
1580 // jumps or after returns from functions (in dead code locations).
1581 // If a long code sequence does not contain unconditional jumps, it is
1582 // necessary to emit the constant pool before the pool gets too far from the
1583 // location it is accessed from. In this case, we emit a jump over the emitted
1584 // constant pool.
1585 // Constants in the pool may be addresses of functions that gets relocated;
1586 // if so, a relocation info entry is associated to the constant pool entry.
1587
1588 // Repeated checking whether the constant pool should be emitted is rather
1589 // expensive. By default we only check again once a number of instructions
1590 // has been generated. That also means that the sizing of the buffers is not
1591 // an exact science, and that we rely on some slop to not overrun buffers.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001592 static const int kCheckPoolIntervalInst = 32;
1593 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001594
1595
Steve Block6ded16b2010-05-10 14:33:55 +01001596 // Emission of the constant pool may be blocked in some code sequences.
1597 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1598 int no_const_pool_before_; // Block emission before this pc offset.
Steve Blocka7e24c12009-10-30 11:49:00 +00001599
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001600 // Keep track of the first instruction requiring a constant pool entry
1601 // since the previous constant pool was emitted.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001602 int first_const_pool_32_use_;
1603 int first_const_pool_64_use_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001604
1605 // Relocation info generation
1606 // Each relocation is encoded as a variable size value
1607 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1608 RelocInfoWriter reloc_info_writer;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001609
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001610 // ConstantPoolEntry records are used during code generation as temporary
Steve Blocka7e24c12009-10-30 11:49:00 +00001611 // containers for constants and code target addresses until they are emitted
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001612 // to the constant pool. These records are temporarily stored in a separate
1613 // buffer until a constant pool is emitted.
Steve Blocka7e24c12009-10-30 11:49:00 +00001614 // If every instruction in a long sequence is accessing the pool, we need one
1615 // pending relocation entry per instruction.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001616
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001617 // The buffers of pending constant pool entries.
1618 ConstantPoolEntry pending_32_bit_constants_buffer_[kMinNumPendingConstants];
1619 ConstantPoolEntry pending_64_bit_constants_buffer_[kMinNumPendingConstants];
1620 ConstantPoolEntry* pending_32_bit_constants_;
1621 ConstantPoolEntry* pending_64_bit_constants_;
1622 // Number of pending constant pool entries in the 32 bits buffer.
1623 int num_pending_32_bit_constants_;
1624 // Number of pending constant pool entries in the 64 bits buffer.
1625 int num_pending_64_bit_constants_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001626
1627 ConstantPoolBuilder constant_pool_builder_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001628
1629 // The bound position, before this we cannot do instruction elimination.
1630 int last_bound_pos_;
1631
Steve Blocka7e24c12009-10-30 11:49:00 +00001632 // Code emission
1633 inline void CheckBuffer();
1634 void GrowBuffer();
1635 inline void emit(Instr x);
1636
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001637 // 32-bit immediate values
1638 void move_32_bit_immediate(Register rd,
1639 const Operand& x,
1640 Condition cond = al);
1641
Steve Blocka7e24c12009-10-30 11:49:00 +00001642 // Instruction generation
1643 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1644 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1645 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1646 void addrmod4(Instr instr, Register rn, RegList rl);
1647 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1648
1649 // Labels
1650 void print(Label* L);
1651 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001652 void next(Label* L);
1653
1654 // Record reloc info for current pc_
1655 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001656 ConstantPoolEntry::Access ConstantPoolAddEntry(int position,
1657 RelocInfo::Mode rmode,
1658 intptr_t value);
1659 ConstantPoolEntry::Access ConstantPoolAddEntry(int position, double value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001660
Steve Blocka7e24c12009-10-30 11:49:00 +00001661 friend class RelocInfo;
1662 friend class CodePatcher;
Steve Block6ded16b2010-05-10 14:33:55 +01001663 friend class BlockConstPoolScope;
Ben Murdochda12d292016-06-02 14:46:10 +01001664 AssemblerPositionsRecorder positions_recorder_;
1665 friend class AssemblerPositionsRecorder;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001666 friend class EnsureSpace;
Steve Blocka7e24c12009-10-30 11:49:00 +00001667};
1668
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001669
1670class EnsureSpace BASE_EMBEDDED {
1671 public:
1672 explicit EnsureSpace(Assembler* assembler) {
1673 assembler->CheckBuffer();
1674 }
1675};
1676
1677
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001678} // namespace internal
1679} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +00001680
1681#endif // V8_ARM_ASSEMBLER_ARM_H_