blob: d381653bde29e748bb11e0338bd2d08ef4bdb752 [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
60#define DOUBLE_REGISTERS(V) \
61 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
62 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
63 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
64 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
65
66#define ALLOCATABLE_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) \
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_NO_VFP32_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// clang-format on
76
Steve Blocka7e24c12009-10-30 11:49:00 +000077// CPU Registers.
78//
79// 1) We would prefer to use an enum, but enum values are assignment-
80// compatible with int, which has caused code-generation bugs.
81//
82// 2) We would prefer to use a class instead of a struct but we don't like
83// the register initialization to depend on the particular initialization
84// order (which appears to be different on OS X, Linux, and Windows for the
85// installed versions of C++ we tried). Using a struct permits C-style
86// "initialization". Also, the Register objects cannot be const as this
87// forces initialization stubs in MSVC, making us dependent on initialization
88// order.
89//
90// 3) By not using an enum, we are possibly preventing the compiler from
91// doing certain constant folds, which may significantly reduce the
92// code generated for some assembly instructions (because they boil down
93// to a few constants). If this is a problem, we could change the code
94// such that we use an enum in optimized mode, and the struct in debug
95// mode. This way we get the compile-time error checking in debug mode
96// and best performance in optimized code.
Steve Block9fac8402011-05-12 15:51:54 +010097
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098struct Register {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 enum Code {
100#define REGISTER_CODE(R) kCode_##R,
101 GENERAL_REGISTERS(REGISTER_CODE)
102#undef REGISTER_CODE
103 kAfterLast,
104 kCode_no_reg = -1
105 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000106
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 static const int kNumRegisters = Code::kAfterLast;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108
109 static Register from_code(int code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 DCHECK(code >= 0);
111 DCHECK(code < kNumRegisters);
112 Register r = {code};
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000113 return r;
114 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 const char* ToString();
116 bool IsAllocatable() const;
117 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
118 bool is(Register reg) const { return reg_code == reg.reg_code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000119 int code() const {
120 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121 return reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122 }
123 int bit() const {
124 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 return 1 << reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127 void set_code(int code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 reg_code = code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129 DCHECK(is_valid());
130 }
131
132 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 int reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000134};
135
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136// r7: context register
137// r8: constant pool pointer register if FLAG_enable_embedded_constant_pool.
138// r9: lithium scratch
139#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
140GENERAL_REGISTERS(DECLARE_REGISTER)
141#undef DECLARE_REGISTER
142const Register no_reg = {Register::kCode_no_reg};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100143
Leon Clarkee46be812010-01-19 14:06:41 +0000144// Single word VFP register.
145struct SwVfpRegister {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 static const int kSizeInBytes = 4;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 bool is_valid() const { return 0 <= reg_code && reg_code < 32; }
148 bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100149 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000150 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 return reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000152 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100153 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 return 1 << reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000156 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100157 void split_code(int* vm, int* m) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159 *m = reg_code & 0x1;
160 *vm = reg_code >> 1;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100161 }
Leon Clarkee46be812010-01-19 14:06:41 +0000162
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000163 int reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000164};
165
166
167// Double word VFP register.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168struct DoubleRegister {
169 enum Code {
170#define REGISTER_CODE(R) kCode_##R,
171 DOUBLE_REGISTERS(REGISTER_CODE)
172#undef REGISTER_CODE
173 kAfterLast,
174 kCode_no_reg = -1
175 };
176
177 static const int kMaxNumRegisters = Code::kAfterLast;
178
179 inline static int NumRegisters();
180
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000181 // A few double registers are reserved: one as a scratch register and one to
182 // hold 0.0, that does not fit in the immediate field of vmov instructions.
183 // d14: 0.0
184 // d15: scratch register.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 static const int kSizeInBytes = 8;
186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 const char* ToString();
188 bool IsAllocatable() const;
189 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
190 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100191 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000192 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 return reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000194 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100195 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 return 1 << reg_code;
198 }
199
200 static DoubleRegister from_code(int code) {
201 DoubleRegister r = {code};
202 return r;
Leon Clarkee46be812010-01-19 14:06:41 +0000203 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100204 void split_code(int* vm, int* m) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 *m = (reg_code & 0x10) >> 4;
207 *vm = reg_code & 0x0F;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100208 }
Leon Clarkee46be812010-01-19 14:06:41 +0000209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 int reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000211};
212
213
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214typedef DoubleRegister DwVfpRegister;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100215
216
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217// Double word VFP register d0-15.
218struct LowDwVfpRegister {
219 public:
220 static const int kMaxNumLowRegisters = 16;
221 operator DwVfpRegister() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 DwVfpRegister r = { reg_code };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000223 return r;
224 }
225 static LowDwVfpRegister from_code(int code) {
226 LowDwVfpRegister r = { code };
227 return r;
228 }
229
230 bool is_valid() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 return 0 <= reg_code && reg_code < kMaxNumLowRegisters;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
234 bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 int code() const {
236 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 return reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 }
239 SwVfpRegister low() const {
240 SwVfpRegister reg;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241 reg.reg_code = reg_code * 2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242
243 DCHECK(reg.is_valid());
244 return reg;
245 }
246 SwVfpRegister high() const {
247 SwVfpRegister reg;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 reg.reg_code = (reg_code * 2) + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249
250 DCHECK(reg.is_valid());
251 return reg;
252 }
253
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254 int reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255};
256
257
258// Quad word NEON register.
259struct QwNeonRegister {
260 static const int kMaxNumRegisters = 16;
261
262 static QwNeonRegister from_code(int code) {
263 QwNeonRegister r = { code };
264 return r;
265 }
266
267 bool is_valid() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 return (0 <= reg_code) && (reg_code < kMaxNumRegisters);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270 bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 int code() const {
272 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000273 return reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 }
275 void split_code(int* vm, int* m) const {
276 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 int encoded_code = reg_code << 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 *m = (encoded_code & 0x10) >> 4;
279 *vm = encoded_code & 0x0F;
280 }
281
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 int reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283};
284
285
286typedef QwNeonRegister QuadRegister;
287
Ben Murdoch097c5b22016-05-18 11:27:45 +0100288typedef QwNeonRegister Simd128Register;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289
Steve Block6ded16b2010-05-10 14:33:55 +0100290// Support for the VFP registers s0 to s31 (d0 to d15).
Leon Clarkee46be812010-01-19 14:06:41 +0000291// Note that "s(N):s(N+1)" is the same as "d(N/2)".
Steve Block6ded16b2010-05-10 14:33:55 +0100292const SwVfpRegister s0 = { 0 };
293const SwVfpRegister s1 = { 1 };
294const SwVfpRegister s2 = { 2 };
295const SwVfpRegister s3 = { 3 };
296const SwVfpRegister s4 = { 4 };
297const SwVfpRegister s5 = { 5 };
298const SwVfpRegister s6 = { 6 };
299const SwVfpRegister s7 = { 7 };
300const SwVfpRegister s8 = { 8 };
301const SwVfpRegister s9 = { 9 };
302const SwVfpRegister s10 = { 10 };
303const SwVfpRegister s11 = { 11 };
304const SwVfpRegister s12 = { 12 };
305const SwVfpRegister s13 = { 13 };
306const SwVfpRegister s14 = { 14 };
307const SwVfpRegister s15 = { 15 };
308const SwVfpRegister s16 = { 16 };
309const SwVfpRegister s17 = { 17 };
310const SwVfpRegister s18 = { 18 };
311const SwVfpRegister s19 = { 19 };
312const SwVfpRegister s20 = { 20 };
313const SwVfpRegister s21 = { 21 };
314const SwVfpRegister s22 = { 22 };
315const SwVfpRegister s23 = { 23 };
316const SwVfpRegister s24 = { 24 };
317const SwVfpRegister s25 = { 25 };
318const SwVfpRegister s26 = { 26 };
319const SwVfpRegister s27 = { 27 };
320const SwVfpRegister s28 = { 28 };
321const SwVfpRegister s29 = { 29 };
322const SwVfpRegister s30 = { 30 };
323const SwVfpRegister s31 = { 31 };
Leon Clarkee46be812010-01-19 14:06:41 +0000324
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100325const DwVfpRegister no_dreg = { -1 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000326const LowDwVfpRegister d0 = { 0 };
327const LowDwVfpRegister d1 = { 1 };
328const LowDwVfpRegister d2 = { 2 };
329const LowDwVfpRegister d3 = { 3 };
330const LowDwVfpRegister d4 = { 4 };
331const LowDwVfpRegister d5 = { 5 };
332const LowDwVfpRegister d6 = { 6 };
333const LowDwVfpRegister d7 = { 7 };
334const LowDwVfpRegister d8 = { 8 };
335const LowDwVfpRegister d9 = { 9 };
336const LowDwVfpRegister d10 = { 10 };
337const LowDwVfpRegister d11 = { 11 };
338const LowDwVfpRegister d12 = { 12 };
339const LowDwVfpRegister d13 = { 13 };
340const LowDwVfpRegister d14 = { 14 };
341const LowDwVfpRegister d15 = { 15 };
342const DwVfpRegister d16 = { 16 };
343const DwVfpRegister d17 = { 17 };
344const DwVfpRegister d18 = { 18 };
345const DwVfpRegister d19 = { 19 };
346const DwVfpRegister d20 = { 20 };
347const DwVfpRegister d21 = { 21 };
348const DwVfpRegister d22 = { 22 };
349const DwVfpRegister d23 = { 23 };
350const DwVfpRegister d24 = { 24 };
351const DwVfpRegister d25 = { 25 };
352const DwVfpRegister d26 = { 26 };
353const DwVfpRegister d27 = { 27 };
354const DwVfpRegister d28 = { 28 };
355const DwVfpRegister d29 = { 29 };
356const DwVfpRegister d30 = { 30 };
357const DwVfpRegister d31 = { 31 };
358
359const QwNeonRegister q0 = { 0 };
360const QwNeonRegister q1 = { 1 };
361const QwNeonRegister q2 = { 2 };
362const QwNeonRegister q3 = { 3 };
363const QwNeonRegister q4 = { 4 };
364const QwNeonRegister q5 = { 5 };
365const QwNeonRegister q6 = { 6 };
366const QwNeonRegister q7 = { 7 };
367const QwNeonRegister q8 = { 8 };
368const QwNeonRegister q9 = { 9 };
369const QwNeonRegister q10 = { 10 };
370const QwNeonRegister q11 = { 11 };
371const QwNeonRegister q12 = { 12 };
372const QwNeonRegister q13 = { 13 };
373const QwNeonRegister q14 = { 14 };
374const QwNeonRegister q15 = { 15 };
375
Leon Clarkee46be812010-01-19 14:06:41 +0000376
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100377// Aliases for double registers. Defined using #define instead of
378// "static const DwVfpRegister&" because Clang complains otherwise when a
379// compilation unit that includes this header doesn't use the variables.
380#define kFirstCalleeSavedDoubleReg d8
381#define kLastCalleeSavedDoubleReg d15
382#define kDoubleRegZero d14
383#define kScratchDoubleReg d15
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +0100384
Steve Blocka7e24c12009-10-30 11:49:00 +0000385
386// Coprocessor register
387struct CRegister {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 bool is_valid() const { return 0 <= reg_code && reg_code < 16; }
389 bool is(CRegister creg) const { return reg_code == creg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100390 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000391 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 return reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100394 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396 return 1 << reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000397 }
398
Andrei Popescu31002712010-02-23 13:46:05 +0000399 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000400 int reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000401};
402
403
Steve Block6ded16b2010-05-10 14:33:55 +0100404const CRegister no_creg = { -1 };
405
406const CRegister cr0 = { 0 };
407const CRegister cr1 = { 1 };
408const CRegister cr2 = { 2 };
409const CRegister cr3 = { 3 };
410const CRegister cr4 = { 4 };
411const CRegister cr5 = { 5 };
412const CRegister cr6 = { 6 };
413const CRegister cr7 = { 7 };
414const CRegister cr8 = { 8 };
415const CRegister cr9 = { 9 };
416const CRegister cr10 = { 10 };
417const CRegister cr11 = { 11 };
418const CRegister cr12 = { 12 };
419const CRegister cr13 = { 13 };
420const CRegister cr14 = { 14 };
421const CRegister cr15 = { 15 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000422
423
424// Coprocessor number
425enum Coprocessor {
426 p0 = 0,
427 p1 = 1,
428 p2 = 2,
429 p3 = 3,
430 p4 = 4,
431 p5 = 5,
432 p6 = 6,
433 p7 = 7,
434 p8 = 8,
435 p9 = 9,
436 p10 = 10,
437 p11 = 11,
438 p12 = 12,
439 p13 = 13,
440 p14 = 14,
441 p15 = 15
442};
443
444
Steve Blocka7e24c12009-10-30 11:49:00 +0000445// -----------------------------------------------------------------------------
446// Machine instruction Operands
447
448// Class Operand represents a shifter operand in data processing instructions
449class Operand BASE_EMBEDDED {
450 public:
451 // immediate
452 INLINE(explicit Operand(int32_t immediate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000453 RelocInfo::Mode rmode = RelocInfo::NONE32));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000454 INLINE(static Operand Zero()) {
455 return Operand(static_cast<int32_t>(0));
456 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000457 INLINE(explicit Operand(const ExternalReference& f));
Steve Blocka7e24c12009-10-30 11:49:00 +0000458 explicit Operand(Handle<Object> handle);
459 INLINE(explicit Operand(Smi* value));
460
461 // rm
462 INLINE(explicit Operand(Register rm));
463
464 // rm <shift_op> shift_imm
465 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000466 INLINE(static Operand SmiUntag(Register rm)) {
467 return Operand(rm, ASR, kSmiTagSize);
468 }
469 INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
470 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
471 return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
472 }
473 INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
474 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
475 return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
476 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000477
478 // rm <shift_op> rs
479 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
480
481 // Return true if this is a register operand.
482 INLINE(bool is_reg() const);
483
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000484 // Return the number of actual instructions required to implement the given
485 // instruction for this particular operand. This can be a single instruction,
486 // if no load into the ip register is necessary, or anything between 2 and 4
487 // instructions when we need to load from the constant pool (depending upon
488 // whether the constant pool entry is in the small or extended section). If
Steve Block44f0eee2011-05-26 01:26:41 +0100489 // the instruction this operand is used for is a MOV or MVN instruction the
490 // actual instruction to use is required for this calculation. For other
491 // instructions instr is ignored.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000492 //
493 // The value returned is only valid as long as no entries are added to the
494 // constant pool between this call and the actual instruction being emitted.
495 int instructions_required(const Assembler* assembler, Instr instr = 0) const;
496 bool must_output_reloc_info(const Assembler* assembler) const;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100497
498 inline int32_t immediate() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 DCHECK(!rm_.is_valid());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100500 return imm32_;
501 }
502
Steve Blocka7e24c12009-10-30 11:49:00 +0000503 Register rm() const { return rm_; }
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100504 Register rs() const { return rs_; }
505 ShiftOp shift_op() const { return shift_op_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000506
507 private:
508 Register rm_;
509 Register rs_;
510 ShiftOp shift_op_;
511 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
512 int32_t imm32_; // valid if rm_ == no_reg
513 RelocInfo::Mode rmode_;
514
515 friend class Assembler;
516};
517
518
519// Class MemOperand represents a memory operand in load and store instructions
520class MemOperand BASE_EMBEDDED {
521 public:
522 // [rn +/- offset] Offset/NegOffset
523 // [rn +/- offset]! PreIndex/NegPreIndex
524 // [rn], +/- offset PostIndex/NegPostIndex
525 // offset is any signed 32-bit value; offset is first loaded to register ip if
526 // it does not fit the addressing mode (12-bit unsigned and sign bit)
527 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
528
529 // [rn +/- rm] Offset/NegOffset
530 // [rn +/- rm]! PreIndex/NegPreIndex
531 // [rn], +/- rm PostIndex/NegPostIndex
532 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
533
534 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
535 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
536 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
537 explicit MemOperand(Register rn, Register rm,
538 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000539 INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
540 Register key,
541 AddrMode am = Offset)) {
542 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
543 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
544 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000545
Kristian Monsen25f61362010-05-21 11:50:48 +0100546 void set_offset(int32_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000547 DCHECK(rm_.is(no_reg));
Kristian Monsen25f61362010-05-21 11:50:48 +0100548 offset_ = offset;
549 }
550
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100551 uint32_t offset() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000552 DCHECK(rm_.is(no_reg));
Kristian Monsen25f61362010-05-21 11:50:48 +0100553 return offset_;
554 }
555
Leon Clarkef7060e22010-06-03 12:02:55 +0100556 Register rn() const { return rn_; }
557 Register rm() const { return rm_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000558 AddrMode am() const { return am_; }
Kristian Monsen25f61362010-05-21 11:50:48 +0100559
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100560 bool OffsetIsUint12Encodable() const {
561 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
562 }
563
Steve Blocka7e24c12009-10-30 11:49:00 +0000564 private:
565 Register rn_; // base
566 Register rm_; // register offset
567 int32_t offset_; // valid if rm_ == no_reg
568 ShiftOp shift_op_;
569 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
570 AddrMode am_; // bits P, U, and W
571
572 friend class Assembler;
573};
574
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575
576// Class NeonMemOperand represents a memory operand in load and
577// store NEON instructions
578class NeonMemOperand BASE_EMBEDDED {
Steve Blockd0582a62009-12-15 09:54:21 +0000579 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580 // [rn {:align}] Offset
581 // [rn {:align}]! PostIndex
582 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
Steve Blockd0582a62009-12-15 09:54:21 +0000583
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584 // [rn {:align}], rm PostIndex
585 explicit NeonMemOperand(Register rn, Register rm, int align = 0);
Steve Blockd0582a62009-12-15 09:54:21 +0000586
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000587 Register rn() const { return rn_; }
588 Register rm() const { return rm_; }
589 int align() const { return align_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100590
Steve Blockd0582a62009-12-15 09:54:21 +0000591 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592 void SetAlignment(int align);
Steve Block44f0eee2011-05-26 01:26:41 +0100593
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000594 Register rn_; // base
595 Register rm_; // register increment
596 int align_;
Steve Blockd0582a62009-12-15 09:54:21 +0000597};
598
Steve Blocka7e24c12009-10-30 11:49:00 +0000599
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600// Class NeonListOperand represents a list of NEON registers
601class NeonListOperand BASE_EMBEDDED {
602 public:
603 explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
604 DoubleRegister base() const { return base_; }
605 NeonListType type() const { return type_; }
606 private:
607 DoubleRegister base_;
608 NeonListType type_;
609};
Steve Blocka7e24c12009-10-30 11:49:00 +0000610
Steve Block1e0659c2011-05-24 12:43:12 +0100611
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612struct VmovIndex {
613 unsigned char index;
614};
615const VmovIndex VmovIndexLo = { 0 };
616const VmovIndex VmovIndexHi = { 1 };
Steve Block1e0659c2011-05-24 12:43:12 +0100617
Steve Block44f0eee2011-05-26 01:26:41 +0100618class Assembler : public AssemblerBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000619 public:
620 // Create an assembler. Instructions and relocation information are emitted
621 // into a buffer, with the instructions starting from the beginning and the
622 // relocation information starting from the end of the buffer. See CodeDesc
623 // for a detailed comment on the layout (globals.h).
624 //
625 // If the provided buffer is NULL, the assembler allocates and grows its own
626 // buffer, and buffer_size determines the initial buffer size. The buffer is
627 // owned by the assembler and deallocated upon destruction of the assembler.
628 //
629 // If the provided buffer is not NULL, the assembler uses the provided buffer
630 // for code generation and assumes its size to be buffer_size. If the buffer
631 // is too small, a fatal error occurs. No deallocation of the buffer is done
632 // upon destruction of the assembler.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100633 Assembler(Isolate* isolate, void* buffer, int buffer_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000634 virtual ~Assembler();
Steve Block44f0eee2011-05-26 01:26:41 +0100635
Steve Blocka7e24c12009-10-30 11:49:00 +0000636 // GetCode emits any pending (non-emitted) code and fills the descriptor
637 // desc. GetCode() is idempotent; it returns the same result if no other
638 // Assembler functions are invoked in between GetCode() calls.
639 void GetCode(CodeDesc* desc);
640
641 // Label operations & relative jumps (PPUM Appendix D)
642 //
643 // Takes a branch opcode (cc) and a label (L) and generates
644 // either a backward branch or a forward branch and links it
645 // to the label fixup chain. Usage:
646 //
647 // Label L; // unbound label
648 // j(cc, &L); // forward branch to unbound label
649 // bind(&L); // bind label to the current pc
650 // j(cc, &L); // backward branch to bound label
651 // bind(&L); // illegal: a label may be bound only once
652 //
653 // Note: The same Label can be used for forward and backward branches
654 // but it may be bound only once.
655
656 void bind(Label* L); // binds an unbound label L to the current code position
657
658 // Returns the branch offset to the given label from the current code position
659 // Links the label to the current position if it is still unbound
660 // Manages the jump elimination optimization if the second parameter is true.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000661 int branch_offset(Label* L);
Steve Blocka7e24c12009-10-30 11:49:00 +0000662
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000663 // Returns true if the given pc address is the start of a constant pool load
664 // instruction sequence.
665 INLINE(static bool is_constant_pool_load(Address pc));
Steve Blocka7e24c12009-10-30 11:49:00 +0000666
667 // Return the address in the constant pool of the code target address used by
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 // the branch/call instruction at pc, or the object in a mov.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669 INLINE(static Address constant_pool_entry_address(Address pc,
670 Address constant_pool));
Steve Blocka7e24c12009-10-30 11:49:00 +0000671
672 // Read/Modify the code target address in the branch/call instruction at pc.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673 INLINE(static Address target_address_at(Address pc, Address constant_pool));
674 INLINE(static void set_target_address_at(
675 Isolate* isolate, Address pc, Address constant_pool, Address target,
676 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677 INLINE(static Address target_address_at(Address pc, Code* code)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000678 Address constant_pool = code ? code->constant_pool() : NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679 return target_address_at(pc, constant_pool);
680 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000681 INLINE(static void set_target_address_at(
682 Isolate* isolate, Address pc, Code* code, Address target,
683 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
684 Address constant_pool = code ? code->constant_pool() : NULL;
685 set_target_address_at(isolate, pc, constant_pool, target,
686 icache_flush_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000687 }
688
689 // Return the code target address at a call site from the return address
690 // of that call in the instruction stream.
691 INLINE(static Address target_address_from_return_address(Address pc));
692
693 // Given the address of the beginning of a call, return the address
694 // in the instruction stream that the call will return from.
695 INLINE(static Address return_address_from_call_start(Address pc));
696
Steve Blockd0582a62009-12-15 09:54:21 +0000697 // This sets the branch destination (which is in the constant pool on ARM).
698 // This is for calls and branches within generated code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100699 inline static void deserialization_set_special_target_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000700 Isolate* isolate, Address constant_pool_entry, Code* code,
701 Address target);
702
703 // This sets the internal reference at the pc.
704 inline static void deserialization_set_target_internal_reference_at(
705 Isolate* isolate, Address pc, Address target,
706 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
Steve Blockd0582a62009-12-15 09:54:21 +0000707
708 // Here we are patching the address in the constant pool, not the actual call
709 // instruction. The address in the constant pool is the same size as a
710 // pointer.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100711 static const int kSpecialTargetSize = kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +0000712
Steve Blocka7e24c12009-10-30 11:49:00 +0000713 // Size of an instruction.
714 static const int kInstrSize = sizeof(Instr);
715
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100716 // Distance between start of patched debug break slot and the emitted address
717 // to jump to.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100718 // Patched debug break slot code is:
719 // ldr ip, [pc, #0] @ emited address and start
720 // blx ip
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 static const int kPatchDebugBreakSlotAddressOffset = 2 * kInstrSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100722
Steve Blocka7e24c12009-10-30 11:49:00 +0000723 // Difference between address of current opcode and value read from pc
724 // register.
725 static const int kPcLoadDelta = 8;
726
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000727 static const int kDebugBreakSlotInstructions = 4;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100728 static const int kDebugBreakSlotLength =
729 kDebugBreakSlotInstructions * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000730
731 // ---------------------------------------------------------------------------
732 // Code generation
733
734 // Insert the smallest number of nop instructions
735 // possible to align the pc offset to a multiple
736 // of m. m must be a power of 2 (>= 4).
737 void Align(int m);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000738 // Insert the smallest number of zero bytes possible to align the pc offset
739 // to a mulitple of m. m must be a power of 2 (>= 2).
740 void DataAlign(int m);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100741 // Aligns code to something that's optimal for a jump target for the platform.
742 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000743
744 // Branch instructions
745 void b(int branch_offset, Condition cond = al);
746 void bl(int branch_offset, Condition cond = al);
747 void blx(int branch_offset); // v5 and above
748 void blx(Register target, Condition cond = al); // v5 and above
749 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
750
751 // Convenience branch instructions using labels
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000752 void b(Label* L, Condition cond = al);
753 void b(Condition cond, Label* L) { b(L, cond); }
754 void bl(Label* L, Condition cond = al);
755 void bl(Condition cond, Label* L) { bl(L, cond); }
756 void blx(Label* L); // v5 and above
Steve Blocka7e24c12009-10-30 11:49:00 +0000757
758 // Data-processing instructions
Andrei Popescu31002712010-02-23 13:46:05 +0000759
Steve Blocka7e24c12009-10-30 11:49:00 +0000760 void and_(Register dst, Register src1, const Operand& src2,
761 SBit s = LeaveCC, Condition cond = al);
762
763 void eor(Register dst, Register src1, const Operand& src2,
764 SBit s = LeaveCC, Condition cond = al);
765
766 void sub(Register dst, Register src1, const Operand& src2,
767 SBit s = LeaveCC, Condition cond = al);
768 void sub(Register dst, Register src1, Register src2,
769 SBit s = LeaveCC, Condition cond = al) {
770 sub(dst, src1, Operand(src2), s, cond);
771 }
772
773 void rsb(Register dst, Register src1, const Operand& src2,
774 SBit s = LeaveCC, Condition cond = al);
775
776 void add(Register dst, Register src1, const Operand& src2,
777 SBit s = LeaveCC, Condition cond = al);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100778 void add(Register dst, Register src1, Register src2,
779 SBit s = LeaveCC, Condition cond = al) {
780 add(dst, src1, Operand(src2), s, cond);
781 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000782
783 void adc(Register dst, Register src1, const Operand& src2,
784 SBit s = LeaveCC, Condition cond = al);
785
786 void sbc(Register dst, Register src1, const Operand& src2,
787 SBit s = LeaveCC, Condition cond = al);
788
789 void rsc(Register dst, Register src1, const Operand& src2,
790 SBit s = LeaveCC, Condition cond = al);
791
792 void tst(Register src1, const Operand& src2, Condition cond = al);
793 void tst(Register src1, Register src2, Condition cond = al) {
794 tst(src1, Operand(src2), cond);
795 }
796
797 void teq(Register src1, const Operand& src2, Condition cond = al);
798
799 void cmp(Register src1, const Operand& src2, Condition cond = al);
800 void cmp(Register src1, Register src2, Condition cond = al) {
801 cmp(src1, Operand(src2), cond);
802 }
Steve Block1e0659c2011-05-24 12:43:12 +0100803 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000804
805 void cmn(Register src1, const Operand& src2, Condition cond = al);
806
807 void orr(Register dst, Register src1, const Operand& src2,
808 SBit s = LeaveCC, Condition cond = al);
809 void orr(Register dst, Register src1, Register src2,
810 SBit s = LeaveCC, Condition cond = al) {
811 orr(dst, src1, Operand(src2), s, cond);
812 }
813
814 void mov(Register dst, const Operand& src,
815 SBit s = LeaveCC, Condition cond = al);
816 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
817 mov(dst, Operand(src), s, cond);
818 }
819
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000820 // Load the position of the label relative to the generated code object
821 // pointer in a register.
822 void mov_label_offset(Register dst, Label* label);
823
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100824 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000825 // The constant for movw and movt should be in the range 0-0xffff.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100826 void movw(Register reg, uint32_t immediate, Condition cond = al);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100827 void movt(Register reg, uint32_t immediate, Condition cond = al);
828
Steve Blocka7e24c12009-10-30 11:49:00 +0000829 void bic(Register dst, Register src1, const Operand& src2,
830 SBit s = LeaveCC, Condition cond = al);
831
832 void mvn(Register dst, const Operand& src,
833 SBit s = LeaveCC, Condition cond = al);
834
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 // Shift instructions
836
837 void asr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
838 Condition cond = al) {
839 if (src2.is_reg()) {
840 mov(dst, Operand(src1, ASR, src2.rm()), s, cond);
841 } else {
842 mov(dst, Operand(src1, ASR, src2.immediate()), s, cond);
843 }
844 }
845
846 void lsl(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
847 Condition cond = al) {
848 if (src2.is_reg()) {
849 mov(dst, Operand(src1, LSL, src2.rm()), s, cond);
850 } else {
851 mov(dst, Operand(src1, LSL, src2.immediate()), s, cond);
852 }
853 }
854
855 void lsr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
856 Condition cond = al) {
857 if (src2.is_reg()) {
858 mov(dst, Operand(src1, LSR, src2.rm()), s, cond);
859 } else {
860 mov(dst, Operand(src1, LSR, src2.immediate()), s, cond);
861 }
862 }
863
Steve Blocka7e24c12009-10-30 11:49:00 +0000864 // Multiply instructions
865
866 void mla(Register dst, Register src1, Register src2, Register srcA,
867 SBit s = LeaveCC, Condition cond = al);
868
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000869 void mls(Register dst, Register src1, Register src2, Register srcA,
870 Condition cond = al);
871
872 void sdiv(Register dst, Register src1, Register src2,
873 Condition cond = al);
874
875 void udiv(Register dst, Register src1, Register src2, Condition cond = al);
876
Steve Blocka7e24c12009-10-30 11:49:00 +0000877 void mul(Register dst, Register src1, Register src2,
878 SBit s = LeaveCC, Condition cond = al);
879
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400880 void smmla(Register dst, Register src1, Register src2, Register srcA,
881 Condition cond = al);
882
883 void smmul(Register dst, Register src1, Register src2, Condition cond = al);
884
Steve Blocka7e24c12009-10-30 11:49:00 +0000885 void smlal(Register dstL, Register dstH, Register src1, Register src2,
886 SBit s = LeaveCC, Condition cond = al);
887
888 void smull(Register dstL, Register dstH, Register src1, Register src2,
889 SBit s = LeaveCC, Condition cond = al);
890
891 void umlal(Register dstL, Register dstH, Register src1, Register src2,
892 SBit s = LeaveCC, Condition cond = al);
893
894 void umull(Register dstL, Register dstH, Register src1, Register src2,
895 SBit s = LeaveCC, Condition cond = al);
896
897 // Miscellaneous arithmetic instructions
898
899 void clz(Register dst, Register src, Condition cond = al); // v5 and above
900
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100901 // Saturating instructions. v6 and above.
902
903 // Unsigned saturate.
904 //
905 // Saturate an optionally shifted signed value to an unsigned range.
906 //
907 // usat dst, #satpos, src
908 // usat dst, #satpos, src, lsl #sh
909 // usat dst, #satpos, src, asr #sh
910 //
911 // Register dst will contain:
912 //
913 // 0, if s < 0
914 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
915 // s, otherwise
916 //
917 // where s is the contents of src after shifting (if used.)
918 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
919
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100920 // Bitfield manipulation instructions. v7 and above.
921
922 void ubfx(Register dst, Register src, int lsb, int width,
923 Condition cond = al);
924
925 void sbfx(Register dst, Register src, int lsb, int width,
926 Condition cond = al);
927
928 void bfc(Register dst, int lsb, int width, Condition cond = al);
929
930 void bfi(Register dst, Register src, int lsb, int width,
931 Condition cond = al);
932
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000933 void pkhbt(Register dst, Register src1, const Operand& src2,
934 Condition cond = al);
935
936 void pkhtb(Register dst, Register src1, const Operand& src2,
937 Condition cond = al);
938
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400939 void sxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
940 void sxtab(Register dst, Register src1, Register src2, int rotate = 0,
941 Condition cond = al);
942 void sxth(Register dst, Register src, int rotate = 0, Condition cond = al);
943 void sxtah(Register dst, Register src1, Register src2, int rotate = 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000944 Condition cond = al);
945
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400946 void uxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
947 void uxtab(Register dst, Register src1, Register src2, int rotate = 0,
948 Condition cond = al);
949 void uxtb16(Register dst, Register src, int rotate = 0, Condition cond = al);
950 void uxth(Register dst, Register src, int rotate = 0, Condition cond = al);
951 void uxtah(Register dst, Register src1, Register src2, int rotate = 0,
952 Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000953
Ben Murdoch097c5b22016-05-18 11:27:45 +0100954 // Reverse the bits in a register.
955 void rbit(Register dst, Register src, Condition cond = al);
956
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 // Status register access instructions
958
959 void mrs(Register dst, SRegister s, Condition cond = al);
960 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
961
962 // Load/Store instructions
963 void ldr(Register dst, const MemOperand& src, Condition cond = al);
964 void str(Register src, const MemOperand& dst, Condition cond = al);
965 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
966 void strb(Register src, const MemOperand& dst, Condition cond = al);
967 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
968 void strh(Register src, const MemOperand& dst, Condition cond = al);
969 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
970 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
Leon Clarkef7060e22010-06-03 12:02:55 +0100971 void ldrd(Register dst1,
972 Register dst2,
973 const MemOperand& src, Condition cond = al);
974 void strd(Register src1,
975 Register src2,
976 const MemOperand& dst, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000977
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000978 // Preload instructions
979 void pld(const MemOperand& address);
980
Steve Blocka7e24c12009-10-30 11:49:00 +0000981 // Load/Store multiple instructions
982 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
983 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
984
Steve Blocka7e24c12009-10-30 11:49:00 +0000985 // Exception-generating instructions and debugging support
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800986 void stop(const char* msg,
987 Condition cond = al,
988 int32_t code = kDefaultStopCode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000989
990 void bkpt(uint32_t imm16); // v5 and above
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800991 void svc(uint32_t imm24, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000992
Ben Murdoch097c5b22016-05-18 11:27:45 +0100993 // Synchronization instructions
994 void dmb(BarrierOption option);
995 void dsb(BarrierOption option);
996 void isb(BarrierOption option);
997
Steve Blocka7e24c12009-10-30 11:49:00 +0000998 // Coprocessor instructions
999
1000 void cdp(Coprocessor coproc, int opcode_1,
1001 CRegister crd, CRegister crn, CRegister crm,
1002 int opcode_2, Condition cond = al);
1003
1004 void cdp2(Coprocessor coproc, int opcode_1,
1005 CRegister crd, CRegister crn, CRegister crm,
1006 int opcode_2); // v5 and above
1007
1008 void mcr(Coprocessor coproc, int opcode_1,
1009 Register rd, CRegister crn, CRegister crm,
1010 int opcode_2 = 0, Condition cond = al);
1011
1012 void mcr2(Coprocessor coproc, int opcode_1,
1013 Register rd, CRegister crn, CRegister crm,
1014 int opcode_2 = 0); // v5 and above
1015
1016 void mrc(Coprocessor coproc, int opcode_1,
1017 Register rd, CRegister crn, CRegister crm,
1018 int opcode_2 = 0, Condition cond = al);
1019
1020 void mrc2(Coprocessor coproc, int opcode_1,
1021 Register rd, CRegister crn, CRegister crm,
1022 int opcode_2 = 0); // v5 and above
1023
1024 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1025 LFlag l = Short, Condition cond = al);
1026 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1027 LFlag l = Short, Condition cond = al);
1028
1029 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1030 LFlag l = Short); // v5 and above
1031 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1032 LFlag l = Short); // v5 and above
1033
Steve Blockd0582a62009-12-15 09:54:21 +00001034 // Support for VFP.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001035 // All these APIs support S0 to S31 and D0 to D31.
Steve Blockd0582a62009-12-15 09:54:21 +00001036
Leon Clarked91b9f72010-01-27 17:25:45 +00001037 void vldr(const DwVfpRegister dst,
1038 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001039 int offset,
1040 const Condition cond = al);
1041 void vldr(const DwVfpRegister dst,
1042 const MemOperand& src,
Leon Clarked91b9f72010-01-27 17:25:45 +00001043 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001044
1045 void vldr(const SwVfpRegister dst,
1046 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001047 int offset,
1048 const Condition cond = al);
1049 void vldr(const SwVfpRegister dst,
1050 const MemOperand& src,
Steve Block6ded16b2010-05-10 14:33:55 +01001051 const Condition cond = al);
1052
Leon Clarked91b9f72010-01-27 17:25:45 +00001053 void vstr(const DwVfpRegister src,
1054 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001055 int offset,
1056 const Condition cond = al);
1057 void vstr(const DwVfpRegister src,
1058 const MemOperand& dst,
Leon Clarked91b9f72010-01-27 17:25:45 +00001059 const Condition cond = al);
Steve Block8defd9f2010-07-08 12:39:36 +01001060
Iain Merrick75681382010-08-19 15:07:18 +01001061 void vstr(const SwVfpRegister src,
1062 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001063 int offset,
1064 const Condition cond = al);
1065 void vstr(const SwVfpRegister src,
1066 const MemOperand& dst,
Iain Merrick75681382010-08-19 15:07:18 +01001067 const Condition cond = al);
1068
Ben Murdoch8b112d22011-06-08 16:22:53 +01001069 void vldm(BlockAddrMode am,
1070 Register base,
1071 DwVfpRegister first,
1072 DwVfpRegister last,
1073 Condition cond = al);
1074
1075 void vstm(BlockAddrMode am,
1076 Register base,
1077 DwVfpRegister first,
1078 DwVfpRegister last,
1079 Condition cond = al);
1080
1081 void vldm(BlockAddrMode am,
1082 Register base,
1083 SwVfpRegister first,
1084 SwVfpRegister last,
1085 Condition cond = al);
1086
1087 void vstm(BlockAddrMode am,
1088 Register base,
1089 SwVfpRegister first,
1090 SwVfpRegister last,
1091 Condition cond = al);
1092
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001093 void vmov(const SwVfpRegister dst, float imm);
Steve Block8defd9f2010-07-08 12:39:36 +01001094 void vmov(const DwVfpRegister dst,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001095 double imm,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001096 const Register scratch = no_reg);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001097 void vmov(const SwVfpRegister dst,
1098 const SwVfpRegister src,
1099 const Condition cond = al);
1100 void vmov(const DwVfpRegister dst,
Steve Block8defd9f2010-07-08 12:39:36 +01001101 const DwVfpRegister src,
1102 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001103 void vmov(const DwVfpRegister dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001104 const VmovIndex index,
1105 const Register src,
1106 const Condition cond = al);
1107 void vmov(const Register dst,
1108 const VmovIndex index,
1109 const DwVfpRegister src,
1110 const Condition cond = al);
1111 void vmov(const DwVfpRegister dst,
Leon Clarkee46be812010-01-19 14:06:41 +00001112 const Register src1,
Steve Blockd0582a62009-12-15 09:54:21 +00001113 const Register src2,
Leon Clarkee46be812010-01-19 14:06:41 +00001114 const Condition cond = al);
1115 void vmov(const Register dst1,
1116 const Register dst2,
1117 const DwVfpRegister src,
1118 const Condition cond = al);
1119 void vmov(const SwVfpRegister dst,
1120 const Register src,
1121 const Condition cond = al);
1122 void vmov(const Register dst,
1123 const SwVfpRegister src,
1124 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001125 void vcvt_f64_s32(const DwVfpRegister dst,
1126 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001127 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001128 const Condition cond = al);
1129 void vcvt_f32_s32(const SwVfpRegister dst,
1130 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001131 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001132 const Condition cond = al);
1133 void vcvt_f64_u32(const DwVfpRegister dst,
1134 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001135 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001136 const Condition cond = al);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001137 void vcvt_f32_u32(const SwVfpRegister dst,
1138 const SwVfpRegister src,
1139 VFPConversionMode mode = kDefaultRoundToZero,
1140 const Condition cond = al);
1141 void vcvt_s32_f32(const SwVfpRegister dst,
1142 const SwVfpRegister src,
1143 VFPConversionMode mode = kDefaultRoundToZero,
1144 const Condition cond = al);
1145 void vcvt_u32_f32(const SwVfpRegister dst,
1146 const SwVfpRegister src,
1147 VFPConversionMode mode = kDefaultRoundToZero,
1148 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001149 void vcvt_s32_f64(const SwVfpRegister dst,
1150 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001151 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001152 const Condition cond = al);
1153 void vcvt_u32_f64(const SwVfpRegister dst,
1154 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001155 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001156 const Condition cond = al);
1157 void vcvt_f64_f32(const DwVfpRegister dst,
1158 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001159 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001160 const Condition cond = al);
1161 void vcvt_f32_f64(const SwVfpRegister dst,
1162 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001163 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001164 const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001165 void vcvt_f64_s32(const DwVfpRegister dst,
1166 int fraction_bits,
1167 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169 void vmrs(const Register dst, const Condition cond = al);
1170 void vmsr(const Register dst, const Condition cond = al);
1171
Steve Block44f0eee2011-05-26 01:26:41 +01001172 void vneg(const DwVfpRegister dst,
1173 const DwVfpRegister src,
1174 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175 void vneg(const SwVfpRegister dst, const SwVfpRegister src,
1176 const Condition cond = al);
Steve Block1e0659c2011-05-24 12:43:12 +01001177 void vabs(const DwVfpRegister dst,
1178 const DwVfpRegister src,
1179 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180 void vabs(const SwVfpRegister dst, const SwVfpRegister src,
1181 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001182 void vadd(const DwVfpRegister dst,
1183 const DwVfpRegister src1,
1184 const DwVfpRegister src2,
1185 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001186 void vadd(const SwVfpRegister dst, const SwVfpRegister src1,
1187 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001188 void vsub(const DwVfpRegister dst,
1189 const DwVfpRegister src1,
1190 const DwVfpRegister src2,
1191 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192 void vsub(const SwVfpRegister dst, const SwVfpRegister src1,
1193 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001194 void vmul(const DwVfpRegister dst,
1195 const DwVfpRegister src1,
1196 const DwVfpRegister src2,
1197 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001198 void vmul(const SwVfpRegister dst, const SwVfpRegister src1,
1199 const SwVfpRegister src2, const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001200 void vmla(const DwVfpRegister dst,
1201 const DwVfpRegister src1,
1202 const DwVfpRegister src2,
1203 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001204 void vmla(const SwVfpRegister dst, const SwVfpRegister src1,
1205 const SwVfpRegister src2, const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206 void vmls(const DwVfpRegister dst,
1207 const DwVfpRegister src1,
1208 const DwVfpRegister src2,
1209 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001210 void vmls(const SwVfpRegister dst, const SwVfpRegister src1,
1211 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001212 void vdiv(const DwVfpRegister dst,
1213 const DwVfpRegister src1,
1214 const DwVfpRegister src2,
1215 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001216 void vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
1217 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001218 void vcmp(const DwVfpRegister src1,
1219 const DwVfpRegister src2,
Steve Blockd0582a62009-12-15 09:54:21 +00001220 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 void vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
1222 const Condition cond = al);
Iain Merrick75681382010-08-19 15:07:18 +01001223 void vcmp(const DwVfpRegister src1,
1224 const double src2,
Iain Merrick75681382010-08-19 15:07:18 +01001225 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 void vcmp(const SwVfpRegister src1, const float src2,
Russell Brenner90bac252010-11-18 13:33:46 -08001227 const Condition cond = al);
Steve Block8defd9f2010-07-08 12:39:36 +01001228 void vsqrt(const DwVfpRegister dst,
1229 const DwVfpRegister src,
1230 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001231 void vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
1232 const Condition cond = al);
Steve Blockd0582a62009-12-15 09:54:21 +00001233
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001234 // ARMv8 rounding instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001235 void vrinta(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001236 void vrinta(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001237 void vrintn(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001238 void vrintn(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 void vrintm(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001240 void vrintm(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001241 void vrintp(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001242 void vrintp(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001243 void vrintz(const SwVfpRegister dst, const SwVfpRegister src,
1244 const Condition cond = al);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001245 void vrintz(const DwVfpRegister dst, const DwVfpRegister src,
1246 const Condition cond = al);
1247
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001248 // Support for NEON.
1249 // All these APIs support D0 to D31 and Q0 to Q15.
1250
1251 void vld1(NeonSize size,
1252 const NeonListOperand& dst,
1253 const NeonMemOperand& src);
1254 void vst1(NeonSize size,
1255 const NeonListOperand& src,
1256 const NeonMemOperand& dst);
1257 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1258
Steve Blocka7e24c12009-10-30 11:49:00 +00001259 // Pseudo instructions
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001260
1261 // Different nop operations are used by the code generator to detect certain
1262 // states of the generated code.
1263 enum NopMarkerTypes {
1264 NON_MARKING_NOP = 0,
1265 DEBUG_BREAK_NOP,
1266 // IC markers.
1267 PROPERTY_ACCESS_INLINED,
1268 PROPERTY_ACCESS_INLINED_CONTEXT,
1269 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1270 // Helper values.
1271 LAST_CODE_MARKER,
1272 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1273 };
1274
1275 void nop(int type = 0); // 0 is the default non-marking type.
Steve Blocka7e24c12009-10-30 11:49:00 +00001276
1277 void push(Register src, Condition cond = al) {
1278 str(src, MemOperand(sp, 4, NegPreIndex), cond);
1279 }
1280
1281 void pop(Register dst, Condition cond = al) {
1282 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1283 }
1284
1285 void pop() {
1286 add(sp, sp, Operand(kPointerSize));
1287 }
1288
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001289 void vpush(DwVfpRegister src, Condition cond = al) {
1290 vstm(db_w, sp, src, src, cond);
1291 }
1292
1293 void vpop(DwVfpRegister dst, Condition cond = al) {
1294 vldm(ia_w, sp, dst, dst, cond);
1295 }
1296
Steve Blocka7e24c12009-10-30 11:49:00 +00001297 // Jump unconditionally to given label.
1298 void jmp(Label* L) { b(L, al); }
1299
1300 // Check the code size generated from label to here.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001301 int SizeOfCodeGeneratedSince(Label* label) {
1302 return pc_offset() - label->pos();
1303 }
1304
1305 // Check the number of instructions generated from label to here.
1306 int InstructionsGeneratedSince(Label* label) {
1307 return SizeOfCodeGeneratedSince(label) / kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 }
1309
Steve Blockd0582a62009-12-15 09:54:21 +00001310 // Check whether an immediate fits an addressing mode 1 instruction.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001311 static bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1312
1313 // Check whether an immediate fits an addressing mode 2 instruction.
1314 bool ImmediateFitsAddrMode2Instruction(int32_t imm32);
Steve Blockd0582a62009-12-15 09:54:21 +00001315
Steve Block6ded16b2010-05-10 14:33:55 +01001316 // Class for scoping postponing the constant pool generation.
1317 class BlockConstPoolScope {
1318 public:
1319 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1320 assem_->StartBlockConstPool();
1321 }
1322 ~BlockConstPoolScope() {
1323 assem_->EndBlockConstPool();
1324 }
1325
1326 private:
1327 Assembler* assem_;
1328
1329 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1330 };
1331
Steve Blocka7e24c12009-10-30 11:49:00 +00001332 // Debugging
1333
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001334 // Mark generator continuation.
1335 void RecordGeneratorContinuation();
Steve Blocka7e24c12009-10-30 11:49:00 +00001336
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001337 // Mark address of a debug break slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001338 void RecordDebugBreakSlot(RelocInfo::Mode mode);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001339
Ben Murdoch257744e2011-11-30 15:57:28 +00001340 // Record the AST id of the CallIC being compiled, so that it can be placed
1341 // in the relocation information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001342 void SetRecordedAstId(TypeFeedbackId ast_id) {
1343 DCHECK(recorded_ast_id_.IsNone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001344 recorded_ast_id_ = ast_id;
1345 }
1346
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347 TypeFeedbackId RecordedAstId() {
1348 DCHECK(!recorded_ast_id_.IsNone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001349 return recorded_ast_id_;
1350 }
1351
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
Ben Murdoch257744e2011-11-30 15:57:28 +00001353
Steve Blocka7e24c12009-10-30 11:49:00 +00001354 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001355 // Use --code-comments to enable.
Steve Blocka7e24c12009-10-30 11:49:00 +00001356 void RecordComment(const char* msg);
1357
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001358 // Record a deoptimization reason that can be used by a log or cpu profiler.
1359 // Use --trace-deopt to enable.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001360 void RecordDeoptReason(const int reason, int raw_position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001361
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001362 // Record the emission of a constant pool.
1363 //
1364 // The emission of constant pool depends on the size of the code generated and
1365 // the number of RelocInfo recorded.
1366 // The Debug mechanism needs to map code offsets between two versions of a
1367 // function, compiled with and without debugger support (see for example
1368 // Debug::PrepareForBreakPoints()).
1369 // Compiling functions with debugger support generates additional code
1370 // (DebugCodegen::GenerateSlot()). This may affect the emission of the
1371 // constant pools and cause the version of the code with debugger support to
1372 // have constant pools generated in different places.
1373 // Recording the position and size of emitted constant pools allows to
1374 // correctly compute the offset mappings between the different versions of a
1375 // function in all situations.
1376 //
1377 // The parameter indicates the size of the constant pool (in bytes), including
1378 // the marker and branch over the data.
1379 void RecordConstPool(int size);
1380
Ben Murdochb8e0da22011-05-16 14:20:40 +01001381 // Writes a single byte or word of data in the code stream. Used
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001382 // for inline tables, e.g., jump-tables. CheckConstantPool() should be
1383 // called before any use of db/dd/dq/dp to ensure that constant pools
Ben Murdochb8e0da22011-05-16 14:20:40 +01001384 // are not emitted as part of the tables generated.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001385 void db(uint8_t data);
1386 void dd(uint32_t data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001387 void dq(uint64_t data);
1388 void dp(uintptr_t data) { dd(data); }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001389
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001390 // Emits the address of the code stub's first instruction.
1391 void emit_code_stub_address(Code* stub);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001392
1393 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
Steve Block6ded16b2010-05-10 14:33:55 +01001394
1395 // Read/patch instructions
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001396 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1397 void instr_at_put(int pos, Instr instr) {
1398 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1399 }
Steve Block6ded16b2010-05-10 14:33:55 +01001400 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1401 static void instr_at_put(byte* pc, Instr instr) {
1402 *reinterpret_cast<Instr*>(pc) = instr;
1403 }
Steve Block1e0659c2011-05-24 12:43:12 +01001404 static Condition GetCondition(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001405 static bool IsBranch(Instr instr);
1406 static int GetBranchOffset(Instr instr);
1407 static bool IsLdrRegisterImmediate(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001408 static bool IsVldrDRegisterImmediate(Instr instr);
1409 static Instr GetConsantPoolLoadPattern();
1410 static Instr GetConsantPoolLoadMask();
1411 static bool IsLdrPpRegOffset(Instr instr);
1412 static Instr GetLdrPpRegOffsetPattern();
1413 static bool IsLdrPpImmediateOffset(Instr instr);
1414 static bool IsVldrDPpImmediateOffset(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001415 static int GetLdrRegisterImmediateOffset(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001416 static int GetVldrDRegisterImmediateOffset(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001417 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001418 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
Kristian Monsen50ef84f2010-07-29 15:18:00 +01001419 static bool IsStrRegisterImmediate(Instr instr);
1420 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1421 static bool IsAddRegisterImmediate(Instr instr);
1422 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
Leon Clarkef7060e22010-06-03 12:02:55 +01001423 static Register GetRd(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001424 static Register GetRn(Instr instr);
1425 static Register GetRm(Instr instr);
Leon Clarkef7060e22010-06-03 12:02:55 +01001426 static bool IsPush(Instr instr);
1427 static bool IsPop(Instr instr);
1428 static bool IsStrRegFpOffset(Instr instr);
1429 static bool IsLdrRegFpOffset(Instr instr);
1430 static bool IsStrRegFpNegOffset(Instr instr);
1431 static bool IsLdrRegFpNegOffset(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001432 static bool IsLdrPcImmediateOffset(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001433 static bool IsVldrDPcImmediateOffset(Instr instr);
1434 static bool IsBlxReg(Instr instr);
1435 static bool IsBlxIp(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001436 static bool IsTstImmediate(Instr instr);
1437 static bool IsCmpRegister(Instr instr);
1438 static bool IsCmpImmediate(Instr instr);
1439 static Register GetCmpImmediateRegister(Instr instr);
1440 static int GetCmpImmediateRawImmediate(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001441 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001442 static bool IsMovImmed(Instr instr);
1443 static bool IsOrrImmed(Instr instr);
1444 static bool IsMovT(Instr instr);
1445 static Instr GetMovTPattern();
1446 static bool IsMovW(Instr instr);
1447 static Instr GetMovWPattern();
1448 static Instr EncodeMovwImmediate(uint32_t immediate);
1449 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate);
1450 static int DecodeShiftImm(Instr instr);
1451 static Instr PatchShiftImm(Instr instr, int immed);
Steve Block6ded16b2010-05-10 14:33:55 +01001452
Ben Murdoch257744e2011-11-30 15:57:28 +00001453 // Constants in pools are accessed via pc relative addressing, which can
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001454 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1455 // PC-relative loads, thereby defining a maximum distance between the
1456 // instruction and the accessed constant.
1457 static const int kMaxDistToIntPool = 4*KB;
1458 static const int kMaxDistToFPPool = 1*KB;
1459 // All relocations could be integer, it therefore acts as the limit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001460 static const int kMinNumPendingConstants = 4;
1461 static const int kMaxNumPending32Constants = kMaxDistToIntPool / kInstrSize;
1462 static const int kMaxNumPending64Constants = kMaxDistToFPPool / kInstrSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00001463
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001464 // Postpone the generation of the constant pool for the specified number of
1465 // instructions.
1466 void BlockConstPoolFor(int instructions);
1467
1468 // Check if is time to emit a constant pool.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001469 void CheckConstPool(bool force_emit, bool require_jump);
Steve Blocka7e24c12009-10-30 11:49:00 +00001470
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001471 void MaybeCheckConstPool() {
1472 if (pc_offset() >= next_buffer_check_) {
1473 CheckConstPool(false, true);
1474 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001475 }
1476
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001477 int EmitEmbeddedConstantPool() {
1478 DCHECK(FLAG_enable_embedded_constant_pool);
1479 return constant_pool_builder_.Emit(this);
1480 }
1481
1482 bool ConstantPoolAccessIsInOverflow() const {
1483 return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1484 ConstantPoolEntry::OVERFLOWED;
1485 }
1486
1487 void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1488 ConstantPoolEntry::Access access,
1489 ConstantPoolEntry::Type type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001490
Steve Blocka7e24c12009-10-30 11:49:00 +00001491 protected:
Ben Murdoch257744e2011-11-30 15:57:28 +00001492 // Relocation for a type-recording IC has the AST id added to it. This
1493 // member variable is a way to pass the information from the call site to
1494 // the relocation info.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001495 TypeFeedbackId recorded_ast_id_;
Steve Block44f0eee2011-05-26 01:26:41 +01001496
Steve Blocka7e24c12009-10-30 11:49:00 +00001497 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1498
Steve Blocka7e24c12009-10-30 11:49:00 +00001499 // Decode branch instruction at pos and return branch target pos
1500 int target_at(int pos);
1501
1502 // Patch branch instruction at pos to branch to given branch target pos
1503 void target_at_put(int pos, int target_pos);
1504
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001505 // Prevent contant pool emission until EndBlockConstPool is called.
1506 // Call to this function can be nested but must be followed by an equal
1507 // number of call to EndBlockConstpool.
1508 void StartBlockConstPool() {
1509 if (const_pool_blocked_nesting_++ == 0) {
1510 // Prevent constant pool checks happening by setting the next check to
1511 // the biggest possible offset.
1512 next_buffer_check_ = kMaxInt;
1513 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001514 }
1515
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001516 // Resume constant pool emission. Need to be called as many time as
1517 // StartBlockConstPool to have an effect.
Steve Block6ded16b2010-05-10 14:33:55 +01001518 void EndBlockConstPool() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001519 if (--const_pool_blocked_nesting_ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001520#ifdef DEBUG
1521 // Max pool start (if we need a jump and an alignment).
1522 int start = pc_offset() + kInstrSize + 2 * kPointerSize;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001523 // Check the constant pool hasn't been blocked for too long.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001524 DCHECK((num_pending_32_bit_constants_ == 0) ||
1525 (start + num_pending_64_bit_constants_ * kDoubleSize <
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001526 (first_const_pool_32_use_ + kMaxDistToIntPool)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001527 DCHECK((num_pending_64_bit_constants_ == 0) ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001528 (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
1529#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001530 // Two cases:
1531 // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1532 // still blocked
1533 // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1534 // trigger a check.
1535 next_buffer_check_ = no_const_pool_before_;
1536 }
Steve Block6ded16b2010-05-10 14:33:55 +01001537 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001538
1539 bool is_const_pool_blocked() const {
1540 return (const_pool_blocked_nesting_ > 0) ||
1541 (pc_offset() < no_const_pool_before_);
1542 }
Steve Block6ded16b2010-05-10 14:33:55 +01001543
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001544 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00001545 int next_buffer_check_; // pc offset of next buffer check
1546
1547 // Code generation
1548 // The relocation writer's position is at least kGap bytes below the end of
1549 // the generated instructions. This is so that multi-instruction sequences do
1550 // not have to check for overflow. The same is true for writes of large
1551 // relocation info entries.
1552 static const int kGap = 32;
Steve Blocka7e24c12009-10-30 11:49:00 +00001553
1554 // Constant pool generation
1555 // Pools are emitted in the instruction stream, preferably after unconditional
1556 // jumps or after returns from functions (in dead code locations).
1557 // If a long code sequence does not contain unconditional jumps, it is
1558 // necessary to emit the constant pool before the pool gets too far from the
1559 // location it is accessed from. In this case, we emit a jump over the emitted
1560 // constant pool.
1561 // Constants in the pool may be addresses of functions that gets relocated;
1562 // if so, a relocation info entry is associated to the constant pool entry.
1563
1564 // Repeated checking whether the constant pool should be emitted is rather
1565 // expensive. By default we only check again once a number of instructions
1566 // has been generated. That also means that the sizing of the buffers is not
1567 // an exact science, and that we rely on some slop to not overrun buffers.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001568 static const int kCheckPoolIntervalInst = 32;
1569 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001570
1571
Steve Block6ded16b2010-05-10 14:33:55 +01001572 // Emission of the constant pool may be blocked in some code sequences.
1573 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1574 int no_const_pool_before_; // Block emission before this pc offset.
Steve Blocka7e24c12009-10-30 11:49:00 +00001575
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001576 // Keep track of the first instruction requiring a constant pool entry
1577 // since the previous constant pool was emitted.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001578 int first_const_pool_32_use_;
1579 int first_const_pool_64_use_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001580
1581 // Relocation info generation
1582 // Each relocation is encoded as a variable size value
1583 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1584 RelocInfoWriter reloc_info_writer;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001585
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001586 // ConstantPoolEntry records are used during code generation as temporary
Steve Blocka7e24c12009-10-30 11:49:00 +00001587 // containers for constants and code target addresses until they are emitted
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 // to the constant pool. These records are temporarily stored in a separate
1589 // buffer until a constant pool is emitted.
Steve Blocka7e24c12009-10-30 11:49:00 +00001590 // If every instruction in a long sequence is accessing the pool, we need one
1591 // pending relocation entry per instruction.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001592
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001593 // The buffers of pending constant pool entries.
1594 ConstantPoolEntry pending_32_bit_constants_buffer_[kMinNumPendingConstants];
1595 ConstantPoolEntry pending_64_bit_constants_buffer_[kMinNumPendingConstants];
1596 ConstantPoolEntry* pending_32_bit_constants_;
1597 ConstantPoolEntry* pending_64_bit_constants_;
1598 // Number of pending constant pool entries in the 32 bits buffer.
1599 int num_pending_32_bit_constants_;
1600 // Number of pending constant pool entries in the 64 bits buffer.
1601 int num_pending_64_bit_constants_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001602
1603 ConstantPoolBuilder constant_pool_builder_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001604
1605 // The bound position, before this we cannot do instruction elimination.
1606 int last_bound_pos_;
1607
Steve Blocka7e24c12009-10-30 11:49:00 +00001608 // Code emission
1609 inline void CheckBuffer();
1610 void GrowBuffer();
1611 inline void emit(Instr x);
1612
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613 // 32-bit immediate values
1614 void move_32_bit_immediate(Register rd,
1615 const Operand& x,
1616 Condition cond = al);
1617
Steve Blocka7e24c12009-10-30 11:49:00 +00001618 // Instruction generation
1619 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1620 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1621 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1622 void addrmod4(Instr instr, Register rn, RegList rl);
1623 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1624
1625 // Labels
1626 void print(Label* L);
1627 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001628 void next(Label* L);
1629
1630 // Record reloc info for current pc_
1631 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001632 ConstantPoolEntry::Access ConstantPoolAddEntry(int position,
1633 RelocInfo::Mode rmode,
1634 intptr_t value);
1635 ConstantPoolEntry::Access ConstantPoolAddEntry(int position, double value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001636
Steve Blocka7e24c12009-10-30 11:49:00 +00001637 friend class RelocInfo;
1638 friend class CodePatcher;
Steve Block6ded16b2010-05-10 14:33:55 +01001639 friend class BlockConstPoolScope;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001640 PositionsRecorder positions_recorder_;
1641 friend class PositionsRecorder;
1642 friend class EnsureSpace;
Steve Blocka7e24c12009-10-30 11:49:00 +00001643};
1644
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001645
1646class EnsureSpace BASE_EMBEDDED {
1647 public:
1648 explicit EnsureSpace(Assembler* assembler) {
1649 assembler->CheckBuffer();
1650 }
1651};
1652
1653
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001654} // namespace internal
1655} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +00001656
1657#endif // V8_ARM_ASSEMBLER_ARM_H_