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

Side by Side Diff: src/ppc/assembler-ppc.h

Issue 422063005: Contribution of PowerPC port. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: re-upload - catch up to 8/19 level Created 6 years, 3 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
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 2012 the V8 project authors. All rights reserved.
36
37 //
38 // Copyright IBM Corp. 2012, 2013. All rights reserved.
39 //
40
41 // A light-weight PPC Assembler
42 // Generates user mode instructions for the PPC architecture up
43
44 #ifndef V8_PPC_ASSEMBLER_PPC_H_
45 #define V8_PPC_ASSEMBLER_PPC_H_
46
47 #include <stdio.h>
48 #include <vector>
49
50 #include "src/assembler.h"
51 #include "src/ppc/constants-ppc.h"
52 #include "src/serialize.h"
53
54 #define ABI_USES_FUNCTION_DESCRIPTORS \
55 (V8_HOST_ARCH_PPC && (V8_OS_AIX || \
56 (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN)))
57
58 #define ABI_PASSES_HANDLES_IN_REGS \
59 (!V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64)
60
61 #define ABI_RETURNS_HANDLES_IN_REGS \
62 (!V8_HOST_ARCH_PPC || V8_TARGET_LITTLE_ENDIAN)
63
64 #define ABI_RETURNS_OBJECT_PAIRS_IN_REGS \
65 (!V8_HOST_ARCH_PPC || V8_TARGET_LITTLE_ENDIAN)
66
67 #define ABI_TOC_ADDRESSABILITY_VIA_IP \
68 (V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
69
70 #if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
71 #define ABI_TOC_REGISTER kRegister_r2_Code
72 #else
73 #define ABI_TOC_REGISTER kRegister_r13_Code
74 #endif
75
76 namespace v8 {
77 namespace internal {
78
79 // CPU Registers.
80 //
81 // 1) We would prefer to use an enum, but enum values are assignment-
82 // compatible with int, which has caused code-generation bugs.
83 //
84 // 2) We would prefer to use a class instead of a struct but we don't like
85 // the register initialization to depend on the particular initialization
86 // order (which appears to be different on OS X, Linux, and Windows for the
87 // installed versions of C++ we tried). Using a struct permits C-style
88 // "initialization". Also, the Register objects cannot be const as this
89 // forces initialization stubs in MSVC, making us dependent on initialization
90 // order.
91 //
92 // 3) By not using an enum, we are possibly preventing the compiler from
93 // doing certain constant folds, which may significantly reduce the
94 // code generated for some assembly instructions (because they boil down
95 // to a few constants). If this is a problem, we could change the code
96 // such that we use an enum in optimized mode, and the struct in debug
97 // mode. This way we get the compile-time error checking in debug mode
98 // and best performance in optimized code.
99
100 // Core register
101 struct Register {
102 static const int kNumRegisters = 32;
103 static const int kSizeInBytes = kPointerSize;
104
105 #if V8_TARGET_LITTLE_ENDIAN
106 static const int kMantissaOffset = 0;
107 static const int kExponentOffset = 4;
108 #else
109 static const int kMantissaOffset = 4;
110 static const int kExponentOffset = 0;
111 #endif
112
113 static const int kAllocatableLowRangeBegin = 3;
114 static const int kAllocatableLowRangeEnd = 10;
115 static const int kAllocatableHighRangeBegin = 14;
116 #if V8_OOL_CONSTANT_POOL
117 static const int kAllocatableHighRangeEnd = 27;
118 #else
119 static const int kAllocatableHighRangeEnd = 28;
120 #endif
121 static const int kAllocatableContext = 30;
122
123 static const int kNumAllocatableLow =
124 kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1;
125 static const int kNumAllocatableHigh =
126 kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1;
127 static const int kMaxNumAllocatableRegisters =
128 kNumAllocatableLow + kNumAllocatableHigh + 1; // cp
129 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
130
131 static int ToAllocationIndex(Register reg) {
132 int index;
133 int code = reg.code();
134 if (code == kAllocatableContext) {
135 // Context is the last index
136 index = NumAllocatableRegisters() - 1;
137 } else if (code <= kAllocatableLowRangeEnd) {
138 // low range
139 index = code - kAllocatableLowRangeBegin;
140 } else {
141 // high range
142 index = code - kAllocatableHighRangeBegin + kNumAllocatableLow;
143 }
144 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
145 return index;
146 }
147
148 static Register FromAllocationIndex(int index) {
149 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
150 // Last index is always the 'cp' register.
151 if (index == kMaxNumAllocatableRegisters - 1) {
152 return from_code(kAllocatableContext);
153 }
154 return (index < kNumAllocatableLow)
155 ? from_code(index + kAllocatableLowRangeBegin)
156 : from_code(index - kNumAllocatableLow +
157 kAllocatableHighRangeBegin);
158 }
159
160 static const char* AllocationIndexToString(int index) {
161 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
162 const char* const names[] = {
163 "r3",
164 "r4",
165 "r5",
166 "r6",
167 "r7",
168 "r8",
169 "r9",
170 "r10",
171 "r14",
172 "r15",
173 "r16",
174 "r17",
175 "r18",
176 "r19",
177 "r20",
178 "r21",
179 "r22",
180 "r23",
181 "r24",
182 "r25",
183 "r26",
184 "r27",
185 #if !V8_OOL_CONSTANT_POOL
186 "r28",
187 #endif
188 "cp",
189 };
190 return names[index];
191 }
192
193 static Register from_code(int code) {
194 Register r = {code};
195 return r;
196 }
197
198 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
199 bool is(Register reg) const { return code_ == reg.code_; }
200 int code() const {
201 DCHECK(is_valid());
202 return code_;
203 }
204 int bit() const {
205 DCHECK(is_valid());
206 return 1 << code_;
207 }
208
209 void set_code(int code) {
210 code_ = code;
211 DCHECK(is_valid());
212 }
213
214 // Unfortunately we can't make this private in a struct.
215 int code_;
216 };
217
218 // These constants are used in several locations, including static initializers
219 const int kRegister_no_reg_Code = -1;
220 const int kRegister_r0_Code = 0; // general scratch
221 const int kRegister_sp_Code = 1; // stack pointer
222 const int kRegister_r2_Code = 2; // special on PowerPC
223 const int kRegister_r3_Code = 3;
224 const int kRegister_r4_Code = 4;
225 const int kRegister_r5_Code = 5;
226 const int kRegister_r6_Code = 6;
227 const int kRegister_r7_Code = 7;
228 const int kRegister_r8_Code = 8;
229 const int kRegister_r9_Code = 9;
230 const int kRegister_r10_Code = 10;
231 const int kRegister_r11_Code = 11; // lithium scratch
232 const int kRegister_ip_Code = 12; // ip (general scratch)
233 const int kRegister_r13_Code = 13; // special on PowerPC
234 const int kRegister_r14_Code = 14;
235 const int kRegister_r15_Code = 15;
236
237 const int kRegister_r16_Code = 16;
238 const int kRegister_r17_Code = 17;
239 const int kRegister_r18_Code = 18;
240 const int kRegister_r19_Code = 19;
241 const int kRegister_r20_Code = 20;
242 const int kRegister_r21_Code = 21;
243 const int kRegister_r22_Code = 22;
244 const int kRegister_r23_Code = 23;
245 const int kRegister_r24_Code = 24;
246 const int kRegister_r25_Code = 25;
247 const int kRegister_r26_Code = 26;
248 const int kRegister_r27_Code = 27;
249 const int kRegister_r28_Code = 28; // constant pool pointer
250 const int kRegister_r29_Code = 29; // roots array pointer
251 const int kRegister_r30_Code = 30; // context pointer
252 const int kRegister_fp_Code = 31; // frame pointer
253
254 const Register no_reg = {kRegister_no_reg_Code};
255
256 const Register r0 = {kRegister_r0_Code};
257 const Register sp = {kRegister_sp_Code};
258 const Register r2 = {kRegister_r2_Code};
259 const Register r3 = {kRegister_r3_Code};
260 const Register r4 = {kRegister_r4_Code};
261 const Register r5 = {kRegister_r5_Code};
262 const Register r6 = {kRegister_r6_Code};
263 const Register r7 = {kRegister_r7_Code};
264 const Register r8 = {kRegister_r8_Code};
265 const Register r9 = {kRegister_r9_Code};
266 const Register r10 = {kRegister_r10_Code};
267 const Register r11 = {kRegister_r11_Code};
268 const Register ip = {kRegister_ip_Code};
269 const Register r13 = {kRegister_r13_Code};
270 const Register r14 = {kRegister_r14_Code};
271 const Register r15 = {kRegister_r15_Code};
272
273 const Register r16 = {kRegister_r16_Code};
274 const Register r17 = {kRegister_r17_Code};
275 const Register r18 = {kRegister_r18_Code};
276 const Register r19 = {kRegister_r19_Code};
277 const Register r20 = {kRegister_r20_Code};
278 const Register r21 = {kRegister_r21_Code};
279 const Register r22 = {kRegister_r22_Code};
280 const Register r23 = {kRegister_r23_Code};
281 const Register r24 = {kRegister_r24_Code};
282 const Register r25 = {kRegister_r25_Code};
283 const Register r26 = {kRegister_r26_Code};
284 const Register r27 = {kRegister_r27_Code};
285 const Register r28 = {kRegister_r28_Code};
286 const Register r29 = {kRegister_r29_Code};
287 const Register r30 = {kRegister_r30_Code};
288 const Register fp = {kRegister_fp_Code};
289
290 // Give alias names to registers
291 const Register cp = {kRegister_r30_Code}; // JavaScript context pointer
292 const Register kRootRegister = {kRegister_r29_Code}; // Roots array pointer.
293 #if V8_OOL_CONSTANT_POOL
294 const Register kConstantPoolRegister = {kRegister_r28_Code}; // Constant pool
295 #endif
296
297 // Double word FP register.
298 struct DoubleRegister {
299 static const int kNumRegisters = 32;
300 static const int kMaxNumRegisters = kNumRegisters;
301 static const int kNumVolatileRegisters = 14; // d0-d13
302 static const int kSizeInBytes = 8;
303
304 static const int kAllocatableLowRangeBegin = 1;
305 static const int kAllocatableLowRangeEnd = 12;
306 static const int kAllocatableHighRangeBegin = 15;
307 static const int kAllocatableHighRangeEnd = 31;
308
309 static const int kNumAllocatableLow =
310 kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1;
311 static const int kNumAllocatableHigh =
312 kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1;
313 static const int kMaxNumAllocatableRegisters =
314 kNumAllocatableLow + kNumAllocatableHigh;
315 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
316
317 static int ToAllocationIndex(DoubleRegister reg) {
318 int code = reg.code();
319 int index = (code <= kAllocatableLowRangeEnd)
320 ? code - kAllocatableLowRangeBegin
321 : code - kAllocatableHighRangeBegin + kNumAllocatableLow;
322 DCHECK(index < kMaxNumAllocatableRegisters);
323 return index;
324 }
325
326 static DoubleRegister FromAllocationIndex(int index) {
327 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
328 return (index < kNumAllocatableLow)
329 ? from_code(index + kAllocatableLowRangeBegin)
330 : from_code(index - kNumAllocatableLow +
331 kAllocatableHighRangeBegin);
332 }
333
334 static const char* AllocationIndexToString(int index);
335
336 static DoubleRegister from_code(int code) {
337 DoubleRegister r = {code};
338 return r;
339 }
340
341 bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; }
342 bool is(DoubleRegister reg) const { return code_ == reg.code_; }
343
344 int code() const {
345 DCHECK(is_valid());
346 return code_;
347 }
348 int bit() const {
349 DCHECK(is_valid());
350 return 1 << code_;
351 }
352 void split_code(int* vm, int* m) const {
353 DCHECK(is_valid());
354 *m = (code_ & 0x10) >> 4;
355 *vm = code_ & 0x0F;
356 }
357
358 int code_;
359 };
360
361
362 const DoubleRegister no_dreg = {-1};
363 const DoubleRegister d0 = {0};
364 const DoubleRegister d1 = {1};
365 const DoubleRegister d2 = {2};
366 const DoubleRegister d3 = {3};
367 const DoubleRegister d4 = {4};
368 const DoubleRegister d5 = {5};
369 const DoubleRegister d6 = {6};
370 const DoubleRegister d7 = {7};
371 const DoubleRegister d8 = {8};
372 const DoubleRegister d9 = {9};
373 const DoubleRegister d10 = {10};
374 const DoubleRegister d11 = {11};
375 const DoubleRegister d12 = {12};
376 const DoubleRegister d13 = {13};
377 const DoubleRegister d14 = {14};
378 const DoubleRegister d15 = {15};
379 const DoubleRegister d16 = {16};
380 const DoubleRegister d17 = {17};
381 const DoubleRegister d18 = {18};
382 const DoubleRegister d19 = {19};
383 const DoubleRegister d20 = {20};
384 const DoubleRegister d21 = {21};
385 const DoubleRegister d22 = {22};
386 const DoubleRegister d23 = {23};
387 const DoubleRegister d24 = {24};
388 const DoubleRegister d25 = {25};
389 const DoubleRegister d26 = {26};
390 const DoubleRegister d27 = {27};
391 const DoubleRegister d28 = {28};
392 const DoubleRegister d29 = {29};
393 const DoubleRegister d30 = {30};
394 const DoubleRegister d31 = {31};
395
396 // Aliases for double registers. Defined using #define instead of
397 // "static const DoubleRegister&" because Clang complains otherwise when a
398 // compilation unit that includes this header doesn't use the variables.
399 #define kFirstCalleeSavedDoubleReg d14
400 #define kLastCalleeSavedDoubleReg d31
401 #define kDoubleRegZero d14
402 #define kScratchDoubleReg d13
403
404 Register ToRegister(int num);
405
406 // Coprocessor register
407 struct CRegister {
408 bool is_valid() const { return 0 <= code_ && code_ < 16; }
409 bool is(CRegister creg) const { return code_ == creg.code_; }
410 int code() const {
411 DCHECK(is_valid());
412 return code_;
413 }
414 int bit() const {
415 DCHECK(is_valid());
416 return 1 << code_;
417 }
418
419 // Unfortunately we can't make this private in a struct.
420 int code_;
421 };
422
423
424 const CRegister no_creg = {-1};
425
426 const CRegister cr0 = {0};
427 const CRegister cr1 = {1};
428 const CRegister cr2 = {2};
429 const CRegister cr3 = {3};
430 const CRegister cr4 = {4};
431 const CRegister cr5 = {5};
432 const CRegister cr6 = {6};
433 const CRegister cr7 = {7};
434 const CRegister cr8 = {8};
435 const CRegister cr9 = {9};
436 const CRegister cr10 = {10};
437 const CRegister cr11 = {11};
438 const CRegister cr12 = {12};
439 const CRegister cr13 = {13};
440 const CRegister cr14 = {14};
441 const CRegister cr15 = {15};
442
443 // -----------------------------------------------------------------------------
444 // Machine instruction Operands
445
446 #if V8_TARGET_ARCH_PPC64
447 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64;
448 #else
449 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32;
450 #endif
451
452 // Class Operand represents a shifter operand in data processing instructions
453 class Operand BASE_EMBEDDED {
454 public:
455 // immediate
456 INLINE(explicit Operand(intptr_t immediate,
457 RelocInfo::Mode rmode = kRelocInfo_NONEPTR));
458 INLINE(static Operand Zero()) { return Operand(static_cast<intptr_t>(0)); }
459 INLINE(explicit Operand(const ExternalReference& f));
460 explicit Operand(Handle<Object> handle);
461 INLINE(explicit Operand(Smi* value));
462
463 // rm
464 INLINE(explicit Operand(Register rm));
465
466 // Return true if this is a register operand.
467 INLINE(bool is_reg() const);
468
469 // For mov. Return the number of actual instructions required to
470 // load the operand into a register. This can be anywhere from
471 // one (constant pool small section) to five instructions (full
472 // 64-bit sequence).
473 //
474 // The value returned is only valid as long as no entries are added to the
475 // constant pool between this call and the actual instruction being emitted.
476 bool must_output_reloc_info(const Assembler* assembler) const;
477
478 inline intptr_t immediate() const {
479 DCHECK(!rm_.is_valid());
480 return imm_;
481 }
482
483 Register rm() const { return rm_; }
484
485 private:
486 Register rm_;
487 intptr_t imm_; // valid if rm_ == no_reg
488 RelocInfo::Mode rmode_;
489
490 friend class Assembler;
491 friend class MacroAssembler;
492 };
493
494
495 // Class MemOperand represents a memory operand in load and store instructions
496 // On PowerPC we have base register + 16bit signed value
497 // Alternatively we can have a 16bit signed value immediate
498 class MemOperand BASE_EMBEDDED {
499 public:
500 explicit MemOperand(Register rn, int32_t offset = 0);
501
502 explicit MemOperand(Register ra, Register rb);
503
504 int32_t offset() const {
505 DCHECK(rb_.is(no_reg));
506 return offset_;
507 }
508
509 // PowerPC - base register
510 Register ra() const {
511 DCHECK(!ra_.is(no_reg));
512 return ra_;
513 }
514
515 Register rb() const {
516 DCHECK(offset_ == 0 && !rb_.is(no_reg));
517 return rb_;
518 }
519
520 private:
521 Register ra_; // base
522 int32_t offset_; // offset
523 Register rb_; // index
524
525 friend class Assembler;
526 };
527
528
529 #if V8_OOL_CONSTANT_POOL
530 // Class used to build a constant pool.
531 class ConstantPoolBuilder BASE_EMBEDDED {
532 public:
533 ConstantPoolBuilder();
534 ConstantPoolArray::LayoutSection AddEntry(Assembler* assm,
535 const RelocInfo& rinfo);
536 void Relocate(intptr_t pc_delta);
537 bool IsEmpty();
538 Handle<ConstantPoolArray> New(Isolate* isolate);
539 void Populate(Assembler* assm, ConstantPoolArray* constant_pool);
540
541 inline ConstantPoolArray::LayoutSection current_section() const {
542 return current_section_;
543 }
544
545 // Rather than increasing the capacity of the ConstantPoolArray's
546 // small section to match the longer (16-bit) reach of PPC's load
547 // instruction (at the expense of a larger header to describe the
548 // layout), the PPC implementation utilizes the extended section to
549 // satisfy that reach. I.e. all entries (regardless of their
550 // section) are reachable with a single load instruction.
551 //
552 // This implementation does not support an unlimited constant pool
553 // size (which would require a multi-instruction sequence). [See
554 // ARM commit e27ab337 for a reference on the changes required to
555 // support the longer instruction sequence.] Note, however, that
556 // going down that path will necessarily generate that longer
557 // sequence for all extended section accesses since the placement of
558 // a given entry within the section is not known at the time of
559 // code generation.
560 //
561 // TODO(mbrandy): Determine whether there is a benefit to supporting
562 // the longer sequence given that nops could be used for those
563 // entries which are reachable with a single instruction.
564 inline bool is_full() const { return !is_int16(size_); }
565
566 inline ConstantPoolArray::NumberOfEntries* number_of_entries(
567 ConstantPoolArray::LayoutSection section) {
568 return &number_of_entries_[section];
569 }
570
571 inline ConstantPoolArray::NumberOfEntries* small_entries() {
572 return number_of_entries(ConstantPoolArray::SMALL_SECTION);
573 }
574
575 inline ConstantPoolArray::NumberOfEntries* extended_entries() {
576 return number_of_entries(ConstantPoolArray::EXTENDED_SECTION);
577 }
578
579 private:
580 struct ConstantPoolEntry {
581 ConstantPoolEntry(RelocInfo rinfo, ConstantPoolArray::LayoutSection section,
582 int merged_index)
583 : rinfo_(rinfo), section_(section), merged_index_(merged_index) {}
584
585 RelocInfo rinfo_;
586 ConstantPoolArray::LayoutSection section_;
587 int merged_index_;
588 };
589
590 ConstantPoolArray::Type GetConstantPoolType(RelocInfo::Mode rmode);
591
592 uint32_t size_;
593 std::vector<ConstantPoolEntry> entries_;
594 ConstantPoolArray::LayoutSection current_section_;
595 ConstantPoolArray::NumberOfEntries number_of_entries_[2];
596 };
597 #endif
598
599
600 class Assembler : public AssemblerBase {
601 public:
602 // Create an assembler. Instructions and relocation information are emitted
603 // into a buffer, with the instructions starting from the beginning and the
604 // relocation information starting from the end of the buffer. See CodeDesc
605 // for a detailed comment on the layout (globals.h).
606 //
607 // If the provided buffer is NULL, the assembler allocates and grows its own
608 // buffer, and buffer_size determines the initial buffer size. The buffer is
609 // owned by the assembler and deallocated upon destruction of the assembler.
610 //
611 // If the provided buffer is not NULL, the assembler uses the provided buffer
612 // for code generation and assumes its size to be buffer_size. If the buffer
613 // is too small, a fatal error occurs. No deallocation of the buffer is done
614 // upon destruction of the assembler.
615 Assembler(Isolate* isolate, void* buffer, int buffer_size);
616 virtual ~Assembler() {}
617
618 // GetCode emits any pending (non-emitted) code and fills the descriptor
619 // desc. GetCode() is idempotent; it returns the same result if no other
620 // Assembler functions are invoked in between GetCode() calls.
621 void GetCode(CodeDesc* desc);
622
623 // Label operations & relative jumps (PPUM Appendix D)
624 //
625 // Takes a branch opcode (cc) and a label (L) and generates
626 // either a backward branch or a forward branch and links it
627 // to the label fixup chain. Usage:
628 //
629 // Label L; // unbound label
630 // j(cc, &L); // forward branch to unbound label
631 // bind(&L); // bind label to the current pc
632 // j(cc, &L); // backward branch to bound label
633 // bind(&L); // illegal: a label may be bound only once
634 //
635 // Note: The same Label can be used for forward and backward branches
636 // but it may be bound only once.
637
638 void bind(Label* L); // binds an unbound label L to the current code position
639 // Determines if Label is bound and near enough so that a single
640 // branch instruction can be used to reach it.
641 bool is_near(Label* L, Condition cond);
642
643 // Returns the branch offset to the given label from the current code position
644 // Links the label to the current position if it is still unbound
645 // Manages the jump elimination optimization if the second parameter is true.
646 int branch_offset(Label* L, bool jump_elimination_allowed);
647
648 // Puts a labels target address at the given position.
649 // The high 8 bits are set to zero.
650 void label_at_put(Label* L, int at_offset);
651
652 #if V8_OOL_CONSTANT_POOL
653 INLINE(static bool IsConstantPoolLoadStart(Address pc));
654 INLINE(static bool IsConstantPoolLoadEnd(Address pc));
655 INLINE(static int GetConstantPoolOffset(Address pc));
656 INLINE(static void SetConstantPoolOffset(Address pc, int offset));
657
658 // Return the address in the constant pool of the code target address used by
659 // the branch/call instruction at pc, or the object in a mov.
660 INLINE(static Address target_constant_pool_address_at(
661 Address pc, ConstantPoolArray* constant_pool));
662 #endif
663
664 // Read/Modify the code target address in the branch/call instruction at pc.
665 INLINE(static Address target_address_at(Address pc,
666 ConstantPoolArray* constant_pool));
667 INLINE(static void set_target_address_at(
668 Address pc, ConstantPoolArray* constant_pool, Address target,
669 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
670 INLINE(static Address target_address_at(Address pc, Code* code)) {
671 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
672 return target_address_at(pc, constant_pool);
673 }
674 INLINE(static void set_target_address_at(
675 Address pc, Code* code, Address target,
676 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
677 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
678 set_target_address_at(pc, constant_pool, target, icache_flush_mode);
679 }
680
681 // Return the code target address at a call site from the return address
682 // of that call in the instruction stream.
683 inline static Address target_address_from_return_address(Address pc);
684
685 // Given the address of the beginning of a call, return the address
686 // in the instruction stream that the call will return to.
687 INLINE(static Address return_address_from_call_start(Address pc));
688
689 // Return the code target address of the patch debug break slot
690 INLINE(static Address break_address_from_return_address(Address pc));
691
692 // This sets the branch destination.
693 // This is for calls and branches within generated code.
694 inline static void deserialization_set_special_target_at(
695 Address instruction_payload, Code* code, Address target);
696
697 // Size of an instruction.
698 static const int kInstrSize = sizeof(Instr);
699
700 // Here we are patching the address in the LUI/ORI instruction pair.
701 // These values are used in the serialization process and must be zero for
702 // PPC platform, as Code, Embedded Object or External-reference pointers
703 // are split across two consecutive instructions and don't exist separately
704 // in the code, so the serializer should not step forwards in memory after
705 // a target is resolved and written.
706 static const int kSpecialTargetSize = 0;
707
708 // Number of instructions to load an address via a mov sequence.
709 #if V8_TARGET_ARCH_PPC64
710 static const int kMovInstructionsConstantPool = 2;
711 static const int kMovInstructionsNoConstantPool = 5;
712 #else
713 static const int kMovInstructionsConstantPool = 1;
714 static const int kMovInstructionsNoConstantPool = 2;
715 #endif
716 #if V8_OOL_CONSTANT_POOL
717 static const int kMovInstructions = kMovInstructionsConstantPool;
718 #else
719 static const int kMovInstructions = kMovInstructionsNoConstantPool;
720 #endif
721
722 // Distance between the instruction referring to the address of the call
723 // target and the return address.
724
725 // Call sequence is a FIXED_SEQUENCE:
726 // mov r8, @ call address
727 // mtlr r8
728 // blrl
729 // @ return address
730 static const int kCallTargetAddressOffset =
731 (kMovInstructions + 2) * kInstrSize;
732
733 // Distance between start of patched return sequence and the emitted address
734 // to jump to.
735 // Patched return sequence is a FIXED_SEQUENCE:
736 // mov r0, <address>
737 // mtlr r0
738 // blrl
739 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize;
740
741 // Distance between start of patched debug break slot and the emitted address
742 // to jump to.
743 // Patched debug break slot code is a FIXED_SEQUENCE:
744 // mov r0, <address>
745 // mtlr r0
746 // blrl
747 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
748
749 // This is the length of the BreakLocationIterator::SetDebugBreakAtReturn()
750 // code patch FIXED_SEQUENCE
751 static const int kJSReturnSequenceInstructions =
752 kMovInstructionsNoConstantPool + 3;
753
754 // This is the length of the code sequence from SetDebugBreakAtSlot()
755 // FIXED_SEQUENCE
756 static const int kDebugBreakSlotInstructions =
757 kMovInstructionsNoConstantPool + 2;
758 static const int kDebugBreakSlotLength =
759 kDebugBreakSlotInstructions * kInstrSize;
760
761 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
762 return ((cr.code() * CRWIDTH) + crbit);
763 }
764
765 // ---------------------------------------------------------------------------
766 // Code generation
767
768 // Insert the smallest number of nop instructions
769 // possible to align the pc offset to a multiple
770 // of m. m must be a power of 2 (>= 4).
771 void Align(int m);
772 // Aligns code to something that's optimal for a jump target for the platform.
773 void CodeTargetAlign();
774
775 // Branch instructions
776 void bclr(BOfield bo, LKBit lk);
777 void blr();
778 void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK);
779 void b(int branch_offset, LKBit lk);
780
781 void bcctr(BOfield bo, LKBit lk);
782 void bctr();
783
784 // Convenience branch instructions using labels
785 void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L, false), lk); }
786
787 void bc_short(Condition cond, Label* L, CRegister cr = cr7,
788 LKBit lk = LeaveLK) {
789 DCHECK(cond != al);
790 DCHECK(cr.code() >= 0 && cr.code() <= 7);
791
792 int b_offset = branch_offset(L, false);
793
794 switch (cond) {
795 case eq:
796 bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk);
797 break;
798 case ne:
799 bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk);
800 break;
801 case gt:
802 bc(b_offset, BT, encode_crbit(cr, CR_GT), lk);
803 break;
804 case le:
805 bc(b_offset, BF, encode_crbit(cr, CR_GT), lk);
806 break;
807 case lt:
808 bc(b_offset, BT, encode_crbit(cr, CR_LT), lk);
809 break;
810 case ge:
811 bc(b_offset, BF, encode_crbit(cr, CR_LT), lk);
812 break;
813 case unordered:
814 bc(b_offset, BT, encode_crbit(cr, CR_FU), lk);
815 break;
816 case ordered:
817 bc(b_offset, BF, encode_crbit(cr, CR_FU), lk);
818 break;
819 case overflow:
820 bc(b_offset, BT, encode_crbit(cr, CR_SO), lk);
821 break;
822 case nooverflow:
823 bc(b_offset, BF, encode_crbit(cr, CR_SO), lk);
824 break;
825 default:
826 UNIMPLEMENTED();
827 }
828 }
829
830 void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
831 if (cond == al) {
832 b(L, lk);
833 return;
834 }
835
836 if ((L->is_bound() && is_near(L, cond)) || !is_trampoline_emitted()) {
837 bc_short(cond, L, cr, lk);
838 return;
839 }
840
841 Label skip;
842 Condition neg_cond = NegateCondition(cond);
843 bc_short(neg_cond, &skip, cr);
844 b(L, lk);
845 bind(&skip);
846 }
847
848 void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
849 b(ne, L, cr, lk);
850 }
851 void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
852 b(eq, L, cr, lk);
853 }
854 void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
855 b(lt, L, cr, lk);
856 }
857 void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
858 b(ge, L, cr, lk);
859 }
860 void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
861 b(le, L, cr, lk);
862 }
863 void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
864 b(gt, L, cr, lk);
865 }
866 void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
867 b(unordered, L, cr, lk);
868 }
869 void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
870 b(ordered, L, cr, lk);
871 }
872 void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
873 b(overflow, L, cr, lk);
874 }
875 void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
876 b(nooverflow, L, cr, lk);
877 }
878
879 // Decrement CTR; branch if CTR != 0
880 void bdnz(Label* L, LKBit lk = LeaveLK) {
881 bc(branch_offset(L, false), DCBNZ, 0, lk);
882 }
883
884 // Data-processing instructions
885
886 void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
887 RCBit r = LeaveRC);
888
889 void subfic(Register dst, Register src, const Operand& imm);
890
891 void subfc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
892 RCBit r = LeaveRC);
893
894 void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
895 RCBit r = LeaveRC);
896
897 void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
898 RCBit r = LeaveRC);
899
900 void addze(Register dst, Register src1, OEBit o, RCBit r);
901
902 void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
903 RCBit r = LeaveRC);
904
905 void mulhw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
906 RCBit r = LeaveRC);
907
908 void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
909 RCBit r = LeaveRC);
910
911 void addi(Register dst, Register src, const Operand& imm);
912 void addis(Register dst, Register src, const Operand& imm);
913 void addic(Register dst, Register src, const Operand& imm);
914
915 void and_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
916 void andc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
917 void andi(Register ra, Register rs, const Operand& imm);
918 void andis(Register ra, Register rs, const Operand& imm);
919 void nor(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
920 void notx(Register dst, Register src, RCBit r = LeaveRC);
921 void ori(Register dst, Register src, const Operand& imm);
922 void oris(Register dst, Register src, const Operand& imm);
923 void orx(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
924 void xori(Register dst, Register src, const Operand& imm);
925 void xoris(Register ra, Register rs, const Operand& imm);
926 void xor_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
927 void cmpi(Register src1, const Operand& src2, CRegister cr = cr7);
928 void cmpli(Register src1, const Operand& src2, CRegister cr = cr7);
929 void cmpwi(Register src1, const Operand& src2, CRegister cr = cr7);
930 void cmplwi(Register src1, const Operand& src2, CRegister cr = cr7);
931 void li(Register dst, const Operand& src);
932 void lis(Register dst, const Operand& imm);
933 void mr(Register dst, Register src);
934
935 void lbz(Register dst, const MemOperand& src);
936 void lbzx(Register dst, const MemOperand& src);
937 void lbzux(Register dst, const MemOperand& src);
938 void lhz(Register dst, const MemOperand& src);
939 void lhzx(Register dst, const MemOperand& src);
940 void lhzux(Register dst, const MemOperand& src);
941 void lwz(Register dst, const MemOperand& src);
942 void lwzu(Register dst, const MemOperand& src);
943 void lwzx(Register dst, const MemOperand& src);
944 void lwzux(Register dst, const MemOperand& src);
945 void lwa(Register dst, const MemOperand& src);
946 void stb(Register dst, const MemOperand& src);
947 void stbx(Register dst, const MemOperand& src);
948 void stbux(Register dst, const MemOperand& src);
949 void sth(Register dst, const MemOperand& src);
950 void sthx(Register dst, const MemOperand& src);
951 void sthux(Register dst, const MemOperand& src);
952 void stw(Register dst, const MemOperand& src);
953 void stwu(Register dst, const MemOperand& src);
954 void stwx(Register rs, const MemOperand& src);
955 void stwux(Register rs, const MemOperand& src);
956
957 void extsb(Register rs, Register ra, RCBit r = LeaveRC);
958 void extsh(Register rs, Register ra, RCBit r = LeaveRC);
959
960 void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC);
961
962 #if V8_TARGET_ARCH_PPC64
963 void ld(Register rd, const MemOperand& src);
964 void ldx(Register rd, const MemOperand& src);
965 void ldu(Register rd, const MemOperand& src);
966 void ldux(Register rd, const MemOperand& src);
967 void std(Register rs, const MemOperand& src);
968 void stdx(Register rs, const MemOperand& src);
969 void stdu(Register rs, const MemOperand& src);
970 void stdux(Register rs, const MemOperand& src);
971 void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
972 void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
973 void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r = LeaveRC);
974 void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC);
975 void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
976 void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
977 void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
978 void clrrdi(Register dst, Register src, const Operand& val,
979 RCBit rc = LeaveRC);
980 void clrldi(Register dst, Register src, const Operand& val,
981 RCBit rc = LeaveRC);
982 void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
983 void srd(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
984 void sld(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
985 void srad(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
986 void rotld(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
987 void rotldi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
988 void rotrdi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
989 void cntlzd_(Register dst, Register src, RCBit rc = LeaveRC);
990 void extsw(Register rs, Register ra, RCBit r = LeaveRC);
991 void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
992 RCBit r = LeaveRC);
993 void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
994 RCBit r = LeaveRC);
995 #endif
996
997 void rlwinm(Register ra, Register rs, int sh, int mb, int me,
998 RCBit rc = LeaveRC);
999 void rlwimi(Register ra, Register rs, int sh, int mb, int me,
1000 RCBit rc = LeaveRC);
1001 void rlwnm(Register ra, Register rs, Register rb, int mb, int me,
1002 RCBit rc = LeaveRC);
1003 void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
1004 void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
1005 void clrrwi(Register dst, Register src, const Operand& val,
1006 RCBit rc = LeaveRC);
1007 void clrlwi(Register dst, Register src, const Operand& val,
1008 RCBit rc = LeaveRC);
1009 void srawi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
1010 void srw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1011 void slw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1012 void sraw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1013 void rotlw(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
1014 void rotlwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
1015 void rotrwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
1016
1017 void cntlzw_(Register dst, Register src, RCBit rc = LeaveRC);
1018
1019 void subi(Register dst, Register src1, const Operand& src2);
1020
1021 void cmp(Register src1, Register src2, CRegister cr = cr7);
1022 void cmpl(Register src1, Register src2, CRegister cr = cr7);
1023 void cmpw(Register src1, Register src2, CRegister cr = cr7);
1024 void cmplw(Register src1, Register src2, CRegister cr = cr7);
1025
1026 void mov(Register dst, const Operand& src);
1027
1028 // Load the position of the label relative to the generated code object
1029 // pointer in a register.
1030 void mov_label_offset(Register dst, Label* label);
1031
1032 // Multiply instructions
1033 void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
1034 RCBit r = LeaveRC);
1035
1036 // Miscellaneous arithmetic instructions
1037
1038 // Special register access
1039 void crxor(int bt, int ba, int bb);
1040 void crclr(int bt) { crxor(bt, bt, bt); }
1041 void creqv(int bt, int ba, int bb);
1042 void crset(int bt) { creqv(bt, bt, bt); }
1043 void mflr(Register dst);
1044 void mtlr(Register src);
1045 void mtctr(Register src);
1046 void mtxer(Register src);
1047 void mcrfs(int bf, int bfa);
1048 void mfcr(Register dst);
1049 #if V8_TARGET_ARCH_PPC64
1050 void mffprd(Register dst, DoubleRegister src);
1051 void mffprwz(Register dst, DoubleRegister src);
1052 void mtfprd(DoubleRegister dst, Register src);
1053 void mtfprwz(DoubleRegister dst, Register src);
1054 void mtfprwa(DoubleRegister dst, Register src);
1055 #endif
1056
1057 void fake_asm(enum FAKE_OPCODE_T fopcode);
1058 void marker_asm(int mcode);
1059 void function_descriptor();
1060
1061 // Exception-generating instructions and debugging support
1062 void stop(const char* msg, Condition cond = al,
1063 int32_t code = kDefaultStopCode, CRegister cr = cr7);
1064
1065 void bkpt(uint32_t imm16); // v5 and above
1066
1067 // Informational messages when simulating
1068 void info(const char* msg, Condition cond = al,
1069 int32_t code = kDefaultStopCode, CRegister cr = cr7);
1070
1071 void dcbf(Register ra, Register rb);
1072 void sync();
1073 void icbi(Register ra, Register rb);
1074 void isync();
1075
1076 // Support for floating point
1077 void lfd(const DoubleRegister frt, const MemOperand& src);
1078 void lfdu(const DoubleRegister frt, const MemOperand& src);
1079 void lfdx(const DoubleRegister frt, const MemOperand& src);
1080 void lfdux(const DoubleRegister frt, const MemOperand& src);
1081 void lfs(const DoubleRegister frt, const MemOperand& src);
1082 void lfsu(const DoubleRegister frt, const MemOperand& src);
1083 void lfsx(const DoubleRegister frt, const MemOperand& src);
1084 void lfsux(const DoubleRegister frt, const MemOperand& src);
1085 void stfd(const DoubleRegister frs, const MemOperand& src);
1086 void stfdu(const DoubleRegister frs, const MemOperand& src);
1087 void stfdx(const DoubleRegister frs, const MemOperand& src);
1088 void stfdux(const DoubleRegister frs, const MemOperand& src);
1089 void stfs(const DoubleRegister frs, const MemOperand& src);
1090 void stfsu(const DoubleRegister frs, const MemOperand& src);
1091 void stfsx(const DoubleRegister frs, const MemOperand& src);
1092 void stfsux(const DoubleRegister frs, const MemOperand& src);
1093
1094 void fadd(const DoubleRegister frt, const DoubleRegister fra,
1095 const DoubleRegister frb, RCBit rc = LeaveRC);
1096 void fsub(const DoubleRegister frt, const DoubleRegister fra,
1097 const DoubleRegister frb, RCBit rc = LeaveRC);
1098 void fdiv(const DoubleRegister frt, const DoubleRegister fra,
1099 const DoubleRegister frb, RCBit rc = LeaveRC);
1100 void fmul(const DoubleRegister frt, const DoubleRegister fra,
1101 const DoubleRegister frc, RCBit rc = LeaveRC);
1102 void fcmpu(const DoubleRegister fra, const DoubleRegister frb,
1103 CRegister cr = cr7);
1104 void fmr(const DoubleRegister frt, const DoubleRegister frb,
1105 RCBit rc = LeaveRC);
1106 void fctiwz(const DoubleRegister frt, const DoubleRegister frb);
1107 void fctiw(const DoubleRegister frt, const DoubleRegister frb);
1108 void frim(const DoubleRegister frt, const DoubleRegister frb);
1109 void frsp(const DoubleRegister frt, const DoubleRegister frb,
1110 RCBit rc = LeaveRC);
1111 void fcfid(const DoubleRegister frt, const DoubleRegister frb,
1112 RCBit rc = LeaveRC);
1113 void fctid(const DoubleRegister frt, const DoubleRegister frb,
1114 RCBit rc = LeaveRC);
1115 void fctidz(const DoubleRegister frt, const DoubleRegister frb,
1116 RCBit rc = LeaveRC);
1117 void fsel(const DoubleRegister frt, const DoubleRegister fra,
1118 const DoubleRegister frc, const DoubleRegister frb,
1119 RCBit rc = LeaveRC);
1120 void fneg(const DoubleRegister frt, const DoubleRegister frb,
1121 RCBit rc = LeaveRC);
1122 void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
1123 void mffs(const DoubleRegister frt, RCBit rc = LeaveRC);
1124 void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
1125 RCBit rc = LeaveRC);
1126 void fsqrt(const DoubleRegister frt, const DoubleRegister frb,
1127 RCBit rc = LeaveRC);
1128 void fabs(const DoubleRegister frt, const DoubleRegister frb,
1129 RCBit rc = LeaveRC);
1130 void fmadd(const DoubleRegister frt, const DoubleRegister fra,
1131 const DoubleRegister frc, const DoubleRegister frb,
1132 RCBit rc = LeaveRC);
1133 void fmsub(const DoubleRegister frt, const DoubleRegister fra,
1134 const DoubleRegister frc, const DoubleRegister frb,
1135 RCBit rc = LeaveRC);
1136
1137 // Pseudo instructions
1138
1139 // Different nop operations are used by the code generator to detect certain
1140 // states of the generated code.
1141 enum NopMarkerTypes {
1142 NON_MARKING_NOP = 0,
1143 DEBUG_BREAK_NOP,
1144 // IC markers.
1145 PROPERTY_ACCESS_INLINED,
1146 PROPERTY_ACCESS_INLINED_CONTEXT,
1147 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1148 // Helper values.
1149 LAST_CODE_MARKER,
1150 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1151 };
1152
1153 void nop(int type = 0); // 0 is the default non-marking type.
1154
1155 void push(Register src) {
1156 #if V8_TARGET_ARCH_PPC64
1157 stdu(src, MemOperand(sp, -8));
1158 #else
1159 stwu(src, MemOperand(sp, -4));
1160 #endif
1161 }
1162
1163 void pop(Register dst) {
1164 #if V8_TARGET_ARCH_PPC64
1165 ld(dst, MemOperand(sp));
1166 addi(sp, sp, Operand(8));
1167 #else
1168 lwz(dst, MemOperand(sp));
1169 addi(sp, sp, Operand(4));
1170 #endif
1171 }
1172
1173 void pop() { addi(sp, sp, Operand(kPointerSize)); }
1174
1175 // Jump unconditionally to given label.
1176 void jmp(Label* L) { b(L); }
1177
1178 // Check the code size generated from label to here.
1179 int SizeOfCodeGeneratedSince(Label* label) {
1180 return pc_offset() - label->pos();
1181 }
1182
1183 // Check the number of instructions generated from label to here.
1184 int InstructionsGeneratedSince(Label* label) {
1185 return SizeOfCodeGeneratedSince(label) / kInstrSize;
1186 }
1187
1188 // Class for scoping postponing the trampoline pool generation.
1189 class BlockTrampolinePoolScope {
1190 public:
1191 explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1192 assem_->StartBlockTrampolinePool();
1193 }
1194 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
1195
1196 private:
1197 Assembler* assem_;
1198
1199 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
1200 };
1201
1202 // Debugging
1203
1204 // Mark address of the ExitJSFrame code.
1205 void RecordJSReturn();
1206
1207 // Mark address of a debug break slot.
1208 void RecordDebugBreakSlot();
1209
1210 // Record the AST id of the CallIC being compiled, so that it can be placed
1211 // in the relocation information.
1212 void SetRecordedAstId(TypeFeedbackId ast_id) {
1213 // PPC - this shouldn't be failing roohack
1214 // DCHECK(recorded_ast_id_.IsNone());
1215 recorded_ast_id_ = ast_id;
1216 }
1217
1218 TypeFeedbackId RecordedAstId() {
1219 // roohack - another issue??? DCHECK(!recorded_ast_id_.IsNone());
1220 return recorded_ast_id_;
1221 }
1222
1223 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1224
1225 // Record a comment relocation entry that can be used by a disassembler.
1226 // Use --code-comments to enable.
1227 void RecordComment(const char* msg);
1228
1229 // Writes a single byte or word of data in the code stream. Used
1230 // for inline tables, e.g., jump-tables.
1231 void db(uint8_t data);
1232 void dd(uint32_t data);
1233 void emit_ptr(uintptr_t data);
1234
1235 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1236
1237 // Read/patch instructions
1238 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1239 void instr_at_put(int pos, Instr instr) {
1240 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1241 }
1242 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1243 static void instr_at_put(byte* pc, Instr instr) {
1244 *reinterpret_cast<Instr*>(pc) = instr;
1245 }
1246 static Condition GetCondition(Instr instr);
1247
1248 static bool IsLis(Instr instr);
1249 static bool IsLi(Instr instr);
1250 static bool IsAddic(Instr instr);
1251 static bool IsOri(Instr instr);
1252
1253 static bool IsBranch(Instr instr);
1254 static Register GetRA(Instr instr);
1255 static Register GetRB(Instr instr);
1256 #if V8_TARGET_ARCH_PPC64
1257 static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3,
1258 Instr instr4, Instr instr5);
1259 #else
1260 static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2);
1261 #endif
1262
1263 static bool IsCmpRegister(Instr instr);
1264 static bool IsCmpImmediate(Instr instr);
1265 static bool IsRlwinm(Instr instr);
1266 #if V8_TARGET_ARCH_PPC64
1267 static bool IsRldicl(Instr instr);
1268 #endif
1269 static bool IsCrSet(Instr instr);
1270 static Register GetCmpImmediateRegister(Instr instr);
1271 static int GetCmpImmediateRawImmediate(Instr instr);
1272 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1273
1274 // Postpone the generation of the trampoline pool for the specified number of
1275 // instructions.
1276 void BlockTrampolinePoolFor(int instructions);
1277 void CheckTrampolinePool();
1278
1279 int instructions_required_for_mov(const Operand& x) const;
1280
1281 #if V8_OOL_CONSTANT_POOL
1282 // Decide between using the constant pool vs. a mov immediate sequence.
1283 bool use_constant_pool_for_mov(const Operand& x, bool canOptimize) const;
1284
1285 // The code currently calls CheckBuffer() too often. This has the side
1286 // effect of randomly growing the buffer in the middle of multi-instruction
1287 // sequences.
1288 // MacroAssembler::LoadConstantPoolPointerRegister() includes a relocation
1289 // and multiple instructions. We cannot grow the buffer until the
1290 // relocation and all of the instructions are written.
1291 //
1292 // This function allows outside callers to check and grow the buffer
1293 void EnsureSpaceFor(int space_needed);
1294 #endif
1295
1296 // Allocate a constant pool of the correct size for the generated code.
1297 Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
1298
1299 // Generate the constant pool for the generated code.
1300 void PopulateConstantPool(ConstantPoolArray* constant_pool);
1301
1302 #if V8_OOL_CONSTANT_POOL
1303 bool is_constant_pool_available() const { return constant_pool_available_; }
1304
1305 bool is_constant_pool_full() const {
1306 return constant_pool_builder_.is_full();
1307 }
1308
1309 bool use_extended_constant_pool() const {
1310 return constant_pool_builder_.current_section() ==
1311 ConstantPoolArray::EXTENDED_SECTION;
1312 }
1313 #endif
1314
1315 #if ABI_USES_FUNCTION_DESCRIPTORS || V8_OOL_CONSTANT_POOL
1316 static void RelocateInternalReference(
1317 Address pc, intptr_t delta, Address code_start,
1318 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
1319 static int DecodeInternalReference(Vector<char> buffer, Address pc);
1320 #endif
1321
1322 protected:
1323 // Relocation for a type-recording IC has the AST id added to it. This
1324 // member variable is a way to pass the information from the call site to
1325 // the relocation info.
1326 TypeFeedbackId recorded_ast_id_;
1327
1328 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1329
1330 // Decode branch instruction at pos and return branch target pos
1331 int target_at(int pos);
1332
1333 // Patch branch instruction at pos to branch to given branch target pos
1334 void target_at_put(int pos, int target_pos);
1335
1336 // Record reloc info for current pc_
1337 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1338 void RecordRelocInfo(const RelocInfo& rinfo);
1339 #if V8_OOL_CONSTANT_POOL
1340 ConstantPoolArray::LayoutSection ConstantPoolAddEntry(
1341 const RelocInfo& rinfo) {
1342 return constant_pool_builder_.AddEntry(this, rinfo);
1343 }
1344 #endif
1345
1346 // Block the emission of the trampoline pool before pc_offset.
1347 void BlockTrampolinePoolBefore(int pc_offset) {
1348 if (no_trampoline_pool_before_ < pc_offset)
1349 no_trampoline_pool_before_ = pc_offset;
1350 }
1351
1352 void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; }
1353
1354 void EndBlockTrampolinePool() { trampoline_pool_blocked_nesting_--; }
1355
1356 bool is_trampoline_pool_blocked() const {
1357 return trampoline_pool_blocked_nesting_ > 0;
1358 }
1359
1360 bool has_exception() const { return internal_trampoline_exception_; }
1361
1362 bool is_trampoline_emitted() const { return trampoline_emitted_; }
1363
1364 #if V8_OOL_CONSTANT_POOL
1365 void set_constant_pool_available(bool available) {
1366 constant_pool_available_ = available;
1367 }
1368 #endif
1369
1370 private:
1371 // Code generation
1372 // The relocation writer's position is at least kGap bytes below the end of
1373 // the generated instructions. This is so that multi-instruction sequences do
1374 // not have to check for overflow. The same is true for writes of large
1375 // relocation info entries.
1376 static const int kGap = 32;
1377
1378 // Repeated checking whether the trampoline pool should be emitted is rather
1379 // expensive. By default we only check again once a number of instructions
1380 // has been generated.
1381 int next_buffer_check_; // pc offset of next buffer check.
1382
1383 // Emission of the trampoline pool may be blocked in some code sequences.
1384 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero.
1385 int no_trampoline_pool_before_; // Block emission before this pc offset.
1386
1387 // Relocation info generation
1388 // Each relocation is encoded as a variable size value
1389 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1390 RelocInfoWriter reloc_info_writer;
1391
1392 // The bound position, before this we cannot do instruction elimination.
1393 int last_bound_pos_;
1394
1395 #if V8_OOL_CONSTANT_POOL
1396 ConstantPoolBuilder constant_pool_builder_;
1397
1398 // Indicates whether the constant pool can be accessed, which is only possible
1399 // if kConstantPoolRegister points to the current code object's constant pool.
1400 bool constant_pool_available_;
1401 #endif
1402
1403 // Code emission
1404 inline void CheckBuffer();
1405 void GrowBuffer();
1406 inline void emit(Instr x);
1407 inline void CheckTrampolinePoolQuick();
1408
1409 // Instruction generation
1410 void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra,
1411 DoubleRegister frb, RCBit r);
1412 void d_form(Instr instr, Register rt, Register ra, const intptr_t val,
1413 bool signed_disp);
1414 void x_form(Instr instr, Register ra, Register rs, Register rb, RCBit r);
1415 void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o,
1416 RCBit r);
1417 void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
1418 RCBit r);
1419 void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit,
1420 RCBit r);
1421
1422 // Labels
1423 void print(Label* L);
1424 int max_reach_from(int pos);
1425 void bind_to(Label* L, int pos);
1426 void next(Label* L);
1427
1428 class Trampoline {
1429 public:
1430 Trampoline() {
1431 next_slot_ = 0;
1432 free_slot_count_ = 0;
1433 }
1434 Trampoline(int start, int slot_count) {
1435 next_slot_ = start;
1436 free_slot_count_ = slot_count;
1437 }
1438 int take_slot() {
1439 int trampoline_slot = kInvalidSlotPos;
1440 if (free_slot_count_ <= 0) {
1441 // We have run out of space on trampolines.
1442 // Make sure we fail in debug mode, so we become aware of each case
1443 // when this happens.
1444 DCHECK(0);
1445 // Internal exception will be caught.
1446 } else {
1447 trampoline_slot = next_slot_;
1448 free_slot_count_--;
1449 next_slot_ += kTrampolineSlotsSize;
1450 }
1451 return trampoline_slot;
1452 }
1453
1454 private:
1455 int next_slot_;
1456 int free_slot_count_;
1457 };
1458
1459 int32_t get_trampoline_entry();
1460 int unbound_labels_count_;
1461 // If trampoline is emitted, generated code is becoming large. As
1462 // this is already a slow case which can possibly break our code
1463 // generation for the extreme case, we use this information to
1464 // trigger different mode of branch instruction generation, where we
1465 // no longer use a single branch instruction.
1466 bool trampoline_emitted_;
1467 static const int kTrampolineSlotsSize = kInstrSize;
1468 static const int kMaxCondBranchReach = (1 << (16 - 1)) - 1;
1469 static const int kMaxBlockTrampolineSectionSize = 64 * kInstrSize;
1470 static const int kInvalidSlotPos = -1;
1471
1472 Trampoline trampoline_;
1473 bool internal_trampoline_exception_;
1474
1475 friend class RegExpMacroAssemblerPPC;
1476 friend class RelocInfo;
1477 friend class CodePatcher;
1478 friend class BlockTrampolinePoolScope;
1479 #if V8_OOL_CONSTANT_POOL
1480 friend class FrameAndConstantPoolScope;
1481 friend class ConstantPoolUnavailableScope;
1482 #endif
1483
1484 PositionsRecorder positions_recorder_;
1485 friend class PositionsRecorder;
1486 friend class EnsureSpace;
1487 };
1488
1489
1490 class EnsureSpace BASE_EMBEDDED {
1491 public:
1492 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1493 };
1494 }
1495 } // namespace v8::internal
1496
1497 #endif // V8_PPC_ASSEMBLER_PPC_H_
OLDNEW
« src/hydrogen-bch.cc ('K') | « src/objects-printer.cc ('k') | src/ppc/assembler-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698