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