blob: cd53dd6097c97d97f468830f8573ff0bb38ad693 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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"
Steve Blockd0582a62009-12-15 09:54:21 +000044#include "serialize.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000045
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
Steve Blockd0582a62009-12-15 09:54:21 +0000106
Leon Clarkee46be812010-01-19 14:06:41 +0000107// 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
Steve Blocka7e24c12009-10-30 11:49:00 +0000194
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 INLINE(explicit Operand(Object** opp));
402 INLINE(explicit Operand(Context** cpp));
403 explicit Operand(Handle<Object> handle);
404 INLINE(explicit Operand(Smi* value));
405
406 // rm
407 INLINE(explicit Operand(Register rm));
408
409 // rm <shift_op> shift_imm
410 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
411
412 // rm <shift_op> rs
413 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
414
415 // Return true if this is a register operand.
416 INLINE(bool is_reg() const);
417
418 Register rm() const { return rm_; }
419
420 private:
421 Register rm_;
422 Register rs_;
423 ShiftOp shift_op_;
424 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
425 int32_t imm32_; // valid if rm_ == no_reg
426 RelocInfo::Mode rmode_;
427
428 friend class Assembler;
429};
430
431
432// Class MemOperand represents a memory operand in load and store instructions
433class MemOperand BASE_EMBEDDED {
434 public:
435 // [rn +/- offset] Offset/NegOffset
436 // [rn +/- offset]! PreIndex/NegPreIndex
437 // [rn], +/- offset PostIndex/NegPostIndex
438 // offset is any signed 32-bit value; offset is first loaded to register ip if
439 // it does not fit the addressing mode (12-bit unsigned and sign bit)
440 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
441
442 // [rn +/- rm] Offset/NegOffset
443 // [rn +/- rm]! PreIndex/NegPreIndex
444 // [rn], +/- rm PostIndex/NegPostIndex
445 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
446
447 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
448 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
449 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
450 explicit MemOperand(Register rn, Register rm,
451 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
452
453 private:
454 Register rn_; // base
455 Register rm_; // register offset
456 int32_t offset_; // valid if rm_ == no_reg
457 ShiftOp shift_op_;
458 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
459 AddrMode am_; // bits P, U, and W
460
461 friend class Assembler;
462};
463
Steve Blockd0582a62009-12-15 09:54:21 +0000464// CpuFeatures keeps track of which features are supported by the target CPU.
465// Supported features must be enabled by a Scope before use.
466class CpuFeatures : public AllStatic {
467 public:
468 // Detect features of the target CPU. Set safe defaults if the serializer
469 // is enabled (snapshots must be portable).
470 static void Probe();
471
472 // Check whether a feature is supported by the target CPU.
473 static bool IsSupported(CpuFeature f) {
474 if (f == VFP3 && !FLAG_enable_vfp3) return false;
475 return (supported_ & (1u << f)) != 0;
476 }
477
478 // Check whether a feature is currently enabled.
479 static bool IsEnabled(CpuFeature f) {
480 return (enabled_ & (1u << f)) != 0;
481 }
482
483 // Enable a specified feature within a scope.
484 class Scope BASE_EMBEDDED {
485#ifdef DEBUG
486 public:
487 explicit Scope(CpuFeature f) {
488 ASSERT(CpuFeatures::IsSupported(f));
489 ASSERT(!Serializer::enabled() ||
490 (found_by_runtime_probing_ & (1u << f)) == 0);
491 old_enabled_ = CpuFeatures::enabled_;
492 CpuFeatures::enabled_ |= 1u << f;
493 }
494 ~Scope() { CpuFeatures::enabled_ = old_enabled_; }
495 private:
496 unsigned old_enabled_;
497#else
498 public:
499 explicit Scope(CpuFeature f) {}
500#endif
501 };
502
503 private:
504 static unsigned supported_;
505 static unsigned enabled_;
506 static unsigned found_by_runtime_probing_;
507};
508
Steve Blocka7e24c12009-10-30 11:49:00 +0000509
510typedef int32_t Instr;
511
512
513extern const Instr kMovLrPc;
514extern const Instr kLdrPCPattern;
515
516
517class Assembler : public Malloced {
518 public:
519 // Create an assembler. Instructions and relocation information are emitted
520 // into a buffer, with the instructions starting from the beginning and the
521 // relocation information starting from the end of the buffer. See CodeDesc
522 // for a detailed comment on the layout (globals.h).
523 //
524 // If the provided buffer is NULL, the assembler allocates and grows its own
525 // buffer, and buffer_size determines the initial buffer size. The buffer is
526 // owned by the assembler and deallocated upon destruction of the assembler.
527 //
528 // If the provided buffer is not NULL, the assembler uses the provided buffer
529 // for code generation and assumes its size to be buffer_size. If the buffer
530 // is too small, a fatal error occurs. No deallocation of the buffer is done
531 // upon destruction of the assembler.
532 Assembler(void* buffer, int buffer_size);
533 ~Assembler();
534
535 // GetCode emits any pending (non-emitted) code and fills the descriptor
536 // desc. GetCode() is idempotent; it returns the same result if no other
537 // Assembler functions are invoked in between GetCode() calls.
538 void GetCode(CodeDesc* desc);
539
540 // Label operations & relative jumps (PPUM Appendix D)
541 //
542 // Takes a branch opcode (cc) and a label (L) and generates
543 // either a backward branch or a forward branch and links it
544 // to the label fixup chain. Usage:
545 //
546 // Label L; // unbound label
547 // j(cc, &L); // forward branch to unbound label
548 // bind(&L); // bind label to the current pc
549 // j(cc, &L); // backward branch to bound label
550 // bind(&L); // illegal: a label may be bound only once
551 //
552 // Note: The same Label can be used for forward and backward branches
553 // but it may be bound only once.
554
555 void bind(Label* L); // binds an unbound label L to the current code position
556
557 // Returns the branch offset to the given label from the current code position
558 // Links the label to the current position if it is still unbound
559 // Manages the jump elimination optimization if the second parameter is true.
560 int branch_offset(Label* L, bool jump_elimination_allowed);
561
562 // Puts a labels target address at the given position.
563 // The high 8 bits are set to zero.
564 void label_at_put(Label* L, int at_offset);
565
566 // Return the address in the constant pool of the code target address used by
567 // the branch/call instruction at pc.
568 INLINE(static Address target_address_address_at(Address pc));
569
570 // Read/Modify the code target address in the branch/call instruction at pc.
571 INLINE(static Address target_address_at(Address pc));
572 INLINE(static void set_target_address_at(Address pc, Address target));
573
Steve Blockd0582a62009-12-15 09:54:21 +0000574 // This sets the branch destination (which is in the constant pool on ARM).
575 // This is for calls and branches within generated code.
576 inline static void set_target_at(Address constant_pool_entry, Address target);
577
578 // This sets the branch destination (which is in the constant pool on ARM).
579 // This is for calls and branches to runtime code.
580 inline static void set_external_target_at(Address constant_pool_entry,
581 Address target) {
582 set_target_at(constant_pool_entry, target);
583 }
584
585 // Here we are patching the address in the constant pool, not the actual call
586 // instruction. The address in the constant pool is the same size as a
587 // pointer.
588 static const int kCallTargetSize = kPointerSize;
589 static const int kExternalTargetSize = kPointerSize;
590
Steve Blocka7e24c12009-10-30 11:49:00 +0000591 // Size of an instruction.
592 static const int kInstrSize = sizeof(Instr);
593
594 // Distance between the instruction referring to the address of the call
595 // target (ldr pc, [target addr in const pool]) and the return address
596 static const int kCallTargetAddressOffset = kInstrSize;
597
598 // Distance between start of patched return sequence and the emitted address
599 // to jump to.
600 static const int kPatchReturnSequenceAddressOffset = kInstrSize;
601
602 // Difference between address of current opcode and value read from pc
603 // register.
604 static const int kPcLoadDelta = 8;
605
Steve Blockd0582a62009-12-15 09:54:21 +0000606 static const int kJSReturnSequenceLength = 4;
Steve Blocka7e24c12009-10-30 11:49:00 +0000607
608 // ---------------------------------------------------------------------------
609 // Code generation
610
611 // Insert the smallest number of nop instructions
612 // possible to align the pc offset to a multiple
613 // of m. m must be a power of 2 (>= 4).
614 void Align(int m);
615
616 // Branch instructions
617 void b(int branch_offset, Condition cond = al);
618 void bl(int branch_offset, Condition cond = al);
619 void blx(int branch_offset); // v5 and above
620 void blx(Register target, Condition cond = al); // v5 and above
621 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
622
623 // Convenience branch instructions using labels
624 void b(Label* L, Condition cond = al) {
625 b(branch_offset(L, cond == al), cond);
626 }
627 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
628 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
629 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
630 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
631
632 // Data-processing instructions
633 void and_(Register dst, Register src1, const Operand& src2,
634 SBit s = LeaveCC, Condition cond = al);
635
636 void eor(Register dst, Register src1, const Operand& src2,
637 SBit s = LeaveCC, Condition cond = al);
638
639 void sub(Register dst, Register src1, const Operand& src2,
640 SBit s = LeaveCC, Condition cond = al);
641 void sub(Register dst, Register src1, Register src2,
642 SBit s = LeaveCC, Condition cond = al) {
643 sub(dst, src1, Operand(src2), s, cond);
644 }
645
646 void rsb(Register dst, Register src1, const Operand& src2,
647 SBit s = LeaveCC, Condition cond = al);
648
649 void add(Register dst, Register src1, const Operand& src2,
650 SBit s = LeaveCC, Condition cond = al);
651
652 void adc(Register dst, Register src1, const Operand& src2,
653 SBit s = LeaveCC, Condition cond = al);
654
655 void sbc(Register dst, Register src1, const Operand& src2,
656 SBit s = LeaveCC, Condition cond = al);
657
658 void rsc(Register dst, Register src1, const Operand& src2,
659 SBit s = LeaveCC, Condition cond = al);
660
661 void tst(Register src1, const Operand& src2, Condition cond = al);
662 void tst(Register src1, Register src2, Condition cond = al) {
663 tst(src1, Operand(src2), cond);
664 }
665
666 void teq(Register src1, const Operand& src2, Condition cond = al);
667
668 void cmp(Register src1, const Operand& src2, Condition cond = al);
669 void cmp(Register src1, Register src2, Condition cond = al) {
670 cmp(src1, Operand(src2), cond);
671 }
672
673 void cmn(Register src1, const Operand& src2, Condition cond = al);
674
675 void orr(Register dst, Register src1, const Operand& src2,
676 SBit s = LeaveCC, Condition cond = al);
677 void orr(Register dst, Register src1, Register src2,
678 SBit s = LeaveCC, Condition cond = al) {
679 orr(dst, src1, Operand(src2), s, cond);
680 }
681
682 void mov(Register dst, const Operand& src,
683 SBit s = LeaveCC, Condition cond = al);
684 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
685 mov(dst, Operand(src), s, cond);
686 }
687
688 void bic(Register dst, Register src1, const Operand& src2,
689 SBit s = LeaveCC, Condition cond = al);
690
691 void mvn(Register dst, const Operand& src,
692 SBit s = LeaveCC, Condition cond = al);
693
694 // Multiply instructions
695
696 void mla(Register dst, Register src1, Register src2, Register srcA,
697 SBit s = LeaveCC, Condition cond = al);
698
699 void mul(Register dst, Register src1, Register src2,
700 SBit s = LeaveCC, Condition cond = al);
701
702 void smlal(Register dstL, Register dstH, Register src1, Register src2,
703 SBit s = LeaveCC, Condition cond = al);
704
705 void smull(Register dstL, Register dstH, Register src1, Register src2,
706 SBit s = LeaveCC, Condition cond = al);
707
708 void umlal(Register dstL, Register dstH, Register src1, Register src2,
709 SBit s = LeaveCC, Condition cond = al);
710
711 void umull(Register dstL, Register dstH, Register src1, Register src2,
712 SBit s = LeaveCC, Condition cond = al);
713
714 // Miscellaneous arithmetic instructions
715
716 void clz(Register dst, Register src, Condition cond = al); // v5 and above
717
718 // Status register access instructions
719
720 void mrs(Register dst, SRegister s, Condition cond = al);
721 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
722
723 // Load/Store instructions
724 void ldr(Register dst, const MemOperand& src, Condition cond = al);
725 void str(Register src, const MemOperand& dst, Condition cond = al);
726 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
727 void strb(Register src, const MemOperand& dst, Condition cond = al);
728 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
729 void strh(Register src, const MemOperand& dst, Condition cond = al);
730 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
731 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
732
733 // Load/Store multiple instructions
734 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
735 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
736
737 // Semaphore instructions
738 void swp(Register dst, Register src, Register base, Condition cond = al);
739 void swpb(Register dst, Register src, Register base, Condition cond = al);
740
741 // Exception-generating instructions and debugging support
742 void stop(const char* msg);
743
744 void bkpt(uint32_t imm16); // v5 and above
745 void swi(uint32_t imm24, Condition cond = al);
746
747 // Coprocessor instructions
748
749 void cdp(Coprocessor coproc, int opcode_1,
750 CRegister crd, CRegister crn, CRegister crm,
751 int opcode_2, Condition cond = al);
752
753 void cdp2(Coprocessor coproc, int opcode_1,
754 CRegister crd, CRegister crn, CRegister crm,
755 int opcode_2); // v5 and above
756
757 void mcr(Coprocessor coproc, int opcode_1,
758 Register rd, CRegister crn, CRegister crm,
759 int opcode_2 = 0, Condition cond = al);
760
761 void mcr2(Coprocessor coproc, int opcode_1,
762 Register rd, CRegister crn, CRegister crm,
763 int opcode_2 = 0); // v5 and above
764
765 void mrc(Coprocessor coproc, int opcode_1,
766 Register rd, CRegister crn, CRegister crm,
767 int opcode_2 = 0, Condition cond = al);
768
769 void mrc2(Coprocessor coproc, int opcode_1,
770 Register rd, CRegister crn, CRegister crm,
771 int opcode_2 = 0); // v5 and above
772
773 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
774 LFlag l = Short, Condition cond = al);
775 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
776 LFlag l = Short, Condition cond = al);
777
778 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
779 LFlag l = Short); // v5 and above
780 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
781 LFlag l = Short); // v5 and above
782
783 void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst,
784 LFlag l = Short, Condition cond = al);
785 void stc(Coprocessor coproc, CRegister crd, Register base, int option,
786 LFlag l = Short, Condition cond = al);
787
788 void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst,
789 LFlag l = Short); // v5 and above
790 void stc2(Coprocessor coproc, CRegister crd, Register base, int option,
791 LFlag l = Short); // v5 and above
792
Steve Blockd0582a62009-12-15 09:54:21 +0000793 // Support for VFP.
794 // All these APIs support S0 to S31 and D0 to D15.
795 // Currently these APIs do not support extended D registers, i.e, D16 to D31.
796 // However, some simple modifications can allow
797 // these APIs to support D16 to D31.
798
Leon Clarkee46be812010-01-19 14:06:41 +0000799 void vmov(const DwVfpRegister dst,
800 const Register src1,
Steve Blockd0582a62009-12-15 09:54:21 +0000801 const Register src2,
Leon Clarkee46be812010-01-19 14:06:41 +0000802 const Condition cond = al);
803 void vmov(const Register dst1,
804 const Register dst2,
805 const DwVfpRegister src,
806 const Condition cond = al);
807 void vmov(const SwVfpRegister dst,
808 const Register src,
809 const Condition cond = al);
810 void vmov(const Register dst,
811 const SwVfpRegister src,
812 const Condition cond = al);
813 void vcvt(const DwVfpRegister dst,
814 const SwVfpRegister src,
815 const Condition cond = al);
816 void vcvt(const SwVfpRegister dst,
817 const DwVfpRegister src,
818 const Condition cond = al);
819
820 void vadd(const DwVfpRegister dst,
821 const DwVfpRegister src1,
822 const DwVfpRegister src2,
823 const Condition cond = al);
824 void vsub(const DwVfpRegister dst,
825 const DwVfpRegister src1,
826 const DwVfpRegister src2,
827 const Condition cond = al);
828 void vmul(const DwVfpRegister dst,
829 const DwVfpRegister src1,
830 const DwVfpRegister src2,
831 const Condition cond = al);
832 void vdiv(const DwVfpRegister dst,
833 const DwVfpRegister src1,
834 const DwVfpRegister src2,
835 const Condition cond = al);
836 void vcmp(const DwVfpRegister src1,
837 const DwVfpRegister src2,
Steve Blockd0582a62009-12-15 09:54:21 +0000838 const SBit s = LeaveCC,
839 const Condition cond = al);
840 void vmrs(const Register dst,
841 const Condition cond = al);
842
Steve Blocka7e24c12009-10-30 11:49:00 +0000843 // Pseudo instructions
844 void nop() { mov(r0, Operand(r0)); }
845
846 void push(Register src, Condition cond = al) {
847 str(src, MemOperand(sp, 4, NegPreIndex), cond);
848 }
849
850 void pop(Register dst, Condition cond = al) {
851 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
852 }
853
854 void pop() {
855 add(sp, sp, Operand(kPointerSize));
856 }
857
858 // Load effective address of memory operand x into register dst
859 void lea(Register dst, const MemOperand& x,
860 SBit s = LeaveCC, Condition cond = al);
861
862 // Jump unconditionally to given label.
863 void jmp(Label* L) { b(L, al); }
864
865 // Check the code size generated from label to here.
866 int InstructionsGeneratedSince(Label* l) {
867 return (pc_offset() - l->pos()) / kInstrSize;
868 }
869
Steve Blockd0582a62009-12-15 09:54:21 +0000870 // Check whether an immediate fits an addressing mode 1 instruction.
871 bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
872
873 // Postpone the generation of the constant pool for the specified number of
874 // instructions.
875 void BlockConstPoolFor(int instructions);
876
Steve Blocka7e24c12009-10-30 11:49:00 +0000877 // Debugging
878
879 // Mark address of the ExitJSFrame code.
880 void RecordJSReturn();
881
882 // Record a comment relocation entry that can be used by a disassembler.
883 // Use --debug_code to enable.
884 void RecordComment(const char* msg);
885
886 void RecordPosition(int pos);
887 void RecordStatementPosition(int pos);
888 void WriteRecordedPositions();
889
890 int pc_offset() const { return pc_ - buffer_; }
891 int current_position() const { return current_position_; }
892 int current_statement_position() const { return current_position_; }
893
894 protected:
895 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
896
897 // Read/patch instructions
898 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
899 void instr_at_put(byte* pc, Instr instr) {
900 *reinterpret_cast<Instr*>(pc) = instr;
901 }
902 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
903 void instr_at_put(int pos, Instr instr) {
904 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
905 }
906
907 // Decode branch instruction at pos and return branch target pos
908 int target_at(int pos);
909
910 // Patch branch instruction at pos to branch to given branch target pos
911 void target_at_put(int pos, int target_pos);
912
913 // Check if is time to emit a constant pool for pending reloc info entries
914 void CheckConstPool(bool force_emit, bool require_jump);
915
916 // Block the emission of the constant pool before pc_offset
917 void BlockConstPoolBefore(int pc_offset) {
918 if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
919 }
920
921 private:
922 // Code buffer:
923 // The buffer into which code and relocation info are generated.
924 byte* buffer_;
925 int buffer_size_;
926 // True if the assembler owns the buffer, false if buffer is external.
927 bool own_buffer_;
928
929 // Buffer size and constant pool distance are checked together at regular
930 // intervals of kBufferCheckInterval emitted bytes
931 static const int kBufferCheckInterval = 1*KB/2;
932 int next_buffer_check_; // pc offset of next buffer check
933
934 // Code generation
935 // The relocation writer's position is at least kGap bytes below the end of
936 // the generated instructions. This is so that multi-instruction sequences do
937 // not have to check for overflow. The same is true for writes of large
938 // relocation info entries.
939 static const int kGap = 32;
940 byte* pc_; // the program counter; moves forward
941
942 // Constant pool generation
943 // Pools are emitted in the instruction stream, preferably after unconditional
944 // jumps or after returns from functions (in dead code locations).
945 // If a long code sequence does not contain unconditional jumps, it is
946 // necessary to emit the constant pool before the pool gets too far from the
947 // location it is accessed from. In this case, we emit a jump over the emitted
948 // constant pool.
949 // Constants in the pool may be addresses of functions that gets relocated;
950 // if so, a relocation info entry is associated to the constant pool entry.
951
952 // Repeated checking whether the constant pool should be emitted is rather
953 // expensive. By default we only check again once a number of instructions
954 // has been generated. That also means that the sizing of the buffers is not
955 // an exact science, and that we rely on some slop to not overrun buffers.
956 static const int kCheckConstIntervalInst = 32;
957 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
958
959
960 // Pools are emitted after function return and in dead code at (more or less)
961 // regular intervals of kDistBetweenPools bytes
962 static const int kDistBetweenPools = 1*KB;
963
964 // Constants in pools are accessed via pc relative addressing, which can
965 // reach +/-4KB thereby defining a maximum distance between the instruction
966 // and the accessed constant. We satisfy this constraint by limiting the
967 // distance between pools.
968 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval;
969
970 // Emission of the constant pool may be blocked in some code sequences
971 int no_const_pool_before_; // block emission before this pc offset
972
973 // Keep track of the last emitted pool to guarantee a maximal distance
974 int last_const_pool_end_; // pc offset following the last constant pool
975
976 // Relocation info generation
977 // Each relocation is encoded as a variable size value
978 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
979 RelocInfoWriter reloc_info_writer;
980 // Relocation info records are also used during code generation as temporary
981 // containers for constants and code target addresses until they are emitted
982 // to the constant pool. These pending relocation info records are temporarily
983 // stored in a separate buffer until a constant pool is emitted.
984 // If every instruction in a long sequence is accessing the pool, we need one
985 // pending relocation entry per instruction.
986 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
987 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info
988 int num_prinfo_; // number of pending reloc info entries in the buffer
989
990 // The bound position, before this we cannot do instruction elimination.
991 int last_bound_pos_;
992
993 // source position information
994 int current_position_;
995 int current_statement_position_;
996 int written_position_;
997 int written_statement_position_;
998
999 // Code emission
1000 inline void CheckBuffer();
1001 void GrowBuffer();
1002 inline void emit(Instr x);
1003
1004 // Instruction generation
1005 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1006 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1007 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1008 void addrmod4(Instr instr, Register rn, RegList rl);
1009 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1010
1011 // Labels
1012 void print(Label* L);
1013 void bind_to(Label* L, int pos);
1014 void link_to(Label* L, Label* appendix);
1015 void next(Label* L);
1016
1017 // Record reloc info for current pc_
1018 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1019
1020 friend class RegExpMacroAssemblerARM;
1021 friend class RelocInfo;
1022 friend class CodePatcher;
1023};
1024
1025} } // namespace v8::internal
1026
1027#endif // V8_ARM_ASSEMBLER_ARM_H_