assembler-arm.h revision 8defd9ff6930b4e24729971a61cf7469daf119be
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 2010 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 "serialize.h"
45
46namespace v8 {
47namespace internal {
48
49// CPU Registers.
50//
51// 1) We would prefer to use an enum, but enum values are assignment-
52// compatible with int, which has caused code-generation bugs.
53//
54// 2) We would prefer to use a class instead of a struct but we don't like
55// the register initialization to depend on the particular initialization
56// order (which appears to be different on OS X, Linux, and Windows for the
57// installed versions of C++ we tried). Using a struct permits C-style
58// "initialization". Also, the Register objects cannot be const as this
59// forces initialization stubs in MSVC, making us dependent on initialization
60// order.
61//
62// 3) By not using an enum, we are possibly preventing the compiler from
63// doing certain constant folds, which may significantly reduce the
64// code generated for some assembly instructions (because they boil down
65// to a few constants). If this is a problem, we could change the code
66// such that we use an enum in optimized mode, and the struct in debug
67// mode. This way we get the compile-time error checking in debug mode
68// and best performance in optimized code.
69//
70// Core register
71struct Register {
72  bool is_valid() const  { return 0 <= code_ && code_ < 16; }
73  bool is(Register reg) const  { return code_ == reg.code_; }
74  int code() const  {
75    ASSERT(is_valid());
76    return code_;
77  }
78  int bit() const  {
79    ASSERT(is_valid());
80    return 1 << code_;
81  }
82
83  void set_code(int code) {
84    code_ = code;
85    ASSERT(is_valid());
86  }
87
88  // Unfortunately we can't make this private in a struct.
89  int code_;
90};
91
92const Register no_reg = { -1 };
93
94const Register r0  = {  0 };
95const Register r1  = {  1 };
96const Register r2  = {  2 };
97const Register r3  = {  3 };
98const Register r4  = {  4 };
99const Register r5  = {  5 };
100const Register r6  = {  6 };
101const Register r7  = {  7 };
102const Register r8  = {  8 };  // Used as context register.
103const Register r9  = {  9 };
104const Register r10 = { 10 };  // Used as roots register.
105const Register fp  = { 11 };
106const Register ip  = { 12 };
107const Register sp  = { 13 };
108const Register lr  = { 14 };
109const Register pc  = { 15 };
110
111// Single word VFP register.
112struct SwVfpRegister {
113  bool is_valid() const  { return 0 <= code_ && code_ < 32; }
114  bool is(SwVfpRegister reg) const  { return code_ == reg.code_; }
115  int code() const  {
116    ASSERT(is_valid());
117    return code_;
118  }
119  int bit() const  {
120    ASSERT(is_valid());
121    return 1 << code_;
122  }
123
124  int code_;
125};
126
127
128// Double word VFP register.
129struct DwVfpRegister {
130  // Supporting d0 to d15, can be later extended to d31.
131  bool is_valid() const  { return 0 <= code_ && code_ < 16; }
132  bool is(DwVfpRegister reg) const  { return code_ == reg.code_; }
133  int code() const  {
134    ASSERT(is_valid());
135    return code_;
136  }
137  int bit() const  {
138    ASSERT(is_valid());
139    return 1 << code_;
140  }
141
142  int code_;
143};
144
145
146// Support for the VFP registers s0 to s31 (d0 to d15).
147// Note that "s(N):s(N+1)" is the same as "d(N/2)".
148const SwVfpRegister s0  = {  0 };
149const SwVfpRegister s1  = {  1 };
150const SwVfpRegister s2  = {  2 };
151const SwVfpRegister s3  = {  3 };
152const SwVfpRegister s4  = {  4 };
153const SwVfpRegister s5  = {  5 };
154const SwVfpRegister s6  = {  6 };
155const SwVfpRegister s7  = {  7 };
156const SwVfpRegister s8  = {  8 };
157const SwVfpRegister s9  = {  9 };
158const SwVfpRegister s10 = { 10 };
159const SwVfpRegister s11 = { 11 };
160const SwVfpRegister s12 = { 12 };
161const SwVfpRegister s13 = { 13 };
162const SwVfpRegister s14 = { 14 };
163const SwVfpRegister s15 = { 15 };
164const SwVfpRegister s16 = { 16 };
165const SwVfpRegister s17 = { 17 };
166const SwVfpRegister s18 = { 18 };
167const SwVfpRegister s19 = { 19 };
168const SwVfpRegister s20 = { 20 };
169const SwVfpRegister s21 = { 21 };
170const SwVfpRegister s22 = { 22 };
171const SwVfpRegister s23 = { 23 };
172const SwVfpRegister s24 = { 24 };
173const SwVfpRegister s25 = { 25 };
174const SwVfpRegister s26 = { 26 };
175const SwVfpRegister s27 = { 27 };
176const SwVfpRegister s28 = { 28 };
177const SwVfpRegister s29 = { 29 };
178const SwVfpRegister s30 = { 30 };
179const SwVfpRegister s31 = { 31 };
180
181const DwVfpRegister d0  = {  0 };
182const DwVfpRegister d1  = {  1 };
183const DwVfpRegister d2  = {  2 };
184const DwVfpRegister d3  = {  3 };
185const DwVfpRegister d4  = {  4 };
186const DwVfpRegister d5  = {  5 };
187const DwVfpRegister d6  = {  6 };
188const DwVfpRegister d7  = {  7 };
189const DwVfpRegister d8  = {  8 };
190const DwVfpRegister d9  = {  9 };
191const DwVfpRegister d10 = { 10 };
192const DwVfpRegister d11 = { 11 };
193const DwVfpRegister d12 = { 12 };
194const DwVfpRegister d13 = { 13 };
195const DwVfpRegister d14 = { 14 };
196const DwVfpRegister d15 = { 15 };
197
198
199// Coprocessor register
200struct CRegister {
201  bool is_valid() const  { return 0 <= code_ && code_ < 16; }
202  bool is(CRegister creg) const  { return code_ == creg.code_; }
203  int code() const  {
204    ASSERT(is_valid());
205    return code_;
206  }
207  int bit() const  {
208    ASSERT(is_valid());
209    return 1 << code_;
210  }
211
212  // Unfortunately we can't make this private in a struct.
213  int code_;
214};
215
216
217const CRegister no_creg = { -1 };
218
219const CRegister cr0  = {  0 };
220const CRegister cr1  = {  1 };
221const CRegister cr2  = {  2 };
222const CRegister cr3  = {  3 };
223const CRegister cr4  = {  4 };
224const CRegister cr5  = {  5 };
225const CRegister cr6  = {  6 };
226const CRegister cr7  = {  7 };
227const CRegister cr8  = {  8 };
228const CRegister cr9  = {  9 };
229const CRegister cr10 = { 10 };
230const CRegister cr11 = { 11 };
231const CRegister cr12 = { 12 };
232const CRegister cr13 = { 13 };
233const CRegister cr14 = { 14 };
234const CRegister cr15 = { 15 };
235
236
237// Coprocessor number
238enum Coprocessor {
239  p0  = 0,
240  p1  = 1,
241  p2  = 2,
242  p3  = 3,
243  p4  = 4,
244  p5  = 5,
245  p6  = 6,
246  p7  = 7,
247  p8  = 8,
248  p9  = 9,
249  p10 = 10,
250  p11 = 11,
251  p12 = 12,
252  p13 = 13,
253  p14 = 14,
254  p15 = 15
255};
256
257
258// Condition field in instructions.
259enum Condition {
260  eq =  0 << 28,  // Z set            equal.
261  ne =  1 << 28,  // Z clear          not equal.
262  nz =  1 << 28,  // Z clear          not zero.
263  cs =  2 << 28,  // C set            carry set.
264  hs =  2 << 28,  // C set            unsigned higher or same.
265  cc =  3 << 28,  // C clear          carry clear.
266  lo =  3 << 28,  // C clear          unsigned lower.
267  mi =  4 << 28,  // N set            negative.
268  pl =  5 << 28,  // N clear          positive or zero.
269  vs =  6 << 28,  // V set            overflow.
270  vc =  7 << 28,  // V clear          no overflow.
271  hi =  8 << 28,  // C set, Z clear   unsigned higher.
272  ls =  9 << 28,  // C clear or Z set unsigned lower or same.
273  ge = 10 << 28,  // N == V           greater or equal.
274  lt = 11 << 28,  // N != V           less than.
275  gt = 12 << 28,  // Z clear, N == V  greater than.
276  le = 13 << 28,  // Z set or N != V  less then or equal
277  al = 14 << 28   //                  always.
278};
279
280
281// Returns the equivalent of !cc.
282inline Condition NegateCondition(Condition cc) {
283  ASSERT(cc != al);
284  return static_cast<Condition>(cc ^ ne);
285}
286
287
288// Corresponds to transposing the operands of a comparison.
289inline Condition ReverseCondition(Condition cc) {
290  switch (cc) {
291    case lo:
292      return hi;
293    case hi:
294      return lo;
295    case hs:
296      return ls;
297    case ls:
298      return hs;
299    case lt:
300      return gt;
301    case gt:
302      return lt;
303    case ge:
304      return le;
305    case le:
306      return ge;
307    default:
308      return cc;
309  };
310}
311
312
313// Branch hints are not used on the ARM.  They are defined so that they can
314// appear in shared function signatures, but will be ignored in ARM
315// implementations.
316enum Hint { no_hint };
317
318// Hints are not used on the arm.  Negating is trivial.
319inline Hint NegateHint(Hint ignored) { return no_hint; }
320
321
322// -----------------------------------------------------------------------------
323// Addressing modes and instruction variants
324
325// Shifter operand shift operation
326enum ShiftOp {
327  LSL = 0 << 5,
328  LSR = 1 << 5,
329  ASR = 2 << 5,
330  ROR = 3 << 5,
331  RRX = -1
332};
333
334
335// Condition code updating mode
336enum SBit {
337  SetCC   = 1 << 20,  // set condition code
338  LeaveCC = 0 << 20   // leave condition code unchanged
339};
340
341
342// Status register selection
343enum SRegister {
344  CPSR = 0 << 22,
345  SPSR = 1 << 22
346};
347
348
349// Status register fields
350enum SRegisterField {
351  CPSR_c = CPSR | 1 << 16,
352  CPSR_x = CPSR | 1 << 17,
353  CPSR_s = CPSR | 1 << 18,
354  CPSR_f = CPSR | 1 << 19,
355  SPSR_c = SPSR | 1 << 16,
356  SPSR_x = SPSR | 1 << 17,
357  SPSR_s = SPSR | 1 << 18,
358  SPSR_f = SPSR | 1 << 19
359};
360
361// Status register field mask (or'ed SRegisterField enum values)
362typedef uint32_t SRegisterFieldMask;
363
364
365// Memory operand addressing mode
366enum AddrMode {
367  // bit encoding P U W
368  Offset       = (8|4|0) << 21,  // offset (without writeback to base)
369  PreIndex     = (8|4|1) << 21,  // pre-indexed addressing with writeback
370  PostIndex    = (0|4|0) << 21,  // post-indexed addressing with writeback
371  NegOffset    = (8|0|0) << 21,  // negative offset (without writeback to base)
372  NegPreIndex  = (8|0|1) << 21,  // negative pre-indexed with writeback
373  NegPostIndex = (0|0|0) << 21   // negative post-indexed with writeback
374};
375
376
377// Load/store multiple addressing mode
378enum BlockAddrMode {
379  // bit encoding P U W
380  da           = (0|0|0) << 21,  // decrement after
381  ia           = (0|4|0) << 21,  // increment after
382  db           = (8|0|0) << 21,  // decrement before
383  ib           = (8|4|0) << 21,  // increment before
384  da_w         = (0|0|1) << 21,  // decrement after with writeback to base
385  ia_w         = (0|4|1) << 21,  // increment after with writeback to base
386  db_w         = (8|0|1) << 21,  // decrement before with writeback to base
387  ib_w         = (8|4|1) << 21   // increment before with writeback to base
388};
389
390
391// Coprocessor load/store operand size
392enum LFlag {
393  Long  = 1 << 22,  // long load/store coprocessor
394  Short = 0 << 22   // short load/store coprocessor
395};
396
397
398// -----------------------------------------------------------------------------
399// Machine instruction Operands
400
401// Class Operand represents a shifter operand in data processing instructions
402class Operand BASE_EMBEDDED {
403 public:
404  // immediate
405  INLINE(explicit Operand(int32_t immediate,
406         RelocInfo::Mode rmode = RelocInfo::NONE));
407  INLINE(explicit Operand(const ExternalReference& f));
408  INLINE(explicit Operand(const char* s));
409  explicit Operand(Handle<Object> handle);
410  INLINE(explicit Operand(Smi* value));
411
412  // rm
413  INLINE(explicit Operand(Register rm));
414
415  // rm <shift_op> shift_imm
416  explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
417
418  // rm <shift_op> rs
419  explicit Operand(Register rm, ShiftOp shift_op, Register rs);
420
421  // Return true if this is a register operand.
422  INLINE(bool is_reg() const);
423
424  // Return true of this operand fits in one instruction so that no
425  // 2-instruction solution with a load into the ip register is necessary.
426  bool is_single_instruction() const;
427
428  inline int32_t immediate() const {
429    ASSERT(!rm_.is_valid());
430    return imm32_;
431  }
432
433  Register rm() const { return rm_; }
434
435 private:
436  Register rm_;
437  Register rs_;
438  ShiftOp shift_op_;
439  int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
440  int32_t imm32_;  // valid if rm_ == no_reg
441  RelocInfo::Mode rmode_;
442
443  friend class Assembler;
444};
445
446
447// Class MemOperand represents a memory operand in load and store instructions
448class MemOperand BASE_EMBEDDED {
449 public:
450  // [rn +/- offset]      Offset/NegOffset
451  // [rn +/- offset]!     PreIndex/NegPreIndex
452  // [rn], +/- offset     PostIndex/NegPostIndex
453  // offset is any signed 32-bit value; offset is first loaded to register ip if
454  // it does not fit the addressing mode (12-bit unsigned and sign bit)
455  explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
456
457  // [rn +/- rm]          Offset/NegOffset
458  // [rn +/- rm]!         PreIndex/NegPreIndex
459  // [rn], +/- rm         PostIndex/NegPostIndex
460  explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
461
462  // [rn +/- rm <shift_op> shift_imm]      Offset/NegOffset
463  // [rn +/- rm <shift_op> shift_imm]!     PreIndex/NegPreIndex
464  // [rn], +/- rm <shift_op> shift_imm     PostIndex/NegPostIndex
465  explicit MemOperand(Register rn, Register rm,
466                      ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
467
468  void set_offset(int32_t offset) {
469      ASSERT(rm_.is(no_reg));
470      offset_ = offset;
471  }
472
473  uint32_t offset() {
474      ASSERT(rm_.is(no_reg));
475      return offset_;
476  }
477
478  Register rn() const { return rn_; }
479  Register rm() const { return rm_; }
480
481 private:
482  Register rn_;  // base
483  Register rm_;  // register offset
484  int32_t offset_;  // valid if rm_ == no_reg
485  ShiftOp shift_op_;
486  int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
487  AddrMode am_;  // bits P, U, and W
488
489  friend class Assembler;
490};
491
492// CpuFeatures keeps track of which features are supported by the target CPU.
493// Supported features must be enabled by a Scope before use.
494class CpuFeatures : public AllStatic {
495 public:
496  // Detect features of the target CPU. Set safe defaults if the serializer
497  // is enabled (snapshots must be portable).
498  static void Probe();
499
500  // Check whether a feature is supported by the target CPU.
501  static bool IsSupported(CpuFeature f) {
502    if (f == VFP3 && !FLAG_enable_vfp3) return false;
503    return (supported_ & (1u << f)) != 0;
504  }
505
506  // Check whether a feature is currently enabled.
507  static bool IsEnabled(CpuFeature f) {
508    return (enabled_ & (1u << f)) != 0;
509  }
510
511  // Enable a specified feature within a scope.
512  class Scope BASE_EMBEDDED {
513#ifdef DEBUG
514   public:
515    explicit Scope(CpuFeature f) {
516      ASSERT(CpuFeatures::IsSupported(f));
517      ASSERT(!Serializer::enabled() ||
518             (found_by_runtime_probing_ & (1u << f)) == 0);
519      old_enabled_ = CpuFeatures::enabled_;
520      CpuFeatures::enabled_ |= 1u << f;
521    }
522    ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
523   private:
524    unsigned old_enabled_;
525#else
526   public:
527    explicit Scope(CpuFeature f) {}
528#endif
529  };
530
531 private:
532  static unsigned supported_;
533  static unsigned enabled_;
534  static unsigned found_by_runtime_probing_;
535};
536
537
538typedef int32_t Instr;
539
540
541extern const Instr kMovLrPc;
542extern const Instr kLdrPCMask;
543extern const Instr kLdrPCPattern;
544extern const Instr kBlxRegMask;
545extern const Instr kBlxRegPattern;
546
547extern const Instr kMovMvnMask;
548extern const Instr kMovMvnPattern;
549extern const Instr kMovMvnFlip;
550
551extern const Instr kMovLeaveCCMask;
552extern const Instr kMovLeaveCCPattern;
553extern const Instr kMovwMask;
554extern const Instr kMovwPattern;
555extern const Instr kMovwLeaveCCFlip;
556
557extern const Instr kCmpCmnMask;
558extern const Instr kCmpCmnPattern;
559extern const Instr kCmpCmnFlip;
560
561extern const Instr kALUMask;
562extern const Instr kAddPattern;
563extern const Instr kSubPattern;
564extern const Instr kAndPattern;
565extern const Instr kBicPattern;
566extern const Instr kAddSubFlip;
567extern const Instr kAndBicFlip;
568
569class Assembler : public Malloced {
570 public:
571  // Create an assembler. Instructions and relocation information are emitted
572  // into a buffer, with the instructions starting from the beginning and the
573  // relocation information starting from the end of the buffer. See CodeDesc
574  // for a detailed comment on the layout (globals.h).
575  //
576  // If the provided buffer is NULL, the assembler allocates and grows its own
577  // buffer, and buffer_size determines the initial buffer size. The buffer is
578  // owned by the assembler and deallocated upon destruction of the assembler.
579  //
580  // If the provided buffer is not NULL, the assembler uses the provided buffer
581  // for code generation and assumes its size to be buffer_size. If the buffer
582  // is too small, a fatal error occurs. No deallocation of the buffer is done
583  // upon destruction of the assembler.
584  Assembler(void* buffer, int buffer_size);
585  ~Assembler();
586
587  // GetCode emits any pending (non-emitted) code and fills the descriptor
588  // desc. GetCode() is idempotent; it returns the same result if no other
589  // Assembler functions are invoked in between GetCode() calls.
590  void GetCode(CodeDesc* desc);
591
592  // Label operations & relative jumps (PPUM Appendix D)
593  //
594  // Takes a branch opcode (cc) and a label (L) and generates
595  // either a backward branch or a forward branch and links it
596  // to the label fixup chain. Usage:
597  //
598  // Label L;    // unbound label
599  // j(cc, &L);  // forward branch to unbound label
600  // bind(&L);   // bind label to the current pc
601  // j(cc, &L);  // backward branch to bound label
602  // bind(&L);   // illegal: a label may be bound only once
603  //
604  // Note: The same Label can be used for forward and backward branches
605  // but it may be bound only once.
606
607  void bind(Label* L);  // binds an unbound label L to the current code position
608
609  // Returns the branch offset to the given label from the current code position
610  // Links the label to the current position if it is still unbound
611  // Manages the jump elimination optimization if the second parameter is true.
612  int branch_offset(Label* L, bool jump_elimination_allowed);
613
614  // Puts a labels target address at the given position.
615  // The high 8 bits are set to zero.
616  void label_at_put(Label* L, int at_offset);
617
618  // Return the address in the constant pool of the code target address used by
619  // the branch/call instruction at pc.
620  INLINE(static Address target_address_address_at(Address pc));
621
622  // Read/Modify the code target address in the branch/call instruction at pc.
623  INLINE(static Address target_address_at(Address pc));
624  INLINE(static void set_target_address_at(Address pc, Address target));
625
626  // This sets the branch destination (which is in the constant pool on ARM).
627  // This is for calls and branches within generated code.
628  inline static void set_target_at(Address constant_pool_entry, Address target);
629
630  // This sets the branch destination (which is in the constant pool on ARM).
631  // This is for calls and branches to runtime code.
632  inline static void set_external_target_at(Address constant_pool_entry,
633                                            Address target) {
634    set_target_at(constant_pool_entry, target);
635  }
636
637  // Here we are patching the address in the constant pool, not the actual call
638  // instruction.  The address in the constant pool is the same size as a
639  // pointer.
640  static const int kCallTargetSize = kPointerSize;
641  static const int kExternalTargetSize = kPointerSize;
642
643  // Size of an instruction.
644  static const int kInstrSize = sizeof(Instr);
645
646  // Distance between the instruction referring to the address of the call
647  // target and the return address.
648#ifdef USE_BLX
649  // Call sequence is:
650  //  ldr  ip, [pc, #...] @ call address
651  //  blx  ip
652  //                      @ return address
653  static const int kCallTargetAddressOffset = 2 * kInstrSize;
654#else
655  // Call sequence is:
656  //  mov  lr, pc
657  //  ldr  pc, [pc, #...] @ call address
658  //                      @ return address
659  static const int kCallTargetAddressOffset = kInstrSize;
660#endif
661
662  // Distance between start of patched return sequence and the emitted address
663  // to jump to.
664#ifdef USE_BLX
665  // Patched return sequence is:
666  //  ldr  ip, [pc, #0]   @ emited address and start
667  //  blx  ip
668  static const int kPatchReturnSequenceAddressOffset =  0 * kInstrSize;
669#else
670  // Patched return sequence is:
671  //  mov  lr, pc         @ start of sequence
672  //  ldr  pc, [pc, #-4]  @ emited address
673  static const int kPatchReturnSequenceAddressOffset =  kInstrSize;
674#endif
675
676  // Distance between start of patched debug break slot and the emitted address
677  // to jump to.
678#ifdef USE_BLX
679  // Patched debug break slot code is:
680  //  ldr  ip, [pc, #0]   @ emited address and start
681  //  blx  ip
682  static const int kPatchDebugBreakSlotAddressOffset =  0 * kInstrSize;
683#else
684  // Patched debug break slot code is:
685  //  mov  lr, pc         @ start of sequence
686  //  ldr  pc, [pc, #-4]  @ emited address
687  static const int kPatchDebugBreakSlotAddressOffset =  kInstrSize;
688#endif
689
690  // Difference between address of current opcode and value read from pc
691  // register.
692  static const int kPcLoadDelta = 8;
693
694  static const int kJSReturnSequenceInstructions = 4;
695  static const int kDebugBreakSlotInstructions = 3;
696  static const int kDebugBreakSlotLength =
697      kDebugBreakSlotInstructions * kInstrSize;
698
699  // ---------------------------------------------------------------------------
700  // Code generation
701
702  // Insert the smallest number of nop instructions
703  // possible to align the pc offset to a multiple
704  // of m. m must be a power of 2 (>= 4).
705  void Align(int m);
706  // Aligns code to something that's optimal for a jump target for the platform.
707  void CodeTargetAlign();
708
709  // Branch instructions
710  void b(int branch_offset, Condition cond = al);
711  void bl(int branch_offset, Condition cond = al);
712  void blx(int branch_offset);  // v5 and above
713  void blx(Register target, Condition cond = al);  // v5 and above
714  void bx(Register target, Condition cond = al);  // v5 and above, plus v4t
715
716  // Convenience branch instructions using labels
717  void b(Label* L, Condition cond = al)  {
718    b(branch_offset(L, cond == al), cond);
719  }
720  void b(Condition cond, Label* L)  { b(branch_offset(L, cond == al), cond); }
721  void bl(Label* L, Condition cond = al)  { bl(branch_offset(L, false), cond); }
722  void bl(Condition cond, Label* L)  { bl(branch_offset(L, false), cond); }
723  void blx(Label* L)  { blx(branch_offset(L, false)); }  // v5 and above
724
725  // Data-processing instructions
726
727  void and_(Register dst, Register src1, const Operand& src2,
728            SBit s = LeaveCC, Condition cond = al);
729
730  void eor(Register dst, Register src1, const Operand& src2,
731           SBit s = LeaveCC, Condition cond = al);
732
733  void sub(Register dst, Register src1, const Operand& src2,
734           SBit s = LeaveCC, Condition cond = al);
735  void sub(Register dst, Register src1, Register src2,
736           SBit s = LeaveCC, Condition cond = al) {
737    sub(dst, src1, Operand(src2), s, cond);
738  }
739
740  void rsb(Register dst, Register src1, const Operand& src2,
741           SBit s = LeaveCC, Condition cond = al);
742
743  void add(Register dst, Register src1, const Operand& src2,
744           SBit s = LeaveCC, Condition cond = al);
745  void add(Register dst, Register src1, Register src2,
746           SBit s = LeaveCC, Condition cond = al) {
747    add(dst, src1, Operand(src2), s, cond);
748  }
749
750  void adc(Register dst, Register src1, const Operand& src2,
751           SBit s = LeaveCC, Condition cond = al);
752
753  void sbc(Register dst, Register src1, const Operand& src2,
754           SBit s = LeaveCC, Condition cond = al);
755
756  void rsc(Register dst, Register src1, const Operand& src2,
757           SBit s = LeaveCC, Condition cond = al);
758
759  void tst(Register src1, const Operand& src2, Condition cond = al);
760  void tst(Register src1, Register src2, Condition cond = al) {
761    tst(src1, Operand(src2), cond);
762  }
763
764  void teq(Register src1, const Operand& src2, Condition cond = al);
765
766  void cmp(Register src1, const Operand& src2, Condition cond = al);
767  void cmp(Register src1, Register src2, Condition cond = al) {
768    cmp(src1, Operand(src2), cond);
769  }
770
771  void cmn(Register src1, const Operand& src2, Condition cond = al);
772
773  void orr(Register dst, Register src1, const Operand& src2,
774           SBit s = LeaveCC, Condition cond = al);
775  void orr(Register dst, Register src1, Register src2,
776           SBit s = LeaveCC, Condition cond = al) {
777    orr(dst, src1, Operand(src2), s, cond);
778  }
779
780  void mov(Register dst, const Operand& src,
781           SBit s = LeaveCC, Condition cond = al);
782  void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
783    mov(dst, Operand(src), s, cond);
784  }
785
786  // ARMv7 instructions for loading a 32 bit immediate in two instructions.
787  // This may actually emit a different mov instruction, but on an ARMv7 it
788  // is guaranteed to only emit one instruction.
789  void movw(Register reg, uint32_t immediate, Condition cond = al);
790  // The constant for movt should be in the range 0-0xffff.
791  void movt(Register reg, uint32_t immediate, Condition cond = al);
792
793  void bic(Register dst, Register src1, const Operand& src2,
794           SBit s = LeaveCC, Condition cond = al);
795
796  void mvn(Register dst, const Operand& src,
797           SBit s = LeaveCC, Condition cond = al);
798
799  // Multiply instructions
800
801  void mla(Register dst, Register src1, Register src2, Register srcA,
802           SBit s = LeaveCC, Condition cond = al);
803
804  void mul(Register dst, Register src1, Register src2,
805           SBit s = LeaveCC, Condition cond = al);
806
807  void smlal(Register dstL, Register dstH, Register src1, Register src2,
808             SBit s = LeaveCC, Condition cond = al);
809
810  void smull(Register dstL, Register dstH, Register src1, Register src2,
811             SBit s = LeaveCC, Condition cond = al);
812
813  void umlal(Register dstL, Register dstH, Register src1, Register src2,
814             SBit s = LeaveCC, Condition cond = al);
815
816  void umull(Register dstL, Register dstH, Register src1, Register src2,
817             SBit s = LeaveCC, Condition cond = al);
818
819  // Miscellaneous arithmetic instructions
820
821  void clz(Register dst, Register src, Condition cond = al);  // v5 and above
822
823  // Bitfield manipulation instructions. v7 and above.
824
825  void ubfx(Register dst, Register src, int lsb, int width,
826            Condition cond = al);
827
828  void sbfx(Register dst, Register src, int lsb, int width,
829            Condition cond = al);
830
831  void bfc(Register dst, int lsb, int width, Condition cond = al);
832
833  void bfi(Register dst, Register src, int lsb, int width,
834           Condition cond = al);
835
836  // Status register access instructions
837
838  void mrs(Register dst, SRegister s, Condition cond = al);
839  void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
840
841  // Load/Store instructions
842  void ldr(Register dst, const MemOperand& src, Condition cond = al);
843  void str(Register src, const MemOperand& dst, Condition cond = al);
844  void ldrb(Register dst, const MemOperand& src, Condition cond = al);
845  void strb(Register src, const MemOperand& dst, Condition cond = al);
846  void ldrh(Register dst, const MemOperand& src, Condition cond = al);
847  void strh(Register src, const MemOperand& dst, Condition cond = al);
848  void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
849  void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
850  void ldrd(Register dst1,
851            Register dst2,
852            const MemOperand& src, Condition cond = al);
853  void strd(Register src1,
854            Register src2,
855            const MemOperand& dst, Condition cond = al);
856
857  // Load/Store multiple instructions
858  void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
859  void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
860
861  // Exception-generating instructions and debugging support
862  void stop(const char* msg);
863
864  void bkpt(uint32_t imm16);  // v5 and above
865  void swi(uint32_t imm24, Condition cond = al);
866
867  // Coprocessor instructions
868
869  void cdp(Coprocessor coproc, int opcode_1,
870           CRegister crd, CRegister crn, CRegister crm,
871           int opcode_2, Condition cond = al);
872
873  void cdp2(Coprocessor coproc, int opcode_1,
874            CRegister crd, CRegister crn, CRegister crm,
875            int opcode_2);  // v5 and above
876
877  void mcr(Coprocessor coproc, int opcode_1,
878           Register rd, CRegister crn, CRegister crm,
879           int opcode_2 = 0, Condition cond = al);
880
881  void mcr2(Coprocessor coproc, int opcode_1,
882            Register rd, CRegister crn, CRegister crm,
883            int opcode_2 = 0);  // v5 and above
884
885  void mrc(Coprocessor coproc, int opcode_1,
886           Register rd, CRegister crn, CRegister crm,
887           int opcode_2 = 0, Condition cond = al);
888
889  void mrc2(Coprocessor coproc, int opcode_1,
890            Register rd, CRegister crn, CRegister crm,
891            int opcode_2 = 0);  // v5 and above
892
893  void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
894           LFlag l = Short, Condition cond = al);
895  void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
896           LFlag l = Short, Condition cond = al);
897
898  void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
899            LFlag l = Short);  // v5 and above
900  void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
901            LFlag l = Short);  // v5 and above
902
903  void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst,
904           LFlag l = Short, Condition cond = al);
905  void stc(Coprocessor coproc, CRegister crd, Register base, int option,
906           LFlag l = Short, Condition cond = al);
907
908  void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst,
909            LFlag l = Short);  // v5 and above
910  void stc2(Coprocessor coproc, CRegister crd, Register base, int option,
911            LFlag l = Short);  // v5 and above
912
913  // Support for VFP.
914  // All these APIs support S0 to S31 and D0 to D15.
915  // Currently these APIs do not support extended D registers, i.e, D16 to D31.
916  // However, some simple modifications can allow
917  // these APIs to support D16 to D31.
918
919  void vldr(const DwVfpRegister dst,
920            const Register base,
921            int offset,  // Offset must be a multiple of 4.
922            const Condition cond = al);
923
924  void vldr(const SwVfpRegister dst,
925            const Register base,
926            int offset,  // Offset must be a multiple of 4.
927            const Condition cond = al);
928
929  void vstr(const DwVfpRegister src,
930            const Register base,
931            int offset,  // Offset must be a multiple of 4.
932            const Condition cond = al);
933
934  void vmov(const DwVfpRegister dst,
935            const DwVfpRegister src,
936            const Condition cond = al);
937  void vmov(const DwVfpRegister dst,
938            const Register src1,
939            const Register src2,
940            const Condition cond = al);
941  void vmov(const Register dst1,
942            const Register dst2,
943            const DwVfpRegister src,
944            const Condition cond = al);
945  void vmov(const SwVfpRegister dst,
946            const Register src,
947            const Condition cond = al);
948  void vmov(const Register dst,
949            const SwVfpRegister src,
950            const Condition cond = al);
951  void vcvt_f64_s32(const DwVfpRegister dst,
952                    const SwVfpRegister src,
953                    const Condition cond = al);
954  void vcvt_f32_s32(const SwVfpRegister dst,
955                    const SwVfpRegister src,
956                    const Condition cond = al);
957  void vcvt_f64_u32(const DwVfpRegister dst,
958                    const SwVfpRegister src,
959                    const Condition cond = al);
960  void vcvt_s32_f64(const SwVfpRegister dst,
961                    const DwVfpRegister src,
962                    const Condition cond = al);
963  void vcvt_u32_f64(const SwVfpRegister dst,
964                    const DwVfpRegister src,
965                    const Condition cond = al);
966  void vcvt_f64_f32(const DwVfpRegister dst,
967                    const SwVfpRegister src,
968                    const Condition cond = al);
969  void vcvt_f32_f64(const SwVfpRegister dst,
970                    const DwVfpRegister src,
971                    const Condition cond = al);
972
973  void vadd(const DwVfpRegister dst,
974            const DwVfpRegister src1,
975            const DwVfpRegister src2,
976            const Condition cond = al);
977  void vsub(const DwVfpRegister dst,
978            const DwVfpRegister src1,
979            const DwVfpRegister src2,
980            const Condition cond = al);
981  void vmul(const DwVfpRegister dst,
982            const DwVfpRegister src1,
983            const DwVfpRegister src2,
984            const Condition cond = al);
985  void vdiv(const DwVfpRegister dst,
986            const DwVfpRegister src1,
987            const DwVfpRegister src2,
988            const Condition cond = al);
989  void vcmp(const DwVfpRegister src1,
990            const DwVfpRegister src2,
991            const SBit s = LeaveCC,
992            const Condition cond = al);
993  void vmrs(const Register dst,
994            const Condition cond = al);
995  void vsqrt(const DwVfpRegister dst,
996             const DwVfpRegister src,
997             const Condition cond = al);
998
999  // Pseudo instructions
1000  void nop(int type = 0);
1001
1002  void push(Register src, Condition cond = al) {
1003    str(src, MemOperand(sp, 4, NegPreIndex), cond);
1004  }
1005
1006  void pop(Register dst, Condition cond = al) {
1007    ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1008  }
1009
1010  void pop() {
1011    add(sp, sp, Operand(kPointerSize));
1012  }
1013
1014  // Jump unconditionally to given label.
1015  void jmp(Label* L) { b(L, al); }
1016
1017  // Check the code size generated from label to here.
1018  int InstructionsGeneratedSince(Label* l) {
1019    return (pc_offset() - l->pos()) / kInstrSize;
1020  }
1021
1022  // Check whether an immediate fits an addressing mode 1 instruction.
1023  bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1024
1025  // Class for scoping postponing the constant pool generation.
1026  class BlockConstPoolScope {
1027   public:
1028    explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1029      assem_->StartBlockConstPool();
1030    }
1031    ~BlockConstPoolScope() {
1032      assem_->EndBlockConstPool();
1033    }
1034
1035   private:
1036    Assembler* assem_;
1037
1038    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1039  };
1040
1041  // Postpone the generation of the constant pool for the specified number of
1042  // instructions.
1043  void BlockConstPoolFor(int instructions);
1044
1045  // Debugging
1046
1047  // Mark address of the ExitJSFrame code.
1048  void RecordJSReturn();
1049
1050  // Mark address of a debug break slot.
1051  void RecordDebugBreakSlot();
1052
1053  // Record a comment relocation entry that can be used by a disassembler.
1054  // Use --debug_code to enable.
1055  void RecordComment(const char* msg);
1056
1057  void RecordPosition(int pos);
1058  void RecordStatementPosition(int pos);
1059  bool WriteRecordedPositions();
1060
1061  int pc_offset() const { return pc_ - buffer_; }
1062  int current_position() const { return current_position_; }
1063  int current_statement_position() const { return current_statement_position_; }
1064
1065  bool can_peephole_optimize(int instructions) {
1066    if (!FLAG_peephole_optimization) return false;
1067    if (last_bound_pos_ > pc_offset() - instructions * kInstrSize) return false;
1068    return reloc_info_writer.last_pc() <= pc_ - instructions * kInstrSize;
1069  }
1070
1071  // Read/patch instructions
1072  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1073  static void instr_at_put(byte* pc, Instr instr) {
1074    *reinterpret_cast<Instr*>(pc) = instr;
1075  }
1076  static bool IsNop(Instr instr, int type = 0);
1077  static bool IsBranch(Instr instr);
1078  static int GetBranchOffset(Instr instr);
1079  static bool IsLdrRegisterImmediate(Instr instr);
1080  static int GetLdrRegisterImmediateOffset(Instr instr);
1081  static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
1082  static Register GetRd(Instr instr);
1083  static bool IsPush(Instr instr);
1084  static bool IsPop(Instr instr);
1085  static bool IsStrRegFpOffset(Instr instr);
1086  static bool IsLdrRegFpOffset(Instr instr);
1087  static bool IsStrRegFpNegOffset(Instr instr);
1088  static bool IsLdrRegFpNegOffset(Instr instr);
1089
1090
1091 protected:
1092  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1093
1094  // Read/patch instructions
1095  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1096  void instr_at_put(int pos, Instr instr) {
1097    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1098  }
1099
1100  // Decode branch instruction at pos and return branch target pos
1101  int target_at(int pos);
1102
1103  // Patch branch instruction at pos to branch to given branch target pos
1104  void target_at_put(int pos, int target_pos);
1105
1106  // Check if is time to emit a constant pool for pending reloc info entries
1107  void CheckConstPool(bool force_emit, bool require_jump);
1108
1109  // Block the emission of the constant pool before pc_offset
1110  void BlockConstPoolBefore(int pc_offset) {
1111    if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
1112  }
1113
1114  void StartBlockConstPool() {
1115    const_pool_blocked_nesting_++;
1116  }
1117  void EndBlockConstPool() {
1118    const_pool_blocked_nesting_--;
1119  }
1120  bool is_const_pool_blocked() const { return const_pool_blocked_nesting_ > 0; }
1121
1122 private:
1123  // Code buffer:
1124  // The buffer into which code and relocation info are generated.
1125  byte* buffer_;
1126  int buffer_size_;
1127  // True if the assembler owns the buffer, false if buffer is external.
1128  bool own_buffer_;
1129
1130  // Buffer size and constant pool distance are checked together at regular
1131  // intervals of kBufferCheckInterval emitted bytes
1132  static const int kBufferCheckInterval = 1*KB/2;
1133  int next_buffer_check_;  // pc offset of next buffer check
1134
1135  // Code generation
1136  // The relocation writer's position is at least kGap bytes below the end of
1137  // the generated instructions. This is so that multi-instruction sequences do
1138  // not have to check for overflow. The same is true for writes of large
1139  // relocation info entries.
1140  static const int kGap = 32;
1141  byte* pc_;  // the program counter; moves forward
1142
1143  // Constant pool generation
1144  // Pools are emitted in the instruction stream, preferably after unconditional
1145  // jumps or after returns from functions (in dead code locations).
1146  // If a long code sequence does not contain unconditional jumps, it is
1147  // necessary to emit the constant pool before the pool gets too far from the
1148  // location it is accessed from. In this case, we emit a jump over the emitted
1149  // constant pool.
1150  // Constants in the pool may be addresses of functions that gets relocated;
1151  // if so, a relocation info entry is associated to the constant pool entry.
1152
1153  // Repeated checking whether the constant pool should be emitted is rather
1154  // expensive. By default we only check again once a number of instructions
1155  // has been generated. That also means that the sizing of the buffers is not
1156  // an exact science, and that we rely on some slop to not overrun buffers.
1157  static const int kCheckConstIntervalInst = 32;
1158  static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
1159
1160
1161  // Pools are emitted after function return and in dead code at (more or less)
1162  // regular intervals of kDistBetweenPools bytes
1163  static const int kDistBetweenPools = 1*KB;
1164
1165  // Constants in pools are accessed via pc relative addressing, which can
1166  // reach +/-4KB thereby defining a maximum distance between the instruction
1167  // and the accessed constant. We satisfy this constraint by limiting the
1168  // distance between pools.
1169  static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval;
1170
1171  // Emission of the constant pool may be blocked in some code sequences.
1172  int const_pool_blocked_nesting_;  // Block emission if this is not zero.
1173  int no_const_pool_before_;  // Block emission before this pc offset.
1174
1175  // Keep track of the last emitted pool to guarantee a maximal distance
1176  int last_const_pool_end_;  // pc offset following the last constant pool
1177
1178  // Relocation info generation
1179  // Each relocation is encoded as a variable size value
1180  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1181  RelocInfoWriter reloc_info_writer;
1182  // Relocation info records are also used during code generation as temporary
1183  // containers for constants and code target addresses until they are emitted
1184  // to the constant pool. These pending relocation info records are temporarily
1185  // stored in a separate buffer until a constant pool is emitted.
1186  // If every instruction in a long sequence is accessing the pool, we need one
1187  // pending relocation entry per instruction.
1188  static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
1189  RelocInfo prinfo_[kMaxNumPRInfo];  // the buffer of pending relocation info
1190  int num_prinfo_;  // number of pending reloc info entries in the buffer
1191
1192  // The bound position, before this we cannot do instruction elimination.
1193  int last_bound_pos_;
1194
1195  // source position information
1196  int current_position_;
1197  int current_statement_position_;
1198  int written_position_;
1199  int written_statement_position_;
1200
1201  // Code emission
1202  inline void CheckBuffer();
1203  void GrowBuffer();
1204  inline void emit(Instr x);
1205
1206  // Instruction generation
1207  void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1208  void addrmod2(Instr instr, Register rd, const MemOperand& x);
1209  void addrmod3(Instr instr, Register rd, const MemOperand& x);
1210  void addrmod4(Instr instr, Register rn, RegList rl);
1211  void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1212
1213  // Labels
1214  void print(Label* L);
1215  void bind_to(Label* L, int pos);
1216  void link_to(Label* L, Label* appendix);
1217  void next(Label* L);
1218
1219  // Record reloc info for current pc_
1220  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1221
1222  friend class RegExpMacroAssemblerARM;
1223  friend class RelocInfo;
1224  friend class CodePatcher;
1225  friend class BlockConstPoolScope;
1226};
1227
1228} }  // namespace v8::internal
1229
1230#endif  // V8_ARM_ASSEMBLER_ARM_H_
1231