blob: 108d5cb0908045353a618e5e05868162697dccbe [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"
48#include "src/serialize.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000049
50namespace v8 {
51namespace internal {
52
53// CPU Registers.
54//
55// 1) We would prefer to use an enum, but enum values are assignment-
56// compatible with int, which has caused code-generation bugs.
57//
58// 2) We would prefer to use a class instead of a struct but we don't like
59// the register initialization to depend on the particular initialization
60// order (which appears to be different on OS X, Linux, and Windows for the
61// installed versions of C++ we tried). Using a struct permits C-style
62// "initialization". Also, the Register objects cannot be const as this
63// forces initialization stubs in MSVC, making us dependent on initialization
64// order.
65//
66// 3) By not using an enum, we are possibly preventing the compiler from
67// doing certain constant folds, which may significantly reduce the
68// code generated for some assembly instructions (because they boil down
69// to a few constants). If this is a problem, we could change the code
70// such that we use an enum in optimized mode, and the struct in debug
71// mode. This way we get the compile-time error checking in debug mode
72// and best performance in optimized code.
Steve Block9fac8402011-05-12 15:51:54 +010073
Ben Murdoch3ef787d2012-04-12 10:51:47 +010074// These constants are used in several locations, including static initializers
75const int kRegister_no_reg_Code = -1;
76const int kRegister_r0_Code = 0;
77const int kRegister_r1_Code = 1;
78const int kRegister_r2_Code = 2;
79const int kRegister_r3_Code = 3;
80const int kRegister_r4_Code = 4;
81const int kRegister_r5_Code = 5;
82const int kRegister_r6_Code = 6;
83const int kRegister_r7_Code = 7;
84const int kRegister_r8_Code = 8;
85const int kRegister_r9_Code = 9;
86const int kRegister_r10_Code = 10;
87const int kRegister_fp_Code = 11;
88const int kRegister_ip_Code = 12;
89const int kRegister_sp_Code = 13;
90const int kRegister_lr_Code = 14;
91const int kRegister_pc_Code = 15;
Steve Blocka7e24c12009-10-30 11:49:00 +000092
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093// Core register
94struct Register {
95 static const int kNumRegisters = 16;
96 static const int kMaxNumAllocatableRegisters =
97 FLAG_enable_ool_constant_pool ? 8 : 9;
98 static const int kSizeInBytes = 4;
99
100 inline static int NumAllocatableRegisters();
101
102 static int ToAllocationIndex(Register reg) {
103 DCHECK(reg.code() < kMaxNumAllocatableRegisters);
104 return reg.code();
105 }
106
107 static Register FromAllocationIndex(int index) {
108 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
109 return from_code(index);
110 }
111
112 static const char* AllocationIndexToString(int index) {
113 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
114 const char* const names[] = {
115 "r0",
116 "r1",
117 "r2",
118 "r3",
119 "r4",
120 "r5",
121 "r6",
122 "r7",
123 "r8",
124 };
125 if (FLAG_enable_ool_constant_pool && (index >= 7)) {
126 return names[index + 1];
127 }
128 return names[index];
129 }
130
131 static Register from_code(int code) {
132 Register r = { code };
133 return r;
134 }
135
136 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
137 bool is(Register reg) const { return code_ == reg.code_; }
138 int code() const {
139 DCHECK(is_valid());
140 return code_;
141 }
142 int bit() const {
143 DCHECK(is_valid());
144 return 1 << code_;
145 }
146
147 void set_code(int code) {
148 code_ = code;
149 DCHECK(is_valid());
150 }
151
152 // Unfortunately we can't make this private in a struct.
153 int code_;
154};
155
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100156const Register no_reg = { kRegister_no_reg_Code };
157
158const Register r0 = { kRegister_r0_Code };
159const Register r1 = { kRegister_r1_Code };
160const Register r2 = { kRegister_r2_Code };
161const Register r3 = { kRegister_r3_Code };
162const Register r4 = { kRegister_r4_Code };
163const Register r5 = { kRegister_r5_Code };
164const Register r6 = { kRegister_r6_Code };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000165// Used as constant pool pointer register if FLAG_enable_ool_constant_pool.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100166const Register r7 = { kRegister_r7_Code };
167// Used as context register.
168const Register r8 = { kRegister_r8_Code };
169// Used as lithium codegen scratch register.
170const Register r9 = { kRegister_r9_Code };
171// Used as roots register.
172const Register r10 = { kRegister_r10_Code };
173const Register fp = { kRegister_fp_Code };
174const Register ip = { kRegister_ip_Code };
175const Register sp = { kRegister_sp_Code };
176const Register lr = { kRegister_lr_Code };
177const Register pc = { kRegister_pc_Code };
178
Leon Clarkee46be812010-01-19 14:06:41 +0000179// Single word VFP register.
180struct SwVfpRegister {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181 static const int kSizeInBytes = 4;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100182 bool is_valid() const { return 0 <= code_ && code_ < 32; }
183 bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
184 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000185 DCHECK(is_valid());
Leon Clarkee46be812010-01-19 14:06:41 +0000186 return code_;
187 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100188 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 DCHECK(is_valid());
Leon Clarkee46be812010-01-19 14:06:41 +0000190 return 1 << code_;
191 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100192 void split_code(int* vm, int* m) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 DCHECK(is_valid());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100194 *m = code_ & 0x1;
195 *vm = code_ >> 1;
196 }
Leon Clarkee46be812010-01-19 14:06:41 +0000197
198 int code_;
199};
200
201
202// Double word VFP register.
203struct DwVfpRegister {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 static const int kMaxNumRegisters = 32;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000205 // A few double registers are reserved: one as a scratch register and one to
206 // hold 0.0, that does not fit in the immediate field of vmov instructions.
207 // d14: 0.0
208 // d15: scratch register.
209 static const int kNumReservedRegisters = 2;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000211 kNumReservedRegisters;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000212 static const int kSizeInBytes = 8;
213
214 // Note: the number of registers can be different at snapshot and run-time.
215 // Any code included in the snapshot must be able to run both with 16 or 32
216 // registers.
217 inline static int NumRegisters();
218 inline static int NumReservedRegisters();
219 inline static int NumAllocatableRegisters();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100220
Ben Murdoch692be652012-01-10 18:47:50 +0000221 inline static int ToAllocationIndex(DwVfpRegister reg);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222 static const char* AllocationIndexToString(int index);
223 inline static DwVfpRegister FromAllocationIndex(int index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100224
225 static DwVfpRegister from_code(int code) {
226 DwVfpRegister r = { code };
227 return r;
228 }
229
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 bool is_valid() const {
231 return 0 <= code_ && code_ < kMaxNumRegisters;
232 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100233 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100234 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 DCHECK(is_valid());
Leon Clarkee46be812010-01-19 14:06:41 +0000236 return code_;
237 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100238 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 DCHECK(is_valid());
Leon Clarkee46be812010-01-19 14:06:41 +0000240 return 1 << code_;
241 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100242 void split_code(int* vm, int* m) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 DCHECK(is_valid());
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100244 *m = (code_ & 0x10) >> 4;
245 *vm = code_ & 0x0F;
246 }
Leon Clarkee46be812010-01-19 14:06:41 +0000247
248 int code_;
249};
250
251
Ben Murdochb0fe1622011-05-05 13:52:32 +0100252typedef DwVfpRegister DoubleRegister;
253
254
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255// Double word VFP register d0-15.
256struct LowDwVfpRegister {
257 public:
258 static const int kMaxNumLowRegisters = 16;
259 operator DwVfpRegister() const {
260 DwVfpRegister r = { code_ };
261 return r;
262 }
263 static LowDwVfpRegister from_code(int code) {
264 LowDwVfpRegister r = { code };
265 return r;
266 }
267
268 bool is_valid() const {
269 return 0 <= code_ && code_ < kMaxNumLowRegisters;
270 }
271 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
272 bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
273 int code() const {
274 DCHECK(is_valid());
275 return code_;
276 }
277 SwVfpRegister low() const {
278 SwVfpRegister reg;
279 reg.code_ = code_ * 2;
280
281 DCHECK(reg.is_valid());
282 return reg;
283 }
284 SwVfpRegister high() const {
285 SwVfpRegister reg;
286 reg.code_ = (code_ * 2) + 1;
287
288 DCHECK(reg.is_valid());
289 return reg;
290 }
291
292 int code_;
293};
294
295
296// Quad word NEON register.
297struct QwNeonRegister {
298 static const int kMaxNumRegisters = 16;
299
300 static QwNeonRegister from_code(int code) {
301 QwNeonRegister r = { code };
302 return r;
303 }
304
305 bool is_valid() const {
306 return (0 <= code_) && (code_ < kMaxNumRegisters);
307 }
308 bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
309 int code() const {
310 DCHECK(is_valid());
311 return code_;
312 }
313 void split_code(int* vm, int* m) const {
314 DCHECK(is_valid());
315 int encoded_code = code_ << 1;
316 *m = (encoded_code & 0x10) >> 4;
317 *vm = encoded_code & 0x0F;
318 }
319
320 int code_;
321};
322
323
324typedef QwNeonRegister QuadRegister;
325
326
Steve Block6ded16b2010-05-10 14:33:55 +0100327// Support for the VFP registers s0 to s31 (d0 to d15).
Leon Clarkee46be812010-01-19 14:06:41 +0000328// Note that "s(N):s(N+1)" is the same as "d(N/2)".
Steve Block6ded16b2010-05-10 14:33:55 +0100329const SwVfpRegister s0 = { 0 };
330const SwVfpRegister s1 = { 1 };
331const SwVfpRegister s2 = { 2 };
332const SwVfpRegister s3 = { 3 };
333const SwVfpRegister s4 = { 4 };
334const SwVfpRegister s5 = { 5 };
335const SwVfpRegister s6 = { 6 };
336const SwVfpRegister s7 = { 7 };
337const SwVfpRegister s8 = { 8 };
338const SwVfpRegister s9 = { 9 };
339const SwVfpRegister s10 = { 10 };
340const SwVfpRegister s11 = { 11 };
341const SwVfpRegister s12 = { 12 };
342const SwVfpRegister s13 = { 13 };
343const SwVfpRegister s14 = { 14 };
344const SwVfpRegister s15 = { 15 };
345const SwVfpRegister s16 = { 16 };
346const SwVfpRegister s17 = { 17 };
347const SwVfpRegister s18 = { 18 };
348const SwVfpRegister s19 = { 19 };
349const SwVfpRegister s20 = { 20 };
350const SwVfpRegister s21 = { 21 };
351const SwVfpRegister s22 = { 22 };
352const SwVfpRegister s23 = { 23 };
353const SwVfpRegister s24 = { 24 };
354const SwVfpRegister s25 = { 25 };
355const SwVfpRegister s26 = { 26 };
356const SwVfpRegister s27 = { 27 };
357const SwVfpRegister s28 = { 28 };
358const SwVfpRegister s29 = { 29 };
359const SwVfpRegister s30 = { 30 };
360const SwVfpRegister s31 = { 31 };
Leon Clarkee46be812010-01-19 14:06:41 +0000361
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100362const DwVfpRegister no_dreg = { -1 };
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000363const LowDwVfpRegister d0 = { 0 };
364const LowDwVfpRegister d1 = { 1 };
365const LowDwVfpRegister d2 = { 2 };
366const LowDwVfpRegister d3 = { 3 };
367const LowDwVfpRegister d4 = { 4 };
368const LowDwVfpRegister d5 = { 5 };
369const LowDwVfpRegister d6 = { 6 };
370const LowDwVfpRegister d7 = { 7 };
371const LowDwVfpRegister d8 = { 8 };
372const LowDwVfpRegister d9 = { 9 };
373const LowDwVfpRegister d10 = { 10 };
374const LowDwVfpRegister d11 = { 11 };
375const LowDwVfpRegister d12 = { 12 };
376const LowDwVfpRegister d13 = { 13 };
377const LowDwVfpRegister d14 = { 14 };
378const LowDwVfpRegister d15 = { 15 };
379const DwVfpRegister d16 = { 16 };
380const DwVfpRegister d17 = { 17 };
381const DwVfpRegister d18 = { 18 };
382const DwVfpRegister d19 = { 19 };
383const DwVfpRegister d20 = { 20 };
384const DwVfpRegister d21 = { 21 };
385const DwVfpRegister d22 = { 22 };
386const DwVfpRegister d23 = { 23 };
387const DwVfpRegister d24 = { 24 };
388const DwVfpRegister d25 = { 25 };
389const DwVfpRegister d26 = { 26 };
390const DwVfpRegister d27 = { 27 };
391const DwVfpRegister d28 = { 28 };
392const DwVfpRegister d29 = { 29 };
393const DwVfpRegister d30 = { 30 };
394const DwVfpRegister d31 = { 31 };
395
396const QwNeonRegister q0 = { 0 };
397const QwNeonRegister q1 = { 1 };
398const QwNeonRegister q2 = { 2 };
399const QwNeonRegister q3 = { 3 };
400const QwNeonRegister q4 = { 4 };
401const QwNeonRegister q5 = { 5 };
402const QwNeonRegister q6 = { 6 };
403const QwNeonRegister q7 = { 7 };
404const QwNeonRegister q8 = { 8 };
405const QwNeonRegister q9 = { 9 };
406const QwNeonRegister q10 = { 10 };
407const QwNeonRegister q11 = { 11 };
408const QwNeonRegister q12 = { 12 };
409const QwNeonRegister q13 = { 13 };
410const QwNeonRegister q14 = { 14 };
411const QwNeonRegister q15 = { 15 };
412
Leon Clarkee46be812010-01-19 14:06:41 +0000413
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100414// Aliases for double registers. Defined using #define instead of
415// "static const DwVfpRegister&" because Clang complains otherwise when a
416// compilation unit that includes this header doesn't use the variables.
417#define kFirstCalleeSavedDoubleReg d8
418#define kLastCalleeSavedDoubleReg d15
419#define kDoubleRegZero d14
420#define kScratchDoubleReg d15
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +0100421
Steve Blocka7e24c12009-10-30 11:49:00 +0000422
423// Coprocessor register
424struct CRegister {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100425 bool is_valid() const { return 0 <= code_ && code_ < 16; }
426 bool is(CRegister creg) const { return code_ == creg.code_; }
427 int code() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000428 DCHECK(is_valid());
Steve Blocka7e24c12009-10-30 11:49:00 +0000429 return code_;
430 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100431 int bit() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432 DCHECK(is_valid());
Steve Blocka7e24c12009-10-30 11:49:00 +0000433 return 1 << code_;
434 }
435
Andrei Popescu31002712010-02-23 13:46:05 +0000436 // Unfortunately we can't make this private in a struct.
Steve Blocka7e24c12009-10-30 11:49:00 +0000437 int code_;
438};
439
440
Steve Block6ded16b2010-05-10 14:33:55 +0100441const CRegister no_creg = { -1 };
442
443const CRegister cr0 = { 0 };
444const CRegister cr1 = { 1 };
445const CRegister cr2 = { 2 };
446const CRegister cr3 = { 3 };
447const CRegister cr4 = { 4 };
448const CRegister cr5 = { 5 };
449const CRegister cr6 = { 6 };
450const CRegister cr7 = { 7 };
451const CRegister cr8 = { 8 };
452const CRegister cr9 = { 9 };
453const CRegister cr10 = { 10 };
454const CRegister cr11 = { 11 };
455const CRegister cr12 = { 12 };
456const CRegister cr13 = { 13 };
457const CRegister cr14 = { 14 };
458const CRegister cr15 = { 15 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000459
460
461// Coprocessor number
462enum Coprocessor {
463 p0 = 0,
464 p1 = 1,
465 p2 = 2,
466 p3 = 3,
467 p4 = 4,
468 p5 = 5,
469 p6 = 6,
470 p7 = 7,
471 p8 = 8,
472 p9 = 9,
473 p10 = 10,
474 p11 = 11,
475 p12 = 12,
476 p13 = 13,
477 p14 = 14,
478 p15 = 15
479};
480
481
Steve Blocka7e24c12009-10-30 11:49:00 +0000482// -----------------------------------------------------------------------------
483// Machine instruction Operands
484
485// Class Operand represents a shifter operand in data processing instructions
486class Operand BASE_EMBEDDED {
487 public:
488 // immediate
489 INLINE(explicit Operand(int32_t immediate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000490 RelocInfo::Mode rmode = RelocInfo::NONE32));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000491 INLINE(static Operand Zero()) {
492 return Operand(static_cast<int32_t>(0));
493 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000494 INLINE(explicit Operand(const ExternalReference& f));
Steve Blocka7e24c12009-10-30 11:49:00 +0000495 explicit Operand(Handle<Object> handle);
496 INLINE(explicit Operand(Smi* value));
497
498 // rm
499 INLINE(explicit Operand(Register rm));
500
501 // rm <shift_op> shift_imm
502 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 INLINE(static Operand SmiUntag(Register rm)) {
504 return Operand(rm, ASR, kSmiTagSize);
505 }
506 INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
507 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
508 return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
509 }
510 INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
511 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
512 return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
513 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000514
515 // rm <shift_op> rs
516 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
517
518 // Return true if this is a register operand.
519 INLINE(bool is_reg() const);
520
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000521 // Return the number of actual instructions required to implement the given
522 // instruction for this particular operand. This can be a single instruction,
523 // if no load into the ip register is necessary, or anything between 2 and 4
524 // instructions when we need to load from the constant pool (depending upon
525 // whether the constant pool entry is in the small or extended section). If
Steve Block44f0eee2011-05-26 01:26:41 +0100526 // the instruction this operand is used for is a MOV or MVN instruction the
527 // actual instruction to use is required for this calculation. For other
528 // instructions instr is ignored.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000529 //
530 // The value returned is only valid as long as no entries are added to the
531 // constant pool between this call and the actual instruction being emitted.
532 int instructions_required(const Assembler* assembler, Instr instr = 0) const;
533 bool must_output_reloc_info(const Assembler* assembler) const;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100534
535 inline int32_t immediate() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000536 DCHECK(!rm_.is_valid());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100537 return imm32_;
538 }
539
Steve Blocka7e24c12009-10-30 11:49:00 +0000540 Register rm() const { return rm_; }
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100541 Register rs() const { return rs_; }
542 ShiftOp shift_op() const { return shift_op_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000543
544 private:
545 Register rm_;
546 Register rs_;
547 ShiftOp shift_op_;
548 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
549 int32_t imm32_; // valid if rm_ == no_reg
550 RelocInfo::Mode rmode_;
551
552 friend class Assembler;
553};
554
555
556// Class MemOperand represents a memory operand in load and store instructions
557class MemOperand BASE_EMBEDDED {
558 public:
559 // [rn +/- offset] Offset/NegOffset
560 // [rn +/- offset]! PreIndex/NegPreIndex
561 // [rn], +/- offset PostIndex/NegPostIndex
562 // offset is any signed 32-bit value; offset is first loaded to register ip if
563 // it does not fit the addressing mode (12-bit unsigned and sign bit)
564 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
565
566 // [rn +/- rm] Offset/NegOffset
567 // [rn +/- rm]! PreIndex/NegPreIndex
568 // [rn], +/- rm PostIndex/NegPostIndex
569 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
570
571 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
572 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
573 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
574 explicit MemOperand(Register rn, Register rm,
575 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576 INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
577 Register key,
578 AddrMode am = Offset)) {
579 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
580 return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
581 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000582
Kristian Monsen25f61362010-05-21 11:50:48 +0100583 void set_offset(int32_t offset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000584 DCHECK(rm_.is(no_reg));
Kristian Monsen25f61362010-05-21 11:50:48 +0100585 offset_ = offset;
586 }
587
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100588 uint32_t offset() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000589 DCHECK(rm_.is(no_reg));
Kristian Monsen25f61362010-05-21 11:50:48 +0100590 return offset_;
591 }
592
Leon Clarkef7060e22010-06-03 12:02:55 +0100593 Register rn() const { return rn_; }
594 Register rm() const { return rm_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000595 AddrMode am() const { return am_; }
Kristian Monsen25f61362010-05-21 11:50:48 +0100596
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100597 bool OffsetIsUint12Encodable() const {
598 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
599 }
600
Steve Blocka7e24c12009-10-30 11:49:00 +0000601 private:
602 Register rn_; // base
603 Register rm_; // register offset
604 int32_t offset_; // valid if rm_ == no_reg
605 ShiftOp shift_op_;
606 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
607 AddrMode am_; // bits P, U, and W
608
609 friend class Assembler;
610};
611
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612
613// Class NeonMemOperand represents a memory operand in load and
614// store NEON instructions
615class NeonMemOperand BASE_EMBEDDED {
Steve Blockd0582a62009-12-15 09:54:21 +0000616 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 // [rn {:align}] Offset
618 // [rn {:align}]! PostIndex
619 explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
Steve Blockd0582a62009-12-15 09:54:21 +0000620
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000621 // [rn {:align}], rm PostIndex
622 explicit NeonMemOperand(Register rn, Register rm, int align = 0);
Steve Blockd0582a62009-12-15 09:54:21 +0000623
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 Register rn() const { return rn_; }
625 Register rm() const { return rm_; }
626 int align() const { return align_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100627
Steve Blockd0582a62009-12-15 09:54:21 +0000628 private:
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 void SetAlignment(int align);
Steve Block44f0eee2011-05-26 01:26:41 +0100630
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 Register rn_; // base
632 Register rm_; // register increment
633 int align_;
Steve Blockd0582a62009-12-15 09:54:21 +0000634};
635
Steve Blocka7e24c12009-10-30 11:49:00 +0000636
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000637// Class NeonListOperand represents a list of NEON registers
638class NeonListOperand BASE_EMBEDDED {
639 public:
640 explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
641 DoubleRegister base() const { return base_; }
642 NeonListType type() const { return type_; }
643 private:
644 DoubleRegister base_;
645 NeonListType type_;
646};
Steve Blocka7e24c12009-10-30 11:49:00 +0000647
Steve Block1e0659c2011-05-24 12:43:12 +0100648
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000649// Class used to build a constant pool.
650class ConstantPoolBuilder BASE_EMBEDDED {
651 public:
652 ConstantPoolBuilder();
653 ConstantPoolArray::LayoutSection AddEntry(Assembler* assm,
654 const RelocInfo& rinfo);
655 void Relocate(int pc_delta);
656 bool IsEmpty();
657 Handle<ConstantPoolArray> New(Isolate* isolate);
658 void Populate(Assembler* assm, ConstantPoolArray* constant_pool);
659
660 inline ConstantPoolArray::LayoutSection current_section() const {
661 return current_section_;
662 }
663
664 inline ConstantPoolArray::NumberOfEntries* number_of_entries(
665 ConstantPoolArray::LayoutSection section) {
666 return &number_of_entries_[section];
667 }
668
669 inline ConstantPoolArray::NumberOfEntries* small_entries() {
670 return number_of_entries(ConstantPoolArray::SMALL_SECTION);
671 }
672
673 inline ConstantPoolArray::NumberOfEntries* extended_entries() {
674 return number_of_entries(ConstantPoolArray::EXTENDED_SECTION);
675 }
676
677 private:
678 struct ConstantPoolEntry {
679 ConstantPoolEntry(RelocInfo rinfo, ConstantPoolArray::LayoutSection section,
680 int merged_index)
681 : rinfo_(rinfo), section_(section), merged_index_(merged_index) {}
682
683 RelocInfo rinfo_;
684 ConstantPoolArray::LayoutSection section_;
685 int merged_index_;
686 };
687
688 ConstantPoolArray::Type GetConstantPoolType(RelocInfo::Mode rmode);
689
690 std::vector<ConstantPoolEntry> entries_;
691 ConstantPoolArray::LayoutSection current_section_;
692 ConstantPoolArray::NumberOfEntries number_of_entries_[2];
693};
694
695struct VmovIndex {
696 unsigned char index;
697};
698const VmovIndex VmovIndexLo = { 0 };
699const VmovIndex VmovIndexHi = { 1 };
Steve Block1e0659c2011-05-24 12:43:12 +0100700
Steve Block44f0eee2011-05-26 01:26:41 +0100701class Assembler : public AssemblerBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000702 public:
703 // Create an assembler. Instructions and relocation information are emitted
704 // into a buffer, with the instructions starting from the beginning and the
705 // relocation information starting from the end of the buffer. See CodeDesc
706 // for a detailed comment on the layout (globals.h).
707 //
708 // If the provided buffer is NULL, the assembler allocates and grows its own
709 // buffer, and buffer_size determines the initial buffer size. The buffer is
710 // owned by the assembler and deallocated upon destruction of the assembler.
711 //
712 // If the provided buffer is not NULL, the assembler uses the provided buffer
713 // for code generation and assumes its size to be buffer_size. If the buffer
714 // is too small, a fatal error occurs. No deallocation of the buffer is done
715 // upon destruction of the assembler.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100716 Assembler(Isolate* isolate, void* buffer, int buffer_size);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717 virtual ~Assembler();
Steve Block44f0eee2011-05-26 01:26:41 +0100718
Steve Blocka7e24c12009-10-30 11:49:00 +0000719 // GetCode emits any pending (non-emitted) code and fills the descriptor
720 // desc. GetCode() is idempotent; it returns the same result if no other
721 // Assembler functions are invoked in between GetCode() calls.
722 void GetCode(CodeDesc* desc);
723
724 // Label operations & relative jumps (PPUM Appendix D)
725 //
726 // Takes a branch opcode (cc) and a label (L) and generates
727 // either a backward branch or a forward branch and links it
728 // to the label fixup chain. Usage:
729 //
730 // Label L; // unbound label
731 // j(cc, &L); // forward branch to unbound label
732 // bind(&L); // bind label to the current pc
733 // j(cc, &L); // backward branch to bound label
734 // bind(&L); // illegal: a label may be bound only once
735 //
736 // Note: The same Label can be used for forward and backward branches
737 // but it may be bound only once.
738
739 void bind(Label* L); // binds an unbound label L to the current code position
740
741 // Returns the branch offset to the given label from the current code position
742 // Links the label to the current position if it is still unbound
743 // Manages the jump elimination optimization if the second parameter is true.
744 int branch_offset(Label* L, bool jump_elimination_allowed);
745
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 // Returns true if the given pc address is the start of a constant pool load
747 // instruction sequence.
748 INLINE(static bool is_constant_pool_load(Address pc));
Steve Blocka7e24c12009-10-30 11:49:00 +0000749
750 // Return the address in the constant pool of the code target address used by
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000751 // the branch/call instruction at pc, or the object in a mov.
752 INLINE(static Address constant_pool_entry_address(
753 Address pc, ConstantPoolArray* constant_pool));
Steve Blocka7e24c12009-10-30 11:49:00 +0000754
755 // Read/Modify the code target address in the branch/call instruction at pc.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000756 INLINE(static Address target_address_at(Address pc,
757 ConstantPoolArray* constant_pool));
758 INLINE(static void set_target_address_at(Address pc,
759 ConstantPoolArray* constant_pool,
760 Address target,
761 ICacheFlushMode icache_flush_mode =
762 FLUSH_ICACHE_IF_NEEDED));
763 INLINE(static Address target_address_at(Address pc, Code* code)) {
764 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
765 return target_address_at(pc, constant_pool);
766 }
767 INLINE(static void set_target_address_at(Address pc,
768 Code* code,
769 Address target,
770 ICacheFlushMode icache_flush_mode =
771 FLUSH_ICACHE_IF_NEEDED)) {
772 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
773 set_target_address_at(pc, constant_pool, target, icache_flush_mode);
774 }
775
776 // Return the code target address at a call site from the return address
777 // of that call in the instruction stream.
778 INLINE(static Address target_address_from_return_address(Address pc));
779
780 // Given the address of the beginning of a call, return the address
781 // in the instruction stream that the call will return from.
782 INLINE(static Address return_address_from_call_start(Address pc));
783
784 // Return the code target address of the patch debug break slot
785 INLINE(static Address break_address_from_return_address(Address pc));
Steve Blocka7e24c12009-10-30 11:49:00 +0000786
Steve Blockd0582a62009-12-15 09:54:21 +0000787 // This sets the branch destination (which is in the constant pool on ARM).
788 // This is for calls and branches within generated code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100789 inline static void deserialization_set_special_target_at(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790 Address constant_pool_entry, Code* code, Address target);
Steve Blockd0582a62009-12-15 09:54:21 +0000791
792 // Here we are patching the address in the constant pool, not the actual call
793 // instruction. The address in the constant pool is the same size as a
794 // pointer.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100795 static const int kSpecialTargetSize = kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +0000796
Steve Blocka7e24c12009-10-30 11:49:00 +0000797 // Size of an instruction.
798 static const int kInstrSize = sizeof(Instr);
799
Steve Blocka7e24c12009-10-30 11:49:00 +0000800 // Distance between start of patched return sequence and the emitted address
801 // to jump to.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100802 // Patched return sequence is:
Steve Block6ded16b2010-05-10 14:33:55 +0100803 // ldr ip, [pc, #0] @ emited address and start
804 // blx ip
805 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000806
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100807 // Distance between start of patched debug break slot and the emitted address
808 // to jump to.
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100809 // Patched debug break slot code is:
810 // ldr ip, [pc, #0] @ emited address and start
811 // blx ip
812 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000813
814 static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100815
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 // Difference between address of current opcode and value read from pc
817 // register.
818 static const int kPcLoadDelta = 8;
819
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100820 static const int kJSReturnSequenceInstructions = 4;
821 static const int kDebugBreakSlotInstructions = 3;
822 static const int kDebugBreakSlotLength =
823 kDebugBreakSlotInstructions * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000824
825 // ---------------------------------------------------------------------------
826 // Code generation
827
828 // Insert the smallest number of nop instructions
829 // possible to align the pc offset to a multiple
830 // of m. m must be a power of 2 (>= 4).
831 void Align(int m);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100832 // Aligns code to something that's optimal for a jump target for the platform.
833 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000834
835 // Branch instructions
836 void b(int branch_offset, Condition cond = al);
837 void bl(int branch_offset, Condition cond = al);
838 void blx(int branch_offset); // v5 and above
839 void blx(Register target, Condition cond = al); // v5 and above
840 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
841
842 // Convenience branch instructions using labels
843 void b(Label* L, Condition cond = al) {
844 b(branch_offset(L, cond == al), cond);
845 }
846 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
847 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
848 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
849 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
850
851 // Data-processing instructions
Andrei Popescu31002712010-02-23 13:46:05 +0000852
Steve Blocka7e24c12009-10-30 11:49:00 +0000853 void and_(Register dst, Register src1, const Operand& src2,
854 SBit s = LeaveCC, Condition cond = al);
855
856 void eor(Register dst, Register src1, const Operand& src2,
857 SBit s = LeaveCC, Condition cond = al);
858
859 void sub(Register dst, Register src1, const Operand& src2,
860 SBit s = LeaveCC, Condition cond = al);
861 void sub(Register dst, Register src1, Register src2,
862 SBit s = LeaveCC, Condition cond = al) {
863 sub(dst, src1, Operand(src2), s, cond);
864 }
865
866 void rsb(Register dst, Register src1, const Operand& src2,
867 SBit s = LeaveCC, Condition cond = al);
868
869 void add(Register dst, Register src1, const Operand& src2,
870 SBit s = LeaveCC, Condition cond = al);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100871 void add(Register dst, Register src1, Register src2,
872 SBit s = LeaveCC, Condition cond = al) {
873 add(dst, src1, Operand(src2), s, cond);
874 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000875
876 void adc(Register dst, Register src1, const Operand& src2,
877 SBit s = LeaveCC, Condition cond = al);
878
879 void sbc(Register dst, Register src1, const Operand& src2,
880 SBit s = LeaveCC, Condition cond = al);
881
882 void rsc(Register dst, Register src1, const Operand& src2,
883 SBit s = LeaveCC, Condition cond = al);
884
885 void tst(Register src1, const Operand& src2, Condition cond = al);
886 void tst(Register src1, Register src2, Condition cond = al) {
887 tst(src1, Operand(src2), cond);
888 }
889
890 void teq(Register src1, const Operand& src2, Condition cond = al);
891
892 void cmp(Register src1, const Operand& src2, Condition cond = al);
893 void cmp(Register src1, Register src2, Condition cond = al) {
894 cmp(src1, Operand(src2), cond);
895 }
Steve Block1e0659c2011-05-24 12:43:12 +0100896 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000897
898 void cmn(Register src1, const Operand& src2, Condition cond = al);
899
900 void orr(Register dst, Register src1, const Operand& src2,
901 SBit s = LeaveCC, Condition cond = al);
902 void orr(Register dst, Register src1, Register src2,
903 SBit s = LeaveCC, Condition cond = al) {
904 orr(dst, src1, Operand(src2), s, cond);
905 }
906
907 void mov(Register dst, const Operand& src,
908 SBit s = LeaveCC, Condition cond = al);
909 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
910 mov(dst, Operand(src), s, cond);
911 }
912
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913 // Load the position of the label relative to the generated code object
914 // pointer in a register.
915 void mov_label_offset(Register dst, Label* label);
916
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100917 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918 // The constant for movw and movt should be in the range 0-0xffff.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100919 void movw(Register reg, uint32_t immediate, Condition cond = al);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100920 void movt(Register reg, uint32_t immediate, Condition cond = al);
921
Steve Blocka7e24c12009-10-30 11:49:00 +0000922 void bic(Register dst, Register src1, const Operand& src2,
923 SBit s = LeaveCC, Condition cond = al);
924
925 void mvn(Register dst, const Operand& src,
926 SBit s = LeaveCC, Condition cond = al);
927
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000928 // Shift instructions
929
930 void asr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
931 Condition cond = al) {
932 if (src2.is_reg()) {
933 mov(dst, Operand(src1, ASR, src2.rm()), s, cond);
934 } else {
935 mov(dst, Operand(src1, ASR, src2.immediate()), s, cond);
936 }
937 }
938
939 void lsl(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
940 Condition cond = al) {
941 if (src2.is_reg()) {
942 mov(dst, Operand(src1, LSL, src2.rm()), s, cond);
943 } else {
944 mov(dst, Operand(src1, LSL, src2.immediate()), s, cond);
945 }
946 }
947
948 void lsr(Register dst, Register src1, const Operand& src2, SBit s = LeaveCC,
949 Condition cond = al) {
950 if (src2.is_reg()) {
951 mov(dst, Operand(src1, LSR, src2.rm()), s, cond);
952 } else {
953 mov(dst, Operand(src1, LSR, src2.immediate()), s, cond);
954 }
955 }
956
Steve Blocka7e24c12009-10-30 11:49:00 +0000957 // Multiply instructions
958
959 void mla(Register dst, Register src1, Register src2, Register srcA,
960 SBit s = LeaveCC, Condition cond = al);
961
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962 void mls(Register dst, Register src1, Register src2, Register srcA,
963 Condition cond = al);
964
965 void sdiv(Register dst, Register src1, Register src2,
966 Condition cond = al);
967
968 void udiv(Register dst, Register src1, Register src2, Condition cond = al);
969
Steve Blocka7e24c12009-10-30 11:49:00 +0000970 void mul(Register dst, Register src1, Register src2,
971 SBit s = LeaveCC, Condition cond = al);
972
973 void smlal(Register dstL, Register dstH, Register src1, Register src2,
974 SBit s = LeaveCC, Condition cond = al);
975
976 void smull(Register dstL, Register dstH, Register src1, Register src2,
977 SBit s = LeaveCC, Condition cond = al);
978
979 void umlal(Register dstL, Register dstH, Register src1, Register src2,
980 SBit s = LeaveCC, Condition cond = al);
981
982 void umull(Register dstL, Register dstH, Register src1, Register src2,
983 SBit s = LeaveCC, Condition cond = al);
984
985 // Miscellaneous arithmetic instructions
986
987 void clz(Register dst, Register src, Condition cond = al); // v5 and above
988
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100989 // Saturating instructions. v6 and above.
990
991 // Unsigned saturate.
992 //
993 // Saturate an optionally shifted signed value to an unsigned range.
994 //
995 // usat dst, #satpos, src
996 // usat dst, #satpos, src, lsl #sh
997 // usat dst, #satpos, src, asr #sh
998 //
999 // Register dst will contain:
1000 //
1001 // 0, if s < 0
1002 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
1003 // s, otherwise
1004 //
1005 // where s is the contents of src after shifting (if used.)
1006 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
1007
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001008 // Bitfield manipulation instructions. v7 and above.
1009
1010 void ubfx(Register dst, Register src, int lsb, int width,
1011 Condition cond = al);
1012
1013 void sbfx(Register dst, Register src, int lsb, int width,
1014 Condition cond = al);
1015
1016 void bfc(Register dst, int lsb, int width, Condition cond = al);
1017
1018 void bfi(Register dst, Register src, int lsb, int width,
1019 Condition cond = al);
1020
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001021 void pkhbt(Register dst, Register src1, const Operand& src2,
1022 Condition cond = al);
1023
1024 void pkhtb(Register dst, Register src1, const Operand& src2,
1025 Condition cond = al);
1026
1027 void uxtb(Register dst, const Operand& src, Condition cond = al);
1028
1029 void uxtab(Register dst, Register src1, const Operand& src2,
1030 Condition cond = al);
1031
1032 void uxtb16(Register dst, const Operand& src, Condition cond = al);
1033
Steve Blocka7e24c12009-10-30 11:49:00 +00001034 // Status register access instructions
1035
1036 void mrs(Register dst, SRegister s, Condition cond = al);
1037 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
1038
1039 // Load/Store instructions
1040 void ldr(Register dst, const MemOperand& src, Condition cond = al);
1041 void str(Register src, const MemOperand& dst, Condition cond = al);
1042 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
1043 void strb(Register src, const MemOperand& dst, Condition cond = al);
1044 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
1045 void strh(Register src, const MemOperand& dst, Condition cond = al);
1046 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
1047 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
Leon Clarkef7060e22010-06-03 12:02:55 +01001048 void ldrd(Register dst1,
1049 Register dst2,
1050 const MemOperand& src, Condition cond = al);
1051 void strd(Register src1,
1052 Register src2,
1053 const MemOperand& dst, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +00001054
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001055 // Preload instructions
1056 void pld(const MemOperand& address);
1057
Steve Blocka7e24c12009-10-30 11:49:00 +00001058 // Load/Store multiple instructions
1059 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
1060 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
1061
Steve Blocka7e24c12009-10-30 11:49:00 +00001062 // Exception-generating instructions and debugging support
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001063 void stop(const char* msg,
1064 Condition cond = al,
1065 int32_t code = kDefaultStopCode);
Steve Blocka7e24c12009-10-30 11:49:00 +00001066
1067 void bkpt(uint32_t imm16); // v5 and above
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001068 void svc(uint32_t imm24, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +00001069
1070 // Coprocessor instructions
1071
1072 void cdp(Coprocessor coproc, int opcode_1,
1073 CRegister crd, CRegister crn, CRegister crm,
1074 int opcode_2, Condition cond = al);
1075
1076 void cdp2(Coprocessor coproc, int opcode_1,
1077 CRegister crd, CRegister crn, CRegister crm,
1078 int opcode_2); // v5 and above
1079
1080 void mcr(Coprocessor coproc, int opcode_1,
1081 Register rd, CRegister crn, CRegister crm,
1082 int opcode_2 = 0, Condition cond = al);
1083
1084 void mcr2(Coprocessor coproc, int opcode_1,
1085 Register rd, CRegister crn, CRegister crm,
1086 int opcode_2 = 0); // v5 and above
1087
1088 void mrc(Coprocessor coproc, int opcode_1,
1089 Register rd, CRegister crn, CRegister crm,
1090 int opcode_2 = 0, Condition cond = al);
1091
1092 void mrc2(Coprocessor coproc, int opcode_1,
1093 Register rd, CRegister crn, CRegister crm,
1094 int opcode_2 = 0); // v5 and above
1095
1096 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1097 LFlag l = Short, Condition cond = al);
1098 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1099 LFlag l = Short, Condition cond = al);
1100
1101 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1102 LFlag l = Short); // v5 and above
1103 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1104 LFlag l = Short); // v5 and above
1105
Steve Blockd0582a62009-12-15 09:54:21 +00001106 // Support for VFP.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001107 // All these APIs support S0 to S31 and D0 to D31.
Steve Blockd0582a62009-12-15 09:54:21 +00001108
Leon Clarked91b9f72010-01-27 17:25:45 +00001109 void vldr(const DwVfpRegister dst,
1110 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001111 int offset,
1112 const Condition cond = al);
1113 void vldr(const DwVfpRegister dst,
1114 const MemOperand& src,
Leon Clarked91b9f72010-01-27 17:25:45 +00001115 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001116
1117 void vldr(const SwVfpRegister dst,
1118 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001119 int offset,
1120 const Condition cond = al);
1121 void vldr(const SwVfpRegister dst,
1122 const MemOperand& src,
Steve Block6ded16b2010-05-10 14:33:55 +01001123 const Condition cond = al);
1124
Leon Clarked91b9f72010-01-27 17:25:45 +00001125 void vstr(const DwVfpRegister src,
1126 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001127 int offset,
1128 const Condition cond = al);
1129 void vstr(const DwVfpRegister src,
1130 const MemOperand& dst,
Leon Clarked91b9f72010-01-27 17:25:45 +00001131 const Condition cond = al);
Steve Block8defd9f2010-07-08 12:39:36 +01001132
Iain Merrick75681382010-08-19 15:07:18 +01001133 void vstr(const SwVfpRegister src,
1134 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001135 int offset,
1136 const Condition cond = al);
1137 void vstr(const SwVfpRegister src,
1138 const MemOperand& dst,
Iain Merrick75681382010-08-19 15:07:18 +01001139 const Condition cond = al);
1140
Ben Murdoch8b112d22011-06-08 16:22:53 +01001141 void vldm(BlockAddrMode am,
1142 Register base,
1143 DwVfpRegister first,
1144 DwVfpRegister last,
1145 Condition cond = al);
1146
1147 void vstm(BlockAddrMode am,
1148 Register base,
1149 DwVfpRegister first,
1150 DwVfpRegister last,
1151 Condition cond = al);
1152
1153 void vldm(BlockAddrMode am,
1154 Register base,
1155 SwVfpRegister first,
1156 SwVfpRegister last,
1157 Condition cond = al);
1158
1159 void vstm(BlockAddrMode am,
1160 Register base,
1161 SwVfpRegister first,
1162 SwVfpRegister last,
1163 Condition cond = al);
1164
Steve Block8defd9f2010-07-08 12:39:36 +01001165 void vmov(const DwVfpRegister dst,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001166 double imm,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001167 const Register scratch = no_reg);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001168 void vmov(const SwVfpRegister dst,
1169 const SwVfpRegister src,
1170 const Condition cond = al);
1171 void vmov(const DwVfpRegister dst,
Steve Block8defd9f2010-07-08 12:39:36 +01001172 const DwVfpRegister src,
1173 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001174 void vmov(const DwVfpRegister dst,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001175 const VmovIndex index,
1176 const Register src,
1177 const Condition cond = al);
1178 void vmov(const Register dst,
1179 const VmovIndex index,
1180 const DwVfpRegister src,
1181 const Condition cond = al);
1182 void vmov(const DwVfpRegister dst,
Leon Clarkee46be812010-01-19 14:06:41 +00001183 const Register src1,
Steve Blockd0582a62009-12-15 09:54:21 +00001184 const Register src2,
Leon Clarkee46be812010-01-19 14:06:41 +00001185 const Condition cond = al);
1186 void vmov(const Register dst1,
1187 const Register dst2,
1188 const DwVfpRegister src,
1189 const Condition cond = al);
1190 void vmov(const SwVfpRegister dst,
1191 const Register src,
1192 const Condition cond = al);
1193 void vmov(const Register dst,
1194 const SwVfpRegister src,
1195 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001196 void vcvt_f64_s32(const DwVfpRegister dst,
1197 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001198 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001199 const Condition cond = al);
1200 void vcvt_f32_s32(const SwVfpRegister dst,
1201 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001202 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001203 const Condition cond = al);
1204 void vcvt_f64_u32(const DwVfpRegister dst,
1205 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001206 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001207 const Condition cond = al);
1208 void vcvt_s32_f64(const SwVfpRegister dst,
1209 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001210 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001211 const Condition cond = al);
1212 void vcvt_u32_f64(const SwVfpRegister dst,
1213 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001214 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001215 const Condition cond = al);
1216 void vcvt_f64_f32(const DwVfpRegister dst,
1217 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001218 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001219 const Condition cond = al);
1220 void vcvt_f32_f64(const SwVfpRegister dst,
1221 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001222 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001223 const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001224 void vcvt_f64_s32(const DwVfpRegister dst,
1225 int fraction_bits,
1226 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001227
Steve Block44f0eee2011-05-26 01:26:41 +01001228 void vneg(const DwVfpRegister dst,
1229 const DwVfpRegister src,
1230 const Condition cond = al);
Steve Block1e0659c2011-05-24 12:43:12 +01001231 void vabs(const DwVfpRegister dst,
1232 const DwVfpRegister src,
1233 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001234 void vadd(const DwVfpRegister dst,
1235 const DwVfpRegister src1,
1236 const DwVfpRegister src2,
1237 const Condition cond = al);
1238 void vsub(const DwVfpRegister dst,
1239 const DwVfpRegister src1,
1240 const DwVfpRegister src2,
1241 const Condition cond = al);
1242 void vmul(const DwVfpRegister dst,
1243 const DwVfpRegister src1,
1244 const DwVfpRegister src2,
1245 const Condition cond = al);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246 void vmla(const DwVfpRegister dst,
1247 const DwVfpRegister src1,
1248 const DwVfpRegister src2,
1249 const Condition cond = al);
1250 void vmls(const DwVfpRegister dst,
1251 const DwVfpRegister src1,
1252 const DwVfpRegister src2,
1253 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001254 void vdiv(const DwVfpRegister dst,
1255 const DwVfpRegister src1,
1256 const DwVfpRegister src2,
1257 const Condition cond = al);
1258 void vcmp(const DwVfpRegister src1,
1259 const DwVfpRegister src2,
Steve Blockd0582a62009-12-15 09:54:21 +00001260 const Condition cond = al);
Iain Merrick75681382010-08-19 15:07:18 +01001261 void vcmp(const DwVfpRegister src1,
1262 const double src2,
Iain Merrick75681382010-08-19 15:07:18 +01001263 const Condition cond = al);
Steve Blockd0582a62009-12-15 09:54:21 +00001264 void vmrs(const Register dst,
1265 const Condition cond = al);
Russell Brenner90bac252010-11-18 13:33:46 -08001266 void vmsr(const Register dst,
1267 const Condition cond = al);
Steve Block8defd9f2010-07-08 12:39:36 +01001268 void vsqrt(const DwVfpRegister dst,
1269 const DwVfpRegister src,
1270 const Condition cond = al);
Steve Blockd0582a62009-12-15 09:54:21 +00001271
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001272 // Support for NEON.
1273 // All these APIs support D0 to D31 and Q0 to Q15.
1274
1275 void vld1(NeonSize size,
1276 const NeonListOperand& dst,
1277 const NeonMemOperand& src);
1278 void vst1(NeonSize size,
1279 const NeonListOperand& src,
1280 const NeonMemOperand& dst);
1281 void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1282
Steve Blocka7e24c12009-10-30 11:49:00 +00001283 // Pseudo instructions
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001284
1285 // Different nop operations are used by the code generator to detect certain
1286 // states of the generated code.
1287 enum NopMarkerTypes {
1288 NON_MARKING_NOP = 0,
1289 DEBUG_BREAK_NOP,
1290 // IC markers.
1291 PROPERTY_ACCESS_INLINED,
1292 PROPERTY_ACCESS_INLINED_CONTEXT,
1293 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1294 // Helper values.
1295 LAST_CODE_MARKER,
1296 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1297 };
1298
1299 void nop(int type = 0); // 0 is the default non-marking type.
Steve Blocka7e24c12009-10-30 11:49:00 +00001300
1301 void push(Register src, Condition cond = al) {
1302 str(src, MemOperand(sp, 4, NegPreIndex), cond);
1303 }
1304
1305 void pop(Register dst, Condition cond = al) {
1306 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1307 }
1308
1309 void pop() {
1310 add(sp, sp, Operand(kPointerSize));
1311 }
1312
Steve Blocka7e24c12009-10-30 11:49:00 +00001313 // Jump unconditionally to given label.
1314 void jmp(Label* L) { b(L, al); }
1315
1316 // Check the code size generated from label to here.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001317 int SizeOfCodeGeneratedSince(Label* label) {
1318 return pc_offset() - label->pos();
1319 }
1320
1321 // Check the number of instructions generated from label to here.
1322 int InstructionsGeneratedSince(Label* label) {
1323 return SizeOfCodeGeneratedSince(label) / kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001324 }
1325
Steve Blockd0582a62009-12-15 09:54:21 +00001326 // Check whether an immediate fits an addressing mode 1 instruction.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001327 static bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1328
1329 // Check whether an immediate fits an addressing mode 2 instruction.
1330 bool ImmediateFitsAddrMode2Instruction(int32_t imm32);
Steve Blockd0582a62009-12-15 09:54:21 +00001331
Steve Block6ded16b2010-05-10 14:33:55 +01001332 // Class for scoping postponing the constant pool generation.
1333 class BlockConstPoolScope {
1334 public:
1335 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1336 assem_->StartBlockConstPool();
1337 }
1338 ~BlockConstPoolScope() {
1339 assem_->EndBlockConstPool();
1340 }
1341
1342 private:
1343 Assembler* assem_;
1344
1345 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1346 };
1347
Steve Blocka7e24c12009-10-30 11:49:00 +00001348 // Debugging
1349
1350 // Mark address of the ExitJSFrame code.
1351 void RecordJSReturn();
1352
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001353 // Mark address of a debug break slot.
1354 void RecordDebugBreakSlot();
1355
Ben Murdoch257744e2011-11-30 15:57:28 +00001356 // Record the AST id of the CallIC being compiled, so that it can be placed
1357 // in the relocation information.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001358 void SetRecordedAstId(TypeFeedbackId ast_id) {
1359 DCHECK(recorded_ast_id_.IsNone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001360 recorded_ast_id_ = ast_id;
1361 }
1362
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001363 TypeFeedbackId RecordedAstId() {
1364 DCHECK(!recorded_ast_id_.IsNone());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001365 return recorded_ast_id_;
1366 }
1367
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
Ben Murdoch257744e2011-11-30 15:57:28 +00001369
Steve Blocka7e24c12009-10-30 11:49:00 +00001370 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001371 // Use --code-comments to enable.
Steve Blocka7e24c12009-10-30 11:49:00 +00001372 void RecordComment(const char* msg);
1373
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001374 // Record the emission of a constant pool.
1375 //
1376 // The emission of constant pool depends on the size of the code generated and
1377 // the number of RelocInfo recorded.
1378 // The Debug mechanism needs to map code offsets between two versions of a
1379 // function, compiled with and without debugger support (see for example
1380 // Debug::PrepareForBreakPoints()).
1381 // Compiling functions with debugger support generates additional code
1382 // (DebugCodegen::GenerateSlot()). This may affect the emission of the
1383 // constant pools and cause the version of the code with debugger support to
1384 // have constant pools generated in different places.
1385 // Recording the position and size of emitted constant pools allows to
1386 // correctly compute the offset mappings between the different versions of a
1387 // function in all situations.
1388 //
1389 // The parameter indicates the size of the constant pool (in bytes), including
1390 // the marker and branch over the data.
1391 void RecordConstPool(int size);
1392
Ben Murdochb8e0da22011-05-16 14:20:40 +01001393 // Writes a single byte or word of data in the code stream. Used
1394 // for inline tables, e.g., jump-tables. The constant pool should be
1395 // emitted before any use of db and dd to ensure that constant pools
1396 // are not emitted as part of the tables generated.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001397 void db(uint8_t data);
1398 void dd(uint32_t data);
1399
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001400 // Emits the address of the code stub's first instruction.
1401 void emit_code_stub_address(Code* stub);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001402
1403 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
Steve Block6ded16b2010-05-10 14:33:55 +01001404
1405 // Read/patch instructions
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001406 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1407 void instr_at_put(int pos, Instr instr) {
1408 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1409 }
Steve Block6ded16b2010-05-10 14:33:55 +01001410 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1411 static void instr_at_put(byte* pc, Instr instr) {
1412 *reinterpret_cast<Instr*>(pc) = instr;
1413 }
Steve Block1e0659c2011-05-24 12:43:12 +01001414 static Condition GetCondition(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001415 static bool IsBranch(Instr instr);
1416 static int GetBranchOffset(Instr instr);
1417 static bool IsLdrRegisterImmediate(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001418 static bool IsVldrDRegisterImmediate(Instr instr);
1419 static Instr GetConsantPoolLoadPattern();
1420 static Instr GetConsantPoolLoadMask();
1421 static bool IsLdrPpRegOffset(Instr instr);
1422 static Instr GetLdrPpRegOffsetPattern();
1423 static bool IsLdrPpImmediateOffset(Instr instr);
1424 static bool IsVldrDPpImmediateOffset(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001425 static int GetLdrRegisterImmediateOffset(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001426 static int GetVldrDRegisterImmediateOffset(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001427 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001428 static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
Kristian Monsen50ef84f2010-07-29 15:18:00 +01001429 static bool IsStrRegisterImmediate(Instr instr);
1430 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1431 static bool IsAddRegisterImmediate(Instr instr);
1432 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
Leon Clarkef7060e22010-06-03 12:02:55 +01001433 static Register GetRd(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001434 static Register GetRn(Instr instr);
1435 static Register GetRm(Instr instr);
Leon Clarkef7060e22010-06-03 12:02:55 +01001436 static bool IsPush(Instr instr);
1437 static bool IsPop(Instr instr);
1438 static bool IsStrRegFpOffset(Instr instr);
1439 static bool IsLdrRegFpOffset(Instr instr);
1440 static bool IsStrRegFpNegOffset(Instr instr);
1441 static bool IsLdrRegFpNegOffset(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001442 static bool IsLdrPcImmediateOffset(Instr instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001443 static bool IsVldrDPcImmediateOffset(Instr instr);
1444 static bool IsBlxReg(Instr instr);
1445 static bool IsBlxIp(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001446 static bool IsTstImmediate(Instr instr);
1447 static bool IsCmpRegister(Instr instr);
1448 static bool IsCmpImmediate(Instr instr);
1449 static Register GetCmpImmediateRegister(Instr instr);
1450 static int GetCmpImmediateRawImmediate(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001451 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001452 static bool IsMovImmed(Instr instr);
1453 static bool IsOrrImmed(Instr instr);
1454 static bool IsMovT(Instr instr);
1455 static Instr GetMovTPattern();
1456 static bool IsMovW(Instr instr);
1457 static Instr GetMovWPattern();
1458 static Instr EncodeMovwImmediate(uint32_t immediate);
1459 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate);
1460 static int DecodeShiftImm(Instr instr);
1461 static Instr PatchShiftImm(Instr instr, int immed);
Steve Block6ded16b2010-05-10 14:33:55 +01001462
Ben Murdoch257744e2011-11-30 15:57:28 +00001463 // Constants in pools are accessed via pc relative addressing, which can
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001464 // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1465 // PC-relative loads, thereby defining a maximum distance between the
1466 // instruction and the accessed constant.
1467 static const int kMaxDistToIntPool = 4*KB;
1468 static const int kMaxDistToFPPool = 1*KB;
1469 // All relocations could be integer, it therefore acts as the limit.
1470 static const int kMaxNumPending32RelocInfo = kMaxDistToIntPool/kInstrSize;
1471 static const int kMaxNumPending64RelocInfo = kMaxDistToFPPool/kInstrSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00001472
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001473 // Postpone the generation of the constant pool for the specified number of
1474 // instructions.
1475 void BlockConstPoolFor(int instructions);
1476
1477 // Check if is time to emit a constant pool.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001478 void CheckConstPool(bool force_emit, bool require_jump);
Steve Blocka7e24c12009-10-30 11:49:00 +00001479
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001480 // Allocate a constant pool of the correct size for the generated code.
1481 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
1482
1483 // Generate the constant pool for the generated code.
1484 void PopulateConstantPool(ConstantPoolArray* constant_pool);
1485
1486 bool is_constant_pool_available() const { return constant_pool_available_; }
1487
1488 bool use_extended_constant_pool() const {
1489 return constant_pool_builder_.current_section() ==
1490 ConstantPoolArray::EXTENDED_SECTION;
1491 }
1492
1493
Steve Blocka7e24c12009-10-30 11:49:00 +00001494 protected:
Ben Murdoch257744e2011-11-30 15:57:28 +00001495 // Relocation for a type-recording IC has the AST id added to it. This
1496 // member variable is a way to pass the information from the call site to
1497 // the relocation info.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001498 TypeFeedbackId recorded_ast_id_;
Steve Block44f0eee2011-05-26 01:26:41 +01001499
Steve Blocka7e24c12009-10-30 11:49:00 +00001500 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1501
Steve Blocka7e24c12009-10-30 11:49:00 +00001502 // Decode branch instruction at pos and return branch target pos
1503 int target_at(int pos);
1504
1505 // Patch branch instruction at pos to branch to given branch target pos
1506 void target_at_put(int pos, int target_pos);
1507
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001508 // Prevent contant pool emission until EndBlockConstPool is called.
1509 // Call to this function can be nested but must be followed by an equal
1510 // number of call to EndBlockConstpool.
1511 void StartBlockConstPool() {
1512 if (const_pool_blocked_nesting_++ == 0) {
1513 // Prevent constant pool checks happening by setting the next check to
1514 // the biggest possible offset.
1515 next_buffer_check_ = kMaxInt;
1516 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001517 }
1518
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001519 // Resume constant pool emission. Need to be called as many time as
1520 // StartBlockConstPool to have an effect.
Steve Block6ded16b2010-05-10 14:33:55 +01001521 void EndBlockConstPool() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001522 if (--const_pool_blocked_nesting_ == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001523#ifdef DEBUG
1524 // Max pool start (if we need a jump and an alignment).
1525 int start = pc_offset() + kInstrSize + 2 * kPointerSize;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001526 // Check the constant pool hasn't been blocked for too long.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001527 DCHECK((num_pending_32_bit_reloc_info_ == 0) ||
1528 (start + num_pending_64_bit_reloc_info_ * kDoubleSize <
1529 (first_const_pool_32_use_ + kMaxDistToIntPool)));
1530 DCHECK((num_pending_64_bit_reloc_info_ == 0) ||
1531 (start < (first_const_pool_64_use_ + kMaxDistToFPPool)));
1532#endif
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001533 // Two cases:
1534 // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1535 // still blocked
1536 // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1537 // trigger a check.
1538 next_buffer_check_ = no_const_pool_before_;
1539 }
Steve Block6ded16b2010-05-10 14:33:55 +01001540 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001541
1542 bool is_const_pool_blocked() const {
1543 return (const_pool_blocked_nesting_ > 0) ||
1544 (pc_offset() < no_const_pool_before_);
1545 }
Steve Block6ded16b2010-05-10 14:33:55 +01001546
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001547 void set_constant_pool_available(bool available) {
1548 constant_pool_available_ = available;
1549 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001550
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001551 private:
Steve Blocka7e24c12009-10-30 11:49:00 +00001552 int next_buffer_check_; // pc offset of next buffer check
1553
1554 // Code generation
1555 // The relocation writer's position is at least kGap bytes below the end of
1556 // the generated instructions. This is so that multi-instruction sequences do
1557 // not have to check for overflow. The same is true for writes of large
1558 // relocation info entries.
1559 static const int kGap = 32;
Steve Blocka7e24c12009-10-30 11:49:00 +00001560
1561 // Constant pool generation
1562 // Pools are emitted in the instruction stream, preferably after unconditional
1563 // jumps or after returns from functions (in dead code locations).
1564 // If a long code sequence does not contain unconditional jumps, it is
1565 // necessary to emit the constant pool before the pool gets too far from the
1566 // location it is accessed from. In this case, we emit a jump over the emitted
1567 // constant pool.
1568 // Constants in the pool may be addresses of functions that gets relocated;
1569 // if so, a relocation info entry is associated to the constant pool entry.
1570
1571 // Repeated checking whether the constant pool should be emitted is rather
1572 // expensive. By default we only check again once a number of instructions
1573 // has been generated. That also means that the sizing of the buffers is not
1574 // an exact science, and that we rely on some slop to not overrun buffers.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001575 static const int kCheckPoolIntervalInst = 32;
1576 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001577
1578
Steve Block6ded16b2010-05-10 14:33:55 +01001579 // Emission of the constant pool may be blocked in some code sequences.
1580 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1581 int no_const_pool_before_; // Block emission before this pc offset.
Steve Blocka7e24c12009-10-30 11:49:00 +00001582
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001583 // Keep track of the first instruction requiring a constant pool entry
1584 // since the previous constant pool was emitted.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001585 int first_const_pool_32_use_;
1586 int first_const_pool_64_use_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001587
1588 // Relocation info generation
1589 // Each relocation is encoded as a variable size value
1590 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1591 RelocInfoWriter reloc_info_writer;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001592
Steve Blocka7e24c12009-10-30 11:49:00 +00001593 // Relocation info records are also used during code generation as temporary
1594 // containers for constants and code target addresses until they are emitted
1595 // to the constant pool. These pending relocation info records are temporarily
1596 // stored in a separate buffer until a constant pool is emitted.
1597 // If every instruction in a long sequence is accessing the pool, we need one
1598 // pending relocation entry per instruction.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001599
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001600 // The buffers of pending relocation info.
1601 RelocInfo pending_32_bit_reloc_info_[kMaxNumPending32RelocInfo];
1602 RelocInfo pending_64_bit_reloc_info_[kMaxNumPending64RelocInfo];
1603 // Number of pending reloc info entries in the 32 bits buffer.
1604 int num_pending_32_bit_reloc_info_;
1605 // Number of pending reloc info entries in the 64 bits buffer.
1606 int num_pending_64_bit_reloc_info_;
1607
1608 ConstantPoolBuilder constant_pool_builder_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001609
1610 // The bound position, before this we cannot do instruction elimination.
1611 int last_bound_pos_;
1612
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613 // Indicates whether the constant pool can be accessed, which is only possible
1614 // if the pp register points to the current code object's constant pool.
1615 bool constant_pool_available_;
1616
Steve Blocka7e24c12009-10-30 11:49:00 +00001617 // Code emission
1618 inline void CheckBuffer();
1619 void GrowBuffer();
1620 inline void emit(Instr x);
1621
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001622 // 32-bit immediate values
1623 void move_32_bit_immediate(Register rd,
1624 const Operand& x,
1625 Condition cond = al);
1626
Steve Blocka7e24c12009-10-30 11:49:00 +00001627 // Instruction generation
1628 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1629 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1630 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1631 void addrmod4(Instr instr, Register rn, RegList rl);
1632 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1633
1634 // Labels
1635 void print(Label* L);
1636 void bind_to(Label* L, int pos);
Steve Blocka7e24c12009-10-30 11:49:00 +00001637 void next(Label* L);
1638
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001639 enum UseConstantPoolMode {
1640 USE_CONSTANT_POOL,
1641 DONT_USE_CONSTANT_POOL
1642 };
1643
Steve Blocka7e24c12009-10-30 11:49:00 +00001644 // Record reloc info for current pc_
1645 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001646 void RecordRelocInfo(const RelocInfo& rinfo);
1647 ConstantPoolArray::LayoutSection ConstantPoolAddEntry(const RelocInfo& rinfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001648
Steve Blocka7e24c12009-10-30 11:49:00 +00001649 friend class RelocInfo;
1650 friend class CodePatcher;
Steve Block6ded16b2010-05-10 14:33:55 +01001651 friend class BlockConstPoolScope;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001652 friend class FrameAndConstantPoolScope;
1653 friend class ConstantPoolUnavailableScope;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001654
1655 PositionsRecorder positions_recorder_;
1656 friend class PositionsRecorder;
1657 friend class EnsureSpace;
Steve Blocka7e24c12009-10-30 11:49:00 +00001658};
1659
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001660
1661class EnsureSpace BASE_EMBEDDED {
1662 public:
1663 explicit EnsureSpace(Assembler* assembler) {
1664 assembler->CheckBuffer();
1665 }
1666};
1667
1668
Steve Blocka7e24c12009-10-30 11:49:00 +00001669} } // namespace v8::internal
1670
1671#endif // V8_ARM_ASSEMBLER_ARM_H_