Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: src/arm/assembler-thumb2.h

Issue 2080017: Remove the fledgling Thumb2 support since we are concentrating... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/assembler-arm.cc ('k') | src/arm/assembler-thumb2.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_THUMB2_H_
41 #define V8_ARM_ASSEMBLER_THUMB2_H_
42 #include <stdio.h>
43 #include "assembler.h"
44 #include "serialize.h"
45
46 namespace v8 {
47 namespace 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
71 struct 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
88 extern Register no_reg;
89 extern Register r0;
90 extern Register r1;
91 extern Register r2;
92 extern Register r3;
93 extern Register r4;
94 extern Register r5;
95 extern Register r6;
96 extern Register r7;
97 extern Register r8;
98 extern Register r9;
99 extern Register r10;
100 extern Register fp;
101 extern Register ip;
102 extern Register sp;
103 extern Register lr;
104 extern Register pc;
105
106
107 // Single word VFP register.
108 struct 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.
125 struct 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)".
144 extern SwVfpRegister s0;
145 extern SwVfpRegister s1;
146 extern SwVfpRegister s2;
147 extern SwVfpRegister s3;
148 extern SwVfpRegister s4;
149 extern SwVfpRegister s5;
150 extern SwVfpRegister s6;
151 extern SwVfpRegister s7;
152 extern SwVfpRegister s8;
153 extern SwVfpRegister s9;
154 extern SwVfpRegister s10;
155 extern SwVfpRegister s11;
156 extern SwVfpRegister s12;
157 extern SwVfpRegister s13;
158 extern SwVfpRegister s14;
159 extern SwVfpRegister s15;
160 extern SwVfpRegister s16;
161 extern SwVfpRegister s17;
162 extern SwVfpRegister s18;
163 extern SwVfpRegister s19;
164 extern SwVfpRegister s20;
165 extern SwVfpRegister s21;
166 extern SwVfpRegister s22;
167 extern SwVfpRegister s23;
168 extern SwVfpRegister s24;
169 extern SwVfpRegister s25;
170 extern SwVfpRegister s26;
171 extern SwVfpRegister s27;
172 extern SwVfpRegister s28;
173 extern SwVfpRegister s29;
174 extern SwVfpRegister s30;
175 extern SwVfpRegister s31;
176
177 extern DwVfpRegister d0;
178 extern DwVfpRegister d1;
179 extern DwVfpRegister d2;
180 extern DwVfpRegister d3;
181 extern DwVfpRegister d4;
182 extern DwVfpRegister d5;
183 extern DwVfpRegister d6;
184 extern DwVfpRegister d7;
185 extern DwVfpRegister d8;
186 extern DwVfpRegister d9;
187 extern DwVfpRegister d10;
188 extern DwVfpRegister d11;
189 extern DwVfpRegister d12;
190 extern DwVfpRegister d13;
191 extern DwVfpRegister d14;
192 extern DwVfpRegister d15;
193
194
195 // Coprocessor register
196 struct 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
213 extern CRegister no_creg;
214 extern CRegister cr0;
215 extern CRegister cr1;
216 extern CRegister cr2;
217 extern CRegister cr3;
218 extern CRegister cr4;
219 extern CRegister cr5;
220 extern CRegister cr6;
221 extern CRegister cr7;
222 extern CRegister cr8;
223 extern CRegister cr9;
224 extern CRegister cr10;
225 extern CRegister cr11;
226 extern CRegister cr12;
227 extern CRegister cr13;
228 extern CRegister cr14;
229 extern CRegister cr15;
230
231
232 // Coprocessor number
233 enum 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.
254 enum 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.
277 INLINE(Condition NegateCondition(Condition cc));
278
279
280 // Corresponds to transposing the operands of a comparison.
281 inline 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.
308 enum Hint { no_hint };
309
310 // Hints are not used on the arm. Negating is trivial.
311 inline Hint NegateHint(Hint ignored) { return no_hint; }
312
313
314 // -----------------------------------------------------------------------------
315 // Addressing modes and instruction variants
316
317 // Shifter operand shift operation
318 enum 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
328 enum SBit {
329 SetCC = 1 << 20, // set condition code
330 LeaveCC = 0 << 20 // leave condition code unchanged
331 };
332
333
334 // Status register selection
335 enum SRegister {
336 CPSR = 0 << 22,
337 SPSR = 1 << 22
338 };
339
340
341 // Status register fields
342 enum 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)
354 typedef uint32_t SRegisterFieldMask;
355
356
357 // Memory operand addressing mode
358 enum 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
370 enum 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
384 enum 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
394 class 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
431 class 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.
464 class 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
508 typedef int32_t Instr;
509
510
511 extern const Instr kMovLrPc;
512 extern const Instr kLdrPCPattern;
513
514
515 class 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 // Exception-generating instructions and debugging support
739 void stop(const char* msg);
740
741 void bkpt(uint32_t imm16); // v5 and above
742 void swi(uint32_t imm24, Condition cond = al);
743
744 // Coprocessor instructions
745
746 void cdp(Coprocessor coproc, int opcode_1,
747 CRegister crd, CRegister crn, CRegister crm,
748 int opcode_2, Condition cond = al);
749
750 void cdp2(Coprocessor coproc, int opcode_1,
751 CRegister crd, CRegister crn, CRegister crm,
752 int opcode_2); // v5 and above
753
754 void mcr(Coprocessor coproc, int opcode_1,
755 Register rd, CRegister crn, CRegister crm,
756 int opcode_2 = 0, Condition cond = al);
757
758 void mcr2(Coprocessor coproc, int opcode_1,
759 Register rd, CRegister crn, CRegister crm,
760 int opcode_2 = 0); // v5 and above
761
762 void mrc(Coprocessor coproc, int opcode_1,
763 Register rd, CRegister crn, CRegister crm,
764 int opcode_2 = 0, Condition cond = al);
765
766 void mrc2(Coprocessor coproc, int opcode_1,
767 Register rd, CRegister crn, CRegister crm,
768 int opcode_2 = 0); // v5 and above
769
770 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
771 LFlag l = Short, Condition cond = al);
772 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
773 LFlag l = Short, Condition cond = al);
774
775 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
776 LFlag l = Short); // v5 and above
777 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
778 LFlag l = Short); // v5 and above
779
780 void stc(Coprocessor coproc, CRegister crd, const MemOperand& dst,
781 LFlag l = Short, Condition cond = al);
782 void stc(Coprocessor coproc, CRegister crd, Register base, int option,
783 LFlag l = Short, Condition cond = al);
784
785 void stc2(Coprocessor coproc, CRegister crd, const MemOperand& dst,
786 LFlag l = Short); // v5 and above
787 void stc2(Coprocessor coproc, CRegister crd, Register base, int option,
788 LFlag l = Short); // v5 and above
789
790 // Support for VFP.
791 // All these APIs support S0 to S31 and D0 to D15.
792 // Currently these APIs do not support extended D registers, i.e, D16 to D31.
793 // However, some simple modifications can allow
794 // these APIs to support D16 to D31.
795
796 void vldr(const DwVfpRegister dst,
797 const Register base,
798 int offset, // Offset must be a multiple of 4.
799 const Condition cond = al);
800 void vstr(const DwVfpRegister src,
801 const Register base,
802 int offset, // Offset must be a multiple of 4.
803 const Condition cond = al);
804 void vmov(const DwVfpRegister dst,
805 const Register src1,
806 const Register src2,
807 const Condition cond = al);
808 void vmov(const Register dst1,
809 const Register dst2,
810 const DwVfpRegister src,
811 const Condition cond = al);
812 void vmov(const SwVfpRegister dst,
813 const Register src,
814 const Condition cond = al);
815 void vmov(const Register dst,
816 const SwVfpRegister src,
817 const Condition cond = al);
818 void vcvt(const DwVfpRegister dst,
819 const SwVfpRegister src,
820 const Condition cond = al);
821 void vcvt(const SwVfpRegister dst,
822 const DwVfpRegister src,
823 const Condition cond = al);
824
825 void vadd(const DwVfpRegister dst,
826 const DwVfpRegister src1,
827 const DwVfpRegister src2,
828 const Condition cond = al);
829 void vsub(const DwVfpRegister dst,
830 const DwVfpRegister src1,
831 const DwVfpRegister src2,
832 const Condition cond = al);
833 void vmul(const DwVfpRegister dst,
834 const DwVfpRegister src1,
835 const DwVfpRegister src2,
836 const Condition cond = al);
837 void vdiv(const DwVfpRegister dst,
838 const DwVfpRegister src1,
839 const DwVfpRegister src2,
840 const Condition cond = al);
841 void vcmp(const DwVfpRegister src1,
842 const DwVfpRegister src2,
843 const SBit s = LeaveCC,
844 const Condition cond = al);
845 void vmrs(const Register dst,
846 const Condition cond = al);
847
848 // Pseudo instructions
849 void nop() { mov(r0, Operand(r0)); }
850
851 void push(Register src, Condition cond = al) {
852 str(src, MemOperand(sp, 4, NegPreIndex), cond);
853 }
854
855 void pop(Register dst, Condition cond = al) {
856 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
857 }
858
859 void pop() {
860 add(sp, sp, Operand(kPointerSize));
861 }
862
863 // Jump unconditionally to given label.
864 void jmp(Label* L) { b(L, al); }
865
866 // Check the code size generated from label to here.
867 int InstructionsGeneratedSince(Label* l) {
868 return (pc_offset() - l->pos()) / kInstrSize;
869 }
870
871 // Check whether an immediate fits an addressing mode 1 instruction.
872 bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
873
874 // Postpone the generation of the constant pool for the specified number of
875 // instructions.
876 void BlockConstPoolFor(int instructions);
877
878 // Debugging
879
880 // Mark address of the ExitJSFrame code.
881 void RecordJSReturn();
882
883 // Record a comment relocation entry that can be used by a disassembler.
884 // Use --debug_code to enable.
885 void RecordComment(const char* msg);
886
887 void RecordPosition(int pos);
888 void RecordStatementPosition(int pos);
889 void WriteRecordedPositions();
890
891 int pc_offset() const { return pc_ - buffer_; }
892 int current_position() const { return current_position_; }
893 int current_statement_position() const { return current_statement_position_; }
894
895 protected:
896 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
897
898 // Read/patch instructions
899 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
900 void instr_at_put(byte* pc, Instr instr) {
901 *reinterpret_cast<Instr*>(pc) = instr;
902 }
903 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
904 void instr_at_put(int pos, Instr instr) {
905 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
906 }
907
908 // Decode branch instruction at pos and return branch target pos
909 int target_at(int pos);
910
911 // Patch branch instruction at pos to branch to given branch target pos
912 void target_at_put(int pos, int target_pos);
913
914 // Check if is time to emit a constant pool for pending reloc info entries
915 void CheckConstPool(bool force_emit, bool require_jump);
916
917 // Block the emission of the constant pool before pc_offset
918 void BlockConstPoolBefore(int pc_offset) {
919 if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
920 }
921
922 private:
923 // Code buffer:
924 // The buffer into which code and relocation info are generated.
925 byte* buffer_;
926 int buffer_size_;
927 // True if the assembler owns the buffer, false if buffer is external.
928 bool own_buffer_;
929
930 // Buffer size and constant pool distance are checked together at regular
931 // intervals of kBufferCheckInterval emitted bytes
932 static const int kBufferCheckInterval = 1*KB/2;
933 int next_buffer_check_; // pc offset of next buffer check
934
935 // Code generation
936 // The relocation writer's position is at least kGap bytes below the end of
937 // the generated instructions. This is so that multi-instruction sequences do
938 // not have to check for overflow. The same is true for writes of large
939 // relocation info entries.
940 static const int kGap = 32;
941 byte* pc_; // the program counter; moves forward
942
943 // Constant pool generation
944 // Pools are emitted in the instruction stream, preferably after unconditional
945 // jumps or after returns from functions (in dead code locations).
946 // If a long code sequence does not contain unconditional jumps, it is
947 // necessary to emit the constant pool before the pool gets too far from the
948 // location it is accessed from. In this case, we emit a jump over the emitted
949 // constant pool.
950 // Constants in the pool may be addresses of functions that gets relocated;
951 // if so, a relocation info entry is associated to the constant pool entry.
952
953 // Repeated checking whether the constant pool should be emitted is rather
954 // expensive. By default we only check again once a number of instructions
955 // has been generated. That also means that the sizing of the buffers is not
956 // an exact science, and that we rely on some slop to not overrun buffers.
957 static const int kCheckConstIntervalInst = 32;
958 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
959
960
961 // Pools are emitted after function return and in dead code at (more or less)
962 // regular intervals of kDistBetweenPools bytes
963 static const int kDistBetweenPools = 1*KB;
964
965 // Constants in pools are accessed via pc relative addressing, which can
966 // reach +/-4KB thereby defining a maximum distance between the instruction
967 // and the accessed constant. We satisfy this constraint by limiting the
968 // distance between pools.
969 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval;
970
971 // Emission of the constant pool may be blocked in some code sequences
972 int no_const_pool_before_; // block emission before this pc offset
973
974 // Keep track of the last emitted pool to guarantee a maximal distance
975 int last_const_pool_end_; // pc offset following the last constant pool
976
977 // Relocation info generation
978 // Each relocation is encoded as a variable size value
979 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
980 RelocInfoWriter reloc_info_writer;
981 // Relocation info records are also used during code generation as temporary
982 // containers for constants and code target addresses until they are emitted
983 // to the constant pool. These pending relocation info records are temporarily
984 // stored in a separate buffer until a constant pool is emitted.
985 // If every instruction in a long sequence is accessing the pool, we need one
986 // pending relocation entry per instruction.
987 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
988 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info
989 int num_prinfo_; // number of pending reloc info entries in the buffer
990
991 // The bound position, before this we cannot do instruction elimination.
992 int last_bound_pos_;
993
994 // source position information
995 int current_position_;
996 int current_statement_position_;
997 int written_position_;
998 int written_statement_position_;
999
1000 // Code emission
1001 inline void CheckBuffer();
1002 void GrowBuffer();
1003 inline void emit(Instr x);
1004
1005 // Instruction generation
1006 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1007 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1008 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1009 void addrmod4(Instr instr, Register rn, RegList rl);
1010 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1011
1012 // Labels
1013 void print(Label* L);
1014 void bind_to(Label* L, int pos);
1015 void link_to(Label* L, Label* appendix);
1016 void next(Label* L);
1017
1018 // Record reloc info for current pc_
1019 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1020
1021 friend class RegExpMacroAssemblerARM;
1022 friend class RelocInfo;
1023 friend class CodePatcher;
1024 };
1025
1026 } } // namespace v8::internal
1027
1028 #endif // V8_ARM_ASSEMBLER_THUMB2_H_
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.cc ('k') | src/arm/assembler-thumb2.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698