OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #if V8_TARGET_ARCH_MIPS64 | 9 #if V8_TARGET_ARCH_MIPS64 |
10 | 10 |
(...skipping 14 matching lines...) Expand all Loading... |
25 if (isolate() != NULL) { | 25 if (isolate() != NULL) { |
26 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), | 26 code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), |
27 isolate()); | 27 isolate()); |
28 } | 28 } |
29 } | 29 } |
30 | 30 |
31 | 31 |
32 void MacroAssembler::Load(Register dst, | 32 void MacroAssembler::Load(Register dst, |
33 const MemOperand& src, | 33 const MemOperand& src, |
34 Representation r) { | 34 Representation r) { |
35 ASSERT(!r.IsDouble()); | 35 DCHECK(!r.IsDouble()); |
36 if (r.IsInteger8()) { | 36 if (r.IsInteger8()) { |
37 lb(dst, src); | 37 lb(dst, src); |
38 } else if (r.IsUInteger8()) { | 38 } else if (r.IsUInteger8()) { |
39 lbu(dst, src); | 39 lbu(dst, src); |
40 } else if (r.IsInteger16()) { | 40 } else if (r.IsInteger16()) { |
41 lh(dst, src); | 41 lh(dst, src); |
42 } else if (r.IsUInteger16()) { | 42 } else if (r.IsUInteger16()) { |
43 lhu(dst, src); | 43 lhu(dst, src); |
44 } else if (r.IsInteger32()) { | 44 } else if (r.IsInteger32()) { |
45 lw(dst, src); | 45 lw(dst, src); |
46 } else { | 46 } else { |
47 ld(dst, src); | 47 ld(dst, src); |
48 } | 48 } |
49 } | 49 } |
50 | 50 |
51 | 51 |
52 void MacroAssembler::Store(Register src, | 52 void MacroAssembler::Store(Register src, |
53 const MemOperand& dst, | 53 const MemOperand& dst, |
54 Representation r) { | 54 Representation r) { |
55 ASSERT(!r.IsDouble()); | 55 DCHECK(!r.IsDouble()); |
56 if (r.IsInteger8() || r.IsUInteger8()) { | 56 if (r.IsInteger8() || r.IsUInteger8()) { |
57 sb(src, dst); | 57 sb(src, dst); |
58 } else if (r.IsInteger16() || r.IsUInteger16()) { | 58 } else if (r.IsInteger16() || r.IsUInteger16()) { |
59 sh(src, dst); | 59 sh(src, dst); |
60 } else if (r.IsInteger32()) { | 60 } else if (r.IsInteger32()) { |
61 sw(src, dst); | 61 sw(src, dst); |
62 } else { | 62 } else { |
63 if (r.IsHeapObject()) { | 63 if (r.IsHeapObject()) { |
64 AssertNotSmi(src); | 64 AssertNotSmi(src); |
65 } else if (r.IsSmi()) { | 65 } else if (r.IsSmi()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 Branch(2, NegateCondition(cond), src1, src2); | 98 Branch(2, NegateCondition(cond), src1, src2); |
99 sd(source, MemOperand(s6, index << kPointerSizeLog2)); | 99 sd(source, MemOperand(s6, index << kPointerSizeLog2)); |
100 } | 100 } |
101 | 101 |
102 | 102 |
103 // Push and pop all registers that can hold pointers. | 103 // Push and pop all registers that can hold pointers. |
104 void MacroAssembler::PushSafepointRegisters() { | 104 void MacroAssembler::PushSafepointRegisters() { |
105 // Safepoints expect a block of kNumSafepointRegisters values on the | 105 // Safepoints expect a block of kNumSafepointRegisters values on the |
106 // stack, so adjust the stack for unsaved registers. | 106 // stack, so adjust the stack for unsaved registers. |
107 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 107 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
108 ASSERT(num_unsaved >= 0); | 108 DCHECK(num_unsaved >= 0); |
109 if (num_unsaved > 0) { | 109 if (num_unsaved > 0) { |
110 Dsubu(sp, sp, Operand(num_unsaved * kPointerSize)); | 110 Dsubu(sp, sp, Operand(num_unsaved * kPointerSize)); |
111 } | 111 } |
112 MultiPush(kSafepointSavedRegisters); | 112 MultiPush(kSafepointSavedRegisters); |
113 } | 113 } |
114 | 114 |
115 | 115 |
116 void MacroAssembler::PopSafepointRegisters() { | 116 void MacroAssembler::PopSafepointRegisters() { |
117 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 117 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
118 MultiPop(kSafepointSavedRegisters); | 118 MultiPop(kSafepointSavedRegisters); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize; | 150 int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize; |
151 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize; | 151 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize; |
152 return MemOperand(sp, doubles_size + register_offset); | 152 return MemOperand(sp, doubles_size + register_offset); |
153 } | 153 } |
154 | 154 |
155 | 155 |
156 void MacroAssembler::InNewSpace(Register object, | 156 void MacroAssembler::InNewSpace(Register object, |
157 Register scratch, | 157 Register scratch, |
158 Condition cc, | 158 Condition cc, |
159 Label* branch) { | 159 Label* branch) { |
160 ASSERT(cc == eq || cc == ne); | 160 DCHECK(cc == eq || cc == ne); |
161 And(scratch, object, Operand(ExternalReference::new_space_mask(isolate()))); | 161 And(scratch, object, Operand(ExternalReference::new_space_mask(isolate()))); |
162 Branch(branch, cc, scratch, | 162 Branch(branch, cc, scratch, |
163 Operand(ExternalReference::new_space_start(isolate()))); | 163 Operand(ExternalReference::new_space_start(isolate()))); |
164 } | 164 } |
165 | 165 |
166 | 166 |
167 void MacroAssembler::RecordWriteField( | 167 void MacroAssembler::RecordWriteField( |
168 Register object, | 168 Register object, |
169 int offset, | 169 int offset, |
170 Register value, | 170 Register value, |
171 Register dst, | 171 Register dst, |
172 RAStatus ra_status, | 172 RAStatus ra_status, |
173 SaveFPRegsMode save_fp, | 173 SaveFPRegsMode save_fp, |
174 RememberedSetAction remembered_set_action, | 174 RememberedSetAction remembered_set_action, |
175 SmiCheck smi_check, | 175 SmiCheck smi_check, |
176 PointersToHereCheck pointers_to_here_check_for_value) { | 176 PointersToHereCheck pointers_to_here_check_for_value) { |
177 ASSERT(!AreAliased(value, dst, t8, object)); | 177 DCHECK(!AreAliased(value, dst, t8, object)); |
178 // First, check if a write barrier is even needed. The tests below | 178 // First, check if a write barrier is even needed. The tests below |
179 // catch stores of Smis. | 179 // catch stores of Smis. |
180 Label done; | 180 Label done; |
181 | 181 |
182 // Skip barrier if writing a smi. | 182 // Skip barrier if writing a smi. |
183 if (smi_check == INLINE_SMI_CHECK) { | 183 if (smi_check == INLINE_SMI_CHECK) { |
184 JumpIfSmi(value, &done); | 184 JumpIfSmi(value, &done); |
185 } | 185 } |
186 | 186 |
187 // Although the object register is tagged, the offset is relative to the start | 187 // Although the object register is tagged, the offset is relative to the start |
188 // of the object, so so offset must be a multiple of kPointerSize. | 188 // of the object, so so offset must be a multiple of kPointerSize. |
189 ASSERT(IsAligned(offset, kPointerSize)); | 189 DCHECK(IsAligned(offset, kPointerSize)); |
190 | 190 |
191 Daddu(dst, object, Operand(offset - kHeapObjectTag)); | 191 Daddu(dst, object, Operand(offset - kHeapObjectTag)); |
192 if (emit_debug_code()) { | 192 if (emit_debug_code()) { |
193 Label ok; | 193 Label ok; |
194 And(t8, dst, Operand((1 << kPointerSizeLog2) - 1)); | 194 And(t8, dst, Operand((1 << kPointerSizeLog2) - 1)); |
195 Branch(&ok, eq, t8, Operand(zero_reg)); | 195 Branch(&ok, eq, t8, Operand(zero_reg)); |
196 stop("Unaligned cell in write barrier"); | 196 stop("Unaligned cell in write barrier"); |
197 bind(&ok); | 197 bind(&ok); |
198 } | 198 } |
199 | 199 |
(...skipping 18 matching lines...) Expand all Loading... |
218 | 218 |
219 | 219 |
220 // Will clobber 4 registers: object, map, dst, ip. The | 220 // Will clobber 4 registers: object, map, dst, ip. The |
221 // register 'object' contains a heap object pointer. | 221 // register 'object' contains a heap object pointer. |
222 void MacroAssembler::RecordWriteForMap(Register object, | 222 void MacroAssembler::RecordWriteForMap(Register object, |
223 Register map, | 223 Register map, |
224 Register dst, | 224 Register dst, |
225 RAStatus ra_status, | 225 RAStatus ra_status, |
226 SaveFPRegsMode fp_mode) { | 226 SaveFPRegsMode fp_mode) { |
227 if (emit_debug_code()) { | 227 if (emit_debug_code()) { |
228 ASSERT(!dst.is(at)); | 228 DCHECK(!dst.is(at)); |
229 ld(dst, FieldMemOperand(map, HeapObject::kMapOffset)); | 229 ld(dst, FieldMemOperand(map, HeapObject::kMapOffset)); |
230 Check(eq, | 230 Check(eq, |
231 kWrongAddressOrValuePassedToRecordWrite, | 231 kWrongAddressOrValuePassedToRecordWrite, |
232 dst, | 232 dst, |
233 Operand(isolate()->factory()->meta_map())); | 233 Operand(isolate()->factory()->meta_map())); |
234 } | 234 } |
235 | 235 |
236 if (!FLAG_incremental_marking) { | 236 if (!FLAG_incremental_marking) { |
237 return; | 237 return; |
238 } | 238 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 // tag is shifted away. | 297 // tag is shifted away. |
298 void MacroAssembler::RecordWrite( | 298 void MacroAssembler::RecordWrite( |
299 Register object, | 299 Register object, |
300 Register address, | 300 Register address, |
301 Register value, | 301 Register value, |
302 RAStatus ra_status, | 302 RAStatus ra_status, |
303 SaveFPRegsMode fp_mode, | 303 SaveFPRegsMode fp_mode, |
304 RememberedSetAction remembered_set_action, | 304 RememberedSetAction remembered_set_action, |
305 SmiCheck smi_check, | 305 SmiCheck smi_check, |
306 PointersToHereCheck pointers_to_here_check_for_value) { | 306 PointersToHereCheck pointers_to_here_check_for_value) { |
307 ASSERT(!AreAliased(object, address, value, t8)); | 307 DCHECK(!AreAliased(object, address, value, t8)); |
308 ASSERT(!AreAliased(object, address, value, t9)); | 308 DCHECK(!AreAliased(object, address, value, t9)); |
309 | 309 |
310 if (emit_debug_code()) { | 310 if (emit_debug_code()) { |
311 ld(at, MemOperand(address)); | 311 ld(at, MemOperand(address)); |
312 Assert( | 312 Assert( |
313 eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value)); | 313 eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value)); |
314 } | 314 } |
315 | 315 |
316 if (remembered_set_action == OMIT_REMEMBERED_SET && | 316 if (remembered_set_action == OMIT_REMEMBERED_SET && |
317 !FLAG_incremental_marking) { | 317 !FLAG_incremental_marking) { |
318 return; | 318 return; |
319 } | 319 } |
320 | 320 |
321 // First, check if a write barrier is even needed. The tests below | 321 // First, check if a write barrier is even needed. The tests below |
322 // catch stores of smis and stores into the young generation. | 322 // catch stores of smis and stores into the young generation. |
323 Label done; | 323 Label done; |
324 | 324 |
325 if (smi_check == INLINE_SMI_CHECK) { | 325 if (smi_check == INLINE_SMI_CHECK) { |
326 ASSERT_EQ(0, kSmiTag); | 326 DCHECK_EQ(0, kSmiTag); |
327 JumpIfSmi(value, &done); | 327 JumpIfSmi(value, &done); |
328 } | 328 } |
329 | 329 |
330 if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) { | 330 if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) { |
331 CheckPageFlag(value, | 331 CheckPageFlag(value, |
332 value, // Used as scratch. | 332 value, // Used as scratch. |
333 MemoryChunk::kPointersToHereAreInterestingMask, | 333 MemoryChunk::kPointersToHereAreInterestingMask, |
334 eq, | 334 eq, |
335 &done); | 335 &done); |
336 } | 336 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 li(t8, Operand(store_buffer)); | 385 li(t8, Operand(store_buffer)); |
386 ld(scratch, MemOperand(t8)); | 386 ld(scratch, MemOperand(t8)); |
387 // Store pointer to buffer and increment buffer top. | 387 // Store pointer to buffer and increment buffer top. |
388 sd(address, MemOperand(scratch)); | 388 sd(address, MemOperand(scratch)); |
389 Daddu(scratch, scratch, kPointerSize); | 389 Daddu(scratch, scratch, kPointerSize); |
390 // Write back new top of buffer. | 390 // Write back new top of buffer. |
391 sd(scratch, MemOperand(t8)); | 391 sd(scratch, MemOperand(t8)); |
392 // Call stub on end of buffer. | 392 // Call stub on end of buffer. |
393 // Check for end of buffer. | 393 // Check for end of buffer. |
394 And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); | 394 And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); |
395 ASSERT(!scratch.is(t8)); | 395 DCHECK(!scratch.is(t8)); |
396 if (and_then == kFallThroughAtEnd) { | 396 if (and_then == kFallThroughAtEnd) { |
397 Branch(&done, eq, t8, Operand(zero_reg)); | 397 Branch(&done, eq, t8, Operand(zero_reg)); |
398 } else { | 398 } else { |
399 ASSERT(and_then == kReturnAtEnd); | 399 DCHECK(and_then == kReturnAtEnd); |
400 Ret(eq, t8, Operand(zero_reg)); | 400 Ret(eq, t8, Operand(zero_reg)); |
401 } | 401 } |
402 push(ra); | 402 push(ra); |
403 StoreBufferOverflowStub store_buffer_overflow = | 403 StoreBufferOverflowStub store_buffer_overflow = |
404 StoreBufferOverflowStub(isolate(), fp_mode); | 404 StoreBufferOverflowStub(isolate(), fp_mode); |
405 CallStub(&store_buffer_overflow); | 405 CallStub(&store_buffer_overflow); |
406 pop(ra); | 406 pop(ra); |
407 bind(&done); | 407 bind(&done); |
408 if (and_then == kReturnAtEnd) { | 408 if (and_then == kReturnAtEnd) { |
409 Ret(); | 409 Ret(); |
410 } | 410 } |
411 } | 411 } |
412 | 412 |
413 | 413 |
414 // ----------------------------------------------------------------------------- | 414 // ----------------------------------------------------------------------------- |
415 // Allocation support. | 415 // Allocation support. |
416 | 416 |
417 | 417 |
418 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 418 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
419 Register scratch, | 419 Register scratch, |
420 Label* miss) { | 420 Label* miss) { |
421 Label same_contexts; | 421 Label same_contexts; |
422 | 422 |
423 ASSERT(!holder_reg.is(scratch)); | 423 DCHECK(!holder_reg.is(scratch)); |
424 ASSERT(!holder_reg.is(at)); | 424 DCHECK(!holder_reg.is(at)); |
425 ASSERT(!scratch.is(at)); | 425 DCHECK(!scratch.is(at)); |
426 | 426 |
427 // Load current lexical context from the stack frame. | 427 // Load current lexical context from the stack frame. |
428 ld(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 428 ld(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
429 // In debug mode, make sure the lexical context is set. | 429 // In debug mode, make sure the lexical context is set. |
430 #ifdef DEBUG | 430 #ifdef DEBUG |
431 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, | 431 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, |
432 scratch, Operand(zero_reg)); | 432 scratch, Operand(zero_reg)); |
433 #endif | 433 #endif |
434 | 434 |
435 // Load the native context of the current context. | 435 // Load the native context of the current context. |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
571 for (int i = 0; i < kNumberDictionaryProbes; i++) { | 571 for (int i = 0; i < kNumberDictionaryProbes; i++) { |
572 // Use reg2 for index calculations and keep the hash intact in reg0. | 572 // Use reg2 for index calculations and keep the hash intact in reg0. |
573 mov(reg2, reg0); | 573 mov(reg2, reg0); |
574 // Compute the masked index: (hash + i + i * i) & mask. | 574 // Compute the masked index: (hash + i + i * i) & mask. |
575 if (i > 0) { | 575 if (i > 0) { |
576 Daddu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); | 576 Daddu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); |
577 } | 577 } |
578 and_(reg2, reg2, reg1); | 578 and_(reg2, reg2, reg1); |
579 | 579 |
580 // Scale the index by multiplying by the element size. | 580 // Scale the index by multiplying by the element size. |
581 ASSERT(SeededNumberDictionary::kEntrySize == 3); | 581 DCHECK(SeededNumberDictionary::kEntrySize == 3); |
582 dsll(at, reg2, 1); // 2x. | 582 dsll(at, reg2, 1); // 2x. |
583 daddu(reg2, reg2, at); // reg2 = reg2 * 3. | 583 daddu(reg2, reg2, at); // reg2 = reg2 * 3. |
584 | 584 |
585 // Check if the key is identical to the name. | 585 // Check if the key is identical to the name. |
586 dsll(at, reg2, kPointerSizeLog2); | 586 dsll(at, reg2, kPointerSizeLog2); |
587 daddu(reg2, elements, at); | 587 daddu(reg2, elements, at); |
588 | 588 |
589 ld(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); | 589 ld(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); |
590 if (i != kNumberDictionaryProbes - 1) { | 590 if (i != kNumberDictionaryProbes - 1) { |
591 Branch(&done, eq, key, Operand(at)); | 591 Branch(&done, eq, key, Operand(at)); |
(...skipping 22 matching lines...) Expand all Loading... |
614 // Instruction macros. | 614 // Instruction macros. |
615 | 615 |
616 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { | 616 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { |
617 if (rt.is_reg()) { | 617 if (rt.is_reg()) { |
618 addu(rd, rs, rt.rm()); | 618 addu(rd, rs, rt.rm()); |
619 } else { | 619 } else { |
620 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { | 620 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
621 addiu(rd, rs, rt.imm64_); | 621 addiu(rd, rs, rt.imm64_); |
622 } else { | 622 } else { |
623 // li handles the relocation. | 623 // li handles the relocation. |
624 ASSERT(!rs.is(at)); | 624 DCHECK(!rs.is(at)); |
625 li(at, rt); | 625 li(at, rt); |
626 addu(rd, rs, at); | 626 addu(rd, rs, at); |
627 } | 627 } |
628 } | 628 } |
629 } | 629 } |
630 | 630 |
631 | 631 |
632 void MacroAssembler::Daddu(Register rd, Register rs, const Operand& rt) { | 632 void MacroAssembler::Daddu(Register rd, Register rs, const Operand& rt) { |
633 if (rt.is_reg()) { | 633 if (rt.is_reg()) { |
634 daddu(rd, rs, rt.rm()); | 634 daddu(rd, rs, rt.rm()); |
635 } else { | 635 } else { |
636 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { | 636 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
637 daddiu(rd, rs, rt.imm64_); | 637 daddiu(rd, rs, rt.imm64_); |
638 } else { | 638 } else { |
639 // li handles the relocation. | 639 // li handles the relocation. |
640 ASSERT(!rs.is(at)); | 640 DCHECK(!rs.is(at)); |
641 li(at, rt); | 641 li(at, rt); |
642 daddu(rd, rs, at); | 642 daddu(rd, rs, at); |
643 } | 643 } |
644 } | 644 } |
645 } | 645 } |
646 | 646 |
647 | 647 |
648 void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) { | 648 void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) { |
649 if (rt.is_reg()) { | 649 if (rt.is_reg()) { |
650 subu(rd, rs, rt.rm()); | 650 subu(rd, rs, rt.rm()); |
651 } else { | 651 } else { |
652 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { | 652 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
653 addiu(rd, rs, -rt.imm64_); // No subiu instr, use addiu(x, y, -imm). | 653 addiu(rd, rs, -rt.imm64_); // No subiu instr, use addiu(x, y, -imm). |
654 } else { | 654 } else { |
655 // li handles the relocation. | 655 // li handles the relocation. |
656 ASSERT(!rs.is(at)); | 656 DCHECK(!rs.is(at)); |
657 li(at, rt); | 657 li(at, rt); |
658 subu(rd, rs, at); | 658 subu(rd, rs, at); |
659 } | 659 } |
660 } | 660 } |
661 } | 661 } |
662 | 662 |
663 | 663 |
664 void MacroAssembler::Dsubu(Register rd, Register rs, const Operand& rt) { | 664 void MacroAssembler::Dsubu(Register rd, Register rs, const Operand& rt) { |
665 if (rt.is_reg()) { | 665 if (rt.is_reg()) { |
666 dsubu(rd, rs, rt.rm()); | 666 dsubu(rd, rs, rt.rm()); |
667 } else { | 667 } else { |
668 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { | 668 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
669 daddiu(rd, rs, -rt.imm64_); // No subiu instr, use addiu(x, y, -imm). | 669 daddiu(rd, rs, -rt.imm64_); // No subiu instr, use addiu(x, y, -imm). |
670 } else { | 670 } else { |
671 // li handles the relocation. | 671 // li handles the relocation. |
672 ASSERT(!rs.is(at)); | 672 DCHECK(!rs.is(at)); |
673 li(at, rt); | 673 li(at, rt); |
674 dsubu(rd, rs, at); | 674 dsubu(rd, rs, at); |
675 } | 675 } |
676 } | 676 } |
677 } | 677 } |
678 | 678 |
679 | 679 |
680 void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) { | 680 void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) { |
681 if (rt.is_reg()) { | 681 if (rt.is_reg()) { |
682 mul(rd, rs, rt.rm()); | 682 mul(rd, rs, rt.rm()); |
683 } else { | 683 } else { |
684 // li handles the relocation. | 684 // li handles the relocation. |
685 ASSERT(!rs.is(at)); | 685 DCHECK(!rs.is(at)); |
686 li(at, rt); | 686 li(at, rt); |
687 mul(rd, rs, at); | 687 mul(rd, rs, at); |
688 } | 688 } |
689 } | 689 } |
690 | 690 |
691 | 691 |
692 void MacroAssembler::Mulh(Register rd, Register rs, const Operand& rt) { | 692 void MacroAssembler::Mulh(Register rd, Register rs, const Operand& rt) { |
693 if (rt.is_reg()) { | 693 if (rt.is_reg()) { |
694 if (kArchVariant != kMips64r6) { | 694 if (kArchVariant != kMips64r6) { |
695 mult(rs, rt.rm()); | 695 mult(rs, rt.rm()); |
696 mfhi(rd); | 696 mfhi(rd); |
697 } else { | 697 } else { |
698 muh(rd, rs, rt.rm()); | 698 muh(rd, rs, rt.rm()); |
699 } | 699 } |
700 } else { | 700 } else { |
701 // li handles the relocation. | 701 // li handles the relocation. |
702 ASSERT(!rs.is(at)); | 702 DCHECK(!rs.is(at)); |
703 li(at, rt); | 703 li(at, rt); |
704 if (kArchVariant != kMips64r6) { | 704 if (kArchVariant != kMips64r6) { |
705 mult(rs, at); | 705 mult(rs, at); |
706 mfhi(rd); | 706 mfhi(rd); |
707 } else { | 707 } else { |
708 muh(rd, rs, at); | 708 muh(rd, rs, at); |
709 } | 709 } |
710 } | 710 } |
711 } | 711 } |
712 | 712 |
713 | 713 |
714 void MacroAssembler::Dmul(Register rd, Register rs, const Operand& rt) { | 714 void MacroAssembler::Dmul(Register rd, Register rs, const Operand& rt) { |
715 if (rt.is_reg()) { | 715 if (rt.is_reg()) { |
716 if (kArchVariant == kMips64r6) { | 716 if (kArchVariant == kMips64r6) { |
717 dmul(rd, rs, rt.rm()); | 717 dmul(rd, rs, rt.rm()); |
718 } else { | 718 } else { |
719 dmult(rs, rt.rm()); | 719 dmult(rs, rt.rm()); |
720 mflo(rd); | 720 mflo(rd); |
721 } | 721 } |
722 } else { | 722 } else { |
723 // li handles the relocation. | 723 // li handles the relocation. |
724 ASSERT(!rs.is(at)); | 724 DCHECK(!rs.is(at)); |
725 li(at, rt); | 725 li(at, rt); |
726 if (kArchVariant == kMips64r6) { | 726 if (kArchVariant == kMips64r6) { |
727 dmul(rd, rs, at); | 727 dmul(rd, rs, at); |
728 } else { | 728 } else { |
729 dmult(rs, at); | 729 dmult(rs, at); |
730 mflo(rd); | 730 mflo(rd); |
731 } | 731 } |
732 } | 732 } |
733 } | 733 } |
734 | 734 |
735 | 735 |
736 void MacroAssembler::Dmulh(Register rd, Register rs, const Operand& rt) { | 736 void MacroAssembler::Dmulh(Register rd, Register rs, const Operand& rt) { |
737 if (rt.is_reg()) { | 737 if (rt.is_reg()) { |
738 if (kArchVariant == kMips64r6) { | 738 if (kArchVariant == kMips64r6) { |
739 dmuh(rd, rs, rt.rm()); | 739 dmuh(rd, rs, rt.rm()); |
740 } else { | 740 } else { |
741 dmult(rs, rt.rm()); | 741 dmult(rs, rt.rm()); |
742 mfhi(rd); | 742 mfhi(rd); |
743 } | 743 } |
744 } else { | 744 } else { |
745 // li handles the relocation. | 745 // li handles the relocation. |
746 ASSERT(!rs.is(at)); | 746 DCHECK(!rs.is(at)); |
747 li(at, rt); | 747 li(at, rt); |
748 if (kArchVariant == kMips64r6) { | 748 if (kArchVariant == kMips64r6) { |
749 dmuh(rd, rs, at); | 749 dmuh(rd, rs, at); |
750 } else { | 750 } else { |
751 dmult(rs, at); | 751 dmult(rs, at); |
752 mfhi(rd); | 752 mfhi(rd); |
753 } | 753 } |
754 } | 754 } |
755 } | 755 } |
756 | 756 |
757 | 757 |
758 void MacroAssembler::Mult(Register rs, const Operand& rt) { | 758 void MacroAssembler::Mult(Register rs, const Operand& rt) { |
759 if (rt.is_reg()) { | 759 if (rt.is_reg()) { |
760 mult(rs, rt.rm()); | 760 mult(rs, rt.rm()); |
761 } else { | 761 } else { |
762 // li handles the relocation. | 762 // li handles the relocation. |
763 ASSERT(!rs.is(at)); | 763 DCHECK(!rs.is(at)); |
764 li(at, rt); | 764 li(at, rt); |
765 mult(rs, at); | 765 mult(rs, at); |
766 } | 766 } |
767 } | 767 } |
768 | 768 |
769 | 769 |
770 void MacroAssembler::Dmult(Register rs, const Operand& rt) { | 770 void MacroAssembler::Dmult(Register rs, const Operand& rt) { |
771 if (rt.is_reg()) { | 771 if (rt.is_reg()) { |
772 dmult(rs, rt.rm()); | 772 dmult(rs, rt.rm()); |
773 } else { | 773 } else { |
774 // li handles the relocation. | 774 // li handles the relocation. |
775 ASSERT(!rs.is(at)); | 775 DCHECK(!rs.is(at)); |
776 li(at, rt); | 776 li(at, rt); |
777 dmult(rs, at); | 777 dmult(rs, at); |
778 } | 778 } |
779 } | 779 } |
780 | 780 |
781 | 781 |
782 void MacroAssembler::Multu(Register rs, const Operand& rt) { | 782 void MacroAssembler::Multu(Register rs, const Operand& rt) { |
783 if (rt.is_reg()) { | 783 if (rt.is_reg()) { |
784 multu(rs, rt.rm()); | 784 multu(rs, rt.rm()); |
785 } else { | 785 } else { |
786 // li handles the relocation. | 786 // li handles the relocation. |
787 ASSERT(!rs.is(at)); | 787 DCHECK(!rs.is(at)); |
788 li(at, rt); | 788 li(at, rt); |
789 multu(rs, at); | 789 multu(rs, at); |
790 } | 790 } |
791 } | 791 } |
792 | 792 |
793 | 793 |
794 void MacroAssembler::Dmultu(Register rs, const Operand& rt) { | 794 void MacroAssembler::Dmultu(Register rs, const Operand& rt) { |
795 if (rt.is_reg()) { | 795 if (rt.is_reg()) { |
796 dmultu(rs, rt.rm()); | 796 dmultu(rs, rt.rm()); |
797 } else { | 797 } else { |
798 // li handles the relocation. | 798 // li handles the relocation. |
799 ASSERT(!rs.is(at)); | 799 DCHECK(!rs.is(at)); |
800 li(at, rt); | 800 li(at, rt); |
801 dmultu(rs, at); | 801 dmultu(rs, at); |
802 } | 802 } |
803 } | 803 } |
804 | 804 |
805 | 805 |
806 void MacroAssembler::Div(Register rs, const Operand& rt) { | 806 void MacroAssembler::Div(Register rs, const Operand& rt) { |
807 if (rt.is_reg()) { | 807 if (rt.is_reg()) { |
808 div(rs, rt.rm()); | 808 div(rs, rt.rm()); |
809 } else { | 809 } else { |
810 // li handles the relocation. | 810 // li handles the relocation. |
811 ASSERT(!rs.is(at)); | 811 DCHECK(!rs.is(at)); |
812 li(at, rt); | 812 li(at, rt); |
813 div(rs, at); | 813 div(rs, at); |
814 } | 814 } |
815 } | 815 } |
816 | 816 |
817 | 817 |
818 void MacroAssembler::Ddiv(Register rs, const Operand& rt) { | 818 void MacroAssembler::Ddiv(Register rs, const Operand& rt) { |
819 if (rt.is_reg()) { | 819 if (rt.is_reg()) { |
820 ddiv(rs, rt.rm()); | 820 ddiv(rs, rt.rm()); |
821 } else { | 821 } else { |
822 // li handles the relocation. | 822 // li handles the relocation. |
823 ASSERT(!rs.is(at)); | 823 DCHECK(!rs.is(at)); |
824 li(at, rt); | 824 li(at, rt); |
825 ddiv(rs, at); | 825 ddiv(rs, at); |
826 } | 826 } |
827 } | 827 } |
828 | 828 |
829 | 829 |
830 void MacroAssembler::Ddiv(Register rd, Register rs, const Operand& rt) { | 830 void MacroAssembler::Ddiv(Register rd, Register rs, const Operand& rt) { |
831 if (kArchVariant != kMips64r6) { | 831 if (kArchVariant != kMips64r6) { |
832 if (rt.is_reg()) { | 832 if (rt.is_reg()) { |
833 ddiv(rs, rt.rm()); | 833 ddiv(rs, rt.rm()); |
834 mflo(rd); | 834 mflo(rd); |
835 } else { | 835 } else { |
836 // li handles the relocation. | 836 // li handles the relocation. |
837 ASSERT(!rs.is(at)); | 837 DCHECK(!rs.is(at)); |
838 li(at, rt); | 838 li(at, rt); |
839 ddiv(rs, at); | 839 ddiv(rs, at); |
840 mflo(rd); | 840 mflo(rd); |
841 } | 841 } |
842 } else { | 842 } else { |
843 if (rt.is_reg()) { | 843 if (rt.is_reg()) { |
844 ddiv(rd, rs, rt.rm()); | 844 ddiv(rd, rs, rt.rm()); |
845 } else { | 845 } else { |
846 // li handles the relocation. | 846 // li handles the relocation. |
847 ASSERT(!rs.is(at)); | 847 DCHECK(!rs.is(at)); |
848 li(at, rt); | 848 li(at, rt); |
849 ddiv(rd, rs, at); | 849 ddiv(rd, rs, at); |
850 } | 850 } |
851 } | 851 } |
852 } | 852 } |
853 | 853 |
854 | 854 |
855 void MacroAssembler::Divu(Register rs, const Operand& rt) { | 855 void MacroAssembler::Divu(Register rs, const Operand& rt) { |
856 if (rt.is_reg()) { | 856 if (rt.is_reg()) { |
857 divu(rs, rt.rm()); | 857 divu(rs, rt.rm()); |
858 } else { | 858 } else { |
859 // li handles the relocation. | 859 // li handles the relocation. |
860 ASSERT(!rs.is(at)); | 860 DCHECK(!rs.is(at)); |
861 li(at, rt); | 861 li(at, rt); |
862 divu(rs, at); | 862 divu(rs, at); |
863 } | 863 } |
864 } | 864 } |
865 | 865 |
866 | 866 |
867 void MacroAssembler::Ddivu(Register rs, const Operand& rt) { | 867 void MacroAssembler::Ddivu(Register rs, const Operand& rt) { |
868 if (rt.is_reg()) { | 868 if (rt.is_reg()) { |
869 ddivu(rs, rt.rm()); | 869 ddivu(rs, rt.rm()); |
870 } else { | 870 } else { |
871 // li handles the relocation. | 871 // li handles the relocation. |
872 ASSERT(!rs.is(at)); | 872 DCHECK(!rs.is(at)); |
873 li(at, rt); | 873 li(at, rt); |
874 ddivu(rs, at); | 874 ddivu(rs, at); |
875 } | 875 } |
876 } | 876 } |
877 | 877 |
878 | 878 |
879 void MacroAssembler::Dmod(Register rd, Register rs, const Operand& rt) { | 879 void MacroAssembler::Dmod(Register rd, Register rs, const Operand& rt) { |
880 if (kArchVariant != kMips64r6) { | 880 if (kArchVariant != kMips64r6) { |
881 if (rt.is_reg()) { | 881 if (rt.is_reg()) { |
882 ddiv(rs, rt.rm()); | 882 ddiv(rs, rt.rm()); |
883 mfhi(rd); | 883 mfhi(rd); |
884 } else { | 884 } else { |
885 // li handles the relocation. | 885 // li handles the relocation. |
886 ASSERT(!rs.is(at)); | 886 DCHECK(!rs.is(at)); |
887 li(at, rt); | 887 li(at, rt); |
888 ddiv(rs, at); | 888 ddiv(rs, at); |
889 mfhi(rd); | 889 mfhi(rd); |
890 } | 890 } |
891 } else { | 891 } else { |
892 if (rt.is_reg()) { | 892 if (rt.is_reg()) { |
893 dmod(rd, rs, rt.rm()); | 893 dmod(rd, rs, rt.rm()); |
894 } else { | 894 } else { |
895 // li handles the relocation. | 895 // li handles the relocation. |
896 ASSERT(!rs.is(at)); | 896 DCHECK(!rs.is(at)); |
897 li(at, rt); | 897 li(at, rt); |
898 dmod(rd, rs, at); | 898 dmod(rd, rs, at); |
899 } | 899 } |
900 } | 900 } |
901 } | 901 } |
902 | 902 |
903 | 903 |
904 void MacroAssembler::And(Register rd, Register rs, const Operand& rt) { | 904 void MacroAssembler::And(Register rd, Register rs, const Operand& rt) { |
905 if (rt.is_reg()) { | 905 if (rt.is_reg()) { |
906 and_(rd, rs, rt.rm()); | 906 and_(rd, rs, rt.rm()); |
907 } else { | 907 } else { |
908 if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) { | 908 if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
909 andi(rd, rs, rt.imm64_); | 909 andi(rd, rs, rt.imm64_); |
910 } else { | 910 } else { |
911 // li handles the relocation. | 911 // li handles the relocation. |
912 ASSERT(!rs.is(at)); | 912 DCHECK(!rs.is(at)); |
913 li(at, rt); | 913 li(at, rt); |
914 and_(rd, rs, at); | 914 and_(rd, rs, at); |
915 } | 915 } |
916 } | 916 } |
917 } | 917 } |
918 | 918 |
919 | 919 |
920 void MacroAssembler::Or(Register rd, Register rs, const Operand& rt) { | 920 void MacroAssembler::Or(Register rd, Register rs, const Operand& rt) { |
921 if (rt.is_reg()) { | 921 if (rt.is_reg()) { |
922 or_(rd, rs, rt.rm()); | 922 or_(rd, rs, rt.rm()); |
923 } else { | 923 } else { |
924 if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) { | 924 if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
925 ori(rd, rs, rt.imm64_); | 925 ori(rd, rs, rt.imm64_); |
926 } else { | 926 } else { |
927 // li handles the relocation. | 927 // li handles the relocation. |
928 ASSERT(!rs.is(at)); | 928 DCHECK(!rs.is(at)); |
929 li(at, rt); | 929 li(at, rt); |
930 or_(rd, rs, at); | 930 or_(rd, rs, at); |
931 } | 931 } |
932 } | 932 } |
933 } | 933 } |
934 | 934 |
935 | 935 |
936 void MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) { | 936 void MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) { |
937 if (rt.is_reg()) { | 937 if (rt.is_reg()) { |
938 xor_(rd, rs, rt.rm()); | 938 xor_(rd, rs, rt.rm()); |
939 } else { | 939 } else { |
940 if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) { | 940 if (is_uint16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
941 xori(rd, rs, rt.imm64_); | 941 xori(rd, rs, rt.imm64_); |
942 } else { | 942 } else { |
943 // li handles the relocation. | 943 // li handles the relocation. |
944 ASSERT(!rs.is(at)); | 944 DCHECK(!rs.is(at)); |
945 li(at, rt); | 945 li(at, rt); |
946 xor_(rd, rs, at); | 946 xor_(rd, rs, at); |
947 } | 947 } |
948 } | 948 } |
949 } | 949 } |
950 | 950 |
951 | 951 |
952 void MacroAssembler::Nor(Register rd, Register rs, const Operand& rt) { | 952 void MacroAssembler::Nor(Register rd, Register rs, const Operand& rt) { |
953 if (rt.is_reg()) { | 953 if (rt.is_reg()) { |
954 nor(rd, rs, rt.rm()); | 954 nor(rd, rs, rt.rm()); |
955 } else { | 955 } else { |
956 // li handles the relocation. | 956 // li handles the relocation. |
957 ASSERT(!rs.is(at)); | 957 DCHECK(!rs.is(at)); |
958 li(at, rt); | 958 li(at, rt); |
959 nor(rd, rs, at); | 959 nor(rd, rs, at); |
960 } | 960 } |
961 } | 961 } |
962 | 962 |
963 | 963 |
964 void MacroAssembler::Neg(Register rs, const Operand& rt) { | 964 void MacroAssembler::Neg(Register rs, const Operand& rt) { |
965 ASSERT(rt.is_reg()); | 965 DCHECK(rt.is_reg()); |
966 ASSERT(!at.is(rs)); | 966 DCHECK(!at.is(rs)); |
967 ASSERT(!at.is(rt.rm())); | 967 DCHECK(!at.is(rt.rm())); |
968 li(at, -1); | 968 li(at, -1); |
969 xor_(rs, rt.rm(), at); | 969 xor_(rs, rt.rm(), at); |
970 } | 970 } |
971 | 971 |
972 | 972 |
973 void MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) { | 973 void MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) { |
974 if (rt.is_reg()) { | 974 if (rt.is_reg()) { |
975 slt(rd, rs, rt.rm()); | 975 slt(rd, rs, rt.rm()); |
976 } else { | 976 } else { |
977 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { | 977 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
978 slti(rd, rs, rt.imm64_); | 978 slti(rd, rs, rt.imm64_); |
979 } else { | 979 } else { |
980 // li handles the relocation. | 980 // li handles the relocation. |
981 ASSERT(!rs.is(at)); | 981 DCHECK(!rs.is(at)); |
982 li(at, rt); | 982 li(at, rt); |
983 slt(rd, rs, at); | 983 slt(rd, rs, at); |
984 } | 984 } |
985 } | 985 } |
986 } | 986 } |
987 | 987 |
988 | 988 |
989 void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) { | 989 void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) { |
990 if (rt.is_reg()) { | 990 if (rt.is_reg()) { |
991 sltu(rd, rs, rt.rm()); | 991 sltu(rd, rs, rt.rm()); |
992 } else { | 992 } else { |
993 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { | 993 if (is_int16(rt.imm64_) && !MustUseReg(rt.rmode_)) { |
994 sltiu(rd, rs, rt.imm64_); | 994 sltiu(rd, rs, rt.imm64_); |
995 } else { | 995 } else { |
996 // li handles the relocation. | 996 // li handles the relocation. |
997 ASSERT(!rs.is(at)); | 997 DCHECK(!rs.is(at)); |
998 li(at, rt); | 998 li(at, rt); |
999 sltu(rd, rs, at); | 999 sltu(rd, rs, at); |
1000 } | 1000 } |
1001 } | 1001 } |
1002 } | 1002 } |
1003 | 1003 |
1004 | 1004 |
1005 void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) { | 1005 void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) { |
1006 if (kArchVariant == kMips64r2) { | 1006 if (kArchVariant == kMips64r2) { |
1007 if (rt.is_reg()) { | 1007 if (rt.is_reg()) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 swr(rd, rs); | 1054 swr(rd, rs); |
1055 swl(rd, MemOperand(rs.rm(), rs.offset() + 3)); | 1055 swl(rd, MemOperand(rs.rm(), rs.offset() + 3)); |
1056 } | 1056 } |
1057 | 1057 |
1058 | 1058 |
1059 // Do 64-bit load from unaligned address. Note this only handles | 1059 // Do 64-bit load from unaligned address. Note this only handles |
1060 // the specific case of 32-bit aligned, but not 64-bit aligned. | 1060 // the specific case of 32-bit aligned, but not 64-bit aligned. |
1061 void MacroAssembler::Uld(Register rd, const MemOperand& rs, Register scratch) { | 1061 void MacroAssembler::Uld(Register rd, const MemOperand& rs, Register scratch) { |
1062 // Assert fail if the offset from start of object IS actually aligned. | 1062 // Assert fail if the offset from start of object IS actually aligned. |
1063 // ONLY use with known misalignment, since there is performance cost. | 1063 // ONLY use with known misalignment, since there is performance cost. |
1064 ASSERT((rs.offset() + kHeapObjectTag) & (kPointerSize - 1)); | 1064 DCHECK((rs.offset() + kHeapObjectTag) & (kPointerSize - 1)); |
1065 // TODO(plind): endian dependency. | 1065 // TODO(plind): endian dependency. |
1066 lwu(rd, rs); | 1066 lwu(rd, rs); |
1067 lw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); | 1067 lw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); |
1068 dsll32(scratch, scratch, 0); | 1068 dsll32(scratch, scratch, 0); |
1069 Daddu(rd, rd, scratch); | 1069 Daddu(rd, rd, scratch); |
1070 } | 1070 } |
1071 | 1071 |
1072 | 1072 |
1073 // Do 64-bit store to unaligned address. Note this only handles | 1073 // Do 64-bit store to unaligned address. Note this only handles |
1074 // the specific case of 32-bit aligned, but not 64-bit aligned. | 1074 // the specific case of 32-bit aligned, but not 64-bit aligned. |
1075 void MacroAssembler::Usd(Register rd, const MemOperand& rs, Register scratch) { | 1075 void MacroAssembler::Usd(Register rd, const MemOperand& rs, Register scratch) { |
1076 // Assert fail if the offset from start of object IS actually aligned. | 1076 // Assert fail if the offset from start of object IS actually aligned. |
1077 // ONLY use with known misalignment, since there is performance cost. | 1077 // ONLY use with known misalignment, since there is performance cost. |
1078 ASSERT((rs.offset() + kHeapObjectTag) & (kPointerSize - 1)); | 1078 DCHECK((rs.offset() + kHeapObjectTag) & (kPointerSize - 1)); |
1079 // TODO(plind): endian dependency. | 1079 // TODO(plind): endian dependency. |
1080 sw(rd, rs); | 1080 sw(rd, rs); |
1081 dsrl32(scratch, rd, 0); | 1081 dsrl32(scratch, rd, 0); |
1082 sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); | 1082 sw(scratch, MemOperand(rs.rm(), rs.offset() + kPointerSize / 2)); |
1083 } | 1083 } |
1084 | 1084 |
1085 | 1085 |
1086 void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) { | 1086 void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) { |
1087 AllowDeferredHandleDereference smi_check; | 1087 AllowDeferredHandleDereference smi_check; |
1088 if (value->IsSmi()) { | 1088 if (value->IsSmi()) { |
1089 li(dst, Operand(value), mode); | 1089 li(dst, Operand(value), mode); |
1090 } else { | 1090 } else { |
1091 ASSERT(value->IsHeapObject()); | 1091 DCHECK(value->IsHeapObject()); |
1092 if (isolate()->heap()->InNewSpace(*value)) { | 1092 if (isolate()->heap()->InNewSpace(*value)) { |
1093 Handle<Cell> cell = isolate()->factory()->NewCell(value); | 1093 Handle<Cell> cell = isolate()->factory()->NewCell(value); |
1094 li(dst, Operand(cell)); | 1094 li(dst, Operand(cell)); |
1095 ld(dst, FieldMemOperand(dst, Cell::kValueOffset)); | 1095 ld(dst, FieldMemOperand(dst, Cell::kValueOffset)); |
1096 } else { | 1096 } else { |
1097 li(dst, Operand(value)); | 1097 li(dst, Operand(value)); |
1098 } | 1098 } |
1099 } | 1099 } |
1100 } | 1100 } |
1101 | 1101 |
1102 | 1102 |
1103 void MacroAssembler::li(Register rd, Operand j, LiFlags mode) { | 1103 void MacroAssembler::li(Register rd, Operand j, LiFlags mode) { |
1104 ASSERT(!j.is_reg()); | 1104 DCHECK(!j.is_reg()); |
1105 BlockTrampolinePoolScope block_trampoline_pool(this); | 1105 BlockTrampolinePoolScope block_trampoline_pool(this); |
1106 if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) { | 1106 if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) { |
1107 // Normal load of an immediate value which does not need Relocation Info. | 1107 // Normal load of an immediate value which does not need Relocation Info. |
1108 if (is_int32(j.imm64_)) { | 1108 if (is_int32(j.imm64_)) { |
1109 if (is_int16(j.imm64_)) { | 1109 if (is_int16(j.imm64_)) { |
1110 daddiu(rd, zero_reg, (j.imm64_ & kImm16Mask)); | 1110 daddiu(rd, zero_reg, (j.imm64_ & kImm16Mask)); |
1111 } else if (!(j.imm64_ & kHiMask)) { | 1111 } else if (!(j.imm64_ & kHiMask)) { |
1112 ori(rd, zero_reg, (j.imm64_ & kImm16Mask)); | 1112 ori(rd, zero_reg, (j.imm64_ & kImm16Mask)); |
1113 } else if (!(j.imm64_ & kImm16Mask)) { | 1113 } else if (!(j.imm64_ & kImm16Mask)) { |
1114 lui(rd, (j.imm64_ >> kLuiShift) & kImm16Mask); | 1114 lui(rd, (j.imm64_ >> kLuiShift) & kImm16Mask); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1268 li(a1, instructions * kInstrSize); | 1268 li(a1, instructions * kInstrSize); |
1269 CallCFunction(ExternalReference::flush_icache_function(isolate()), 2); | 1269 CallCFunction(ExternalReference::flush_icache_function(isolate()), 2); |
1270 MultiPop(saved_regs); | 1270 MultiPop(saved_regs); |
1271 } | 1271 } |
1272 | 1272 |
1273 | 1273 |
1274 void MacroAssembler::Ext(Register rt, | 1274 void MacroAssembler::Ext(Register rt, |
1275 Register rs, | 1275 Register rs, |
1276 uint16_t pos, | 1276 uint16_t pos, |
1277 uint16_t size) { | 1277 uint16_t size) { |
1278 ASSERT(pos < 32); | 1278 DCHECK(pos < 32); |
1279 ASSERT(pos + size < 33); | 1279 DCHECK(pos + size < 33); |
1280 ext_(rt, rs, pos, size); | 1280 ext_(rt, rs, pos, size); |
1281 } | 1281 } |
1282 | 1282 |
1283 | 1283 |
1284 void MacroAssembler::Ins(Register rt, | 1284 void MacroAssembler::Ins(Register rt, |
1285 Register rs, | 1285 Register rs, |
1286 uint16_t pos, | 1286 uint16_t pos, |
1287 uint16_t size) { | 1287 uint16_t size) { |
1288 ASSERT(pos < 32); | 1288 DCHECK(pos < 32); |
1289 ASSERT(pos + size <= 32); | 1289 DCHECK(pos + size <= 32); |
1290 ASSERT(size != 0); | 1290 DCHECK(size != 0); |
1291 ins_(rt, rs, pos, size); | 1291 ins_(rt, rs, pos, size); |
1292 } | 1292 } |
1293 | 1293 |
1294 | 1294 |
1295 void MacroAssembler::Cvt_d_uw(FPURegister fd, | 1295 void MacroAssembler::Cvt_d_uw(FPURegister fd, |
1296 FPURegister fs, | 1296 FPURegister fs, |
1297 FPURegister scratch) { | 1297 FPURegister scratch) { |
1298 // Move the data from fs to t8. | 1298 // Move the data from fs to t8. |
1299 mfc1(t8, fs); | 1299 mfc1(t8, fs); |
1300 Cvt_d_uw(fd, t8, scratch); | 1300 Cvt_d_uw(fd, t8, scratch); |
1301 } | 1301 } |
1302 | 1302 |
1303 | 1303 |
1304 void MacroAssembler::Cvt_d_uw(FPURegister fd, | 1304 void MacroAssembler::Cvt_d_uw(FPURegister fd, |
1305 Register rs, | 1305 Register rs, |
1306 FPURegister scratch) { | 1306 FPURegister scratch) { |
1307 // Convert rs to a FP value in fd (and fd + 1). | 1307 // Convert rs to a FP value in fd (and fd + 1). |
1308 // We do this by converting rs minus the MSB to avoid sign conversion, | 1308 // We do this by converting rs minus the MSB to avoid sign conversion, |
1309 // then adding 2^31 to the result (if needed). | 1309 // then adding 2^31 to the result (if needed). |
1310 | 1310 |
1311 ASSERT(!fd.is(scratch)); | 1311 DCHECK(!fd.is(scratch)); |
1312 ASSERT(!rs.is(t9)); | 1312 DCHECK(!rs.is(t9)); |
1313 ASSERT(!rs.is(at)); | 1313 DCHECK(!rs.is(at)); |
1314 | 1314 |
1315 // Save rs's MSB to t9. | 1315 // Save rs's MSB to t9. |
1316 Ext(t9, rs, 31, 1); | 1316 Ext(t9, rs, 31, 1); |
1317 // Remove rs's MSB. | 1317 // Remove rs's MSB. |
1318 Ext(at, rs, 0, 31); | 1318 Ext(at, rs, 0, 31); |
1319 // Move the result to fd. | 1319 // Move the result to fd. |
1320 mtc1(at, fd); | 1320 mtc1(at, fd); |
1321 mthc1(zero_reg, fd); | 1321 mthc1(zero_reg, fd); |
1322 | 1322 |
1323 // Convert fd to a real FP value. | 1323 // Convert fd to a real FP value. |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 | 1397 |
1398 | 1398 |
1399 void MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) { | 1399 void MacroAssembler::Ceil_w_d(FPURegister fd, FPURegister fs) { |
1400 ceil_w_d(fd, fs); | 1400 ceil_w_d(fd, fs); |
1401 } | 1401 } |
1402 | 1402 |
1403 | 1403 |
1404 void MacroAssembler::Trunc_uw_d(FPURegister fd, | 1404 void MacroAssembler::Trunc_uw_d(FPURegister fd, |
1405 Register rs, | 1405 Register rs, |
1406 FPURegister scratch) { | 1406 FPURegister scratch) { |
1407 ASSERT(!fd.is(scratch)); | 1407 DCHECK(!fd.is(scratch)); |
1408 ASSERT(!rs.is(at)); | 1408 DCHECK(!rs.is(at)); |
1409 | 1409 |
1410 // Load 2^31 into scratch as its float representation. | 1410 // Load 2^31 into scratch as its float representation. |
1411 li(at, 0x41E00000); | 1411 li(at, 0x41E00000); |
1412 mtc1(zero_reg, scratch); | 1412 mtc1(zero_reg, scratch); |
1413 mthc1(at, scratch); | 1413 mthc1(at, scratch); |
1414 // Test if scratch > fd. | 1414 // Test if scratch > fd. |
1415 // If fd < 2^31 we can convert it normally. | 1415 // If fd < 2^31 we can convert it normally. |
1416 Label simple_convert; | 1416 Label simple_convert; |
1417 BranchF(&simple_convert, NULL, lt, fd, scratch); | 1417 BranchF(&simple_convert, NULL, lt, fd, scratch); |
1418 | 1418 |
(...skipping 14 matching lines...) Expand all Loading... |
1433 bind(&done); | 1433 bind(&done); |
1434 } | 1434 } |
1435 | 1435 |
1436 | 1436 |
1437 void MacroAssembler::Madd_d(FPURegister fd, FPURegister fr, FPURegister fs, | 1437 void MacroAssembler::Madd_d(FPURegister fd, FPURegister fr, FPURegister fs, |
1438 FPURegister ft, FPURegister scratch) { | 1438 FPURegister ft, FPURegister scratch) { |
1439 if (0) { // TODO(plind): find reasonable arch-variant symbol names. | 1439 if (0) { // TODO(plind): find reasonable arch-variant symbol names. |
1440 madd_d(fd, fr, fs, ft); | 1440 madd_d(fd, fr, fs, ft); |
1441 } else { | 1441 } else { |
1442 // Can not change source regs's value. | 1442 // Can not change source regs's value. |
1443 ASSERT(!fr.is(scratch) && !fs.is(scratch) && !ft.is(scratch)); | 1443 DCHECK(!fr.is(scratch) && !fs.is(scratch) && !ft.is(scratch)); |
1444 mul_d(scratch, fs, ft); | 1444 mul_d(scratch, fs, ft); |
1445 add_d(fd, fr, scratch); | 1445 add_d(fd, fr, scratch); |
1446 } | 1446 } |
1447 } | 1447 } |
1448 | 1448 |
1449 | 1449 |
1450 void MacroAssembler::BranchF(Label* target, | 1450 void MacroAssembler::BranchF(Label* target, |
1451 Label* nan, | 1451 Label* nan, |
1452 Condition cc, | 1452 Condition cc, |
1453 FPURegister cmp1, | 1453 FPURegister cmp1, |
1454 FPURegister cmp2, | 1454 FPURegister cmp2, |
1455 BranchDelaySlot bd) { | 1455 BranchDelaySlot bd) { |
1456 BlockTrampolinePoolScope block_trampoline_pool(this); | 1456 BlockTrampolinePoolScope block_trampoline_pool(this); |
1457 if (cc == al) { | 1457 if (cc == al) { |
1458 Branch(bd, target); | 1458 Branch(bd, target); |
1459 return; | 1459 return; |
1460 } | 1460 } |
1461 | 1461 |
1462 ASSERT(nan || target); | 1462 DCHECK(nan || target); |
1463 // Check for unordered (NaN) cases. | 1463 // Check for unordered (NaN) cases. |
1464 if (nan) { | 1464 if (nan) { |
1465 if (kArchVariant != kMips64r6) { | 1465 if (kArchVariant != kMips64r6) { |
1466 c(UN, D, cmp1, cmp2); | 1466 c(UN, D, cmp1, cmp2); |
1467 bc1t(nan); | 1467 bc1t(nan); |
1468 } else { | 1468 } else { |
1469 // Use f31 for comparison result. It has to be unavailable to lithium | 1469 // Use f31 for comparison result. It has to be unavailable to lithium |
1470 // register allocator. | 1470 // register allocator. |
1471 ASSERT(!cmp1.is(f31) && !cmp2.is(f31)); | 1471 DCHECK(!cmp1.is(f31) && !cmp2.is(f31)); |
1472 cmp(UN, L, f31, cmp1, cmp2); | 1472 cmp(UN, L, f31, cmp1, cmp2); |
1473 bc1nez(nan, f31); | 1473 bc1nez(nan, f31); |
1474 } | 1474 } |
1475 } | 1475 } |
1476 | 1476 |
1477 if (kArchVariant != kMips64r6) { | 1477 if (kArchVariant != kMips64r6) { |
1478 if (target) { | 1478 if (target) { |
1479 // Here NaN cases were either handled by this function or are assumed to | 1479 // Here NaN cases were either handled by this function or are assumed to |
1480 // have been handled by the caller. | 1480 // have been handled by the caller. |
1481 switch (cc) { | 1481 switch (cc) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1514 default: | 1514 default: |
1515 CHECK(0); | 1515 CHECK(0); |
1516 } | 1516 } |
1517 } | 1517 } |
1518 } else { | 1518 } else { |
1519 if (target) { | 1519 if (target) { |
1520 // Here NaN cases were either handled by this function or are assumed to | 1520 // Here NaN cases were either handled by this function or are assumed to |
1521 // have been handled by the caller. | 1521 // have been handled by the caller. |
1522 // Unsigned conditions are treated as their signed counterpart. | 1522 // Unsigned conditions are treated as their signed counterpart. |
1523 // Use f31 for comparison result, it is valid in fp64 (FR = 1) mode. | 1523 // Use f31 for comparison result, it is valid in fp64 (FR = 1) mode. |
1524 ASSERT(!cmp1.is(f31) && !cmp2.is(f31)); | 1524 DCHECK(!cmp1.is(f31) && !cmp2.is(f31)); |
1525 switch (cc) { | 1525 switch (cc) { |
1526 case lt: | 1526 case lt: |
1527 cmp(OLT, L, f31, cmp1, cmp2); | 1527 cmp(OLT, L, f31, cmp1, cmp2); |
1528 bc1nez(target, f31); | 1528 bc1nez(target, f31); |
1529 break; | 1529 break; |
1530 case gt: | 1530 case gt: |
1531 cmp(ULE, L, f31, cmp1, cmp2); | 1531 cmp(ULE, L, f31, cmp1, cmp2); |
1532 bc1eqz(target, f31); | 1532 bc1eqz(target, f31); |
1533 break; | 1533 break; |
1534 case ge: | 1534 case ge: |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1639 } | 1639 } |
1640 | 1640 |
1641 | 1641 |
1642 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode, | 1642 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode, |
1643 Register result, | 1643 Register result, |
1644 DoubleRegister double_input, | 1644 DoubleRegister double_input, |
1645 Register scratch, | 1645 Register scratch, |
1646 DoubleRegister double_scratch, | 1646 DoubleRegister double_scratch, |
1647 Register except_flag, | 1647 Register except_flag, |
1648 CheckForInexactConversion check_inexact) { | 1648 CheckForInexactConversion check_inexact) { |
1649 ASSERT(!result.is(scratch)); | 1649 DCHECK(!result.is(scratch)); |
1650 ASSERT(!double_input.is(double_scratch)); | 1650 DCHECK(!double_input.is(double_scratch)); |
1651 ASSERT(!except_flag.is(scratch)); | 1651 DCHECK(!except_flag.is(scratch)); |
1652 | 1652 |
1653 Label done; | 1653 Label done; |
1654 | 1654 |
1655 // Clear the except flag (0 = no exception) | 1655 // Clear the except flag (0 = no exception) |
1656 mov(except_flag, zero_reg); | 1656 mov(except_flag, zero_reg); |
1657 | 1657 |
1658 // Test for values that can be exactly represented as a signed 32-bit integer. | 1658 // Test for values that can be exactly represented as a signed 32-bit integer. |
1659 cvt_w_d(double_scratch, double_input); | 1659 cvt_w_d(double_scratch, double_input); |
1660 mfc1(result, double_scratch); | 1660 mfc1(result, double_scratch); |
1661 cvt_d_w(double_scratch, double_scratch); | 1661 cvt_d_w(double_scratch, double_scratch); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1745 Daddu(sp, sp, Operand(kDoubleSize)); | 1745 Daddu(sp, sp, Operand(kDoubleSize)); |
1746 pop(ra); | 1746 pop(ra); |
1747 | 1747 |
1748 bind(&done); | 1748 bind(&done); |
1749 } | 1749 } |
1750 | 1750 |
1751 | 1751 |
1752 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) { | 1752 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) { |
1753 Label done; | 1753 Label done; |
1754 DoubleRegister double_scratch = f12; | 1754 DoubleRegister double_scratch = f12; |
1755 ASSERT(!result.is(object)); | 1755 DCHECK(!result.is(object)); |
1756 | 1756 |
1757 ldc1(double_scratch, | 1757 ldc1(double_scratch, |
1758 MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag)); | 1758 MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag)); |
1759 TryInlineTruncateDoubleToI(result, double_scratch, &done); | 1759 TryInlineTruncateDoubleToI(result, double_scratch, &done); |
1760 | 1760 |
1761 // If we fell through then inline version didn't succeed - call stub instead. | 1761 // If we fell through then inline version didn't succeed - call stub instead. |
1762 push(ra); | 1762 push(ra); |
1763 DoubleToIStub stub(isolate(), | 1763 DoubleToIStub stub(isolate(), |
1764 object, | 1764 object, |
1765 result, | 1765 result, |
1766 HeapNumber::kValueOffset - kHeapObjectTag, | 1766 HeapNumber::kValueOffset - kHeapObjectTag, |
1767 true, | 1767 true, |
1768 true); | 1768 true); |
1769 CallStub(&stub); | 1769 CallStub(&stub); |
1770 pop(ra); | 1770 pop(ra); |
1771 | 1771 |
1772 bind(&done); | 1772 bind(&done); |
1773 } | 1773 } |
1774 | 1774 |
1775 | 1775 |
1776 void MacroAssembler::TruncateNumberToI(Register object, | 1776 void MacroAssembler::TruncateNumberToI(Register object, |
1777 Register result, | 1777 Register result, |
1778 Register heap_number_map, | 1778 Register heap_number_map, |
1779 Register scratch, | 1779 Register scratch, |
1780 Label* not_number) { | 1780 Label* not_number) { |
1781 Label done; | 1781 Label done; |
1782 ASSERT(!result.is(object)); | 1782 DCHECK(!result.is(object)); |
1783 | 1783 |
1784 UntagAndJumpIfSmi(result, object, &done); | 1784 UntagAndJumpIfSmi(result, object, &done); |
1785 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); | 1785 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); |
1786 TruncateHeapNumberToI(result, object); | 1786 TruncateHeapNumberToI(result, object); |
1787 | 1787 |
1788 bind(&done); | 1788 bind(&done); |
1789 } | 1789 } |
1790 | 1790 |
1791 | 1791 |
1792 void MacroAssembler::GetLeastBitsFromSmi(Register dst, | 1792 void MacroAssembler::GetLeastBitsFromSmi(Register dst, |
1793 Register src, | 1793 Register src, |
1794 int num_least_bits) { | 1794 int num_least_bits) { |
1795 // Ext(dst, src, kSmiTagSize, num_least_bits); | 1795 // Ext(dst, src, kSmiTagSize, num_least_bits); |
1796 SmiUntag(dst, src); | 1796 SmiUntag(dst, src); |
1797 And(dst, dst, Operand((1 << num_least_bits) - 1)); | 1797 And(dst, dst, Operand((1 << num_least_bits) - 1)); |
1798 } | 1798 } |
1799 | 1799 |
1800 | 1800 |
1801 void MacroAssembler::GetLeastBitsFromInt32(Register dst, | 1801 void MacroAssembler::GetLeastBitsFromInt32(Register dst, |
1802 Register src, | 1802 Register src, |
1803 int num_least_bits) { | 1803 int num_least_bits) { |
1804 ASSERT(!src.is(dst)); | 1804 DCHECK(!src.is(dst)); |
1805 And(dst, src, Operand((1 << num_least_bits) - 1)); | 1805 And(dst, src, Operand((1 << num_least_bits) - 1)); |
1806 } | 1806 } |
1807 | 1807 |
1808 | 1808 |
1809 // Emulated condtional branches do not emit a nop in the branch delay slot. | 1809 // Emulated condtional branches do not emit a nop in the branch delay slot. |
1810 // | 1810 // |
1811 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. | 1811 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. |
1812 #define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT( \ | 1812 #define BRANCH_ARGS_CHECK(cond, rs, rt) DCHECK( \ |
1813 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ | 1813 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ |
1814 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) | 1814 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) |
1815 | 1815 |
1816 | 1816 |
1817 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { | 1817 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { |
1818 BranchShort(offset, bdslot); | 1818 BranchShort(offset, bdslot); |
1819 } | 1819 } |
1820 | 1820 |
1821 | 1821 |
1822 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, | 1822 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1894 // Emit a nop in the branch delay slot if required. | 1894 // Emit a nop in the branch delay slot if required. |
1895 if (bdslot == PROTECT) | 1895 if (bdslot == PROTECT) |
1896 nop(); | 1896 nop(); |
1897 } | 1897 } |
1898 | 1898 |
1899 | 1899 |
1900 void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs, | 1900 void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs, |
1901 const Operand& rt, | 1901 const Operand& rt, |
1902 BranchDelaySlot bdslot) { | 1902 BranchDelaySlot bdslot) { |
1903 BRANCH_ARGS_CHECK(cond, rs, rt); | 1903 BRANCH_ARGS_CHECK(cond, rs, rt); |
1904 ASSERT(!rs.is(zero_reg)); | 1904 DCHECK(!rs.is(zero_reg)); |
1905 Register r2 = no_reg; | 1905 Register r2 = no_reg; |
1906 Register scratch = at; | 1906 Register scratch = at; |
1907 | 1907 |
1908 if (rt.is_reg()) { | 1908 if (rt.is_reg()) { |
1909 // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or | 1909 // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or |
1910 // rt. | 1910 // rt. |
1911 BlockTrampolinePoolScope block_trampoline_pool(this); | 1911 BlockTrampolinePoolScope block_trampoline_pool(this); |
1912 r2 = rt.rm_; | 1912 r2 = rt.rm_; |
1913 switch (cond) { | 1913 switch (cond) { |
1914 case cc_always: | 1914 case cc_always: |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1994 // Be careful to always use shifted_branch_offset only just before the | 1994 // Be careful to always use shifted_branch_offset only just before the |
1995 // branch instruction, as the location will be remember for patching the | 1995 // branch instruction, as the location will be remember for patching the |
1996 // target. | 1996 // target. |
1997 BlockTrampolinePoolScope block_trampoline_pool(this); | 1997 BlockTrampolinePoolScope block_trampoline_pool(this); |
1998 switch (cond) { | 1998 switch (cond) { |
1999 case cc_always: | 1999 case cc_always: |
2000 b(offset); | 2000 b(offset); |
2001 break; | 2001 break; |
2002 case eq: | 2002 case eq: |
2003 // We don't want any other register but scratch clobbered. | 2003 // We don't want any other register but scratch clobbered. |
2004 ASSERT(!scratch.is(rs)); | 2004 DCHECK(!scratch.is(rs)); |
2005 r2 = scratch; | 2005 r2 = scratch; |
2006 li(r2, rt); | 2006 li(r2, rt); |
2007 beq(rs, r2, offset); | 2007 beq(rs, r2, offset); |
2008 break; | 2008 break; |
2009 case ne: | 2009 case ne: |
2010 // We don't want any other register but scratch clobbered. | 2010 // We don't want any other register but scratch clobbered. |
2011 ASSERT(!scratch.is(rs)); | 2011 DCHECK(!scratch.is(rs)); |
2012 r2 = scratch; | 2012 r2 = scratch; |
2013 li(r2, rt); | 2013 li(r2, rt); |
2014 bne(rs, r2, offset); | 2014 bne(rs, r2, offset); |
2015 break; | 2015 break; |
2016 // Signed comparison. | 2016 // Signed comparison. |
2017 case greater: | 2017 case greater: |
2018 if (rt.imm64_ == 0) { | 2018 if (rt.imm64_ == 0) { |
2019 bgtz(rs, offset); | 2019 bgtz(rs, offset); |
2020 } else { | 2020 } else { |
2021 r2 = scratch; | 2021 r2 = scratch; |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2246 // Be careful to always use shifted_branch_offset only just before the | 2246 // Be careful to always use shifted_branch_offset only just before the |
2247 // branch instruction, as the location will be remember for patching the | 2247 // branch instruction, as the location will be remember for patching the |
2248 // target. | 2248 // target. |
2249 BlockTrampolinePoolScope block_trampoline_pool(this); | 2249 BlockTrampolinePoolScope block_trampoline_pool(this); |
2250 switch (cond) { | 2250 switch (cond) { |
2251 case cc_always: | 2251 case cc_always: |
2252 offset = shifted_branch_offset(L, false); | 2252 offset = shifted_branch_offset(L, false); |
2253 b(offset); | 2253 b(offset); |
2254 break; | 2254 break; |
2255 case eq: | 2255 case eq: |
2256 ASSERT(!scratch.is(rs)); | 2256 DCHECK(!scratch.is(rs)); |
2257 r2 = scratch; | 2257 r2 = scratch; |
2258 li(r2, rt); | 2258 li(r2, rt); |
2259 offset = shifted_branch_offset(L, false); | 2259 offset = shifted_branch_offset(L, false); |
2260 beq(rs, r2, offset); | 2260 beq(rs, r2, offset); |
2261 break; | 2261 break; |
2262 case ne: | 2262 case ne: |
2263 ASSERT(!scratch.is(rs)); | 2263 DCHECK(!scratch.is(rs)); |
2264 r2 = scratch; | 2264 r2 = scratch; |
2265 li(r2, rt); | 2265 li(r2, rt); |
2266 offset = shifted_branch_offset(L, false); | 2266 offset = shifted_branch_offset(L, false); |
2267 bne(rs, r2, offset); | 2267 bne(rs, r2, offset); |
2268 break; | 2268 break; |
2269 // Signed comparison. | 2269 // Signed comparison. |
2270 case greater: | 2270 case greater: |
2271 if (rt.imm64_ == 0) { | 2271 if (rt.imm64_ == 0) { |
2272 offset = shifted_branch_offset(L, false); | 2272 offset = shifted_branch_offset(L, false); |
2273 bgtz(rs, offset); | 2273 bgtz(rs, offset); |
2274 } else { | 2274 } else { |
2275 ASSERT(!scratch.is(rs)); | 2275 DCHECK(!scratch.is(rs)); |
2276 r2 = scratch; | 2276 r2 = scratch; |
2277 li(r2, rt); | 2277 li(r2, rt); |
2278 slt(scratch, r2, rs); | 2278 slt(scratch, r2, rs); |
2279 offset = shifted_branch_offset(L, false); | 2279 offset = shifted_branch_offset(L, false); |
2280 bne(scratch, zero_reg, offset); | 2280 bne(scratch, zero_reg, offset); |
2281 } | 2281 } |
2282 break; | 2282 break; |
2283 case greater_equal: | 2283 case greater_equal: |
2284 if (rt.imm64_ == 0) { | 2284 if (rt.imm64_ == 0) { |
2285 offset = shifted_branch_offset(L, false); | 2285 offset = shifted_branch_offset(L, false); |
2286 bgez(rs, offset); | 2286 bgez(rs, offset); |
2287 } else if (is_int16(rt.imm64_)) { | 2287 } else if (is_int16(rt.imm64_)) { |
2288 slti(scratch, rs, rt.imm64_); | 2288 slti(scratch, rs, rt.imm64_); |
2289 offset = shifted_branch_offset(L, false); | 2289 offset = shifted_branch_offset(L, false); |
2290 beq(scratch, zero_reg, offset); | 2290 beq(scratch, zero_reg, offset); |
2291 } else { | 2291 } else { |
2292 ASSERT(!scratch.is(rs)); | 2292 DCHECK(!scratch.is(rs)); |
2293 r2 = scratch; | 2293 r2 = scratch; |
2294 li(r2, rt); | 2294 li(r2, rt); |
2295 slt(scratch, rs, r2); | 2295 slt(scratch, rs, r2); |
2296 offset = shifted_branch_offset(L, false); | 2296 offset = shifted_branch_offset(L, false); |
2297 beq(scratch, zero_reg, offset); | 2297 beq(scratch, zero_reg, offset); |
2298 } | 2298 } |
2299 break; | 2299 break; |
2300 case less: | 2300 case less: |
2301 if (rt.imm64_ == 0) { | 2301 if (rt.imm64_ == 0) { |
2302 offset = shifted_branch_offset(L, false); | 2302 offset = shifted_branch_offset(L, false); |
2303 bltz(rs, offset); | 2303 bltz(rs, offset); |
2304 } else if (is_int16(rt.imm64_)) { | 2304 } else if (is_int16(rt.imm64_)) { |
2305 slti(scratch, rs, rt.imm64_); | 2305 slti(scratch, rs, rt.imm64_); |
2306 offset = shifted_branch_offset(L, false); | 2306 offset = shifted_branch_offset(L, false); |
2307 bne(scratch, zero_reg, offset); | 2307 bne(scratch, zero_reg, offset); |
2308 } else { | 2308 } else { |
2309 ASSERT(!scratch.is(rs)); | 2309 DCHECK(!scratch.is(rs)); |
2310 r2 = scratch; | 2310 r2 = scratch; |
2311 li(r2, rt); | 2311 li(r2, rt); |
2312 slt(scratch, rs, r2); | 2312 slt(scratch, rs, r2); |
2313 offset = shifted_branch_offset(L, false); | 2313 offset = shifted_branch_offset(L, false); |
2314 bne(scratch, zero_reg, offset); | 2314 bne(scratch, zero_reg, offset); |
2315 } | 2315 } |
2316 break; | 2316 break; |
2317 case less_equal: | 2317 case less_equal: |
2318 if (rt.imm64_ == 0) { | 2318 if (rt.imm64_ == 0) { |
2319 offset = shifted_branch_offset(L, false); | 2319 offset = shifted_branch_offset(L, false); |
2320 blez(rs, offset); | 2320 blez(rs, offset); |
2321 } else { | 2321 } else { |
2322 ASSERT(!scratch.is(rs)); | 2322 DCHECK(!scratch.is(rs)); |
2323 r2 = scratch; | 2323 r2 = scratch; |
2324 li(r2, rt); | 2324 li(r2, rt); |
2325 slt(scratch, r2, rs); | 2325 slt(scratch, r2, rs); |
2326 offset = shifted_branch_offset(L, false); | 2326 offset = shifted_branch_offset(L, false); |
2327 beq(scratch, zero_reg, offset); | 2327 beq(scratch, zero_reg, offset); |
2328 } | 2328 } |
2329 break; | 2329 break; |
2330 // Unsigned comparison. | 2330 // Unsigned comparison. |
2331 case Ugreater: | 2331 case Ugreater: |
2332 if (rt.imm64_ == 0) { | 2332 if (rt.imm64_ == 0) { |
2333 offset = shifted_branch_offset(L, false); | 2333 offset = shifted_branch_offset(L, false); |
2334 bne(rs, zero_reg, offset); | 2334 bne(rs, zero_reg, offset); |
2335 } else { | 2335 } else { |
2336 ASSERT(!scratch.is(rs)); | 2336 DCHECK(!scratch.is(rs)); |
2337 r2 = scratch; | 2337 r2 = scratch; |
2338 li(r2, rt); | 2338 li(r2, rt); |
2339 sltu(scratch, r2, rs); | 2339 sltu(scratch, r2, rs); |
2340 offset = shifted_branch_offset(L, false); | 2340 offset = shifted_branch_offset(L, false); |
2341 bne(scratch, zero_reg, offset); | 2341 bne(scratch, zero_reg, offset); |
2342 } | 2342 } |
2343 break; | 2343 break; |
2344 case Ugreater_equal: | 2344 case Ugreater_equal: |
2345 if (rt.imm64_ == 0) { | 2345 if (rt.imm64_ == 0) { |
2346 offset = shifted_branch_offset(L, false); | 2346 offset = shifted_branch_offset(L, false); |
2347 bgez(rs, offset); | 2347 bgez(rs, offset); |
2348 } else if (is_int16(rt.imm64_)) { | 2348 } else if (is_int16(rt.imm64_)) { |
2349 sltiu(scratch, rs, rt.imm64_); | 2349 sltiu(scratch, rs, rt.imm64_); |
2350 offset = shifted_branch_offset(L, false); | 2350 offset = shifted_branch_offset(L, false); |
2351 beq(scratch, zero_reg, offset); | 2351 beq(scratch, zero_reg, offset); |
2352 } else { | 2352 } else { |
2353 ASSERT(!scratch.is(rs)); | 2353 DCHECK(!scratch.is(rs)); |
2354 r2 = scratch; | 2354 r2 = scratch; |
2355 li(r2, rt); | 2355 li(r2, rt); |
2356 sltu(scratch, rs, r2); | 2356 sltu(scratch, rs, r2); |
2357 offset = shifted_branch_offset(L, false); | 2357 offset = shifted_branch_offset(L, false); |
2358 beq(scratch, zero_reg, offset); | 2358 beq(scratch, zero_reg, offset); |
2359 } | 2359 } |
2360 break; | 2360 break; |
2361 case Uless: | 2361 case Uless: |
2362 if (rt.imm64_ == 0) { | 2362 if (rt.imm64_ == 0) { |
2363 // No code needs to be emitted. | 2363 // No code needs to be emitted. |
2364 return; | 2364 return; |
2365 } else if (is_int16(rt.imm64_)) { | 2365 } else if (is_int16(rt.imm64_)) { |
2366 sltiu(scratch, rs, rt.imm64_); | 2366 sltiu(scratch, rs, rt.imm64_); |
2367 offset = shifted_branch_offset(L, false); | 2367 offset = shifted_branch_offset(L, false); |
2368 bne(scratch, zero_reg, offset); | 2368 bne(scratch, zero_reg, offset); |
2369 } else { | 2369 } else { |
2370 ASSERT(!scratch.is(rs)); | 2370 DCHECK(!scratch.is(rs)); |
2371 r2 = scratch; | 2371 r2 = scratch; |
2372 li(r2, rt); | 2372 li(r2, rt); |
2373 sltu(scratch, rs, r2); | 2373 sltu(scratch, rs, r2); |
2374 offset = shifted_branch_offset(L, false); | 2374 offset = shifted_branch_offset(L, false); |
2375 bne(scratch, zero_reg, offset); | 2375 bne(scratch, zero_reg, offset); |
2376 } | 2376 } |
2377 break; | 2377 break; |
2378 case Uless_equal: | 2378 case Uless_equal: |
2379 if (rt.imm64_ == 0) { | 2379 if (rt.imm64_ == 0) { |
2380 offset = shifted_branch_offset(L, false); | 2380 offset = shifted_branch_offset(L, false); |
2381 beq(rs, zero_reg, offset); | 2381 beq(rs, zero_reg, offset); |
2382 } else { | 2382 } else { |
2383 ASSERT(!scratch.is(rs)); | 2383 DCHECK(!scratch.is(rs)); |
2384 r2 = scratch; | 2384 r2 = scratch; |
2385 li(r2, rt); | 2385 li(r2, rt); |
2386 sltu(scratch, r2, rs); | 2386 sltu(scratch, r2, rs); |
2387 offset = shifted_branch_offset(L, false); | 2387 offset = shifted_branch_offset(L, false); |
2388 beq(scratch, zero_reg, offset); | 2388 beq(scratch, zero_reg, offset); |
2389 } | 2389 } |
2390 break; | 2390 break; |
2391 default: | 2391 default: |
2392 UNREACHABLE(); | 2392 UNREACHABLE(); |
2393 } | 2393 } |
2394 } | 2394 } |
2395 // Check that offset could actually hold on an int16_t. | 2395 // Check that offset could actually hold on an int16_t. |
2396 ASSERT(is_int16(offset)); | 2396 DCHECK(is_int16(offset)); |
2397 // Emit a nop in the branch delay slot if required. | 2397 // Emit a nop in the branch delay slot if required. |
2398 if (bdslot == PROTECT) | 2398 if (bdslot == PROTECT) |
2399 nop(); | 2399 nop(); |
2400 } | 2400 } |
2401 | 2401 |
2402 | 2402 |
2403 void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) { | 2403 void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) { |
2404 BranchAndLinkShort(offset, bdslot); | 2404 BranchAndLinkShort(offset, bdslot); |
2405 } | 2405 } |
2406 | 2406 |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2681 nop(); | 2681 nop(); |
2682 offset = shifted_branch_offset(L, false); | 2682 offset = shifted_branch_offset(L, false); |
2683 bal(offset); | 2683 bal(offset); |
2684 break; | 2684 break; |
2685 | 2685 |
2686 default: | 2686 default: |
2687 UNREACHABLE(); | 2687 UNREACHABLE(); |
2688 } | 2688 } |
2689 } | 2689 } |
2690 // Check that offset could actually hold on an int16_t. | 2690 // Check that offset could actually hold on an int16_t. |
2691 ASSERT(is_int16(offset)); | 2691 DCHECK(is_int16(offset)); |
2692 | 2692 |
2693 // Emit a nop in the branch delay slot if required. | 2693 // Emit a nop in the branch delay slot if required. |
2694 if (bdslot == PROTECT) | 2694 if (bdslot == PROTECT) |
2695 nop(); | 2695 nop(); |
2696 } | 2696 } |
2697 | 2697 |
2698 | 2698 |
2699 void MacroAssembler::Jump(Register target, | 2699 void MacroAssembler::Jump(Register target, |
2700 Condition cond, | 2700 Condition cond, |
2701 Register rs, | 2701 Register rs, |
(...skipping 30 matching lines...) Expand all Loading... |
2732 bind(&skip); | 2732 bind(&skip); |
2733 } | 2733 } |
2734 | 2734 |
2735 | 2735 |
2736 void MacroAssembler::Jump(Address target, | 2736 void MacroAssembler::Jump(Address target, |
2737 RelocInfo::Mode rmode, | 2737 RelocInfo::Mode rmode, |
2738 Condition cond, | 2738 Condition cond, |
2739 Register rs, | 2739 Register rs, |
2740 const Operand& rt, | 2740 const Operand& rt, |
2741 BranchDelaySlot bd) { | 2741 BranchDelaySlot bd) { |
2742 ASSERT(!RelocInfo::IsCodeTarget(rmode)); | 2742 DCHECK(!RelocInfo::IsCodeTarget(rmode)); |
2743 Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd); | 2743 Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd); |
2744 } | 2744 } |
2745 | 2745 |
2746 | 2746 |
2747 void MacroAssembler::Jump(Handle<Code> code, | 2747 void MacroAssembler::Jump(Handle<Code> code, |
2748 RelocInfo::Mode rmode, | 2748 RelocInfo::Mode rmode, |
2749 Condition cond, | 2749 Condition cond, |
2750 Register rs, | 2750 Register rs, |
2751 const Operand& rt, | 2751 const Operand& rt, |
2752 BranchDelaySlot bd) { | 2752 BranchDelaySlot bd) { |
2753 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 2753 DCHECK(RelocInfo::IsCodeTarget(rmode)); |
2754 AllowDeferredHandleDereference embedding_raw_address; | 2754 AllowDeferredHandleDereference embedding_raw_address; |
2755 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd); | 2755 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd); |
2756 } | 2756 } |
2757 | 2757 |
2758 | 2758 |
2759 int MacroAssembler::CallSize(Register target, | 2759 int MacroAssembler::CallSize(Register target, |
2760 Condition cond, | 2760 Condition cond, |
2761 Register rs, | 2761 Register rs, |
2762 const Operand& rt, | 2762 const Operand& rt, |
2763 BranchDelaySlot bd) { | 2763 BranchDelaySlot bd) { |
(...skipping 25 matching lines...) Expand all Loading... |
2789 jalr(target); | 2789 jalr(target); |
2790 } else { | 2790 } else { |
2791 BRANCH_ARGS_CHECK(cond, rs, rt); | 2791 BRANCH_ARGS_CHECK(cond, rs, rt); |
2792 Branch(2, NegateCondition(cond), rs, rt); | 2792 Branch(2, NegateCondition(cond), rs, rt); |
2793 jalr(target); | 2793 jalr(target); |
2794 } | 2794 } |
2795 // Emit a nop in the branch delay slot if required. | 2795 // Emit a nop in the branch delay slot if required. |
2796 if (bd == PROTECT) | 2796 if (bd == PROTECT) |
2797 nop(); | 2797 nop(); |
2798 | 2798 |
2799 ASSERT_EQ(CallSize(target, cond, rs, rt, bd), | 2799 DCHECK_EQ(CallSize(target, cond, rs, rt, bd), |
2800 SizeOfCodeGeneratedSince(&start)); | 2800 SizeOfCodeGeneratedSince(&start)); |
2801 } | 2801 } |
2802 | 2802 |
2803 | 2803 |
2804 int MacroAssembler::CallSize(Address target, | 2804 int MacroAssembler::CallSize(Address target, |
2805 RelocInfo::Mode rmode, | 2805 RelocInfo::Mode rmode, |
2806 Condition cond, | 2806 Condition cond, |
2807 Register rs, | 2807 Register rs, |
2808 const Operand& rt, | 2808 const Operand& rt, |
2809 BranchDelaySlot bd) { | 2809 BranchDelaySlot bd) { |
(...skipping 10 matching lines...) Expand all Loading... |
2820 BranchDelaySlot bd) { | 2820 BranchDelaySlot bd) { |
2821 BlockTrampolinePoolScope block_trampoline_pool(this); | 2821 BlockTrampolinePoolScope block_trampoline_pool(this); |
2822 Label start; | 2822 Label start; |
2823 bind(&start); | 2823 bind(&start); |
2824 int64_t target_int = reinterpret_cast<int64_t>(target); | 2824 int64_t target_int = reinterpret_cast<int64_t>(target); |
2825 // Must record previous source positions before the | 2825 // Must record previous source positions before the |
2826 // li() generates a new code target. | 2826 // li() generates a new code target. |
2827 positions_recorder()->WriteRecordedPositions(); | 2827 positions_recorder()->WriteRecordedPositions(); |
2828 li(t9, Operand(target_int, rmode), ADDRESS_LOAD); | 2828 li(t9, Operand(target_int, rmode), ADDRESS_LOAD); |
2829 Call(t9, cond, rs, rt, bd); | 2829 Call(t9, cond, rs, rt, bd); |
2830 ASSERT_EQ(CallSize(target, rmode, cond, rs, rt, bd), | 2830 DCHECK_EQ(CallSize(target, rmode, cond, rs, rt, bd), |
2831 SizeOfCodeGeneratedSince(&start)); | 2831 SizeOfCodeGeneratedSince(&start)); |
2832 } | 2832 } |
2833 | 2833 |
2834 | 2834 |
2835 int MacroAssembler::CallSize(Handle<Code> code, | 2835 int MacroAssembler::CallSize(Handle<Code> code, |
2836 RelocInfo::Mode rmode, | 2836 RelocInfo::Mode rmode, |
2837 TypeFeedbackId ast_id, | 2837 TypeFeedbackId ast_id, |
2838 Condition cond, | 2838 Condition cond, |
2839 Register rs, | 2839 Register rs, |
2840 const Operand& rt, | 2840 const Operand& rt, |
2841 BranchDelaySlot bd) { | 2841 BranchDelaySlot bd) { |
2842 AllowDeferredHandleDereference using_raw_address; | 2842 AllowDeferredHandleDereference using_raw_address; |
2843 return CallSize(reinterpret_cast<Address>(code.location()), | 2843 return CallSize(reinterpret_cast<Address>(code.location()), |
2844 rmode, cond, rs, rt, bd); | 2844 rmode, cond, rs, rt, bd); |
2845 } | 2845 } |
2846 | 2846 |
2847 | 2847 |
2848 void MacroAssembler::Call(Handle<Code> code, | 2848 void MacroAssembler::Call(Handle<Code> code, |
2849 RelocInfo::Mode rmode, | 2849 RelocInfo::Mode rmode, |
2850 TypeFeedbackId ast_id, | 2850 TypeFeedbackId ast_id, |
2851 Condition cond, | 2851 Condition cond, |
2852 Register rs, | 2852 Register rs, |
2853 const Operand& rt, | 2853 const Operand& rt, |
2854 BranchDelaySlot bd) { | 2854 BranchDelaySlot bd) { |
2855 BlockTrampolinePoolScope block_trampoline_pool(this); | 2855 BlockTrampolinePoolScope block_trampoline_pool(this); |
2856 Label start; | 2856 Label start; |
2857 bind(&start); | 2857 bind(&start); |
2858 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 2858 DCHECK(RelocInfo::IsCodeTarget(rmode)); |
2859 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) { | 2859 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) { |
2860 SetRecordedAstId(ast_id); | 2860 SetRecordedAstId(ast_id); |
2861 rmode = RelocInfo::CODE_TARGET_WITH_ID; | 2861 rmode = RelocInfo::CODE_TARGET_WITH_ID; |
2862 } | 2862 } |
2863 AllowDeferredHandleDereference embedding_raw_address; | 2863 AllowDeferredHandleDereference embedding_raw_address; |
2864 Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd); | 2864 Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd); |
2865 ASSERT_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd), | 2865 DCHECK_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd), |
2866 SizeOfCodeGeneratedSince(&start)); | 2866 SizeOfCodeGeneratedSince(&start)); |
2867 } | 2867 } |
2868 | 2868 |
2869 | 2869 |
2870 void MacroAssembler::Ret(Condition cond, | 2870 void MacroAssembler::Ret(Condition cond, |
2871 Register rs, | 2871 Register rs, |
2872 const Operand& rt, | 2872 const Operand& rt, |
2873 BranchDelaySlot bd) { | 2873 BranchDelaySlot bd) { |
2874 Jump(ra, cond, rs, rt, bd); | 2874 Jump(ra, cond, rs, rt, bd); |
2875 } | 2875 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2998 } | 2998 } |
2999 | 2999 |
3000 | 3000 |
3001 void MacroAssembler::Push(Handle<Object> handle) { | 3001 void MacroAssembler::Push(Handle<Object> handle) { |
3002 li(at, Operand(handle)); | 3002 li(at, Operand(handle)); |
3003 push(at); | 3003 push(at); |
3004 } | 3004 } |
3005 | 3005 |
3006 | 3006 |
3007 void MacroAssembler::PushRegisterAsTwoSmis(Register src, Register scratch) { | 3007 void MacroAssembler::PushRegisterAsTwoSmis(Register src, Register scratch) { |
3008 ASSERT(!src.is(scratch)); | 3008 DCHECK(!src.is(scratch)); |
3009 mov(scratch, src); | 3009 mov(scratch, src); |
3010 dsrl32(src, src, 0); | 3010 dsrl32(src, src, 0); |
3011 dsll32(src, src, 0); | 3011 dsll32(src, src, 0); |
3012 push(src); | 3012 push(src); |
3013 dsll32(scratch, scratch, 0); | 3013 dsll32(scratch, scratch, 0); |
3014 push(scratch); | 3014 push(scratch); |
3015 } | 3015 } |
3016 | 3016 |
3017 | 3017 |
3018 void MacroAssembler::PopRegisterAsTwoSmis(Register dst, Register scratch) { | 3018 void MacroAssembler::PopRegisterAsTwoSmis(Register dst, Register scratch) { |
3019 ASSERT(!dst.is(scratch)); | 3019 DCHECK(!dst.is(scratch)); |
3020 pop(scratch); | 3020 pop(scratch); |
3021 dsrl32(scratch, scratch, 0); | 3021 dsrl32(scratch, scratch, 0); |
3022 pop(dst); | 3022 pop(dst); |
3023 dsrl32(dst, dst, 0); | 3023 dsrl32(dst, dst, 0); |
3024 dsll32(dst, dst, 0); | 3024 dsll32(dst, dst, 0); |
3025 or_(dst, dst, scratch); | 3025 or_(dst, dst, scratch); |
3026 } | 3026 } |
3027 | 3027 |
3028 | 3028 |
3029 void MacroAssembler::DebugBreak() { | 3029 void MacroAssembler::DebugBreak() { |
3030 PrepareCEntryArgs(0); | 3030 PrepareCEntryArgs(0); |
3031 PrepareCEntryFunction(ExternalReference(Runtime::kDebugBreak, isolate())); | 3031 PrepareCEntryFunction(ExternalReference(Runtime::kDebugBreak, isolate())); |
3032 CEntryStub ces(isolate(), 1); | 3032 CEntryStub ces(isolate(), 1); |
3033 ASSERT(AllowThisStubCall(&ces)); | 3033 DCHECK(AllowThisStubCall(&ces)); |
3034 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 3034 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
3035 } | 3035 } |
3036 | 3036 |
3037 | 3037 |
3038 // --------------------------------------------------------------------------- | 3038 // --------------------------------------------------------------------------- |
3039 // Exception handling. | 3039 // Exception handling. |
3040 | 3040 |
3041 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, | 3041 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, |
3042 int handler_index) { | 3042 int handler_index) { |
3043 // Adjust this code if not the case. | 3043 // Adjust this code if not the case. |
3044 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 3044 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
3045 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 3045 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
3046 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); | 3046 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
3047 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); | 3047 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
3048 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); | 3048 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
3049 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); | 3049 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
3050 | 3050 |
3051 // For the JSEntry handler, we must preserve a0-a3 and s0. | 3051 // For the JSEntry handler, we must preserve a0-a3 and s0. |
3052 // a5-a7 are available. We will build up the handler from the bottom by | 3052 // a5-a7 are available. We will build up the handler from the bottom by |
3053 // pushing on the stack. | 3053 // pushing on the stack. |
3054 // Set up the code object (a5) and the state (a6) for pushing. | 3054 // Set up the code object (a5) and the state (a6) for pushing. |
3055 unsigned state = | 3055 unsigned state = |
3056 StackHandler::IndexField::encode(handler_index) | | 3056 StackHandler::IndexField::encode(handler_index) | |
3057 StackHandler::KindField::encode(kind); | 3057 StackHandler::KindField::encode(kind); |
3058 li(a5, Operand(CodeObject()), CONSTANT_SIZE); | 3058 li(a5, Operand(CodeObject()), CONSTANT_SIZE); |
3059 li(a6, Operand(state)); | 3059 li(a6, Operand(state)); |
3060 | 3060 |
3061 // Push the frame pointer, context, state, and code object. | 3061 // Push the frame pointer, context, state, and code object. |
3062 if (kind == StackHandler::JS_ENTRY) { | 3062 if (kind == StackHandler::JS_ENTRY) { |
3063 ASSERT_EQ(Smi::FromInt(0), 0); | 3063 DCHECK_EQ(Smi::FromInt(0), 0); |
3064 // The second zero_reg indicates no context. | 3064 // The second zero_reg indicates no context. |
3065 // The first zero_reg is the NULL frame pointer. | 3065 // The first zero_reg is the NULL frame pointer. |
3066 // The operands are reversed to match the order of MultiPush/Pop. | 3066 // The operands are reversed to match the order of MultiPush/Pop. |
3067 Push(zero_reg, zero_reg, a6, a5); | 3067 Push(zero_reg, zero_reg, a6, a5); |
3068 } else { | 3068 } else { |
3069 MultiPush(a5.bit() | a6.bit() | cp.bit() | fp.bit()); | 3069 MultiPush(a5.bit() | a6.bit() | cp.bit() | fp.bit()); |
3070 } | 3070 } |
3071 | 3071 |
3072 // Link the current handler as the next handler. | 3072 // Link the current handler as the next handler. |
3073 li(a6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 3073 li(a6, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3181 JumpToHandlerEntry(); | 3181 JumpToHandlerEntry(); |
3182 } | 3182 } |
3183 | 3183 |
3184 | 3184 |
3185 void MacroAssembler::Allocate(int object_size, | 3185 void MacroAssembler::Allocate(int object_size, |
3186 Register result, | 3186 Register result, |
3187 Register scratch1, | 3187 Register scratch1, |
3188 Register scratch2, | 3188 Register scratch2, |
3189 Label* gc_required, | 3189 Label* gc_required, |
3190 AllocationFlags flags) { | 3190 AllocationFlags flags) { |
3191 ASSERT(object_size <= Page::kMaxRegularHeapObjectSize); | 3191 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); |
3192 if (!FLAG_inline_new) { | 3192 if (!FLAG_inline_new) { |
3193 if (emit_debug_code()) { | 3193 if (emit_debug_code()) { |
3194 // Trash the registers to simulate an allocation failure. | 3194 // Trash the registers to simulate an allocation failure. |
3195 li(result, 0x7091); | 3195 li(result, 0x7091); |
3196 li(scratch1, 0x7191); | 3196 li(scratch1, 0x7191); |
3197 li(scratch2, 0x7291); | 3197 li(scratch2, 0x7291); |
3198 } | 3198 } |
3199 jmp(gc_required); | 3199 jmp(gc_required); |
3200 return; | 3200 return; |
3201 } | 3201 } |
3202 | 3202 |
3203 ASSERT(!result.is(scratch1)); | 3203 DCHECK(!result.is(scratch1)); |
3204 ASSERT(!result.is(scratch2)); | 3204 DCHECK(!result.is(scratch2)); |
3205 ASSERT(!scratch1.is(scratch2)); | 3205 DCHECK(!scratch1.is(scratch2)); |
3206 ASSERT(!scratch1.is(t9)); | 3206 DCHECK(!scratch1.is(t9)); |
3207 ASSERT(!scratch2.is(t9)); | 3207 DCHECK(!scratch2.is(t9)); |
3208 ASSERT(!result.is(t9)); | 3208 DCHECK(!result.is(t9)); |
3209 | 3209 |
3210 // Make object size into bytes. | 3210 // Make object size into bytes. |
3211 if ((flags & SIZE_IN_WORDS) != 0) { | 3211 if ((flags & SIZE_IN_WORDS) != 0) { |
3212 object_size *= kPointerSize; | 3212 object_size *= kPointerSize; |
3213 } | 3213 } |
3214 ASSERT(0 == (object_size & kObjectAlignmentMask)); | 3214 DCHECK(0 == (object_size & kObjectAlignmentMask)); |
3215 | 3215 |
3216 // Check relative positions of allocation top and limit addresses. | 3216 // Check relative positions of allocation top and limit addresses. |
3217 // ARM adds additional checks to make sure the ldm instruction can be | 3217 // ARM adds additional checks to make sure the ldm instruction can be |
3218 // used. On MIPS we don't have ldm so we don't need additional checks either. | 3218 // used. On MIPS we don't have ldm so we don't need additional checks either. |
3219 ExternalReference allocation_top = | 3219 ExternalReference allocation_top = |
3220 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3220 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
3221 ExternalReference allocation_limit = | 3221 ExternalReference allocation_limit = |
3222 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3222 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
3223 | 3223 |
3224 intptr_t top = | 3224 intptr_t top = |
3225 reinterpret_cast<intptr_t>(allocation_top.address()); | 3225 reinterpret_cast<intptr_t>(allocation_top.address()); |
3226 intptr_t limit = | 3226 intptr_t limit = |
3227 reinterpret_cast<intptr_t>(allocation_limit.address()); | 3227 reinterpret_cast<intptr_t>(allocation_limit.address()); |
3228 ASSERT((limit - top) == kPointerSize); | 3228 DCHECK((limit - top) == kPointerSize); |
3229 | 3229 |
3230 // Set up allocation top address and object size registers. | 3230 // Set up allocation top address and object size registers. |
3231 Register topaddr = scratch1; | 3231 Register topaddr = scratch1; |
3232 li(topaddr, Operand(allocation_top)); | 3232 li(topaddr, Operand(allocation_top)); |
3233 | 3233 |
3234 // This code stores a temporary value in t9. | 3234 // This code stores a temporary value in t9. |
3235 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3235 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
3236 // Load allocation top into result and allocation limit into t9. | 3236 // Load allocation top into result and allocation limit into t9. |
3237 ld(result, MemOperand(topaddr)); | 3237 ld(result, MemOperand(topaddr)); |
3238 ld(t9, MemOperand(topaddr, kPointerSize)); | 3238 ld(t9, MemOperand(topaddr, kPointerSize)); |
3239 } else { | 3239 } else { |
3240 if (emit_debug_code()) { | 3240 if (emit_debug_code()) { |
3241 // Assert that result actually contains top on entry. t9 is used | 3241 // Assert that result actually contains top on entry. t9 is used |
3242 // immediately below so this use of t9 does not cause difference with | 3242 // immediately below so this use of t9 does not cause difference with |
3243 // respect to register content between debug and release mode. | 3243 // respect to register content between debug and release mode. |
3244 ld(t9, MemOperand(topaddr)); | 3244 ld(t9, MemOperand(topaddr)); |
3245 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | 3245 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); |
3246 } | 3246 } |
3247 // Load allocation limit into t9. Result already contains allocation top. | 3247 // Load allocation limit into t9. Result already contains allocation top. |
3248 ld(t9, MemOperand(topaddr, limit - top)); | 3248 ld(t9, MemOperand(topaddr, limit - top)); |
3249 } | 3249 } |
3250 | 3250 |
3251 ASSERT(kPointerSize == kDoubleSize); | 3251 DCHECK(kPointerSize == kDoubleSize); |
3252 if (emit_debug_code()) { | 3252 if (emit_debug_code()) { |
3253 And(at, result, Operand(kDoubleAlignmentMask)); | 3253 And(at, result, Operand(kDoubleAlignmentMask)); |
3254 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); | 3254 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); |
3255 } | 3255 } |
3256 | 3256 |
3257 // Calculate new top and bail out if new space is exhausted. Use result | 3257 // Calculate new top and bail out if new space is exhausted. Use result |
3258 // to calculate the new top. | 3258 // to calculate the new top. |
3259 Daddu(scratch2, result, Operand(object_size)); | 3259 Daddu(scratch2, result, Operand(object_size)); |
3260 Branch(gc_required, Ugreater, scratch2, Operand(t9)); | 3260 Branch(gc_required, Ugreater, scratch2, Operand(t9)); |
3261 sd(scratch2, MemOperand(topaddr)); | 3261 sd(scratch2, MemOperand(topaddr)); |
(...skipping 15 matching lines...) Expand all Loading... |
3277 if (emit_debug_code()) { | 3277 if (emit_debug_code()) { |
3278 // Trash the registers to simulate an allocation failure. | 3278 // Trash the registers to simulate an allocation failure. |
3279 li(result, 0x7091); | 3279 li(result, 0x7091); |
3280 li(scratch1, 0x7191); | 3280 li(scratch1, 0x7191); |
3281 li(scratch2, 0x7291); | 3281 li(scratch2, 0x7291); |
3282 } | 3282 } |
3283 jmp(gc_required); | 3283 jmp(gc_required); |
3284 return; | 3284 return; |
3285 } | 3285 } |
3286 | 3286 |
3287 ASSERT(!result.is(scratch1)); | 3287 DCHECK(!result.is(scratch1)); |
3288 ASSERT(!result.is(scratch2)); | 3288 DCHECK(!result.is(scratch2)); |
3289 ASSERT(!scratch1.is(scratch2)); | 3289 DCHECK(!scratch1.is(scratch2)); |
3290 ASSERT(!object_size.is(t9)); | 3290 DCHECK(!object_size.is(t9)); |
3291 ASSERT(!scratch1.is(t9) && !scratch2.is(t9) && !result.is(t9)); | 3291 DCHECK(!scratch1.is(t9) && !scratch2.is(t9) && !result.is(t9)); |
3292 | 3292 |
3293 // Check relative positions of allocation top and limit addresses. | 3293 // Check relative positions of allocation top and limit addresses. |
3294 // ARM adds additional checks to make sure the ldm instruction can be | 3294 // ARM adds additional checks to make sure the ldm instruction can be |
3295 // used. On MIPS we don't have ldm so we don't need additional checks either. | 3295 // used. On MIPS we don't have ldm so we don't need additional checks either. |
3296 ExternalReference allocation_top = | 3296 ExternalReference allocation_top = |
3297 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3297 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
3298 ExternalReference allocation_limit = | 3298 ExternalReference allocation_limit = |
3299 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3299 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
3300 intptr_t top = | 3300 intptr_t top = |
3301 reinterpret_cast<intptr_t>(allocation_top.address()); | 3301 reinterpret_cast<intptr_t>(allocation_top.address()); |
3302 intptr_t limit = | 3302 intptr_t limit = |
3303 reinterpret_cast<intptr_t>(allocation_limit.address()); | 3303 reinterpret_cast<intptr_t>(allocation_limit.address()); |
3304 ASSERT((limit - top) == kPointerSize); | 3304 DCHECK((limit - top) == kPointerSize); |
3305 | 3305 |
3306 // Set up allocation top address and object size registers. | 3306 // Set up allocation top address and object size registers. |
3307 Register topaddr = scratch1; | 3307 Register topaddr = scratch1; |
3308 li(topaddr, Operand(allocation_top)); | 3308 li(topaddr, Operand(allocation_top)); |
3309 | 3309 |
3310 // This code stores a temporary value in t9. | 3310 // This code stores a temporary value in t9. |
3311 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3311 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
3312 // Load allocation top into result and allocation limit into t9. | 3312 // Load allocation top into result and allocation limit into t9. |
3313 ld(result, MemOperand(topaddr)); | 3313 ld(result, MemOperand(topaddr)); |
3314 ld(t9, MemOperand(topaddr, kPointerSize)); | 3314 ld(t9, MemOperand(topaddr, kPointerSize)); |
3315 } else { | 3315 } else { |
3316 if (emit_debug_code()) { | 3316 if (emit_debug_code()) { |
3317 // Assert that result actually contains top on entry. t9 is used | 3317 // Assert that result actually contains top on entry. t9 is used |
3318 // immediately below so this use of t9 does not cause difference with | 3318 // immediately below so this use of t9 does not cause difference with |
3319 // respect to register content between debug and release mode. | 3319 // respect to register content between debug and release mode. |
3320 ld(t9, MemOperand(topaddr)); | 3320 ld(t9, MemOperand(topaddr)); |
3321 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | 3321 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); |
3322 } | 3322 } |
3323 // Load allocation limit into t9. Result already contains allocation top. | 3323 // Load allocation limit into t9. Result already contains allocation top. |
3324 ld(t9, MemOperand(topaddr, limit - top)); | 3324 ld(t9, MemOperand(topaddr, limit - top)); |
3325 } | 3325 } |
3326 | 3326 |
3327 ASSERT(kPointerSize == kDoubleSize); | 3327 DCHECK(kPointerSize == kDoubleSize); |
3328 if (emit_debug_code()) { | 3328 if (emit_debug_code()) { |
3329 And(at, result, Operand(kDoubleAlignmentMask)); | 3329 And(at, result, Operand(kDoubleAlignmentMask)); |
3330 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); | 3330 Check(eq, kAllocationIsNotDoubleAligned, at, Operand(zero_reg)); |
3331 } | 3331 } |
3332 | 3332 |
3333 // Calculate new top and bail out if new space is exhausted. Use result | 3333 // Calculate new top and bail out if new space is exhausted. Use result |
3334 // to calculate the new top. Object size may be in words so a shift is | 3334 // to calculate the new top. Object size may be in words so a shift is |
3335 // required to get the number of bytes. | 3335 // required to get the number of bytes. |
3336 if ((flags & SIZE_IN_WORDS) != 0) { | 3336 if ((flags & SIZE_IN_WORDS) != 0) { |
3337 dsll(scratch2, object_size, kPointerSizeLog2); | 3337 dsll(scratch2, object_size, kPointerSizeLog2); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3376 | 3376 |
3377 | 3377 |
3378 void MacroAssembler::AllocateTwoByteString(Register result, | 3378 void MacroAssembler::AllocateTwoByteString(Register result, |
3379 Register length, | 3379 Register length, |
3380 Register scratch1, | 3380 Register scratch1, |
3381 Register scratch2, | 3381 Register scratch2, |
3382 Register scratch3, | 3382 Register scratch3, |
3383 Label* gc_required) { | 3383 Label* gc_required) { |
3384 // Calculate the number of bytes needed for the characters in the string while | 3384 // Calculate the number of bytes needed for the characters in the string while |
3385 // observing object alignment. | 3385 // observing object alignment. |
3386 ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3386 DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
3387 dsll(scratch1, length, 1); // Length in bytes, not chars. | 3387 dsll(scratch1, length, 1); // Length in bytes, not chars. |
3388 daddiu(scratch1, scratch1, | 3388 daddiu(scratch1, scratch1, |
3389 kObjectAlignmentMask + SeqTwoByteString::kHeaderSize); | 3389 kObjectAlignmentMask + SeqTwoByteString::kHeaderSize); |
3390 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); | 3390 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); |
3391 | 3391 |
3392 // Allocate two-byte string in new space. | 3392 // Allocate two-byte string in new space. |
3393 Allocate(scratch1, | 3393 Allocate(scratch1, |
3394 result, | 3394 result, |
3395 scratch2, | 3395 scratch2, |
3396 scratch3, | 3396 scratch3, |
(...skipping 10 matching lines...) Expand all Loading... |
3407 | 3407 |
3408 | 3408 |
3409 void MacroAssembler::AllocateAsciiString(Register result, | 3409 void MacroAssembler::AllocateAsciiString(Register result, |
3410 Register length, | 3410 Register length, |
3411 Register scratch1, | 3411 Register scratch1, |
3412 Register scratch2, | 3412 Register scratch2, |
3413 Register scratch3, | 3413 Register scratch3, |
3414 Label* gc_required) { | 3414 Label* gc_required) { |
3415 // Calculate the number of bytes needed for the characters in the string | 3415 // Calculate the number of bytes needed for the characters in the string |
3416 // while observing object alignment. | 3416 // while observing object alignment. |
3417 ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3417 DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
3418 ASSERT(kCharSize == 1); | 3418 DCHECK(kCharSize == 1); |
3419 daddiu(scratch1, length, | 3419 daddiu(scratch1, length, |
3420 kObjectAlignmentMask + SeqOneByteString::kHeaderSize); | 3420 kObjectAlignmentMask + SeqOneByteString::kHeaderSize); |
3421 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); | 3421 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); |
3422 | 3422 |
3423 // Allocate ASCII string in new space. | 3423 // Allocate ASCII string in new space. |
3424 Allocate(scratch1, | 3424 Allocate(scratch1, |
3425 result, | 3425 result, |
3426 scratch2, | 3426 scratch2, |
3427 scratch3, | 3427 scratch3, |
3428 gc_required, | 3428 gc_required, |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3553 AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required); | 3553 AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required); |
3554 sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset)); | 3554 sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset)); |
3555 } | 3555 } |
3556 | 3556 |
3557 | 3557 |
3558 // Copies a fixed number of fields of heap objects from src to dst. | 3558 // Copies a fixed number of fields of heap objects from src to dst. |
3559 void MacroAssembler::CopyFields(Register dst, | 3559 void MacroAssembler::CopyFields(Register dst, |
3560 Register src, | 3560 Register src, |
3561 RegList temps, | 3561 RegList temps, |
3562 int field_count) { | 3562 int field_count) { |
3563 ASSERT((temps & dst.bit()) == 0); | 3563 DCHECK((temps & dst.bit()) == 0); |
3564 ASSERT((temps & src.bit()) == 0); | 3564 DCHECK((temps & src.bit()) == 0); |
3565 // Primitive implementation using only one temporary register. | 3565 // Primitive implementation using only one temporary register. |
3566 | 3566 |
3567 Register tmp = no_reg; | 3567 Register tmp = no_reg; |
3568 // Find a temp register in temps list. | 3568 // Find a temp register in temps list. |
3569 for (int i = 0; i < kNumRegisters; i++) { | 3569 for (int i = 0; i < kNumRegisters; i++) { |
3570 if ((temps & (1 << i)) != 0) { | 3570 if ((temps & (1 << i)) != 0) { |
3571 tmp.code_ = i; | 3571 tmp.code_ = i; |
3572 break; | 3572 break; |
3573 } | 3573 } |
3574 } | 3574 } |
3575 ASSERT(!tmp.is(no_reg)); | 3575 DCHECK(!tmp.is(no_reg)); |
3576 | 3576 |
3577 for (int i = 0; i < field_count; i++) { | 3577 for (int i = 0; i < field_count; i++) { |
3578 ld(tmp, FieldMemOperand(src, i * kPointerSize)); | 3578 ld(tmp, FieldMemOperand(src, i * kPointerSize)); |
3579 sd(tmp, FieldMemOperand(dst, i * kPointerSize)); | 3579 sd(tmp, FieldMemOperand(dst, i * kPointerSize)); |
3580 } | 3580 } |
3581 } | 3581 } |
3582 | 3582 |
3583 | 3583 |
3584 void MacroAssembler::CopyBytes(Register src, | 3584 void MacroAssembler::CopyBytes(Register src, |
3585 Register dst, | 3585 Register dst, |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3866 Move(v0, v1, src); | 3866 Move(v0, v1, src); |
3867 } | 3867 } |
3868 } | 3868 } |
3869 | 3869 |
3870 | 3870 |
3871 void MacroAssembler::MovToFloatParameters(DoubleRegister src1, | 3871 void MacroAssembler::MovToFloatParameters(DoubleRegister src1, |
3872 DoubleRegister src2) { | 3872 DoubleRegister src2) { |
3873 if (!IsMipsSoftFloatABI) { | 3873 if (!IsMipsSoftFloatABI) { |
3874 const DoubleRegister fparg2 = (kMipsAbi == kN64) ? f13 : f14; | 3874 const DoubleRegister fparg2 = (kMipsAbi == kN64) ? f13 : f14; |
3875 if (src2.is(f12)) { | 3875 if (src2.is(f12)) { |
3876 ASSERT(!src1.is(fparg2)); | 3876 DCHECK(!src1.is(fparg2)); |
3877 Move(fparg2, src2); | 3877 Move(fparg2, src2); |
3878 Move(f12, src1); | 3878 Move(f12, src1); |
3879 } else { | 3879 } else { |
3880 Move(f12, src1); | 3880 Move(f12, src1); |
3881 Move(fparg2, src2); | 3881 Move(fparg2, src2); |
3882 } | 3882 } |
3883 } else { | 3883 } else { |
3884 Move(a0, a1, src1); | 3884 Move(a0, a1, src1); |
3885 Move(a2, a3, src2); | 3885 Move(a2, a3, src2); |
3886 } | 3886 } |
(...skipping 17 matching lines...) Expand all Loading... |
3904 | 3904 |
3905 // Check whether the expected and actual arguments count match. If not, | 3905 // Check whether the expected and actual arguments count match. If not, |
3906 // setup registers according to contract with ArgumentsAdaptorTrampoline: | 3906 // setup registers according to contract with ArgumentsAdaptorTrampoline: |
3907 // a0: actual arguments count | 3907 // a0: actual arguments count |
3908 // a1: function (passed through to callee) | 3908 // a1: function (passed through to callee) |
3909 // a2: expected arguments count | 3909 // a2: expected arguments count |
3910 | 3910 |
3911 // The code below is made a lot easier because the calling code already sets | 3911 // The code below is made a lot easier because the calling code already sets |
3912 // up actual and expected registers according to the contract if values are | 3912 // up actual and expected registers according to the contract if values are |
3913 // passed in registers. | 3913 // passed in registers. |
3914 ASSERT(actual.is_immediate() || actual.reg().is(a0)); | 3914 DCHECK(actual.is_immediate() || actual.reg().is(a0)); |
3915 ASSERT(expected.is_immediate() || expected.reg().is(a2)); | 3915 DCHECK(expected.is_immediate() || expected.reg().is(a2)); |
3916 ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(a3)); | 3916 DCHECK((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(a3)); |
3917 | 3917 |
3918 if (expected.is_immediate()) { | 3918 if (expected.is_immediate()) { |
3919 ASSERT(actual.is_immediate()); | 3919 DCHECK(actual.is_immediate()); |
3920 if (expected.immediate() == actual.immediate()) { | 3920 if (expected.immediate() == actual.immediate()) { |
3921 definitely_matches = true; | 3921 definitely_matches = true; |
3922 } else { | 3922 } else { |
3923 li(a0, Operand(actual.immediate())); | 3923 li(a0, Operand(actual.immediate())); |
3924 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3924 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
3925 if (expected.immediate() == sentinel) { | 3925 if (expected.immediate() == sentinel) { |
3926 // Don't worry about adapting arguments for builtins that | 3926 // Don't worry about adapting arguments for builtins that |
3927 // don't want that done. Skip adaption code by making it look | 3927 // don't want that done. Skip adaption code by making it look |
3928 // like we have a match between expected and actual number of | 3928 // like we have a match between expected and actual number of |
3929 // arguments. | 3929 // arguments. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3962 } | 3962 } |
3963 } | 3963 } |
3964 | 3964 |
3965 | 3965 |
3966 void MacroAssembler::InvokeCode(Register code, | 3966 void MacroAssembler::InvokeCode(Register code, |
3967 const ParameterCount& expected, | 3967 const ParameterCount& expected, |
3968 const ParameterCount& actual, | 3968 const ParameterCount& actual, |
3969 InvokeFlag flag, | 3969 InvokeFlag flag, |
3970 const CallWrapper& call_wrapper) { | 3970 const CallWrapper& call_wrapper) { |
3971 // You can't call a function without a valid frame. | 3971 // You can't call a function without a valid frame. |
3972 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3972 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
3973 | 3973 |
3974 Label done; | 3974 Label done; |
3975 | 3975 |
3976 bool definitely_mismatches = false; | 3976 bool definitely_mismatches = false; |
3977 InvokePrologue(expected, actual, Handle<Code>::null(), code, | 3977 InvokePrologue(expected, actual, Handle<Code>::null(), code, |
3978 &done, &definitely_mismatches, flag, | 3978 &done, &definitely_mismatches, flag, |
3979 call_wrapper); | 3979 call_wrapper); |
3980 if (!definitely_mismatches) { | 3980 if (!definitely_mismatches) { |
3981 if (flag == CALL_FUNCTION) { | 3981 if (flag == CALL_FUNCTION) { |
3982 call_wrapper.BeforeCall(CallSize(code)); | 3982 call_wrapper.BeforeCall(CallSize(code)); |
3983 Call(code); | 3983 Call(code); |
3984 call_wrapper.AfterCall(); | 3984 call_wrapper.AfterCall(); |
3985 } else { | 3985 } else { |
3986 ASSERT(flag == JUMP_FUNCTION); | 3986 DCHECK(flag == JUMP_FUNCTION); |
3987 Jump(code); | 3987 Jump(code); |
3988 } | 3988 } |
3989 // Continue here if InvokePrologue does handle the invocation due to | 3989 // Continue here if InvokePrologue does handle the invocation due to |
3990 // mismatched parameter counts. | 3990 // mismatched parameter counts. |
3991 bind(&done); | 3991 bind(&done); |
3992 } | 3992 } |
3993 } | 3993 } |
3994 | 3994 |
3995 | 3995 |
3996 void MacroAssembler::InvokeFunction(Register function, | 3996 void MacroAssembler::InvokeFunction(Register function, |
3997 const ParameterCount& actual, | 3997 const ParameterCount& actual, |
3998 InvokeFlag flag, | 3998 InvokeFlag flag, |
3999 const CallWrapper& call_wrapper) { | 3999 const CallWrapper& call_wrapper) { |
4000 // You can't call a function without a valid frame. | 4000 // You can't call a function without a valid frame. |
4001 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 4001 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
4002 | 4002 |
4003 // Contract with called JS functions requires that function is passed in a1. | 4003 // Contract with called JS functions requires that function is passed in a1. |
4004 ASSERT(function.is(a1)); | 4004 DCHECK(function.is(a1)); |
4005 Register expected_reg = a2; | 4005 Register expected_reg = a2; |
4006 Register code_reg = a3; | 4006 Register code_reg = a3; |
4007 ld(code_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 4007 ld(code_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
4008 ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 4008 ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
4009 // The argument count is stored as int32_t on 64-bit platforms. | 4009 // The argument count is stored as int32_t on 64-bit platforms. |
4010 // TODO(plind): Smi on 32-bit platforms. | 4010 // TODO(plind): Smi on 32-bit platforms. |
4011 lw(expected_reg, | 4011 lw(expected_reg, |
4012 FieldMemOperand(code_reg, | 4012 FieldMemOperand(code_reg, |
4013 SharedFunctionInfo::kFormalParameterCountOffset)); | 4013 SharedFunctionInfo::kFormalParameterCountOffset)); |
4014 ld(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 4014 ld(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
4015 ParameterCount expected(expected_reg); | 4015 ParameterCount expected(expected_reg); |
4016 InvokeCode(code_reg, expected, actual, flag, call_wrapper); | 4016 InvokeCode(code_reg, expected, actual, flag, call_wrapper); |
4017 } | 4017 } |
4018 | 4018 |
4019 | 4019 |
4020 void MacroAssembler::InvokeFunction(Register function, | 4020 void MacroAssembler::InvokeFunction(Register function, |
4021 const ParameterCount& expected, | 4021 const ParameterCount& expected, |
4022 const ParameterCount& actual, | 4022 const ParameterCount& actual, |
4023 InvokeFlag flag, | 4023 InvokeFlag flag, |
4024 const CallWrapper& call_wrapper) { | 4024 const CallWrapper& call_wrapper) { |
4025 // You can't call a function without a valid frame. | 4025 // You can't call a function without a valid frame. |
4026 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 4026 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
4027 | 4027 |
4028 // Contract with called JS functions requires that function is passed in a1. | 4028 // Contract with called JS functions requires that function is passed in a1. |
4029 ASSERT(function.is(a1)); | 4029 DCHECK(function.is(a1)); |
4030 | 4030 |
4031 // Get the function and setup the context. | 4031 // Get the function and setup the context. |
4032 ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 4032 ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
4033 | 4033 |
4034 // We call indirectly through the code field in the function to | 4034 // We call indirectly through the code field in the function to |
4035 // allow recompilation to take effect without changing any of the | 4035 // allow recompilation to take effect without changing any of the |
4036 // call sites. | 4036 // call sites. |
4037 ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 4037 ld(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
4038 InvokeCode(a3, expected, actual, flag, call_wrapper); | 4038 InvokeCode(a3, expected, actual, flag, call_wrapper); |
4039 } | 4039 } |
(...skipping 23 matching lines...) Expand all Loading... |
4063 Label* fail) { | 4063 Label* fail) { |
4064 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 4064 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
4065 Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 4065 Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
4066 Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 4066 Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
4067 } | 4067 } |
4068 | 4068 |
4069 | 4069 |
4070 void MacroAssembler::IsObjectJSStringType(Register object, | 4070 void MacroAssembler::IsObjectJSStringType(Register object, |
4071 Register scratch, | 4071 Register scratch, |
4072 Label* fail) { | 4072 Label* fail) { |
4073 ASSERT(kNotStringTag != 0); | 4073 DCHECK(kNotStringTag != 0); |
4074 | 4074 |
4075 ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 4075 ld(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
4076 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 4076 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
4077 And(scratch, scratch, Operand(kIsNotStringMask)); | 4077 And(scratch, scratch, Operand(kIsNotStringMask)); |
4078 Branch(fail, ne, scratch, Operand(zero_reg)); | 4078 Branch(fail, ne, scratch, Operand(zero_reg)); |
4079 } | 4079 } |
4080 | 4080 |
4081 | 4081 |
4082 void MacroAssembler::IsObjectNameType(Register object, | 4082 void MacroAssembler::IsObjectNameType(Register object, |
4083 Register scratch, | 4083 Register scratch, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4162 | 4162 |
4163 // ----------------------------------------------------------------------------- | 4163 // ----------------------------------------------------------------------------- |
4164 // Runtime calls. | 4164 // Runtime calls. |
4165 | 4165 |
4166 void MacroAssembler::CallStub(CodeStub* stub, | 4166 void MacroAssembler::CallStub(CodeStub* stub, |
4167 TypeFeedbackId ast_id, | 4167 TypeFeedbackId ast_id, |
4168 Condition cond, | 4168 Condition cond, |
4169 Register r1, | 4169 Register r1, |
4170 const Operand& r2, | 4170 const Operand& r2, |
4171 BranchDelaySlot bd) { | 4171 BranchDelaySlot bd) { |
4172 ASSERT(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. | 4172 DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. |
4173 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, | 4173 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, |
4174 cond, r1, r2, bd); | 4174 cond, r1, r2, bd); |
4175 } | 4175 } |
4176 | 4176 |
4177 | 4177 |
4178 void MacroAssembler::TailCallStub(CodeStub* stub, | 4178 void MacroAssembler::TailCallStub(CodeStub* stub, |
4179 Condition cond, | 4179 Condition cond, |
4180 Register r1, | 4180 Register r1, |
4181 const Operand& r2, | 4181 const Operand& r2, |
4182 BranchDelaySlot bd) { | 4182 BranchDelaySlot bd) { |
4183 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2, bd); | 4183 Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond, r1, r2, bd); |
4184 } | 4184 } |
4185 | 4185 |
4186 | 4186 |
4187 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | 4187 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
4188 int64_t offset = (ref0.address() - ref1.address()); | 4188 int64_t offset = (ref0.address() - ref1.address()); |
4189 ASSERT(static_cast<int>(offset) == offset); | 4189 DCHECK(static_cast<int>(offset) == offset); |
4190 return static_cast<int>(offset); | 4190 return static_cast<int>(offset); |
4191 } | 4191 } |
4192 | 4192 |
4193 | 4193 |
4194 void MacroAssembler::CallApiFunctionAndReturn( | 4194 void MacroAssembler::CallApiFunctionAndReturn( |
4195 Register function_address, | 4195 Register function_address, |
4196 ExternalReference thunk_ref, | 4196 ExternalReference thunk_ref, |
4197 int stack_space, | 4197 int stack_space, |
4198 MemOperand return_value_operand, | 4198 MemOperand return_value_operand, |
4199 MemOperand* context_restore_operand) { | 4199 MemOperand* context_restore_operand) { |
4200 ExternalReference next_address = | 4200 ExternalReference next_address = |
4201 ExternalReference::handle_scope_next_address(isolate()); | 4201 ExternalReference::handle_scope_next_address(isolate()); |
4202 const int kNextOffset = 0; | 4202 const int kNextOffset = 0; |
4203 const int kLimitOffset = AddressOffset( | 4203 const int kLimitOffset = AddressOffset( |
4204 ExternalReference::handle_scope_limit_address(isolate()), | 4204 ExternalReference::handle_scope_limit_address(isolate()), |
4205 next_address); | 4205 next_address); |
4206 const int kLevelOffset = AddressOffset( | 4206 const int kLevelOffset = AddressOffset( |
4207 ExternalReference::handle_scope_level_address(isolate()), | 4207 ExternalReference::handle_scope_level_address(isolate()), |
4208 next_address); | 4208 next_address); |
4209 | 4209 |
4210 ASSERT(function_address.is(a1) || function_address.is(a2)); | 4210 DCHECK(function_address.is(a1) || function_address.is(a2)); |
4211 | 4211 |
4212 Label profiler_disabled; | 4212 Label profiler_disabled; |
4213 Label end_profiler_check; | 4213 Label end_profiler_check; |
4214 li(t9, Operand(ExternalReference::is_profiling_address(isolate()))); | 4214 li(t9, Operand(ExternalReference::is_profiling_address(isolate()))); |
4215 lb(t9, MemOperand(t9, 0)); | 4215 lb(t9, MemOperand(t9, 0)); |
4216 Branch(&profiler_disabled, eq, t9, Operand(zero_reg)); | 4216 Branch(&profiler_disabled, eq, t9, Operand(zero_reg)); |
4217 | 4217 |
4218 // Additional parameter is the address of the actual callback. | 4218 // Additional parameter is the address of the actual callback. |
4219 li(t9, Operand(thunk_ref)); | 4219 li(t9, Operand(thunk_ref)); |
4220 jmp(&end_profiler_check); | 4220 jmp(&end_profiler_check); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4318 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { | 4318 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { |
4319 return has_frame_ || !stub->SometimesSetsUpAFrame(); | 4319 return has_frame_ || !stub->SometimesSetsUpAFrame(); |
4320 } | 4320 } |
4321 | 4321 |
4322 | 4322 |
4323 void MacroAssembler::IndexFromHash(Register hash, Register index) { | 4323 void MacroAssembler::IndexFromHash(Register hash, Register index) { |
4324 // If the hash field contains an array index pick it out. The assert checks | 4324 // If the hash field contains an array index pick it out. The assert checks |
4325 // that the constants for the maximum number of digits for an array index | 4325 // that the constants for the maximum number of digits for an array index |
4326 // cached in the hash field and the number of bits reserved for it does not | 4326 // cached in the hash field and the number of bits reserved for it does not |
4327 // conflict. | 4327 // conflict. |
4328 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 4328 DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) < |
4329 (1 << String::kArrayIndexValueBits)); | 4329 (1 << String::kArrayIndexValueBits)); |
4330 DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash); | 4330 DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash); |
4331 } | 4331 } |
4332 | 4332 |
4333 | 4333 |
4334 void MacroAssembler::ObjectToDoubleFPURegister(Register object, | 4334 void MacroAssembler::ObjectToDoubleFPURegister(Register object, |
4335 FPURegister result, | 4335 FPURegister result, |
4336 Register scratch1, | 4336 Register scratch1, |
4337 Register scratch2, | 4337 Register scratch2, |
4338 Register heap_number_map, | 4338 Register heap_number_map, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4377 mtc1(scratch1, value); | 4377 mtc1(scratch1, value); |
4378 cvt_d_w(value, value); | 4378 cvt_d_w(value, value); |
4379 } | 4379 } |
4380 | 4380 |
4381 | 4381 |
4382 void MacroAssembler::AdduAndCheckForOverflow(Register dst, | 4382 void MacroAssembler::AdduAndCheckForOverflow(Register dst, |
4383 Register left, | 4383 Register left, |
4384 Register right, | 4384 Register right, |
4385 Register overflow_dst, | 4385 Register overflow_dst, |
4386 Register scratch) { | 4386 Register scratch) { |
4387 ASSERT(!dst.is(overflow_dst)); | 4387 DCHECK(!dst.is(overflow_dst)); |
4388 ASSERT(!dst.is(scratch)); | 4388 DCHECK(!dst.is(scratch)); |
4389 ASSERT(!overflow_dst.is(scratch)); | 4389 DCHECK(!overflow_dst.is(scratch)); |
4390 ASSERT(!overflow_dst.is(left)); | 4390 DCHECK(!overflow_dst.is(left)); |
4391 ASSERT(!overflow_dst.is(right)); | 4391 DCHECK(!overflow_dst.is(right)); |
4392 | 4392 |
4393 if (left.is(right) && dst.is(left)) { | 4393 if (left.is(right) && dst.is(left)) { |
4394 ASSERT(!dst.is(t9)); | 4394 DCHECK(!dst.is(t9)); |
4395 ASSERT(!scratch.is(t9)); | 4395 DCHECK(!scratch.is(t9)); |
4396 ASSERT(!left.is(t9)); | 4396 DCHECK(!left.is(t9)); |
4397 ASSERT(!right.is(t9)); | 4397 DCHECK(!right.is(t9)); |
4398 ASSERT(!overflow_dst.is(t9)); | 4398 DCHECK(!overflow_dst.is(t9)); |
4399 mov(t9, right); | 4399 mov(t9, right); |
4400 right = t9; | 4400 right = t9; |
4401 } | 4401 } |
4402 | 4402 |
4403 if (dst.is(left)) { | 4403 if (dst.is(left)) { |
4404 mov(scratch, left); // Preserve left. | 4404 mov(scratch, left); // Preserve left. |
4405 daddu(dst, left, right); // Left is overwritten. | 4405 daddu(dst, left, right); // Left is overwritten. |
4406 xor_(scratch, dst, scratch); // Original left. | 4406 xor_(scratch, dst, scratch); // Original left. |
4407 xor_(overflow_dst, dst, right); | 4407 xor_(overflow_dst, dst, right); |
4408 and_(overflow_dst, overflow_dst, scratch); | 4408 and_(overflow_dst, overflow_dst, scratch); |
(...skipping 10 matching lines...) Expand all Loading... |
4419 and_(overflow_dst, scratch, overflow_dst); | 4419 and_(overflow_dst, scratch, overflow_dst); |
4420 } | 4420 } |
4421 } | 4421 } |
4422 | 4422 |
4423 | 4423 |
4424 void MacroAssembler::SubuAndCheckForOverflow(Register dst, | 4424 void MacroAssembler::SubuAndCheckForOverflow(Register dst, |
4425 Register left, | 4425 Register left, |
4426 Register right, | 4426 Register right, |
4427 Register overflow_dst, | 4427 Register overflow_dst, |
4428 Register scratch) { | 4428 Register scratch) { |
4429 ASSERT(!dst.is(overflow_dst)); | 4429 DCHECK(!dst.is(overflow_dst)); |
4430 ASSERT(!dst.is(scratch)); | 4430 DCHECK(!dst.is(scratch)); |
4431 ASSERT(!overflow_dst.is(scratch)); | 4431 DCHECK(!overflow_dst.is(scratch)); |
4432 ASSERT(!overflow_dst.is(left)); | 4432 DCHECK(!overflow_dst.is(left)); |
4433 ASSERT(!overflow_dst.is(right)); | 4433 DCHECK(!overflow_dst.is(right)); |
4434 ASSERT(!scratch.is(left)); | 4434 DCHECK(!scratch.is(left)); |
4435 ASSERT(!scratch.is(right)); | 4435 DCHECK(!scratch.is(right)); |
4436 | 4436 |
4437 // This happens with some crankshaft code. Since Subu works fine if | 4437 // This happens with some crankshaft code. Since Subu works fine if |
4438 // left == right, let's not make that restriction here. | 4438 // left == right, let's not make that restriction here. |
4439 if (left.is(right)) { | 4439 if (left.is(right)) { |
4440 mov(dst, zero_reg); | 4440 mov(dst, zero_reg); |
4441 mov(overflow_dst, zero_reg); | 4441 mov(overflow_dst, zero_reg); |
4442 return; | 4442 return; |
4443 } | 4443 } |
4444 | 4444 |
4445 if (dst.is(left)) { | 4445 if (dst.is(left)) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4526 zero_reg, | 4526 zero_reg, |
4527 Operand(zero_reg), | 4527 Operand(zero_reg), |
4528 bd); | 4528 bd); |
4529 } | 4529 } |
4530 | 4530 |
4531 | 4531 |
4532 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 4532 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
4533 InvokeFlag flag, | 4533 InvokeFlag flag, |
4534 const CallWrapper& call_wrapper) { | 4534 const CallWrapper& call_wrapper) { |
4535 // You can't call a builtin without a valid frame. | 4535 // You can't call a builtin without a valid frame. |
4536 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 4536 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
4537 | 4537 |
4538 GetBuiltinEntry(t9, id); | 4538 GetBuiltinEntry(t9, id); |
4539 if (flag == CALL_FUNCTION) { | 4539 if (flag == CALL_FUNCTION) { |
4540 call_wrapper.BeforeCall(CallSize(t9)); | 4540 call_wrapper.BeforeCall(CallSize(t9)); |
4541 Call(t9); | 4541 Call(t9); |
4542 call_wrapper.AfterCall(); | 4542 call_wrapper.AfterCall(); |
4543 } else { | 4543 } else { |
4544 ASSERT(flag == JUMP_FUNCTION); | 4544 DCHECK(flag == JUMP_FUNCTION); |
4545 Jump(t9); | 4545 Jump(t9); |
4546 } | 4546 } |
4547 } | 4547 } |
4548 | 4548 |
4549 | 4549 |
4550 void MacroAssembler::GetBuiltinFunction(Register target, | 4550 void MacroAssembler::GetBuiltinFunction(Register target, |
4551 Builtins::JavaScript id) { | 4551 Builtins::JavaScript id) { |
4552 // Load the builtins object into target register. | 4552 // Load the builtins object into target register. |
4553 ld(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 4553 ld(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
4554 ld(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); | 4554 ld(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); |
4555 // Load the JavaScript builtin function from the builtins object. | 4555 // Load the JavaScript builtin function from the builtins object. |
4556 ld(target, FieldMemOperand(target, | 4556 ld(target, FieldMemOperand(target, |
4557 JSBuiltinsObject::OffsetOfFunctionWithId(id))); | 4557 JSBuiltinsObject::OffsetOfFunctionWithId(id))); |
4558 } | 4558 } |
4559 | 4559 |
4560 | 4560 |
4561 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { | 4561 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { |
4562 ASSERT(!target.is(a1)); | 4562 DCHECK(!target.is(a1)); |
4563 GetBuiltinFunction(a1, id); | 4563 GetBuiltinFunction(a1, id); |
4564 // Load the code entry point from the builtins object. | 4564 // Load the code entry point from the builtins object. |
4565 ld(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 4565 ld(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
4566 } | 4566 } |
4567 | 4567 |
4568 | 4568 |
4569 void MacroAssembler::SetCounter(StatsCounter* counter, int value, | 4569 void MacroAssembler::SetCounter(StatsCounter* counter, int value, |
4570 Register scratch1, Register scratch2) { | 4570 Register scratch1, Register scratch2) { |
4571 if (FLAG_native_code_counters && counter->Enabled()) { | 4571 if (FLAG_native_code_counters && counter->Enabled()) { |
4572 li(scratch1, Operand(value)); | 4572 li(scratch1, Operand(value)); |
4573 li(scratch2, Operand(ExternalReference(counter))); | 4573 li(scratch2, Operand(ExternalReference(counter))); |
4574 sd(scratch1, MemOperand(scratch2)); | 4574 sd(scratch1, MemOperand(scratch2)); |
4575 } | 4575 } |
4576 } | 4576 } |
4577 | 4577 |
4578 | 4578 |
4579 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value, | 4579 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value, |
4580 Register scratch1, Register scratch2) { | 4580 Register scratch1, Register scratch2) { |
4581 ASSERT(value > 0); | 4581 DCHECK(value > 0); |
4582 if (FLAG_native_code_counters && counter->Enabled()) { | 4582 if (FLAG_native_code_counters && counter->Enabled()) { |
4583 li(scratch2, Operand(ExternalReference(counter))); | 4583 li(scratch2, Operand(ExternalReference(counter))); |
4584 ld(scratch1, MemOperand(scratch2)); | 4584 ld(scratch1, MemOperand(scratch2)); |
4585 Daddu(scratch1, scratch1, Operand(value)); | 4585 Daddu(scratch1, scratch1, Operand(value)); |
4586 sd(scratch1, MemOperand(scratch2)); | 4586 sd(scratch1, MemOperand(scratch2)); |
4587 } | 4587 } |
4588 } | 4588 } |
4589 | 4589 |
4590 | 4590 |
4591 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value, | 4591 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value, |
4592 Register scratch1, Register scratch2) { | 4592 Register scratch1, Register scratch2) { |
4593 ASSERT(value > 0); | 4593 DCHECK(value > 0); |
4594 if (FLAG_native_code_counters && counter->Enabled()) { | 4594 if (FLAG_native_code_counters && counter->Enabled()) { |
4595 li(scratch2, Operand(ExternalReference(counter))); | 4595 li(scratch2, Operand(ExternalReference(counter))); |
4596 ld(scratch1, MemOperand(scratch2)); | 4596 ld(scratch1, MemOperand(scratch2)); |
4597 Dsubu(scratch1, scratch1, Operand(value)); | 4597 Dsubu(scratch1, scratch1, Operand(value)); |
4598 sd(scratch1, MemOperand(scratch2)); | 4598 sd(scratch1, MemOperand(scratch2)); |
4599 } | 4599 } |
4600 } | 4600 } |
4601 | 4601 |
4602 | 4602 |
4603 // ----------------------------------------------------------------------------- | 4603 // ----------------------------------------------------------------------------- |
4604 // Debugging. | 4604 // Debugging. |
4605 | 4605 |
4606 void MacroAssembler::Assert(Condition cc, BailoutReason reason, | 4606 void MacroAssembler::Assert(Condition cc, BailoutReason reason, |
4607 Register rs, Operand rt) { | 4607 Register rs, Operand rt) { |
4608 if (emit_debug_code()) | 4608 if (emit_debug_code()) |
4609 Check(cc, reason, rs, rt); | 4609 Check(cc, reason, rs, rt); |
4610 } | 4610 } |
4611 | 4611 |
4612 | 4612 |
4613 void MacroAssembler::AssertFastElements(Register elements) { | 4613 void MacroAssembler::AssertFastElements(Register elements) { |
4614 if (emit_debug_code()) { | 4614 if (emit_debug_code()) { |
4615 ASSERT(!elements.is(at)); | 4615 DCHECK(!elements.is(at)); |
4616 Label ok; | 4616 Label ok; |
4617 push(elements); | 4617 push(elements); |
4618 ld(elements, FieldMemOperand(elements, HeapObject::kMapOffset)); | 4618 ld(elements, FieldMemOperand(elements, HeapObject::kMapOffset)); |
4619 LoadRoot(at, Heap::kFixedArrayMapRootIndex); | 4619 LoadRoot(at, Heap::kFixedArrayMapRootIndex); |
4620 Branch(&ok, eq, elements, Operand(at)); | 4620 Branch(&ok, eq, elements, Operand(at)); |
4621 LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); | 4621 LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); |
4622 Branch(&ok, eq, elements, Operand(at)); | 4622 Branch(&ok, eq, elements, Operand(at)); |
4623 LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex); | 4623 LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex); |
4624 Branch(&ok, eq, elements, Operand(at)); | 4624 Branch(&ok, eq, elements, Operand(at)); |
4625 Abort(kJSObjectWithFastElementsMapHasSlowElements); | 4625 Abort(kJSObjectWithFastElementsMapHasSlowElements); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4668 } | 4668 } |
4669 // Will not return here. | 4669 // Will not return here. |
4670 if (is_trampoline_pool_blocked()) { | 4670 if (is_trampoline_pool_blocked()) { |
4671 // If the calling code cares about the exact number of | 4671 // If the calling code cares about the exact number of |
4672 // instructions generated, we insert padding here to keep the size | 4672 // instructions generated, we insert padding here to keep the size |
4673 // of the Abort macro constant. | 4673 // of the Abort macro constant. |
4674 // Currently in debug mode with debug_code enabled the number of | 4674 // Currently in debug mode with debug_code enabled the number of |
4675 // generated instructions is 10, so we use this as a maximum value. | 4675 // generated instructions is 10, so we use this as a maximum value. |
4676 static const int kExpectedAbortInstructions = 10; | 4676 static const int kExpectedAbortInstructions = 10; |
4677 int abort_instructions = InstructionsGeneratedSince(&abort_start); | 4677 int abort_instructions = InstructionsGeneratedSince(&abort_start); |
4678 ASSERT(abort_instructions <= kExpectedAbortInstructions); | 4678 DCHECK(abort_instructions <= kExpectedAbortInstructions); |
4679 while (abort_instructions++ < kExpectedAbortInstructions) { | 4679 while (abort_instructions++ < kExpectedAbortInstructions) { |
4680 nop(); | 4680 nop(); |
4681 } | 4681 } |
4682 } | 4682 } |
4683 } | 4683 } |
4684 | 4684 |
4685 | 4685 |
4686 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 4686 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
4687 if (context_chain_length > 0) { | 4687 if (context_chain_length > 0) { |
4688 // Move up the chain of contexts to the context containing the slot. | 4688 // Move up the chain of contexts to the context containing the slot. |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4859 // Remember: we only need to save every 2nd double FPU value. | 4859 // Remember: we only need to save every 2nd double FPU value. |
4860 for (int i = 0; i < kNumOfSavedRegisters; i++) { | 4860 for (int i = 0; i < kNumOfSavedRegisters; i++) { |
4861 FPURegister reg = FPURegister::from_code(2 * i); | 4861 FPURegister reg = FPURegister::from_code(2 * i); |
4862 sdc1(reg, MemOperand(sp, i * kDoubleSize)); | 4862 sdc1(reg, MemOperand(sp, i * kDoubleSize)); |
4863 } | 4863 } |
4864 } | 4864 } |
4865 | 4865 |
4866 // Reserve place for the return address, stack space and an optional slot | 4866 // Reserve place for the return address, stack space and an optional slot |
4867 // (used by the DirectCEntryStub to hold the return value if a struct is | 4867 // (used by the DirectCEntryStub to hold the return value if a struct is |
4868 // returned) and align the frame preparing for calling the runtime function. | 4868 // returned) and align the frame preparing for calling the runtime function. |
4869 ASSERT(stack_space >= 0); | 4869 DCHECK(stack_space >= 0); |
4870 Dsubu(sp, sp, Operand((stack_space + 2) * kPointerSize)); | 4870 Dsubu(sp, sp, Operand((stack_space + 2) * kPointerSize)); |
4871 if (frame_alignment > 0) { | 4871 if (frame_alignment > 0) { |
4872 ASSERT(IsPowerOf2(frame_alignment)); | 4872 DCHECK(IsPowerOf2(frame_alignment)); |
4873 And(sp, sp, Operand(-frame_alignment)); // Align stack. | 4873 And(sp, sp, Operand(-frame_alignment)); // Align stack. |
4874 } | 4874 } |
4875 | 4875 |
4876 // Set the exit frame sp value to point just before the return address | 4876 // Set the exit frame sp value to point just before the return address |
4877 // location. | 4877 // location. |
4878 daddiu(at, sp, kPointerSize); | 4878 daddiu(at, sp, kPointerSize); |
4879 sd(at, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 4879 sd(at, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
4880 } | 4880 } |
4881 | 4881 |
4882 | 4882 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4960 } | 4960 } |
4961 | 4961 |
4962 | 4962 |
4963 void MacroAssembler::AssertStackIsAligned() { | 4963 void MacroAssembler::AssertStackIsAligned() { |
4964 if (emit_debug_code()) { | 4964 if (emit_debug_code()) { |
4965 const int frame_alignment = ActivationFrameAlignment(); | 4965 const int frame_alignment = ActivationFrameAlignment(); |
4966 const int frame_alignment_mask = frame_alignment - 1; | 4966 const int frame_alignment_mask = frame_alignment - 1; |
4967 | 4967 |
4968 if (frame_alignment > kPointerSize) { | 4968 if (frame_alignment > kPointerSize) { |
4969 Label alignment_as_expected; | 4969 Label alignment_as_expected; |
4970 ASSERT(IsPowerOf2(frame_alignment)); | 4970 DCHECK(IsPowerOf2(frame_alignment)); |
4971 andi(at, sp, frame_alignment_mask); | 4971 andi(at, sp, frame_alignment_mask); |
4972 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); | 4972 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); |
4973 // Don't use Check here, as it will call Runtime_Abort re-entering here. | 4973 // Don't use Check here, as it will call Runtime_Abort re-entering here. |
4974 stop("Unexpected stack alignment"); | 4974 stop("Unexpected stack alignment"); |
4975 bind(&alignment_as_expected); | 4975 bind(&alignment_as_expected); |
4976 } | 4976 } |
4977 } | 4977 } |
4978 } | 4978 } |
4979 | 4979 |
4980 | 4980 |
4981 void MacroAssembler::JumpIfNotPowerOfTwoOrZero( | 4981 void MacroAssembler::JumpIfNotPowerOfTwoOrZero( |
4982 Register reg, | 4982 Register reg, |
4983 Register scratch, | 4983 Register scratch, |
4984 Label* not_power_of_two_or_zero) { | 4984 Label* not_power_of_two_or_zero) { |
4985 Dsubu(scratch, reg, Operand(1)); | 4985 Dsubu(scratch, reg, Operand(1)); |
4986 Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt, | 4986 Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt, |
4987 scratch, Operand(zero_reg)); | 4987 scratch, Operand(zero_reg)); |
4988 and_(at, scratch, reg); // In the delay slot. | 4988 and_(at, scratch, reg); // In the delay slot. |
4989 Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg)); | 4989 Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg)); |
4990 } | 4990 } |
4991 | 4991 |
4992 | 4992 |
4993 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) { | 4993 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) { |
4994 ASSERT(!reg.is(overflow)); | 4994 DCHECK(!reg.is(overflow)); |
4995 mov(overflow, reg); // Save original value. | 4995 mov(overflow, reg); // Save original value. |
4996 SmiTag(reg); | 4996 SmiTag(reg); |
4997 xor_(overflow, overflow, reg); // Overflow if (value ^ 2 * value) < 0. | 4997 xor_(overflow, overflow, reg); // Overflow if (value ^ 2 * value) < 0. |
4998 } | 4998 } |
4999 | 4999 |
5000 | 5000 |
5001 void MacroAssembler::SmiTagCheckOverflow(Register dst, | 5001 void MacroAssembler::SmiTagCheckOverflow(Register dst, |
5002 Register src, | 5002 Register src, |
5003 Register overflow) { | 5003 Register overflow) { |
5004 if (dst.is(src)) { | 5004 if (dst.is(src)) { |
5005 // Fall back to slower case. | 5005 // Fall back to slower case. |
5006 SmiTagCheckOverflow(dst, overflow); | 5006 SmiTagCheckOverflow(dst, overflow); |
5007 } else { | 5007 } else { |
5008 ASSERT(!dst.is(src)); | 5008 DCHECK(!dst.is(src)); |
5009 ASSERT(!dst.is(overflow)); | 5009 DCHECK(!dst.is(overflow)); |
5010 ASSERT(!src.is(overflow)); | 5010 DCHECK(!src.is(overflow)); |
5011 SmiTag(dst, src); | 5011 SmiTag(dst, src); |
5012 xor_(overflow, dst, src); // Overflow if (value ^ 2 * value) < 0. | 5012 xor_(overflow, dst, src); // Overflow if (value ^ 2 * value) < 0. |
5013 } | 5013 } |
5014 } | 5014 } |
5015 | 5015 |
5016 | 5016 |
5017 void MacroAssembler::SmiLoadUntag(Register dst, MemOperand src) { | 5017 void MacroAssembler::SmiLoadUntag(Register dst, MemOperand src) { |
5018 if (SmiValuesAre32Bits()) { | 5018 if (SmiValuesAre32Bits()) { |
5019 lw(dst, UntagSmiMemOperand(src.rm(), src.offset())); | 5019 lw(dst, UntagSmiMemOperand(src.rm(), src.offset())); |
5020 } else { | 5020 } else { |
5021 lw(dst, src); | 5021 lw(dst, src); |
5022 SmiUntag(dst); | 5022 SmiUntag(dst); |
5023 } | 5023 } |
5024 } | 5024 } |
5025 | 5025 |
5026 | 5026 |
5027 void MacroAssembler::SmiLoadScale(Register dst, MemOperand src, int scale) { | 5027 void MacroAssembler::SmiLoadScale(Register dst, MemOperand src, int scale) { |
5028 if (SmiValuesAre32Bits()) { | 5028 if (SmiValuesAre32Bits()) { |
5029 // TODO(plind): not clear if lw or ld faster here, need micro-benchmark. | 5029 // TODO(plind): not clear if lw or ld faster here, need micro-benchmark. |
5030 lw(dst, UntagSmiMemOperand(src.rm(), src.offset())); | 5030 lw(dst, UntagSmiMemOperand(src.rm(), src.offset())); |
5031 dsll(dst, dst, scale); | 5031 dsll(dst, dst, scale); |
5032 } else { | 5032 } else { |
5033 lw(dst, src); | 5033 lw(dst, src); |
5034 ASSERT(scale >= kSmiTagSize); | 5034 DCHECK(scale >= kSmiTagSize); |
5035 sll(dst, dst, scale - kSmiTagSize); | 5035 sll(dst, dst, scale - kSmiTagSize); |
5036 } | 5036 } |
5037 } | 5037 } |
5038 | 5038 |
5039 | 5039 |
5040 // Returns 2 values: the Smi and a scaled version of the int within the Smi. | 5040 // Returns 2 values: the Smi and a scaled version of the int within the Smi. |
5041 void MacroAssembler::SmiLoadWithScale(Register d_smi, | 5041 void MacroAssembler::SmiLoadWithScale(Register d_smi, |
5042 Register d_scaled, | 5042 Register d_scaled, |
5043 MemOperand src, | 5043 MemOperand src, |
5044 int scale) { | 5044 int scale) { |
5045 if (SmiValuesAre32Bits()) { | 5045 if (SmiValuesAre32Bits()) { |
5046 ld(d_smi, src); | 5046 ld(d_smi, src); |
5047 dsra(d_scaled, d_smi, kSmiShift - scale); | 5047 dsra(d_scaled, d_smi, kSmiShift - scale); |
5048 } else { | 5048 } else { |
5049 lw(d_smi, src); | 5049 lw(d_smi, src); |
5050 ASSERT(scale >= kSmiTagSize); | 5050 DCHECK(scale >= kSmiTagSize); |
5051 sll(d_scaled, d_smi, scale - kSmiTagSize); | 5051 sll(d_scaled, d_smi, scale - kSmiTagSize); |
5052 } | 5052 } |
5053 } | 5053 } |
5054 | 5054 |
5055 | 5055 |
5056 // Returns 2 values: the untagged Smi (int32) and scaled version of that int. | 5056 // Returns 2 values: the untagged Smi (int32) and scaled version of that int. |
5057 void MacroAssembler::SmiLoadUntagWithScale(Register d_int, | 5057 void MacroAssembler::SmiLoadUntagWithScale(Register d_int, |
5058 Register d_scaled, | 5058 Register d_scaled, |
5059 MemOperand src, | 5059 MemOperand src, |
5060 int scale) { | 5060 int scale) { |
5061 if (SmiValuesAre32Bits()) { | 5061 if (SmiValuesAre32Bits()) { |
5062 lw(d_int, UntagSmiMemOperand(src.rm(), src.offset())); | 5062 lw(d_int, UntagSmiMemOperand(src.rm(), src.offset())); |
5063 dsll(d_scaled, d_int, scale); | 5063 dsll(d_scaled, d_int, scale); |
5064 } else { | 5064 } else { |
5065 lw(d_int, src); | 5065 lw(d_int, src); |
5066 // Need both the int and the scaled in, so use two instructions. | 5066 // Need both the int and the scaled in, so use two instructions. |
5067 SmiUntag(d_int); | 5067 SmiUntag(d_int); |
5068 sll(d_scaled, d_int, scale); | 5068 sll(d_scaled, d_int, scale); |
5069 } | 5069 } |
5070 } | 5070 } |
5071 | 5071 |
5072 | 5072 |
5073 void MacroAssembler::UntagAndJumpIfSmi(Register dst, | 5073 void MacroAssembler::UntagAndJumpIfSmi(Register dst, |
5074 Register src, | 5074 Register src, |
5075 Label* smi_case) { | 5075 Label* smi_case) { |
5076 // ASSERT(!dst.is(src)); | 5076 // DCHECK(!dst.is(src)); |
5077 JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT); | 5077 JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT); |
5078 SmiUntag(dst, src); | 5078 SmiUntag(dst, src); |
5079 } | 5079 } |
5080 | 5080 |
5081 | 5081 |
5082 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst, | 5082 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst, |
5083 Register src, | 5083 Register src, |
5084 Label* non_smi_case) { | 5084 Label* non_smi_case) { |
5085 // ASSERT(!dst.is(src)); | 5085 // DCHECK(!dst.is(src)); |
5086 JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT); | 5086 JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT); |
5087 SmiUntag(dst, src); | 5087 SmiUntag(dst, src); |
5088 } | 5088 } |
5089 | 5089 |
5090 void MacroAssembler::JumpIfSmi(Register value, | 5090 void MacroAssembler::JumpIfSmi(Register value, |
5091 Label* smi_label, | 5091 Label* smi_label, |
5092 Register scratch, | 5092 Register scratch, |
5093 BranchDelaySlot bd) { | 5093 BranchDelaySlot bd) { |
5094 ASSERT_EQ(0, kSmiTag); | 5094 DCHECK_EQ(0, kSmiTag); |
5095 andi(scratch, value, kSmiTagMask); | 5095 andi(scratch, value, kSmiTagMask); |
5096 Branch(bd, smi_label, eq, scratch, Operand(zero_reg)); | 5096 Branch(bd, smi_label, eq, scratch, Operand(zero_reg)); |
5097 } | 5097 } |
5098 | 5098 |
5099 void MacroAssembler::JumpIfNotSmi(Register value, | 5099 void MacroAssembler::JumpIfNotSmi(Register value, |
5100 Label* not_smi_label, | 5100 Label* not_smi_label, |
5101 Register scratch, | 5101 Register scratch, |
5102 BranchDelaySlot bd) { | 5102 BranchDelaySlot bd) { |
5103 ASSERT_EQ(0, kSmiTag); | 5103 DCHECK_EQ(0, kSmiTag); |
5104 andi(scratch, value, kSmiTagMask); | 5104 andi(scratch, value, kSmiTagMask); |
5105 Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg)); | 5105 Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg)); |
5106 } | 5106 } |
5107 | 5107 |
5108 | 5108 |
5109 void MacroAssembler::JumpIfNotBothSmi(Register reg1, | 5109 void MacroAssembler::JumpIfNotBothSmi(Register reg1, |
5110 Register reg2, | 5110 Register reg2, |
5111 Label* on_not_both_smi) { | 5111 Label* on_not_both_smi) { |
5112 STATIC_ASSERT(kSmiTag == 0); | 5112 STATIC_ASSERT(kSmiTag == 0); |
5113 // TODO(plind): Find some better to fix this assert issue. | 5113 // TODO(plind): Find some better to fix this assert issue. |
5114 #if defined(__APPLE__) | 5114 #if defined(__APPLE__) |
5115 ASSERT_EQ(1, kSmiTagMask); | 5115 DCHECK_EQ(1, kSmiTagMask); |
5116 #else | 5116 #else |
5117 ASSERT_EQ((uint64_t)1, kSmiTagMask); | 5117 DCHECK_EQ((uint64_t)1, kSmiTagMask); |
5118 #endif | 5118 #endif |
5119 or_(at, reg1, reg2); | 5119 or_(at, reg1, reg2); |
5120 JumpIfNotSmi(at, on_not_both_smi); | 5120 JumpIfNotSmi(at, on_not_both_smi); |
5121 } | 5121 } |
5122 | 5122 |
5123 | 5123 |
5124 void MacroAssembler::JumpIfEitherSmi(Register reg1, | 5124 void MacroAssembler::JumpIfEitherSmi(Register reg1, |
5125 Register reg2, | 5125 Register reg2, |
5126 Label* on_either_smi) { | 5126 Label* on_either_smi) { |
5127 STATIC_ASSERT(kSmiTag == 0); | 5127 STATIC_ASSERT(kSmiTag == 0); |
5128 // TODO(plind): Find some better to fix this assert issue. | 5128 // TODO(plind): Find some better to fix this assert issue. |
5129 #if defined(__APPLE__) | 5129 #if defined(__APPLE__) |
5130 ASSERT_EQ(1, kSmiTagMask); | 5130 DCHECK_EQ(1, kSmiTagMask); |
5131 #else | 5131 #else |
5132 ASSERT_EQ((uint64_t)1, kSmiTagMask); | 5132 DCHECK_EQ((uint64_t)1, kSmiTagMask); |
5133 #endif | 5133 #endif |
5134 // Both Smi tags must be 1 (not Smi). | 5134 // Both Smi tags must be 1 (not Smi). |
5135 and_(at, reg1, reg2); | 5135 and_(at, reg1, reg2); |
5136 JumpIfSmi(at, on_either_smi); | 5136 JumpIfSmi(at, on_either_smi); |
5137 } | 5137 } |
5138 | 5138 |
5139 | 5139 |
5140 void MacroAssembler::AssertNotSmi(Register object) { | 5140 void MacroAssembler::AssertNotSmi(Register object) { |
5141 if (emit_debug_code()) { | 5141 if (emit_debug_code()) { |
5142 STATIC_ASSERT(kSmiTag == 0); | 5142 STATIC_ASSERT(kSmiTag == 0); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5195 LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex); | 5195 LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex); |
5196 Assert(eq, kExpectedUndefinedOrCell, object, Operand(scratch)); | 5196 Assert(eq, kExpectedUndefinedOrCell, object, Operand(scratch)); |
5197 pop(object); | 5197 pop(object); |
5198 bind(&done_checking); | 5198 bind(&done_checking); |
5199 } | 5199 } |
5200 } | 5200 } |
5201 | 5201 |
5202 | 5202 |
5203 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) { | 5203 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) { |
5204 if (emit_debug_code()) { | 5204 if (emit_debug_code()) { |
5205 ASSERT(!reg.is(at)); | 5205 DCHECK(!reg.is(at)); |
5206 LoadRoot(at, index); | 5206 LoadRoot(at, index); |
5207 Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at)); | 5207 Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at)); |
5208 } | 5208 } |
5209 } | 5209 } |
5210 | 5210 |
5211 | 5211 |
5212 void MacroAssembler::JumpIfNotHeapNumber(Register object, | 5212 void MacroAssembler::JumpIfNotHeapNumber(Register object, |
5213 Register heap_number_map, | 5213 Register heap_number_map, |
5214 Register scratch, | 5214 Register scratch, |
5215 Label* on_not_heap_number) { | 5215 Label* on_not_heap_number) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5342 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( | 5342 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( |
5343 Register first, | 5343 Register first, |
5344 Register second, | 5344 Register second, |
5345 Register scratch1, | 5345 Register scratch1, |
5346 Register scratch2, | 5346 Register scratch2, |
5347 Label* failure) { | 5347 Label* failure) { |
5348 const int kFlatAsciiStringMask = | 5348 const int kFlatAsciiStringMask = |
5349 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 5349 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
5350 const int kFlatAsciiStringTag = | 5350 const int kFlatAsciiStringTag = |
5351 kStringTag | kOneByteStringTag | kSeqStringTag; | 5351 kStringTag | kOneByteStringTag | kSeqStringTag; |
5352 ASSERT(kFlatAsciiStringTag <= 0xffff); // Ensure this fits 16-bit immed. | 5352 DCHECK(kFlatAsciiStringTag <= 0xffff); // Ensure this fits 16-bit immed. |
5353 andi(scratch1, first, kFlatAsciiStringMask); | 5353 andi(scratch1, first, kFlatAsciiStringMask); |
5354 Branch(failure, ne, scratch1, Operand(kFlatAsciiStringTag)); | 5354 Branch(failure, ne, scratch1, Operand(kFlatAsciiStringTag)); |
5355 andi(scratch2, second, kFlatAsciiStringMask); | 5355 andi(scratch2, second, kFlatAsciiStringMask); |
5356 Branch(failure, ne, scratch2, Operand(kFlatAsciiStringTag)); | 5356 Branch(failure, ne, scratch2, Operand(kFlatAsciiStringTag)); |
5357 } | 5357 } |
5358 | 5358 |
5359 | 5359 |
5360 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type, | 5360 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type, |
5361 Register scratch, | 5361 Register scratch, |
5362 Label* failure) { | 5362 Label* failure) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5400 | 5400 |
5401 andi(at, at, kStringRepresentationMask | kStringEncodingMask); | 5401 andi(at, at, kStringRepresentationMask | kStringEncodingMask); |
5402 li(scratch, Operand(encoding_mask)); | 5402 li(scratch, Operand(encoding_mask)); |
5403 Check(eq, kUnexpectedStringType, at, Operand(scratch)); | 5403 Check(eq, kUnexpectedStringType, at, Operand(scratch)); |
5404 | 5404 |
5405 // TODO(plind): requires Smi size check code for mips32. | 5405 // TODO(plind): requires Smi size check code for mips32. |
5406 | 5406 |
5407 ld(at, FieldMemOperand(string, String::kLengthOffset)); | 5407 ld(at, FieldMemOperand(string, String::kLengthOffset)); |
5408 Check(lt, kIndexIsTooLarge, index, Operand(at)); | 5408 Check(lt, kIndexIsTooLarge, index, Operand(at)); |
5409 | 5409 |
5410 ASSERT(Smi::FromInt(0) == 0); | 5410 DCHECK(Smi::FromInt(0) == 0); |
5411 Check(ge, kIndexIsNegative, index, Operand(zero_reg)); | 5411 Check(ge, kIndexIsNegative, index, Operand(zero_reg)); |
5412 } | 5412 } |
5413 | 5413 |
5414 | 5414 |
5415 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 5415 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
5416 int num_double_arguments, | 5416 int num_double_arguments, |
5417 Register scratch) { | 5417 Register scratch) { |
5418 int frame_alignment = ActivationFrameAlignment(); | 5418 int frame_alignment = ActivationFrameAlignment(); |
5419 | 5419 |
5420 // n64: Up to eight simple arguments in a0..a3, a4..a7, No argument slots. | 5420 // n64: Up to eight simple arguments in a0..a3, a4..a7, No argument slots. |
5421 // O32: Up to four simple arguments are passed in registers a0..a3. | 5421 // O32: Up to four simple arguments are passed in registers a0..a3. |
5422 // Those four arguments must have reserved argument slots on the stack for | 5422 // Those four arguments must have reserved argument slots on the stack for |
5423 // mips, even though those argument slots are not normally used. | 5423 // mips, even though those argument slots are not normally used. |
5424 // Both ABIs: Remaining arguments are pushed on the stack, above (higher | 5424 // Both ABIs: Remaining arguments are pushed on the stack, above (higher |
5425 // address than) the (O32) argument slots. (arg slot calculation handled by | 5425 // address than) the (O32) argument slots. (arg slot calculation handled by |
5426 // CalculateStackPassedWords()). | 5426 // CalculateStackPassedWords()). |
5427 int stack_passed_arguments = CalculateStackPassedWords( | 5427 int stack_passed_arguments = CalculateStackPassedWords( |
5428 num_reg_arguments, num_double_arguments); | 5428 num_reg_arguments, num_double_arguments); |
5429 if (frame_alignment > kPointerSize) { | 5429 if (frame_alignment > kPointerSize) { |
5430 // Make stack end at alignment and make room for num_arguments - 4 words | 5430 // Make stack end at alignment and make room for num_arguments - 4 words |
5431 // and the original value of sp. | 5431 // and the original value of sp. |
5432 mov(scratch, sp); | 5432 mov(scratch, sp); |
5433 Dsubu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); | 5433 Dsubu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); |
5434 ASSERT(IsPowerOf2(frame_alignment)); | 5434 DCHECK(IsPowerOf2(frame_alignment)); |
5435 And(sp, sp, Operand(-frame_alignment)); | 5435 And(sp, sp, Operand(-frame_alignment)); |
5436 sd(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); | 5436 sd(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
5437 } else { | 5437 } else { |
5438 Dsubu(sp, sp, Operand(stack_passed_arguments * kPointerSize)); | 5438 Dsubu(sp, sp, Operand(stack_passed_arguments * kPointerSize)); |
5439 } | 5439 } |
5440 } | 5440 } |
5441 | 5441 |
5442 | 5442 |
5443 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 5443 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
5444 Register scratch) { | 5444 Register scratch) { |
(...skipping 24 matching lines...) Expand all Loading... |
5469 | 5469 |
5470 void MacroAssembler::CallCFunction(Register function, | 5470 void MacroAssembler::CallCFunction(Register function, |
5471 int num_arguments) { | 5471 int num_arguments) { |
5472 CallCFunction(function, num_arguments, 0); | 5472 CallCFunction(function, num_arguments, 0); |
5473 } | 5473 } |
5474 | 5474 |
5475 | 5475 |
5476 void MacroAssembler::CallCFunctionHelper(Register function, | 5476 void MacroAssembler::CallCFunctionHelper(Register function, |
5477 int num_reg_arguments, | 5477 int num_reg_arguments, |
5478 int num_double_arguments) { | 5478 int num_double_arguments) { |
5479 ASSERT(has_frame()); | 5479 DCHECK(has_frame()); |
5480 // Make sure that the stack is aligned before calling a C function unless | 5480 // Make sure that the stack is aligned before calling a C function unless |
5481 // running in the simulator. The simulator has its own alignment check which | 5481 // running in the simulator. The simulator has its own alignment check which |
5482 // provides more information. | 5482 // provides more information. |
5483 // The argument stots are presumed to have been set up by | 5483 // The argument stots are presumed to have been set up by |
5484 // PrepareCallCFunction. The C function must be called via t9, for mips ABI. | 5484 // PrepareCallCFunction. The C function must be called via t9, for mips ABI. |
5485 | 5485 |
5486 #if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64 | 5486 #if V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64 |
5487 if (emit_debug_code()) { | 5487 if (emit_debug_code()) { |
5488 int frame_alignment = base::OS::ActivationFrameAlignment(); | 5488 int frame_alignment = base::OS::ActivationFrameAlignment(); |
5489 int frame_alignment_mask = frame_alignment - 1; | 5489 int frame_alignment_mask = frame_alignment - 1; |
5490 if (frame_alignment > kPointerSize) { | 5490 if (frame_alignment > kPointerSize) { |
5491 ASSERT(IsPowerOf2(frame_alignment)); | 5491 DCHECK(IsPowerOf2(frame_alignment)); |
5492 Label alignment_as_expected; | 5492 Label alignment_as_expected; |
5493 And(at, sp, Operand(frame_alignment_mask)); | 5493 And(at, sp, Operand(frame_alignment_mask)); |
5494 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); | 5494 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); |
5495 // Don't use Check here, as it will call Runtime_Abort possibly | 5495 // Don't use Check here, as it will call Runtime_Abort possibly |
5496 // re-entering here. | 5496 // re-entering here. |
5497 stop("Unexpected alignment in CallCFunction"); | 5497 stop("Unexpected alignment in CallCFunction"); |
5498 bind(&alignment_as_expected); | 5498 bind(&alignment_as_expected); |
5499 } | 5499 } |
5500 } | 5500 } |
5501 #endif // V8_HOST_ARCH_MIPS | 5501 #endif // V8_HOST_ARCH_MIPS |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5636 Branch(if_deprecated, ne, scratch, Operand(zero_reg)); | 5636 Branch(if_deprecated, ne, scratch, Operand(zero_reg)); |
5637 } | 5637 } |
5638 } | 5638 } |
5639 | 5639 |
5640 | 5640 |
5641 void MacroAssembler::JumpIfBlack(Register object, | 5641 void MacroAssembler::JumpIfBlack(Register object, |
5642 Register scratch0, | 5642 Register scratch0, |
5643 Register scratch1, | 5643 Register scratch1, |
5644 Label* on_black) { | 5644 Label* on_black) { |
5645 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. | 5645 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. |
5646 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 5646 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
5647 } | 5647 } |
5648 | 5648 |
5649 | 5649 |
5650 void MacroAssembler::HasColor(Register object, | 5650 void MacroAssembler::HasColor(Register object, |
5651 Register bitmap_scratch, | 5651 Register bitmap_scratch, |
5652 Register mask_scratch, | 5652 Register mask_scratch, |
5653 Label* has_color, | 5653 Label* has_color, |
5654 int first_bit, | 5654 int first_bit, |
5655 int second_bit) { | 5655 int second_bit) { |
5656 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t8)); | 5656 DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t8)); |
5657 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t9)); | 5657 DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t9)); |
5658 | 5658 |
5659 GetMarkBits(object, bitmap_scratch, mask_scratch); | 5659 GetMarkBits(object, bitmap_scratch, mask_scratch); |
5660 | 5660 |
5661 Label other_color; | 5661 Label other_color; |
5662 // Note that we are using a 4-byte aligned 8-byte load. | 5662 // Note that we are using a 4-byte aligned 8-byte load. |
5663 Uld(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5663 Uld(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
5664 And(t8, t9, Operand(mask_scratch)); | 5664 And(t8, t9, Operand(mask_scratch)); |
5665 Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg)); | 5665 Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg)); |
5666 // Shift left 1 by adding. | 5666 // Shift left 1 by adding. |
5667 Daddu(mask_scratch, mask_scratch, Operand(mask_scratch)); | 5667 Daddu(mask_scratch, mask_scratch, Operand(mask_scratch)); |
5668 And(t8, t9, Operand(mask_scratch)); | 5668 And(t8, t9, Operand(mask_scratch)); |
5669 Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg)); | 5669 Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg)); |
5670 | 5670 |
5671 bind(&other_color); | 5671 bind(&other_color); |
5672 } | 5672 } |
5673 | 5673 |
5674 | 5674 |
5675 // Detect some, but not all, common pointer-free objects. This is used by the | 5675 // Detect some, but not all, common pointer-free objects. This is used by the |
5676 // incremental write barrier which doesn't care about oddballs (they are always | 5676 // incremental write barrier which doesn't care about oddballs (they are always |
5677 // marked black immediately so this code is not hit). | 5677 // marked black immediately so this code is not hit). |
5678 void MacroAssembler::JumpIfDataObject(Register value, | 5678 void MacroAssembler::JumpIfDataObject(Register value, |
5679 Register scratch, | 5679 Register scratch, |
5680 Label* not_data_object) { | 5680 Label* not_data_object) { |
5681 ASSERT(!AreAliased(value, scratch, t8, no_reg)); | 5681 DCHECK(!AreAliased(value, scratch, t8, no_reg)); |
5682 Label is_data_object; | 5682 Label is_data_object; |
5683 ld(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | 5683 ld(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); |
5684 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | 5684 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); |
5685 Branch(&is_data_object, eq, t8, Operand(scratch)); | 5685 Branch(&is_data_object, eq, t8, Operand(scratch)); |
5686 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | 5686 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); |
5687 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | 5687 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); |
5688 // If it's a string and it's not a cons string then it's an object containing | 5688 // If it's a string and it's not a cons string then it's an object containing |
5689 // no GC pointers. | 5689 // no GC pointers. |
5690 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 5690 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
5691 And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); | 5691 And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); |
5692 Branch(not_data_object, ne, t8, Operand(zero_reg)); | 5692 Branch(not_data_object, ne, t8, Operand(zero_reg)); |
5693 bind(&is_data_object); | 5693 bind(&is_data_object); |
5694 } | 5694 } |
5695 | 5695 |
5696 | 5696 |
5697 void MacroAssembler::GetMarkBits(Register addr_reg, | 5697 void MacroAssembler::GetMarkBits(Register addr_reg, |
5698 Register bitmap_reg, | 5698 Register bitmap_reg, |
5699 Register mask_reg) { | 5699 Register mask_reg) { |
5700 ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); | 5700 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); |
5701 // addr_reg is divided into fields: | 5701 // addr_reg is divided into fields: |
5702 // |63 page base 20|19 high 8|7 shift 3|2 0| | 5702 // |63 page base 20|19 high 8|7 shift 3|2 0| |
5703 // 'high' gives the index of the cell holding color bits for the object. | 5703 // 'high' gives the index of the cell holding color bits for the object. |
5704 // 'shift' gives the offset in the cell for this object's color. | 5704 // 'shift' gives the offset in the cell for this object's color. |
5705 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); | 5705 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); |
5706 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); | 5706 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); |
5707 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; | 5707 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; |
5708 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); | 5708 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); |
5709 dsll(t8, t8, Bitmap::kBytesPerCellLog2); | 5709 dsll(t8, t8, Bitmap::kBytesPerCellLog2); |
5710 Daddu(bitmap_reg, bitmap_reg, t8); | 5710 Daddu(bitmap_reg, bitmap_reg, t8); |
5711 li(t8, Operand(1)); | 5711 li(t8, Operand(1)); |
5712 dsllv(mask_reg, t8, mask_reg); | 5712 dsllv(mask_reg, t8, mask_reg); |
5713 } | 5713 } |
5714 | 5714 |
5715 | 5715 |
5716 void MacroAssembler::EnsureNotWhite( | 5716 void MacroAssembler::EnsureNotWhite( |
5717 Register value, | 5717 Register value, |
5718 Register bitmap_scratch, | 5718 Register bitmap_scratch, |
5719 Register mask_scratch, | 5719 Register mask_scratch, |
5720 Register load_scratch, | 5720 Register load_scratch, |
5721 Label* value_is_white_and_not_data) { | 5721 Label* value_is_white_and_not_data) { |
5722 ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); | 5722 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); |
5723 GetMarkBits(value, bitmap_scratch, mask_scratch); | 5723 GetMarkBits(value, bitmap_scratch, mask_scratch); |
5724 | 5724 |
5725 // If the value is black or grey we don't need to do anything. | 5725 // If the value is black or grey we don't need to do anything. |
5726 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 5726 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
5727 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 5727 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
5728 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); | 5728 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); |
5729 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 5729 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
5730 | 5730 |
5731 Label done; | 5731 Label done; |
5732 | 5732 |
5733 // Since both black and grey have a 1 in the first position and white does | 5733 // Since both black and grey have a 1 in the first position and white does |
5734 // not have a 1 there we only need to check one bit. | 5734 // not have a 1 there we only need to check one bit. |
5735 // Note that we are using a 4-byte aligned 8-byte load. | 5735 // Note that we are using a 4-byte aligned 8-byte load. |
5736 Uld(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5736 Uld(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
5737 And(t8, mask_scratch, load_scratch); | 5737 And(t8, mask_scratch, load_scratch); |
5738 Branch(&done, ne, t8, Operand(zero_reg)); | 5738 Branch(&done, ne, t8, Operand(zero_reg)); |
5739 | 5739 |
(...skipping 19 matching lines...) Expand all Loading... |
5759 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | 5759 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); |
5760 { | 5760 { |
5761 Label skip; | 5761 Label skip; |
5762 Branch(&skip, ne, t8, Operand(map)); | 5762 Branch(&skip, ne, t8, Operand(map)); |
5763 li(length, HeapNumber::kSize); | 5763 li(length, HeapNumber::kSize); |
5764 Branch(&is_data_object); | 5764 Branch(&is_data_object); |
5765 bind(&skip); | 5765 bind(&skip); |
5766 } | 5766 } |
5767 | 5767 |
5768 // Check for strings. | 5768 // Check for strings. |
5769 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | 5769 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); |
5770 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | 5770 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); |
5771 // If it's a string and it's not a cons string then it's an object containing | 5771 // If it's a string and it's not a cons string then it's an object containing |
5772 // no GC pointers. | 5772 // no GC pointers. |
5773 Register instance_type = load_scratch; | 5773 Register instance_type = load_scratch; |
5774 lbu(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 5774 lbu(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
5775 And(t8, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask)); | 5775 And(t8, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask)); |
5776 Branch(value_is_white_and_not_data, ne, t8, Operand(zero_reg)); | 5776 Branch(value_is_white_and_not_data, ne, t8, Operand(zero_reg)); |
5777 // It's a non-indirect (non-cons and non-slice) string. | 5777 // It's a non-indirect (non-cons and non-slice) string. |
5778 // If it's external, the length is just ExternalString::kSize. | 5778 // If it's external, the length is just ExternalString::kSize. |
5779 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). | 5779 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). |
5780 // External strings are the only ones with the kExternalStringTag bit | 5780 // External strings are the only ones with the kExternalStringTag bit |
5781 // set. | 5781 // set. |
5782 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); | 5782 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); |
5783 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); | 5783 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); |
5784 And(t8, instance_type, Operand(kExternalStringTag)); | 5784 And(t8, instance_type, Operand(kExternalStringTag)); |
5785 { | 5785 { |
5786 Label skip; | 5786 Label skip; |
5787 Branch(&skip, eq, t8, Operand(zero_reg)); | 5787 Branch(&skip, eq, t8, Operand(zero_reg)); |
5788 li(length, ExternalString::kSize); | 5788 li(length, ExternalString::kSize); |
5789 Branch(&is_data_object); | 5789 Branch(&is_data_object); |
5790 bind(&skip); | 5790 bind(&skip); |
5791 } | 5791 } |
5792 | 5792 |
5793 // Sequential string, either ASCII or UC16. | 5793 // Sequential string, either ASCII or UC16. |
5794 // For ASCII (char-size of 1) we shift the smi tag away to get the length. | 5794 // For ASCII (char-size of 1) we shift the smi tag away to get the length. |
5795 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby | 5795 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby |
5796 // getting the length multiplied by 2. | 5796 // getting the length multiplied by 2. |
5797 ASSERT(kOneByteStringTag == 4 && kStringEncodingMask == 4); | 5797 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4); |
5798 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 5798 DCHECK(kSmiTag == 0 && kSmiTagSize == 1); |
5799 lw(t9, UntagSmiFieldMemOperand(value, String::kLengthOffset)); | 5799 lw(t9, UntagSmiFieldMemOperand(value, String::kLengthOffset)); |
5800 And(t8, instance_type, Operand(kStringEncodingMask)); | 5800 And(t8, instance_type, Operand(kStringEncodingMask)); |
5801 { | 5801 { |
5802 Label skip; | 5802 Label skip; |
5803 Branch(&skip, ne, t8, Operand(zero_reg)); | 5803 Branch(&skip, ne, t8, Operand(zero_reg)); |
5804 // Adjust length for UC16. | 5804 // Adjust length for UC16. |
5805 dsll(t9, t9, 1); | 5805 dsll(t9, t9, 1); |
5806 bind(&skip); | 5806 bind(&skip); |
5807 } | 5807 } |
5808 Daddu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); | 5808 Daddu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); |
5809 ASSERT(!length.is(t8)); | 5809 DCHECK(!length.is(t8)); |
5810 And(length, length, Operand(~kObjectAlignmentMask)); | 5810 And(length, length, Operand(~kObjectAlignmentMask)); |
5811 | 5811 |
5812 bind(&is_data_object); | 5812 bind(&is_data_object); |
5813 // Value is a data object, and it is white. Mark it black. Since we know | 5813 // Value is a data object, and it is white. Mark it black. Since we know |
5814 // that the object is white we can make it black by flipping one bit. | 5814 // that the object is white we can make it black by flipping one bit. |
5815 Uld(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5815 Uld(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
5816 Or(t8, t8, Operand(mask_scratch)); | 5816 Or(t8, t8, Operand(mask_scratch)); |
5817 Usd(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5817 Usd(t8, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
5818 | 5818 |
5819 And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); | 5819 And(bitmap_scratch, bitmap_scratch, Operand(~Page::kPageAlignmentMask)); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5880 LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex); | 5880 LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex); |
5881 Branch(call_runtime, ne, a2, Operand(at)); | 5881 Branch(call_runtime, ne, a2, Operand(at)); |
5882 | 5882 |
5883 bind(&no_elements); | 5883 bind(&no_elements); |
5884 ld(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); | 5884 ld(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); |
5885 Branch(&next, ne, a2, Operand(null_value)); | 5885 Branch(&next, ne, a2, Operand(null_value)); |
5886 } | 5886 } |
5887 | 5887 |
5888 | 5888 |
5889 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { | 5889 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { |
5890 ASSERT(!output_reg.is(input_reg)); | 5890 DCHECK(!output_reg.is(input_reg)); |
5891 Label done; | 5891 Label done; |
5892 li(output_reg, Operand(255)); | 5892 li(output_reg, Operand(255)); |
5893 // Normal branch: nop in delay slot. | 5893 // Normal branch: nop in delay slot. |
5894 Branch(&done, gt, input_reg, Operand(output_reg)); | 5894 Branch(&done, gt, input_reg, Operand(output_reg)); |
5895 // Use delay slot in this branch. | 5895 // Use delay slot in this branch. |
5896 Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg)); | 5896 Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg)); |
5897 mov(output_reg, zero_reg); // In delay slot. | 5897 mov(output_reg, zero_reg); // In delay slot. |
5898 mov(output_reg, input_reg); // Value is in range 0..255. | 5898 mov(output_reg, input_reg); // Value is in range 0..255. |
5899 bind(&done); | 5899 bind(&done); |
5900 } | 5900 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5975 UNREACHABLE(); | 5975 UNREACHABLE(); |
5976 return no_reg; | 5976 return no_reg; |
5977 } | 5977 } |
5978 | 5978 |
5979 | 5979 |
5980 void MacroAssembler::JumpIfDictionaryInPrototypeChain( | 5980 void MacroAssembler::JumpIfDictionaryInPrototypeChain( |
5981 Register object, | 5981 Register object, |
5982 Register scratch0, | 5982 Register scratch0, |
5983 Register scratch1, | 5983 Register scratch1, |
5984 Label* found) { | 5984 Label* found) { |
5985 ASSERT(!scratch1.is(scratch0)); | 5985 DCHECK(!scratch1.is(scratch0)); |
5986 Factory* factory = isolate()->factory(); | 5986 Factory* factory = isolate()->factory(); |
5987 Register current = scratch0; | 5987 Register current = scratch0; |
5988 Label loop_again; | 5988 Label loop_again; |
5989 | 5989 |
5990 // Scratch contained elements pointer. | 5990 // Scratch contained elements pointer. |
5991 Move(current, object); | 5991 Move(current, object); |
5992 | 5992 |
5993 // Loop based on the map going up the prototype chain. | 5993 // Loop based on the map going up the prototype chain. |
5994 bind(&loop_again); | 5994 bind(&loop_again); |
5995 ld(current, FieldMemOperand(current, HeapObject::kMapOffset)); | 5995 ld(current, FieldMemOperand(current, HeapObject::kMapOffset)); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6031 CodePatcher::CodePatcher(byte* address, | 6031 CodePatcher::CodePatcher(byte* address, |
6032 int instructions, | 6032 int instructions, |
6033 FlushICache flush_cache) | 6033 FlushICache flush_cache) |
6034 : address_(address), | 6034 : address_(address), |
6035 size_(instructions * Assembler::kInstrSize), | 6035 size_(instructions * Assembler::kInstrSize), |
6036 masm_(NULL, address, size_ + Assembler::kGap), | 6036 masm_(NULL, address, size_ + Assembler::kGap), |
6037 flush_cache_(flush_cache) { | 6037 flush_cache_(flush_cache) { |
6038 // Create a new macro assembler pointing to the address of the code to patch. | 6038 // Create a new macro assembler pointing to the address of the code to patch. |
6039 // The size is adjusted with kGap on order for the assembler to generate size | 6039 // The size is adjusted with kGap on order for the assembler to generate size |
6040 // bytes of instructions without failing with buffer size constraints. | 6040 // bytes of instructions without failing with buffer size constraints. |
6041 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 6041 DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
6042 } | 6042 } |
6043 | 6043 |
6044 | 6044 |
6045 CodePatcher::~CodePatcher() { | 6045 CodePatcher::~CodePatcher() { |
6046 // Indicate that code has changed. | 6046 // Indicate that code has changed. |
6047 if (flush_cache_ == FLUSH) { | 6047 if (flush_cache_ == FLUSH) { |
6048 CpuFeatures::FlushICache(address_, size_); | 6048 CpuFeatures::FlushICache(address_, size_); |
6049 } | 6049 } |
6050 // Check that the code was patched as expected. | 6050 // Check that the code was patched as expected. |
6051 ASSERT(masm_.pc_ == address_ + size_); | 6051 DCHECK(masm_.pc_ == address_ + size_); |
6052 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 6052 DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
6053 } | 6053 } |
6054 | 6054 |
6055 | 6055 |
6056 void CodePatcher::Emit(Instr instr) { | 6056 void CodePatcher::Emit(Instr instr) { |
6057 masm()->emit(instr); | 6057 masm()->emit(instr); |
6058 } | 6058 } |
6059 | 6059 |
6060 | 6060 |
6061 void CodePatcher::Emit(Address addr) { | 6061 void CodePatcher::Emit(Address addr) { |
6062 // masm()->emit(reinterpret_cast<Instr>(addr)); | 6062 // masm()->emit(reinterpret_cast<Instr>(addr)); |
6063 } | 6063 } |
6064 | 6064 |
6065 | 6065 |
6066 void CodePatcher::ChangeBranchCondition(Condition cond) { | 6066 void CodePatcher::ChangeBranchCondition(Condition cond) { |
6067 Instr instr = Assembler::instr_at(masm_.pc_); | 6067 Instr instr = Assembler::instr_at(masm_.pc_); |
6068 ASSERT(Assembler::IsBranch(instr)); | 6068 DCHECK(Assembler::IsBranch(instr)); |
6069 uint32_t opcode = Assembler::GetOpcodeField(instr); | 6069 uint32_t opcode = Assembler::GetOpcodeField(instr); |
6070 // Currently only the 'eq' and 'ne' cond values are supported and the simple | 6070 // Currently only the 'eq' and 'ne' cond values are supported and the simple |
6071 // branch instructions (with opcode being the branch type). | 6071 // branch instructions (with opcode being the branch type). |
6072 // There are some special cases (see Assembler::IsBranch()) so extending this | 6072 // There are some special cases (see Assembler::IsBranch()) so extending this |
6073 // would be tricky. | 6073 // would be tricky. |
6074 ASSERT(opcode == BEQ || | 6074 DCHECK(opcode == BEQ || |
6075 opcode == BNE || | 6075 opcode == BNE || |
6076 opcode == BLEZ || | 6076 opcode == BLEZ || |
6077 opcode == BGTZ || | 6077 opcode == BGTZ || |
6078 opcode == BEQL || | 6078 opcode == BEQL || |
6079 opcode == BNEL || | 6079 opcode == BNEL || |
6080 opcode == BLEZL || | 6080 opcode == BLEZL || |
6081 opcode == BGTZL); | 6081 opcode == BGTZL); |
6082 opcode = (cond == eq) ? BEQ : BNE; | 6082 opcode = (cond == eq) ? BEQ : BNE; |
6083 instr = (instr & ~kOpcodeMask) | opcode; | 6083 instr = (instr & ~kOpcodeMask) | opcode; |
6084 masm_.emit(instr); | 6084 masm_.emit(instr); |
6085 } | 6085 } |
6086 | 6086 |
6087 | 6087 |
6088 void MacroAssembler::TruncatingDiv(Register result, | 6088 void MacroAssembler::TruncatingDiv(Register result, |
6089 Register dividend, | 6089 Register dividend, |
6090 int32_t divisor) { | 6090 int32_t divisor) { |
6091 ASSERT(!dividend.is(result)); | 6091 DCHECK(!dividend.is(result)); |
6092 ASSERT(!dividend.is(at)); | 6092 DCHECK(!dividend.is(at)); |
6093 ASSERT(!result.is(at)); | 6093 DCHECK(!result.is(at)); |
6094 MultiplierAndShift ms(divisor); | 6094 MultiplierAndShift ms(divisor); |
6095 li(at, Operand(ms.multiplier())); | 6095 li(at, Operand(ms.multiplier())); |
6096 Mulh(result, dividend, Operand(at)); | 6096 Mulh(result, dividend, Operand(at)); |
6097 if (divisor > 0 && ms.multiplier() < 0) { | 6097 if (divisor > 0 && ms.multiplier() < 0) { |
6098 Addu(result, result, Operand(dividend)); | 6098 Addu(result, result, Operand(dividend)); |
6099 } | 6099 } |
6100 if (divisor < 0 && ms.multiplier() > 0) { | 6100 if (divisor < 0 && ms.multiplier() > 0) { |
6101 Subu(result, result, Operand(dividend)); | 6101 Subu(result, result, Operand(dividend)); |
6102 } | 6102 } |
6103 if (ms.shift() > 0) sra(result, result, ms.shift()); | 6103 if (ms.shift() > 0) sra(result, result, ms.shift()); |
6104 srl(at, dividend, 31); | 6104 srl(at, dividend, 31); |
6105 Addu(result, result, Operand(at)); | 6105 Addu(result, result, Operand(at)); |
6106 } | 6106 } |
6107 | 6107 |
6108 | 6108 |
6109 } } // namespace v8::internal | 6109 } } // namespace v8::internal |
6110 | 6110 |
6111 #endif // V8_TARGET_ARCH_MIPS64 | 6111 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |