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

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

Issue 422063005: Contribution of PowerPC port. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 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
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 //
3 // Copyright IBM Corp. 2012, 2013. All rights reserved.
4 //
2 // Use of this source code is governed by a BSD-style license that can be 5 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 6 // found in the LICENSE file.
4 7
5 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ 8 #ifndef V8_PPC_MACRO_ASSEMBLER_PPC_H_
6 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ 9 #define V8_PPC_MACRO_ASSEMBLER_PPC_H_
7 10
8 #include "src/assembler.h" 11 #include "src/assembler.h"
9 #include "src/frames.h" 12 #include "src/frames.h"
10 #include "src/globals.h" 13 #include "src/globals.h"
11 14
12 namespace v8 { 15 namespace v8 {
13 namespace internal { 16 namespace internal {
14 17
15 // ---------------------------------------------------------------------------- 18 // ----------------------------------------------------------------------------
16 // Static helper functions 19 // Static helper functions
17 20
18 // Generate a MemOperand for loading a field from an object. 21 // Generate a MemOperand for loading a field from an object.
19 inline MemOperand FieldMemOperand(Register object, int offset) { 22 inline MemOperand FieldMemOperand(Register object, int offset) {
20 return MemOperand(object, offset - kHeapObjectTag); 23 return MemOperand(object, offset - kHeapObjectTag);
21 } 24 }
22 25
23 26
24 // Give alias names to registers
25 const Register cp = { kRegister_r7_Code }; // JavaScript context pointer.
26 const Register pp = { kRegister_r8_Code }; // Constant pool pointer.
27 const Register kRootRegister = { kRegister_r10_Code }; // Roots array pointer.
28
29 // Flags used for AllocateHeapNumber 27 // Flags used for AllocateHeapNumber
30 enum TaggingMode { 28 enum TaggingMode {
31 // Tag the result. 29 // Tag the result.
32 TAG_RESULT, 30 TAG_RESULT,
33 // Don't tag 31 // Don't tag
34 DONT_TAG_RESULT 32 DONT_TAG_RESULT
35 }; 33 };
36 34
37 35
38 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET }; 36 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
(...skipping 17 matching lines...) Expand all
56 bool AreAliased(Register reg1, 54 bool AreAliased(Register reg1,
57 Register reg2, 55 Register reg2,
58 Register reg3 = no_reg, 56 Register reg3 = no_reg,
59 Register reg4 = no_reg, 57 Register reg4 = no_reg,
60 Register reg5 = no_reg, 58 Register reg5 = no_reg,
61 Register reg6 = no_reg, 59 Register reg6 = no_reg,
62 Register reg7 = no_reg, 60 Register reg7 = no_reg,
63 Register reg8 = no_reg); 61 Register reg8 = no_reg);
64 #endif 62 #endif
65 63
64 // These exist to provide portability between 32 and 64bit
65 #if V8_TARGET_ARCH_PPC64
66 #define LoadPU ldu
67 #define LoadPX ldx
68 #define LoadPUX ldux
69 #define StorePU stdu
70 #define StorePX stdx
71 #define StorePUX stdux
72 #define ShiftLeftImm sldi
73 #define ShiftRightImm srdi
74 #define ClearLeftImm clrldi
75 #define ClearRightImm clrrdi
76 #define ShiftRightArithImm sradi
77 #define ShiftLeft sld
78 #define ShiftRight srd
79 #define ShiftRightArith srad
80 #define Mul mulld
81 #define Div divd
82 #else
83 #define LoadPU lwzu
84 #define LoadPX lwzx
85 #define LoadPUX lwzux
86 #define StorePU stwu
87 #define StorePX stwx
88 #define StorePUX stwux
89 #define ShiftLeftImm slwi
90 #define ShiftRightImm srwi
91 #define ClearLeftImm clrlwi
92 #define ClearRightImm clrrwi
93 #define ShiftRightArithImm srawi
94 #define ShiftLeft slw
95 #define ShiftRight srw
96 #define ShiftRightArith sraw
97 #define Mul mullw
98 #define Div divw
99 #endif
66 100
67 enum TargetAddressStorageMode {
68 CAN_INLINE_TARGET_ADDRESS,
69 NEVER_INLINE_TARGET_ADDRESS
70 };
71 101
72 // MacroAssembler implements a collection of frequently used macros. 102 // MacroAssembler implements a collection of frequently used macros.
73 class MacroAssembler: public Assembler { 103 class MacroAssembler: public Assembler {
74 public: 104 public:
75 // The isolate parameter can be NULL if the macro assembler should 105 // The isolate parameter can be NULL if the macro assembler should
76 // not use isolate-dependent functionality. In this case, it's the 106 // not use isolate-dependent functionality. In this case, it's the
77 // responsibility of the caller to never invoke such function on the 107 // responsibility of the caller to never invoke such function on the
78 // macro assembler. 108 // macro assembler.
79 MacroAssembler(Isolate* isolate, void* buffer, int size); 109 MacroAssembler(Isolate* isolate, void* buffer, int size);
80 110
81 111
82 // Returns the size of a call in instructions. Note, the value returned is 112 // Returns the size of a call in instructions. Note, the value returned is
83 // only valid as long as no entries are added to the constant pool between 113 // only valid as long as no entries are added to the constant pool between
84 // checking the call size and emitting the actual call. 114 // checking the call size and emitting the actual call.
85 static int CallSize(Register target, Condition cond = al); 115 static int CallSize(Register target, Condition cond = al);
86 int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al); 116 int CallSize(Address target, RelocInfo::Mode rmode, Condition cond = al);
87 int CallStubSize(CodeStub* stub, 117 static int CallSizeNotPredictableCodeSize(Address target,
88 TypeFeedbackId ast_id = TypeFeedbackId::None(),
89 Condition cond = al);
90 static int CallSizeNotPredictableCodeSize(Isolate* isolate,
91 Address target,
92 RelocInfo::Mode rmode, 118 RelocInfo::Mode rmode,
93 Condition cond = al); 119 Condition cond = al);
94 120
95 // Jump, Call, and Ret pseudo instructions implementing inter-working. 121 // Jump, Call, and Ret pseudo instructions implementing inter-working.
96 void Jump(Register target, Condition cond = al); 122 void Jump(Register target, Condition cond = al);
97 void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al); 123 void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al,
124 CRegister cr = cr7);
98 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); 125 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
99 void Call(Register target, Condition cond = al); 126 void Call(Register target, Condition cond = al);
100 void Call(Address target, RelocInfo::Mode rmode, 127 void Call(Address target, RelocInfo::Mode rmode, Condition cond = al);
101 Condition cond = al,
102 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
103 int CallSize(Handle<Code> code, 128 int CallSize(Handle<Code> code,
104 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 129 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
105 TypeFeedbackId ast_id = TypeFeedbackId::None(), 130 TypeFeedbackId ast_id = TypeFeedbackId::None(),
106 Condition cond = al); 131 Condition cond = al);
107 void Call(Handle<Code> code, 132 void Call(Handle<Code> code,
108 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 133 RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
109 TypeFeedbackId ast_id = TypeFeedbackId::None(), 134 TypeFeedbackId ast_id = TypeFeedbackId::None(),
110 Condition cond = al, 135 Condition cond = al);
111 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS);
112 void Ret(Condition cond = al); 136 void Ret(Condition cond = al);
113 137
114 // Emit code to discard a non-negative number of pointer-sized elements 138 // Emit code to discard a non-negative number of pointer-sized elements
115 // from the stack, clobbering only the sp register. 139 // from the stack, clobbering only the sp register.
116 void Drop(int count, Condition cond = al); 140 void Drop(int count, Condition cond = al);
117 141
118 void Ret(int drop, Condition cond = al); 142 void Ret(int drop, Condition cond = al);
119 143
120 // Swap two registers. If the scratch register is omitted then a slightly 144 void Call(Label* target);
121 // less efficient form using xor instead of mov is emitted.
122 void Swap(Register reg1,
123 Register reg2,
124 Register scratch = no_reg,
125 Condition cond = al);
126 145
127 void Mls(Register dst, Register src1, Register src2, Register srcA, 146 // Emit call to the code we are currently generating.
128 Condition cond = al); 147 void CallSelf() {
129 void And(Register dst, Register src1, const Operand& src2, 148 Handle<Code> self(reinterpret_cast<Code**>(CodeObject().location()));
130 Condition cond = al); 149 Call(self, RelocInfo::CODE_TARGET);
131 void Ubfx(Register dst, Register src, int lsb, int width, 150 }
132 Condition cond = al);
133 void Sbfx(Register dst, Register src, int lsb, int width,
134 Condition cond = al);
135 // The scratch register is not used for ARMv7.
136 // scratch can be the same register as src (in which case it is trashed), but
137 // not the same as dst.
138 void Bfi(Register dst,
139 Register src,
140 Register scratch,
141 int lsb,
142 int width,
143 Condition cond = al);
144 void Bfc(Register dst, Register src, int lsb, int width, Condition cond = al);
145 void Usat(Register dst, int satpos, const Operand& src,
146 Condition cond = al);
147
148 void Call(Label* target);
149 void Push(Register src) { push(src); }
150 void Pop(Register dst) { pop(dst); }
151 151
152 // Register move. May do nothing if the registers are identical. 152 // Register move. May do nothing if the registers are identical.
153 void Move(Register dst, Handle<Object> value); 153 void Move(Register dst, Handle<Object> value);
154 void Move(Register dst, Register src, Condition cond = al); 154 void Move(Register dst, Register src, Condition cond = al);
155 void Move(DwVfpRegister dst, DwVfpRegister src); 155 void Move(DoubleRegister dst, DoubleRegister src);
156 156
157 void Load(Register dst, const MemOperand& src, Representation r); 157 void MultiPush(RegList regs);
158 void Store(Register src, const MemOperand& dst, Representation r); 158 void MultiPop(RegList regs);
159 159
160 // Load an object from the root table. 160 // Load an object from the root table.
161 void LoadRoot(Register destination, 161 void LoadRoot(Register destination,
162 Heap::RootListIndex index, 162 Heap::RootListIndex index,
163 Condition cond = al); 163 Condition cond = al);
164 // Store an object to the root table. 164 // Store an object to the root table.
165 void StoreRoot(Register source, 165 void StoreRoot(Register source,
166 Heap::RootListIndex index, 166 Heap::RootListIndex index,
167 Condition cond = al); 167 Condition cond = al);
168 168
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 Register object, 298 Register object,
299 Register address, 299 Register address,
300 Register value, 300 Register value,
301 LinkRegisterStatus lr_status, 301 LinkRegisterStatus lr_status,
302 SaveFPRegsMode save_fp, 302 SaveFPRegsMode save_fp,
303 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET, 303 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
304 SmiCheck smi_check = INLINE_SMI_CHECK, 304 SmiCheck smi_check = INLINE_SMI_CHECK,
305 PointersToHereCheck pointers_to_here_check_for_value = 305 PointersToHereCheck pointers_to_here_check_for_value =
306 kPointersToHereMaybeInteresting); 306 kPointersToHereMaybeInteresting);
307 307
308 void Push(Register src) { push(src); }
309
308 // Push a handle. 310 // Push a handle.
309 void Push(Handle<Object> handle); 311 void Push(Handle<Object> handle);
310 void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); } 312 void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
311 313
312 // Push two registers. Pushes leftmost register first (to highest address). 314 // Push two registers. Pushes leftmost register first (to highest address).
313 void Push(Register src1, Register src2, Condition cond = al) { 315 void Push(Register src1, Register src2) {
314 ASSERT(!src1.is(src2)); 316 StorePU(src1, MemOperand(sp, -kPointerSize));
315 if (src1.code() > src2.code()) { 317 StorePU(src2, MemOperand(sp, -kPointerSize));
316 stm(db_w, sp, src1.bit() | src2.bit(), cond);
317 } else {
318 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
319 str(src2, MemOperand(sp, 4, NegPreIndex), cond);
320 }
321 } 318 }
322 319
323 // Push three registers. Pushes leftmost register first (to highest address). 320 // Push three registers. Pushes leftmost register first (to highest address).
324 void Push(Register src1, Register src2, Register src3, Condition cond = al) { 321 void Push(Register src1, Register src2, Register src3) {
325 ASSERT(!src1.is(src2)); 322 StorePU(src1, MemOperand(sp, -kPointerSize));
326 ASSERT(!src2.is(src3)); 323 StorePU(src2, MemOperand(sp, -kPointerSize));
327 ASSERT(!src1.is(src3)); 324 StorePU(src3, MemOperand(sp, -kPointerSize));
328 if (src1.code() > src2.code()) {
329 if (src2.code() > src3.code()) {
330 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
331 } else {
332 stm(db_w, sp, src1.bit() | src2.bit(), cond);
333 str(src3, MemOperand(sp, 4, NegPreIndex), cond);
334 }
335 } else {
336 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
337 Push(src2, src3, cond);
338 }
339 } 325 }
340 326
341 // Push four registers. Pushes leftmost register first (to highest address). 327 // Push four registers. Pushes leftmost register first (to highest address).
342 void Push(Register src1, 328 void Push(Register src1,
343 Register src2, 329 Register src2,
344 Register src3, 330 Register src3,
345 Register src4, 331 Register src4) {
346 Condition cond = al) { 332 StorePU(src1, MemOperand(sp, -kPointerSize));
347 ASSERT(!src1.is(src2)); 333 StorePU(src2, MemOperand(sp, -kPointerSize));
348 ASSERT(!src2.is(src3)); 334 StorePU(src3, MemOperand(sp, -kPointerSize));
349 ASSERT(!src1.is(src3)); 335 StorePU(src4, MemOperand(sp, -kPointerSize));
350 ASSERT(!src1.is(src4));
351 ASSERT(!src2.is(src4));
352 ASSERT(!src3.is(src4));
353 if (src1.code() > src2.code()) {
354 if (src2.code() > src3.code()) {
355 if (src3.code() > src4.code()) {
356 stm(db_w,
357 sp,
358 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
359 cond);
360 } else {
361 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
362 str(src4, MemOperand(sp, 4, NegPreIndex), cond);
363 }
364 } else {
365 stm(db_w, sp, src1.bit() | src2.bit(), cond);
366 Push(src3, src4, cond);
367 }
368 } else {
369 str(src1, MemOperand(sp, 4, NegPreIndex), cond);
370 Push(src2, src3, src4, cond);
371 }
372 } 336 }
373 337
338 // Push five registers. Pushes leftmost register first (to highest address).
339 void Push(Register src1,
340 Register src2,
341 Register src3,
342 Register src4,
343 Register src5) {
344 StorePU(src1, MemOperand(sp, -kPointerSize));
345 StorePU(src2, MemOperand(sp, -kPointerSize));
346 StorePU(src3, MemOperand(sp, -kPointerSize));
347 StorePU(src4, MemOperand(sp, -kPointerSize));
348 StorePU(src5, MemOperand(sp, -kPointerSize));
349 }
350
351 void Pop(Register dst) { pop(dst); }
352
374 // Pop two registers. Pops rightmost register first (from lower address). 353 // Pop two registers. Pops rightmost register first (from lower address).
375 void Pop(Register src1, Register src2, Condition cond = al) { 354 void Pop(Register src1, Register src2) {
376 ASSERT(!src1.is(src2)); 355 LoadP(src2, MemOperand(sp, 0));
377 if (src1.code() > src2.code()) { 356 LoadP(src1, MemOperand(sp, kPointerSize));
378 ldm(ia_w, sp, src1.bit() | src2.bit(), cond); 357 addi(sp, sp, Operand(2 * kPointerSize));
379 } else {
380 ldr(src2, MemOperand(sp, 4, PostIndex), cond);
381 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
382 }
383 } 358 }
384 359
385 // Pop three registers. Pops rightmost register first (from lower address). 360 // Pop three registers. Pops rightmost register first (from lower address).
386 void Pop(Register src1, Register src2, Register src3, Condition cond = al) { 361 void Pop(Register src1, Register src2, Register src3) {
387 ASSERT(!src1.is(src2)); 362 LoadP(src3, MemOperand(sp, 0));
388 ASSERT(!src2.is(src3)); 363 LoadP(src2, MemOperand(sp, kPointerSize));
389 ASSERT(!src1.is(src3)); 364 LoadP(src1, MemOperand(sp, 2 * kPointerSize));
390 if (src1.code() > src2.code()) { 365 addi(sp, sp, Operand(3 * kPointerSize));
391 if (src2.code() > src3.code()) {
392 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
393 } else {
394 ldr(src3, MemOperand(sp, 4, PostIndex), cond);
395 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
396 }
397 } else {
398 Pop(src2, src3, cond);
399 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
400 }
401 } 366 }
402 367
403 // Pop four registers. Pops rightmost register first (from lower address). 368 // Pop four registers. Pops rightmost register first (from lower address).
404 void Pop(Register src1, 369 void Pop(Register src1,
405 Register src2, 370 Register src2,
406 Register src3, 371 Register src3,
407 Register src4, 372 Register src4) {
408 Condition cond = al) { 373 LoadP(src4, MemOperand(sp, 0));
409 ASSERT(!src1.is(src2)); 374 LoadP(src3, MemOperand(sp, kPointerSize));
410 ASSERT(!src2.is(src3)); 375 LoadP(src2, MemOperand(sp, 2 * kPointerSize));
411 ASSERT(!src1.is(src3)); 376 LoadP(src1, MemOperand(sp, 3 * kPointerSize));
412 ASSERT(!src1.is(src4)); 377 addi(sp, sp, Operand(4 * kPointerSize));
413 ASSERT(!src2.is(src4));
414 ASSERT(!src3.is(src4));
415 if (src1.code() > src2.code()) {
416 if (src2.code() > src3.code()) {
417 if (src3.code() > src4.code()) {
418 ldm(ia_w,
419 sp,
420 src1.bit() | src2.bit() | src3.bit() | src4.bit(),
421 cond);
422 } else {
423 ldr(src4, MemOperand(sp, 4, PostIndex), cond);
424 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
425 }
426 } else {
427 Pop(src3, src4, cond);
428 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
429 }
430 } else {
431 Pop(src2, src3, src4, cond);
432 ldr(src1, MemOperand(sp, 4, PostIndex), cond);
433 }
434 } 378 }
435 379
436 // Push a fixed frame, consisting of lr, fp, constant pool (if 380 // Pop five registers. Pops rightmost register first (from lower address).
437 // FLAG_enable_ool_constant_pool), context and JS function / marker id if 381 void Pop(Register src1,
438 // marker_reg is a valid register. 382 Register src2,
383 Register src3,
384 Register src4,
385 Register src5) {
386 LoadP(src5, MemOperand(sp, 0));
387 LoadP(src4, MemOperand(sp, kPointerSize));
388 LoadP(src3, MemOperand(sp, 2 * kPointerSize));
389 LoadP(src2, MemOperand(sp, 3 * kPointerSize));
390 LoadP(src1, MemOperand(sp, 4 * kPointerSize));
391 addi(sp, sp, Operand(5 * kPointerSize));
392 }
393
394 // Push a fixed frame, consisting of lr, fp, context and
395 // JS function / marker id if marker_reg is a valid register.
439 void PushFixedFrame(Register marker_reg = no_reg); 396 void PushFixedFrame(Register marker_reg = no_reg);
440 void PopFixedFrame(Register marker_reg = no_reg); 397 void PopFixedFrame(Register marker_reg = no_reg);
441 398
442 // Push and pop the registers that can hold pointers, as defined by the 399 // Push and pop the registers that can hold pointers, as defined by the
443 // RegList constant kSafepointSavedRegisters. 400 // RegList constant kSafepointSavedRegisters.
444 void PushSafepointRegisters(); 401 void PushSafepointRegisters();
445 void PopSafepointRegisters(); 402 void PopSafepointRegisters();
446 // Store value in register src in the safepoint stack slot for 403 // Store value in register src in the safepoint stack slot for
447 // register dst. 404 // register dst.
448 void StoreToSafepointRegisterSlot(Register src, Register dst); 405 void StoreToSafepointRegisterSlot(Register src, Register dst);
449 // Load the value of the src register from its safepoint stack slot 406 // Load the value of the src register from its safepoint stack slot
450 // into register dst. 407 // into register dst.
451 void LoadFromSafepointRegisterSlot(Register dst, Register src); 408 void LoadFromSafepointRegisterSlot(Register dst, Register src);
452 409
453 // Load two consecutive registers with two consecutive memory locations. 410 // Flush the I-cache from asm code. You should use CpuFeatures::FlushICache
454 void Ldrd(Register dst1, 411 // from C.
455 Register dst2, 412 // Does not handle errors.
456 const MemOperand& src, 413 void FlushICache(Register address, size_t size,
457 Condition cond = al); 414 Register scratch);
458
459 // Store two consecutive registers to two consecutive memory locations.
460 void Strd(Register src1,
461 Register src2,
462 const MemOperand& dst,
463 Condition cond = al);
464
465 // Ensure that FPSCR contains values needed by JavaScript.
466 // We need the NaNModeControlBit to be sure that operations like
467 // vadd and vsub generate the Canonical NaN (if a NaN must be generated).
468 // In VFP3 it will be always the Canonical NaN.
469 // In VFP2 it will be either the Canonical NaN or the negative version
470 // of the Canonical NaN. It doesn't matter if we have two values. The aim
471 // is to be sure to never generate the hole NaN.
472 void VFPEnsureFPSCRState(Register scratch);
473 415
474 // If the value is a NaN, canonicalize the value else, do nothing. 416 // If the value is a NaN, canonicalize the value else, do nothing.
475 void VFPCanonicalizeNaN(const DwVfpRegister dst, 417 void CanonicalizeNaN(const DoubleRegister dst,
476 const DwVfpRegister src, 418 const DoubleRegister src);
477 const Condition cond = al); 419 void CanonicalizeNaN(const DoubleRegister value) {
478 void VFPCanonicalizeNaN(const DwVfpRegister value, 420 CanonicalizeNaN(value, value);
479 const Condition cond = al) {
480 VFPCanonicalizeNaN(value, value, cond);
481 } 421 }
482 422
483 // Compare double values and move the result to the normal condition flags. 423 // Converts the integer (untagged smi) in |src| to a double, storing
484 void VFPCompareAndSetFlags(const DwVfpRegister src1, 424 // the result to |double_dst|
485 const DwVfpRegister src2, 425 void ConvertIntToDouble(Register src,
486 const Condition cond = al); 426 DoubleRegister double_dst);
487 void VFPCompareAndSetFlags(const DwVfpRegister src1,
488 const double src2,
489 const Condition cond = al);
490 427
491 // Compare double values and then load the fpscr flags to a register. 428 // Converts the unsigned integer (untagged smi) in |src| to
492 void VFPCompareAndLoadFlags(const DwVfpRegister src1, 429 // a double, storing the result to |double_dst|
493 const DwVfpRegister src2, 430 void ConvertUnsignedIntToDouble(Register src,
494 const Register fpscr_flags, 431 DoubleRegister double_dst);
495 const Condition cond = al);
496 void VFPCompareAndLoadFlags(const DwVfpRegister src1,
497 const double src2,
498 const Register fpscr_flags,
499 const Condition cond = al);
500 432
501 void Vmov(const DwVfpRegister dst, 433 // Converts the integer (untagged smi) in |src| to
502 const double imm, 434 // a float, storing the result in |dst|
503 const Register scratch = no_reg); 435 // Warning: The value in |int_scrach| will be changed in the process!
436 void ConvertIntToFloat(const DoubleRegister dst,
437 const Register src,
438 const Register int_scratch);
504 439
505 void VmovHigh(Register dst, DwVfpRegister src); 440 // Converts the double_input to an integer. Note that, upon return,
506 void VmovHigh(DwVfpRegister dst, Register src); 441 // the contents of double_dst will also hold the fixed point representation.
507 void VmovLow(Register dst, DwVfpRegister src); 442 void ConvertDoubleToInt64(const DoubleRegister double_input,
508 void VmovLow(DwVfpRegister dst, Register src); 443 const Register dst,
509 444 #if !V8_TARGET_ARCH_PPC64
510 // Loads the number from object into dst register. 445 const Register dst_hi,
511 // If |object| is neither smi nor heap number, |not_number| is jumped to 446 #endif
512 // with |object| still intact. 447 const DoubleRegister double_dst,
513 void LoadNumber(Register object, 448 FPRoundingMode rounding_mode = kRoundToZero);
514 LowDwVfpRegister dst,
515 Register heap_number_map,
516 Register scratch,
517 Label* not_number);
518
519 // Loads the number from object into double_dst in the double format.
520 // Control will jump to not_int32 if the value cannot be exactly represented
521 // by a 32-bit integer.
522 // Floating point value in the 32-bit integer range that are not exact integer
523 // won't be loaded.
524 void LoadNumberAsInt32Double(Register object,
525 DwVfpRegister double_dst,
526 Register heap_number_map,
527 Register scratch,
528 LowDwVfpRegister double_scratch,
529 Label* not_int32);
530
531 // Loads the number from object into dst as a 32-bit integer.
532 // Control will jump to not_int32 if the object cannot be exactly represented
533 // by a 32-bit integer.
534 // Floating point value in the 32-bit integer range that are not exact integer
535 // won't be converted.
536 void LoadNumberAsInt32(Register object,
537 Register dst,
538 Register heap_number_map,
539 Register scratch,
540 DwVfpRegister double_scratch0,
541 LowDwVfpRegister double_scratch1,
542 Label* not_int32);
543 449
544 // Generates function and stub prologue code. 450 // Generates function and stub prologue code.
545 void StubPrologue(); 451 void StubPrologue();
546 void Prologue(bool code_pre_aging); 452 void Prologue(bool code_pre_aging);
547 453
548 // Enter exit frame. 454 // Enter exit frame.
549 // stack_space - extra stack space, used for alignment before call to C. 455 // stack_space - extra stack space, used for alignment before call to C.
550 void EnterExitFrame(bool save_doubles, int stack_space = 0); 456 void EnterExitFrame(bool save_doubles, int stack_space = 0);
551 457
552 // Leave the current exit frame. Expects the return value in r0. 458 // Leave the current exit frame. Expects the return value in r0.
(...skipping 26 matching lines...) Expand all
579 void LoadGlobalFunctionInitialMap(Register function, 485 void LoadGlobalFunctionInitialMap(Register function,
580 Register map, 486 Register map,
581 Register scratch); 487 Register scratch);
582 488
583 void InitializeRootRegister() { 489 void InitializeRootRegister() {
584 ExternalReference roots_array_start = 490 ExternalReference roots_array_start =
585 ExternalReference::roots_array_start(isolate()); 491 ExternalReference::roots_array_start(isolate());
586 mov(kRootRegister, Operand(roots_array_start)); 492 mov(kRootRegister, Operand(roots_array_start));
587 } 493 }
588 494
495 // ----------------------------------------------------------------
496 // new PPC macro-assembler interfaces that are slightly higher level
497 // than assembler-ppc and may generate variable length sequences
498
499 // load a literal signed int value <value> to GPR <dst>
500 void LoadIntLiteral(Register dst, int value);
501
502 // load an SMI value <value> to GPR <dst>
503 void LoadSmiLiteral(Register dst, Smi *smi);
504
505 // load a literal double value <value> to FPR <result>
506 void LoadDoubleLiteral(DoubleRegister result,
507 double value,
508 Register scratch);
509
510 void LoadWord(Register dst,
511 const MemOperand& mem,
512 Register scratch,
513 bool updateForm = false);
514
515 void LoadWordArith(Register dst,
516 const MemOperand& mem,
517 Register scratch = no_reg);
518
519 void StoreWord(Register src,
520 const MemOperand& mem,
521 Register scratch,
522 bool updateForm = false);
523
524 void LoadHalfWord(Register dst,
525 const MemOperand& mem,
526 Register scratch,
527 bool updateForm = false);
528
529 void StoreHalfWord(Register src,
530 const MemOperand& mem,
531 Register scratch,
532 bool updateForm = false);
533
534 void LoadByte(Register dst,
535 const MemOperand& mem,
536 Register scratch,
537 bool updateForm = false);
538
539 void StoreByte(Register src,
540 const MemOperand& mem,
541 Register scratch,
542 bool updateForm = false);
543
544 void LoadRepresentation(Register dst,
545 const MemOperand& mem,
546 Representation r,
547 Register scratch = no_reg);
548
549 void StoreRepresentation(Register src,
550 const MemOperand& mem,
551 Representation r,
552 Register scratch = no_reg);
553
554
555
556 void Add(Register dst, Register src, intptr_t value, Register scratch);
557 void Cmpi(Register src1, const Operand& src2, Register scratch,
558 CRegister cr = cr7);
559 void Cmpli(Register src1, const Operand& src2, Register scratch,
560 CRegister cr = cr7);
561 void Cmpwi(Register src1, const Operand& src2, Register scratch,
562 CRegister cr = cr7);
563 void Cmplwi(Register src1, const Operand& src2, Register scratch,
564 CRegister cr = cr7);
565 void And(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
566 void Or(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
567 void Xor(Register ra, Register rs, const Operand& rb, RCBit rc = LeaveRC);
568
569 void AddSmiLiteral(Register dst, Register src, Smi *smi, Register scratch);
570 void SubSmiLiteral(Register dst, Register src, Smi *smi, Register scratch);
571 void CmpSmiLiteral(Register src1, Smi *smi, Register scratch,
572 CRegister cr = cr7);
573 void CmplSmiLiteral(Register src1, Smi *smi, Register scratch,
574 CRegister cr = cr7);
575 void AndSmiLiteral(Register dst, Register src, Smi *smi, Register scratch,
576 RCBit rc = LeaveRC);
577
578 // Set new rounding mode RN to FPSCR
579 void SetRoundingMode(FPRoundingMode RN);
580
581 // reset rounding mode to default (kRoundToNearest)
582 void ResetRoundingMode();
583
584 // These exist to provide portability between 32 and 64bit
585 void LoadP(Register dst, const MemOperand& mem, Register scratch = no_reg);
586 void StoreP(Register src, const MemOperand& mem, Register scratch = no_reg);
587
589 // --------------------------------------------------------------------------- 588 // ---------------------------------------------------------------------------
590 // JavaScript invokes 589 // JavaScript invokes
591 590
592 // Invoke the JavaScript function code by either calling or jumping. 591 // Invoke the JavaScript function code by either calling or jumping.
593 void InvokeCode(Register code, 592 void InvokeCode(Register code,
594 const ParameterCount& expected, 593 const ParameterCount& expected,
595 const ParameterCount& actual, 594 const ParameterCount& actual,
596 InvokeFlag flag, 595 InvokeFlag flag,
597 const CallWrapper& call_wrapper); 596 const CallWrapper& call_wrapper);
598 597
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 // space is full and a scavenge is needed. All registers are clobbered also 777 // space is full and a scavenge is needed. All registers are clobbered also
779 // when control continues at the gc_required label. 778 // when control continues at the gc_required label.
780 void AllocateHeapNumber(Register result, 779 void AllocateHeapNumber(Register result,
781 Register scratch1, 780 Register scratch1,
782 Register scratch2, 781 Register scratch2,
783 Register heap_number_map, 782 Register heap_number_map,
784 Label* gc_required, 783 Label* gc_required,
785 TaggingMode tagging_mode = TAG_RESULT, 784 TaggingMode tagging_mode = TAG_RESULT,
786 MutableMode mode = IMMUTABLE); 785 MutableMode mode = IMMUTABLE);
787 void AllocateHeapNumberWithValue(Register result, 786 void AllocateHeapNumberWithValue(Register result,
788 DwVfpRegister value, 787 DoubleRegister value,
789 Register scratch1, 788 Register scratch1,
790 Register scratch2, 789 Register scratch2,
791 Register heap_number_map, 790 Register heap_number_map,
792 Label* gc_required); 791 Label* gc_required);
793 792
794 // Copies a fixed number of fields of heap objects from src to dst. 793 // Copies a fixed number of fields of heap objects from src to dst.
795 void CopyFields(Register dst, 794 void CopyFields(Register dst, Register src, RegList temps, int field_count);
796 Register src,
797 LowDwVfpRegister double_scratch,
798 int field_count);
799 795
800 // Copies a number of bytes from src to dst. All registers are clobbered. On 796 // Copies a number of bytes from src to dst. All registers are clobbered. On
801 // exit src and dst will point to the place just after where the last byte was 797 // exit src and dst will point to the place just after where the last byte was
802 // read or written and length will be zero. 798 // read or written and length will be zero.
803 void CopyBytes(Register src, 799 void CopyBytes(Register src,
804 Register dst, 800 Register dst,
805 Register length, 801 Register length,
806 Register scratch); 802 Register scratch);
807 803
804 // Initialize fields with filler values. |count| fields starting at
805 // |start_offset| are overwritten with the value in |filler|. At the end the
806 // loop, |start_offset| points at the next uninitialized field. |count| is
807 // assumed to be non-zero.
808 void InitializeNFieldsWithFiller(Register start_offset,
809 Register count,
810 Register filler);
811
808 // Initialize fields with filler values. Fields starting at |start_offset| 812 // Initialize fields with filler values. Fields starting at |start_offset|
809 // not including end_offset are overwritten with the value in |filler|. At 813 // not including end_offset are overwritten with the value in |filler|. At
810 // the end the loop, |start_offset| takes the value of |end_offset|. 814 // the end the loop, |start_offset| takes the value of |end_offset|.
811 void InitializeFieldsWithFiller(Register start_offset, 815 void InitializeFieldsWithFiller(Register start_offset,
812 Register end_offset, 816 Register end_offset,
813 Register filler); 817 Register filler);
814 818
815 // --------------------------------------------------------------------------- 819 // ---------------------------------------------------------------------------
816 // Support functions. 820 // Support functions.
817 821
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
874 Register scratch, 878 Register scratch,
875 Label* fail); 879 Label* fail);
876 880
877 // Check to see if maybe_number can be stored as a double in 881 // Check to see if maybe_number can be stored as a double in
878 // FastDoubleElements. If it can, store it at the index specified by key in 882 // FastDoubleElements. If it can, store it at the index specified by key in
879 // the FastDoubleElements array elements. Otherwise jump to fail. 883 // the FastDoubleElements array elements. Otherwise jump to fail.
880 void StoreNumberToDoubleElements(Register value_reg, 884 void StoreNumberToDoubleElements(Register value_reg,
881 Register key_reg, 885 Register key_reg,
882 Register elements_reg, 886 Register elements_reg,
883 Register scratch1, 887 Register scratch1,
884 LowDwVfpRegister double_scratch, 888 DoubleRegister double_scratch,
885 Label* fail, 889 Label* fail,
886 int elements_offset = 0); 890 int elements_offset = 0);
887 891
888 // Compare an object's map with the specified map and its transitioned 892 // Compare an object's map with the specified map and its transitioned
889 // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are 893 // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are
890 // set with result of map compare. If multiple map compares are required, the 894 // set with result of map compare. If multiple map compares are required, the
891 // compare sequences branches to early_success. 895 // compare sequences branches to early_success.
892 void CompareMap(Register obj, 896 void CompareMap(Register obj,
893 Register scratch, 897 Register scratch,
894 Handle<Map> map, 898 Handle<Map> map,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 SmiCheckType smi_check_type); 932 SmiCheckType smi_check_type);
929 933
930 934
931 // Compare the object in a register to a value from the root list. 935 // Compare the object in a register to a value from the root list.
932 // Uses the ip register as scratch. 936 // Uses the ip register as scratch.
933 void CompareRoot(Register obj, Heap::RootListIndex index); 937 void CompareRoot(Register obj, Heap::RootListIndex index);
934 938
935 939
936 // Load and check the instance type of an object for being a string. 940 // Load and check the instance type of an object for being a string.
937 // Loads the type into the second argument register. 941 // Loads the type into the second argument register.
938 // Returns a condition that will be enabled if the object was a string 942 // Returns a condition that will be enabled if the object was a string.
939 // and the passed-in condition passed. If the passed-in condition failed
940 // then flags remain unchanged.
941 Condition IsObjectStringType(Register obj, 943 Condition IsObjectStringType(Register obj,
942 Register type, 944 Register type) {
943 Condition cond = al) { 945 LoadP(type, FieldMemOperand(obj, HeapObject::kMapOffset));
944 ldr(type, FieldMemOperand(obj, HeapObject::kMapOffset), cond); 946 lbz(type, FieldMemOperand(type, Map::kInstanceTypeOffset));
945 ldrb(type, FieldMemOperand(type, Map::kInstanceTypeOffset), cond); 947 andi(r0, type, Operand(kIsNotStringMask));
946 tst(type, Operand(kIsNotStringMask), cond);
947 ASSERT_EQ(0, kStringTag); 948 ASSERT_EQ(0, kStringTag);
948 return eq; 949 return eq;
949 } 950 }
950 951
951 952
952 // Picks out an array index from the hash field. 953 // Picks out an array index from the hash field.
953 // Register use: 954 // Register use:
954 // hash - holds the index's hash. Clobbered. 955 // hash - holds the index's hash. Clobbered.
955 // index - holds the overwritten index on exit. 956 // index - holds the overwritten index on exit.
956 void IndexFromHash(Register hash, Register index); 957 void IndexFromHash(Register hash, Register index);
957 958
958 // Get the number of least significant bits from a register 959 // Get the number of least significant bits from a register
959 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits); 960 void GetLeastBitsFromSmi(Register dst, Register src, int num_least_bits);
960 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits); 961 void GetLeastBitsFromInt32(Register dst, Register src, int mun_least_bits);
961 962
962 // Load the value of a smi object into a double register. 963 // Load the value of a smi object into a double register.
963 // The register value must be between d0 and d15. 964 void SmiToDouble(DoubleRegister value, Register smi);
964 void SmiToDouble(LowDwVfpRegister value, Register smi);
965 965
966 // Check if a double can be exactly represented as a signed 32-bit integer. 966 // Check if a double can be exactly represented as a signed 32-bit integer.
967 // Z flag set to one if true. 967 // CR_EQ in cr7 is set if true.
968 void TestDoubleIsInt32(DwVfpRegister double_input, 968 void TestDoubleIsInt32(DoubleRegister double_input,
969 LowDwVfpRegister double_scratch); 969 Register scratch1,
970 Register scratch2,
971 DoubleRegister double_scratch);
970 972
971 // Try to convert a double to a signed 32-bit integer. 973 // Try to convert a double to a signed 32-bit integer.
972 // Z flag set to one and result assigned if the conversion is exact. 974 // CR_EQ in cr7 is set and result assigned if the conversion is exact.
973 void TryDoubleToInt32Exact(Register result, 975 void TryDoubleToInt32Exact(Register result,
974 DwVfpRegister double_input, 976 DoubleRegister double_input,
975 LowDwVfpRegister double_scratch); 977 Register scratch,
978 DoubleRegister double_scratch);
976 979
977 // Floor a double and writes the value to the result register. 980 // Floor a double and writes the value to the result register.
978 // Go to exact if the conversion is exact (to be able to test -0), 981 // Go to exact if the conversion is exact (to be able to test -0),
979 // fall through calling code if an overflow occurred, else go to done. 982 // fall through calling code if an overflow occurred, else go to done.
980 // In return, input_high is loaded with high bits of input. 983 // In return, input_high is loaded with high bits of input.
981 void TryInt32Floor(Register result, 984 void TryInt32Floor(Register result,
982 DwVfpRegister double_input, 985 DoubleRegister double_input,
983 Register input_high, 986 Register input_high,
984 LowDwVfpRegister double_scratch, 987 Register scratch,
988 DoubleRegister double_scratch,
985 Label* done, 989 Label* done,
986 Label* exact); 990 Label* exact);
987 991
988 // Performs a truncating conversion of a floating point number as used by 992 // Performs a truncating conversion of a floating point number as used by
989 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it 993 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. Goes to 'done' if it
990 // succeeds, otherwise falls through if result is saturated. On return 994 // succeeds, otherwise falls through if result is saturated. On return
991 // 'result' either holds answer, or is clobbered on fall through. 995 // 'result' either holds answer, or is clobbered on fall through.
992 // 996 //
993 // Only public for the test code in test-code-stubs-arm.cc. 997 // Only public for the test code in test-code-stubs-arm.cc.
994 void TryInlineTruncateDoubleToI(Register result, 998 void TryInlineTruncateDoubleToI(Register result,
995 DwVfpRegister input, 999 DoubleRegister input,
996 Label* done); 1000 Label* done);
997 1001
998 // Performs a truncating conversion of a floating point number as used by 1002 // Performs a truncating conversion of a floating point number as used by
999 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 1003 // the JS bitwise operations. See ECMA-262 9.5: ToInt32.
1000 // Exits with 'result' holding the answer. 1004 // Exits with 'result' holding the answer.
1001 void TruncateDoubleToI(Register result, DwVfpRegister double_input); 1005 void TruncateDoubleToI(Register result, DoubleRegister double_input);
1002 1006
1003 // Performs a truncating conversion of a heap number as used by 1007 // Performs a truncating conversion of a heap number as used by
1004 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input' 1008 // the JS bitwise operations. See ECMA-262 9.5: ToInt32. 'result' and 'input'
1005 // must be different registers. Exits with 'result' holding the answer. 1009 // must be different registers. Exits with 'result' holding the answer.
1006 void TruncateHeapNumberToI(Register result, Register object); 1010 void TruncateHeapNumberToI(Register result, Register object);
1007 1011
1008 // Converts the smi or heap number in object to an int32 using the rules 1012 // Converts the smi or heap number in object to an int32 using the rules
1009 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated 1013 // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
1010 // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be 1014 // and brought into the range -2^31 .. +2^31 - 1. 'result' and 'input' must be
1011 // different registers. 1015 // different registers.
1012 void TruncateNumberToI(Register object, 1016 void TruncateNumberToI(Register object,
1013 Register result, 1017 Register result,
1014 Register heap_number_map, 1018 Register heap_number_map,
1015 Register scratch1, 1019 Register scratch1,
1016 Label* not_int32); 1020 Label* not_int32);
1017 1021
1018 // Check whether d16-d31 are available on the CPU. The result is given by the 1022 // Overflow handling functions.
1019 // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise. 1023 // Usage: call the appropriate arithmetic function and then call one of the
1020 void CheckFor32DRegs(Register scratch); 1024 // flow control functions with the corresponding label.
1021 1025
1022 // Does a runtime check for 16/32 FP registers. Either way, pushes 32 double 1026 // Compute dst = left + right, setting condition codes. dst may be same as
1023 // values to location, saving [d0..(d15|d31)]. 1027 // either left or right (or a unique register). left and right must not be
1024 void SaveFPRegs(Register location, Register scratch); 1028 // the same register.
1029 void AddAndCheckForOverflow(Register dst,
1030 Register left,
1031 Register right,
1032 Register overflow_dst,
1033 Register scratch = r0);
1025 1034
1026 // Does a runtime check for 16/32 FP registers. Either way, pops 32 double 1035 // Compute dst = left - right, setting condition codes. dst may be same as
1027 // values to location, restoring [d0..(d15|d31)]. 1036 // either left or right (or a unique register). left and right must not be
1028 void RestoreFPRegs(Register location, Register scratch); 1037 // the same register.
1038 void SubAndCheckForOverflow(Register dst,
1039 Register left,
1040 Register right,
1041 Register overflow_dst,
1042 Register scratch = r0);
1043
1044 void BranchOnOverflow(Label* label) {
1045 blt(label, cr0);
1046 }
1047
1048 void BranchOnNoOverflow(Label* label) {
1049 bge(label, cr0);
1050 }
1051
1052 void RetOnOverflow(void) {
1053 Label label;
1054
1055 blt(&label, cr0);
1056 Ret();
1057 bind(&label);
1058 }
1059
1060 void RetOnNoOverflow(void) {
1061 Label label;
1062
1063 bge(&label, cr0);
1064 Ret();
1065 bind(&label);
1066 }
1067
1068 // Pushes <count> double values to <location>, starting from d<first>.
1069 void SaveFPRegs(Register location, int first, int count);
1070
1071 // Pops <count> double values from <location>, starting from d<first>.
1072 void RestoreFPRegs(Register location, int first, int count);
1029 1073
1030 // --------------------------------------------------------------------------- 1074 // ---------------------------------------------------------------------------
1031 // Runtime calls 1075 // Runtime calls
1032 1076
1033 // Call a code stub. 1077 // Call a code stub.
1034 void CallStub(CodeStub* stub, 1078 void CallStub(CodeStub* stub,
1035 TypeFeedbackId ast_id = TypeFeedbackId::None(), 1079 TypeFeedbackId ast_id = TypeFeedbackId::None(),
1036 Condition cond = al); 1080 Condition cond = al);
1037 1081
1038 // Call a code stub. 1082 // Call a code stub.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 void PrepareCallCFunction(int num_reg_arguments, 1130 void PrepareCallCFunction(int num_reg_arguments,
1087 int num_double_registers, 1131 int num_double_registers,
1088 Register scratch); 1132 Register scratch);
1089 void PrepareCallCFunction(int num_reg_arguments, 1133 void PrepareCallCFunction(int num_reg_arguments,
1090 Register scratch); 1134 Register scratch);
1091 1135
1092 // There are two ways of passing double arguments on ARM, depending on 1136 // There are two ways of passing double arguments on ARM, depending on
1093 // whether soft or hard floating point ABI is used. These functions 1137 // whether soft or hard floating point ABI is used. These functions
1094 // abstract parameter passing for the three different ways we call 1138 // abstract parameter passing for the three different ways we call
1095 // C functions from generated code. 1139 // C functions from generated code.
1096 void MovToFloatParameter(DwVfpRegister src); 1140 void MovToFloatParameter(DoubleRegister src);
1097 void MovToFloatParameters(DwVfpRegister src1, DwVfpRegister src2); 1141 void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
1098 void MovToFloatResult(DwVfpRegister src); 1142 void MovToFloatResult(DoubleRegister src);
1099 1143
1100 // Calls a C function and cleans up the space for arguments allocated 1144 // Calls a C function and cleans up the space for arguments allocated
1101 // by PrepareCallCFunction. The called function is not allowed to trigger a 1145 // by PrepareCallCFunction. The called function is not allowed to trigger a
1102 // garbage collection, since that might move the code and invalidate the 1146 // garbage collection, since that might move the code and invalidate the
1103 // return address (unless this is somehow accounted for by the called 1147 // return address (unless this is somehow accounted for by the called
1104 // function). 1148 // function).
1105 void CallCFunction(ExternalReference function, int num_arguments); 1149 void CallCFunction(ExternalReference function, int num_arguments);
1106 void CallCFunction(Register function, int num_arguments); 1150 void CallCFunction(Register function, int num_arguments);
1107 void CallCFunction(ExternalReference function, 1151 void CallCFunction(ExternalReference function,
1108 int num_reg_arguments, 1152 int num_reg_arguments,
1109 int num_double_arguments); 1153 int num_double_arguments);
1110 void CallCFunction(Register function, 1154 void CallCFunction(Register function,
1111 int num_reg_arguments, 1155 int num_reg_arguments,
1112 int num_double_arguments); 1156 int num_double_arguments);
1113 1157
1114 void MovFromFloatParameter(DwVfpRegister dst); 1158 void MovFromFloatParameter(DoubleRegister dst);
1115 void MovFromFloatResult(DwVfpRegister dst); 1159 void MovFromFloatResult(DoubleRegister dst);
1116 1160
1117 // Calls an API function. Allocates HandleScope, extracts returned value 1161 // Calls an API function. Allocates HandleScope, extracts returned value
1118 // from handle and propagates exceptions. Restores context. stack_space 1162 // from handle and propagates exceptions. Restores context. stack_space
1119 // - space to be unwound on exit (includes the call JS arguments space and 1163 // - space to be unwound on exit (includes the call JS arguments space and
1120 // the additional space allocated for the fast call). 1164 // the additional space allocated for the fast call).
1121 void CallApiFunctionAndReturn(Register function_address, 1165 void CallApiFunctionAndReturn(Register function_address,
1122 ExternalReference thunk_ref, 1166 ExternalReference thunk_ref,
1123 int stack_space, 1167 int stack_space,
1124 MemOperand return_value_operand, 1168 MemOperand return_value_operand,
1125 MemOperand* context_restore_operand); 1169 MemOperand* context_restore_operand);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1159 Register scratch1, Register scratch2); 1203 Register scratch1, Register scratch2);
1160 void DecrementCounter(StatsCounter* counter, int value, 1204 void DecrementCounter(StatsCounter* counter, int value,
1161 Register scratch1, Register scratch2); 1205 Register scratch1, Register scratch2);
1162 1206
1163 1207
1164 // --------------------------------------------------------------------------- 1208 // ---------------------------------------------------------------------------
1165 // Debugging 1209 // Debugging
1166 1210
1167 // Calls Abort(msg) if the condition cond is not satisfied. 1211 // Calls Abort(msg) if the condition cond is not satisfied.
1168 // Use --debug_code to enable. 1212 // Use --debug_code to enable.
1169 void Assert(Condition cond, BailoutReason reason); 1213 void Assert(Condition cond, BailoutReason reason, CRegister cr = cr7);
1170 void AssertFastElements(Register elements); 1214 void AssertFastElements(Register elements);
1171 1215
1172 // Like Assert(), but always enabled. 1216 // Like Assert(), but always enabled.
1173 void Check(Condition cond, BailoutReason reason); 1217 void Check(Condition cond, BailoutReason reason, CRegister cr = cr7);
1174 1218
1175 // Print a message to stdout and abort execution. 1219 // Print a message to stdout and abort execution.
1176 void Abort(BailoutReason msg); 1220 void Abort(BailoutReason reason);
1177 1221
1178 // Verify restrictions about code generated in stubs. 1222 // Verify restrictions about code generated in stubs.
1179 void set_generating_stub(bool value) { generating_stub_ = value; } 1223 void set_generating_stub(bool value) { generating_stub_ = value; }
1180 bool generating_stub() { return generating_stub_; } 1224 bool generating_stub() { return generating_stub_; }
1181 void set_has_frame(bool value) { has_frame_ = value; } 1225 void set_has_frame(bool value) { has_frame_ = value; }
1182 bool has_frame() { return has_frame_; } 1226 bool has_frame() { return has_frame_; }
1183 inline bool AllowThisStubCall(CodeStub* stub); 1227 inline bool AllowThisStubCall(CodeStub* stub);
1184 1228
1185 // EABI variant for double arguments in use.
1186 bool use_eabi_hardfloat() {
1187 #ifdef __arm__
1188 return base::OS::ArmUsingHardFloat();
1189 #elif USE_EABI_HARDFLOAT
1190 return true;
1191 #else
1192 return false;
1193 #endif
1194 }
1195
1196 // --------------------------------------------------------------------------- 1229 // ---------------------------------------------------------------------------
1197 // Number utilities 1230 // Number utilities
1198 1231
1199 // Check whether the value of reg is a power of two and not zero. If not 1232 // Check whether the value of reg is a power of two and not zero. If not
1200 // control continues at the label not_power_of_two. If reg is a power of two 1233 // control continues at the label not_power_of_two. If reg is a power of two
1201 // the register scratch contains the value of (reg - 1) when control falls 1234 // the register scratch contains the value of (reg - 1) when control falls
1202 // through. 1235 // through.
1203 void JumpIfNotPowerOfTwoOrZero(Register reg, 1236 void JumpIfNotPowerOfTwoOrZero(Register reg,
1204 Register scratch, 1237 Register scratch,
1205 Label* not_power_of_two_or_zero); 1238 Label* not_power_of_two_or_zero);
1206 // Check whether the value of reg is a power of two and not zero. 1239 // Check whether the value of reg is a power of two and not zero.
1207 // Control falls through if it is, with scratch containing the mask 1240 // Control falls through if it is, with scratch containing the mask
1208 // value (reg - 1). 1241 // value (reg - 1).
1209 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is 1242 // Otherwise control jumps to the 'zero_and_neg' label if the value of reg is
1210 // zero or negative, or jumps to the 'not_power_of_two' label if the value is 1243 // zero or negative, or jumps to the 'not_power_of_two' label if the value is
1211 // strictly positive but not a power of two. 1244 // strictly positive but not a power of two.
1212 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg, 1245 void JumpIfNotPowerOfTwoOrZeroAndNeg(Register reg,
1213 Register scratch, 1246 Register scratch,
1214 Label* zero_and_neg, 1247 Label* zero_and_neg,
1215 Label* not_power_of_two); 1248 Label* not_power_of_two);
1216 1249
1217 // --------------------------------------------------------------------------- 1250 // ---------------------------------------------------------------------------
1251 // Bit testing/extraction
1252 //
1253 // Bit numbering is such that the least significant bit is bit 0
1254 // (for consistency between 32/64-bit).
1255
1256 // Extract consecutive bits (defined by rangeStart - rangeEnd) from src
1257 // and place them into the least significant bits of dst.
1258 inline void ExtractBitRange(Register dst, Register src,
1259 int rangeStart, int rangeEnd,
1260 RCBit rc = LeaveRC) {
1261 ASSERT(rangeStart >= rangeEnd && rangeStart < kBitsPerPointer);
1262 int rotate = (rangeEnd == 0) ? 0 : kBitsPerPointer - rangeEnd;
1263 int width = rangeStart - rangeEnd + 1;
1264 #if V8_TARGET_ARCH_PPC64
1265 rldicl(dst, src, rotate, kBitsPerPointer - width, rc);
1266 #else
1267 rlwinm(dst, src, rotate, kBitsPerPointer - width, kBitsPerPointer - 1, rc);
1268 #endif
1269 }
1270
1271 inline void ExtractBit(Register dst, Register src, uint32_t bitNumber,
1272 RCBit rc = LeaveRC) {
1273 ExtractBitRange(dst, src, bitNumber, bitNumber, rc);
1274 }
1275
1276 // Extract consecutive bits (defined by mask) from src and place them
1277 // into the least significant bits of dst.
1278 inline void ExtractBitMask(Register dst, Register src, uintptr_t mask,
1279 RCBit rc = LeaveRC) {
1280 int start = kBitsPerPointer - 1;
1281 int end;
1282 uintptr_t bit = (1L << start);
1283
1284 while (bit && (mask & bit) == 0) {
1285 start--;
1286 bit >>= 1;
1287 }
1288 end = start;
1289 bit >>= 1;
1290
1291 while (bit && (mask & bit)) {
1292 end--;
1293 bit >>= 1;
1294 }
1295
1296 // 1-bits in mask must be contiguous
1297 ASSERT(bit == 0 || (mask & ((bit << 1) - 1)) == 0);
1298
1299 ExtractBitRange(dst, src, start, end, rc);
1300 }
1301
1302 // Test single bit in value.
1303 inline void TestBit(Register value, int bitNumber,
1304 Register scratch = r0) {
1305 ExtractBitRange(scratch, value, bitNumber, bitNumber, SetRC);
1306 }
1307
1308 // Test consecutive bit range in value. Range is defined by
1309 // rangeStart - rangeEnd.
1310 inline void TestBitRange(Register value,
1311 int rangeStart, int rangeEnd,
1312 Register scratch = r0) {
1313 ExtractBitRange(scratch, value, rangeStart, rangeEnd, SetRC);
1314 }
1315
1316 // Test consecutive bit range in value. Range is defined by mask.
1317 inline void TestBitMask(Register value, uintptr_t mask,
1318 Register scratch = r0) {
1319 ExtractBitMask(scratch, value, mask, SetRC);
1320 }
1321
1322
1323 // ---------------------------------------------------------------------------
1218 // Smi utilities 1324 // Smi utilities
1219 1325
1220 void SmiTag(Register reg, SBit s = LeaveCC) { 1326 // Shift left by 1
1221 add(reg, reg, Operand(reg), s); 1327 void SmiTag(Register reg, RCBit rc = LeaveRC) {
1328 SmiTag(reg, reg, rc);
1222 } 1329 }
1223 void SmiTag(Register dst, Register src, SBit s = LeaveCC) { 1330 void SmiTag(Register dst, Register src, RCBit rc = LeaveRC) {
1224 add(dst, src, Operand(src), s); 1331 ShiftLeftImm(dst, src, Operand(kSmiShift), rc);
1225 } 1332 }
1226 1333
1227 // Try to convert int32 to smi. If the value is to large, preserve 1334 #if !V8_TARGET_ARCH_PPC64
1228 // the original value and jump to not_a_smi. Destroys scratch and 1335 // Test for overflow < 0: use BranchOnOverflow() or BranchOnNoOverflow().
1229 // sets flags. 1336 void SmiTagCheckOverflow(Register reg, Register overflow);
1230 void TrySmiTag(Register reg, Label* not_a_smi) { 1337 void SmiTagCheckOverflow(Register dst, Register src, Register overflow);
1231 TrySmiTag(reg, reg, not_a_smi); 1338
1339 inline void JumpIfNotSmiCandidate(Register value, Register scratch,
1340 Label* not_smi_label) {
1341 // High bits must be identical to fit into an Smi
1342 addis(scratch, value, Operand(0x40000000u >> 16));
1343 cmpi(scratch, Operand::Zero());
1344 blt(not_smi_label);
1232 } 1345 }
1233 void TrySmiTag(Register reg, Register src, Label* not_a_smi) { 1346 #endif
1234 SmiTag(ip, src, SetCC); 1347 inline void TestUnsignedSmiCandidate(Register value, Register scratch) {
1235 b(vs, not_a_smi); 1348 // The test is different for unsigned int values. Since we need
1236 mov(reg, ip); 1349 // the value to be in the range of a positive smi, we can't
1350 // handle any of the high bits being set in the value.
1351 TestBitRange(value,
1352 kBitsPerPointer - 1,
1353 kBitsPerPointer - 1 - kSmiShift,
1354 scratch);
1355 }
1356 inline void JumpIfNotUnsignedSmiCandidate(Register value, Register scratch,
1357 Label* not_smi_label) {
1358 TestUnsignedSmiCandidate(value, scratch);
1359 bne(not_smi_label, cr0);
1237 } 1360 }
1238 1361
1362 void SmiUntag(Register reg, RCBit rc = LeaveRC) {
1363 SmiUntag(reg, reg, rc);
1364 }
1239 1365
1240 void SmiUntag(Register reg, SBit s = LeaveCC) { 1366 void SmiUntag(Register dst, Register src, RCBit rc = LeaveRC) {
1241 mov(reg, Operand::SmiUntag(reg), s); 1367 ShiftRightArithImm(dst, src, kSmiShift, rc);
1242 } 1368 }
1243 void SmiUntag(Register dst, Register src, SBit s = LeaveCC) { 1369
1244 mov(dst, Operand::SmiUntag(src), s); 1370 void SmiToPtrArrayOffset(Register dst, Register src) {
1371 #if V8_TARGET_ARCH_PPC64
1372 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kPointerSizeLog2);
1373 ShiftRightArithImm(dst, src, kSmiShift - kPointerSizeLog2);
1374 #else
1375 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kPointerSizeLog2);
1376 ShiftLeftImm(dst, src, Operand(kPointerSizeLog2 - kSmiShift));
1377 #endif
1378 }
1379
1380 void SmiToByteArrayOffset(Register dst, Register src) {
1381 SmiUntag(dst, src);
1382 }
1383
1384 void SmiToShortArrayOffset(Register dst, Register src) {
1385 #if V8_TARGET_ARCH_PPC64
1386 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 1);
1387 ShiftRightArithImm(dst, src, kSmiShift - 1);
1388 #else
1389 STATIC_ASSERT(kSmiTag == 0 && kSmiShift == 1);
1390 if (!dst.is(src)) {
1391 mr(dst, src);
1392 }
1393 #endif
1394 }
1395
1396 void SmiToIntArrayOffset(Register dst, Register src) {
1397 #if V8_TARGET_ARCH_PPC64
1398 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > 2);
1399 ShiftRightArithImm(dst, src, kSmiShift - 2);
1400 #else
1401 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < 2);
1402 ShiftLeftImm(dst, src, Operand(2 - kSmiShift));
1403 #endif
1404 }
1405
1406 #define SmiToFloatArrayOffset SmiToIntArrayOffset
1407
1408 void SmiToDoubleArrayOffset(Register dst, Register src) {
1409 #if V8_TARGET_ARCH_PPC64
1410 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kDoubleSizeLog2);
1411 ShiftRightArithImm(dst, src, kSmiShift - kDoubleSizeLog2);
1412 #else
1413 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kDoubleSizeLog2);
1414 ShiftLeftImm(dst, src, Operand(kDoubleSizeLog2 - kSmiShift));
1415 #endif
1416 }
1417
1418 void SmiToArrayOffset(Register dst, Register src, int elementSizeLog2) {
1419 if (kSmiShift < elementSizeLog2) {
1420 ShiftLeftImm(dst, src, Operand(elementSizeLog2 - kSmiShift));
1421 } else if (kSmiShift > elementSizeLog2) {
1422 ShiftRightArithImm(dst, src, kSmiShift - elementSizeLog2);
1423 } else if (!dst.is(src)) {
1424 mr(dst, src);
1425 }
1426 }
1427
1428 void IndexToArrayOffset(Register dst, Register src, int elementSizeLog2,
1429 bool isSmi) {
1430 if (isSmi) {
1431 SmiToArrayOffset(dst, src, elementSizeLog2);
1432 } else {
1433 ShiftLeftImm(dst, src, Operand(elementSizeLog2));
1434 }
1245 } 1435 }
1246 1436
1247 // Untag the source value into destination and jump if source is a smi. 1437 // Untag the source value into destination and jump if source is a smi.
1248 // Souce and destination can be the same register. 1438 // Souce and destination can be the same register.
1249 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case); 1439 void UntagAndJumpIfSmi(Register dst, Register src, Label* smi_case);
1250 1440
1251 // Untag the source value into destination and jump if source is not a smi. 1441 // Untag the source value into destination and jump if source is not a smi.
1252 // Souce and destination can be the same register. 1442 // Souce and destination can be the same register.
1253 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case); 1443 void UntagAndJumpIfNotSmi(Register dst, Register src, Label* non_smi_case);
1254 1444
1255 // Test if the register contains a smi (Z == 0 (eq) if true). 1445 inline void TestIfSmi(Register value, Register scratch) {
1256 inline void SmiTst(Register value) { 1446 TestBit(value, 0, scratch); // tst(value, Operand(kSmiTagMask));
1257 tst(value, Operand(kSmiTagMask));
1258 } 1447 }
1259 inline void NonNegativeSmiTst(Register value) { 1448
1260 tst(value, Operand(kSmiTagMask | kSmiSignMask)); 1449 inline void TestIfPositiveSmi(Register value, Register scratch) {
1450 STATIC_ASSERT((kSmiTagMask | kSmiSignMask) ==
1451 (intptr_t)(1UL << (kBitsPerPointer - 1) | 1));
1452 #if V8_TARGET_ARCH_PPC64
1453 rldicl(scratch, value, 1, kBitsPerPointer - 2, SetRC);
1454 #else
1455 rlwinm(scratch, value, 1, kBitsPerPointer - 2, kBitsPerPointer - 1, SetRC);
1456 #endif
1261 } 1457 }
1262 // Jump if the register contains a smi. 1458
1459 // Jump the register contains a smi.
1263 inline void JumpIfSmi(Register value, Label* smi_label) { 1460 inline void JumpIfSmi(Register value, Label* smi_label) {
1264 tst(value, Operand(kSmiTagMask)); 1461 TestIfSmi(value, r0);
1265 b(eq, smi_label); 1462 beq(smi_label, cr0); // branch if SMI
1266 } 1463 }
1267 // Jump if either of the registers contain a non-smi. 1464 // Jump if either of the registers contain a non-smi.
1268 inline void JumpIfNotSmi(Register value, Label* not_smi_label) { 1465 inline void JumpIfNotSmi(Register value, Label* not_smi_label) {
1269 tst(value, Operand(kSmiTagMask)); 1466 TestIfSmi(value, r0);
1270 b(ne, not_smi_label); 1467 bne(not_smi_label, cr0);
1271 } 1468 }
1272 // Jump if either of the registers contain a non-smi. 1469 // Jump if either of the registers contain a non-smi.
1273 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi); 1470 void JumpIfNotBothSmi(Register reg1, Register reg2, Label* on_not_both_smi);
1274 // Jump if either of the registers contain a smi. 1471 // Jump if either of the registers contain a smi.
1275 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi); 1472 void JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi);
1276 1473
1277 // Abort execution if argument is a smi, enabled via --debug-code. 1474 // Abort execution if argument is a smi, enabled via --debug-code.
1278 void AssertNotSmi(Register object); 1475 void AssertNotSmi(Register object);
1279 void AssertSmi(Register object); 1476 void AssertSmi(Register object);
1280 1477
1478
1479 #if V8_TARGET_ARCH_PPC64
1480 inline void TestIfInt32(Register value,
1481 Register scratch1, Register scratch2,
1482 CRegister cr = cr7) {
1483 // High bits must be identical to fit into an 32-bit integer
1484 srawi(scratch1, value, 31);
1485 sradi(scratch2, value, 32);
1486 cmp(scratch1, scratch2, cr);
1487 }
1488 #else
1489 inline void TestIfInt32(Register hi_word, Register lo_word,
1490 Register scratch, CRegister cr = cr7) {
1491 // High bits must be identical to fit into an 32-bit integer
1492 srawi(scratch, lo_word, 31);
1493 cmp(scratch, hi_word, cr);
1494 }
1495 #endif
1496
1281 // Abort execution if argument is not a string, enabled via --debug-code. 1497 // Abort execution if argument is not a string, enabled via --debug-code.
1282 void AssertString(Register object); 1498 void AssertString(Register object);
1283 1499
1284 // Abort execution if argument is not a name, enabled via --debug-code. 1500 // Abort execution if argument is not a name, enabled via --debug-code.
1285 void AssertName(Register object); 1501 void AssertName(Register object);
1286 1502
1287 // Abort execution if argument is not undefined or an AllocationSite, enabled 1503 // Abort execution if argument is not undefined or an AllocationSite, enabled
1288 // via --debug-code. 1504 // via --debug-code.
1289 void AssertUndefinedOrAllocationSite(Register object, Register scratch); 1505 void AssertUndefinedOrAllocationSite(Register object, Register scratch);
1290 1506
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1349 void JumpIfNotUniqueName(Register reg, Label* not_unique_name); 1565 void JumpIfNotUniqueName(Register reg, Label* not_unique_name);
1350 1566
1351 void EmitSeqStringSetCharCheck(Register string, 1567 void EmitSeqStringSetCharCheck(Register string,
1352 Register index, 1568 Register index,
1353 Register value, 1569 Register value,
1354 uint32_t encoding_mask); 1570 uint32_t encoding_mask);
1355 1571
1356 // --------------------------------------------------------------------------- 1572 // ---------------------------------------------------------------------------
1357 // Patching helpers. 1573 // Patching helpers.
1358 1574
1359 // Get the location of a relocated constant (its address in the constant pool) 1575 // Retrieve/patch the relocated value (lis/ori pair or constant pool load).
1360 // from its load site. 1576 void GetRelocatedValue(Register location,
1361 void GetRelocatedValueLocation(Register ldr_location, Register result, 1577 Register result,
1362 Register scratch); 1578 Register scratch);
1363 1579 void SetRelocatedValue(Register location,
1580 Register scratch,
1581 Register new_value);
1364 1582
1365 void ClampUint8(Register output_reg, Register input_reg); 1583 void ClampUint8(Register output_reg, Register input_reg);
1366 1584
1585 // Saturate a value into 8-bit unsigned integer
1586 // if input_value < 0, output_value is 0
1587 // if input_value > 255, output_value is 255
1588 // otherwise output_value is the (int)input_value (round to nearest)
1367 void ClampDoubleToUint8(Register result_reg, 1589 void ClampDoubleToUint8(Register result_reg,
1368 DwVfpRegister input_reg, 1590 DoubleRegister input_reg,
1369 LowDwVfpRegister double_scratch); 1591 DoubleRegister temp_double_reg);
1370 1592
1371 1593
1372 void LoadInstanceDescriptors(Register map, Register descriptors); 1594 void LoadInstanceDescriptors(Register map, Register descriptors);
1373 void EnumLength(Register dst, Register map); 1595 void EnumLength(Register dst, Register map);
1374 void NumberOfOwnDescriptors(Register dst, Register map); 1596 void NumberOfOwnDescriptors(Register dst, Register map);
1375 1597
1376 template<typename Field> 1598 template<typename Field>
1377 void DecodeField(Register dst, Register src) { 1599 void DecodeField(Register dst, Register src) {
1378 Ubfx(dst, src, Field::kShift, Field::kSize); 1600 ExtractBitRange(dst, src, Field::kShift + Field::kSize - 1, Field::kShift);
1379 } 1601 }
1380 1602
1381 template<typename Field> 1603 template<typename Field>
1382 void DecodeField(Register reg) { 1604 void DecodeField(Register reg) {
1383 DecodeField<Field>(reg, reg); 1605 DecodeField<Field>(reg, reg);
1384 } 1606 }
1385 1607
1386 template<typename Field> 1608 template<typename Field>
1387 void DecodeFieldToSmi(Register dst, Register src) { 1609 void DecodeFieldToSmi(Register dst, Register src) {
1388 static const int shift = Field::kShift; 1610 #if V8_TARGET_ARCH_PPC64
1389 static const int mask = Field::kMask >> shift << kSmiTagSize; 1611 DecodeField<Field>(dst, src);
1390 STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0); 1612 SmiTag(dst);
1391 STATIC_ASSERT(kSmiTag == 0); 1613 #else
1392 if (shift < kSmiTagSize) { 1614 // 32-bit can do this in one instruction:
1393 mov(dst, Operand(src, LSL, kSmiTagSize - shift)); 1615 int start = Field::kSize + kSmiShift - 1;
1394 and_(dst, dst, Operand(mask)); 1616 int end = kSmiShift;
1395 } else if (shift > kSmiTagSize) { 1617 int rotate = kSmiShift - Field::kShift;
1396 mov(dst, Operand(src, LSR, shift - kSmiTagSize)); 1618 if (rotate < 0) {
1397 and_(dst, dst, Operand(mask)); 1619 rotate += kBitsPerPointer;
1398 } else {
1399 and_(dst, src, Operand(mask));
1400 } 1620 }
1621 rlwinm(dst, src, rotate,
1622 kBitsPerPointer - start - 1,
1623 kBitsPerPointer - end - 1);
1624 #endif
1401 } 1625 }
1402 1626
1403 template<typename Field> 1627 template<typename Field>
1404 void DecodeFieldToSmi(Register reg) { 1628 void DecodeFieldToSmi(Register reg) {
1405 DecodeField<Field>(reg, reg); 1629 DecodeFieldToSmi<Field>(reg, reg);
1406 } 1630 }
1407 1631
1408 // Activation support. 1632 // Activation support.
1409 void EnterFrame(StackFrame::Type type, bool load_constant_pool = false); 1633 void EnterFrame(StackFrame::Type type, bool load_constant_pool = false);
1410 // Returns the pc offset at which the frame ends. 1634 // Returns the pc offset at which the frame ends.
1411 int LeaveFrame(StackFrame::Type type); 1635 int LeaveFrame(StackFrame::Type type);
1412 1636
1413 // Expects object in r0 and returns map with validated enum cache 1637 // Expects object in r0 and returns map with validated enum cache
1414 // in r0. Assumes that any other register can be used as a scratch. 1638 // in r0. Assumes that any other register can be used as a scratch.
1415 void CheckEnumCache(Register null_value, Label* call_runtime); 1639 void CheckEnumCache(Register null_value, Label* call_runtime);
1416 1640
1417 // AllocationMemento support. Arrays may have an associated 1641 // AllocationMemento support. Arrays may have an associated
1418 // AllocationMemento object that can be checked for in order to pretransition 1642 // AllocationMemento object that can be checked for in order to pretransition
1419 // to another type. 1643 // to another type.
1420 // On entry, receiver_reg should point to the array object. 1644 // On entry, receiver_reg should point to the array object.
1421 // scratch_reg gets clobbered. 1645 // scratch_reg gets clobbered.
1422 // If allocation info is present, condition flags are set to eq. 1646 // If allocation info is present, condition flags are set to eq.
1423 void TestJSArrayForAllocationMemento(Register receiver_reg, 1647 void TestJSArrayForAllocationMemento(Register receiver_reg,
1424 Register scratch_reg, 1648 Register scratch_reg,
1425 Label* no_memento_found); 1649 Label* no_memento_found);
1426 1650
1427 void JumpIfJSArrayHasAllocationMemento(Register receiver_reg, 1651 void JumpIfJSArrayHasAllocationMemento(Register receiver_reg,
1428 Register scratch_reg, 1652 Register scratch_reg,
1429 Label* memento_found) { 1653 Label* memento_found) {
1430 Label no_memento_found; 1654 Label no_memento_found;
1431 TestJSArrayForAllocationMemento(receiver_reg, scratch_reg, 1655 TestJSArrayForAllocationMemento(receiver_reg, scratch_reg,
1432 &no_memento_found); 1656 &no_memento_found);
1433 b(eq, memento_found); 1657 beq(memento_found);
1434 bind(&no_memento_found); 1658 bind(&no_memento_found);
1435 } 1659 }
1436 1660
1437 // Jumps to found label if a prototype map has dictionary elements. 1661 // Jumps to found label if a prototype map has dictionary elements.
1438 void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0, 1662 void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
1439 Register scratch1, Label* found); 1663 Register scratch1, Label* found);
1440 1664
1441 private: 1665 private:
1666 static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
1667
1442 void CallCFunctionHelper(Register function, 1668 void CallCFunctionHelper(Register function,
1443 int num_reg_arguments, 1669 int num_reg_arguments,
1444 int num_double_arguments); 1670 int num_double_arguments);
1445 1671
1446 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); 1672 void Jump(intptr_t target, RelocInfo::Mode rmode,
1673 Condition cond = al, CRegister cr = cr7);
1447 1674
1448 // Helper functions for generating invokes. 1675 // Helper functions for generating invokes.
1449 void InvokePrologue(const ParameterCount& expected, 1676 void InvokePrologue(const ParameterCount& expected,
1450 const ParameterCount& actual, 1677 const ParameterCount& actual,
1451 Handle<Code> code_constant, 1678 Handle<Code> code_constant,
1452 Register code_reg, 1679 Register code_reg,
1453 Label* done, 1680 Label* done,
1454 bool* definitely_mismatches, 1681 bool* definitely_mismatches,
1455 InvokeFlag flag, 1682 InvokeFlag flag,
1456 const CallWrapper& call_wrapper); 1683 const CallWrapper& call_wrapper);
(...skipping 19 matching lines...) Expand all
1476 1703
1477 // Helper for throwing exceptions. Compute a handler address and jump to 1704 // Helper for throwing exceptions. Compute a handler address and jump to
1478 // it. See the implementation for register usage. 1705 // it. See the implementation for register usage.
1479 void JumpToHandlerEntry(); 1706 void JumpToHandlerEntry();
1480 1707
1481 // Compute memory operands for safepoint stack slots. 1708 // Compute memory operands for safepoint stack slots.
1482 static int SafepointRegisterStackIndex(int reg_code); 1709 static int SafepointRegisterStackIndex(int reg_code);
1483 MemOperand SafepointRegisterSlot(Register reg); 1710 MemOperand SafepointRegisterSlot(Register reg);
1484 MemOperand SafepointRegistersAndDoublesSlot(Register reg); 1711 MemOperand SafepointRegistersAndDoublesSlot(Register reg);
1485 1712
1486 // Loads the constant pool pointer (pp) register. 1713 #if V8_OOL_CONSTANT_POOL
1714 // Loads the constant pool pointer (kConstantPoolRegister).
1487 void LoadConstantPoolPointerRegister(); 1715 void LoadConstantPoolPointerRegister();
1716 #endif
1488 1717
1489 bool generating_stub_; 1718 bool generating_stub_;
1490 bool has_frame_; 1719 bool has_frame_;
1491 // This handle will be patched with the code object on installation. 1720 // This handle will be patched with the code object on installation.
1492 Handle<Object> code_object_; 1721 Handle<Object> code_object_;
1493 1722
1494 // Needs access to SafepointRegisterStackIndex for compiled frame 1723 // Needs access to SafepointRegisterStackIndex for compiled frame
1495 // traversal. 1724 // traversal.
1496 friend class StandardFrame; 1725 friend class StandardFrame;
1497 }; 1726 };
(...skipping 15 matching lines...) Expand all
1513 int instructions, 1742 int instructions,
1514 FlushICache flush_cache = FLUSH); 1743 FlushICache flush_cache = FLUSH);
1515 virtual ~CodePatcher(); 1744 virtual ~CodePatcher();
1516 1745
1517 // Macro assembler to emit code. 1746 // Macro assembler to emit code.
1518 MacroAssembler* masm() { return &masm_; } 1747 MacroAssembler* masm() { return &masm_; }
1519 1748
1520 // Emit an instruction directly. 1749 // Emit an instruction directly.
1521 void Emit(Instr instr); 1750 void Emit(Instr instr);
1522 1751
1523 // Emit an address directly.
1524 void Emit(Address addr);
1525
1526 // Emit the condition part of an instruction leaving the rest of the current 1752 // Emit the condition part of an instruction leaving the rest of the current
1527 // instruction unchanged. 1753 // instruction unchanged.
1528 void EmitCondition(Condition cond); 1754 void EmitCondition(Condition cond);
1529 1755
1530 private: 1756 private:
1531 byte* address_; // The address of the code being patched. 1757 byte* address_; // The address of the code being patched.
1532 int size_; // Number of bytes of the expected patch size. 1758 int size_; // Number of bytes of the expected patch size.
1533 MacroAssembler masm_; // Macro assembler used to generate the code. 1759 MacroAssembler masm_; // Macro assembler used to generate the code.
1534 FlushICache flush_cache_; // Whether to flush the I cache after patching. 1760 FlushICache flush_cache_; // Whether to flush the I cache after patching.
1535 }; 1761 };
1536 1762
1537 1763
1764 #if V8_OOL_CONSTANT_POOL
1538 class FrameAndConstantPoolScope { 1765 class FrameAndConstantPoolScope {
1539 public: 1766 public:
1540 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type) 1767 FrameAndConstantPoolScope(MacroAssembler* masm, StackFrame::Type type)
1541 : masm_(masm), 1768 : masm_(masm),
1542 type_(type), 1769 type_(type),
1543 old_has_frame_(masm->has_frame()), 1770 old_has_frame_(masm->has_frame()),
1544 old_constant_pool_available_(masm->is_constant_pool_available()) { 1771 old_constant_pool_available_(masm->is_constant_pool_available()) {
1545 // We only want to enable constant pool access for non-manual frame scopes 1772 // We only want to enable constant pool access for non-manual frame scopes
1546 // to ensure the constant pool pointer is valid throughout the scope. 1773 // to ensure the constant pool pointer is valid throughout the scope.
1547 ASSERT(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE); 1774 ASSERT(type_ != StackFrame::MANUAL && type_ != StackFrame::NONE);
(...skipping 19 matching lines...) Expand all
1567 } 1794 }
1568 1795
1569 private: 1796 private:
1570 MacroAssembler* masm_; 1797 MacroAssembler* masm_;
1571 StackFrame::Type type_; 1798 StackFrame::Type type_;
1572 bool old_has_frame_; 1799 bool old_has_frame_;
1573 bool old_constant_pool_available_; 1800 bool old_constant_pool_available_;
1574 1801
1575 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope); 1802 DISALLOW_IMPLICIT_CONSTRUCTORS(FrameAndConstantPoolScope);
1576 }; 1803 };
1804 #else
1805 #define FrameAndConstantPoolScope FrameScope
1806 #endif
1577 1807
1578 1808
1809 #if V8_OOL_CONSTANT_POOL
1579 // Class for scoping the the unavailability of constant pool access. 1810 // Class for scoping the the unavailability of constant pool access.
1580 class ConstantPoolUnavailableScope { 1811 class ConstantPoolUnavailableScope {
1581 public: 1812 public:
1582 explicit ConstantPoolUnavailableScope(MacroAssembler* masm) 1813 explicit ConstantPoolUnavailableScope(MacroAssembler* masm)
1583 : masm_(masm), 1814 : masm_(masm),
1584 old_constant_pool_available_(masm->is_constant_pool_available()) { 1815 old_constant_pool_available_(masm->is_constant_pool_available()) {
1585 if (FLAG_enable_ool_constant_pool) { 1816 if (FLAG_enable_ool_constant_pool) {
1586 masm_->set_constant_pool_available(false); 1817 masm_->set_constant_pool_available(false);
1587 } 1818 }
1588 } 1819 }
1589 ~ConstantPoolUnavailableScope() { 1820 ~ConstantPoolUnavailableScope() {
1590 if (FLAG_enable_ool_constant_pool) { 1821 if (FLAG_enable_ool_constant_pool) {
1591 masm_->set_constant_pool_available(old_constant_pool_available_); 1822 masm_->set_constant_pool_available(old_constant_pool_available_);
1592 } 1823 }
1593 } 1824 }
1594 1825
1595 private: 1826 private:
1596 MacroAssembler* masm_; 1827 MacroAssembler* masm_;
1597 int old_constant_pool_available_; 1828 int old_constant_pool_available_;
1598 1829
1599 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope); 1830 DISALLOW_IMPLICIT_CONSTRUCTORS(ConstantPoolUnavailableScope);
1600 }; 1831 };
1832 #endif
1601 1833
1602 1834
1603 // ----------------------------------------------------------------------------- 1835 // -----------------------------------------------------------------------------
1604 // Static helper functions. 1836 // Static helper functions.
1605 1837
1606 inline MemOperand ContextOperand(Register context, int index) { 1838 inline MemOperand ContextOperand(Register context, int index) {
1607 return MemOperand(context, Context::SlotOffset(index)); 1839 return MemOperand(context, Context::SlotOffset(index));
1608 } 1840 }
1609 1841
1610 1842
1611 inline MemOperand GlobalObjectOperand() { 1843 inline MemOperand GlobalObjectOperand() {
1612 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX); 1844 return ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX);
1613 } 1845 }
1614 1846
1615 1847
1616 #ifdef GENERATED_CODE_COVERAGE 1848 #ifdef GENERATED_CODE_COVERAGE
1617 #define CODE_COVERAGE_STRINGIFY(x) #x 1849 #define CODE_COVERAGE_STRINGIFY(x) #x
1618 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) 1850 #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x)
1619 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__) 1851 #define __FILE_LINE__ __FILE__ ":" CODE_COVERAGE_TOSTRING(__LINE__)
1620 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm-> 1852 #define ACCESS_MASM(masm) masm->stop(__FILE_LINE__); masm->
1621 #else 1853 #else
1622 #define ACCESS_MASM(masm) masm-> 1854 #define ACCESS_MASM(masm) masm->
1623 #endif 1855 #endif
1624 1856
1625 1857
1626 } } // namespace v8::internal 1858 } } // namespace v8::internal
1627 1859
1628 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_ 1860 #endif // V8_PPC_MACRO_ASSEMBLER_PPC_H_
OLDNEW
« src/objects-inl.h ('K') | « src/ppc/lithium-ppc.cc ('k') | src/ppc/macro-assembler-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698