• 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 modified
34 // significantly by Google Inc.
35 // Copyright 2006-2008 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 
45 namespace v8 {
46 namespace internal {
47 
48 // CPU Registers.
49 //
50 // 1) We would prefer to use an enum, but enum values are assignment-
51 // compatible with int, which has caused code-generation bugs.
52 //
53 // 2) We would prefer to use a class instead of a struct but we don't like
54 // the register initialization to depend on the particular initialization
55 // order (which appears to be different on OS X, Linux, and Windows for the
56 // installed versions of C++ we tried). Using a struct permits C-style
57 // "initialization". Also, the Register objects cannot be const as this
58 // forces initialization stubs in MSVC, making us dependent on initialization
59 // order.
60 //
61 // 3) By not using an enum, we are possibly preventing the compiler from
62 // doing certain constant folds, which may significantly reduce the
63 // code generated for some assembly instructions (because they boil down
64 // to a few constants). If this is a problem, we could change the code
65 // such that we use an enum in optimized mode, and the struct in debug
66 // mode. This way we get the compile-time error checking in debug mode
67 // and best performance in optimized code.
68 //
69 // Core register
70 struct Register {
is_validRegister71   bool is_valid() const  { return 0 <= code_ && code_ < 16; }
isRegister72   bool is(Register reg) const  { return code_ == reg.code_; }
codeRegister73   int code() const  {
74     ASSERT(is_valid());
75     return code_;
76   }
bitRegister77   int bit() const  {
78     ASSERT(is_valid());
79     return 1 << code_;
80   }
81 
82   // (unfortunately we can't make this private in a struct)
83   int code_;
84 };
85 
86 
87 extern Register no_reg;
88 extern Register r0;
89 extern Register r1;
90 extern Register r2;
91 extern Register r3;
92 extern Register r4;
93 extern Register r5;
94 extern Register r6;
95 extern Register r7;
96 extern Register r8;
97 extern Register r9;
98 extern Register r10;
99 extern Register fp;
100 extern Register ip;
101 extern Register sp;
102 extern Register lr;
103 extern Register pc;
104 
105 
106 // Coprocessor register
107 struct CRegister {
is_validCRegister108   bool is_valid() const  { return 0 <= code_ && code_ < 16; }
isCRegister109   bool is(CRegister creg) const  { return code_ == creg.code_; }
codeCRegister110   int code() const  {
111     ASSERT(is_valid());
112     return code_;
113   }
bitCRegister114   int bit() const  {
115     ASSERT(is_valid());
116     return 1 << code_;
117   }
118 
119   // (unfortunately we can't make this private in a struct)
120   int code_;
121 };
122 
123 
124 extern CRegister no_creg;
125 extern CRegister cr0;
126 extern CRegister cr1;
127 extern CRegister cr2;
128 extern CRegister cr3;
129 extern CRegister cr4;
130 extern CRegister cr5;
131 extern CRegister cr6;
132 extern CRegister cr7;
133 extern CRegister cr8;
134 extern CRegister cr9;
135 extern CRegister cr10;
136 extern CRegister cr11;
137 extern CRegister cr12;
138 extern CRegister cr13;
139 extern CRegister cr14;
140 extern CRegister cr15;
141 
142 
143 // Coprocessor number
144 enum Coprocessor {
145   p0  = 0,
146   p1  = 1,
147   p2  = 2,
148   p3  = 3,
149   p4  = 4,
150   p5  = 5,
151   p6  = 6,
152   p7  = 7,
153   p8  = 8,
154   p9  = 9,
155   p10 = 10,
156   p11 = 11,
157   p12 = 12,
158   p13 = 13,
159   p14 = 14,
160   p15 = 15
161 };
162 
163 
164 // Condition field in instructions
165 enum Condition {
166   eq =  0 << 28,  // Z set            equal.
167   ne =  1 << 28,  // Z clear          not equal.
168   nz =  1 << 28,  // Z clear          not zero.
169   cs =  2 << 28,  // C set            carry set.
170   hs =  2 << 28,  // C set            unsigned higher or same.
171   cc =  3 << 28,  // C clear          carry clear.
172   lo =  3 << 28,  // C clear          unsigned lower.
173   mi =  4 << 28,  // N set            negative.
174   pl =  5 << 28,  // N clear          positive or zero.
175   vs =  6 << 28,  // V set            overflow.
176   vc =  7 << 28,  // V clear          no overflow.
177   hi =  8 << 28,  // C set, Z clear   unsigned higher.
178   ls =  9 << 28,  // C clear or Z set unsigned lower or same.
179   ge = 10 << 28,  // N == V           greater or equal.
180   lt = 11 << 28,  // N != V           less than.
181   gt = 12 << 28,  // Z clear, N == V  greater than.
182   le = 13 << 28,  // Z set or N != V  less then or equal
183   al = 14 << 28   //                  always.
184 };
185 
186 
187 // Returns the equivalent of !cc.
188 INLINE(Condition NegateCondition(Condition cc));
189 
190 
191 // Corresponds to transposing the operands of a comparison.
ReverseCondition(Condition cc)192 inline Condition ReverseCondition(Condition cc) {
193   switch (cc) {
194     case lo:
195       return hi;
196     case hi:
197       return lo;
198     case hs:
199       return ls;
200     case ls:
201       return hs;
202     case lt:
203       return gt;
204     case gt:
205       return lt;
206     case ge:
207       return le;
208     case le:
209       return ge;
210     default:
211       return cc;
212   };
213 }
214 
215 
216 // Branch hints are not used on the ARM.  They are defined so that they can
217 // appear in shared function signatures, but will be ignored in ARM
218 // implementations.
219 enum Hint { no_hint };
220 
221 // Hints are not used on the arm.  Negating is trivial.
NegateHint(Hint ignored)222 inline Hint NegateHint(Hint ignored) { return no_hint; }
223 
224 
225 // -----------------------------------------------------------------------------
226 // Addressing modes and instruction variants
227 
228 // Shifter operand shift operation
229 enum ShiftOp {
230   LSL = 0 << 5,
231   LSR = 1 << 5,
232   ASR = 2 << 5,
233   ROR = 3 << 5,
234   RRX = -1
235 };
236 
237 
238 // Condition code updating mode
239 enum SBit {
240   SetCC   = 1 << 20,  // set condition code
241   LeaveCC = 0 << 20   // leave condition code unchanged
242 };
243 
244 
245 // Status register selection
246 enum SRegister {
247   CPSR = 0 << 22,
248   SPSR = 1 << 22
249 };
250 
251 
252 // Status register fields
253 enum SRegisterField {
254   CPSR_c = CPSR | 1 << 16,
255   CPSR_x = CPSR | 1 << 17,
256   CPSR_s = CPSR | 1 << 18,
257   CPSR_f = CPSR | 1 << 19,
258   SPSR_c = SPSR | 1 << 16,
259   SPSR_x = SPSR | 1 << 17,
260   SPSR_s = SPSR | 1 << 18,
261   SPSR_f = SPSR | 1 << 19
262 };
263 
264 // Status register field mask (or'ed SRegisterField enum values)
265 typedef uint32_t SRegisterFieldMask;
266 
267 
268 // Memory operand addressing mode
269 enum AddrMode {
270   // bit encoding P U W
271   Offset       = (8|4|0) << 21,  // offset (without writeback to base)
272   PreIndex     = (8|4|1) << 21,  // pre-indexed addressing with writeback
273   PostIndex    = (0|4|0) << 21,  // post-indexed addressing with writeback
274   NegOffset    = (8|0|0) << 21,  // negative offset (without writeback to base)
275   NegPreIndex  = (8|0|1) << 21,  // negative pre-indexed with writeback
276   NegPostIndex = (0|0|0) << 21   // negative post-indexed with writeback
277 };
278 
279 
280 // Load/store multiple addressing mode
281 enum BlockAddrMode {
282   // bit encoding P U W
283   da           = (0|0|0) << 21,  // decrement after
284   ia           = (0|4|0) << 21,  // increment after
285   db           = (8|0|0) << 21,  // decrement before
286   ib           = (8|4|0) << 21,  // increment before
287   da_w         = (0|0|1) << 21,  // decrement after with writeback to base
288   ia_w         = (0|4|1) << 21,  // increment after with writeback to base
289   db_w         = (8|0|1) << 21,  // decrement before with writeback to base
290   ib_w         = (8|4|1) << 21   // increment before with writeback to base
291 };
292 
293 
294 // Coprocessor load/store operand size
295 enum LFlag {
296   Long  = 1 << 22,  // long load/store coprocessor
297   Short = 0 << 22   // short load/store coprocessor
298 };
299 
300 
301 // -----------------------------------------------------------------------------
302 // Machine instruction Operands
303 
304 // Class Operand represents a shifter operand in data processing instructions
305 class Operand BASE_EMBEDDED {
306  public:
307   // immediate
308   INLINE(explicit Operand(int32_t immediate,
309          RelocInfo::Mode rmode = RelocInfo::NONE));
310   INLINE(explicit Operand(const ExternalReference& f));
311   INLINE(explicit Operand(const char* s));
312   INLINE(explicit Operand(Object** opp));
313   INLINE(explicit Operand(Context** cpp));
314   explicit Operand(Handle<Object> handle);
315   INLINE(explicit Operand(Smi* value));
316 
317   // rm
318   INLINE(explicit Operand(Register rm));
319 
320   // rm <shift_op> shift_imm
321   explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
322 
323   // rm <shift_op> rs
324   explicit Operand(Register rm, ShiftOp shift_op, Register rs);
325 
326   // Return true if this is a register operand.
327   INLINE(bool is_reg() const);
328 
rm()329   Register rm() const { return rm_; }
330 
331  private:
332   Register rm_;
333   Register rs_;
334   ShiftOp shift_op_;
335   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
336   int32_t imm32_;  // valid if rm_ == no_reg
337   RelocInfo::Mode rmode_;
338 
339   friend class Assembler;
340 };
341 
342 
343 // Class MemOperand represents a memory operand in load and store instructions
344 class MemOperand BASE_EMBEDDED {
345  public:
346   // [rn +/- offset]      Offset/NegOffset
347   // [rn +/- offset]!     PreIndex/NegPreIndex
348   // [rn], +/- offset     PostIndex/NegPostIndex
349   // offset is any signed 32-bit value; offset is first loaded to register ip if
350   // it does not fit the addressing mode (12-bit unsigned and sign bit)
351   explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
352 
353   // [rn +/- rm]          Offset/NegOffset
354   // [rn +/- rm]!         PreIndex/NegPreIndex
355   // [rn], +/- rm         PostIndex/NegPostIndex
356   explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
357 
358   // [rn +/- rm <shift_op> shift_imm]      Offset/NegOffset
359   // [rn +/- rm <shift_op> shift_imm]!     PreIndex/NegPreIndex
360   // [rn], +/- rm <shift_op> shift_imm     PostIndex/NegPostIndex
361   explicit MemOperand(Register rn, Register rm,
362                       ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
363 
364  private:
365   Register rn_;  // base
366   Register rm_;  // register offset
367   int32_t offset_;  // valid if rm_ == no_reg
368   ShiftOp shift_op_;
369   int shift_imm_;  // valid if rm_ != no_reg && rs_ == no_reg
370   AddrMode am_;  // bits P, U, and W
371 
372   friend class Assembler;
373 };
374 
375 
376 typedef int32_t Instr;
377 
378 
379 class Assembler : public Malloced {
380  public:
381   // Create an assembler. Instructions and relocation information are emitted
382   // into a buffer, with the instructions starting from the beginning and the
383   // relocation information starting from the end of the buffer. See CodeDesc
384   // for a detailed comment on the layout (globals.h).
385   //
386   // If the provided buffer is NULL, the assembler allocates and grows its own
387   // buffer, and buffer_size determines the initial buffer size. The buffer is
388   // owned by the assembler and deallocated upon destruction of the assembler.
389   //
390   // If the provided buffer is not NULL, the assembler uses the provided buffer
391   // for code generation and assumes its size to be buffer_size. If the buffer
392   // is too small, a fatal error occurs. No deallocation of the buffer is done
393   // upon destruction of the assembler.
394   Assembler(void* buffer, int buffer_size);
395   ~Assembler();
396 
397   // GetCode emits any pending (non-emitted) code and fills the descriptor
398   // desc. GetCode() is idempotent; it returns the same result if no other
399   // Assembler functions are invoked in between GetCode() calls.
400   void GetCode(CodeDesc* desc);
401 
402   // Label operations & relative jumps (PPUM Appendix D)
403   //
404   // Takes a branch opcode (cc) and a label (L) and generates
405   // either a backward branch or a forward branch and links it
406   // to the label fixup chain. Usage:
407   //
408   // Label L;    // unbound label
409   // j(cc, &L);  // forward branch to unbound label
410   // bind(&L);   // bind label to the current pc
411   // j(cc, &L);  // backward branch to bound label
412   // bind(&L);   // illegal: a label may be bound only once
413   //
414   // Note: The same Label can be used for forward and backward branches
415   // but it may be bound only once.
416 
417   void bind(Label* L);  // binds an unbound label L to the current code position
418 
419   // Returns the branch offset to the given label from the current code position
420   // Links the label to the current position if it is still unbound
421   // Manages the jump elimination optimization if the second parameter is true.
422   int branch_offset(Label* L, bool jump_elimination_allowed);
423 
424   // Puts a labels target address at the given position.
425   // The high 8 bits are set to zero.
426   void label_at_put(Label* L, int at_offset);
427 
428   // Return the address in the constant pool of the code target address used by
429   // the branch/call instruction at pc.
430   INLINE(static Address target_address_address_at(Address pc));
431 
432   // Read/Modify the code target address in the branch/call instruction at pc.
433   INLINE(static Address target_address_at(Address pc));
434   INLINE(static void set_target_address_at(Address pc, Address target));
435 
436   // Distance between the instruction referring to the address of the call
437   // target (ldr pc, [target addr in const pool]) and the return address
438   static const int kPatchReturnSequenceLength = sizeof(Instr);
439   // Distance between start of patched return sequence and the emitted address
440   // to jump to.
441   static const int kPatchReturnSequenceAddressOffset = 1;
442 
443   // Difference between address of current opcode and value read from pc
444   // register.
445   static const int kPcLoadDelta = 8;
446 
447 
448   // ---------------------------------------------------------------------------
449   // Code generation
450 
451   // Insert the smallest number of nop instructions
452   // possible to align the pc offset to a multiple
453   // of m. m must be a power of 2 (>= 4).
454   void Align(int m);
455 
456   // Branch instructions
457   void b(int branch_offset, Condition cond = al);
458   void bl(int branch_offset, Condition cond = al);
459   void blx(int branch_offset);  // v5 and above
460   void blx(Register target, Condition cond = al);  // v5 and above
461   void bx(Register target, Condition cond = al);  // v5 and above, plus v4t
462 
463   // Convenience branch instructions using labels
464   void b(Label* L, Condition cond = al)  {
465     b(branch_offset(L, cond == al), cond);
466   }
b(Condition cond,Label * L)467   void b(Condition cond, Label* L)  { b(branch_offset(L, cond == al), cond); }
468   void bl(Label* L, Condition cond = al)  { bl(branch_offset(L, false), cond); }
bl(Condition cond,Label * L)469   void bl(Condition cond, Label* L)  { bl(branch_offset(L, false), cond); }
blx(Label * L)470   void blx(Label* L)  { blx(branch_offset(L, false)); }  // v5 and above
471 
472   // Data-processing instructions
473   void and_(Register dst, Register src1, const Operand& src2,
474             SBit s = LeaveCC, Condition cond = al);
475 
476   void eor(Register dst, Register src1, const Operand& src2,
477            SBit s = LeaveCC, Condition cond = al);
478 
479   void sub(Register dst, Register src1, const Operand& src2,
480            SBit s = LeaveCC, Condition cond = al);
481   void sub(Register dst, Register src1, Register src2,
482            SBit s = LeaveCC, Condition cond = al) {
483     sub(dst, src1, Operand(src2), s, cond);
484   }
485 
486   void rsb(Register dst, Register src1, const Operand& src2,
487            SBit s = LeaveCC, Condition cond = al);
488 
489   void add(Register dst, Register src1, const Operand& src2,
490            SBit s = LeaveCC, Condition cond = al);
491 
492   void adc(Register dst, Register src1, const Operand& src2,
493            SBit s = LeaveCC, Condition cond = al);
494 
495   void sbc(Register dst, Register src1, const Operand& src2,
496            SBit s = LeaveCC, Condition cond = al);
497 
498   void rsc(Register dst, Register src1, const Operand& src2,
499            SBit s = LeaveCC, Condition cond = al);
500 
501   void tst(Register src1, const Operand& src2, Condition cond = al);
502   void tst(Register src1, Register src2, Condition cond = al) {
503     tst(src1, Operand(src2), cond);
504   }
505 
506   void teq(Register src1, const Operand& src2, Condition cond = al);
507 
508   void cmp(Register src1, const Operand& src2, Condition cond = al);
509   void cmp(Register src1, Register src2, Condition cond = al) {
510     cmp(src1, Operand(src2), cond);
511   }
512 
513   void cmn(Register src1, const Operand& src2, Condition cond = al);
514 
515   void orr(Register dst, Register src1, const Operand& src2,
516            SBit s = LeaveCC, Condition cond = al);
517   void orr(Register dst, Register src1, Register src2,
518            SBit s = LeaveCC, Condition cond = al) {
519     orr(dst, src1, Operand(src2), s, cond);
520   }
521 
522   void mov(Register dst, const Operand& src,
523            SBit s = LeaveCC, Condition cond = al);
524   void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
525     mov(dst, Operand(src), s, cond);
526   }
527 
528   void bic(Register dst, Register src1, const Operand& src2,
529            SBit s = LeaveCC, Condition cond = al);
530 
531   void mvn(Register dst, const Operand& src,
532            SBit s = LeaveCC, Condition cond = al);
533 
534   // Multiply instructions
535 
536   void mla(Register dst, Register src1, Register src2, Register srcA,
537            SBit s = LeaveCC, Condition cond = al);
538 
539   void mul(Register dst, Register src1, Register src2,
540            SBit s = LeaveCC, Condition cond = al);
541 
542   void smlal(Register dstL, Register dstH, Register src1, Register src2,
543              SBit s = LeaveCC, Condition cond = al);
544 
545   void smull(Register dstL, Register dstH, Register src1, Register src2,
546              SBit s = LeaveCC, Condition cond = al);
547 
548   void umlal(Register dstL, Register dstH, Register src1, Register src2,
549              SBit s = LeaveCC, Condition cond = al);
550 
551   void umull(Register dstL, Register dstH, Register src1, Register src2,
552              SBit s = LeaveCC, Condition cond = al);
553 
554   // Miscellaneous arithmetic instructions
555 
556   void clz(Register dst, Register src, Condition cond = al);  // v5 and above
557 
558   // Status register access instructions
559 
560   void mrs(Register dst, SRegister s, Condition cond = al);
561   void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
562 
563   // Load/Store instructions
564   void ldr(Register dst, const MemOperand& src, Condition cond = al);
565   void str(Register src, const MemOperand& dst, Condition cond = al);
566   void ldrb(Register dst, const MemOperand& src, Condition cond = al);
567   void strb(Register src, const MemOperand& dst, Condition cond = al);
568   void ldrh(Register dst, const MemOperand& src, Condition cond = al);
569   void strh(Register src, const MemOperand& dst, Condition cond = al);
570   void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
571   void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
572 
573   // Load/Store multiple instructions
574   void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
575   void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
576 
577   // Semaphore instructions
578   void swp(Register dst, Register src, Register base, Condition cond = al);
579   void swpb(Register dst, Register src, Register base, Condition cond = al);
580 
581   // Exception-generating instructions and debugging support
582   void stop(const char* msg);
583 
584   void bkpt(uint32_t imm16);  // v5 and above
585   void swi(uint32_t imm24, Condition cond = al);
586 
587   // Coprocessor instructions
588 
589   void cdp(Coprocessor coproc, int opcode_1,
590            CRegister crd, CRegister crn, CRegister crm,
591            int opcode_2, Condition cond = al);
592 
593   void cdp2(Coprocessor coproc, int opcode_1,
594             CRegister crd, CRegister crn, CRegister crm,
595             int opcode_2);  // v5 and above
596 
597   void mcr(Coprocessor coproc, int opcode_1,
598            Register rd, CRegister crn, CRegister crm,
599            int opcode_2 = 0, Condition cond = al);
600 
601   void mcr2(Coprocessor coproc, int opcode_1,
602             Register rd, CRegister crn, CRegister crm,
603             int opcode_2 = 0);  // v5 and above
604 
605   void mrc(Coprocessor coproc, int opcode_1,
606            Register rd, CRegister crn, CRegister crm,
607            int opcode_2 = 0, Condition cond = al);
608 
609   void mrc2(Coprocessor coproc, int opcode_1,
610             Register rd, CRegister crn, CRegister crm,
611             int opcode_2 = 0);  // v5 and above
612 
613   void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
614            LFlag l = Short, Condition cond = al);
615   void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
616            LFlag l = Short, Condition cond = al);
617 
618   void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
619             LFlag l = Short);  // v5 and above
620   void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
621             LFlag l = Short);  // v5 and above
622 
623   void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst,
624            LFlag l = Short, Condition cond = al);
625   void stc(Coprocessor coproc, CRegister crd, Register base, int option,
626            LFlag l = Short, Condition cond = al);
627 
628   void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst,
629             LFlag l = Short);  // v5 and above
630   void stc2(Coprocessor coproc, CRegister crd, Register base, int option,
631             LFlag l = Short);  // v5 and above
632 
633   // Pseudo instructions
nop()634   void nop()  { mov(r0, Operand(r0)); }
635 
636   void push(Register src, Condition cond = al) {
637     str(src, MemOperand(sp, 4, NegPreIndex), cond);
638   }
639 
pop(Register dst)640   void pop(Register dst) {
641     ldr(dst, MemOperand(sp, 4, PostIndex), al);
642   }
643 
pop()644   void pop() {
645     add(sp, sp, Operand(kPointerSize));
646   }
647 
648   // Load effective address of memory operand x into register dst
649   void lea(Register dst, const MemOperand& x,
650            SBit s = LeaveCC, Condition cond = al);
651 
652   // Jump unconditionally to given label.
jmp(Label * L)653   void jmp(Label* L) { b(L, al); }
654 
655 
656   // Debugging
657 
658   // Record a comment relocation entry that can be used by a disassembler.
659   // Use --debug_code to enable.
660   void RecordComment(const char* msg);
661 
662   void RecordPosition(int pos);
663   void RecordStatementPosition(int pos);
664   void WriteRecordedPositions();
665 
pc_offset()666   int pc_offset() const { return pc_ - buffer_; }
current_position()667   int current_position() const { return current_position_; }
current_statement_position()668   int current_statement_position() const { return current_position_; }
669 
670  protected:
buffer_space()671   int buffer_space() const { return reloc_info_writer.pos() - pc_; }
672 
673   // Read/patch instructions
instr_at(byte * pc)674   Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
instr_at_put(byte * pc,Instr instr)675   void instr_at_put(byte* pc, Instr instr) {
676     *reinterpret_cast<Instr*>(pc) = instr;
677   }
instr_at(int pos)678   Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
instr_at_put(int pos,Instr instr)679   void instr_at_put(int pos, Instr instr) {
680     *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
681   }
682 
683   // Decode branch instruction at pos and return branch target pos
684   int target_at(int pos);
685 
686   // Patch branch instruction at pos to branch to given branch target pos
687   void target_at_put(int pos, int target_pos);
688 
689   // Check if is time to emit a constant pool for pending reloc info entries
690   void CheckConstPool(bool force_emit, bool require_jump);
691 
692   // Block the emission of the constant pool before pc_offset
BlockConstPoolBefore(int pc_offset)693   void BlockConstPoolBefore(int pc_offset) {
694     if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
695   }
696 
697  private:
698   // Code buffer:
699   // The buffer into which code and relocation info are generated.
700   byte* buffer_;
701   int buffer_size_;
702   // True if the assembler owns the buffer, false if buffer is external.
703   bool own_buffer_;
704 
705   // Buffer size and constant pool distance are checked together at regular
706   // intervals of kBufferCheckInterval emitted bytes
707   static const int kBufferCheckInterval = 1*KB/2;
708   int next_buffer_check_;  // pc offset of next buffer check
709 
710   // Code generation
711   static const int kInstrSize = sizeof(Instr);  // signed size
712   // The relocation writer's position is at least kGap bytes below the end of
713   // the generated instructions. This is so that multi-instruction sequences do
714   // not have to check for overflow. The same is true for writes of large
715   // relocation info entries.
716   static const int kGap = 32;
717   byte* pc_;  // the program counter; moves forward
718 
719   // Constant pool generation
720   // Pools are emitted in the instruction stream, preferably after unconditional
721   // jumps or after returns from functions (in dead code locations).
722   // If a long code sequence does not contain unconditional jumps, it is
723   // necessary to emit the constant pool before the pool gets too far from the
724   // location it is accessed from. In this case, we emit a jump over the emitted
725   // constant pool.
726   // Constants in the pool may be addresses of functions that gets relocated;
727   // if so, a relocation info entry is associated to the constant pool entry.
728 
729   // Repeated checking whether the constant pool should be emitted is rather
730   // expensive. By default we only check again once a number of instructions
731   // has been generated. That also means that the sizing of the buffers is not
732   // an exact science, and that we rely on some slop to not overrun buffers.
733   static const int kCheckConstIntervalInst = 32;
734   static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
735 
736 
737   // Pools are emitted after function return and in dead code at (more or less)
738   // regular intervals of kDistBetweenPools bytes
739   static const int kDistBetweenPools = 1*KB;
740 
741   // Constants in pools are accessed via pc relative addressing, which can
742   // reach +/-4KB thereby defining a maximum distance between the instruction
743   // and the accessed constant. We satisfy this constraint by limiting the
744   // distance between pools.
745   static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval;
746 
747   // Emission of the constant pool may be blocked in some code sequences
748   int no_const_pool_before_;  // block emission before this pc offset
749 
750   // Keep track of the last emitted pool to guarantee a maximal distance
751   int last_const_pool_end_;  // pc offset following the last constant pool
752 
753   // Relocation info generation
754   // Each relocation is encoded as a variable size value
755   static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
756   RelocInfoWriter reloc_info_writer;
757   // Relocation info records are also used during code generation as temporary
758   // containers for constants and code target addresses until they are emitted
759   // to the constant pool. These pending relocation info records are temporarily
760   // stored in a separate buffer until a constant pool is emitted.
761   // If every instruction in a long sequence is accessing the pool, we need one
762   // pending relocation entry per instruction.
763   static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
764   RelocInfo prinfo_[kMaxNumPRInfo];  // the buffer of pending relocation info
765   int num_prinfo_;  // number of pending reloc info entries in the buffer
766 
767   // The bound position, before this we cannot do instruction elimination.
768   int last_bound_pos_;
769 
770   // source position information
771   int current_position_;
772   int current_statement_position_;
773   int written_position_;
774   int written_statement_position_;
775 
776   // Code emission
777   inline void CheckBuffer();
778   void GrowBuffer();
779   inline void emit(Instr x);
780 
781   // Instruction generation
782   void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
783   void addrmod2(Instr instr, Register rd, const MemOperand& x);
784   void addrmod3(Instr instr, Register rd, const MemOperand& x);
785   void addrmod4(Instr instr, Register rn, RegList rl);
786   void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
787 
788   // Labels
789   void print(Label* L);
790   void bind_to(Label* L, int pos);
791   void link_to(Label* L, Label* appendix);
792   void next(Label* L);
793 
794   // Record reloc info for current pc_
795   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
796 
797   friend class RegExpMacroAssemblerARM;
798 };
799 
800 } }  // namespace v8::internal
801 
802 #endif  // V8_ARM_ASSEMBLER_ARM_H_
803