• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // CPU Registers.
51 //
52 // 1) We would prefer to use an enum, but enum values are assignment-
53 // compatible with int, which has caused code-generation bugs.
54 //
55 // 2) We would prefer to use a class instead of a struct but we don't like
56 // the register initialization to depend on the particular initialization
57 // order (which appears to be different on OS X, Linux, and Windows for the
58 // installed versions of C++ we tried). Using a struct permits C-style
59 // "initialization". Also, the Register objects cannot be const as this
60 // forces initialization stubs in MSVC, making us dependent on initialization
61 // order.
62 //
63 // 3) By not using an enum, we are possibly preventing the compiler from
64 // doing certain constant folds, which may significantly reduce the
65 // code generated for some assembly instructions (because they boil down
66 // to a few constants). If this is a problem, we could change the code
67 // such that we use an enum in optimized mode, and the struct in debug
68 // mode. This way we get the compile-time error checking in debug mode
69 // and best performance in optimized code.
70 
71 // Core register
72 struct Register {
73   static const int kNumRegisters = 16;
74   static const int kNumAllocatableRegisters = 8;
75   static const int kSizeInBytes = 4;
76 
ToAllocationIndexRegister77   static int ToAllocationIndex(Register reg) {
78     ASSERT(reg.code() < kNumAllocatableRegisters);
79     return reg.code();
80   }
81 
FromAllocationIndexRegister82   static Register FromAllocationIndex(int index) {
83     ASSERT(index >= 0 && index < kNumAllocatableRegisters);
84     return from_code(index);
85   }
86 
AllocationIndexToStringRegister87   static const char* AllocationIndexToString(int index) {
88     ASSERT(index >= 0 && index < kNumAllocatableRegisters);
89     const char* const names[] = {
90       "r0",
91       "r1",
92       "r2",
93       "r3",
94       "r4",
95       "r5",
96       "r6",
97       "r7",
98     };
99     return names[index];
100   }
101 
from_codeRegister102   static Register from_code(int code) {
103     Register r = { code };
104     return r;
105   }
106 
is_validRegister107   bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
isRegister108   bool is(Register reg) const { return code_ == reg.code_; }
codeRegister109   int code() const {
110     ASSERT(is_valid());
111     return code_;
112   }
bitRegister113   int bit() const {
114     ASSERT(is_valid());
115     return 1 << code_;
116   }
117 
set_codeRegister118   void set_code(int code) {
119     code_ = code;
120     ASSERT(is_valid());
121   }
122 
123   // Unfortunately we can't make this private in a struct.
124   int code_;
125 };
126 
127 // These constants are used in several locations, including static initializers
128 const int kRegister_no_reg_Code = -1;
129 const int kRegister_r0_Code = 0;
130 const int kRegister_r1_Code = 1;
131 const int kRegister_r2_Code = 2;
132 const int kRegister_r3_Code = 3;
133 const int kRegister_r4_Code = 4;
134 const int kRegister_r5_Code = 5;
135 const int kRegister_r6_Code = 6;
136 const int kRegister_r7_Code = 7;
137 const int kRegister_r8_Code = 8;
138 const int kRegister_r9_Code = 9;
139 const int kRegister_r10_Code = 10;
140 const int kRegister_fp_Code = 11;
141 const int kRegister_ip_Code = 12;
142 const int kRegister_sp_Code = 13;
143 const int kRegister_lr_Code = 14;
144 const int kRegister_pc_Code = 15;
145 
146 const Register no_reg = { kRegister_no_reg_Code };
147 
148 const Register r0  = { kRegister_r0_Code };
149 const Register r1  = { kRegister_r1_Code };
150 const Register r2  = { kRegister_r2_Code };
151 const Register r3  = { kRegister_r3_Code };
152 const Register r4  = { kRegister_r4_Code };
153 const Register r5  = { kRegister_r5_Code };
154 const Register r6  = { kRegister_r6_Code };
155 const Register r7  = { kRegister_r7_Code };
156 // Used as context register.
157 const Register r8  = { kRegister_r8_Code };
158 // Used as lithium codegen scratch register.
159 const Register r9  = { kRegister_r9_Code };
160 // Used as roots register.
161 const Register r10 = { kRegister_r10_Code };
162 const Register fp  = { kRegister_fp_Code };
163 const Register ip  = { kRegister_ip_Code };
164 const Register sp  = { kRegister_sp_Code };
165 const Register lr  = { kRegister_lr_Code };
166 const Register pc  = { kRegister_pc_Code };
167 
168 
169 // Single word VFP register.
170 struct SwVfpRegister {
is_validSwVfpRegister171   bool is_valid() const { return 0 <= code_ && code_ < 32; }
isSwVfpRegister172   bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
codeSwVfpRegister173   int code() const {
174     ASSERT(is_valid());
175     return code_;
176   }
bitSwVfpRegister177   int bit() const {
178     ASSERT(is_valid());
179     return 1 << code_;
180   }
split_codeSwVfpRegister181   void split_code(int* vm, int* m) const {
182     ASSERT(is_valid());
183     *m = code_ & 0x1;
184     *vm = code_ >> 1;
185   }
186 
187   int code_;
188 };
189 
190 
191 // Double word VFP register.
192 struct DwVfpRegister {
193   static const int kNumRegisters = 16;
194   // A few double registers are reserved: one as a scratch register and one to
195   // hold 0.0, that does not fit in the immediate field of vmov instructions.
196   //  d14: 0.0
197   //  d15: scratch register.
198   static const int kNumReservedRegisters = 2;
199   static const int kNumAllocatableRegisters = kNumRegisters -
200       kNumReservedRegisters;
201 
202   inline static int ToAllocationIndex(DwVfpRegister reg);
203 
FromAllocationIndexDwVfpRegister204   static DwVfpRegister FromAllocationIndex(int index) {
205     ASSERT(index >= 0 && index < kNumAllocatableRegisters);
206     return from_code(index);
207   }
208 
AllocationIndexToStringDwVfpRegister209   static const char* AllocationIndexToString(int index) {
210     ASSERT(index >= 0 && index < kNumAllocatableRegisters);
211     const char* const names[] = {
212       "d0",
213       "d1",
214       "d2",
215       "d3",
216       "d4",
217       "d5",
218       "d6",
219       "d7",
220       "d8",
221       "d9",
222       "d10",
223       "d11",
224       "d12",
225       "d13"
226     };
227     return names[index];
228   }
229 
from_codeDwVfpRegister230   static DwVfpRegister from_code(int code) {
231     DwVfpRegister r = { code };
232     return r;
233   }
234 
235   // Supporting d0 to d15, can be later extended to d31.
is_validDwVfpRegister236   bool is_valid() const { return 0 <= code_ && code_ < 16; }
isDwVfpRegister237   bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
lowDwVfpRegister238   SwVfpRegister low() const {
239     SwVfpRegister reg;
240     reg.code_ = code_ * 2;
241 
242     ASSERT(reg.is_valid());
243     return reg;
244   }
highDwVfpRegister245   SwVfpRegister high() const {
246     SwVfpRegister reg;
247     reg.code_ = (code_ * 2) + 1;
248 
249     ASSERT(reg.is_valid());
250     return reg;
251   }
codeDwVfpRegister252   int code() const {
253     ASSERT(is_valid());
254     return code_;
255   }
bitDwVfpRegister256   int bit() const {
257     ASSERT(is_valid());
258     return 1 << code_;
259   }
split_codeDwVfpRegister260   void split_code(int* vm, int* m) const {
261     ASSERT(is_valid());
262     *m = (code_ & 0x10) >> 4;
263     *vm = code_ & 0x0F;
264   }
265 
266   int code_;
267 };
268 
269 
270 typedef DwVfpRegister DoubleRegister;
271 
272 
273 // Support for the VFP registers s0 to s31 (d0 to d15).
274 // Note that "s(N):s(N+1)" is the same as "d(N/2)".
275 const SwVfpRegister s0  = {  0 };
276 const SwVfpRegister s1  = {  1 };
277 const SwVfpRegister s2  = {  2 };
278 const SwVfpRegister s3  = {  3 };
279 const SwVfpRegister s4  = {  4 };
280 const SwVfpRegister s5  = {  5 };
281 const SwVfpRegister s6  = {  6 };
282 const SwVfpRegister s7  = {  7 };
283 const SwVfpRegister s8  = {  8 };
284 const SwVfpRegister s9  = {  9 };
285 const SwVfpRegister s10 = { 10 };
286 const SwVfpRegister s11 = { 11 };
287 const SwVfpRegister s12 = { 12 };
288 const SwVfpRegister s13 = { 13 };
289 const SwVfpRegister s14 = { 14 };
290 const SwVfpRegister s15 = { 15 };
291 const SwVfpRegister s16 = { 16 };
292 const SwVfpRegister s17 = { 17 };
293 const SwVfpRegister s18 = { 18 };
294 const SwVfpRegister s19 = { 19 };
295 const SwVfpRegister s20 = { 20 };
296 const SwVfpRegister s21 = { 21 };
297 const SwVfpRegister s22 = { 22 };
298 const SwVfpRegister s23 = { 23 };
299 const SwVfpRegister s24 = { 24 };
300 const SwVfpRegister s25 = { 25 };
301 const SwVfpRegister s26 = { 26 };
302 const SwVfpRegister s27 = { 27 };
303 const SwVfpRegister s28 = { 28 };
304 const SwVfpRegister s29 = { 29 };
305 const SwVfpRegister s30 = { 30 };
306 const SwVfpRegister s31 = { 31 };
307 
308 const DwVfpRegister no_dreg = { -1 };
309 const DwVfpRegister d0  = {  0 };
310 const DwVfpRegister d1  = {  1 };
311 const DwVfpRegister d2  = {  2 };
312 const DwVfpRegister d3  = {  3 };
313 const DwVfpRegister d4  = {  4 };
314 const DwVfpRegister d5  = {  5 };
315 const DwVfpRegister d6  = {  6 };
316 const DwVfpRegister d7  = {  7 };
317 const DwVfpRegister d8  = {  8 };
318 const DwVfpRegister d9  = {  9 };
319 const DwVfpRegister d10 = { 10 };
320 const DwVfpRegister d11 = { 11 };
321 const DwVfpRegister d12 = { 12 };
322 const DwVfpRegister d13 = { 13 };
323 const DwVfpRegister d14 = { 14 };
324 const DwVfpRegister d15 = { 15 };
325 
326 // Aliases for double registers.  Defined using #define instead of
327 // "static const DwVfpRegister&" because Clang complains otherwise when a
328 // compilation unit that includes this header doesn't use the variables.
329 #define kFirstCalleeSavedDoubleReg d8
330 #define kLastCalleeSavedDoubleReg d15
331 #define kDoubleRegZero d14
332 #define kScratchDoubleReg d15
333 
334 
335 // Coprocessor register
336 struct CRegister {
is_validCRegister337   bool is_valid() const { return 0 <= code_ && code_ < 16; }
isCRegister338   bool is(CRegister creg) const { return code_ == creg.code_; }
codeCRegister339   int code() const {
340     ASSERT(is_valid());
341     return code_;
342   }
bitCRegister343   int bit() const {
344     ASSERT(is_valid());
345     return 1 << code_;
346   }
347 
348   // Unfortunately we can't make this private in a struct.
349   int code_;
350 };
351 
352 
353 const CRegister no_creg = { -1 };
354 
355 const CRegister cr0  = {  0 };
356 const CRegister cr1  = {  1 };
357 const CRegister cr2  = {  2 };
358 const CRegister cr3  = {  3 };
359 const CRegister cr4  = {  4 };
360 const CRegister cr5  = {  5 };
361 const CRegister cr6  = {  6 };
362 const CRegister cr7  = {  7 };
363 const CRegister cr8  = {  8 };
364 const CRegister cr9  = {  9 };
365 const CRegister cr10 = { 10 };
366 const CRegister cr11 = { 11 };
367 const CRegister cr12 = { 12 };
368 const CRegister cr13 = { 13 };
369 const CRegister cr14 = { 14 };
370 const CRegister cr15 = { 15 };
371 
372 
373 // Coprocessor number
374 enum Coprocessor {
375   p0  = 0,
376   p1  = 1,
377   p2  = 2,
378   p3  = 3,
379   p4  = 4,
380   p5  = 5,
381   p6  = 6,
382   p7  = 7,
383   p8  = 8,
384   p9  = 9,
385   p10 = 10,
386   p11 = 11,
387   p12 = 12,
388   p13 = 13,
389   p14 = 14,
390   p15 = 15
391 };
392 
393 
394 // -----------------------------------------------------------------------------
395 // Machine instruction Operands
396 
397 // Class Operand represents a shifter operand in data processing instructions
398 class Operand BASE_EMBEDDED {
399  public:
400   // immediate
401   INLINE(explicit Operand(int32_t immediate,
402          RelocInfo::Mode rmode = RelocInfo::NONE));
INLINE(static Operand Zero ())403   INLINE(static Operand Zero()) {
404     return Operand(static_cast<int32_t>(0));
405   }
406   INLINE(explicit Operand(const ExternalReference& f));
407   explicit Operand(Handle<Object> handle);
408   INLINE(explicit Operand(Smi* value));
409 
410   // rm
411   INLINE(explicit Operand(Register rm));
412 
413   // rm <shift_op> shift_imm
414   explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
415 
416   // rm <shift_op> rs
417   explicit Operand(Register rm, ShiftOp shift_op, Register rs);
418 
419   // Return true if this is a register operand.
420   INLINE(bool is_reg() const);
421 
422   // Return true if this operand fits in one instruction so that no
423   // 2-instruction solution with a load into the ip register is necessary. If
424   // the instruction this operand is used for is a MOV or MVN instruction the
425   // actual instruction to use is required for this calculation. For other
426   // instructions instr is ignored.
427   bool is_single_instruction(Instr instr = 0) const;
428   bool must_use_constant_pool() const;
429 
immediate()430   inline int32_t immediate() const {
431     ASSERT(!rm_.is_valid());
432     return imm32_;
433   }
434 
rm()435   Register rm() const { return rm_; }
rs()436   Register rs() const { return rs_; }
shift_op()437   ShiftOp shift_op() const { return shift_op_; }
438 
439  private:
440   Register rm_;
441   Register rs_;
442   ShiftOp shift_op_;
443   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
444   int32_t imm32_;  // valid if rm_ == no_reg
445   RelocInfo::Mode rmode_;
446 
447   friend class Assembler;
448 };
449 
450 
451 // Class MemOperand represents a memory operand in load and store instructions
452 class MemOperand BASE_EMBEDDED {
453  public:
454   // [rn +/- offset]      Offset/NegOffset
455   // [rn +/- offset]!     PreIndex/NegPreIndex
456   // [rn], +/- offset     PostIndex/NegPostIndex
457   // offset is any signed 32-bit value; offset is first loaded to register ip if
458   // it does not fit the addressing mode (12-bit unsigned and sign bit)
459   explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
460 
461   // [rn +/- rm]          Offset/NegOffset
462   // [rn +/- rm]!         PreIndex/NegPreIndex
463   // [rn], +/- rm         PostIndex/NegPostIndex
464   explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
465 
466   // [rn +/- rm <shift_op> shift_imm]      Offset/NegOffset
467   // [rn +/- rm <shift_op> shift_imm]!     PreIndex/NegPreIndex
468   // [rn], +/- rm <shift_op> shift_imm     PostIndex/NegPostIndex
469   explicit MemOperand(Register rn, Register rm,
470                       ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
471 
set_offset(int32_t offset)472   void set_offset(int32_t offset) {
473       ASSERT(rm_.is(no_reg));
474       offset_ = offset;
475   }
476 
offset()477   uint32_t offset() const {
478       ASSERT(rm_.is(no_reg));
479       return offset_;
480   }
481 
rn()482   Register rn() const { return rn_; }
rm()483   Register rm() const { return rm_; }
am()484   AddrMode am() const { return am_; }
485 
OffsetIsUint12Encodable()486   bool OffsetIsUint12Encodable() const {
487     return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
488   }
489 
490  private:
491   Register rn_;  // base
492   Register rm_;  // register offset
493   int32_t offset_;  // valid if rm_ == no_reg
494   ShiftOp shift_op_;
495   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
496   AddrMode am_;  // bits P, U, and W
497 
498   friend class Assembler;
499 };
500 
501 // CpuFeatures keeps track of which features are supported by the target CPU.
502 // Supported features must be enabled by a Scope before use.
503 class CpuFeatures : public AllStatic {
504  public:
505   // Detect features of the target CPU. Set safe defaults if the serializer
506   // is enabled (snapshots must be portable).
507   static void Probe();
508 
509   // Check whether a feature is supported by the target CPU.
IsSupported(CpuFeature f)510   static bool IsSupported(CpuFeature f) {
511     ASSERT(initialized_);
512     if (f == VFP3 && !FLAG_enable_vfp3) return false;
513     return (supported_ & (1u << f)) != 0;
514   }
515 
516 #ifdef DEBUG
517   // Check whether a feature is currently enabled.
IsEnabled(CpuFeature f)518   static bool IsEnabled(CpuFeature f) {
519     ASSERT(initialized_);
520     Isolate* isolate = Isolate::UncheckedCurrent();
521     if (isolate == NULL) {
522       // When no isolate is available, work as if we're running in
523       // release mode.
524       return IsSupported(f);
525     }
526     unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
527     return (enabled & (1u << f)) != 0;
528   }
529 #endif
530 
531   // Enable a specified feature within a scope.
532   class Scope BASE_EMBEDDED {
533 #ifdef DEBUG
534 
535    public:
Scope(CpuFeature f)536     explicit Scope(CpuFeature f) {
537       unsigned mask = 1u << f;
538       ASSERT(CpuFeatures::IsSupported(f));
539       ASSERT(!Serializer::enabled() ||
540              (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
541       isolate_ = Isolate::UncheckedCurrent();
542       old_enabled_ = 0;
543       if (isolate_ != NULL) {
544         old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
545         isolate_->set_enabled_cpu_features(old_enabled_ | mask);
546       }
547     }
~Scope()548     ~Scope() {
549       ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
550       if (isolate_ != NULL) {
551         isolate_->set_enabled_cpu_features(old_enabled_);
552       }
553     }
554 
555    private:
556     Isolate* isolate_;
557     unsigned old_enabled_;
558 #else
559 
560    public:
561     explicit Scope(CpuFeature f) {}
562 #endif
563   };
564 
565   class TryForceFeatureScope BASE_EMBEDDED {
566    public:
TryForceFeatureScope(CpuFeature f)567     explicit TryForceFeatureScope(CpuFeature f)
568         : old_supported_(CpuFeatures::supported_) {
569       if (CanForce()) {
570         CpuFeatures::supported_ |= (1u << f);
571       }
572     }
573 
~TryForceFeatureScope()574     ~TryForceFeatureScope() {
575       if (CanForce()) {
576         CpuFeatures::supported_ = old_supported_;
577       }
578     }
579 
580    private:
CanForce()581     static bool CanForce() {
582       // It's only safe to temporarily force support of CPU features
583       // when there's only a single isolate, which is guaranteed when
584       // the serializer is enabled.
585       return Serializer::enabled();
586     }
587 
588     const unsigned old_supported_;
589   };
590 
591  private:
592 #ifdef DEBUG
593   static bool initialized_;
594 #endif
595   static unsigned supported_;
596   static unsigned found_by_runtime_probing_;
597 
598   DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
599 };
600 
601 
602 extern const Instr kMovLrPc;
603 extern const Instr kLdrPCMask;
604 extern const Instr kLdrPCPattern;
605 extern const Instr kBlxRegMask;
606 extern const Instr kBlxRegPattern;
607 extern const Instr kBlxIp;
608 
609 extern const Instr kMovMvnMask;
610 extern const Instr kMovMvnPattern;
611 extern const Instr kMovMvnFlip;
612 
613 extern const Instr kMovLeaveCCMask;
614 extern const Instr kMovLeaveCCPattern;
615 extern const Instr kMovwMask;
616 extern const Instr kMovwPattern;
617 extern const Instr kMovwLeaveCCFlip;
618 
619 extern const Instr kCmpCmnMask;
620 extern const Instr kCmpCmnPattern;
621 extern const Instr kCmpCmnFlip;
622 extern const Instr kAddSubFlip;
623 extern const Instr kAndBicFlip;
624 
625 
626 
627 class Assembler : public AssemblerBase {
628  public:
629   // Create an assembler. Instructions and relocation information are emitted
630   // into a buffer, with the instructions starting from the beginning and the
631   // relocation information starting from the end of the buffer. See CodeDesc
632   // for a detailed comment on the layout (globals.h).
633   //
634   // If the provided buffer is NULL, the assembler allocates and grows its own
635   // buffer, and buffer_size determines the initial buffer size. The buffer is
636   // owned by the assembler and deallocated upon destruction of the assembler.
637   //
638   // If the provided buffer is not NULL, the assembler uses the provided buffer
639   // for code generation and assumes its size to be buffer_size. If the buffer
640   // is too small, a fatal error occurs. No deallocation of the buffer is done
641   // upon destruction of the assembler.
642   Assembler(Isolate* isolate, void* buffer, int buffer_size);
643   ~Assembler();
644 
645   // Overrides the default provided by FLAG_debug_code.
set_emit_debug_code(bool value)646   void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
647 
648   // GetCode emits any pending (non-emitted) code and fills the descriptor
649   // desc. GetCode() is idempotent; it returns the same result if no other
650   // Assembler functions are invoked in between GetCode() calls.
651   void GetCode(CodeDesc* desc);
652 
653   // Label operations & relative jumps (PPUM Appendix D)
654   //
655   // Takes a branch opcode (cc) and a label (L) and generates
656   // either a backward branch or a forward branch and links it
657   // to the label fixup chain. Usage:
658   //
659   // Label L;    // unbound label
660   // j(cc, &L);  // forward branch to unbound label
661   // bind(&L);   // bind label to the current pc
662   // j(cc, &L);  // backward branch to bound label
663   // bind(&L);   // illegal: a label may be bound only once
664   //
665   // Note: The same Label can be used for forward and backward branches
666   // but it may be bound only once.
667 
668   void bind(Label* L);  // binds an unbound label L to the current code position
669 
670   // Returns the branch offset to the given label from the current code position
671   // Links the label to the current position if it is still unbound
672   // Manages the jump elimination optimization if the second parameter is true.
673   int branch_offset(Label* L, bool jump_elimination_allowed);
674 
675   // Puts a labels target address at the given position.
676   // The high 8 bits are set to zero.
677   void label_at_put(Label* L, int at_offset);
678 
679   // Return the address in the constant pool of the code target address used by
680   // the branch/call instruction at pc.
681   INLINE(static Address target_address_address_at(Address pc));
682 
683   // Read/Modify the code target address in the branch/call instruction at pc.
684   INLINE(static Address target_address_at(Address pc));
685   INLINE(static void set_target_address_at(Address pc, Address target));
686 
687   // This sets the branch destination (which is in the constant pool on ARM).
688   // This is for calls and branches within generated code.
689   inline static void deserialization_set_special_target_at(
690       Address constant_pool_entry, Address target);
691 
692   // This sets the branch destination (which is in the constant pool on ARM).
693   // This is for calls and branches to runtime code.
694   inline static void set_external_target_at(Address constant_pool_entry,
695                                             Address target);
696 
697   // Here we are patching the address in the constant pool, not the actual call
698   // instruction.  The address in the constant pool is the same size as a
699   // pointer.
700   static const int kSpecialTargetSize = kPointerSize;
701 
702   // Size of an instruction.
703   static const int kInstrSize = sizeof(Instr);
704 
705   // Distance between the instruction referring to the address of the call
706   // target and the return address.
707 #ifdef USE_BLX
708   // Call sequence is:
709   //  ldr  ip, [pc, #...] @ call address
710   //  blx  ip
711   //                      @ return address
712   static const int kCallTargetAddressOffset = 2 * kInstrSize;
713 #else
714   // Call sequence is:
715   //  mov  lr, pc
716   //  ldr  pc, [pc, #...] @ call address
717   //                      @ return address
718   static const int kCallTargetAddressOffset = kInstrSize;
719 #endif
720 
721   // Distance between start of patched return sequence and the emitted address
722   // to jump to.
723 #ifdef USE_BLX
724   // Patched return sequence is:
725   //  ldr  ip, [pc, #0]   @ emited address and start
726   //  blx  ip
727   static const int kPatchReturnSequenceAddressOffset =  0 * kInstrSize;
728 #else
729   // Patched return sequence is:
730   //  mov  lr, pc         @ start of sequence
731   //  ldr  pc, [pc, #-4]  @ emited address
732   static const int kPatchReturnSequenceAddressOffset =  kInstrSize;
733 #endif
734 
735   // Distance between start of patched debug break slot and the emitted address
736   // to jump to.
737 #ifdef USE_BLX
738   // Patched debug break slot code is:
739   //  ldr  ip, [pc, #0]   @ emited address and start
740   //  blx  ip
741   static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
742 #else
743   // Patched debug break slot code is:
744   //  mov  lr, pc         @ start of sequence
745   //  ldr  pc, [pc, #-4]  @ emited address
746   static const int kPatchDebugBreakSlotAddressOffset =  kInstrSize;
747 #endif
748 
749   // Difference between address of current opcode and value read from pc
750   // register.
751   static const int kPcLoadDelta = 8;
752 
753   static const int kJSReturnSequenceInstructions = 4;
754   static const int kDebugBreakSlotInstructions = 3;
755   static const int kDebugBreakSlotLength =
756       kDebugBreakSlotInstructions * kInstrSize;
757 
758   // ---------------------------------------------------------------------------
759   // Code generation
760 
761   // Insert the smallest number of nop instructions
762   // possible to align the pc offset to a multiple
763   // of m. m must be a power of 2 (>= 4).
764   void Align(int m);
765   // Aligns code to something that's optimal for a jump target for the platform.
766   void CodeTargetAlign();
767 
768   // Branch instructions
769   void b(int branch_offset, Condition cond = al);
770   void bl(int branch_offset, Condition cond = al);
771   void blx(int branch_offset);  // v5 and above
772   void blx(Register target, Condition cond = al);  // v5 and above
773   void bx(Register target, Condition cond = al);  // v5 and above, plus v4t
774 
775   // Convenience branch instructions using labels
776   void b(Label* L, Condition cond = al)  {
777     b(branch_offset(L, cond == al), cond);
778   }
b(Condition cond,Label * L)779   void b(Condition cond, Label* L)  { b(branch_offset(L, cond == al), cond); }
780   void bl(Label* L, Condition cond = al)  { bl(branch_offset(L, false), cond); }
bl(Condition cond,Label * L)781   void bl(Condition cond, Label* L)  { bl(branch_offset(L, false), cond); }
blx(Label * L)782   void blx(Label* L)  { blx(branch_offset(L, false)); }  // v5 and above
783 
784   // Data-processing instructions
785 
786   void and_(Register dst, Register src1, const Operand& src2,
787             SBit s = LeaveCC, Condition cond = al);
788 
789   void eor(Register dst, Register src1, const Operand& src2,
790            SBit s = LeaveCC, Condition cond = al);
791 
792   void sub(Register dst, Register src1, const Operand& src2,
793            SBit s = LeaveCC, Condition cond = al);
794   void sub(Register dst, Register src1, Register src2,
795            SBit s = LeaveCC, Condition cond = al) {
796     sub(dst, src1, Operand(src2), s, cond);
797   }
798 
799   void rsb(Register dst, Register src1, const Operand& src2,
800            SBit s = LeaveCC, Condition cond = al);
801 
802   void add(Register dst, Register src1, const Operand& src2,
803            SBit s = LeaveCC, Condition cond = al);
804   void add(Register dst, Register src1, Register src2,
805            SBit s = LeaveCC, Condition cond = al) {
806     add(dst, src1, Operand(src2), s, cond);
807   }
808 
809   void adc(Register dst, Register src1, const Operand& src2,
810            SBit s = LeaveCC, Condition cond = al);
811 
812   void sbc(Register dst, Register src1, const Operand& src2,
813            SBit s = LeaveCC, Condition cond = al);
814 
815   void rsc(Register dst, Register src1, const Operand& src2,
816            SBit s = LeaveCC, Condition cond = al);
817 
818   void tst(Register src1, const Operand& src2, Condition cond = al);
819   void tst(Register src1, Register src2, Condition cond = al) {
820     tst(src1, Operand(src2), cond);
821   }
822 
823   void teq(Register src1, const Operand& src2, Condition cond = al);
824 
825   void cmp(Register src1, const Operand& src2, Condition cond = al);
826   void cmp(Register src1, Register src2, Condition cond = al) {
827     cmp(src1, Operand(src2), cond);
828   }
829   void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
830 
831   void cmn(Register src1, const Operand& src2, Condition cond = al);
832 
833   void orr(Register dst, Register src1, const Operand& src2,
834            SBit s = LeaveCC, Condition cond = al);
835   void orr(Register dst, Register src1, Register src2,
836            SBit s = LeaveCC, Condition cond = al) {
837     orr(dst, src1, Operand(src2), s, cond);
838   }
839 
840   void mov(Register dst, const Operand& src,
841            SBit s = LeaveCC, Condition cond = al);
842   void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
843     mov(dst, Operand(src), s, cond);
844   }
845 
846   // ARMv7 instructions for loading a 32 bit immediate in two instructions.
847   // This may actually emit a different mov instruction, but on an ARMv7 it
848   // is guaranteed to only emit one instruction.
849   void movw(Register reg, uint32_t immediate, Condition cond = al);
850   // The constant for movt should be in the range 0-0xffff.
851   void movt(Register reg, uint32_t immediate, Condition cond = al);
852 
853   void bic(Register dst, Register src1, const Operand& src2,
854            SBit s = LeaveCC, Condition cond = al);
855 
856   void mvn(Register dst, const Operand& src,
857            SBit s = LeaveCC, Condition cond = al);
858 
859   // Multiply instructions
860 
861   void mla(Register dst, Register src1, Register src2, Register srcA,
862            SBit s = LeaveCC, Condition cond = al);
863 
864   void mul(Register dst, Register src1, Register src2,
865            SBit s = LeaveCC, Condition cond = al);
866 
867   void smlal(Register dstL, Register dstH, Register src1, Register src2,
868              SBit s = LeaveCC, Condition cond = al);
869 
870   void smull(Register dstL, Register dstH, Register src1, Register src2,
871              SBit s = LeaveCC, Condition cond = al);
872 
873   void umlal(Register dstL, Register dstH, Register src1, Register src2,
874              SBit s = LeaveCC, Condition cond = al);
875 
876   void umull(Register dstL, Register dstH, Register src1, Register src2,
877              SBit s = LeaveCC, Condition cond = al);
878 
879   // Miscellaneous arithmetic instructions
880 
881   void clz(Register dst, Register src, Condition cond = al);  // v5 and above
882 
883   // Saturating instructions. v6 and above.
884 
885   // Unsigned saturate.
886   //
887   // Saturate an optionally shifted signed value to an unsigned range.
888   //
889   //   usat dst, #satpos, src
890   //   usat dst, #satpos, src, lsl #sh
891   //   usat dst, #satpos, src, asr #sh
892   //
893   // Register dst will contain:
894   //
895   //   0,                 if s < 0
896   //   (1 << satpos) - 1, if s > ((1 << satpos) - 1)
897   //   s,                 otherwise
898   //
899   // where s is the contents of src after shifting (if used.)
900   void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
901 
902   // Bitfield manipulation instructions. v7 and above.
903 
904   void ubfx(Register dst, Register src, int lsb, int width,
905             Condition cond = al);
906 
907   void sbfx(Register dst, Register src, int lsb, int width,
908             Condition cond = al);
909 
910   void bfc(Register dst, int lsb, int width, Condition cond = al);
911 
912   void bfi(Register dst, Register src, int lsb, int width,
913            Condition cond = al);
914 
915   // Status register access instructions
916 
917   void mrs(Register dst, SRegister s, Condition cond = al);
918   void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
919 
920   // Load/Store instructions
921   void ldr(Register dst, const MemOperand& src, Condition cond = al);
922   void str(Register src, const MemOperand& dst, Condition cond = al);
923   void ldrb(Register dst, const MemOperand& src, Condition cond = al);
924   void strb(Register src, const MemOperand& dst, Condition cond = al);
925   void ldrh(Register dst, const MemOperand& src, Condition cond = al);
926   void strh(Register src, const MemOperand& dst, Condition cond = al);
927   void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
928   void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
929   void ldrd(Register dst1,
930             Register dst2,
931             const MemOperand& src, Condition cond = al);
932   void strd(Register src1,
933             Register src2,
934             const MemOperand& dst, Condition cond = al);
935 
936   // Load/Store multiple instructions
937   void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
938   void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
939 
940   // Exception-generating instructions and debugging support
941   void stop(const char* msg,
942             Condition cond = al,
943             int32_t code = kDefaultStopCode);
944 
945   void bkpt(uint32_t imm16);  // v5 and above
946   void svc(uint32_t imm24, Condition cond = al);
947 
948   // Coprocessor instructions
949 
950   void cdp(Coprocessor coproc, int opcode_1,
951            CRegister crd, CRegister crn, CRegister crm,
952            int opcode_2, Condition cond = al);
953 
954   void cdp2(Coprocessor coproc, int opcode_1,
955             CRegister crd, CRegister crn, CRegister crm,
956             int opcode_2);  // v5 and above
957 
958   void mcr(Coprocessor coproc, int opcode_1,
959            Register rd, CRegister crn, CRegister crm,
960            int opcode_2 = 0, Condition cond = al);
961 
962   void mcr2(Coprocessor coproc, int opcode_1,
963             Register rd, CRegister crn, CRegister crm,
964             int opcode_2 = 0);  // v5 and above
965 
966   void mrc(Coprocessor coproc, int opcode_1,
967            Register rd, CRegister crn, CRegister crm,
968            int opcode_2 = 0, Condition cond = al);
969 
970   void mrc2(Coprocessor coproc, int opcode_1,
971             Register rd, CRegister crn, CRegister crm,
972             int opcode_2 = 0);  // v5 and above
973 
974   void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
975            LFlag l = Short, Condition cond = al);
976   void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
977            LFlag l = Short, Condition cond = al);
978 
979   void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
980             LFlag l = Short);  // v5 and above
981   void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
982             LFlag l = Short);  // v5 and above
983 
984   // Support for VFP.
985   // All these APIs support S0 to S31 and D0 to D15.
986   // Currently these APIs do not support extended D registers, i.e, D16 to D31.
987   // However, some simple modifications can allow
988   // these APIs to support D16 to D31.
989 
990   void vldr(const DwVfpRegister dst,
991             const Register base,
992             int offset,
993             const Condition cond = al);
994   void vldr(const DwVfpRegister dst,
995             const MemOperand& src,
996             const Condition cond = al);
997 
998   void vldr(const SwVfpRegister dst,
999             const Register base,
1000             int offset,
1001             const Condition cond = al);
1002   void vldr(const SwVfpRegister dst,
1003             const MemOperand& src,
1004             const Condition cond = al);
1005 
1006   void vstr(const DwVfpRegister src,
1007             const Register base,
1008             int offset,
1009             const Condition cond = al);
1010   void vstr(const DwVfpRegister src,
1011             const MemOperand& dst,
1012             const Condition cond = al);
1013 
1014   void vstr(const SwVfpRegister src,
1015             const Register base,
1016             int offset,
1017             const Condition cond = al);
1018   void vstr(const SwVfpRegister src,
1019             const MemOperand& dst,
1020             const Condition cond = al);
1021 
1022   void vldm(BlockAddrMode am,
1023             Register base,
1024             DwVfpRegister first,
1025             DwVfpRegister last,
1026             Condition cond = al);
1027 
1028   void vstm(BlockAddrMode am,
1029             Register base,
1030             DwVfpRegister first,
1031             DwVfpRegister last,
1032             Condition cond = al);
1033 
1034   void vldm(BlockAddrMode am,
1035             Register base,
1036             SwVfpRegister first,
1037             SwVfpRegister last,
1038             Condition cond = al);
1039 
1040   void vstm(BlockAddrMode am,
1041             Register base,
1042             SwVfpRegister first,
1043             SwVfpRegister last,
1044             Condition cond = al);
1045 
1046   void vmov(const DwVfpRegister dst,
1047             double imm,
1048             const Condition cond = al);
1049   void vmov(const SwVfpRegister dst,
1050             const SwVfpRegister src,
1051             const Condition cond = al);
1052   void vmov(const DwVfpRegister dst,
1053             const DwVfpRegister src,
1054             const Condition cond = al);
1055   void vmov(const DwVfpRegister dst,
1056             const Register src1,
1057             const Register src2,
1058             const Condition cond = al);
1059   void vmov(const Register dst1,
1060             const Register dst2,
1061             const DwVfpRegister src,
1062             const Condition cond = al);
1063   void vmov(const SwVfpRegister dst,
1064             const Register src,
1065             const Condition cond = al);
1066   void vmov(const Register dst,
1067             const SwVfpRegister src,
1068             const Condition cond = al);
1069   void vcvt_f64_s32(const DwVfpRegister dst,
1070                     const SwVfpRegister src,
1071                     VFPConversionMode mode = kDefaultRoundToZero,
1072                     const Condition cond = al);
1073   void vcvt_f32_s32(const SwVfpRegister dst,
1074                     const SwVfpRegister src,
1075                     VFPConversionMode mode = kDefaultRoundToZero,
1076                     const Condition cond = al);
1077   void vcvt_f64_u32(const DwVfpRegister dst,
1078                     const SwVfpRegister src,
1079                     VFPConversionMode mode = kDefaultRoundToZero,
1080                     const Condition cond = al);
1081   void vcvt_s32_f64(const SwVfpRegister dst,
1082                     const DwVfpRegister src,
1083                     VFPConversionMode mode = kDefaultRoundToZero,
1084                     const Condition cond = al);
1085   void vcvt_u32_f64(const SwVfpRegister dst,
1086                     const DwVfpRegister src,
1087                     VFPConversionMode mode = kDefaultRoundToZero,
1088                     const Condition cond = al);
1089   void vcvt_f64_f32(const DwVfpRegister dst,
1090                     const SwVfpRegister src,
1091                     VFPConversionMode mode = kDefaultRoundToZero,
1092                     const Condition cond = al);
1093   void vcvt_f32_f64(const SwVfpRegister dst,
1094                     const DwVfpRegister src,
1095                     VFPConversionMode mode = kDefaultRoundToZero,
1096                     const Condition cond = al);
1097 
1098   void vneg(const DwVfpRegister dst,
1099             const DwVfpRegister src,
1100             const Condition cond = al);
1101   void vabs(const DwVfpRegister dst,
1102             const DwVfpRegister src,
1103             const Condition cond = al);
1104   void vadd(const DwVfpRegister dst,
1105             const DwVfpRegister src1,
1106             const DwVfpRegister src2,
1107             const Condition cond = al);
1108   void vsub(const DwVfpRegister dst,
1109             const DwVfpRegister src1,
1110             const DwVfpRegister src2,
1111             const Condition cond = al);
1112   void vmul(const DwVfpRegister dst,
1113             const DwVfpRegister src1,
1114             const DwVfpRegister src2,
1115             const Condition cond = al);
1116   void vdiv(const DwVfpRegister dst,
1117             const DwVfpRegister src1,
1118             const DwVfpRegister src2,
1119             const Condition cond = al);
1120   void vcmp(const DwVfpRegister src1,
1121             const DwVfpRegister src2,
1122             const Condition cond = al);
1123   void vcmp(const DwVfpRegister src1,
1124             const double src2,
1125             const Condition cond = al);
1126   void vmrs(const Register dst,
1127             const Condition cond = al);
1128   void vmsr(const Register dst,
1129             const Condition cond = al);
1130   void vsqrt(const DwVfpRegister dst,
1131              const DwVfpRegister src,
1132              const Condition cond = al);
1133 
1134   // Pseudo instructions
1135 
1136   // Different nop operations are used by the code generator to detect certain
1137   // states of the generated code.
1138   enum NopMarkerTypes {
1139     NON_MARKING_NOP = 0,
1140     DEBUG_BREAK_NOP,
1141     // IC markers.
1142     PROPERTY_ACCESS_INLINED,
1143     PROPERTY_ACCESS_INLINED_CONTEXT,
1144     PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1145     // Helper values.
1146     LAST_CODE_MARKER,
1147     FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1148   };
1149 
1150   void nop(int type = 0);   // 0 is the default non-marking type.
1151 
1152   void push(Register src, Condition cond = al) {
1153     str(src, MemOperand(sp, 4, NegPreIndex), cond);
1154   }
1155 
1156   void pop(Register dst, Condition cond = al) {
1157     ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1158   }
1159 
pop()1160   void pop() {
1161     add(sp, sp, Operand(kPointerSize));
1162   }
1163 
1164   // Jump unconditionally to given label.
jmp(Label * L)1165   void jmp(Label* L) { b(L, al); }
1166 
1167   // Check the code size generated from label to here.
SizeOfCodeGeneratedSince(Label * label)1168   int SizeOfCodeGeneratedSince(Label* label) {
1169     return pc_offset() - label->pos();
1170   }
1171 
1172   // Check the number of instructions generated from label to here.
InstructionsGeneratedSince(Label * label)1173   int InstructionsGeneratedSince(Label* label) {
1174     return SizeOfCodeGeneratedSince(label) / kInstrSize;
1175   }
1176 
1177   // Check whether an immediate fits an addressing mode 1 instruction.
1178   bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1179 
1180   // Class for scoping postponing the constant pool generation.
1181   class BlockConstPoolScope {
1182    public:
BlockConstPoolScope(Assembler * assem)1183     explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1184       assem_->StartBlockConstPool();
1185     }
~BlockConstPoolScope()1186     ~BlockConstPoolScope() {
1187       assem_->EndBlockConstPool();
1188     }
1189 
1190    private:
1191     Assembler* assem_;
1192 
1193     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1194   };
1195 
1196   // Debugging
1197 
1198   // Mark address of the ExitJSFrame code.
1199   void RecordJSReturn();
1200 
1201   // Mark address of a debug break slot.
1202   void RecordDebugBreakSlot();
1203 
1204   // Record the AST id of the CallIC being compiled, so that it can be placed
1205   // in the relocation information.
SetRecordedAstId(unsigned ast_id)1206   void SetRecordedAstId(unsigned ast_id) {
1207     ASSERT(recorded_ast_id_ == kNoASTId);
1208     recorded_ast_id_ = ast_id;
1209   }
1210 
RecordedAstId()1211   unsigned RecordedAstId() {
1212     ASSERT(recorded_ast_id_ != kNoASTId);
1213     return recorded_ast_id_;
1214   }
1215 
ClearRecordedAstId()1216   void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; }
1217 
1218   // Record a comment relocation entry that can be used by a disassembler.
1219   // Use --code-comments to enable.
1220   void RecordComment(const char* msg);
1221 
1222   // Writes a single byte or word of data in the code stream.  Used
1223   // for inline tables, e.g., jump-tables. The constant pool should be
1224   // emitted before any use of db and dd to ensure that constant pools
1225   // are not emitted as part of the tables generated.
1226   void db(uint8_t data);
1227   void dd(uint32_t data);
1228 
pc_offset()1229   int pc_offset() const { return pc_ - buffer_; }
1230 
positions_recorder()1231   PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1232 
1233   // Read/patch instructions
instr_at(int pos)1234   Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
instr_at_put(int pos,Instr instr)1235   void instr_at_put(int pos, Instr instr) {
1236     *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1237   }
instr_at(byte * pc)1238   static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
instr_at_put(byte * pc,Instr instr)1239   static void instr_at_put(byte* pc, Instr instr) {
1240     *reinterpret_cast<Instr*>(pc) = instr;
1241   }
1242   static Condition GetCondition(Instr instr);
1243   static bool IsBranch(Instr instr);
1244   static int GetBranchOffset(Instr instr);
1245   static bool IsLdrRegisterImmediate(Instr instr);
1246   static int GetLdrRegisterImmediateOffset(Instr instr);
1247   static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
1248   static bool IsStrRegisterImmediate(Instr instr);
1249   static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1250   static bool IsAddRegisterImmediate(Instr instr);
1251   static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
1252   static Register GetRd(Instr instr);
1253   static Register GetRn(Instr instr);
1254   static Register GetRm(Instr instr);
1255   static bool IsPush(Instr instr);
1256   static bool IsPop(Instr instr);
1257   static bool IsStrRegFpOffset(Instr instr);
1258   static bool IsLdrRegFpOffset(Instr instr);
1259   static bool IsStrRegFpNegOffset(Instr instr);
1260   static bool IsLdrRegFpNegOffset(Instr instr);
1261   static bool IsLdrPcImmediateOffset(Instr instr);
1262   static bool IsTstImmediate(Instr instr);
1263   static bool IsCmpRegister(Instr instr);
1264   static bool IsCmpImmediate(Instr instr);
1265   static Register GetCmpImmediateRegister(Instr instr);
1266   static int GetCmpImmediateRawImmediate(Instr instr);
1267   static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1268 
1269   // Constants in pools are accessed via pc relative addressing, which can
1270   // reach +/-4KB thereby defining a maximum distance between the instruction
1271   // and the accessed constant.
1272   static const int kMaxDistToPool = 4*KB;
1273   static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize;
1274 
1275   // Postpone the generation of the constant pool for the specified number of
1276   // instructions.
1277   void BlockConstPoolFor(int instructions);
1278 
1279   // Check if is time to emit a constant pool.
1280   void CheckConstPool(bool force_emit, bool require_jump);
1281 
1282  protected:
1283   // Relocation for a type-recording IC has the AST id added to it.  This
1284   // member variable is a way to pass the information from the call site to
1285   // the relocation info.
1286   unsigned recorded_ast_id_;
1287 
emit_debug_code()1288   bool emit_debug_code() const { return emit_debug_code_; }
1289 
buffer_space()1290   int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1291 
1292   // Decode branch instruction at pos and return branch target pos
1293   int target_at(int pos);
1294 
1295   // Patch branch instruction at pos to branch to given branch target pos
1296   void target_at_put(int pos, int target_pos);
1297 
1298   // Prevent contant pool emission until EndBlockConstPool is called.
1299   // Call to this function can be nested but must be followed by an equal
1300   // number of call to EndBlockConstpool.
StartBlockConstPool()1301   void StartBlockConstPool() {
1302     if (const_pool_blocked_nesting_++ == 0) {
1303       // Prevent constant pool checks happening by setting the next check to
1304       // the biggest possible offset.
1305       next_buffer_check_ = kMaxInt;
1306     }
1307   }
1308 
1309   // Resume constant pool emission. Need to be called as many time as
1310   // StartBlockConstPool to have an effect.
EndBlockConstPool()1311   void EndBlockConstPool() {
1312     if (--const_pool_blocked_nesting_ == 0) {
1313       // Check the constant pool hasn't been blocked for too long.
1314       ASSERT((num_pending_reloc_info_ == 0) ||
1315              (pc_offset() < (first_const_pool_use_ + kMaxDistToPool)));
1316       // Two cases:
1317       //  * no_const_pool_before_ >= next_buffer_check_ and the emission is
1318       //    still blocked
1319       //  * no_const_pool_before_ < next_buffer_check_ and the next emit will
1320       //    trigger a check.
1321       next_buffer_check_ = no_const_pool_before_;
1322     }
1323   }
1324 
is_const_pool_blocked()1325   bool is_const_pool_blocked() const {
1326     return (const_pool_blocked_nesting_ > 0) ||
1327            (pc_offset() < no_const_pool_before_);
1328   }
1329 
1330  private:
1331   // Code buffer:
1332   // The buffer into which code and relocation info are generated.
1333   byte* buffer_;
1334   int buffer_size_;
1335   // True if the assembler owns the buffer, false if buffer is external.
1336   bool own_buffer_;
1337 
1338   int next_buffer_check_;  // pc offset of next buffer check
1339 
1340   // Code generation
1341   // The relocation writer's position is at least kGap bytes below the end of
1342   // the generated instructions. This is so that multi-instruction sequences do
1343   // not have to check for overflow. The same is true for writes of large
1344   // relocation info entries.
1345   static const int kGap = 32;
1346   byte* pc_;  // the program counter; moves forward
1347 
1348   // Constant pool generation
1349   // Pools are emitted in the instruction stream, preferably after unconditional
1350   // jumps or after returns from functions (in dead code locations).
1351   // If a long code sequence does not contain unconditional jumps, it is
1352   // necessary to emit the constant pool before the pool gets too far from the
1353   // location it is accessed from. In this case, we emit a jump over the emitted
1354   // constant pool.
1355   // Constants in the pool may be addresses of functions that gets relocated;
1356   // if so, a relocation info entry is associated to the constant pool entry.
1357 
1358   // Repeated checking whether the constant pool should be emitted is rather
1359   // expensive. By default we only check again once a number of instructions
1360   // has been generated. That also means that the sizing of the buffers is not
1361   // an exact science, and that we rely on some slop to not overrun buffers.
1362   static const int kCheckPoolIntervalInst = 32;
1363   static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
1364 
1365 
1366   // Average distance beetween a constant pool and the first instruction
1367   // accessing the constant pool. Longer distance should result in less I-cache
1368   // pollution.
1369   // In practice the distance will be smaller since constant pool emission is
1370   // forced after function return and sometimes after unconditional branches.
1371   static const int kAvgDistToPool = kMaxDistToPool - kCheckPoolInterval;
1372 
1373   // Emission of the constant pool may be blocked in some code sequences.
1374   int const_pool_blocked_nesting_;  // Block emission if this is not zero.
1375   int no_const_pool_before_;  // Block emission before this pc offset.
1376 
1377   // Keep track of the first instruction requiring a constant pool entry
1378   // since the previous constant pool was emitted.
1379   int first_const_pool_use_;
1380 
1381   // Relocation info generation
1382   // Each relocation is encoded as a variable size value
1383   static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1384   RelocInfoWriter reloc_info_writer;
1385 
1386   // Relocation info records are also used during code generation as temporary
1387   // containers for constants and code target addresses until they are emitted
1388   // to the constant pool. These pending relocation info records are temporarily
1389   // stored in a separate buffer until a constant pool is emitted.
1390   // If every instruction in a long sequence is accessing the pool, we need one
1391   // pending relocation entry per instruction.
1392 
1393   // the buffer of pending relocation info
1394   RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo];
1395   // number of pending reloc info entries in the buffer
1396   int num_pending_reloc_info_;
1397 
1398   // The bound position, before this we cannot do instruction elimination.
1399   int last_bound_pos_;
1400 
1401   // Code emission
1402   inline void CheckBuffer();
1403   void GrowBuffer();
1404   inline void emit(Instr x);
1405 
1406   // Instruction generation
1407   void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1408   void addrmod2(Instr instr, Register rd, const MemOperand& x);
1409   void addrmod3(Instr instr, Register rd, const MemOperand& x);
1410   void addrmod4(Instr instr, Register rn, RegList rl);
1411   void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1412 
1413   // Labels
1414   void print(Label* L);
1415   void bind_to(Label* L, int pos);
1416   void link_to(Label* L, Label* appendix);
1417   void next(Label* L);
1418 
1419   // Record reloc info for current pc_
1420   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1421 
1422   friend class RegExpMacroAssemblerARM;
1423   friend class RelocInfo;
1424   friend class CodePatcher;
1425   friend class BlockConstPoolScope;
1426 
1427   PositionsRecorder positions_recorder_;
1428   bool emit_debug_code_;
1429   friend class PositionsRecorder;
1430   friend class EnsureSpace;
1431 };
1432 
1433 
1434 class EnsureSpace BASE_EMBEDDED {
1435  public:
EnsureSpace(Assembler * assembler)1436   explicit EnsureSpace(Assembler* assembler) {
1437     assembler->CheckBuffer();
1438   }
1439 };
1440 
1441 
1442 } }  // namespace v8::internal
1443 
1444 #endif  // V8_ARM_ASSEMBLER_ARM_H_
1445