blob: 461d5b0aa66e10f98783b9a3d794440bfd7a7789 [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 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
122 bool is(Register reg) const { return reg_code == reg.reg_code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000123 int code() const {
124 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 return reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126 }
127 int bit() const {
128 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 return 1 << reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000130 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000131 void set_code(int code) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132 reg_code = code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 DCHECK(is_valid());
134 }
135
136 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137 int reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138};
139
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140// r7: context register
141// r8: constant pool pointer register if FLAG_enable_embedded_constant_pool.
142// r9: lithium scratch
143#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
144GENERAL_REGISTERS(DECLARE_REGISTER)
145#undef DECLARE_REGISTER
146const Register no_reg = {Register::kCode_no_reg};
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100147
Ben Murdoch61f157c2016-09-16 13:49:30 +0100148static const bool kSimpleFPAliasing = false;
149
Leon Clarkee46be812010-01-19 14:06:41 +0000150// Single word VFP register.
151struct SwVfpRegister {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100152 enum Code {
153#define REGISTER_CODE(R) kCode_##R,
154 FLOAT_REGISTERS(REGISTER_CODE)
155#undef REGISTER_CODE
156 kAfterLast,
157 kCode_no_reg = -1
158 };
159
160 static const int kMaxNumRegisters = Code::kAfterLast;
161
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 static const int kSizeInBytes = 4;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100163
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164 bool is_valid() const { return 0 <= reg_code && reg_code < 32; }
165 bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100166 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 return reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000169 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100170 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 return 1 << reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000173 }
Ben Murdochc5610432016-08-08 18:44:38 +0100174 static SwVfpRegister from_code(int code) {
175 SwVfpRegister r = {code};
176 return r;
177 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100178 void split_code(int* vm, int* m) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000179 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 *m = reg_code & 0x1;
181 *vm = reg_code >> 1;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100182 }
Leon Clarkee46be812010-01-19 14:06:41 +0000183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 int reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000185};
186
Ben Murdochc5610432016-08-08 18:44:38 +0100187typedef SwVfpRegister FloatRegister;
Leon Clarkee46be812010-01-19 14:06:41 +0000188
189// Double word VFP register.
Ben Murdochc5610432016-08-08 18:44:38 +0100190struct DwVfpRegister {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 enum Code {
192#define REGISTER_CODE(R) kCode_##R,
193 DOUBLE_REGISTERS(REGISTER_CODE)
194#undef REGISTER_CODE
195 kAfterLast,
196 kCode_no_reg = -1
197 };
198
199 static const int kMaxNumRegisters = Code::kAfterLast;
200
201 inline static int NumRegisters();
202
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000203 // A few double registers are reserved: one as a scratch register and one to
204 // hold 0.0, that does not fit in the immediate field of vmov instructions.
205 // d14: 0.0
206 // d15: scratch register.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000207 static const int kSizeInBytes = 8;
208
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
Ben Murdochc5610432016-08-08 18:44:38 +0100210 bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100211 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213 return reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000214 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100215 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217 return 1 << reg_code;
218 }
219
Ben Murdochc5610432016-08-08 18:44:38 +0100220 static DwVfpRegister from_code(int code) {
221 DwVfpRegister r = {code};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 return r;
Leon Clarkee46be812010-01-19 14:06:41 +0000223 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100224 void split_code(int* vm, int* m) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000226 *m = (reg_code & 0x10) >> 4;
227 *vm = reg_code & 0x0F;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100228 }
Leon Clarkee46be812010-01-19 14:06:41 +0000229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 int reg_code;
Leon Clarkee46be812010-01-19 14:06:41 +0000231};
232
233
Ben Murdochc5610432016-08-08 18:44:38 +0100234typedef DwVfpRegister DoubleRegister;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100235
236
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000237// Double word VFP register d0-15.
238struct LowDwVfpRegister {
239 public:
240 static const int kMaxNumLowRegisters = 16;
241 operator DwVfpRegister() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 DwVfpRegister r = { reg_code };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 return r;
244 }
245 static LowDwVfpRegister from_code(int code) {
246 LowDwVfpRegister r = { code };
247 return r;
248 }
249
250 bool is_valid() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000251 return 0 <= reg_code && reg_code < kMaxNumLowRegisters;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000252 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253 bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
254 bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 int code() const {
256 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257 return reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258 }
259 SwVfpRegister low() const {
260 SwVfpRegister reg;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000261 reg.reg_code = reg_code * 2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000262
263 DCHECK(reg.is_valid());
264 return reg;
265 }
266 SwVfpRegister high() const {
267 SwVfpRegister reg;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 reg.reg_code = (reg_code * 2) + 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269
270 DCHECK(reg.is_valid());
271 return reg;
272 }
273
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 int reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275};
276
277
278// Quad word NEON register.
279struct QwNeonRegister {
280 static const int kMaxNumRegisters = 16;
281
282 static QwNeonRegister from_code(int code) {
283 QwNeonRegister r = { code };
284 return r;
285 }
286
287 bool is_valid() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 return (0 <= reg_code) && (reg_code < kMaxNumRegisters);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000290 bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000291 int code() const {
292 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 return reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294 }
295 void split_code(int* vm, int* m) const {
296 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 int encoded_code = reg_code << 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 *m = (encoded_code & 0x10) >> 4;
299 *vm = encoded_code & 0x0F;
300 }
301
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302 int reg_code;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303};
304
305
306typedef QwNeonRegister QuadRegister;
307
Ben Murdoch097c5b22016-05-18 11:27:45 +0100308typedef QwNeonRegister Simd128Register;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309
Steve Block6ded16b2010-05-10 14:33:55 +0100310// Support for the VFP registers s0 to s31 (d0 to d15).
Leon Clarkee46be812010-01-19 14:06:41 +0000311// Note that "s(N):s(N+1)" is the same as "d(N/2)".
Steve Block6ded16b2010-05-10 14:33:55 +0100312const SwVfpRegister s0 = { 0 };
313const SwVfpRegister s1 = { 1 };
314const SwVfpRegister s2 = { 2 };
315const SwVfpRegister s3 = { 3 };
316const SwVfpRegister s4 = { 4 };
317const SwVfpRegister s5 = { 5 };
318const SwVfpRegister s6 = { 6 };
319const SwVfpRegister s7 = { 7 };
320const SwVfpRegister s8 = { 8 };
321const SwVfpRegister s9 = { 9 };
322const SwVfpRegister s10 = { 10 };
323const SwVfpRegister s11 = { 11 };
324const SwVfpRegister s12 = { 12 };
325const SwVfpRegister s13 = { 13 };
326const SwVfpRegister s14 = { 14 };
327const SwVfpRegister s15 = { 15 };
328const SwVfpRegister s16 = { 16 };
329const SwVfpRegister s17 = { 17 };
330const SwVfpRegister s18 = { 18 };
331const SwVfpRegister s19 = { 19 };
332const SwVfpRegister s20 = { 20 };
333const SwVfpRegister s21 = { 21 };
334const SwVfpRegister s22 = { 22 };
335const SwVfpRegister s23 = { 23 };
336const SwVfpRegister s24 = { 24 };
337const SwVfpRegister s25 = { 25 };
338const SwVfpRegister s26 = { 26 };
339const SwVfpRegister s27 = { 27 };
340const SwVfpRegister s28 = { 28 };
341const SwVfpRegister s29 = { 29 };
342const SwVfpRegister s30 = { 30 };
343const SwVfpRegister s31 = { 31 };
Leon Clarkee46be812010-01-19 14:06:41 +0000344
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100345const DwVfpRegister no_dreg = { -1 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346const LowDwVfpRegister d0 = { 0 };
347const LowDwVfpRegister d1 = { 1 };
348const LowDwVfpRegister d2 = { 2 };
349const LowDwVfpRegister d3 = { 3 };
350const LowDwVfpRegister d4 = { 4 };
351const LowDwVfpRegister d5 = { 5 };
352const LowDwVfpRegister d6 = { 6 };
353const LowDwVfpRegister d7 = { 7 };
354const LowDwVfpRegister d8 = { 8 };
355const LowDwVfpRegister d9 = { 9 };
356const LowDwVfpRegister d10 = { 10 };
357const LowDwVfpRegister d11 = { 11 };
358const LowDwVfpRegister d12 = { 12 };
359const LowDwVfpRegister d13 = { 13 };
360const LowDwVfpRegister d14 = { 14 };
361const LowDwVfpRegister d15 = { 15 };
362const DwVfpRegister d16 = { 16 };
363const DwVfpRegister d17 = { 17 };
364const DwVfpRegister d18 = { 18 };
365const DwVfpRegister d19 = { 19 };
366const DwVfpRegister d20 = { 20 };
367const DwVfpRegister d21 = { 21 };
368const DwVfpRegister d22 = { 22 };
369const DwVfpRegister d23 = { 23 };
370const DwVfpRegister d24 = { 24 };
371const DwVfpRegister d25 = { 25 };
372const DwVfpRegister d26 = { 26 };
373const DwVfpRegister d27 = { 27 };
374const DwVfpRegister d28 = { 28 };
375const DwVfpRegister d29 = { 29 };
376const DwVfpRegister d30 = { 30 };
377const DwVfpRegister d31 = { 31 };
378
379const QwNeonRegister q0 = { 0 };
380const QwNeonRegister q1 = { 1 };
381const QwNeonRegister q2 = { 2 };
382const QwNeonRegister q3 = { 3 };
383const QwNeonRegister q4 = { 4 };
384const QwNeonRegister q5 = { 5 };
385const QwNeonRegister q6 = { 6 };
386const QwNeonRegister q7 = { 7 };
387const QwNeonRegister q8 = { 8 };
388const QwNeonRegister q9 = { 9 };
389const QwNeonRegister q10 = { 10 };
390const QwNeonRegister q11 = { 11 };
391const QwNeonRegister q12 = { 12 };
392const QwNeonRegister q13 = { 13 };
393const QwNeonRegister q14 = { 14 };
394const QwNeonRegister q15 = { 15 };
395
Leon Clarkee46be812010-01-19 14:06:41 +0000396
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100397// Aliases for double registers. Defined using #define instead of
398// "static const DwVfpRegister&" because Clang complains otherwise when a
399// compilation unit that includes this header doesn't use the variables.
400#define kFirstCalleeSavedDoubleReg d8
401#define kLastCalleeSavedDoubleReg d15
402#define kDoubleRegZero d14
403#define kScratchDoubleReg d15
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +0100404
Steve Blocka7e24c12009-10-30 11:49:00 +0000405
406// Coprocessor register
407struct CRegister {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 bool is_valid() const { return 0 <= reg_code && reg_code < 16; }
409 bool is(CRegister creg) const { return reg_code == creg.reg_code; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100410 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 return reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000413 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100414 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000415 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 return 1 << reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000417 }
418
Andrei Popescu31002712010-02-23 13:46:05 +0000419 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420 int reg_code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000421};
422
423
Steve Block6ded16b2010-05-10 14:33:55 +0100424const CRegister no_creg = { -1 };
425
426const CRegister cr0 = { 0 };
427const CRegister cr1 = { 1 };
428const CRegister cr2 = { 2 };
429const CRegister cr3 = { 3 };
430const CRegister cr4 = { 4 };
431const CRegister cr5 = { 5 };
432const CRegister cr6 = { 6 };
433const CRegister cr7 = { 7 };
434const CRegister cr8 = { 8 };
435const CRegister cr9 = { 9 };
436const CRegister cr10 = { 10 };
437const CRegister cr11 = { 11 };
438const CRegister cr12 = { 12 };
439const CRegister cr13 = { 13 };
440const CRegister cr14 = { 14 };
441const CRegister cr15 = { 15 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000442
443
444// Coprocessor number
445enum Coprocessor {
446 p0 = 0,
447 p1 = 1,
448 p2 = 2,
449 p3 = 3,
450 p4 = 4,
451 p5 = 5,
452 p6 = 6,
453 p7 = 7,
454 p8 = 8,
455 p9 = 9,
456 p10 = 10,
457 p11 = 11,
458 p12 = 12,
459 p13 = 13,
460 p14 = 14,
461 p15 = 15
462};
463
464
Steve Blocka7e24c12009-10-30 11:49:00 +0000465// -----------------------------------------------------------------------------
466// Machine instruction Operands
467
468// Class Operand represents a shifter operand in data processing instructions
469class Operand BASE_EMBEDDED {
470 public:
471 // immediate
472 INLINE(explicit Operand(int32_t immediate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000473 RelocInfo::Mode rmode = RelocInfo::NONE32));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000474 INLINE(static Operand Zero()) {
475 return Operand(static_cast<int32_t>(0));
476 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000477 INLINE(explicit Operand(const ExternalReference& f));
Steve Blocka7e24c12009-10-30 11:49:00 +0000478 explicit Operand(Handle<Object> handle);
479 INLINE(explicit Operand(Smi* value));
480
481 // rm
482 INLINE(explicit Operand(Register rm));
483
484 // rm <shift_op> shift_imm
485 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000486 INLINE(static Operand SmiUntag(Register rm)) {
487 return Operand(rm, ASR, kSmiTagSize);
488 }
489 INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
490 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
491 return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
492 }
493 INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
494 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
495 return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
496 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000497
498 // rm <shift_op> rs
499 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
500
501 // Return true if this is a register operand.
502 INLINE(bool is_reg() const);
503
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000504 // Return the number of actual instructions required to implement the given
505 // instruction for this particular operand. This can be a single instruction,
506 // if no load into the ip register is necessary, or anything between 2 and 4
507 // instructions when we need to load from the constant pool (depending upon
508 // whether the constant pool entry is in the small or extended section). If
Steve Block44f0eee2011-05-26 01:26:41 +0100509 // the instruction this operand is used for is a MOV or MVN instruction the
510 // actual instruction to use is required for this calculation. For other
511 // instructions instr is ignored.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512 //
513 // The value returned is only valid as long as no entries are added to the
514 // constant pool between this call and the actual instruction being emitted.
515 int instructions_required(const Assembler* assembler, Instr instr = 0) const;
516 bool must_output_reloc_info(const Assembler* assembler) const;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100517
518 inline int32_t immediate() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000519 DCHECK(!rm_.is_valid());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100520 return imm32_;
521 }
522
Steve Blocka7e24c12009-10-30 11:49:00 +0000523 Register rm() const { return rm_; }
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100524 Register rs() const { return rs_; }
525 ShiftOp shift_op() const { return shift_op_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000526
527 private:
528 Register rm_;
529 Register rs_;
530 ShiftOp shift_op_;
531 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
532 int32_t imm32_; // valid if rm_ == no_reg
533 RelocInfo::Mode rmode_;
534
535 friend class Assembler;
536};
537
538
539// Class MemOperand represents a memory operand in load and store instructions
540class MemOperand BASE_EMBEDDED {
541 public:
542 // [rn +/- offset] Offset/NegOffset
543 // [rn +/- offset]! PreIndex/NegPreIndex
544 // [rn], +/- offset PostIndex/NegPostIndex
545 // offset is any signed 32-bit value; offset is first loaded to register ip if
546 // it does not fit the addressing mode (12-bit unsigned and sign bit)
547 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
548
549 // [rn +/- rm] Offset/NegOffset
550 // [rn +/- rm]! PreIndex/NegPreIndex
551 // [rn], +/- rm PostIndex/NegPostIndex
552 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
553
554 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
555 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
556 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
557 explicit MemOperand(Register rn, Register rm,
558 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
560 Register key,
561 AddrMode am = Offset)) {
562 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
563 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
564 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000565
Kristian Monsen25f61362010-05-21 11:50:48 +0100566 void set_offset(int32_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567 DCHECK(rm_.is(no_reg));
Kristian Monsen25f61362010-05-21 11:50:48 +0100568 offset_ = offset;
569 }
570
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100571 uint32_t offset() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000572 DCHECK(rm_.is(no_reg));
Kristian Monsen25f61362010-05-21 11:50:48 +0100573 return offset_;
574 }
575
Leon Clarkef7060e22010-06-03 12:02:55 +0100576 Register rn() const { return rn_; }
577 Register rm() const { return rm_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000578 AddrMode am() const { return am_; }
Kristian Monsen25f61362010-05-21 11:50:48 +0100579
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100580 bool OffsetIsUint12Encodable() const {
581 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
582 }
583
Steve Blocka7e24c12009-10-30 11:49:00 +0000584 private:
585 Register rn_; // base
586 Register rm_; // register offset
587 int32_t offset_; // valid if rm_ == no_reg
588 ShiftOp shift_op_;
589 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
590 AddrMode am_; // bits P, U, and W
591
592 friend class Assembler;
593};
594
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000595
596// Class NeonMemOperand represents a memory operand in load and
597// store NEON instructions
598class NeonMemOperand BASE_EMBEDDED {
Steve Blockd0582a62009-12-15 09:54:21 +0000599 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 // [rn {:align}] Offset
601 // [rn {:align}]! PostIndex
602 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
Steve Blockd0582a62009-12-15 09:54:21 +0000603
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000604 // [rn {:align}], rm PostIndex
605 explicit NeonMemOperand(Register rn, Register rm, int align = 0);
Steve Blockd0582a62009-12-15 09:54:21 +0000606
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607 Register rn() const { return rn_; }
608 Register rm() const { return rm_; }
609 int align() const { return align_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100610
Steve Blockd0582a62009-12-15 09:54:21 +0000611 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612 void SetAlignment(int align);
Steve Block44f0eee2011-05-26 01:26:41 +0100613
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000614 Register rn_; // base
615 Register rm_; // register increment
616 int align_;
Steve Blockd0582a62009-12-15 09:54:21 +0000617};
618
Steve Blocka7e24c12009-10-30 11:49:00 +0000619
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620// Class NeonListOperand represents a list of NEON registers
621class NeonListOperand BASE_EMBEDDED {
622 public:
623 explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
624 DoubleRegister base() const { return base_; }
625 NeonListType type() const { return type_; }
626 private:
627 DoubleRegister base_;
628 NeonListType type_;
629};
Steve Blocka7e24c12009-10-30 11:49:00 +0000630
Steve Block1e0659c2011-05-24 12:43:12 +0100631
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000632struct VmovIndex {
633 unsigned char index;
634};
635const VmovIndex VmovIndexLo = { 0 };
636const VmovIndex VmovIndexHi = { 1 };
Steve Block1e0659c2011-05-24 12:43:12 +0100637
Steve Block44f0eee2011-05-26 01:26:41 +0100638class Assembler : public AssemblerBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000639 public:
640 // Create an assembler. Instructions and relocation information are emitted
641 // into a buffer, with the instructions starting from the beginning and the
642 // relocation information starting from the end of the buffer. See CodeDesc
643 // for a detailed comment on the layout (globals.h).
644 //
645 // If the provided buffer is NULL, the assembler allocates and grows its own
646 // buffer, and buffer_size determines the initial buffer size. The buffer is
647 // owned by the assembler and deallocated upon destruction of the assembler.
648 //
649 // If the provided buffer is not NULL, the assembler uses the provided buffer
650 // for code generation and assumes its size to be buffer_size. If the buffer
651 // is too small, a fatal error occurs. No deallocation of the buffer is done
652 // upon destruction of the assembler.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100653 Assembler(Isolate* isolate, void* buffer, int buffer_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 virtual ~Assembler();
Steve Block44f0eee2011-05-26 01:26:41 +0100655
Steve Blocka7e24c12009-10-30 11:49:00 +0000656 // GetCode emits any pending (non-emitted) code and fills the descriptor
657 // desc. GetCode() is idempotent; it returns the same result if no other
658 // Assembler functions are invoked in between GetCode() calls.
659 void GetCode(CodeDesc* desc);
660
661 // Label operations & relative jumps (PPUM Appendix D)
662 //
663 // Takes a branch opcode (cc) and a label (L) and generates
664 // either a backward branch or a forward branch and links it
665 // to the label fixup chain. Usage:
666 //
667 // Label L; // unbound label
668 // j(cc, &L); // forward branch to unbound label
669 // bind(&L); // bind label to the current pc
670 // j(cc, &L); // backward branch to bound label
671 // bind(&L); // illegal: a label may be bound only once
672 //
673 // Note: The same Label can be used for forward and backward branches
674 // but it may be bound only once.
675
676 void bind(Label* L); // binds an unbound label L to the current code position
677
678 // Returns the branch offset to the given label from the current code position
679 // Links the label to the current position if it is still unbound
680 // Manages the jump elimination optimization if the second parameter is true.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000681 int branch_offset(Label* L);
Steve Blocka7e24c12009-10-30 11:49:00 +0000682
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000683 // Returns true if the given pc address is the start of a constant pool load
684 // instruction sequence.
685 INLINE(static bool is_constant_pool_load(Address pc));
Steve Blocka7e24c12009-10-30 11:49:00 +0000686
687 // Return the address in the constant pool of the code target address used by
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000688 // the branch/call instruction at pc, or the object in a mov.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000689 INLINE(static Address constant_pool_entry_address(Address pc,
690 Address constant_pool));
Steve Blocka7e24c12009-10-30 11:49:00 +0000691
692 // Read/Modify the code target address in the branch/call instruction at pc.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000693 INLINE(static Address target_address_at(Address pc, Address constant_pool));
694 INLINE(static void set_target_address_at(
695 Isolate* isolate, Address pc, Address constant_pool, Address target,
696 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000697 INLINE(static Address target_address_at(Address pc, Code* code)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000698 Address constant_pool = code ? code->constant_pool() : NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000699 return target_address_at(pc, constant_pool);
700 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000701 INLINE(static void set_target_address_at(
702 Isolate* isolate, Address pc, Code* code, Address target,
703 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
704 Address constant_pool = code ? code->constant_pool() : NULL;
705 set_target_address_at(isolate, pc, constant_pool, target,
706 icache_flush_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 }
708
709 // Return the code target address at a call site from the return address
710 // of that call in the instruction stream.
711 INLINE(static Address target_address_from_return_address(Address pc));
712
713 // Given the address of the beginning of a call, return the address
714 // in the instruction stream that the call will return from.
715 INLINE(static Address return_address_from_call_start(Address pc));
716
Steve Blockd0582a62009-12-15 09:54:21 +0000717 // This sets the branch destination (which is in the constant pool on ARM).
718 // This is for calls and branches within generated code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100719 inline static void deserialization_set_special_target_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 Isolate* isolate, Address constant_pool_entry, Code* code,
721 Address target);
722
723 // This sets the internal reference at the pc.
724 inline static void deserialization_set_target_internal_reference_at(
725 Isolate* isolate, Address pc, Address target,
726 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
Steve Blockd0582a62009-12-15 09:54:21 +0000727
728 // Here we are patching the address in the constant pool, not the actual call
729 // instruction. The address in the constant pool is the same size as a
730 // pointer.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100731 static const int kSpecialTargetSize = kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +0000732
Steve Blocka7e24c12009-10-30 11:49:00 +0000733 // Size of an instruction.
734 static const int kInstrSize = sizeof(Instr);
735
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100736 // Distance between start of patched debug break slot and the emitted address
737 // to jump to.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100738 // Patched debug break slot code is:
739 // ldr ip, [pc, #0] @ emited address and start
740 // blx ip
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 static const int kPatchDebugBreakSlotAddressOffset = 2 * kInstrSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100742
Steve Blocka7e24c12009-10-30 11:49:00 +0000743 // Difference between address of current opcode and value read from pc
744 // register.
745 static const int kPcLoadDelta = 8;
746
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747 static const int kDebugBreakSlotInstructions = 4;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100748 static const int kDebugBreakSlotLength =
749 kDebugBreakSlotInstructions * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000750
751 // ---------------------------------------------------------------------------
752 // Code generation
753
754 // Insert the smallest number of nop instructions
755 // possible to align the pc offset to a multiple
756 // of m. m must be a power of 2 (>= 4).
757 void Align(int m);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000758 // Insert the smallest number of zero bytes possible to align the pc offset
759 // to a mulitple of m. m must be a power of 2 (>= 2).
760 void DataAlign(int m);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100761 // Aligns code to something that's optimal for a jump target for the platform.
762 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000763
764 // Branch instructions
765 void b(int branch_offset, Condition cond = al);
766 void bl(int branch_offset, Condition cond = al);
767 void blx(int branch_offset); // v5 and above
768 void blx(Register target, Condition cond = al); // v5 and above
769 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
770
771 // Convenience branch instructions using labels
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772 void b(Label* L, Condition cond = al);
773 void b(Condition cond, Label* L) { b(L, cond); }
774 void bl(Label* L, Condition cond = al);
775 void bl(Condition cond, Label* L) { bl(L, cond); }
776 void blx(Label* L); // v5 and above
Steve Blocka7e24c12009-10-30 11:49:00 +0000777
778 // Data-processing instructions
Andrei Popescu31002712010-02-23 13:46:05 +0000779
Steve Blocka7e24c12009-10-30 11:49:00 +0000780 void and_(Register dst, Register src1, const Operand& src2,
781 SBit s = LeaveCC, Condition cond = al);
782
783 void eor(Register dst, Register src1, const Operand& src2,
784 SBit s = LeaveCC, Condition cond = al);
785
786 void sub(Register dst, Register src1, const Operand& src2,
787 SBit s = LeaveCC, Condition cond = al);
788 void sub(Register dst, Register src1, Register src2,
789 SBit s = LeaveCC, Condition cond = al) {
790 sub(dst, src1, Operand(src2), s, cond);
791 }
792
793 void rsb(Register dst, Register src1, const Operand& src2,
794 SBit s = LeaveCC, Condition cond = al);
795
796 void add(Register dst, Register src1, const Operand& src2,
797 SBit s = LeaveCC, Condition cond = al);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100798 void add(Register dst, Register src1, Register src2,
799 SBit s = LeaveCC, Condition cond = al) {
800 add(dst, src1, Operand(src2), s, cond);
801 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000802
803 void adc(Register dst, Register src1, const Operand& src2,
804 SBit s = LeaveCC, Condition cond = al);
805
806 void sbc(Register dst, Register src1, const Operand& src2,
807 SBit s = LeaveCC, Condition cond = al);
808
809 void rsc(Register dst, Register src1, const Operand& src2,
810 SBit s = LeaveCC, Condition cond = al);
811
812 void tst(Register src1, const Operand& src2, Condition cond = al);
813 void tst(Register src1, Register src2, Condition cond = al) {
814 tst(src1, Operand(src2), cond);
815 }
816
817 void teq(Register src1, const Operand& src2, Condition cond = al);
818
819 void cmp(Register src1, const Operand& src2, Condition cond = al);
820 void cmp(Register src1, Register src2, Condition cond = al) {
821 cmp(src1, Operand(src2), cond);
822 }
Steve Block1e0659c2011-05-24 12:43:12 +0100823 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000824
825 void cmn(Register src1, const Operand& src2, Condition cond = al);
826
827 void orr(Register dst, Register src1, const Operand& src2,
828 SBit s = LeaveCC, Condition cond = al);
829 void orr(Register dst, Register src1, Register src2,
830 SBit s = LeaveCC, Condition cond = al) {
831 orr(dst, src1, Operand(src2), s, cond);
832 }
833
834 void mov(Register dst, const Operand& src,
835 SBit s = LeaveCC, Condition cond = al);
836 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
837 mov(dst, Operand(src), s, cond);
838 }
839
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000840 // Load the position of the label relative to the generated code object
841 // pointer in a register.
842 void mov_label_offset(Register dst, Label* label);
843
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100844 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000845 // The constant for movw and movt should be in the range 0-0xffff.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100846 void movw(Register reg, uint32_t immediate, Condition cond = al);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100847 void movt(Register reg, uint32_t immediate, Condition cond = al);
848
Steve Blocka7e24c12009-10-30 11:49:00 +0000849 void bic(Register dst, Register src1, const Operand& src2,
850 SBit s = LeaveCC, Condition cond = al);
851
852 void mvn(Register dst, const Operand& src,
853 SBit s = LeaveCC, Condition cond = al);
854
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000855 // Shift instructions
856
857 void asr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
858 Condition cond = al) {
859 if (src2.is_reg()) {
860 mov(dst, Operand(src1, ASR, src2.rm()), s, cond);
861 } else {
862 mov(dst, Operand(src1, ASR, src2.immediate()), s, cond);
863 }
864 }
865
866 void lsl(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
867 Condition cond = al) {
868 if (src2.is_reg()) {
869 mov(dst, Operand(src1, LSL, src2.rm()), s, cond);
870 } else {
871 mov(dst, Operand(src1, LSL, src2.immediate()), s, cond);
872 }
873 }
874
875 void lsr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
876 Condition cond = al) {
877 if (src2.is_reg()) {
878 mov(dst, Operand(src1, LSR, src2.rm()), s, cond);
879 } else {
880 mov(dst, Operand(src1, LSR, src2.immediate()), s, cond);
881 }
882 }
883
Steve Blocka7e24c12009-10-30 11:49:00 +0000884 // Multiply instructions
885
886 void mla(Register dst, Register src1, Register src2, Register srcA,
887 SBit s = LeaveCC, Condition cond = al);
888
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889 void mls(Register dst, Register src1, Register src2, Register srcA,
890 Condition cond = al);
891
892 void sdiv(Register dst, Register src1, Register src2,
893 Condition cond = al);
894
895 void udiv(Register dst, Register src1, Register src2, Condition cond = al);
896
Steve Blocka7e24c12009-10-30 11:49:00 +0000897 void mul(Register dst, Register src1, Register src2,
898 SBit s = LeaveCC, Condition cond = al);
899
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400900 void smmla(Register dst, Register src1, Register src2, Register srcA,
901 Condition cond = al);
902
903 void smmul(Register dst, Register src1, Register src2, Condition cond = al);
904
Steve Blocka7e24c12009-10-30 11:49:00 +0000905 void smlal(Register dstL, Register dstH, Register src1, Register src2,
906 SBit s = LeaveCC, Condition cond = al);
907
908 void smull(Register dstL, Register dstH, Register src1, Register src2,
909 SBit s = LeaveCC, Condition cond = al);
910
911 void umlal(Register dstL, Register dstH, Register src1, Register src2,
912 SBit s = LeaveCC, Condition cond = al);
913
914 void umull(Register dstL, Register dstH, Register src1, Register src2,
915 SBit s = LeaveCC, Condition cond = al);
916
917 // Miscellaneous arithmetic instructions
918
919 void clz(Register dst, Register src, Condition cond = al); // v5 and above
920
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100921 // Saturating instructions. v6 and above.
922
923 // Unsigned saturate.
924 //
925 // Saturate an optionally shifted signed value to an unsigned range.
926 //
927 // usat dst, #satpos, src
928 // usat dst, #satpos, src, lsl #sh
929 // usat dst, #satpos, src, asr #sh
930 //
931 // Register dst will contain:
932 //
933 // 0, if s < 0
934 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
935 // s, otherwise
936 //
937 // where s is the contents of src after shifting (if used.)
938 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
939
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100940 // Bitfield manipulation instructions. v7 and above.
941
942 void ubfx(Register dst, Register src, int lsb, int width,
943 Condition cond = al);
944
945 void sbfx(Register dst, Register src, int lsb, int width,
946 Condition cond = al);
947
948 void bfc(Register dst, int lsb, int width, Condition cond = al);
949
950 void bfi(Register dst, Register src, int lsb, int width,
951 Condition cond = al);
952
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000953 void pkhbt(Register dst, Register src1, const Operand& src2,
954 Condition cond = al);
955
956 void pkhtb(Register dst, Register src1, const Operand& src2,
957 Condition cond = al);
958
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400959 void sxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
960 void sxtab(Register dst, Register src1, Register src2, int rotate = 0,
961 Condition cond = al);
962 void sxth(Register dst, Register src, int rotate = 0, Condition cond = al);
963 void sxtah(Register dst, Register src1, Register src2, int rotate = 0,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964 Condition cond = al);
965
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400966 void uxtb(Register dst, Register src, int rotate = 0, Condition cond = al);
967 void uxtab(Register dst, Register src1, Register src2, int rotate = 0,
968 Condition cond = al);
969 void uxtb16(Register dst, Register src, int rotate = 0, Condition cond = al);
970 void uxth(Register dst, Register src, int rotate = 0, Condition cond = al);
971 void uxtah(Register dst, Register src1, Register src2, int rotate = 0,
972 Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000973
Ben Murdoch097c5b22016-05-18 11:27:45 +0100974 // Reverse the bits in a register.
975 void rbit(Register dst, Register src, Condition cond = al);
976
Steve Blocka7e24c12009-10-30 11:49:00 +0000977 // Status register access instructions
978
979 void mrs(Register dst, SRegister s, Condition cond = al);
980 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
981
982 // Load/Store instructions
983 void ldr(Register dst, const MemOperand& src, Condition cond = al);
984 void str(Register src, const MemOperand& dst, Condition cond = al);
985 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
986 void strb(Register src, const MemOperand& dst, Condition cond = al);
987 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
988 void strh(Register src, const MemOperand& dst, Condition cond = al);
989 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
990 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
Leon Clarkef7060e22010-06-03 12:02:55 +0100991 void ldrd(Register dst1,
992 Register dst2,
993 const MemOperand& src, Condition cond = al);
994 void strd(Register src1,
995 Register src2,
996 const MemOperand& dst, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000997
Ben Murdoch61f157c2016-09-16 13:49:30 +0100998 // Load/Store exclusive instructions
999 void ldrex(Register dst, Register src, Condition cond = al);
1000 void strex(Register src1, Register src2, Register dst, Condition cond = al);
1001 void ldrexb(Register dst, Register src, Condition cond = al);
1002 void strexb(Register src1, Register src2, Register dst, Condition cond = al);
1003 void ldrexh(Register dst, Register src, Condition cond = al);
1004 void strexh(Register src1, Register src2, Register dst, Condition cond = al);
1005
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001006 // Preload instructions
1007 void pld(const MemOperand& address);
1008
Steve Blocka7e24c12009-10-30 11:49:00 +00001009 // Load/Store multiple instructions
1010 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
1011 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
1012
Steve Blocka7e24c12009-10-30 11:49:00 +00001013 // Exception-generating instructions and debugging support
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001014 void stop(const char* msg,
1015 Condition cond = al,
1016 int32_t code = kDefaultStopCode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001017
1018 void bkpt(uint32_t imm16); // v5 and above
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001019 void svc(uint32_t imm24, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +00001020
Ben Murdoch097c5b22016-05-18 11:27:45 +01001021 // Synchronization instructions
1022 void dmb(BarrierOption option);
1023 void dsb(BarrierOption option);
1024 void isb(BarrierOption option);
1025
Steve Blocka7e24c12009-10-30 11:49:00 +00001026 // Coprocessor instructions
1027
1028 void cdp(Coprocessor coproc, int opcode_1,
1029 CRegister crd, CRegister crn, CRegister crm,
1030 int opcode_2, Condition cond = al);
1031
1032 void cdp2(Coprocessor coproc, int opcode_1,
1033 CRegister crd, CRegister crn, CRegister crm,
1034 int opcode_2); // v5 and above
1035
1036 void mcr(Coprocessor coproc, int opcode_1,
1037 Register rd, CRegister crn, CRegister crm,
1038 int opcode_2 = 0, Condition cond = al);
1039
1040 void mcr2(Coprocessor coproc, int opcode_1,
1041 Register rd, CRegister crn, CRegister crm,
1042 int opcode_2 = 0); // v5 and above
1043
1044 void mrc(Coprocessor coproc, int opcode_1,
1045 Register rd, CRegister crn, CRegister crm,
1046 int opcode_2 = 0, Condition cond = al);
1047
1048 void mrc2(Coprocessor coproc, int opcode_1,
1049 Register rd, CRegister crn, CRegister crm,
1050 int opcode_2 = 0); // v5 and above
1051
1052 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1053 LFlag l = Short, Condition cond = al);
1054 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1055 LFlag l = Short, Condition cond = al);
1056
1057 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1058 LFlag l = Short); // v5 and above
1059 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1060 LFlag l = Short); // v5 and above
1061
Steve Blockd0582a62009-12-15 09:54:21 +00001062 // Support for VFP.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001063 // All these APIs support S0 to S31 and D0 to D31.
Steve Blockd0582a62009-12-15 09:54:21 +00001064
Leon Clarked91b9f72010-01-27 17:25:45 +00001065 void vldr(const DwVfpRegister dst,
1066 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001067 int offset,
1068 const Condition cond = al);
1069 void vldr(const DwVfpRegister dst,
1070 const MemOperand& src,
Leon Clarked91b9f72010-01-27 17:25:45 +00001071 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001072
1073 void vldr(const SwVfpRegister dst,
1074 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001075 int offset,
1076 const Condition cond = al);
1077 void vldr(const SwVfpRegister dst,
1078 const MemOperand& src,
Steve Block6ded16b2010-05-10 14:33:55 +01001079 const Condition cond = al);
1080
Leon Clarked91b9f72010-01-27 17:25:45 +00001081 void vstr(const DwVfpRegister src,
1082 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001083 int offset,
1084 const Condition cond = al);
1085 void vstr(const DwVfpRegister src,
1086 const MemOperand& dst,
Leon Clarked91b9f72010-01-27 17:25:45 +00001087 const Condition cond = al);
Steve Block8defd9f2010-07-08 12:39:36 +01001088
Iain Merrick75681382010-08-19 15:07:18 +01001089 void vstr(const SwVfpRegister src,
1090 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001091 int offset,
1092 const Condition cond = al);
1093 void vstr(const SwVfpRegister src,
1094 const MemOperand& dst,
Iain Merrick75681382010-08-19 15:07:18 +01001095 const Condition cond = al);
1096
Ben Murdoch8b112d22011-06-08 16:22:53 +01001097 void vldm(BlockAddrMode am,
1098 Register base,
1099 DwVfpRegister first,
1100 DwVfpRegister last,
1101 Condition cond = al);
1102
1103 void vstm(BlockAddrMode am,
1104 Register base,
1105 DwVfpRegister first,
1106 DwVfpRegister last,
1107 Condition cond = al);
1108
1109 void vldm(BlockAddrMode am,
1110 Register base,
1111 SwVfpRegister first,
1112 SwVfpRegister last,
1113 Condition cond = al);
1114
1115 void vstm(BlockAddrMode am,
1116 Register base,
1117 SwVfpRegister first,
1118 SwVfpRegister last,
1119 Condition cond = al);
1120
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001121 void vmov(const SwVfpRegister dst, float imm);
Steve Block8defd9f2010-07-08 12:39:36 +01001122 void vmov(const DwVfpRegister dst,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001123 double imm,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001124 const Register scratch = no_reg);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001125 void vmov(const SwVfpRegister dst,
1126 const SwVfpRegister src,
1127 const Condition cond = al);
1128 void vmov(const DwVfpRegister dst,
Steve Block8defd9f2010-07-08 12:39:36 +01001129 const DwVfpRegister src,
1130 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001131 void vmov(const DwVfpRegister dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001132 const VmovIndex index,
1133 const Register src,
1134 const Condition cond = al);
1135 void vmov(const Register dst,
1136 const VmovIndex index,
1137 const DwVfpRegister src,
1138 const Condition cond = al);
1139 void vmov(const DwVfpRegister dst,
Leon Clarkee46be812010-01-19 14:06:41 +00001140 const Register src1,
Steve Blockd0582a62009-12-15 09:54:21 +00001141 const Register src2,
Leon Clarkee46be812010-01-19 14:06:41 +00001142 const Condition cond = al);
1143 void vmov(const Register dst1,
1144 const Register dst2,
1145 const DwVfpRegister src,
1146 const Condition cond = al);
1147 void vmov(const SwVfpRegister dst,
1148 const Register src,
1149 const Condition cond = al);
1150 void vmov(const Register dst,
1151 const SwVfpRegister src,
1152 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001153 void vcvt_f64_s32(const DwVfpRegister dst,
1154 const SwVfpRegister 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_f32_s32(const SwVfpRegister 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_f64_u32(const DwVfpRegister dst,
1162 const SwVfpRegister 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 Murdoch097c5b22016-05-18 11:27:45 +01001165 void vcvt_f32_u32(const SwVfpRegister dst,
1166 const SwVfpRegister src,
1167 VFPConversionMode mode = kDefaultRoundToZero,
1168 const Condition cond = al);
1169 void vcvt_s32_f32(const SwVfpRegister dst,
1170 const SwVfpRegister src,
1171 VFPConversionMode mode = kDefaultRoundToZero,
1172 const Condition cond = al);
1173 void vcvt_u32_f32(const SwVfpRegister dst,
1174 const SwVfpRegister src,
1175 VFPConversionMode mode = kDefaultRoundToZero,
1176 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001177 void vcvt_s32_f64(const SwVfpRegister dst,
1178 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001179 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001180 const Condition cond = al);
1181 void vcvt_u32_f64(const SwVfpRegister dst,
1182 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001183 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001184 const Condition cond = al);
1185 void vcvt_f64_f32(const DwVfpRegister dst,
1186 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001187 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001188 const Condition cond = al);
1189 void vcvt_f32_f64(const SwVfpRegister dst,
1190 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001191 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001192 const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001193 void vcvt_f64_s32(const DwVfpRegister dst,
1194 int fraction_bits,
1195 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001196
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001197 void vmrs(const Register dst, const Condition cond = al);
1198 void vmsr(const Register dst, const Condition cond = al);
1199
Steve Block44f0eee2011-05-26 01:26:41 +01001200 void vneg(const DwVfpRegister dst,
1201 const DwVfpRegister src,
1202 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001203 void vneg(const SwVfpRegister dst, const SwVfpRegister src,
1204 const Condition cond = al);
Steve Block1e0659c2011-05-24 12:43:12 +01001205 void vabs(const DwVfpRegister dst,
1206 const DwVfpRegister src,
1207 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001208 void vabs(const SwVfpRegister dst, const SwVfpRegister src,
1209 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001210 void vadd(const DwVfpRegister dst,
1211 const DwVfpRegister src1,
1212 const DwVfpRegister src2,
1213 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001214 void vadd(const SwVfpRegister dst, const SwVfpRegister src1,
1215 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001216 void vsub(const DwVfpRegister dst,
1217 const DwVfpRegister src1,
1218 const DwVfpRegister src2,
1219 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001220 void vsub(const SwVfpRegister dst, const SwVfpRegister src1,
1221 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001222 void vmul(const DwVfpRegister dst,
1223 const DwVfpRegister src1,
1224 const DwVfpRegister src2,
1225 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 void vmul(const SwVfpRegister dst, const SwVfpRegister src1,
1227 const SwVfpRegister src2, const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001228 void vmla(const DwVfpRegister dst,
1229 const DwVfpRegister src1,
1230 const DwVfpRegister src2,
1231 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232 void vmla(const SwVfpRegister dst, const SwVfpRegister src1,
1233 const SwVfpRegister src2, const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001234 void vmls(const DwVfpRegister dst,
1235 const DwVfpRegister src1,
1236 const DwVfpRegister src2,
1237 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238 void vmls(const SwVfpRegister dst, const SwVfpRegister src1,
1239 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001240 void vdiv(const DwVfpRegister dst,
1241 const DwVfpRegister src1,
1242 const DwVfpRegister src2,
1243 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001244 void vdiv(const SwVfpRegister dst, const SwVfpRegister src1,
1245 const SwVfpRegister src2, const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001246 void vcmp(const DwVfpRegister src1,
1247 const DwVfpRegister src2,
Steve Blockd0582a62009-12-15 09:54:21 +00001248 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001249 void vcmp(const SwVfpRegister src1, const SwVfpRegister src2,
1250 const Condition cond = al);
Iain Merrick75681382010-08-19 15:07:18 +01001251 void vcmp(const DwVfpRegister src1,
1252 const double src2,
Iain Merrick75681382010-08-19 15:07:18 +01001253 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001254 void vcmp(const SwVfpRegister src1, const float src2,
Russell Brenner90bac252010-11-18 13:33:46 -08001255 const Condition cond = al);
Ben Murdochc5610432016-08-08 18:44:38 +01001256
1257 // VSEL supports cond in {eq, ne, ge, lt, gt, le, vs, vc}.
1258 void vsel(const Condition cond,
1259 const DwVfpRegister dst,
1260 const DwVfpRegister src1,
1261 const DwVfpRegister src2);
1262 void vsel(const Condition cond,
1263 const SwVfpRegister dst,
1264 const SwVfpRegister src1,
1265 const SwVfpRegister src2);
1266
Steve Block8defd9f2010-07-08 12:39:36 +01001267 void vsqrt(const DwVfpRegister dst,
1268 const DwVfpRegister src,
1269 const Condition cond = al);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 void vsqrt(const SwVfpRegister dst, const SwVfpRegister src,
1271 const Condition cond = al);
Steve Blockd0582a62009-12-15 09:54:21 +00001272
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001273 // ARMv8 rounding instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 void vrinta(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001275 void vrinta(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276 void vrintn(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001277 void vrintn(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001278 void vrintm(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001279 void vrintm(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 void vrintp(const SwVfpRegister dst, const SwVfpRegister src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001281 void vrintp(const DwVfpRegister dst, const DwVfpRegister src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282 void vrintz(const SwVfpRegister dst, const SwVfpRegister src,
1283 const Condition cond = al);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001284 void vrintz(const DwVfpRegister dst, const DwVfpRegister src,
1285 const Condition cond = al);
1286
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 // Support for NEON.
1288 // All these APIs support D0 to D31 and Q0 to Q15.
1289
1290 void vld1(NeonSize size,
1291 const NeonListOperand& dst,
1292 const NeonMemOperand& src);
1293 void vst1(NeonSize size,
1294 const NeonListOperand& src,
1295 const NeonMemOperand& dst);
1296 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1297
Steve Blocka7e24c12009-10-30 11:49:00 +00001298 // Pseudo instructions
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001299
1300 // Different nop operations are used by the code generator to detect certain
1301 // states of the generated code.
1302 enum NopMarkerTypes {
1303 NON_MARKING_NOP = 0,
1304 DEBUG_BREAK_NOP,
1305 // IC markers.
1306 PROPERTY_ACCESS_INLINED,
1307 PROPERTY_ACCESS_INLINED_CONTEXT,
1308 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1309 // Helper values.
1310 LAST_CODE_MARKER,
1311 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1312 };
1313
1314 void nop(int type = 0); // 0 is the default non-marking type.
Steve Blocka7e24c12009-10-30 11:49:00 +00001315
1316 void push(Register src, Condition cond = al) {
1317 str(src, MemOperand(sp, 4, NegPreIndex), cond);
1318 }
1319
1320 void pop(Register dst, Condition cond = al) {
1321 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1322 }
1323
1324 void pop() {
1325 add(sp, sp, Operand(kPointerSize));
1326 }
1327
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001328 void vpush(DwVfpRegister src, Condition cond = al) {
1329 vstm(db_w, sp, src, src, cond);
1330 }
1331
Ben Murdoch61f157c2016-09-16 13:49:30 +01001332 void vpush(SwVfpRegister src, Condition cond = al) {
1333 vstm(db_w, sp, src, src, cond);
1334 }
1335
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001336 void vpop(DwVfpRegister dst, Condition cond = al) {
1337 vldm(ia_w, sp, dst, dst, cond);
1338 }
1339
Steve Blocka7e24c12009-10-30 11:49:00 +00001340 // Jump unconditionally to given label.
1341 void jmp(Label* L) { b(L, al); }
1342
1343 // Check the code size generated from label to here.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001344 int SizeOfCodeGeneratedSince(Label* label) {
1345 return pc_offset() - label->pos();
1346 }
1347
1348 // Check the number of instructions generated from label to here.
1349 int InstructionsGeneratedSince(Label* label) {
1350 return SizeOfCodeGeneratedSince(label) / kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001351 }
1352
Steve Blockd0582a62009-12-15 09:54:21 +00001353 // Check whether an immediate fits an addressing mode 1 instruction.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001354 static bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1355
1356 // Check whether an immediate fits an addressing mode 2 instruction.
1357 bool ImmediateFitsAddrMode2Instruction(int32_t imm32);
Steve Blockd0582a62009-12-15 09:54:21 +00001358
Steve Block6ded16b2010-05-10 14:33:55 +01001359 // Class for scoping postponing the constant pool generation.
1360 class BlockConstPoolScope {
1361 public:
1362 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1363 assem_->StartBlockConstPool();
1364 }
1365 ~BlockConstPoolScope() {
1366 assem_->EndBlockConstPool();
1367 }
1368
1369 private:
1370 Assembler* assem_;
1371
1372 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1373 };
1374
Steve Blocka7e24c12009-10-30 11:49:00 +00001375 // Debugging
1376
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001377 // Mark generator continuation.
1378 void RecordGeneratorContinuation();
Steve Blocka7e24c12009-10-30 11:49:00 +00001379
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001380 // Mark address of a debug break slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001381 void RecordDebugBreakSlot(RelocInfo::Mode mode);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001382
Ben Murdoch257744e2011-11-30 15:57:28 +00001383 // Record the AST id of the CallIC being compiled, so that it can be placed
1384 // in the relocation information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001385 void SetRecordedAstId(TypeFeedbackId ast_id) {
1386 DCHECK(recorded_ast_id_.IsNone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001387 recorded_ast_id_ = ast_id;
1388 }
1389
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001390 TypeFeedbackId RecordedAstId() {
1391 DCHECK(!recorded_ast_id_.IsNone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001392 return recorded_ast_id_;
1393 }
1394
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001395 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
Ben Murdoch257744e2011-11-30 15:57:28 +00001396
Steve Blocka7e24c12009-10-30 11:49:00 +00001397 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001398 // Use --code-comments to enable.
Steve Blocka7e24c12009-10-30 11:49:00 +00001399 void RecordComment(const char* msg);
1400
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001401 // Record a deoptimization reason that can be used by a log or cpu profiler.
1402 // Use --trace-deopt to enable.
Ben Murdochc5610432016-08-08 18:44:38 +01001403 void RecordDeoptReason(const int reason, int raw_position, int id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001404
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001405 // Record the emission of a constant pool.
1406 //
1407 // The emission of constant pool depends on the size of the code generated and
1408 // the number of RelocInfo recorded.
1409 // The Debug mechanism needs to map code offsets between two versions of a
1410 // function, compiled with and without debugger support (see for example
1411 // Debug::PrepareForBreakPoints()).
1412 // Compiling functions with debugger support generates additional code
1413 // (DebugCodegen::GenerateSlot()). This may affect the emission of the
1414 // constant pools and cause the version of the code with debugger support to
1415 // have constant pools generated in different places.
1416 // Recording the position and size of emitted constant pools allows to
1417 // correctly compute the offset mappings between the different versions of a
1418 // function in all situations.
1419 //
1420 // The parameter indicates the size of the constant pool (in bytes), including
1421 // the marker and branch over the data.
1422 void RecordConstPool(int size);
1423
Ben Murdochb8e0da22011-05-16 14:20:40 +01001424 // Writes a single byte or word of data in the code stream. Used
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001425 // for inline tables, e.g., jump-tables. CheckConstantPool() should be
1426 // called before any use of db/dd/dq/dp to ensure that constant pools
Ben Murdochb8e0da22011-05-16 14:20:40 +01001427 // are not emitted as part of the tables generated.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001428 void db(uint8_t data);
1429 void dd(uint32_t data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001430 void dq(uint64_t data);
1431 void dp(uintptr_t data) { dd(data); }
Ben Murdochb0fe1622011-05-05 13:52:32 +01001432
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001433 // Emits the address of the code stub's first instruction.
1434 void emit_code_stub_address(Code* stub);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001435
Ben Murdochda12d292016-06-02 14:46:10 +01001436 AssemblerPositionsRecorder* positions_recorder() {
1437 return &positions_recorder_;
1438 }
Steve Block6ded16b2010-05-10 14:33:55 +01001439
1440 // Read/patch instructions
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001441 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1442 void instr_at_put(int pos, Instr instr) {
1443 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1444 }
Steve Block6ded16b2010-05-10 14:33:55 +01001445 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1446 static void instr_at_put(byte* pc, Instr instr) {
1447 *reinterpret_cast<Instr*>(pc) = instr;
1448 }
Steve Block1e0659c2011-05-24 12:43:12 +01001449 static Condition GetCondition(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001450 static bool IsBranch(Instr instr);
1451 static int GetBranchOffset(Instr instr);
1452 static bool IsLdrRegisterImmediate(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001453 static bool IsVldrDRegisterImmediate(Instr instr);
1454 static Instr GetConsantPoolLoadPattern();
1455 static Instr GetConsantPoolLoadMask();
1456 static bool IsLdrPpRegOffset(Instr instr);
1457 static Instr GetLdrPpRegOffsetPattern();
1458 static bool IsLdrPpImmediateOffset(Instr instr);
1459 static bool IsVldrDPpImmediateOffset(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001460 static int GetLdrRegisterImmediateOffset(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001461 static int GetVldrDRegisterImmediateOffset(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001462 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001463 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
Kristian Monsen50ef84f2010-07-29 15:18:00 +01001464 static bool IsStrRegisterImmediate(Instr instr);
1465 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1466 static bool IsAddRegisterImmediate(Instr instr);
1467 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
Leon Clarkef7060e22010-06-03 12:02:55 +01001468 static Register GetRd(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001469 static Register GetRn(Instr instr);
1470 static Register GetRm(Instr instr);
Leon Clarkef7060e22010-06-03 12:02:55 +01001471 static bool IsPush(Instr instr);
1472 static bool IsPop(Instr instr);
1473 static bool IsStrRegFpOffset(Instr instr);
1474 static bool IsLdrRegFpOffset(Instr instr);
1475 static bool IsStrRegFpNegOffset(Instr instr);
1476 static bool IsLdrRegFpNegOffset(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001477 static bool IsLdrPcImmediateOffset(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001478 static bool IsVldrDPcImmediateOffset(Instr instr);
1479 static bool IsBlxReg(Instr instr);
1480 static bool IsBlxIp(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001481 static bool IsTstImmediate(Instr instr);
1482 static bool IsCmpRegister(Instr instr);
1483 static bool IsCmpImmediate(Instr instr);
1484 static Register GetCmpImmediateRegister(Instr instr);
1485 static int GetCmpImmediateRawImmediate(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001486 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001487 static bool IsMovImmed(Instr instr);
1488 static bool IsOrrImmed(Instr instr);
1489 static bool IsMovT(Instr instr);
1490 static Instr GetMovTPattern();
1491 static bool IsMovW(Instr instr);
1492 static Instr GetMovWPattern();
1493 static Instr EncodeMovwImmediate(uint32_t immediate);
1494 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate);
1495 static int DecodeShiftImm(Instr instr);
1496 static Instr PatchShiftImm(Instr instr, int immed);
Steve Block6ded16b2010-05-10 14:33:55 +01001497
Ben Murdoch257744e2011-11-30 15:57:28 +00001498 // Constants in pools are accessed via pc relative addressing, which can
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1500 // PC-relative loads, thereby defining a maximum distance between the
1501 // instruction and the accessed constant.
1502 static const int kMaxDistToIntPool = 4*KB;
1503 static const int kMaxDistToFPPool = 1*KB;
1504 // All relocations could be integer, it therefore acts as the limit.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001505 static const int kMinNumPendingConstants = 4;
1506 static const int kMaxNumPending32Constants = kMaxDistToIntPool / kInstrSize;
1507 static const int kMaxNumPending64Constants = kMaxDistToFPPool / kInstrSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00001508
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001509 // Postpone the generation of the constant pool for the specified number of
1510 // instructions.
1511 void BlockConstPoolFor(int instructions);
1512
1513 // Check if is time to emit a constant pool.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001514 void CheckConstPool(bool force_emit, bool require_jump);
Steve Blocka7e24c12009-10-30 11:49:00 +00001515
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001516 void MaybeCheckConstPool() {
1517 if (pc_offset() >= next_buffer_check_) {
1518 CheckConstPool(false, true);
1519 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001520 }
1521
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001522 int EmitEmbeddedConstantPool() {
1523 DCHECK(FLAG_enable_embedded_constant_pool);
1524 return constant_pool_builder_.Emit(this);
1525 }
1526
1527 bool ConstantPoolAccessIsInOverflow() const {
1528 return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1529 ConstantPoolEntry::OVERFLOWED;
1530 }
1531
1532 void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1533 ConstantPoolEntry::Access access,
1534 ConstantPoolEntry::Type type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535
Steve Blocka7e24c12009-10-30 11:49:00 +00001536 protected:
Ben Murdoch257744e2011-11-30 15:57:28 +00001537 // Relocation for a type-recording IC has the AST id added to it. This
1538 // member variable is a way to pass the information from the call site to
1539 // the relocation info.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540 TypeFeedbackId recorded_ast_id_;
Steve Block44f0eee2011-05-26 01:26:41 +01001541
Steve Blocka7e24c12009-10-30 11:49:00 +00001542 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1543
Steve Blocka7e24c12009-10-30 11:49:00 +00001544 // Decode branch instruction at pos and return branch target pos
1545 int target_at(int pos);
1546
1547 // Patch branch instruction at pos to branch to given branch target pos
1548 void target_at_put(int pos, int target_pos);
1549
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001550 // Prevent contant pool emission until EndBlockConstPool is called.
1551 // Call to this function can be nested but must be followed by an equal
1552 // number of call to EndBlockConstpool.
1553 void StartBlockConstPool() {
1554 if (const_pool_blocked_nesting_++ == 0) {
1555 // Prevent constant pool checks happening by setting the next check to
1556 // the biggest possible offset.
1557 next_buffer_check_ = kMaxInt;
1558 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001559 }
1560
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001561 // Resume constant pool emission. Need to be called as many time as
1562 // StartBlockConstPool to have an effect.
Steve Block6ded16b2010-05-10 14:33:55 +01001563 void EndBlockConstPool() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001564 if (--const_pool_blocked_nesting_ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001565#ifdef DEBUG
1566 // Max pool start (if we need a jump and an alignment).
1567 int start = pc_offset() + kInstrSize + 2 * kPointerSize;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001568 // Check the constant pool hasn't been blocked for too long.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001569 DCHECK(pending_32_bit_constants_.empty() ||
1570 (start + pending_64_bit_constants_.size() * kDoubleSize <
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001571 (first_const_pool_32_use_ + kMaxDistToIntPool)));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001572 DCHECK(pending_64_bit_constants_.empty() ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001573 (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
1574#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001575 // Two cases:
1576 // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1577 // still blocked
1578 // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1579 // trigger a check.
1580 next_buffer_check_ = no_const_pool_before_;
1581 }
Steve Block6ded16b2010-05-10 14:33:55 +01001582 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001583
1584 bool is_const_pool_blocked() const {
1585 return (const_pool_blocked_nesting_ > 0) ||
1586 (pc_offset() < no_const_pool_before_);
1587 }
Steve Block6ded16b2010-05-10 14:33:55 +01001588
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001589 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00001590 int next_buffer_check_; // pc offset of next buffer check
1591
1592 // Code generation
1593 // The relocation writer's position is at least kGap bytes below the end of
1594 // the generated instructions. This is so that multi-instruction sequences do
1595 // not have to check for overflow. The same is true for writes of large
1596 // relocation info entries.
1597 static const int kGap = 32;
Steve Blocka7e24c12009-10-30 11:49:00 +00001598
1599 // Constant pool generation
1600 // Pools are emitted in the instruction stream, preferably after unconditional
1601 // jumps or after returns from functions (in dead code locations).
1602 // If a long code sequence does not contain unconditional jumps, it is
1603 // necessary to emit the constant pool before the pool gets too far from the
1604 // location it is accessed from. In this case, we emit a jump over the emitted
1605 // constant pool.
1606 // Constants in the pool may be addresses of functions that gets relocated;
1607 // if so, a relocation info entry is associated to the constant pool entry.
1608
1609 // Repeated checking whether the constant pool should be emitted is rather
1610 // expensive. By default we only check again once a number of instructions
1611 // has been generated. That also means that the sizing of the buffers is not
1612 // an exact science, and that we rely on some slop to not overrun buffers.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001613 static const int kCheckPoolIntervalInst = 32;
1614 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001615
1616
Steve Block6ded16b2010-05-10 14:33:55 +01001617 // Emission of the constant pool may be blocked in some code sequences.
1618 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1619 int no_const_pool_before_; // Block emission before this pc offset.
Steve Blocka7e24c12009-10-30 11:49:00 +00001620
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001621 // Keep track of the first instruction requiring a constant pool entry
1622 // since the previous constant pool was emitted.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001623 int first_const_pool_32_use_;
1624 int first_const_pool_64_use_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001625
1626 // Relocation info generation
1627 // Each relocation is encoded as a variable size value
1628 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1629 RelocInfoWriter reloc_info_writer;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001630
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001631 // ConstantPoolEntry records are used during code generation as temporary
Steve Blocka7e24c12009-10-30 11:49:00 +00001632 // containers for constants and code target addresses until they are emitted
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001633 // to the constant pool. These records are temporarily stored in a separate
1634 // buffer until a constant pool is emitted.
Steve Blocka7e24c12009-10-30 11:49:00 +00001635 // If every instruction in a long sequence is accessing the pool, we need one
1636 // pending relocation entry per instruction.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001637
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001638 // The buffers of pending constant pool entries.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001639 std::vector<ConstantPoolEntry> pending_32_bit_constants_;
1640 std::vector<ConstantPoolEntry> pending_64_bit_constants_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001641
1642 ConstantPoolBuilder constant_pool_builder_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001643
1644 // The bound position, before this we cannot do instruction elimination.
1645 int last_bound_pos_;
1646
Steve Blocka7e24c12009-10-30 11:49:00 +00001647 // Code emission
1648 inline void CheckBuffer();
1649 void GrowBuffer();
1650 inline void emit(Instr x);
1651
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001652 // 32-bit immediate values
1653 void move_32_bit_immediate(Register rd,
1654 const Operand& x,
1655 Condition cond = al);
1656
Steve Blocka7e24c12009-10-30 11:49:00 +00001657 // Instruction generation
1658 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1659 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1660 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1661 void addrmod4(Instr instr, Register rn, RegList rl);
1662 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1663
1664 // Labels
1665 void print(Label* L);
1666 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001667 void next(Label* L);
1668
1669 // Record reloc info for current pc_
1670 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001671 ConstantPoolEntry::Access ConstantPoolAddEntry(int position,
1672 RelocInfo::Mode rmode,
1673 intptr_t value);
1674 ConstantPoolEntry::Access ConstantPoolAddEntry(int position, double value);
Steve Blocka7e24c12009-10-30 11:49:00 +00001675
Steve Blocka7e24c12009-10-30 11:49:00 +00001676 friend class RelocInfo;
1677 friend class CodePatcher;
Steve Block6ded16b2010-05-10 14:33:55 +01001678 friend class BlockConstPoolScope;
Ben Murdochda12d292016-06-02 14:46:10 +01001679 AssemblerPositionsRecorder positions_recorder_;
1680 friend class AssemblerPositionsRecorder;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001681 friend class EnsureSpace;
Steve Blocka7e24c12009-10-30 11:49:00 +00001682};
1683
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001684
1685class EnsureSpace BASE_EMBEDDED {
1686 public:
1687 explicit EnsureSpace(Assembler* assembler) {
1688 assembler->CheckBuffer();
1689 }
1690};
1691
1692
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001693} // namespace internal
1694} // namespace v8
Steve Blocka7e24c12009-10-30 11:49:00 +00001695
1696#endif // V8_ARM_ASSEMBLER_ARM_H_