The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / arm / assembler-arm.h @ f230a1cf

History | View | Annotate | Download (54.7 KB)

1
// 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

    
33
// The original source code covered by the above license above has been
34
// modified significantly by Google Inc.
35
// Copyright 2012 the V8 project authors. All rights reserved.
36

    
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_
42
#include <stdio.h>
43
#include "assembler.h"
44
#include "constants-arm.h"
45
#include "serialize.h"
46

    
47
namespace v8 {
48
namespace internal {
49

    
50
// CpuFeatures keeps track of which features are supported by the target CPU.
51
// Supported features must be enabled by a CpuFeatureScope before use.
52
class CpuFeatures : public AllStatic {
53
 public:
54
  // Detect features of the target CPU. Set safe defaults if the serializer
55
  // is enabled (snapshots must be portable).
56
  static void Probe();
57

    
58
  // Display target use when compiling.
59
  static void PrintTarget();
60

    
61
  // Display features.
62
  static void PrintFeatures();
63

    
64
  // Check whether a feature is supported by the target CPU.
65
  static bool IsSupported(CpuFeature f) {
66
    ASSERT(initialized_);
67
    return Check(f, supported_);
68
  }
69

    
70
  static bool IsFoundByRuntimeProbingOnly(CpuFeature f) {
71
    ASSERT(initialized_);
72
    return Check(f, found_by_runtime_probing_only_);
73
  }
74

    
75
  static bool IsSafeForSnapshot(CpuFeature f) {
76
    return Check(f, cross_compile_) ||
77
           (IsSupported(f) &&
78
            (!Serializer::enabled() || !IsFoundByRuntimeProbingOnly(f)));
79
  }
80

    
81
  static unsigned cache_line_size() { return cache_line_size_; }
82

    
83
  static bool VerifyCrossCompiling() {
84
    return cross_compile_ == 0;
85
  }
86

    
87
  static bool VerifyCrossCompiling(CpuFeature f) {
88
    unsigned mask = flag2set(f);
89
    return cross_compile_ == 0 ||
90
           (cross_compile_ & mask) == mask;
91
  }
92

    
93
 private:
94
  static bool Check(CpuFeature f, unsigned set) {
95
    return (set & flag2set(f)) != 0;
96
  }
97

    
98
  static unsigned flag2set(CpuFeature f) {
99
    return 1u << f;
100
  }
101

    
102
#ifdef DEBUG
103
  static bool initialized_;
104
#endif
105
  static unsigned supported_;
106
  static unsigned found_by_runtime_probing_only_;
107
  static unsigned cache_line_size_;
108

    
109
  static unsigned cross_compile_;
110

    
111
  friend class ExternalReference;
112
  friend class PlatformFeatureScope;
113
  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
114
};
115

    
116

    
117
// CPU Registers.
118
//
119
// 1) We would prefer to use an enum, but enum values are assignment-
120
// compatible with int, which has caused code-generation bugs.
121
//
122
// 2) We would prefer to use a class instead of a struct but we don't like
123
// the register initialization to depend on the particular initialization
124
// order (which appears to be different on OS X, Linux, and Windows for the
125
// installed versions of C++ we tried). Using a struct permits C-style
126
// "initialization". Also, the Register objects cannot be const as this
127
// forces initialization stubs in MSVC, making us dependent on initialization
128
// order.
129
//
130
// 3) By not using an enum, we are possibly preventing the compiler from
131
// doing certain constant folds, which may significantly reduce the
132
// code generated for some assembly instructions (because they boil down
133
// to a few constants). If this is a problem, we could change the code
134
// such that we use an enum in optimized mode, and the struct in debug
135
// mode. This way we get the compile-time error checking in debug mode
136
// and best performance in optimized code.
137

    
138
// These constants are used in several locations, including static initializers
139
const int kRegister_no_reg_Code = -1;
140
const int kRegister_r0_Code = 0;
141
const int kRegister_r1_Code = 1;
142
const int kRegister_r2_Code = 2;
143
const int kRegister_r3_Code = 3;
144
const int kRegister_r4_Code = 4;
145
const int kRegister_r5_Code = 5;
146
const int kRegister_r6_Code = 6;
147
const int kRegister_r7_Code = 7;
148
const int kRegister_r8_Code = 8;
149
const int kRegister_r9_Code = 9;
150
const int kRegister_r10_Code = 10;
151
const int kRegister_fp_Code = 11;
152
const int kRegister_ip_Code = 12;
153
const int kRegister_sp_Code = 13;
154
const int kRegister_lr_Code = 14;
155
const int kRegister_pc_Code = 15;
156

    
157
// Core register
158
struct Register {
159
  static const int kNumRegisters = 16;
160
  static const int kMaxNumAllocatableRegisters =
161
      FLAG_enable_ool_constant_pool ? 8 : 9;
162
  static const int kSizeInBytes = 4;
163

    
164
  inline static int NumAllocatableRegisters();
165

    
166
  static int ToAllocationIndex(Register reg) {
167
    if (FLAG_enable_ool_constant_pool && (reg.code() >= kRegister_r8_Code)) {
168
      return reg.code() - 1;
169
    }
170
    ASSERT(reg.code() < kMaxNumAllocatableRegisters);
171
    return reg.code();
172
  }
173

    
174
  static Register FromAllocationIndex(int index) {
175
    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
176
    if (FLAG_enable_ool_constant_pool && (index >= 7)) {
177
      return from_code(index + 1);
178
    }
179
    return from_code(index);
180
  }
181

    
182
  static const char* AllocationIndexToString(int index) {
183
    ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters);
184
    const char* const names[] = {
185
      "r0",
186
      "r1",
187
      "r2",
188
      "r3",
189
      "r4",
190
      "r5",
191
      "r6",
192
      "r7",
193
      "r8",
194
    };
195
    if (FLAG_enable_ool_constant_pool && (index >= 7)) {
196
      return names[index + 1];
197
    }
198
    return names[index];
199
  }
200

    
201
  static Register from_code(int code) {
202
    Register r = { code };
203
    return r;
204
  }
205

    
206
  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
207
  bool is(Register reg) const { return code_ == reg.code_; }
208
  int code() const {
209
    ASSERT(is_valid());
210
    return code_;
211
  }
212
  int bit() const {
213
    ASSERT(is_valid());
214
    return 1 << code_;
215
  }
216

    
217
  void set_code(int code) {
218
    code_ = code;
219
    ASSERT(is_valid());
220
  }
221

    
222
  // Unfortunately we can't make this private in a struct.
223
  int code_;
224
};
225

    
226
const Register no_reg = { kRegister_no_reg_Code };
227

    
228
const Register r0  = { kRegister_r0_Code };
229
const Register r1  = { kRegister_r1_Code };
230
const Register r2  = { kRegister_r2_Code };
231
const Register r3  = { kRegister_r3_Code };
232
const Register r4  = { kRegister_r4_Code };
233
const Register r5  = { kRegister_r5_Code };
234
const Register r6  = { kRegister_r6_Code };
235
// Used as constant pool pointer register if FLAG_enable_ool_constant_pool.
236
const Register r7  = { kRegister_r7_Code };
237
// Used as context register.
238
const Register r8  = { kRegister_r8_Code };
239
// Used as lithium codegen scratch register.
240
const Register r9  = { kRegister_r9_Code };
241
// Used as roots register.
242
const Register r10 = { kRegister_r10_Code };
243
const Register fp  = { kRegister_fp_Code };
244
const Register ip  = { kRegister_ip_Code };
245
const Register sp  = { kRegister_sp_Code };
246
const Register lr  = { kRegister_lr_Code };
247
const Register pc  = { kRegister_pc_Code };
248

    
249
// Single word VFP register.
250
struct SwVfpRegister {
251
  static const int kSizeInBytes = 4;
252
  bool is_valid() const { return 0 <= code_ && code_ < 32; }
253
  bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
254
  int code() const {
255
    ASSERT(is_valid());
256
    return code_;
257
  }
258
  int bit() const {
259
    ASSERT(is_valid());
260
    return 1 << code_;
261
  }
262
  void split_code(int* vm, int* m) const {
263
    ASSERT(is_valid());
264
    *m = code_ & 0x1;
265
    *vm = code_ >> 1;
266
  }
267

    
268
  int code_;
269
};
270

    
271

    
272
// Double word VFP register.
273
struct DwVfpRegister {
274
  static const int kMaxNumRegisters = 32;
275
  // A few double registers are reserved: one as a scratch register and one to
276
  // hold 0.0, that does not fit in the immediate field of vmov instructions.
277
  //  d14: 0.0
278
  //  d15: scratch register.
279
  static const int kNumReservedRegisters = 2;
280
  static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
281
      kNumReservedRegisters;
282
  static const int kSizeInBytes = 8;
283

    
284
  // Note: the number of registers can be different at snapshot and run-time.
285
  // Any code included in the snapshot must be able to run both with 16 or 32
286
  // registers.
287
  inline static int NumRegisters();
288
  inline static int NumAllocatableRegisters();
289

    
290
  inline static int ToAllocationIndex(DwVfpRegister reg);
291
  static const char* AllocationIndexToString(int index);
292
  inline static DwVfpRegister FromAllocationIndex(int index);
293

    
294
  static DwVfpRegister from_code(int code) {
295
    DwVfpRegister r = { code };
296
    return r;
297
  }
298

    
299
  bool is_valid() const {
300
    return 0 <= code_ && code_ < kMaxNumRegisters;
301
  }
302
  bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
303
  int code() const {
304
    ASSERT(is_valid());
305
    return code_;
306
  }
307
  int bit() const {
308
    ASSERT(is_valid());
309
    return 1 << code_;
310
  }
311
  void split_code(int* vm, int* m) const {
312
    ASSERT(is_valid());
313
    *m = (code_ & 0x10) >> 4;
314
    *vm = code_ & 0x0F;
315
  }
316

    
317
  int code_;
318
};
319

    
320

    
321
typedef DwVfpRegister DoubleRegister;
322

    
323

    
324
// Double word VFP register d0-15.
325
struct LowDwVfpRegister {
326
 public:
327
  static const int kMaxNumLowRegisters = 16;
328
  operator DwVfpRegister() const {
329
    DwVfpRegister r = { code_ };
330
    return r;
331
  }
332
  static LowDwVfpRegister from_code(int code) {
333
    LowDwVfpRegister r = { code };
334
    return r;
335
  }
336

    
337
  bool is_valid() const {
338
    return 0 <= code_ && code_ < kMaxNumLowRegisters;
339
  }
340
  bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
341
  bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
342
  int code() const {
343
    ASSERT(is_valid());
344
    return code_;
345
  }
346
  SwVfpRegister low() const {
347
    SwVfpRegister reg;
348
    reg.code_ = code_ * 2;
349

    
350
    ASSERT(reg.is_valid());
351
    return reg;
352
  }
353
  SwVfpRegister high() const {
354
    SwVfpRegister reg;
355
    reg.code_ = (code_ * 2) + 1;
356

    
357
    ASSERT(reg.is_valid());
358
    return reg;
359
  }
360

    
361
  int code_;
362
};
363

    
364

    
365
// Quad word NEON register.
366
struct QwNeonRegister {
367
  static const int kMaxNumRegisters = 16;
368

    
369
  static QwNeonRegister from_code(int code) {
370
    QwNeonRegister r = { code };
371
    return r;
372
  }
373

    
374
  bool is_valid() const {
375
    return (0 <= code_) && (code_ < kMaxNumRegisters);
376
  }
377
  bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
378
  int code() const {
379
    ASSERT(is_valid());
380
    return code_;
381
  }
382
  void split_code(int* vm, int* m) const {
383
    ASSERT(is_valid());
384
    *m = (code_ & 0x10) >> 4;
385
    *vm = code_ & 0x0F;
386
  }
387

    
388
  int code_;
389
};
390

    
391

    
392
typedef QwNeonRegister QuadRegister;
393

    
394

    
395
// Support for the VFP registers s0 to s31 (d0 to d15).
396
// Note that "s(N):s(N+1)" is the same as "d(N/2)".
397
const SwVfpRegister s0  = {  0 };
398
const SwVfpRegister s1  = {  1 };
399
const SwVfpRegister s2  = {  2 };
400
const SwVfpRegister s3  = {  3 };
401
const SwVfpRegister s4  = {  4 };
402
const SwVfpRegister s5  = {  5 };
403
const SwVfpRegister s6  = {  6 };
404
const SwVfpRegister s7  = {  7 };
405
const SwVfpRegister s8  = {  8 };
406
const SwVfpRegister s9  = {  9 };
407
const SwVfpRegister s10 = { 10 };
408
const SwVfpRegister s11 = { 11 };
409
const SwVfpRegister s12 = { 12 };
410
const SwVfpRegister s13 = { 13 };
411
const SwVfpRegister s14 = { 14 };
412
const SwVfpRegister s15 = { 15 };
413
const SwVfpRegister s16 = { 16 };
414
const SwVfpRegister s17 = { 17 };
415
const SwVfpRegister s18 = { 18 };
416
const SwVfpRegister s19 = { 19 };
417
const SwVfpRegister s20 = { 20 };
418
const SwVfpRegister s21 = { 21 };
419
const SwVfpRegister s22 = { 22 };
420
const SwVfpRegister s23 = { 23 };
421
const SwVfpRegister s24 = { 24 };
422
const SwVfpRegister s25 = { 25 };
423
const SwVfpRegister s26 = { 26 };
424
const SwVfpRegister s27 = { 27 };
425
const SwVfpRegister s28 = { 28 };
426
const SwVfpRegister s29 = { 29 };
427
const SwVfpRegister s30 = { 30 };
428
const SwVfpRegister s31 = { 31 };
429

    
430
const DwVfpRegister no_dreg = { -1 };
431
const LowDwVfpRegister d0 = { 0 };
432
const LowDwVfpRegister d1 = { 1 };
433
const LowDwVfpRegister d2 = { 2 };
434
const LowDwVfpRegister d3 = { 3 };
435
const LowDwVfpRegister d4 = { 4 };
436
const LowDwVfpRegister d5 = { 5 };
437
const LowDwVfpRegister d6 = { 6 };
438
const LowDwVfpRegister d7 = { 7 };
439
const LowDwVfpRegister d8 = { 8 };
440
const LowDwVfpRegister d9 = { 9 };
441
const LowDwVfpRegister d10 = { 10 };
442
const LowDwVfpRegister d11 = { 11 };
443
const LowDwVfpRegister d12 = { 12 };
444
const LowDwVfpRegister d13 = { 13 };
445
const LowDwVfpRegister d14 = { 14 };
446
const LowDwVfpRegister d15 = { 15 };
447
const DwVfpRegister d16 = { 16 };
448
const DwVfpRegister d17 = { 17 };
449
const DwVfpRegister d18 = { 18 };
450
const DwVfpRegister d19 = { 19 };
451
const DwVfpRegister d20 = { 20 };
452
const DwVfpRegister d21 = { 21 };
453
const DwVfpRegister d22 = { 22 };
454
const DwVfpRegister d23 = { 23 };
455
const DwVfpRegister d24 = { 24 };
456
const DwVfpRegister d25 = { 25 };
457
const DwVfpRegister d26 = { 26 };
458
const DwVfpRegister d27 = { 27 };
459
const DwVfpRegister d28 = { 28 };
460
const DwVfpRegister d29 = { 29 };
461
const DwVfpRegister d30 = { 30 };
462
const DwVfpRegister d31 = { 31 };
463

    
464
const QwNeonRegister q0  = {  0 };
465
const QwNeonRegister q1  = {  1 };
466
const QwNeonRegister q2  = {  2 };
467
const QwNeonRegister q3  = {  3 };
468
const QwNeonRegister q4  = {  4 };
469
const QwNeonRegister q5  = {  5 };
470
const QwNeonRegister q6  = {  6 };
471
const QwNeonRegister q7  = {  7 };
472
const QwNeonRegister q8  = {  8 };
473
const QwNeonRegister q9  = {  9 };
474
const QwNeonRegister q10 = { 10 };
475
const QwNeonRegister q11 = { 11 };
476
const QwNeonRegister q12 = { 12 };
477
const QwNeonRegister q13 = { 13 };
478
const QwNeonRegister q14 = { 14 };
479
const QwNeonRegister q15 = { 15 };
480

    
481

    
482
// Aliases for double registers.  Defined using #define instead of
483
// "static const DwVfpRegister&" because Clang complains otherwise when a
484
// compilation unit that includes this header doesn't use the variables.
485
#define kFirstCalleeSavedDoubleReg d8
486
#define kLastCalleeSavedDoubleReg d15
487
#define kDoubleRegZero d14
488
#define kScratchDoubleReg d15
489

    
490

    
491
// Coprocessor register
492
struct CRegister {
493
  bool is_valid() const { return 0 <= code_ && code_ < 16; }
494
  bool is(CRegister creg) const { return code_ == creg.code_; }
495
  int code() const {
496
    ASSERT(is_valid());
497
    return code_;
498
  }
499
  int bit() const {
500
    ASSERT(is_valid());
501
    return 1 << code_;
502
  }
503

    
504
  // Unfortunately we can't make this private in a struct.
505
  int code_;
506
};
507

    
508

    
509
const CRegister no_creg = { -1 };
510

    
511
const CRegister cr0  = {  0 };
512
const CRegister cr1  = {  1 };
513
const CRegister cr2  = {  2 };
514
const CRegister cr3  = {  3 };
515
const CRegister cr4  = {  4 };
516
const CRegister cr5  = {  5 };
517
const CRegister cr6  = {  6 };
518
const CRegister cr7  = {  7 };
519
const CRegister cr8  = {  8 };
520
const CRegister cr9  = {  9 };
521
const CRegister cr10 = { 10 };
522
const CRegister cr11 = { 11 };
523
const CRegister cr12 = { 12 };
524
const CRegister cr13 = { 13 };
525
const CRegister cr14 = { 14 };
526
const CRegister cr15 = { 15 };
527

    
528

    
529
// Coprocessor number
530
enum Coprocessor {
531
  p0  = 0,
532
  p1  = 1,
533
  p2  = 2,
534
  p3  = 3,
535
  p4  = 4,
536
  p5  = 5,
537
  p6  = 6,
538
  p7  = 7,
539
  p8  = 8,
540
  p9  = 9,
541
  p10 = 10,
542
  p11 = 11,
543
  p12 = 12,
544
  p13 = 13,
545
  p14 = 14,
546
  p15 = 15
547
};
548

    
549

    
550
// -----------------------------------------------------------------------------
551
// Machine instruction Operands
552

    
553
// Class Operand represents a shifter operand in data processing instructions
554
class Operand BASE_EMBEDDED {
555
 public:
556
  // immediate
557
  INLINE(explicit Operand(int32_t immediate,
558
         RelocInfo::Mode rmode = RelocInfo::NONE32));
559
  INLINE(static Operand Zero()) {
560
    return Operand(static_cast<int32_t>(0));
561
  }
562
  INLINE(explicit Operand(const ExternalReference& f));
563
  explicit Operand(Handle<Object> handle);
564
  INLINE(explicit Operand(Smi* value));
565

    
566
  // rm
567
  INLINE(explicit Operand(Register rm));
568

    
569
  // rm <shift_op> shift_imm
570
  explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
571
  INLINE(static Operand SmiUntag(Register rm)) {
572
    return Operand(rm, ASR, kSmiTagSize);
573
  }
574
  INLINE(static Operand PointerOffsetFromSmiKey(Register key)) {
575
    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
576
    return Operand(key, LSL, kPointerSizeLog2 - kSmiTagSize);
577
  }
578
  INLINE(static Operand DoubleOffsetFromSmiKey(Register key)) {
579
    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kDoubleSizeLog2);
580
    return Operand(key, LSL, kDoubleSizeLog2 - kSmiTagSize);
581
  }
582

    
583
  // rm <shift_op> rs
584
  explicit Operand(Register rm, ShiftOp shift_op, Register rs);
585

    
586
  // Return true if this is a register operand.
587
  INLINE(bool is_reg() const);
588

    
589
  // Return true if this operand fits in one instruction so that no
590
  // 2-instruction solution with a load into the ip register is necessary. If
591
  // the instruction this operand is used for is a MOV or MVN instruction the
592
  // actual instruction to use is required for this calculation. For other
593
  // instructions instr is ignored.
594
  bool is_single_instruction(const Assembler* assembler, Instr instr = 0) const;
595
  bool must_output_reloc_info(const Assembler* assembler) const;
596

    
597
  inline int32_t immediate() const {
598
    ASSERT(!rm_.is_valid());
599
    return imm32_;
600
  }
601

    
602
  Register rm() const { return rm_; }
603
  Register rs() const { return rs_; }
604
  ShiftOp shift_op() const { return shift_op_; }
605

    
606
 private:
607
  Register rm_;
608
  Register rs_;
609
  ShiftOp shift_op_;
610
  int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
611
  int32_t imm32_;  // valid if rm_ == no_reg
612
  RelocInfo::Mode rmode_;
613

    
614
  friend class Assembler;
615
};
616

    
617

    
618
// Class MemOperand represents a memory operand in load and store instructions
619
class MemOperand BASE_EMBEDDED {
620
 public:
621
  // [rn +/- offset]      Offset/NegOffset
622
  // [rn +/- offset]!     PreIndex/NegPreIndex
623
  // [rn], +/- offset     PostIndex/NegPostIndex
624
  // offset is any signed 32-bit value; offset is first loaded to register ip if
625
  // it does not fit the addressing mode (12-bit unsigned and sign bit)
626
  explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
627

    
628
  // [rn +/- rm]          Offset/NegOffset
629
  // [rn +/- rm]!         PreIndex/NegPreIndex
630
  // [rn], +/- rm         PostIndex/NegPostIndex
631
  explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
632

    
633
  // [rn +/- rm <shift_op> shift_imm]      Offset/NegOffset
634
  // [rn +/- rm <shift_op> shift_imm]!     PreIndex/NegPreIndex
635
  // [rn], +/- rm <shift_op> shift_imm     PostIndex/NegPostIndex
636
  explicit MemOperand(Register rn, Register rm,
637
                      ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
638
  INLINE(static MemOperand PointerAddressFromSmiKey(Register array,
639
                                                    Register key,
640
                                                    AddrMode am = Offset)) {
641
    STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
642
    return MemOperand(array, key, LSL, kPointerSizeLog2 - kSmiTagSize, am);
643
  }
644

    
645
  void set_offset(int32_t offset) {
646
      ASSERT(rm_.is(no_reg));
647
      offset_ = offset;
648
  }
649

    
650
  uint32_t offset() const {
651
      ASSERT(rm_.is(no_reg));
652
      return offset_;
653
  }
654

    
655
  Register rn() const { return rn_; }
656
  Register rm() const { return rm_; }
657
  AddrMode am() const { return am_; }
658

    
659
  bool OffsetIsUint12Encodable() const {
660
    return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
661
  }
662

    
663
 private:
664
  Register rn_;  // base
665
  Register rm_;  // register offset
666
  int32_t offset_;  // valid if rm_ == no_reg
667
  ShiftOp shift_op_;
668
  int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
669
  AddrMode am_;  // bits P, U, and W
670

    
671
  friend class Assembler;
672
};
673

    
674

    
675
// Class NeonMemOperand represents a memory operand in load and
676
// store NEON instructions
677
class NeonMemOperand BASE_EMBEDDED {
678
 public:
679
  // [rn {:align}]       Offset
680
  // [rn {:align}]!      PostIndex
681
  explicit NeonMemOperand(Register rn, AddrMode am = Offset, int align = 0);
682

    
683
  // [rn {:align}], rm   PostIndex
684
  explicit NeonMemOperand(Register rn, Register rm, int align = 0);
685

    
686
  Register rn() const { return rn_; }
687
  Register rm() const { return rm_; }
688
  int align() const { return align_; }
689

    
690
 private:
691
  void SetAlignment(int align);
692

    
693
  Register rn_;  // base
694
  Register rm_;  // register increment
695
  int align_;
696
};
697

    
698

    
699
// Class NeonListOperand represents a list of NEON registers
700
class NeonListOperand BASE_EMBEDDED {
701
 public:
702
  explicit NeonListOperand(DoubleRegister base, int registers_count = 1);
703
  DoubleRegister base() const { return base_; }
704
  NeonListType type() const { return type_; }
705
 private:
706
  DoubleRegister base_;
707
  NeonListType type_;
708
};
709

    
710
extern const Instr kMovLrPc;
711
extern const Instr kLdrPCMask;
712
extern const Instr kLdrPCPattern;
713
extern const Instr kBlxRegMask;
714
extern const Instr kBlxRegPattern;
715
extern const Instr kBlxIp;
716

    
717
extern const Instr kMovMvnMask;
718
extern const Instr kMovMvnPattern;
719
extern const Instr kMovMvnFlip;
720

    
721
extern const Instr kMovLeaveCCMask;
722
extern const Instr kMovLeaveCCPattern;
723
extern const Instr kMovwMask;
724
extern const Instr kMovwPattern;
725
extern const Instr kMovwLeaveCCFlip;
726

    
727
extern const Instr kCmpCmnMask;
728
extern const Instr kCmpCmnPattern;
729
extern const Instr kCmpCmnFlip;
730
extern const Instr kAddSubFlip;
731
extern const Instr kAndBicFlip;
732

    
733
struct VmovIndex {
734
  unsigned char index;
735
};
736
const VmovIndex VmovIndexLo = { 0 };
737
const VmovIndex VmovIndexHi = { 1 };
738

    
739
class Assembler : public AssemblerBase {
740
 public:
741
  // Create an assembler. Instructions and relocation information are emitted
742
  // into a buffer, with the instructions starting from the beginning and the
743
  // relocation information starting from the end of the buffer. See CodeDesc
744
  // for a detailed comment on the layout (globals.h).
745
  //
746
  // If the provided buffer is NULL, the assembler allocates and grows its own
747
  // buffer, and buffer_size determines the initial buffer size. The buffer is
748
  // owned by the assembler and deallocated upon destruction of the assembler.
749
  //
750
  // If the provided buffer is not NULL, the assembler uses the provided buffer
751
  // for code generation and assumes its size to be buffer_size. If the buffer
752
  // is too small, a fatal error occurs. No deallocation of the buffer is done
753
  // upon destruction of the assembler.
754
  Assembler(Isolate* isolate, void* buffer, int buffer_size);
755
  virtual ~Assembler();
756

    
757
  // GetCode emits any pending (non-emitted) code and fills the descriptor
758
  // desc. GetCode() is idempotent; it returns the same result if no other
759
  // Assembler functions are invoked in between GetCode() calls.
760
  void GetCode(CodeDesc* desc);
761

    
762
  // Label operations & relative jumps (PPUM Appendix D)
763
  //
764
  // Takes a branch opcode (cc) and a label (L) and generates
765
  // either a backward branch or a forward branch and links it
766
  // to the label fixup chain. Usage:
767
  //
768
  // Label L;    // unbound label
769
  // j(cc, &L);  // forward branch to unbound label
770
  // bind(&L);   // bind label to the current pc
771
  // j(cc, &L);  // backward branch to bound label
772
  // bind(&L);   // illegal: a label may be bound only once
773
  //
774
  // Note: The same Label can be used for forward and backward branches
775
  // but it may be bound only once.
776

    
777
  void bind(Label* L);  // binds an unbound label L to the current code position
778

    
779
  // Returns the branch offset to the given label from the current code position
780
  // Links the label to the current position if it is still unbound
781
  // Manages the jump elimination optimization if the second parameter is true.
782
  int branch_offset(Label* L, bool jump_elimination_allowed);
783

    
784
  // Return the address in the constant pool of the code target address used by
785
  // the branch/call instruction at pc, or the object in a mov.
786
  INLINE(static Address target_pointer_address_at(Address pc));
787

    
788
  // Read/Modify the pointer in the branch/call/move instruction at pc.
789
  INLINE(static Address target_pointer_at(Address pc));
790
  INLINE(static void set_target_pointer_at(Address pc, Address target));
791

    
792
  // Read/Modify the code target address in the branch/call instruction at pc.
793
  INLINE(static Address target_address_at(Address pc));
794
  INLINE(static void set_target_address_at(Address pc, Address target));
795

    
796
  // Return the code target address at a call site from the return address
797
  // of that call in the instruction stream.
798
  INLINE(static Address target_address_from_return_address(Address pc));
799

    
800
  // Given the address of the beginning of a call, return the address
801
  // in the instruction stream that the call will return from.
802
  INLINE(static Address return_address_from_call_start(Address pc));
803

    
804
  // This sets the branch destination (which is in the constant pool on ARM).
805
  // This is for calls and branches within generated code.
806
  inline static void deserialization_set_special_target_at(
807
      Address constant_pool_entry, Address target);
808

    
809
  // This sets the branch destination (which is in the constant pool on ARM).
810
  // This is for calls and branches to runtime code.
811
  inline static void set_external_target_at(Address constant_pool_entry,
812
                                            Address target);
813

    
814
  // Here we are patching the address in the constant pool, not the actual call
815
  // instruction.  The address in the constant pool is the same size as a
816
  // pointer.
817
  static const int kSpecialTargetSize = kPointerSize;
818

    
819
  // Size of an instruction.
820
  static const int kInstrSize = sizeof(Instr);
821

    
822
  // Distance between start of patched return sequence and the emitted address
823
  // to jump to.
824
  // Patched return sequence is:
825
  //  ldr  ip, [pc, #0]   @ emited address and start
826
  //  blx  ip
827
  static const int kPatchReturnSequenceAddressOffset =  0 * kInstrSize;
828

    
829
  // Distance between start of patched debug break slot and the emitted address
830
  // to jump to.
831
  // Patched debug break slot code is:
832
  //  ldr  ip, [pc, #0]   @ emited address and start
833
  //  blx  ip
834
  static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
835

    
836
  static const int kPatchDebugBreakSlotReturnOffset = 2 * kInstrSize;
837

    
838
  // Difference between address of current opcode and value read from pc
839
  // register.
840
  static const int kPcLoadDelta = 8;
841

    
842
  static const int kJSReturnSequenceInstructions = 4;
843
  static const int kDebugBreakSlotInstructions = 3;
844
  static const int kDebugBreakSlotLength =
845
      kDebugBreakSlotInstructions * kInstrSize;
846

    
847
  // ---------------------------------------------------------------------------
848
  // Code generation
849

    
850
  // Insert the smallest number of nop instructions
851
  // possible to align the pc offset to a multiple
852
  // of m. m must be a power of 2 (>= 4).
853
  void Align(int m);
854
  // Aligns code to something that's optimal for a jump target for the platform.
855
  void CodeTargetAlign();
856

    
857
  // Branch instructions
858
  void b(int branch_offset, Condition cond = al);
859
  void bl(int branch_offset, Condition cond = al);
860
  void blx(int branch_offset);  // v5 and above
861
  void blx(Register target, Condition cond = al);  // v5 and above
862
  void bx(Register target, Condition cond = al);  // v5 and above, plus v4t
863

    
864
  // Convenience branch instructions using labels
865
  void b(Label* L, Condition cond = al)  {
866
    b(branch_offset(L, cond == al), cond);
867
  }
868
  void b(Condition cond, Label* L)  { b(branch_offset(L, cond == al), cond); }
869
  void bl(Label* L, Condition cond = al)  { bl(branch_offset(L, false), cond); }
870
  void bl(Condition cond, Label* L)  { bl(branch_offset(L, false), cond); }
871
  void blx(Label* L)  { blx(branch_offset(L, false)); }  // v5 and above
872

    
873
  // Data-processing instructions
874

    
875
  void and_(Register dst, Register src1, const Operand& src2,
876
            SBit s = LeaveCC, Condition cond = al);
877

    
878
  void eor(Register dst, Register src1, const Operand& src2,
879
           SBit s = LeaveCC, Condition cond = al);
880

    
881
  void sub(Register dst, Register src1, const Operand& src2,
882
           SBit s = LeaveCC, Condition cond = al);
883
  void sub(Register dst, Register src1, Register src2,
884
           SBit s = LeaveCC, Condition cond = al) {
885
    sub(dst, src1, Operand(src2), s, cond);
886
  }
887

    
888
  void rsb(Register dst, Register src1, const Operand& src2,
889
           SBit s = LeaveCC, Condition cond = al);
890

    
891
  void add(Register dst, Register src1, const Operand& src2,
892
           SBit s = LeaveCC, Condition cond = al);
893
  void add(Register dst, Register src1, Register src2,
894
           SBit s = LeaveCC, Condition cond = al) {
895
    add(dst, src1, Operand(src2), s, cond);
896
  }
897

    
898
  void adc(Register dst, Register src1, const Operand& src2,
899
           SBit s = LeaveCC, Condition cond = al);
900

    
901
  void sbc(Register dst, Register src1, const Operand& src2,
902
           SBit s = LeaveCC, Condition cond = al);
903

    
904
  void rsc(Register dst, Register src1, const Operand& src2,
905
           SBit s = LeaveCC, Condition cond = al);
906

    
907
  void tst(Register src1, const Operand& src2, Condition cond = al);
908
  void tst(Register src1, Register src2, Condition cond = al) {
909
    tst(src1, Operand(src2), cond);
910
  }
911

    
912
  void teq(Register src1, const Operand& src2, Condition cond = al);
913

    
914
  void cmp(Register src1, const Operand& src2, Condition cond = al);
915
  void cmp(Register src1, Register src2, Condition cond = al) {
916
    cmp(src1, Operand(src2), cond);
917
  }
918
  void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
919

    
920
  void cmn(Register src1, const Operand& src2, Condition cond = al);
921

    
922
  void orr(Register dst, Register src1, const Operand& src2,
923
           SBit s = LeaveCC, Condition cond = al);
924
  void orr(Register dst, Register src1, Register src2,
925
           SBit s = LeaveCC, Condition cond = al) {
926
    orr(dst, src1, Operand(src2), s, cond);
927
  }
928

    
929
  void mov(Register dst, const Operand& src,
930
           SBit s = LeaveCC, Condition cond = al);
931
  void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
932
    mov(dst, Operand(src), s, cond);
933
  }
934

    
935
  // Load the position of the label relative to the generated code object
936
  // pointer in a register.
937
  void mov_label_offset(Register dst, Label* label);
938

    
939
  // ARMv7 instructions for loading a 32 bit immediate in two instructions.
940
  // This may actually emit a different mov instruction, but on an ARMv7 it
941
  // is guaranteed to only emit one instruction.
942
  void movw(Register reg, uint32_t immediate, Condition cond = al);
943
  // The constant for movt should be in the range 0-0xffff.
944
  void movt(Register reg, uint32_t immediate, Condition cond = al);
945

    
946
  void bic(Register dst, Register src1, const Operand& src2,
947
           SBit s = LeaveCC, Condition cond = al);
948

    
949
  void mvn(Register dst, const Operand& src,
950
           SBit s = LeaveCC, Condition cond = al);
951

    
952
  // Multiply instructions
953

    
954
  void mla(Register dst, Register src1, Register src2, Register srcA,
955
           SBit s = LeaveCC, Condition cond = al);
956

    
957
  void mls(Register dst, Register src1, Register src2, Register srcA,
958
           Condition cond = al);
959

    
960
  void sdiv(Register dst, Register src1, Register src2,
961
            Condition cond = al);
962

    
963
  void mul(Register dst, Register src1, Register src2,
964
           SBit s = LeaveCC, Condition cond = al);
965

    
966
  void smlal(Register dstL, Register dstH, Register src1, Register src2,
967
             SBit s = LeaveCC, Condition cond = al);
968

    
969
  void smull(Register dstL, Register dstH, Register src1, Register src2,
970
             SBit s = LeaveCC, Condition cond = al);
971

    
972
  void umlal(Register dstL, Register dstH, Register src1, Register src2,
973
             SBit s = LeaveCC, Condition cond = al);
974

    
975
  void umull(Register dstL, Register dstH, Register src1, Register src2,
976
             SBit s = LeaveCC, Condition cond = al);
977

    
978
  // Miscellaneous arithmetic instructions
979

    
980
  void clz(Register dst, Register src, Condition cond = al);  // v5 and above
981

    
982
  // Saturating instructions. v6 and above.
983

    
984
  // Unsigned saturate.
985
  //
986
  // Saturate an optionally shifted signed value to an unsigned range.
987
  //
988
  //   usat dst, #satpos, src
989
  //   usat dst, #satpos, src, lsl #sh
990
  //   usat dst, #satpos, src, asr #sh
991
  //
992
  // Register dst will contain:
993
  //
994
  //   0,                 if s < 0
995
  //   (1 << satpos) - 1, if s > ((1 << satpos) - 1)
996
  //   s,                 otherwise
997
  //
998
  // where s is the contents of src after shifting (if used.)
999
  void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
1000

    
1001
  // Bitfield manipulation instructions. v7 and above.
1002

    
1003
  void ubfx(Register dst, Register src, int lsb, int width,
1004
            Condition cond = al);
1005

    
1006
  void sbfx(Register dst, Register src, int lsb, int width,
1007
            Condition cond = al);
1008

    
1009
  void bfc(Register dst, int lsb, int width, Condition cond = al);
1010

    
1011
  void bfi(Register dst, Register src, int lsb, int width,
1012
           Condition cond = al);
1013

    
1014
  void pkhbt(Register dst, Register src1, const Operand& src2,
1015
             Condition cond = al);
1016

    
1017
  void pkhtb(Register dst, Register src1, const Operand& src2,
1018
             Condition cond = al);
1019

    
1020
  void uxtb(Register dst, const Operand& src, Condition cond = al);
1021

    
1022
  void uxtab(Register dst, Register src1, const Operand& src2,
1023
             Condition cond = al);
1024

    
1025
  void uxtb16(Register dst, const Operand& src, Condition cond = al);
1026

    
1027
  // Status register access instructions
1028

    
1029
  void mrs(Register dst, SRegister s, Condition cond = al);
1030
  void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
1031

    
1032
  // Load/Store instructions
1033
  void ldr(Register dst, const MemOperand& src, Condition cond = al);
1034
  void str(Register src, const MemOperand& dst, Condition cond = al);
1035
  void ldrb(Register dst, const MemOperand& src, Condition cond = al);
1036
  void strb(Register src, const MemOperand& dst, Condition cond = al);
1037
  void ldrh(Register dst, const MemOperand& src, Condition cond = al);
1038
  void strh(Register src, const MemOperand& dst, Condition cond = al);
1039
  void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
1040
  void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
1041
  void ldrd(Register dst1,
1042
            Register dst2,
1043
            const MemOperand& src, Condition cond = al);
1044
  void strd(Register src1,
1045
            Register src2,
1046
            const MemOperand& dst, Condition cond = al);
1047

    
1048
  // Preload instructions
1049
  void pld(const MemOperand& address);
1050

    
1051
  // Load/Store multiple instructions
1052
  void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
1053
  void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
1054

    
1055
  // Exception-generating instructions and debugging support
1056
  void stop(const char* msg,
1057
            Condition cond = al,
1058
            int32_t code = kDefaultStopCode);
1059

    
1060
  void bkpt(uint32_t imm16);  // v5 and above
1061
  void svc(uint32_t imm24, Condition cond = al);
1062

    
1063
  // Coprocessor instructions
1064

    
1065
  void cdp(Coprocessor coproc, int opcode_1,
1066
           CRegister crd, CRegister crn, CRegister crm,
1067
           int opcode_2, Condition cond = al);
1068

    
1069
  void cdp2(Coprocessor coproc, int opcode_1,
1070
            CRegister crd, CRegister crn, CRegister crm,
1071
            int opcode_2);  // v5 and above
1072

    
1073
  void mcr(Coprocessor coproc, int opcode_1,
1074
           Register rd, CRegister crn, CRegister crm,
1075
           int opcode_2 = 0, Condition cond = al);
1076

    
1077
  void mcr2(Coprocessor coproc, int opcode_1,
1078
            Register rd, CRegister crn, CRegister crm,
1079
            int opcode_2 = 0);  // v5 and above
1080

    
1081
  void mrc(Coprocessor coproc, int opcode_1,
1082
           Register rd, CRegister crn, CRegister crm,
1083
           int opcode_2 = 0, Condition cond = al);
1084

    
1085
  void mrc2(Coprocessor coproc, int opcode_1,
1086
            Register rd, CRegister crn, CRegister crm,
1087
            int opcode_2 = 0);  // v5 and above
1088

    
1089
  void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
1090
           LFlag l = Short, Condition cond = al);
1091
  void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
1092
           LFlag l = Short, Condition cond = al);
1093

    
1094
  void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
1095
            LFlag l = Short);  // v5 and above
1096
  void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
1097
            LFlag l = Short);  // v5 and above
1098

    
1099
  // Support for VFP.
1100
  // All these APIs support S0 to S31 and D0 to D31.
1101

    
1102
  void vldr(const DwVfpRegister dst,
1103
            const Register base,
1104
            int offset,
1105
            const Condition cond = al);
1106
  void vldr(const DwVfpRegister dst,
1107
            const MemOperand& src,
1108
            const Condition cond = al);
1109

    
1110
  void vldr(const SwVfpRegister dst,
1111
            const Register base,
1112
            int offset,
1113
            const Condition cond = al);
1114
  void vldr(const SwVfpRegister dst,
1115
            const MemOperand& src,
1116
            const Condition cond = al);
1117

    
1118
  void vstr(const DwVfpRegister src,
1119
            const Register base,
1120
            int offset,
1121
            const Condition cond = al);
1122
  void vstr(const DwVfpRegister src,
1123
            const MemOperand& dst,
1124
            const Condition cond = al);
1125

    
1126
  void vstr(const SwVfpRegister src,
1127
            const Register base,
1128
            int offset,
1129
            const Condition cond = al);
1130
  void vstr(const SwVfpRegister src,
1131
            const MemOperand& dst,
1132
            const Condition cond = al);
1133

    
1134
  void vldm(BlockAddrMode am,
1135
            Register base,
1136
            DwVfpRegister first,
1137
            DwVfpRegister last,
1138
            Condition cond = al);
1139

    
1140
  void vstm(BlockAddrMode am,
1141
            Register base,
1142
            DwVfpRegister first,
1143
            DwVfpRegister last,
1144
            Condition cond = al);
1145

    
1146
  void vldm(BlockAddrMode am,
1147
            Register base,
1148
            SwVfpRegister first,
1149
            SwVfpRegister last,
1150
            Condition cond = al);
1151

    
1152
  void vstm(BlockAddrMode am,
1153
            Register base,
1154
            SwVfpRegister first,
1155
            SwVfpRegister last,
1156
            Condition cond = al);
1157

    
1158
  void vmov(const DwVfpRegister dst,
1159
            double imm,
1160
            const Register scratch = no_reg);
1161
  void vmov(const SwVfpRegister dst,
1162
            const SwVfpRegister src,
1163
            const Condition cond = al);
1164
  void vmov(const DwVfpRegister dst,
1165
            const DwVfpRegister src,
1166
            const Condition cond = al);
1167
  void vmov(const DwVfpRegister dst,
1168
            const VmovIndex index,
1169
            const Register src,
1170
            const Condition cond = al);
1171
  void vmov(const Register dst,
1172
            const VmovIndex index,
1173
            const DwVfpRegister src,
1174
            const Condition cond = al);
1175
  void vmov(const DwVfpRegister dst,
1176
            const Register src1,
1177
            const Register src2,
1178
            const Condition cond = al);
1179
  void vmov(const Register dst1,
1180
            const Register dst2,
1181
            const DwVfpRegister src,
1182
            const Condition cond = al);
1183
  void vmov(const SwVfpRegister dst,
1184
            const Register src,
1185
            const Condition cond = al);
1186
  void vmov(const Register dst,
1187
            const SwVfpRegister src,
1188
            const Condition cond = al);
1189
  void vcvt_f64_s32(const DwVfpRegister dst,
1190
                    const SwVfpRegister src,
1191
                    VFPConversionMode mode = kDefaultRoundToZero,
1192
                    const Condition cond = al);
1193
  void vcvt_f32_s32(const SwVfpRegister dst,
1194
                    const SwVfpRegister src,
1195
                    VFPConversionMode mode = kDefaultRoundToZero,
1196
                    const Condition cond = al);
1197
  void vcvt_f64_u32(const DwVfpRegister dst,
1198
                    const SwVfpRegister src,
1199
                    VFPConversionMode mode = kDefaultRoundToZero,
1200
                    const Condition cond = al);
1201
  void vcvt_s32_f64(const SwVfpRegister dst,
1202
                    const DwVfpRegister src,
1203
                    VFPConversionMode mode = kDefaultRoundToZero,
1204
                    const Condition cond = al);
1205
  void vcvt_u32_f64(const SwVfpRegister dst,
1206
                    const DwVfpRegister src,
1207
                    VFPConversionMode mode = kDefaultRoundToZero,
1208
                    const Condition cond = al);
1209
  void vcvt_f64_f32(const DwVfpRegister dst,
1210
                    const SwVfpRegister src,
1211
                    VFPConversionMode mode = kDefaultRoundToZero,
1212
                    const Condition cond = al);
1213
  void vcvt_f32_f64(const SwVfpRegister dst,
1214
                    const DwVfpRegister src,
1215
                    VFPConversionMode mode = kDefaultRoundToZero,
1216
                    const Condition cond = al);
1217
  void vcvt_f64_s32(const DwVfpRegister dst,
1218
                    int fraction_bits,
1219
                    const Condition cond = al);
1220

    
1221
  void vneg(const DwVfpRegister dst,
1222
            const DwVfpRegister src,
1223
            const Condition cond = al);
1224
  void vabs(const DwVfpRegister dst,
1225
            const DwVfpRegister src,
1226
            const Condition cond = al);
1227
  void vadd(const DwVfpRegister dst,
1228
            const DwVfpRegister src1,
1229
            const DwVfpRegister src2,
1230
            const Condition cond = al);
1231
  void vsub(const DwVfpRegister dst,
1232
            const DwVfpRegister src1,
1233
            const DwVfpRegister src2,
1234
            const Condition cond = al);
1235
  void vmul(const DwVfpRegister dst,
1236
            const DwVfpRegister src1,
1237
            const DwVfpRegister src2,
1238
            const Condition cond = al);
1239
  void vmla(const DwVfpRegister dst,
1240
            const DwVfpRegister src1,
1241
            const DwVfpRegister src2,
1242
            const Condition cond = al);
1243
  void vmls(const DwVfpRegister dst,
1244
            const DwVfpRegister src1,
1245
            const DwVfpRegister src2,
1246
            const Condition cond = al);
1247
  void vdiv(const DwVfpRegister dst,
1248
            const DwVfpRegister src1,
1249
            const DwVfpRegister src2,
1250
            const Condition cond = al);
1251
  void vcmp(const DwVfpRegister src1,
1252
            const DwVfpRegister src2,
1253
            const Condition cond = al);
1254
  void vcmp(const DwVfpRegister src1,
1255
            const double src2,
1256
            const Condition cond = al);
1257
  void vmrs(const Register dst,
1258
            const Condition cond = al);
1259
  void vmsr(const Register dst,
1260
            const Condition cond = al);
1261
  void vsqrt(const DwVfpRegister dst,
1262
             const DwVfpRegister src,
1263
             const Condition cond = al);
1264

    
1265
  // Support for NEON.
1266
  // All these APIs support D0 to D31 and Q0 to Q15.
1267

    
1268
  void vld1(NeonSize size,
1269
            const NeonListOperand& dst,
1270
            const NeonMemOperand& src);
1271
  void vst1(NeonSize size,
1272
            const NeonListOperand& src,
1273
            const NeonMemOperand& dst);
1274
  void vmovl(NeonDataType dt, QwNeonRegister dst, DwVfpRegister src);
1275

    
1276
  // Pseudo instructions
1277

    
1278
  // Different nop operations are used by the code generator to detect certain
1279
  // states of the generated code.
1280
  enum NopMarkerTypes {
1281
    NON_MARKING_NOP = 0,
1282
    DEBUG_BREAK_NOP,
1283
    // IC markers.
1284
    PROPERTY_ACCESS_INLINED,
1285
    PROPERTY_ACCESS_INLINED_CONTEXT,
1286
    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1287
    // Helper values.
1288
    LAST_CODE_MARKER,
1289
    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1290
  };
1291

    
1292
  void nop(int type = 0);   // 0 is the default non-marking type.
1293

    
1294
  void push(Register src, Condition cond = al) {
1295
    str(src, MemOperand(sp, 4, NegPreIndex), cond);
1296
  }
1297

    
1298
  void pop(Register dst, Condition cond = al) {
1299
    ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1300
  }
1301

    
1302
  void pop() {
1303
    add(sp, sp, Operand(kPointerSize));
1304
  }
1305

    
1306
  // Jump unconditionally to given label.
1307
  void jmp(Label* L) { b(L, al); }
1308

    
1309
  static bool use_immediate_embedded_pointer_loads(
1310
      const Assembler* assembler) {
1311
    return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
1312
        (assembler == NULL || !assembler->predictable_code_size());
1313
  }
1314

    
1315
  // Check the code size generated from label to here.
1316
  int SizeOfCodeGeneratedSince(Label* label) {
1317
    return pc_offset() - label->pos();
1318
  }
1319

    
1320
  // Check the number of instructions generated from label to here.
1321
  int InstructionsGeneratedSince(Label* label) {
1322
    return SizeOfCodeGeneratedSince(label) / kInstrSize;
1323
  }
1324

    
1325
  // Check whether an immediate fits an addressing mode 1 instruction.
1326
  bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1327

    
1328
  // Class for scoping postponing the constant pool generation.
1329
  class BlockConstPoolScope {
1330
   public:
1331
    explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1332
      assem_->StartBlockConstPool();
1333
    }
1334
    ~BlockConstPoolScope() {
1335
      assem_->EndBlockConstPool();
1336
    }
1337

    
1338
   private:
1339
    Assembler* assem_;
1340

    
1341
    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1342
  };
1343

    
1344
  // Debugging
1345

    
1346
  // Mark address of the ExitJSFrame code.
1347
  void RecordJSReturn();
1348

    
1349
  // Mark address of a debug break slot.
1350
  void RecordDebugBreakSlot();
1351

    
1352
  // Record the AST id of the CallIC being compiled, so that it can be placed
1353
  // in the relocation information.
1354
  void SetRecordedAstId(TypeFeedbackId ast_id) {
1355
    ASSERT(recorded_ast_id_.IsNone());
1356
    recorded_ast_id_ = ast_id;
1357
  }
1358

    
1359
  TypeFeedbackId RecordedAstId() {
1360
    ASSERT(!recorded_ast_id_.IsNone());
1361
    return recorded_ast_id_;
1362
  }
1363

    
1364
  void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1365

    
1366
  // Record a comment relocation entry that can be used by a disassembler.
1367
  // Use --code-comments to enable.
1368
  void RecordComment(const char* msg);
1369

    
1370
  // Record the emission of a constant pool.
1371
  //
1372
  // The emission of constant pool depends on the size of the code generated and
1373
  // the number of RelocInfo recorded.
1374
  // The Debug mechanism needs to map code offsets between two versions of a
1375
  // function, compiled with and without debugger support (see for example
1376
  // Debug::PrepareForBreakPoints()).
1377
  // Compiling functions with debugger support generates additional code
1378
  // (Debug::GenerateSlot()). This may affect the emission of the constant
1379
  // pools and cause the version of the code with debugger support to have
1380
  // constant pools generated in different places.
1381
  // Recording the position and size of emitted constant pools allows to
1382
  // correctly compute the offset mappings between the different versions of a
1383
  // function in all situations.
1384
  //
1385
  // The parameter indicates the size of the constant pool (in bytes), including
1386
  // the marker and branch over the data.
1387
  void RecordConstPool(int size);
1388

    
1389
  // Writes a single byte or word of data in the code stream.  Used
1390
  // for inline tables, e.g., jump-tables. The constant pool should be
1391
  // emitted before any use of db and dd to ensure that constant pools
1392
  // are not emitted as part of the tables generated.
1393
  void db(uint8_t data);
1394
  void dd(uint32_t data);
1395

    
1396
  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1397

    
1398
  // Read/patch instructions
1399
  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1400
  void instr_at_put(int pos, Instr instr) {
1401
    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1402
  }
1403
  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1404
  static void instr_at_put(byte* pc, Instr instr) {
1405
    *reinterpret_cast<Instr*>(pc) = instr;
1406
  }
1407
  static Condition GetCondition(Instr instr);
1408
  static bool IsBranch(Instr instr);
1409
  static int GetBranchOffset(Instr instr);
1410
  static bool IsLdrRegisterImmediate(Instr instr);
1411
  static bool IsVldrDRegisterImmediate(Instr instr);
1412
  static int GetLdrRegisterImmediateOffset(Instr instr);
1413
  static int GetVldrDRegisterImmediateOffset(Instr instr);
1414
  static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
1415
  static Instr SetVldrDRegisterImmediateOffset(Instr instr, int offset);
1416
  static bool IsStrRegisterImmediate(Instr instr);
1417
  static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1418
  static bool IsAddRegisterImmediate(Instr instr);
1419
  static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
1420
  static Register GetRd(Instr instr);
1421
  static Register GetRn(Instr instr);
1422
  static Register GetRm(Instr instr);
1423
  static bool IsPush(Instr instr);
1424
  static bool IsPop(Instr instr);
1425
  static bool IsStrRegFpOffset(Instr instr);
1426
  static bool IsLdrRegFpOffset(Instr instr);
1427
  static bool IsStrRegFpNegOffset(Instr instr);
1428
  static bool IsLdrRegFpNegOffset(Instr instr);
1429
  static bool IsLdrPcImmediateOffset(Instr instr);
1430
  static bool IsVldrDPcImmediateOffset(Instr instr);
1431
  static bool IsTstImmediate(Instr instr);
1432
  static bool IsCmpRegister(Instr instr);
1433
  static bool IsCmpImmediate(Instr instr);
1434
  static Register GetCmpImmediateRegister(Instr instr);
1435
  static int GetCmpImmediateRawImmediate(Instr instr);
1436
  static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1437
  static bool IsMovT(Instr instr);
1438
  static bool IsMovW(Instr instr);
1439

    
1440
  // Constants in pools are accessed via pc relative addressing, which can
1441
  // reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
1442
  // PC-relative loads, thereby defining a maximum distance between the
1443
  // instruction and the accessed constant.
1444
  static const int kMaxDistToIntPool = 4*KB;
1445
  static const int kMaxDistToFPPool = 1*KB;
1446
  // All relocations could be integer, it therefore acts as the limit.
1447
  static const int kMaxNumPendingRelocInfo = kMaxDistToIntPool/kInstrSize;
1448

    
1449
  // Postpone the generation of the constant pool for the specified number of
1450
  // instructions.
1451
  void BlockConstPoolFor(int instructions);
1452

    
1453
  // Check if is time to emit a constant pool.
1454
  void CheckConstPool(bool force_emit, bool require_jump);
1455

    
1456
 protected:
1457
  // Relocation for a type-recording IC has the AST id added to it.  This
1458
  // member variable is a way to pass the information from the call site to
1459
  // the relocation info.
1460
  TypeFeedbackId recorded_ast_id_;
1461

    
1462
  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1463

    
1464
  // Decode branch instruction at pos and return branch target pos
1465
  int target_at(int pos);
1466

    
1467
  // Patch branch instruction at pos to branch to given branch target pos
1468
  void target_at_put(int pos, int target_pos);
1469

    
1470
  // Prevent contant pool emission until EndBlockConstPool is called.
1471
  // Call to this function can be nested but must be followed by an equal
1472
  // number of call to EndBlockConstpool.
1473
  void StartBlockConstPool() {
1474
    if (const_pool_blocked_nesting_++ == 0) {
1475
      // Prevent constant pool checks happening by setting the next check to
1476
      // the biggest possible offset.
1477
      next_buffer_check_ = kMaxInt;
1478
    }
1479
  }
1480

    
1481
  // Resume constant pool emission. Need to be called as many time as
1482
  // StartBlockConstPool to have an effect.
1483
  void EndBlockConstPool() {
1484
    if (--const_pool_blocked_nesting_ == 0) {
1485
      // Check the constant pool hasn't been blocked for too long.
1486
      ASSERT((num_pending_reloc_info_ == 0) ||
1487
             (pc_offset() < (first_const_pool_use_ + kMaxDistToIntPool)));
1488
      ASSERT((num_pending_64_bit_reloc_info_ == 0) ||
1489
             (pc_offset() < (first_const_pool_use_ + kMaxDistToFPPool)));
1490
      // Two cases:
1491
      //  * no_const_pool_before_ >= next_buffer_check_ and the emission is
1492
      //    still blocked
1493
      //  * no_const_pool_before_ < next_buffer_check_ and the next emit will
1494
      //    trigger a check.
1495
      next_buffer_check_ = no_const_pool_before_;
1496
    }
1497
  }
1498

    
1499
  bool is_const_pool_blocked() const {
1500
    return (const_pool_blocked_nesting_ > 0) ||
1501
           (pc_offset() < no_const_pool_before_);
1502
  }
1503

    
1504
 private:
1505
  int next_buffer_check_;  // pc offset of next buffer check
1506

    
1507
  // Code generation
1508
  // The relocation writer's position is at least kGap bytes below the end of
1509
  // the generated instructions. This is so that multi-instruction sequences do
1510
  // not have to check for overflow. The same is true for writes of large
1511
  // relocation info entries.
1512
  static const int kGap = 32;
1513

    
1514
  // Constant pool generation
1515
  // Pools are emitted in the instruction stream, preferably after unconditional
1516
  // jumps or after returns from functions (in dead code locations).
1517
  // If a long code sequence does not contain unconditional jumps, it is
1518
  // necessary to emit the constant pool before the pool gets too far from the
1519
  // location it is accessed from. In this case, we emit a jump over the emitted
1520
  // constant pool.
1521
  // Constants in the pool may be addresses of functions that gets relocated;
1522
  // if so, a relocation info entry is associated to the constant pool entry.
1523

    
1524
  // Repeated checking whether the constant pool should be emitted is rather
1525
  // expensive. By default we only check again once a number of instructions
1526
  // has been generated. That also means that the sizing of the buffers is not
1527
  // an exact science, and that we rely on some slop to not overrun buffers.
1528
  static const int kCheckPoolIntervalInst = 32;
1529
  static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
1530

    
1531

    
1532
  // Emission of the constant pool may be blocked in some code sequences.
1533
  int const_pool_blocked_nesting_;  // Block emission if this is not zero.
1534
  int no_const_pool_before_;  // Block emission before this pc offset.
1535

    
1536
  // Keep track of the first instruction requiring a constant pool entry
1537
  // since the previous constant pool was emitted.
1538
  int first_const_pool_use_;
1539

    
1540
  // Relocation info generation
1541
  // Each relocation is encoded as a variable size value
1542
  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1543
  RelocInfoWriter reloc_info_writer;
1544

    
1545
  // Relocation info records are also used during code generation as temporary
1546
  // containers for constants and code target addresses until they are emitted
1547
  // to the constant pool. These pending relocation info records are temporarily
1548
  // stored in a separate buffer until a constant pool is emitted.
1549
  // If every instruction in a long sequence is accessing the pool, we need one
1550
  // pending relocation entry per instruction.
1551

    
1552
  // the buffer of pending relocation info
1553
  RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo];
1554
  // number of pending reloc info entries in the buffer
1555
  int num_pending_reloc_info_;
1556
  // Number of pending reloc info entries included above which also happen to
1557
  // be 64-bit.
1558
  int num_pending_64_bit_reloc_info_;
1559

    
1560
  // The bound position, before this we cannot do instruction elimination.
1561
  int last_bound_pos_;
1562

    
1563
  // Code emission
1564
  inline void CheckBuffer();
1565
  void GrowBuffer();
1566
  inline void emit(Instr x);
1567

    
1568
  // 32-bit immediate values
1569
  void move_32_bit_immediate(Condition cond,
1570
                             Register rd,
1571
                             SBit s,
1572
                             const Operand& x);
1573

    
1574
  // Instruction generation
1575
  void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1576
  void addrmod2(Instr instr, Register rd, const MemOperand& x);
1577
  void addrmod3(Instr instr, Register rd, const MemOperand& x);
1578
  void addrmod4(Instr instr, Register rn, RegList rl);
1579
  void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1580

    
1581
  // Labels
1582
  void print(Label* L);
1583
  void bind_to(Label* L, int pos);
1584
  void next(Label* L);
1585

    
1586
  enum UseConstantPoolMode {
1587
    USE_CONSTANT_POOL,
1588
    DONT_USE_CONSTANT_POOL
1589
  };
1590

    
1591
  // Record reloc info for current pc_
1592
  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0,
1593
                       UseConstantPoolMode mode = USE_CONSTANT_POOL);
1594
  void RecordRelocInfo(double data);
1595
  void RecordRelocInfoConstantPoolEntryHelper(const RelocInfo& rinfo);
1596

    
1597
  friend class RelocInfo;
1598
  friend class CodePatcher;
1599
  friend class BlockConstPoolScope;
1600

    
1601
  PositionsRecorder positions_recorder_;
1602
  friend class PositionsRecorder;
1603
  friend class EnsureSpace;
1604
};
1605

    
1606

    
1607
class EnsureSpace BASE_EMBEDDED {
1608
 public:
1609
  explicit EnsureSpace(Assembler* assembler) {
1610
    assembler->CheckBuffer();
1611
  }
1612
};
1613

    
1614

    
1615
} }  // namespace v8::internal
1616

    
1617
#endif  // V8_ARM_ASSEMBLER_ARM_H_