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_MIPS | 9 #if V8_TARGET_ARCH_MIPS |
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 { | 44 } else { |
45 lw(dst, src); | 45 lw(dst, src); |
46 } | 46 } |
47 } | 47 } |
48 | 48 |
49 | 49 |
50 void MacroAssembler::Store(Register src, | 50 void MacroAssembler::Store(Register src, |
51 const MemOperand& dst, | 51 const MemOperand& dst, |
52 Representation r) { | 52 Representation r) { |
53 ASSERT(!r.IsDouble()); | 53 DCHECK(!r.IsDouble()); |
54 if (r.IsInteger8() || r.IsUInteger8()) { | 54 if (r.IsInteger8() || r.IsUInteger8()) { |
55 sb(src, dst); | 55 sb(src, dst); |
56 } else if (r.IsInteger16() || r.IsUInteger16()) { | 56 } else if (r.IsInteger16() || r.IsUInteger16()) { |
57 sh(src, dst); | 57 sh(src, dst); |
58 } else { | 58 } else { |
59 if (r.IsHeapObject()) { | 59 if (r.IsHeapObject()) { |
60 AssertNotSmi(src); | 60 AssertNotSmi(src); |
61 } else if (r.IsSmi()) { | 61 } else if (r.IsSmi()) { |
62 AssertSmi(src); | 62 AssertSmi(src); |
63 } | 63 } |
(...skipping 30 matching lines...) Expand all Loading... |
94 Branch(2, NegateCondition(cond), src1, src2); | 94 Branch(2, NegateCondition(cond), src1, src2); |
95 sw(source, MemOperand(s6, index << kPointerSizeLog2)); | 95 sw(source, MemOperand(s6, index << kPointerSizeLog2)); |
96 } | 96 } |
97 | 97 |
98 | 98 |
99 // Push and pop all registers that can hold pointers. | 99 // Push and pop all registers that can hold pointers. |
100 void MacroAssembler::PushSafepointRegisters() { | 100 void MacroAssembler::PushSafepointRegisters() { |
101 // Safepoints expect a block of kNumSafepointRegisters values on the | 101 // Safepoints expect a block of kNumSafepointRegisters values on the |
102 // stack, so adjust the stack for unsaved registers. | 102 // stack, so adjust the stack for unsaved registers. |
103 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 103 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
104 ASSERT(num_unsaved >= 0); | 104 DCHECK(num_unsaved >= 0); |
105 if (num_unsaved > 0) { | 105 if (num_unsaved > 0) { |
106 Subu(sp, sp, Operand(num_unsaved * kPointerSize)); | 106 Subu(sp, sp, Operand(num_unsaved * kPointerSize)); |
107 } | 107 } |
108 MultiPush(kSafepointSavedRegisters); | 108 MultiPush(kSafepointSavedRegisters); |
109 } | 109 } |
110 | 110 |
111 | 111 |
112 void MacroAssembler::PopSafepointRegisters() { | 112 void MacroAssembler::PopSafepointRegisters() { |
113 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 113 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
114 MultiPop(kSafepointSavedRegisters); | 114 MultiPop(kSafepointSavedRegisters); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize; | 146 int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize; |
147 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize; | 147 int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize; |
148 return MemOperand(sp, doubles_size + register_offset); | 148 return MemOperand(sp, doubles_size + register_offset); |
149 } | 149 } |
150 | 150 |
151 | 151 |
152 void MacroAssembler::InNewSpace(Register object, | 152 void MacroAssembler::InNewSpace(Register object, |
153 Register scratch, | 153 Register scratch, |
154 Condition cc, | 154 Condition cc, |
155 Label* branch) { | 155 Label* branch) { |
156 ASSERT(cc == eq || cc == ne); | 156 DCHECK(cc == eq || cc == ne); |
157 And(scratch, object, Operand(ExternalReference::new_space_mask(isolate()))); | 157 And(scratch, object, Operand(ExternalReference::new_space_mask(isolate()))); |
158 Branch(branch, cc, scratch, | 158 Branch(branch, cc, scratch, |
159 Operand(ExternalReference::new_space_start(isolate()))); | 159 Operand(ExternalReference::new_space_start(isolate()))); |
160 } | 160 } |
161 | 161 |
162 | 162 |
163 void MacroAssembler::RecordWriteField( | 163 void MacroAssembler::RecordWriteField( |
164 Register object, | 164 Register object, |
165 int offset, | 165 int offset, |
166 Register value, | 166 Register value, |
167 Register dst, | 167 Register dst, |
168 RAStatus ra_status, | 168 RAStatus ra_status, |
169 SaveFPRegsMode save_fp, | 169 SaveFPRegsMode save_fp, |
170 RememberedSetAction remembered_set_action, | 170 RememberedSetAction remembered_set_action, |
171 SmiCheck smi_check, | 171 SmiCheck smi_check, |
172 PointersToHereCheck pointers_to_here_check_for_value) { | 172 PointersToHereCheck pointers_to_here_check_for_value) { |
173 ASSERT(!AreAliased(value, dst, t8, object)); | 173 DCHECK(!AreAliased(value, dst, t8, object)); |
174 // First, check if a write barrier is even needed. The tests below | 174 // First, check if a write barrier is even needed. The tests below |
175 // catch stores of Smis. | 175 // catch stores of Smis. |
176 Label done; | 176 Label done; |
177 | 177 |
178 // Skip barrier if writing a smi. | 178 // Skip barrier if writing a smi. |
179 if (smi_check == INLINE_SMI_CHECK) { | 179 if (smi_check == INLINE_SMI_CHECK) { |
180 JumpIfSmi(value, &done); | 180 JumpIfSmi(value, &done); |
181 } | 181 } |
182 | 182 |
183 // Although the object register is tagged, the offset is relative to the start | 183 // Although the object register is tagged, the offset is relative to the start |
184 // of the object, so so offset must be a multiple of kPointerSize. | 184 // of the object, so so offset must be a multiple of kPointerSize. |
185 ASSERT(IsAligned(offset, kPointerSize)); | 185 DCHECK(IsAligned(offset, kPointerSize)); |
186 | 186 |
187 Addu(dst, object, Operand(offset - kHeapObjectTag)); | 187 Addu(dst, object, Operand(offset - kHeapObjectTag)); |
188 if (emit_debug_code()) { | 188 if (emit_debug_code()) { |
189 Label ok; | 189 Label ok; |
190 And(t8, dst, Operand((1 << kPointerSizeLog2) - 1)); | 190 And(t8, dst, Operand((1 << kPointerSizeLog2) - 1)); |
191 Branch(&ok, eq, t8, Operand(zero_reg)); | 191 Branch(&ok, eq, t8, Operand(zero_reg)); |
192 stop("Unaligned cell in write barrier"); | 192 stop("Unaligned cell in write barrier"); |
193 bind(&ok); | 193 bind(&ok); |
194 } | 194 } |
195 | 195 |
(...skipping 18 matching lines...) Expand all Loading... |
214 | 214 |
215 | 215 |
216 // Will clobber 4 registers: object, map, dst, ip. The | 216 // Will clobber 4 registers: object, map, dst, ip. The |
217 // register 'object' contains a heap object pointer. | 217 // register 'object' contains a heap object pointer. |
218 void MacroAssembler::RecordWriteForMap(Register object, | 218 void MacroAssembler::RecordWriteForMap(Register object, |
219 Register map, | 219 Register map, |
220 Register dst, | 220 Register dst, |
221 RAStatus ra_status, | 221 RAStatus ra_status, |
222 SaveFPRegsMode fp_mode) { | 222 SaveFPRegsMode fp_mode) { |
223 if (emit_debug_code()) { | 223 if (emit_debug_code()) { |
224 ASSERT(!dst.is(at)); | 224 DCHECK(!dst.is(at)); |
225 lw(dst, FieldMemOperand(map, HeapObject::kMapOffset)); | 225 lw(dst, FieldMemOperand(map, HeapObject::kMapOffset)); |
226 Check(eq, | 226 Check(eq, |
227 kWrongAddressOrValuePassedToRecordWrite, | 227 kWrongAddressOrValuePassedToRecordWrite, |
228 dst, | 228 dst, |
229 Operand(isolate()->factory()->meta_map())); | 229 Operand(isolate()->factory()->meta_map())); |
230 } | 230 } |
231 | 231 |
232 if (!FLAG_incremental_marking) { | 232 if (!FLAG_incremental_marking) { |
233 return; | 233 return; |
234 } | 234 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 // tag is shifted away. | 293 // tag is shifted away. |
294 void MacroAssembler::RecordWrite( | 294 void MacroAssembler::RecordWrite( |
295 Register object, | 295 Register object, |
296 Register address, | 296 Register address, |
297 Register value, | 297 Register value, |
298 RAStatus ra_status, | 298 RAStatus ra_status, |
299 SaveFPRegsMode fp_mode, | 299 SaveFPRegsMode fp_mode, |
300 RememberedSetAction remembered_set_action, | 300 RememberedSetAction remembered_set_action, |
301 SmiCheck smi_check, | 301 SmiCheck smi_check, |
302 PointersToHereCheck pointers_to_here_check_for_value) { | 302 PointersToHereCheck pointers_to_here_check_for_value) { |
303 ASSERT(!AreAliased(object, address, value, t8)); | 303 DCHECK(!AreAliased(object, address, value, t8)); |
304 ASSERT(!AreAliased(object, address, value, t9)); | 304 DCHECK(!AreAliased(object, address, value, t9)); |
305 | 305 |
306 if (emit_debug_code()) { | 306 if (emit_debug_code()) { |
307 lw(at, MemOperand(address)); | 307 lw(at, MemOperand(address)); |
308 Assert( | 308 Assert( |
309 eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value)); | 309 eq, kWrongAddressOrValuePassedToRecordWrite, at, Operand(value)); |
310 } | 310 } |
311 | 311 |
312 if (remembered_set_action == OMIT_REMEMBERED_SET && | 312 if (remembered_set_action == OMIT_REMEMBERED_SET && |
313 !FLAG_incremental_marking) { | 313 !FLAG_incremental_marking) { |
314 return; | 314 return; |
315 } | 315 } |
316 | 316 |
317 // First, check if a write barrier is even needed. The tests below | 317 // First, check if a write barrier is even needed. The tests below |
318 // catch stores of smis and stores into the young generation. | 318 // catch stores of smis and stores into the young generation. |
319 Label done; | 319 Label done; |
320 | 320 |
321 if (smi_check == INLINE_SMI_CHECK) { | 321 if (smi_check == INLINE_SMI_CHECK) { |
322 ASSERT_EQ(0, kSmiTag); | 322 DCHECK_EQ(0, kSmiTag); |
323 JumpIfSmi(value, &done); | 323 JumpIfSmi(value, &done); |
324 } | 324 } |
325 | 325 |
326 if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) { | 326 if (pointers_to_here_check_for_value != kPointersToHereAreAlwaysInteresting) { |
327 CheckPageFlag(value, | 327 CheckPageFlag(value, |
328 value, // Used as scratch. | 328 value, // Used as scratch. |
329 MemoryChunk::kPointersToHereAreInterestingMask, | 329 MemoryChunk::kPointersToHereAreInterestingMask, |
330 eq, | 330 eq, |
331 &done); | 331 &done); |
332 } | 332 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 sw(address, MemOperand(scratch)); | 384 sw(address, MemOperand(scratch)); |
385 Addu(scratch, scratch, kPointerSize); | 385 Addu(scratch, scratch, kPointerSize); |
386 // Write back new top of buffer. | 386 // Write back new top of buffer. |
387 sw(scratch, MemOperand(t8)); | 387 sw(scratch, MemOperand(t8)); |
388 // Call stub on end of buffer. | 388 // Call stub on end of buffer. |
389 // Check for end of buffer. | 389 // Check for end of buffer. |
390 And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); | 390 And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); |
391 if (and_then == kFallThroughAtEnd) { | 391 if (and_then == kFallThroughAtEnd) { |
392 Branch(&done, eq, t8, Operand(zero_reg)); | 392 Branch(&done, eq, t8, Operand(zero_reg)); |
393 } else { | 393 } else { |
394 ASSERT(and_then == kReturnAtEnd); | 394 DCHECK(and_then == kReturnAtEnd); |
395 Ret(eq, t8, Operand(zero_reg)); | 395 Ret(eq, t8, Operand(zero_reg)); |
396 } | 396 } |
397 push(ra); | 397 push(ra); |
398 StoreBufferOverflowStub store_buffer_overflow = | 398 StoreBufferOverflowStub store_buffer_overflow = |
399 StoreBufferOverflowStub(isolate(), fp_mode); | 399 StoreBufferOverflowStub(isolate(), fp_mode); |
400 CallStub(&store_buffer_overflow); | 400 CallStub(&store_buffer_overflow); |
401 pop(ra); | 401 pop(ra); |
402 bind(&done); | 402 bind(&done); |
403 if (and_then == kReturnAtEnd) { | 403 if (and_then == kReturnAtEnd) { |
404 Ret(); | 404 Ret(); |
405 } | 405 } |
406 } | 406 } |
407 | 407 |
408 | 408 |
409 // ----------------------------------------------------------------------------- | 409 // ----------------------------------------------------------------------------- |
410 // Allocation support. | 410 // Allocation support. |
411 | 411 |
412 | 412 |
413 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 413 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
414 Register scratch, | 414 Register scratch, |
415 Label* miss) { | 415 Label* miss) { |
416 Label same_contexts; | 416 Label same_contexts; |
417 | 417 |
418 ASSERT(!holder_reg.is(scratch)); | 418 DCHECK(!holder_reg.is(scratch)); |
419 ASSERT(!holder_reg.is(at)); | 419 DCHECK(!holder_reg.is(at)); |
420 ASSERT(!scratch.is(at)); | 420 DCHECK(!scratch.is(at)); |
421 | 421 |
422 // Load current lexical context from the stack frame. | 422 // Load current lexical context from the stack frame. |
423 lw(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 423 lw(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
424 // In debug mode, make sure the lexical context is set. | 424 // In debug mode, make sure the lexical context is set. |
425 #ifdef DEBUG | 425 #ifdef DEBUG |
426 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, | 426 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, |
427 scratch, Operand(zero_reg)); | 427 scratch, Operand(zero_reg)); |
428 #endif | 428 #endif |
429 | 429 |
430 // Load the native context of the current context. | 430 // Load the native context of the current context. |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 for (int i = 0; i < kNumberDictionaryProbes; i++) { | 565 for (int i = 0; i < kNumberDictionaryProbes; i++) { |
566 // Use reg2 for index calculations and keep the hash intact in reg0. | 566 // Use reg2 for index calculations and keep the hash intact in reg0. |
567 mov(reg2, reg0); | 567 mov(reg2, reg0); |
568 // Compute the masked index: (hash + i + i * i) & mask. | 568 // Compute the masked index: (hash + i + i * i) & mask. |
569 if (i > 0) { | 569 if (i > 0) { |
570 Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); | 570 Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); |
571 } | 571 } |
572 and_(reg2, reg2, reg1); | 572 and_(reg2, reg2, reg1); |
573 | 573 |
574 // Scale the index by multiplying by the element size. | 574 // Scale the index by multiplying by the element size. |
575 ASSERT(SeededNumberDictionary::kEntrySize == 3); | 575 DCHECK(SeededNumberDictionary::kEntrySize == 3); |
576 sll(at, reg2, 1); // 2x. | 576 sll(at, reg2, 1); // 2x. |
577 addu(reg2, reg2, at); // reg2 = reg2 * 3. | 577 addu(reg2, reg2, at); // reg2 = reg2 * 3. |
578 | 578 |
579 // Check if the key is identical to the name. | 579 // Check if the key is identical to the name. |
580 sll(at, reg2, kPointerSizeLog2); | 580 sll(at, reg2, kPointerSizeLog2); |
581 addu(reg2, elements, at); | 581 addu(reg2, elements, at); |
582 | 582 |
583 lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); | 583 lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); |
584 if (i != kNumberDictionaryProbes - 1) { | 584 if (i != kNumberDictionaryProbes - 1) { |
585 Branch(&done, eq, key, Operand(at)); | 585 Branch(&done, eq, key, Operand(at)); |
(...skipping 22 matching lines...) Expand all Loading... |
608 // Instruction macros. | 608 // Instruction macros. |
609 | 609 |
610 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { | 610 void MacroAssembler::Addu(Register rd, Register rs, const Operand& rt) { |
611 if (rt.is_reg()) { | 611 if (rt.is_reg()) { |
612 addu(rd, rs, rt.rm()); | 612 addu(rd, rs, rt.rm()); |
613 } else { | 613 } else { |
614 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 614 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { |
615 addiu(rd, rs, rt.imm32_); | 615 addiu(rd, rs, rt.imm32_); |
616 } else { | 616 } else { |
617 // li handles the relocation. | 617 // li handles the relocation. |
618 ASSERT(!rs.is(at)); | 618 DCHECK(!rs.is(at)); |
619 li(at, rt); | 619 li(at, rt); |
620 addu(rd, rs, at); | 620 addu(rd, rs, at); |
621 } | 621 } |
622 } | 622 } |
623 } | 623 } |
624 | 624 |
625 | 625 |
626 void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) { | 626 void MacroAssembler::Subu(Register rd, Register rs, const Operand& rt) { |
627 if (rt.is_reg()) { | 627 if (rt.is_reg()) { |
628 subu(rd, rs, rt.rm()); | 628 subu(rd, rs, rt.rm()); |
629 } else { | 629 } else { |
630 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 630 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { |
631 addiu(rd, rs, -rt.imm32_); // No subiu instr, use addiu(x, y, -imm). | 631 addiu(rd, rs, -rt.imm32_); // No subiu instr, use addiu(x, y, -imm). |
632 } else { | 632 } else { |
633 // li handles the relocation. | 633 // li handles the relocation. |
634 ASSERT(!rs.is(at)); | 634 DCHECK(!rs.is(at)); |
635 li(at, rt); | 635 li(at, rt); |
636 subu(rd, rs, at); | 636 subu(rd, rs, at); |
637 } | 637 } |
638 } | 638 } |
639 } | 639 } |
640 | 640 |
641 | 641 |
642 void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) { | 642 void MacroAssembler::Mul(Register rd, Register rs, const Operand& rt) { |
643 if (rt.is_reg()) { | 643 if (rt.is_reg()) { |
644 if (kArchVariant == kLoongson) { | 644 if (kArchVariant == kLoongson) { |
645 mult(rs, rt.rm()); | 645 mult(rs, rt.rm()); |
646 mflo(rd); | 646 mflo(rd); |
647 } else { | 647 } else { |
648 mul(rd, rs, rt.rm()); | 648 mul(rd, rs, rt.rm()); |
649 } | 649 } |
650 } else { | 650 } else { |
651 // li handles the relocation. | 651 // li handles the relocation. |
652 ASSERT(!rs.is(at)); | 652 DCHECK(!rs.is(at)); |
653 li(at, rt); | 653 li(at, rt); |
654 if (kArchVariant == kLoongson) { | 654 if (kArchVariant == kLoongson) { |
655 mult(rs, at); | 655 mult(rs, at); |
656 mflo(rd); | 656 mflo(rd); |
657 } else { | 657 } else { |
658 mul(rd, rs, at); | 658 mul(rd, rs, at); |
659 } | 659 } |
660 } | 660 } |
661 } | 661 } |
662 | 662 |
663 | 663 |
664 void MacroAssembler::Mult(Register rs, const Operand& rt) { | 664 void MacroAssembler::Mult(Register rs, const Operand& rt) { |
665 if (rt.is_reg()) { | 665 if (rt.is_reg()) { |
666 mult(rs, rt.rm()); | 666 mult(rs, rt.rm()); |
667 } else { | 667 } else { |
668 // li handles the relocation. | 668 // li handles the relocation. |
669 ASSERT(!rs.is(at)); | 669 DCHECK(!rs.is(at)); |
670 li(at, rt); | 670 li(at, rt); |
671 mult(rs, at); | 671 mult(rs, at); |
672 } | 672 } |
673 } | 673 } |
674 | 674 |
675 | 675 |
676 void MacroAssembler::Multu(Register rs, const Operand& rt) { | 676 void MacroAssembler::Multu(Register rs, const Operand& rt) { |
677 if (rt.is_reg()) { | 677 if (rt.is_reg()) { |
678 multu(rs, rt.rm()); | 678 multu(rs, rt.rm()); |
679 } else { | 679 } else { |
680 // li handles the relocation. | 680 // li handles the relocation. |
681 ASSERT(!rs.is(at)); | 681 DCHECK(!rs.is(at)); |
682 li(at, rt); | 682 li(at, rt); |
683 multu(rs, at); | 683 multu(rs, at); |
684 } | 684 } |
685 } | 685 } |
686 | 686 |
687 | 687 |
688 void MacroAssembler::Div(Register rs, const Operand& rt) { | 688 void MacroAssembler::Div(Register rs, const Operand& rt) { |
689 if (rt.is_reg()) { | 689 if (rt.is_reg()) { |
690 div(rs, rt.rm()); | 690 div(rs, rt.rm()); |
691 } else { | 691 } else { |
692 // li handles the relocation. | 692 // li handles the relocation. |
693 ASSERT(!rs.is(at)); | 693 DCHECK(!rs.is(at)); |
694 li(at, rt); | 694 li(at, rt); |
695 div(rs, at); | 695 div(rs, at); |
696 } | 696 } |
697 } | 697 } |
698 | 698 |
699 | 699 |
700 void MacroAssembler::Divu(Register rs, const Operand& rt) { | 700 void MacroAssembler::Divu(Register rs, const Operand& rt) { |
701 if (rt.is_reg()) { | 701 if (rt.is_reg()) { |
702 divu(rs, rt.rm()); | 702 divu(rs, rt.rm()); |
703 } else { | 703 } else { |
704 // li handles the relocation. | 704 // li handles the relocation. |
705 ASSERT(!rs.is(at)); | 705 DCHECK(!rs.is(at)); |
706 li(at, rt); | 706 li(at, rt); |
707 divu(rs, at); | 707 divu(rs, at); |
708 } | 708 } |
709 } | 709 } |
710 | 710 |
711 | 711 |
712 void MacroAssembler::And(Register rd, Register rs, const Operand& rt) { | 712 void MacroAssembler::And(Register rd, Register rs, const Operand& rt) { |
713 if (rt.is_reg()) { | 713 if (rt.is_reg()) { |
714 and_(rd, rs, rt.rm()); | 714 and_(rd, rs, rt.rm()); |
715 } else { | 715 } else { |
716 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 716 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { |
717 andi(rd, rs, rt.imm32_); | 717 andi(rd, rs, rt.imm32_); |
718 } else { | 718 } else { |
719 // li handles the relocation. | 719 // li handles the relocation. |
720 ASSERT(!rs.is(at)); | 720 DCHECK(!rs.is(at)); |
721 li(at, rt); | 721 li(at, rt); |
722 and_(rd, rs, at); | 722 and_(rd, rs, at); |
723 } | 723 } |
724 } | 724 } |
725 } | 725 } |
726 | 726 |
727 | 727 |
728 void MacroAssembler::Or(Register rd, Register rs, const Operand& rt) { | 728 void MacroAssembler::Or(Register rd, Register rs, const Operand& rt) { |
729 if (rt.is_reg()) { | 729 if (rt.is_reg()) { |
730 or_(rd, rs, rt.rm()); | 730 or_(rd, rs, rt.rm()); |
731 } else { | 731 } else { |
732 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 732 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { |
733 ori(rd, rs, rt.imm32_); | 733 ori(rd, rs, rt.imm32_); |
734 } else { | 734 } else { |
735 // li handles the relocation. | 735 // li handles the relocation. |
736 ASSERT(!rs.is(at)); | 736 DCHECK(!rs.is(at)); |
737 li(at, rt); | 737 li(at, rt); |
738 or_(rd, rs, at); | 738 or_(rd, rs, at); |
739 } | 739 } |
740 } | 740 } |
741 } | 741 } |
742 | 742 |
743 | 743 |
744 void MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) { | 744 void MacroAssembler::Xor(Register rd, Register rs, const Operand& rt) { |
745 if (rt.is_reg()) { | 745 if (rt.is_reg()) { |
746 xor_(rd, rs, rt.rm()); | 746 xor_(rd, rs, rt.rm()); |
747 } else { | 747 } else { |
748 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 748 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { |
749 xori(rd, rs, rt.imm32_); | 749 xori(rd, rs, rt.imm32_); |
750 } else { | 750 } else { |
751 // li handles the relocation. | 751 // li handles the relocation. |
752 ASSERT(!rs.is(at)); | 752 DCHECK(!rs.is(at)); |
753 li(at, rt); | 753 li(at, rt); |
754 xor_(rd, rs, at); | 754 xor_(rd, rs, at); |
755 } | 755 } |
756 } | 756 } |
757 } | 757 } |
758 | 758 |
759 | 759 |
760 void MacroAssembler::Nor(Register rd, Register rs, const Operand& rt) { | 760 void MacroAssembler::Nor(Register rd, Register rs, const Operand& rt) { |
761 if (rt.is_reg()) { | 761 if (rt.is_reg()) { |
762 nor(rd, rs, rt.rm()); | 762 nor(rd, rs, rt.rm()); |
763 } else { | 763 } else { |
764 // li handles the relocation. | 764 // li handles the relocation. |
765 ASSERT(!rs.is(at)); | 765 DCHECK(!rs.is(at)); |
766 li(at, rt); | 766 li(at, rt); |
767 nor(rd, rs, at); | 767 nor(rd, rs, at); |
768 } | 768 } |
769 } | 769 } |
770 | 770 |
771 | 771 |
772 void MacroAssembler::Neg(Register rs, const Operand& rt) { | 772 void MacroAssembler::Neg(Register rs, const Operand& rt) { |
773 ASSERT(rt.is_reg()); | 773 DCHECK(rt.is_reg()); |
774 ASSERT(!at.is(rs)); | 774 DCHECK(!at.is(rs)); |
775 ASSERT(!at.is(rt.rm())); | 775 DCHECK(!at.is(rt.rm())); |
776 li(at, -1); | 776 li(at, -1); |
777 xor_(rs, rt.rm(), at); | 777 xor_(rs, rt.rm(), at); |
778 } | 778 } |
779 | 779 |
780 | 780 |
781 void MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) { | 781 void MacroAssembler::Slt(Register rd, Register rs, const Operand& rt) { |
782 if (rt.is_reg()) { | 782 if (rt.is_reg()) { |
783 slt(rd, rs, rt.rm()); | 783 slt(rd, rs, rt.rm()); |
784 } else { | 784 } else { |
785 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 785 if (is_int16(rt.imm32_) && !MustUseReg(rt.rmode_)) { |
786 slti(rd, rs, rt.imm32_); | 786 slti(rd, rs, rt.imm32_); |
787 } else { | 787 } else { |
788 // li handles the relocation. | 788 // li handles the relocation. |
789 ASSERT(!rs.is(at)); | 789 DCHECK(!rs.is(at)); |
790 li(at, rt); | 790 li(at, rt); |
791 slt(rd, rs, at); | 791 slt(rd, rs, at); |
792 } | 792 } |
793 } | 793 } |
794 } | 794 } |
795 | 795 |
796 | 796 |
797 void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) { | 797 void MacroAssembler::Sltu(Register rd, Register rs, const Operand& rt) { |
798 if (rt.is_reg()) { | 798 if (rt.is_reg()) { |
799 sltu(rd, rs, rt.rm()); | 799 sltu(rd, rs, rt.rm()); |
800 } else { | 800 } else { |
801 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { | 801 if (is_uint16(rt.imm32_) && !MustUseReg(rt.rmode_)) { |
802 sltiu(rd, rs, rt.imm32_); | 802 sltiu(rd, rs, rt.imm32_); |
803 } else { | 803 } else { |
804 // li handles the relocation. | 804 // li handles the relocation. |
805 ASSERT(!rs.is(at)); | 805 DCHECK(!rs.is(at)); |
806 li(at, rt); | 806 li(at, rt); |
807 sltu(rd, rs, at); | 807 sltu(rd, rs, at); |
808 } | 808 } |
809 } | 809 } |
810 } | 810 } |
811 | 811 |
812 | 812 |
813 void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) { | 813 void MacroAssembler::Ror(Register rd, Register rs, const Operand& rt) { |
814 if (kArchVariant == kMips32r2) { | 814 if (kArchVariant == kMips32r2) { |
815 if (rt.is_reg()) { | 815 if (rt.is_reg()) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 swr(rd, rs); | 857 swr(rd, rs); |
858 swl(rd, MemOperand(rs.rm(), rs.offset() + 3)); | 858 swl(rd, MemOperand(rs.rm(), rs.offset() + 3)); |
859 } | 859 } |
860 | 860 |
861 | 861 |
862 void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) { | 862 void MacroAssembler::li(Register dst, Handle<Object> value, LiFlags mode) { |
863 AllowDeferredHandleDereference smi_check; | 863 AllowDeferredHandleDereference smi_check; |
864 if (value->IsSmi()) { | 864 if (value->IsSmi()) { |
865 li(dst, Operand(value), mode); | 865 li(dst, Operand(value), mode); |
866 } else { | 866 } else { |
867 ASSERT(value->IsHeapObject()); | 867 DCHECK(value->IsHeapObject()); |
868 if (isolate()->heap()->InNewSpace(*value)) { | 868 if (isolate()->heap()->InNewSpace(*value)) { |
869 Handle<Cell> cell = isolate()->factory()->NewCell(value); | 869 Handle<Cell> cell = isolate()->factory()->NewCell(value); |
870 li(dst, Operand(cell)); | 870 li(dst, Operand(cell)); |
871 lw(dst, FieldMemOperand(dst, Cell::kValueOffset)); | 871 lw(dst, FieldMemOperand(dst, Cell::kValueOffset)); |
872 } else { | 872 } else { |
873 li(dst, Operand(value)); | 873 li(dst, Operand(value)); |
874 } | 874 } |
875 } | 875 } |
876 } | 876 } |
877 | 877 |
878 | 878 |
879 void MacroAssembler::li(Register rd, Operand j, LiFlags mode) { | 879 void MacroAssembler::li(Register rd, Operand j, LiFlags mode) { |
880 ASSERT(!j.is_reg()); | 880 DCHECK(!j.is_reg()); |
881 BlockTrampolinePoolScope block_trampoline_pool(this); | 881 BlockTrampolinePoolScope block_trampoline_pool(this); |
882 if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) { | 882 if (!MustUseReg(j.rmode_) && mode == OPTIMIZE_SIZE) { |
883 // Normal load of an immediate value which does not need Relocation Info. | 883 // Normal load of an immediate value which does not need Relocation Info. |
884 if (is_int16(j.imm32_)) { | 884 if (is_int16(j.imm32_)) { |
885 addiu(rd, zero_reg, j.imm32_); | 885 addiu(rd, zero_reg, j.imm32_); |
886 } else if (!(j.imm32_ & kHiMask)) { | 886 } else if (!(j.imm32_ & kHiMask)) { |
887 ori(rd, zero_reg, j.imm32_); | 887 ori(rd, zero_reg, j.imm32_); |
888 } else if (!(j.imm32_ & kImm16Mask)) { | 888 } else if (!(j.imm32_ & kImm16Mask)) { |
889 lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask); | 889 lui(rd, (j.imm32_ >> kLuiShift) & kImm16Mask); |
890 } else { | 890 } else { |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1023 li(a1, instructions * kInstrSize); | 1023 li(a1, instructions * kInstrSize); |
1024 CallCFunction(ExternalReference::flush_icache_function(isolate()), 2); | 1024 CallCFunction(ExternalReference::flush_icache_function(isolate()), 2); |
1025 MultiPop(saved_regs); | 1025 MultiPop(saved_regs); |
1026 } | 1026 } |
1027 | 1027 |
1028 | 1028 |
1029 void MacroAssembler::Ext(Register rt, | 1029 void MacroAssembler::Ext(Register rt, |
1030 Register rs, | 1030 Register rs, |
1031 uint16_t pos, | 1031 uint16_t pos, |
1032 uint16_t size) { | 1032 uint16_t size) { |
1033 ASSERT(pos < 32); | 1033 DCHECK(pos < 32); |
1034 ASSERT(pos + size < 33); | 1034 DCHECK(pos + size < 33); |
1035 | 1035 |
1036 if (kArchVariant == kMips32r2) { | 1036 if (kArchVariant == kMips32r2) { |
1037 ext_(rt, rs, pos, size); | 1037 ext_(rt, rs, pos, size); |
1038 } else { | 1038 } else { |
1039 // Move rs to rt and shift it left then right to get the | 1039 // Move rs to rt and shift it left then right to get the |
1040 // desired bitfield on the right side and zeroes on the left. | 1040 // desired bitfield on the right side and zeroes on the left. |
1041 int shift_left = 32 - (pos + size); | 1041 int shift_left = 32 - (pos + size); |
1042 sll(rt, rs, shift_left); // Acts as a move if shift_left == 0. | 1042 sll(rt, rs, shift_left); // Acts as a move if shift_left == 0. |
1043 | 1043 |
1044 int shift_right = 32 - size; | 1044 int shift_right = 32 - size; |
1045 if (shift_right > 0) { | 1045 if (shift_right > 0) { |
1046 srl(rt, rt, shift_right); | 1046 srl(rt, rt, shift_right); |
1047 } | 1047 } |
1048 } | 1048 } |
1049 } | 1049 } |
1050 | 1050 |
1051 | 1051 |
1052 void MacroAssembler::Ins(Register rt, | 1052 void MacroAssembler::Ins(Register rt, |
1053 Register rs, | 1053 Register rs, |
1054 uint16_t pos, | 1054 uint16_t pos, |
1055 uint16_t size) { | 1055 uint16_t size) { |
1056 ASSERT(pos < 32); | 1056 DCHECK(pos < 32); |
1057 ASSERT(pos + size <= 32); | 1057 DCHECK(pos + size <= 32); |
1058 ASSERT(size != 0); | 1058 DCHECK(size != 0); |
1059 | 1059 |
1060 if (kArchVariant == kMips32r2) { | 1060 if (kArchVariant == kMips32r2) { |
1061 ins_(rt, rs, pos, size); | 1061 ins_(rt, rs, pos, size); |
1062 } else { | 1062 } else { |
1063 ASSERT(!rt.is(t8) && !rs.is(t8)); | 1063 DCHECK(!rt.is(t8) && !rs.is(t8)); |
1064 Subu(at, zero_reg, Operand(1)); | 1064 Subu(at, zero_reg, Operand(1)); |
1065 srl(at, at, 32 - size); | 1065 srl(at, at, 32 - size); |
1066 and_(t8, rs, at); | 1066 and_(t8, rs, at); |
1067 sll(t8, t8, pos); | 1067 sll(t8, t8, pos); |
1068 sll(at, at, pos); | 1068 sll(at, at, pos); |
1069 nor(at, at, zero_reg); | 1069 nor(at, at, zero_reg); |
1070 and_(at, rt, at); | 1070 and_(at, rt, at); |
1071 or_(rt, t8, at); | 1071 or_(rt, t8, at); |
1072 } | 1072 } |
1073 } | 1073 } |
1074 | 1074 |
1075 | 1075 |
1076 void MacroAssembler::Cvt_d_uw(FPURegister fd, | 1076 void MacroAssembler::Cvt_d_uw(FPURegister fd, |
1077 FPURegister fs, | 1077 FPURegister fs, |
1078 FPURegister scratch) { | 1078 FPURegister scratch) { |
1079 // Move the data from fs to t8. | 1079 // Move the data from fs to t8. |
1080 mfc1(t8, fs); | 1080 mfc1(t8, fs); |
1081 Cvt_d_uw(fd, t8, scratch); | 1081 Cvt_d_uw(fd, t8, scratch); |
1082 } | 1082 } |
1083 | 1083 |
1084 | 1084 |
1085 void MacroAssembler::Cvt_d_uw(FPURegister fd, | 1085 void MacroAssembler::Cvt_d_uw(FPURegister fd, |
1086 Register rs, | 1086 Register rs, |
1087 FPURegister scratch) { | 1087 FPURegister scratch) { |
1088 // Convert rs to a FP value in fd (and fd + 1). | 1088 // Convert rs to a FP value in fd (and fd + 1). |
1089 // We do this by converting rs minus the MSB to avoid sign conversion, | 1089 // We do this by converting rs minus the MSB to avoid sign conversion, |
1090 // then adding 2^31 to the result (if needed). | 1090 // then adding 2^31 to the result (if needed). |
1091 | 1091 |
1092 ASSERT(!fd.is(scratch)); | 1092 DCHECK(!fd.is(scratch)); |
1093 ASSERT(!rs.is(t9)); | 1093 DCHECK(!rs.is(t9)); |
1094 ASSERT(!rs.is(at)); | 1094 DCHECK(!rs.is(at)); |
1095 | 1095 |
1096 // Save rs's MSB to t9. | 1096 // Save rs's MSB to t9. |
1097 Ext(t9, rs, 31, 1); | 1097 Ext(t9, rs, 31, 1); |
1098 // Remove rs's MSB. | 1098 // Remove rs's MSB. |
1099 Ext(at, rs, 0, 31); | 1099 Ext(at, rs, 0, 31); |
1100 // Move the result to fd. | 1100 // Move the result to fd. |
1101 mtc1(at, fd); | 1101 mtc1(at, fd); |
1102 | 1102 |
1103 // Convert fd to a real FP value. | 1103 // Convert fd to a real FP value. |
1104 cvt_d_w(fd, fd); | 1104 cvt_d_w(fd, fd); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1168 mtc1(t8, FPURegister::from_code(fs.code() + 1)); | 1168 mtc1(t8, FPURegister::from_code(fs.code() + 1)); |
1169 } else { | 1169 } else { |
1170 ceil_w_d(fd, fs); | 1170 ceil_w_d(fd, fs); |
1171 } | 1171 } |
1172 } | 1172 } |
1173 | 1173 |
1174 | 1174 |
1175 void MacroAssembler::Trunc_uw_d(FPURegister fd, | 1175 void MacroAssembler::Trunc_uw_d(FPURegister fd, |
1176 Register rs, | 1176 Register rs, |
1177 FPURegister scratch) { | 1177 FPURegister scratch) { |
1178 ASSERT(!fd.is(scratch)); | 1178 DCHECK(!fd.is(scratch)); |
1179 ASSERT(!rs.is(at)); | 1179 DCHECK(!rs.is(at)); |
1180 | 1180 |
1181 // Load 2^31 into scratch as its float representation. | 1181 // Load 2^31 into scratch as its float representation. |
1182 li(at, 0x41E00000); | 1182 li(at, 0x41E00000); |
1183 mtc1(at, FPURegister::from_code(scratch.code() + 1)); | 1183 mtc1(at, FPURegister::from_code(scratch.code() + 1)); |
1184 mtc1(zero_reg, scratch); | 1184 mtc1(zero_reg, scratch); |
1185 // Test if scratch > fd. | 1185 // Test if scratch > fd. |
1186 // If fd < 2^31 we can convert it normally. | 1186 // If fd < 2^31 we can convert it normally. |
1187 Label simple_convert; | 1187 Label simple_convert; |
1188 BranchF(&simple_convert, NULL, lt, fd, scratch); | 1188 BranchF(&simple_convert, NULL, lt, fd, scratch); |
1189 | 1189 |
(...skipping 20 matching lines...) Expand all Loading... |
1210 Condition cc, | 1210 Condition cc, |
1211 FPURegister cmp1, | 1211 FPURegister cmp1, |
1212 FPURegister cmp2, | 1212 FPURegister cmp2, |
1213 BranchDelaySlot bd) { | 1213 BranchDelaySlot bd) { |
1214 BlockTrampolinePoolScope block_trampoline_pool(this); | 1214 BlockTrampolinePoolScope block_trampoline_pool(this); |
1215 if (cc == al) { | 1215 if (cc == al) { |
1216 Branch(bd, target); | 1216 Branch(bd, target); |
1217 return; | 1217 return; |
1218 } | 1218 } |
1219 | 1219 |
1220 ASSERT(nan || target); | 1220 DCHECK(nan || target); |
1221 // Check for unordered (NaN) cases. | 1221 // Check for unordered (NaN) cases. |
1222 if (nan) { | 1222 if (nan) { |
1223 c(UN, D, cmp1, cmp2); | 1223 c(UN, D, cmp1, cmp2); |
1224 bc1t(nan); | 1224 bc1t(nan); |
1225 } | 1225 } |
1226 | 1226 |
1227 if (target) { | 1227 if (target) { |
1228 // Here NaN cases were either handled by this function or are assumed to | 1228 // Here NaN cases were either handled by this function or are assumed to |
1229 // have been handled by the caller. | 1229 // have been handled by the caller. |
1230 // Unsigned conditions are treated as their signed counterpart. | 1230 // Unsigned conditions are treated as their signed counterpart. |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1326 } else { | 1326 } else { |
1327 movn(rd, rs, rt); | 1327 movn(rd, rs, rt); |
1328 } | 1328 } |
1329 } | 1329 } |
1330 | 1330 |
1331 | 1331 |
1332 void MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) { | 1332 void MacroAssembler::Movt(Register rd, Register rs, uint16_t cc) { |
1333 if (kArchVariant == kLoongson) { | 1333 if (kArchVariant == kLoongson) { |
1334 // Tests an FP condition code and then conditionally move rs to rd. | 1334 // Tests an FP condition code and then conditionally move rs to rd. |
1335 // We do not currently use any FPU cc bit other than bit 0. | 1335 // We do not currently use any FPU cc bit other than bit 0. |
1336 ASSERT(cc == 0); | 1336 DCHECK(cc == 0); |
1337 ASSERT(!(rs.is(t8) || rd.is(t8))); | 1337 DCHECK(!(rs.is(t8) || rd.is(t8))); |
1338 Label done; | 1338 Label done; |
1339 Register scratch = t8; | 1339 Register scratch = t8; |
1340 // For testing purposes we need to fetch content of the FCSR register and | 1340 // For testing purposes we need to fetch content of the FCSR register and |
1341 // than test its cc (floating point condition code) bit (for cc = 0, it is | 1341 // than test its cc (floating point condition code) bit (for cc = 0, it is |
1342 // 24. bit of the FCSR). | 1342 // 24. bit of the FCSR). |
1343 cfc1(scratch, FCSR); | 1343 cfc1(scratch, FCSR); |
1344 // For the MIPS I, II and III architectures, the contents of scratch is | 1344 // For the MIPS I, II and III architectures, the contents of scratch is |
1345 // UNPREDICTABLE for the instruction immediately following CFC1. | 1345 // UNPREDICTABLE for the instruction immediately following CFC1. |
1346 nop(); | 1346 nop(); |
1347 srl(scratch, scratch, 16); | 1347 srl(scratch, scratch, 16); |
1348 andi(scratch, scratch, 0x0080); | 1348 andi(scratch, scratch, 0x0080); |
1349 Branch(&done, eq, scratch, Operand(zero_reg)); | 1349 Branch(&done, eq, scratch, Operand(zero_reg)); |
1350 mov(rd, rs); | 1350 mov(rd, rs); |
1351 bind(&done); | 1351 bind(&done); |
1352 } else { | 1352 } else { |
1353 movt(rd, rs, cc); | 1353 movt(rd, rs, cc); |
1354 } | 1354 } |
1355 } | 1355 } |
1356 | 1356 |
1357 | 1357 |
1358 void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) { | 1358 void MacroAssembler::Movf(Register rd, Register rs, uint16_t cc) { |
1359 if (kArchVariant == kLoongson) { | 1359 if (kArchVariant == kLoongson) { |
1360 // Tests an FP condition code and then conditionally move rs to rd. | 1360 // Tests an FP condition code and then conditionally move rs to rd. |
1361 // We do not currently use any FPU cc bit other than bit 0. | 1361 // We do not currently use any FPU cc bit other than bit 0. |
1362 ASSERT(cc == 0); | 1362 DCHECK(cc == 0); |
1363 ASSERT(!(rs.is(t8) || rd.is(t8))); | 1363 DCHECK(!(rs.is(t8) || rd.is(t8))); |
1364 Label done; | 1364 Label done; |
1365 Register scratch = t8; | 1365 Register scratch = t8; |
1366 // For testing purposes we need to fetch content of the FCSR register and | 1366 // For testing purposes we need to fetch content of the FCSR register and |
1367 // than test its cc (floating point condition code) bit (for cc = 0, it is | 1367 // than test its cc (floating point condition code) bit (for cc = 0, it is |
1368 // 24. bit of the FCSR). | 1368 // 24. bit of the FCSR). |
1369 cfc1(scratch, FCSR); | 1369 cfc1(scratch, FCSR); |
1370 // For the MIPS I, II and III architectures, the contents of scratch is | 1370 // For the MIPS I, II and III architectures, the contents of scratch is |
1371 // UNPREDICTABLE for the instruction immediately following CFC1. | 1371 // UNPREDICTABLE for the instruction immediately following CFC1. |
1372 nop(); | 1372 nop(); |
1373 srl(scratch, scratch, 16); | 1373 srl(scratch, scratch, 16); |
1374 andi(scratch, scratch, 0x0080); | 1374 andi(scratch, scratch, 0x0080); |
1375 Branch(&done, ne, scratch, Operand(zero_reg)); | 1375 Branch(&done, ne, scratch, Operand(zero_reg)); |
1376 mov(rd, rs); | 1376 mov(rd, rs); |
1377 bind(&done); | 1377 bind(&done); |
1378 } else { | 1378 } else { |
1379 movf(rd, rs, cc); | 1379 movf(rd, rs, cc); |
1380 } | 1380 } |
1381 } | 1381 } |
1382 | 1382 |
1383 | 1383 |
1384 void MacroAssembler::Clz(Register rd, Register rs) { | 1384 void MacroAssembler::Clz(Register rd, Register rs) { |
1385 if (kArchVariant == kLoongson) { | 1385 if (kArchVariant == kLoongson) { |
1386 ASSERT(!(rd.is(t8) || rd.is(t9)) && !(rs.is(t8) || rs.is(t9))); | 1386 DCHECK(!(rd.is(t8) || rd.is(t9)) && !(rs.is(t8) || rs.is(t9))); |
1387 Register mask = t8; | 1387 Register mask = t8; |
1388 Register scratch = t9; | 1388 Register scratch = t9; |
1389 Label loop, end; | 1389 Label loop, end; |
1390 mov(at, rs); | 1390 mov(at, rs); |
1391 mov(rd, zero_reg); | 1391 mov(rd, zero_reg); |
1392 lui(mask, 0x8000); | 1392 lui(mask, 0x8000); |
1393 bind(&loop); | 1393 bind(&loop); |
1394 and_(scratch, at, mask); | 1394 and_(scratch, at, mask); |
1395 Branch(&end, ne, scratch, Operand(zero_reg)); | 1395 Branch(&end, ne, scratch, Operand(zero_reg)); |
1396 addiu(rd, rd, 1); | 1396 addiu(rd, rd, 1); |
1397 Branch(&loop, ne, mask, Operand(zero_reg), USE_DELAY_SLOT); | 1397 Branch(&loop, ne, mask, Operand(zero_reg), USE_DELAY_SLOT); |
1398 srl(mask, mask, 1); | 1398 srl(mask, mask, 1); |
1399 bind(&end); | 1399 bind(&end); |
1400 } else { | 1400 } else { |
1401 clz(rd, rs); | 1401 clz(rd, rs); |
1402 } | 1402 } |
1403 } | 1403 } |
1404 | 1404 |
1405 | 1405 |
1406 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode, | 1406 void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode, |
1407 Register result, | 1407 Register result, |
1408 DoubleRegister double_input, | 1408 DoubleRegister double_input, |
1409 Register scratch, | 1409 Register scratch, |
1410 DoubleRegister double_scratch, | 1410 DoubleRegister double_scratch, |
1411 Register except_flag, | 1411 Register except_flag, |
1412 CheckForInexactConversion check_inexact) { | 1412 CheckForInexactConversion check_inexact) { |
1413 ASSERT(!result.is(scratch)); | 1413 DCHECK(!result.is(scratch)); |
1414 ASSERT(!double_input.is(double_scratch)); | 1414 DCHECK(!double_input.is(double_scratch)); |
1415 ASSERT(!except_flag.is(scratch)); | 1415 DCHECK(!except_flag.is(scratch)); |
1416 | 1416 |
1417 Label done; | 1417 Label done; |
1418 | 1418 |
1419 // Clear the except flag (0 = no exception) | 1419 // Clear the except flag (0 = no exception) |
1420 mov(except_flag, zero_reg); | 1420 mov(except_flag, zero_reg); |
1421 | 1421 |
1422 // Test for values that can be exactly represented as a signed 32-bit integer. | 1422 // Test for values that can be exactly represented as a signed 32-bit integer. |
1423 cvt_w_d(double_scratch, double_input); | 1423 cvt_w_d(double_scratch, double_input); |
1424 mfc1(result, double_scratch); | 1424 mfc1(result, double_scratch); |
1425 cvt_d_w(double_scratch, double_scratch); | 1425 cvt_d_w(double_scratch, double_scratch); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1509 Addu(sp, sp, Operand(kDoubleSize)); | 1509 Addu(sp, sp, Operand(kDoubleSize)); |
1510 pop(ra); | 1510 pop(ra); |
1511 | 1511 |
1512 bind(&done); | 1512 bind(&done); |
1513 } | 1513 } |
1514 | 1514 |
1515 | 1515 |
1516 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) { | 1516 void MacroAssembler::TruncateHeapNumberToI(Register result, Register object) { |
1517 Label done; | 1517 Label done; |
1518 DoubleRegister double_scratch = f12; | 1518 DoubleRegister double_scratch = f12; |
1519 ASSERT(!result.is(object)); | 1519 DCHECK(!result.is(object)); |
1520 | 1520 |
1521 ldc1(double_scratch, | 1521 ldc1(double_scratch, |
1522 MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag)); | 1522 MemOperand(object, HeapNumber::kValueOffset - kHeapObjectTag)); |
1523 TryInlineTruncateDoubleToI(result, double_scratch, &done); | 1523 TryInlineTruncateDoubleToI(result, double_scratch, &done); |
1524 | 1524 |
1525 // If we fell through then inline version didn't succeed - call stub instead. | 1525 // If we fell through then inline version didn't succeed - call stub instead. |
1526 push(ra); | 1526 push(ra); |
1527 DoubleToIStub stub(isolate(), | 1527 DoubleToIStub stub(isolate(), |
1528 object, | 1528 object, |
1529 result, | 1529 result, |
1530 HeapNumber::kValueOffset - kHeapObjectTag, | 1530 HeapNumber::kValueOffset - kHeapObjectTag, |
1531 true, | 1531 true, |
1532 true); | 1532 true); |
1533 CallStub(&stub); | 1533 CallStub(&stub); |
1534 pop(ra); | 1534 pop(ra); |
1535 | 1535 |
1536 bind(&done); | 1536 bind(&done); |
1537 } | 1537 } |
1538 | 1538 |
1539 | 1539 |
1540 void MacroAssembler::TruncateNumberToI(Register object, | 1540 void MacroAssembler::TruncateNumberToI(Register object, |
1541 Register result, | 1541 Register result, |
1542 Register heap_number_map, | 1542 Register heap_number_map, |
1543 Register scratch, | 1543 Register scratch, |
1544 Label* not_number) { | 1544 Label* not_number) { |
1545 Label done; | 1545 Label done; |
1546 ASSERT(!result.is(object)); | 1546 DCHECK(!result.is(object)); |
1547 | 1547 |
1548 UntagAndJumpIfSmi(result, object, &done); | 1548 UntagAndJumpIfSmi(result, object, &done); |
1549 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); | 1549 JumpIfNotHeapNumber(object, heap_number_map, scratch, not_number); |
1550 TruncateHeapNumberToI(result, object); | 1550 TruncateHeapNumberToI(result, object); |
1551 | 1551 |
1552 bind(&done); | 1552 bind(&done); |
1553 } | 1553 } |
1554 | 1554 |
1555 | 1555 |
1556 void MacroAssembler::GetLeastBitsFromSmi(Register dst, | 1556 void MacroAssembler::GetLeastBitsFromSmi(Register dst, |
1557 Register src, | 1557 Register src, |
1558 int num_least_bits) { | 1558 int num_least_bits) { |
1559 Ext(dst, src, kSmiTagSize, num_least_bits); | 1559 Ext(dst, src, kSmiTagSize, num_least_bits); |
1560 } | 1560 } |
1561 | 1561 |
1562 | 1562 |
1563 void MacroAssembler::GetLeastBitsFromInt32(Register dst, | 1563 void MacroAssembler::GetLeastBitsFromInt32(Register dst, |
1564 Register src, | 1564 Register src, |
1565 int num_least_bits) { | 1565 int num_least_bits) { |
1566 And(dst, src, Operand((1 << num_least_bits) - 1)); | 1566 And(dst, src, Operand((1 << num_least_bits) - 1)); |
1567 } | 1567 } |
1568 | 1568 |
1569 | 1569 |
1570 // Emulated condtional branches do not emit a nop in the branch delay slot. | 1570 // Emulated condtional branches do not emit a nop in the branch delay slot. |
1571 // | 1571 // |
1572 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. | 1572 // BRANCH_ARGS_CHECK checks that conditional jump arguments are correct. |
1573 #define BRANCH_ARGS_CHECK(cond, rs, rt) ASSERT( \ | 1573 #define BRANCH_ARGS_CHECK(cond, rs, rt) DCHECK( \ |
1574 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ | 1574 (cond == cc_always && rs.is(zero_reg) && rt.rm().is(zero_reg)) || \ |
1575 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) | 1575 (cond != cc_always && (!rs.is(zero_reg) || !rt.rm().is(zero_reg)))) |
1576 | 1576 |
1577 | 1577 |
1578 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { | 1578 void MacroAssembler::Branch(int16_t offset, BranchDelaySlot bdslot) { |
1579 BranchShort(offset, bdslot); | 1579 BranchShort(offset, bdslot); |
1580 } | 1580 } |
1581 | 1581 |
1582 | 1582 |
1583 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, | 1583 void MacroAssembler::Branch(int16_t offset, Condition cond, Register rs, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1655 // Emit a nop in the branch delay slot if required. | 1655 // Emit a nop in the branch delay slot if required. |
1656 if (bdslot == PROTECT) | 1656 if (bdslot == PROTECT) |
1657 nop(); | 1657 nop(); |
1658 } | 1658 } |
1659 | 1659 |
1660 | 1660 |
1661 void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs, | 1661 void MacroAssembler::BranchShort(int16_t offset, Condition cond, Register rs, |
1662 const Operand& rt, | 1662 const Operand& rt, |
1663 BranchDelaySlot bdslot) { | 1663 BranchDelaySlot bdslot) { |
1664 BRANCH_ARGS_CHECK(cond, rs, rt); | 1664 BRANCH_ARGS_CHECK(cond, rs, rt); |
1665 ASSERT(!rs.is(zero_reg)); | 1665 DCHECK(!rs.is(zero_reg)); |
1666 Register r2 = no_reg; | 1666 Register r2 = no_reg; |
1667 Register scratch = at; | 1667 Register scratch = at; |
1668 | 1668 |
1669 if (rt.is_reg()) { | 1669 if (rt.is_reg()) { |
1670 // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or | 1670 // NOTE: 'at' can be clobbered by Branch but it is legal to use it as rs or |
1671 // rt. | 1671 // rt. |
1672 BlockTrampolinePoolScope block_trampoline_pool(this); | 1672 BlockTrampolinePoolScope block_trampoline_pool(this); |
1673 r2 = rt.rm_; | 1673 r2 = rt.rm_; |
1674 switch (cond) { | 1674 switch (cond) { |
1675 case cc_always: | 1675 case cc_always: |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1755 // Be careful to always use shifted_branch_offset only just before the | 1755 // Be careful to always use shifted_branch_offset only just before the |
1756 // branch instruction, as the location will be remember for patching the | 1756 // branch instruction, as the location will be remember for patching the |
1757 // target. | 1757 // target. |
1758 BlockTrampolinePoolScope block_trampoline_pool(this); | 1758 BlockTrampolinePoolScope block_trampoline_pool(this); |
1759 switch (cond) { | 1759 switch (cond) { |
1760 case cc_always: | 1760 case cc_always: |
1761 b(offset); | 1761 b(offset); |
1762 break; | 1762 break; |
1763 case eq: | 1763 case eq: |
1764 // We don't want any other register but scratch clobbered. | 1764 // We don't want any other register but scratch clobbered. |
1765 ASSERT(!scratch.is(rs)); | 1765 DCHECK(!scratch.is(rs)); |
1766 r2 = scratch; | 1766 r2 = scratch; |
1767 li(r2, rt); | 1767 li(r2, rt); |
1768 beq(rs, r2, offset); | 1768 beq(rs, r2, offset); |
1769 break; | 1769 break; |
1770 case ne: | 1770 case ne: |
1771 // We don't want any other register but scratch clobbered. | 1771 // We don't want any other register but scratch clobbered. |
1772 ASSERT(!scratch.is(rs)); | 1772 DCHECK(!scratch.is(rs)); |
1773 r2 = scratch; | 1773 r2 = scratch; |
1774 li(r2, rt); | 1774 li(r2, rt); |
1775 bne(rs, r2, offset); | 1775 bne(rs, r2, offset); |
1776 break; | 1776 break; |
1777 // Signed comparison. | 1777 // Signed comparison. |
1778 case greater: | 1778 case greater: |
1779 if (rt.imm32_ == 0) { | 1779 if (rt.imm32_ == 0) { |
1780 bgtz(rs, offset); | 1780 bgtz(rs, offset); |
1781 } else { | 1781 } else { |
1782 r2 = scratch; | 1782 r2 = scratch; |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2007 // Be careful to always use shifted_branch_offset only just before the | 2007 // Be careful to always use shifted_branch_offset only just before the |
2008 // branch instruction, as the location will be remember for patching the | 2008 // branch instruction, as the location will be remember for patching the |
2009 // target. | 2009 // target. |
2010 BlockTrampolinePoolScope block_trampoline_pool(this); | 2010 BlockTrampolinePoolScope block_trampoline_pool(this); |
2011 switch (cond) { | 2011 switch (cond) { |
2012 case cc_always: | 2012 case cc_always: |
2013 offset = shifted_branch_offset(L, false); | 2013 offset = shifted_branch_offset(L, false); |
2014 b(offset); | 2014 b(offset); |
2015 break; | 2015 break; |
2016 case eq: | 2016 case eq: |
2017 ASSERT(!scratch.is(rs)); | 2017 DCHECK(!scratch.is(rs)); |
2018 r2 = scratch; | 2018 r2 = scratch; |
2019 li(r2, rt); | 2019 li(r2, rt); |
2020 offset = shifted_branch_offset(L, false); | 2020 offset = shifted_branch_offset(L, false); |
2021 beq(rs, r2, offset); | 2021 beq(rs, r2, offset); |
2022 break; | 2022 break; |
2023 case ne: | 2023 case ne: |
2024 ASSERT(!scratch.is(rs)); | 2024 DCHECK(!scratch.is(rs)); |
2025 r2 = scratch; | 2025 r2 = scratch; |
2026 li(r2, rt); | 2026 li(r2, rt); |
2027 offset = shifted_branch_offset(L, false); | 2027 offset = shifted_branch_offset(L, false); |
2028 bne(rs, r2, offset); | 2028 bne(rs, r2, offset); |
2029 break; | 2029 break; |
2030 // Signed comparison. | 2030 // Signed comparison. |
2031 case greater: | 2031 case greater: |
2032 if (rt.imm32_ == 0) { | 2032 if (rt.imm32_ == 0) { |
2033 offset = shifted_branch_offset(L, false); | 2033 offset = shifted_branch_offset(L, false); |
2034 bgtz(rs, offset); | 2034 bgtz(rs, offset); |
2035 } else { | 2035 } else { |
2036 ASSERT(!scratch.is(rs)); | 2036 DCHECK(!scratch.is(rs)); |
2037 r2 = scratch; | 2037 r2 = scratch; |
2038 li(r2, rt); | 2038 li(r2, rt); |
2039 slt(scratch, r2, rs); | 2039 slt(scratch, r2, rs); |
2040 offset = shifted_branch_offset(L, false); | 2040 offset = shifted_branch_offset(L, false); |
2041 bne(scratch, zero_reg, offset); | 2041 bne(scratch, zero_reg, offset); |
2042 } | 2042 } |
2043 break; | 2043 break; |
2044 case greater_equal: | 2044 case greater_equal: |
2045 if (rt.imm32_ == 0) { | 2045 if (rt.imm32_ == 0) { |
2046 offset = shifted_branch_offset(L, false); | 2046 offset = shifted_branch_offset(L, false); |
2047 bgez(rs, offset); | 2047 bgez(rs, offset); |
2048 } else if (is_int16(rt.imm32_)) { | 2048 } else if (is_int16(rt.imm32_)) { |
2049 slti(scratch, rs, rt.imm32_); | 2049 slti(scratch, rs, rt.imm32_); |
2050 offset = shifted_branch_offset(L, false); | 2050 offset = shifted_branch_offset(L, false); |
2051 beq(scratch, zero_reg, offset); | 2051 beq(scratch, zero_reg, offset); |
2052 } else { | 2052 } else { |
2053 ASSERT(!scratch.is(rs)); | 2053 DCHECK(!scratch.is(rs)); |
2054 r2 = scratch; | 2054 r2 = scratch; |
2055 li(r2, rt); | 2055 li(r2, rt); |
2056 slt(scratch, rs, r2); | 2056 slt(scratch, rs, r2); |
2057 offset = shifted_branch_offset(L, false); | 2057 offset = shifted_branch_offset(L, false); |
2058 beq(scratch, zero_reg, offset); | 2058 beq(scratch, zero_reg, offset); |
2059 } | 2059 } |
2060 break; | 2060 break; |
2061 case less: | 2061 case less: |
2062 if (rt.imm32_ == 0) { | 2062 if (rt.imm32_ == 0) { |
2063 offset = shifted_branch_offset(L, false); | 2063 offset = shifted_branch_offset(L, false); |
2064 bltz(rs, offset); | 2064 bltz(rs, offset); |
2065 } else if (is_int16(rt.imm32_)) { | 2065 } else if (is_int16(rt.imm32_)) { |
2066 slti(scratch, rs, rt.imm32_); | 2066 slti(scratch, rs, rt.imm32_); |
2067 offset = shifted_branch_offset(L, false); | 2067 offset = shifted_branch_offset(L, false); |
2068 bne(scratch, zero_reg, offset); | 2068 bne(scratch, zero_reg, offset); |
2069 } else { | 2069 } else { |
2070 ASSERT(!scratch.is(rs)); | 2070 DCHECK(!scratch.is(rs)); |
2071 r2 = scratch; | 2071 r2 = scratch; |
2072 li(r2, rt); | 2072 li(r2, rt); |
2073 slt(scratch, rs, r2); | 2073 slt(scratch, rs, r2); |
2074 offset = shifted_branch_offset(L, false); | 2074 offset = shifted_branch_offset(L, false); |
2075 bne(scratch, zero_reg, offset); | 2075 bne(scratch, zero_reg, offset); |
2076 } | 2076 } |
2077 break; | 2077 break; |
2078 case less_equal: | 2078 case less_equal: |
2079 if (rt.imm32_ == 0) { | 2079 if (rt.imm32_ == 0) { |
2080 offset = shifted_branch_offset(L, false); | 2080 offset = shifted_branch_offset(L, false); |
2081 blez(rs, offset); | 2081 blez(rs, offset); |
2082 } else { | 2082 } else { |
2083 ASSERT(!scratch.is(rs)); | 2083 DCHECK(!scratch.is(rs)); |
2084 r2 = scratch; | 2084 r2 = scratch; |
2085 li(r2, rt); | 2085 li(r2, rt); |
2086 slt(scratch, r2, rs); | 2086 slt(scratch, r2, rs); |
2087 offset = shifted_branch_offset(L, false); | 2087 offset = shifted_branch_offset(L, false); |
2088 beq(scratch, zero_reg, offset); | 2088 beq(scratch, zero_reg, offset); |
2089 } | 2089 } |
2090 break; | 2090 break; |
2091 // Unsigned comparison. | 2091 // Unsigned comparison. |
2092 case Ugreater: | 2092 case Ugreater: |
2093 if (rt.imm32_ == 0) { | 2093 if (rt.imm32_ == 0) { |
2094 offset = shifted_branch_offset(L, false); | 2094 offset = shifted_branch_offset(L, false); |
2095 bne(rs, zero_reg, offset); | 2095 bne(rs, zero_reg, offset); |
2096 } else { | 2096 } else { |
2097 ASSERT(!scratch.is(rs)); | 2097 DCHECK(!scratch.is(rs)); |
2098 r2 = scratch; | 2098 r2 = scratch; |
2099 li(r2, rt); | 2099 li(r2, rt); |
2100 sltu(scratch, r2, rs); | 2100 sltu(scratch, r2, rs); |
2101 offset = shifted_branch_offset(L, false); | 2101 offset = shifted_branch_offset(L, false); |
2102 bne(scratch, zero_reg, offset); | 2102 bne(scratch, zero_reg, offset); |
2103 } | 2103 } |
2104 break; | 2104 break; |
2105 case Ugreater_equal: | 2105 case Ugreater_equal: |
2106 if (rt.imm32_ == 0) { | 2106 if (rt.imm32_ == 0) { |
2107 offset = shifted_branch_offset(L, false); | 2107 offset = shifted_branch_offset(L, false); |
2108 bgez(rs, offset); | 2108 bgez(rs, offset); |
2109 } else if (is_int16(rt.imm32_)) { | 2109 } else if (is_int16(rt.imm32_)) { |
2110 sltiu(scratch, rs, rt.imm32_); | 2110 sltiu(scratch, rs, rt.imm32_); |
2111 offset = shifted_branch_offset(L, false); | 2111 offset = shifted_branch_offset(L, false); |
2112 beq(scratch, zero_reg, offset); | 2112 beq(scratch, zero_reg, offset); |
2113 } else { | 2113 } else { |
2114 ASSERT(!scratch.is(rs)); | 2114 DCHECK(!scratch.is(rs)); |
2115 r2 = scratch; | 2115 r2 = scratch; |
2116 li(r2, rt); | 2116 li(r2, rt); |
2117 sltu(scratch, rs, r2); | 2117 sltu(scratch, rs, r2); |
2118 offset = shifted_branch_offset(L, false); | 2118 offset = shifted_branch_offset(L, false); |
2119 beq(scratch, zero_reg, offset); | 2119 beq(scratch, zero_reg, offset); |
2120 } | 2120 } |
2121 break; | 2121 break; |
2122 case Uless: | 2122 case Uless: |
2123 if (rt.imm32_ == 0) { | 2123 if (rt.imm32_ == 0) { |
2124 // No code needs to be emitted. | 2124 // No code needs to be emitted. |
2125 return; | 2125 return; |
2126 } else if (is_int16(rt.imm32_)) { | 2126 } else if (is_int16(rt.imm32_)) { |
2127 sltiu(scratch, rs, rt.imm32_); | 2127 sltiu(scratch, rs, rt.imm32_); |
2128 offset = shifted_branch_offset(L, false); | 2128 offset = shifted_branch_offset(L, false); |
2129 bne(scratch, zero_reg, offset); | 2129 bne(scratch, zero_reg, offset); |
2130 } else { | 2130 } else { |
2131 ASSERT(!scratch.is(rs)); | 2131 DCHECK(!scratch.is(rs)); |
2132 r2 = scratch; | 2132 r2 = scratch; |
2133 li(r2, rt); | 2133 li(r2, rt); |
2134 sltu(scratch, rs, r2); | 2134 sltu(scratch, rs, r2); |
2135 offset = shifted_branch_offset(L, false); | 2135 offset = shifted_branch_offset(L, false); |
2136 bne(scratch, zero_reg, offset); | 2136 bne(scratch, zero_reg, offset); |
2137 } | 2137 } |
2138 break; | 2138 break; |
2139 case Uless_equal: | 2139 case Uless_equal: |
2140 if (rt.imm32_ == 0) { | 2140 if (rt.imm32_ == 0) { |
2141 offset = shifted_branch_offset(L, false); | 2141 offset = shifted_branch_offset(L, false); |
2142 beq(rs, zero_reg, offset); | 2142 beq(rs, zero_reg, offset); |
2143 } else { | 2143 } else { |
2144 ASSERT(!scratch.is(rs)); | 2144 DCHECK(!scratch.is(rs)); |
2145 r2 = scratch; | 2145 r2 = scratch; |
2146 li(r2, rt); | 2146 li(r2, rt); |
2147 sltu(scratch, r2, rs); | 2147 sltu(scratch, r2, rs); |
2148 offset = shifted_branch_offset(L, false); | 2148 offset = shifted_branch_offset(L, false); |
2149 beq(scratch, zero_reg, offset); | 2149 beq(scratch, zero_reg, offset); |
2150 } | 2150 } |
2151 break; | 2151 break; |
2152 default: | 2152 default: |
2153 UNREACHABLE(); | 2153 UNREACHABLE(); |
2154 } | 2154 } |
2155 } | 2155 } |
2156 // Check that offset could actually hold on an int16_t. | 2156 // Check that offset could actually hold on an int16_t. |
2157 ASSERT(is_int16(offset)); | 2157 DCHECK(is_int16(offset)); |
2158 // Emit a nop in the branch delay slot if required. | 2158 // Emit a nop in the branch delay slot if required. |
2159 if (bdslot == PROTECT) | 2159 if (bdslot == PROTECT) |
2160 nop(); | 2160 nop(); |
2161 } | 2161 } |
2162 | 2162 |
2163 | 2163 |
2164 void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) { | 2164 void MacroAssembler::BranchAndLink(int16_t offset, BranchDelaySlot bdslot) { |
2165 BranchAndLinkShort(offset, bdslot); | 2165 BranchAndLinkShort(offset, bdslot); |
2166 } | 2166 } |
2167 | 2167 |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2409 addiu(scratch, scratch, -1); | 2409 addiu(scratch, scratch, -1); |
2410 offset = shifted_branch_offset(L, false); | 2410 offset = shifted_branch_offset(L, false); |
2411 bltzal(scratch, offset); | 2411 bltzal(scratch, offset); |
2412 break; | 2412 break; |
2413 | 2413 |
2414 default: | 2414 default: |
2415 UNREACHABLE(); | 2415 UNREACHABLE(); |
2416 } | 2416 } |
2417 } | 2417 } |
2418 // Check that offset could actually hold on an int16_t. | 2418 // Check that offset could actually hold on an int16_t. |
2419 ASSERT(is_int16(offset)); | 2419 DCHECK(is_int16(offset)); |
2420 | 2420 |
2421 // Emit a nop in the branch delay slot if required. | 2421 // Emit a nop in the branch delay slot if required. |
2422 if (bdslot == PROTECT) | 2422 if (bdslot == PROTECT) |
2423 nop(); | 2423 nop(); |
2424 } | 2424 } |
2425 | 2425 |
2426 | 2426 |
2427 void MacroAssembler::Jump(Register target, | 2427 void MacroAssembler::Jump(Register target, |
2428 Condition cond, | 2428 Condition cond, |
2429 Register rs, | 2429 Register rs, |
(...skipping 30 matching lines...) Expand all Loading... |
2460 bind(&skip); | 2460 bind(&skip); |
2461 } | 2461 } |
2462 | 2462 |
2463 | 2463 |
2464 void MacroAssembler::Jump(Address target, | 2464 void MacroAssembler::Jump(Address target, |
2465 RelocInfo::Mode rmode, | 2465 RelocInfo::Mode rmode, |
2466 Condition cond, | 2466 Condition cond, |
2467 Register rs, | 2467 Register rs, |
2468 const Operand& rt, | 2468 const Operand& rt, |
2469 BranchDelaySlot bd) { | 2469 BranchDelaySlot bd) { |
2470 ASSERT(!RelocInfo::IsCodeTarget(rmode)); | 2470 DCHECK(!RelocInfo::IsCodeTarget(rmode)); |
2471 Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd); | 2471 Jump(reinterpret_cast<intptr_t>(target), rmode, cond, rs, rt, bd); |
2472 } | 2472 } |
2473 | 2473 |
2474 | 2474 |
2475 void MacroAssembler::Jump(Handle<Code> code, | 2475 void MacroAssembler::Jump(Handle<Code> code, |
2476 RelocInfo::Mode rmode, | 2476 RelocInfo::Mode rmode, |
2477 Condition cond, | 2477 Condition cond, |
2478 Register rs, | 2478 Register rs, |
2479 const Operand& rt, | 2479 const Operand& rt, |
2480 BranchDelaySlot bd) { | 2480 BranchDelaySlot bd) { |
2481 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 2481 DCHECK(RelocInfo::IsCodeTarget(rmode)); |
2482 AllowDeferredHandleDereference embedding_raw_address; | 2482 AllowDeferredHandleDereference embedding_raw_address; |
2483 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd); | 2483 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond, rs, rt, bd); |
2484 } | 2484 } |
2485 | 2485 |
2486 | 2486 |
2487 int MacroAssembler::CallSize(Register target, | 2487 int MacroAssembler::CallSize(Register target, |
2488 Condition cond, | 2488 Condition cond, |
2489 Register rs, | 2489 Register rs, |
2490 const Operand& rt, | 2490 const Operand& rt, |
2491 BranchDelaySlot bd) { | 2491 BranchDelaySlot bd) { |
(...skipping 25 matching lines...) Expand all Loading... |
2517 jalr(target); | 2517 jalr(target); |
2518 } else { | 2518 } else { |
2519 BRANCH_ARGS_CHECK(cond, rs, rt); | 2519 BRANCH_ARGS_CHECK(cond, rs, rt); |
2520 Branch(2, NegateCondition(cond), rs, rt); | 2520 Branch(2, NegateCondition(cond), rs, rt); |
2521 jalr(target); | 2521 jalr(target); |
2522 } | 2522 } |
2523 // Emit a nop in the branch delay slot if required. | 2523 // Emit a nop in the branch delay slot if required. |
2524 if (bd == PROTECT) | 2524 if (bd == PROTECT) |
2525 nop(); | 2525 nop(); |
2526 | 2526 |
2527 ASSERT_EQ(CallSize(target, cond, rs, rt, bd), | 2527 DCHECK_EQ(CallSize(target, cond, rs, rt, bd), |
2528 SizeOfCodeGeneratedSince(&start)); | 2528 SizeOfCodeGeneratedSince(&start)); |
2529 } | 2529 } |
2530 | 2530 |
2531 | 2531 |
2532 int MacroAssembler::CallSize(Address target, | 2532 int MacroAssembler::CallSize(Address target, |
2533 RelocInfo::Mode rmode, | 2533 RelocInfo::Mode rmode, |
2534 Condition cond, | 2534 Condition cond, |
2535 Register rs, | 2535 Register rs, |
2536 const Operand& rt, | 2536 const Operand& rt, |
2537 BranchDelaySlot bd) { | 2537 BranchDelaySlot bd) { |
(...skipping 10 matching lines...) Expand all Loading... |
2548 BranchDelaySlot bd) { | 2548 BranchDelaySlot bd) { |
2549 BlockTrampolinePoolScope block_trampoline_pool(this); | 2549 BlockTrampolinePoolScope block_trampoline_pool(this); |
2550 Label start; | 2550 Label start; |
2551 bind(&start); | 2551 bind(&start); |
2552 int32_t target_int = reinterpret_cast<int32_t>(target); | 2552 int32_t target_int = reinterpret_cast<int32_t>(target); |
2553 // Must record previous source positions before the | 2553 // Must record previous source positions before the |
2554 // li() generates a new code target. | 2554 // li() generates a new code target. |
2555 positions_recorder()->WriteRecordedPositions(); | 2555 positions_recorder()->WriteRecordedPositions(); |
2556 li(t9, Operand(target_int, rmode), CONSTANT_SIZE); | 2556 li(t9, Operand(target_int, rmode), CONSTANT_SIZE); |
2557 Call(t9, cond, rs, rt, bd); | 2557 Call(t9, cond, rs, rt, bd); |
2558 ASSERT_EQ(CallSize(target, rmode, cond, rs, rt, bd), | 2558 DCHECK_EQ(CallSize(target, rmode, cond, rs, rt, bd), |
2559 SizeOfCodeGeneratedSince(&start)); | 2559 SizeOfCodeGeneratedSince(&start)); |
2560 } | 2560 } |
2561 | 2561 |
2562 | 2562 |
2563 int MacroAssembler::CallSize(Handle<Code> code, | 2563 int MacroAssembler::CallSize(Handle<Code> code, |
2564 RelocInfo::Mode rmode, | 2564 RelocInfo::Mode rmode, |
2565 TypeFeedbackId ast_id, | 2565 TypeFeedbackId ast_id, |
2566 Condition cond, | 2566 Condition cond, |
2567 Register rs, | 2567 Register rs, |
2568 const Operand& rt, | 2568 const Operand& rt, |
2569 BranchDelaySlot bd) { | 2569 BranchDelaySlot bd) { |
2570 AllowDeferredHandleDereference using_raw_address; | 2570 AllowDeferredHandleDereference using_raw_address; |
2571 return CallSize(reinterpret_cast<Address>(code.location()), | 2571 return CallSize(reinterpret_cast<Address>(code.location()), |
2572 rmode, cond, rs, rt, bd); | 2572 rmode, cond, rs, rt, bd); |
2573 } | 2573 } |
2574 | 2574 |
2575 | 2575 |
2576 void MacroAssembler::Call(Handle<Code> code, | 2576 void MacroAssembler::Call(Handle<Code> code, |
2577 RelocInfo::Mode rmode, | 2577 RelocInfo::Mode rmode, |
2578 TypeFeedbackId ast_id, | 2578 TypeFeedbackId ast_id, |
2579 Condition cond, | 2579 Condition cond, |
2580 Register rs, | 2580 Register rs, |
2581 const Operand& rt, | 2581 const Operand& rt, |
2582 BranchDelaySlot bd) { | 2582 BranchDelaySlot bd) { |
2583 BlockTrampolinePoolScope block_trampoline_pool(this); | 2583 BlockTrampolinePoolScope block_trampoline_pool(this); |
2584 Label start; | 2584 Label start; |
2585 bind(&start); | 2585 bind(&start); |
2586 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 2586 DCHECK(RelocInfo::IsCodeTarget(rmode)); |
2587 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) { | 2587 if (rmode == RelocInfo::CODE_TARGET && !ast_id.IsNone()) { |
2588 SetRecordedAstId(ast_id); | 2588 SetRecordedAstId(ast_id); |
2589 rmode = RelocInfo::CODE_TARGET_WITH_ID; | 2589 rmode = RelocInfo::CODE_TARGET_WITH_ID; |
2590 } | 2590 } |
2591 AllowDeferredHandleDereference embedding_raw_address; | 2591 AllowDeferredHandleDereference embedding_raw_address; |
2592 Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd); | 2592 Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd); |
2593 ASSERT_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd), | 2593 DCHECK_EQ(CallSize(code, rmode, ast_id, cond, rs, rt, bd), |
2594 SizeOfCodeGeneratedSince(&start)); | 2594 SizeOfCodeGeneratedSince(&start)); |
2595 } | 2595 } |
2596 | 2596 |
2597 | 2597 |
2598 void MacroAssembler::Ret(Condition cond, | 2598 void MacroAssembler::Ret(Condition cond, |
2599 Register rs, | 2599 Register rs, |
2600 const Operand& rt, | 2600 const Operand& rt, |
2601 BranchDelaySlot bd) { | 2601 BranchDelaySlot bd) { |
2602 Jump(ra, cond, rs, rt, bd); | 2602 Jump(ra, cond, rs, rt, bd); |
2603 } | 2603 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2731 void MacroAssembler::Push(Handle<Object> handle) { | 2731 void MacroAssembler::Push(Handle<Object> handle) { |
2732 li(at, Operand(handle)); | 2732 li(at, Operand(handle)); |
2733 push(at); | 2733 push(at); |
2734 } | 2734 } |
2735 | 2735 |
2736 | 2736 |
2737 void MacroAssembler::DebugBreak() { | 2737 void MacroAssembler::DebugBreak() { |
2738 PrepareCEntryArgs(0); | 2738 PrepareCEntryArgs(0); |
2739 PrepareCEntryFunction(ExternalReference(Runtime::kDebugBreak, isolate())); | 2739 PrepareCEntryFunction(ExternalReference(Runtime::kDebugBreak, isolate())); |
2740 CEntryStub ces(isolate(), 1); | 2740 CEntryStub ces(isolate(), 1); |
2741 ASSERT(AllowThisStubCall(&ces)); | 2741 DCHECK(AllowThisStubCall(&ces)); |
2742 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 2742 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
2743 } | 2743 } |
2744 | 2744 |
2745 | 2745 |
2746 // --------------------------------------------------------------------------- | 2746 // --------------------------------------------------------------------------- |
2747 // Exception handling. | 2747 // Exception handling. |
2748 | 2748 |
2749 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, | 2749 void MacroAssembler::PushTryHandler(StackHandler::Kind kind, |
2750 int handler_index) { | 2750 int handler_index) { |
2751 // Adjust this code if not the case. | 2751 // Adjust this code if not the case. |
2752 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); | 2752 STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize); |
2753 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); | 2753 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0 * kPointerSize); |
2754 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); | 2754 STATIC_ASSERT(StackHandlerConstants::kCodeOffset == 1 * kPointerSize); |
2755 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); | 2755 STATIC_ASSERT(StackHandlerConstants::kStateOffset == 2 * kPointerSize); |
2756 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); | 2756 STATIC_ASSERT(StackHandlerConstants::kContextOffset == 3 * kPointerSize); |
2757 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); | 2757 STATIC_ASSERT(StackHandlerConstants::kFPOffset == 4 * kPointerSize); |
2758 | 2758 |
2759 // For the JSEntry handler, we must preserve a0-a3 and s0. | 2759 // For the JSEntry handler, we must preserve a0-a3 and s0. |
2760 // t1-t3 are available. We will build up the handler from the bottom by | 2760 // t1-t3 are available. We will build up the handler from the bottom by |
2761 // pushing on the stack. | 2761 // pushing on the stack. |
2762 // Set up the code object (t1) and the state (t2) for pushing. | 2762 // Set up the code object (t1) and the state (t2) for pushing. |
2763 unsigned state = | 2763 unsigned state = |
2764 StackHandler::IndexField::encode(handler_index) | | 2764 StackHandler::IndexField::encode(handler_index) | |
2765 StackHandler::KindField::encode(kind); | 2765 StackHandler::KindField::encode(kind); |
2766 li(t1, Operand(CodeObject()), CONSTANT_SIZE); | 2766 li(t1, Operand(CodeObject()), CONSTANT_SIZE); |
2767 li(t2, Operand(state)); | 2767 li(t2, Operand(state)); |
2768 | 2768 |
2769 // Push the frame pointer, context, state, and code object. | 2769 // Push the frame pointer, context, state, and code object. |
2770 if (kind == StackHandler::JS_ENTRY) { | 2770 if (kind == StackHandler::JS_ENTRY) { |
2771 ASSERT_EQ(Smi::FromInt(0), 0); | 2771 DCHECK_EQ(Smi::FromInt(0), 0); |
2772 // The second zero_reg indicates no context. | 2772 // The second zero_reg indicates no context. |
2773 // The first zero_reg is the NULL frame pointer. | 2773 // The first zero_reg is the NULL frame pointer. |
2774 // The operands are reversed to match the order of MultiPush/Pop. | 2774 // The operands are reversed to match the order of MultiPush/Pop. |
2775 Push(zero_reg, zero_reg, t2, t1); | 2775 Push(zero_reg, zero_reg, t2, t1); |
2776 } else { | 2776 } else { |
2777 MultiPush(t1.bit() | t2.bit() | cp.bit() | fp.bit()); | 2777 MultiPush(t1.bit() | t2.bit() | cp.bit() | fp.bit()); |
2778 } | 2778 } |
2779 | 2779 |
2780 // Link the current handler as the next handler. | 2780 // Link the current handler as the next handler. |
2781 li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); | 2781 li(t2, Operand(ExternalReference(Isolate::kHandlerAddress, isolate()))); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2889 JumpToHandlerEntry(); | 2889 JumpToHandlerEntry(); |
2890 } | 2890 } |
2891 | 2891 |
2892 | 2892 |
2893 void MacroAssembler::Allocate(int object_size, | 2893 void MacroAssembler::Allocate(int object_size, |
2894 Register result, | 2894 Register result, |
2895 Register scratch1, | 2895 Register scratch1, |
2896 Register scratch2, | 2896 Register scratch2, |
2897 Label* gc_required, | 2897 Label* gc_required, |
2898 AllocationFlags flags) { | 2898 AllocationFlags flags) { |
2899 ASSERT(object_size <= Page::kMaxRegularHeapObjectSize); | 2899 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); |
2900 if (!FLAG_inline_new) { | 2900 if (!FLAG_inline_new) { |
2901 if (emit_debug_code()) { | 2901 if (emit_debug_code()) { |
2902 // Trash the registers to simulate an allocation failure. | 2902 // Trash the registers to simulate an allocation failure. |
2903 li(result, 0x7091); | 2903 li(result, 0x7091); |
2904 li(scratch1, 0x7191); | 2904 li(scratch1, 0x7191); |
2905 li(scratch2, 0x7291); | 2905 li(scratch2, 0x7291); |
2906 } | 2906 } |
2907 jmp(gc_required); | 2907 jmp(gc_required); |
2908 return; | 2908 return; |
2909 } | 2909 } |
2910 | 2910 |
2911 ASSERT(!result.is(scratch1)); | 2911 DCHECK(!result.is(scratch1)); |
2912 ASSERT(!result.is(scratch2)); | 2912 DCHECK(!result.is(scratch2)); |
2913 ASSERT(!scratch1.is(scratch2)); | 2913 DCHECK(!scratch1.is(scratch2)); |
2914 ASSERT(!scratch1.is(t9)); | 2914 DCHECK(!scratch1.is(t9)); |
2915 ASSERT(!scratch2.is(t9)); | 2915 DCHECK(!scratch2.is(t9)); |
2916 ASSERT(!result.is(t9)); | 2916 DCHECK(!result.is(t9)); |
2917 | 2917 |
2918 // Make object size into bytes. | 2918 // Make object size into bytes. |
2919 if ((flags & SIZE_IN_WORDS) != 0) { | 2919 if ((flags & SIZE_IN_WORDS) != 0) { |
2920 object_size *= kPointerSize; | 2920 object_size *= kPointerSize; |
2921 } | 2921 } |
2922 ASSERT_EQ(0, object_size & kObjectAlignmentMask); | 2922 DCHECK_EQ(0, object_size & kObjectAlignmentMask); |
2923 | 2923 |
2924 // Check relative positions of allocation top and limit addresses. | 2924 // Check relative positions of allocation top and limit addresses. |
2925 // ARM adds additional checks to make sure the ldm instruction can be | 2925 // ARM adds additional checks to make sure the ldm instruction can be |
2926 // used. On MIPS we don't have ldm so we don't need additional checks either. | 2926 // used. On MIPS we don't have ldm so we don't need additional checks either. |
2927 ExternalReference allocation_top = | 2927 ExternalReference allocation_top = |
2928 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 2928 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
2929 ExternalReference allocation_limit = | 2929 ExternalReference allocation_limit = |
2930 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 2930 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
2931 | 2931 |
2932 intptr_t top = | 2932 intptr_t top = |
2933 reinterpret_cast<intptr_t>(allocation_top.address()); | 2933 reinterpret_cast<intptr_t>(allocation_top.address()); |
2934 intptr_t limit = | 2934 intptr_t limit = |
2935 reinterpret_cast<intptr_t>(allocation_limit.address()); | 2935 reinterpret_cast<intptr_t>(allocation_limit.address()); |
2936 ASSERT((limit - top) == kPointerSize); | 2936 DCHECK((limit - top) == kPointerSize); |
2937 | 2937 |
2938 // Set up allocation top address and object size registers. | 2938 // Set up allocation top address and object size registers. |
2939 Register topaddr = scratch1; | 2939 Register topaddr = scratch1; |
2940 li(topaddr, Operand(allocation_top)); | 2940 li(topaddr, Operand(allocation_top)); |
2941 | 2941 |
2942 // This code stores a temporary value in t9. | 2942 // This code stores a temporary value in t9. |
2943 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 2943 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
2944 // Load allocation top into result and allocation limit into t9. | 2944 // Load allocation top into result and allocation limit into t9. |
2945 lw(result, MemOperand(topaddr)); | 2945 lw(result, MemOperand(topaddr)); |
2946 lw(t9, MemOperand(topaddr, kPointerSize)); | 2946 lw(t9, MemOperand(topaddr, kPointerSize)); |
2947 } else { | 2947 } else { |
2948 if (emit_debug_code()) { | 2948 if (emit_debug_code()) { |
2949 // Assert that result actually contains top on entry. t9 is used | 2949 // Assert that result actually contains top on entry. t9 is used |
2950 // immediately below so this use of t9 does not cause difference with | 2950 // immediately below so this use of t9 does not cause difference with |
2951 // respect to register content between debug and release mode. | 2951 // respect to register content between debug and release mode. |
2952 lw(t9, MemOperand(topaddr)); | 2952 lw(t9, MemOperand(topaddr)); |
2953 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | 2953 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); |
2954 } | 2954 } |
2955 // Load allocation limit into t9. Result already contains allocation top. | 2955 // Load allocation limit into t9. Result already contains allocation top. |
2956 lw(t9, MemOperand(topaddr, limit - top)); | 2956 lw(t9, MemOperand(topaddr, limit - top)); |
2957 } | 2957 } |
2958 | 2958 |
2959 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 2959 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
2960 // Align the next allocation. Storing the filler map without checking top is | 2960 // Align the next allocation. Storing the filler map without checking top is |
2961 // safe in new-space because the limit of the heap is aligned there. | 2961 // safe in new-space because the limit of the heap is aligned there. |
2962 ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); | 2962 DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0); |
2963 ASSERT(kPointerAlignment * 2 == kDoubleAlignment); | 2963 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); |
2964 And(scratch2, result, Operand(kDoubleAlignmentMask)); | 2964 And(scratch2, result, Operand(kDoubleAlignmentMask)); |
2965 Label aligned; | 2965 Label aligned; |
2966 Branch(&aligned, eq, scratch2, Operand(zero_reg)); | 2966 Branch(&aligned, eq, scratch2, Operand(zero_reg)); |
2967 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { | 2967 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { |
2968 Branch(gc_required, Ugreater_equal, result, Operand(t9)); | 2968 Branch(gc_required, Ugreater_equal, result, Operand(t9)); |
2969 } | 2969 } |
2970 li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | 2970 li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); |
2971 sw(scratch2, MemOperand(result)); | 2971 sw(scratch2, MemOperand(result)); |
2972 Addu(result, result, Operand(kDoubleSize / 2)); | 2972 Addu(result, result, Operand(kDoubleSize / 2)); |
2973 bind(&aligned); | 2973 bind(&aligned); |
(...skipping 22 matching lines...) Expand all Loading... |
2996 if (emit_debug_code()) { | 2996 if (emit_debug_code()) { |
2997 // Trash the registers to simulate an allocation failure. | 2997 // Trash the registers to simulate an allocation failure. |
2998 li(result, 0x7091); | 2998 li(result, 0x7091); |
2999 li(scratch1, 0x7191); | 2999 li(scratch1, 0x7191); |
3000 li(scratch2, 0x7291); | 3000 li(scratch2, 0x7291); |
3001 } | 3001 } |
3002 jmp(gc_required); | 3002 jmp(gc_required); |
3003 return; | 3003 return; |
3004 } | 3004 } |
3005 | 3005 |
3006 ASSERT(!result.is(scratch1)); | 3006 DCHECK(!result.is(scratch1)); |
3007 ASSERT(!result.is(scratch2)); | 3007 DCHECK(!result.is(scratch2)); |
3008 ASSERT(!scratch1.is(scratch2)); | 3008 DCHECK(!scratch1.is(scratch2)); |
3009 ASSERT(!object_size.is(t9)); | 3009 DCHECK(!object_size.is(t9)); |
3010 ASSERT(!scratch1.is(t9) && !scratch2.is(t9) && !result.is(t9)); | 3010 DCHECK(!scratch1.is(t9) && !scratch2.is(t9) && !result.is(t9)); |
3011 | 3011 |
3012 // Check relative positions of allocation top and limit addresses. | 3012 // Check relative positions of allocation top and limit addresses. |
3013 // ARM adds additional checks to make sure the ldm instruction can be | 3013 // ARM adds additional checks to make sure the ldm instruction can be |
3014 // used. On MIPS we don't have ldm so we don't need additional checks either. | 3014 // used. On MIPS we don't have ldm so we don't need additional checks either. |
3015 ExternalReference allocation_top = | 3015 ExternalReference allocation_top = |
3016 AllocationUtils::GetAllocationTopReference(isolate(), flags); | 3016 AllocationUtils::GetAllocationTopReference(isolate(), flags); |
3017 ExternalReference allocation_limit = | 3017 ExternalReference allocation_limit = |
3018 AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 3018 AllocationUtils::GetAllocationLimitReference(isolate(), flags); |
3019 intptr_t top = | 3019 intptr_t top = |
3020 reinterpret_cast<intptr_t>(allocation_top.address()); | 3020 reinterpret_cast<intptr_t>(allocation_top.address()); |
3021 intptr_t limit = | 3021 intptr_t limit = |
3022 reinterpret_cast<intptr_t>(allocation_limit.address()); | 3022 reinterpret_cast<intptr_t>(allocation_limit.address()); |
3023 ASSERT((limit - top) == kPointerSize); | 3023 DCHECK((limit - top) == kPointerSize); |
3024 | 3024 |
3025 // Set up allocation top address and object size registers. | 3025 // Set up allocation top address and object size registers. |
3026 Register topaddr = scratch1; | 3026 Register topaddr = scratch1; |
3027 li(topaddr, Operand(allocation_top)); | 3027 li(topaddr, Operand(allocation_top)); |
3028 | 3028 |
3029 // This code stores a temporary value in t9. | 3029 // This code stores a temporary value in t9. |
3030 if ((flags & RESULT_CONTAINS_TOP) == 0) { | 3030 if ((flags & RESULT_CONTAINS_TOP) == 0) { |
3031 // Load allocation top into result and allocation limit into t9. | 3031 // Load allocation top into result and allocation limit into t9. |
3032 lw(result, MemOperand(topaddr)); | 3032 lw(result, MemOperand(topaddr)); |
3033 lw(t9, MemOperand(topaddr, kPointerSize)); | 3033 lw(t9, MemOperand(topaddr, kPointerSize)); |
3034 } else { | 3034 } else { |
3035 if (emit_debug_code()) { | 3035 if (emit_debug_code()) { |
3036 // Assert that result actually contains top on entry. t9 is used | 3036 // Assert that result actually contains top on entry. t9 is used |
3037 // immediately below so this use of t9 does not cause difference with | 3037 // immediately below so this use of t9 does not cause difference with |
3038 // respect to register content between debug and release mode. | 3038 // respect to register content between debug and release mode. |
3039 lw(t9, MemOperand(topaddr)); | 3039 lw(t9, MemOperand(topaddr)); |
3040 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); | 3040 Check(eq, kUnexpectedAllocationTop, result, Operand(t9)); |
3041 } | 3041 } |
3042 // Load allocation limit into t9. Result already contains allocation top. | 3042 // Load allocation limit into t9. Result already contains allocation top. |
3043 lw(t9, MemOperand(topaddr, limit - top)); | 3043 lw(t9, MemOperand(topaddr, limit - top)); |
3044 } | 3044 } |
3045 | 3045 |
3046 if ((flags & DOUBLE_ALIGNMENT) != 0) { | 3046 if ((flags & DOUBLE_ALIGNMENT) != 0) { |
3047 // Align the next allocation. Storing the filler map without checking top is | 3047 // Align the next allocation. Storing the filler map without checking top is |
3048 // safe in new-space because the limit of the heap is aligned there. | 3048 // safe in new-space because the limit of the heap is aligned there. |
3049 ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); | 3049 DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0); |
3050 ASSERT(kPointerAlignment * 2 == kDoubleAlignment); | 3050 DCHECK(kPointerAlignment * 2 == kDoubleAlignment); |
3051 And(scratch2, result, Operand(kDoubleAlignmentMask)); | 3051 And(scratch2, result, Operand(kDoubleAlignmentMask)); |
3052 Label aligned; | 3052 Label aligned; |
3053 Branch(&aligned, eq, scratch2, Operand(zero_reg)); | 3053 Branch(&aligned, eq, scratch2, Operand(zero_reg)); |
3054 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { | 3054 if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { |
3055 Branch(gc_required, Ugreater_equal, result, Operand(t9)); | 3055 Branch(gc_required, Ugreater_equal, result, Operand(t9)); |
3056 } | 3056 } |
3057 li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); | 3057 li(scratch2, Operand(isolate()->factory()->one_pointer_filler_map())); |
3058 sw(scratch2, MemOperand(result)); | 3058 sw(scratch2, MemOperand(result)); |
3059 Addu(result, result, Operand(kDoubleSize / 2)); | 3059 Addu(result, result, Operand(kDoubleSize / 2)); |
3060 bind(&aligned); | 3060 bind(&aligned); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3106 | 3106 |
3107 | 3107 |
3108 void MacroAssembler::AllocateTwoByteString(Register result, | 3108 void MacroAssembler::AllocateTwoByteString(Register result, |
3109 Register length, | 3109 Register length, |
3110 Register scratch1, | 3110 Register scratch1, |
3111 Register scratch2, | 3111 Register scratch2, |
3112 Register scratch3, | 3112 Register scratch3, |
3113 Label* gc_required) { | 3113 Label* gc_required) { |
3114 // Calculate the number of bytes needed for the characters in the string while | 3114 // Calculate the number of bytes needed for the characters in the string while |
3115 // observing object alignment. | 3115 // observing object alignment. |
3116 ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3116 DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
3117 sll(scratch1, length, 1); // Length in bytes, not chars. | 3117 sll(scratch1, length, 1); // Length in bytes, not chars. |
3118 addiu(scratch1, scratch1, | 3118 addiu(scratch1, scratch1, |
3119 kObjectAlignmentMask + SeqTwoByteString::kHeaderSize); | 3119 kObjectAlignmentMask + SeqTwoByteString::kHeaderSize); |
3120 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); | 3120 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); |
3121 | 3121 |
3122 // Allocate two-byte string in new space. | 3122 // Allocate two-byte string in new space. |
3123 Allocate(scratch1, | 3123 Allocate(scratch1, |
3124 result, | 3124 result, |
3125 scratch2, | 3125 scratch2, |
3126 scratch3, | 3126 scratch3, |
(...skipping 10 matching lines...) Expand all Loading... |
3137 | 3137 |
3138 | 3138 |
3139 void MacroAssembler::AllocateAsciiString(Register result, | 3139 void MacroAssembler::AllocateAsciiString(Register result, |
3140 Register length, | 3140 Register length, |
3141 Register scratch1, | 3141 Register scratch1, |
3142 Register scratch2, | 3142 Register scratch2, |
3143 Register scratch3, | 3143 Register scratch3, |
3144 Label* gc_required) { | 3144 Label* gc_required) { |
3145 // Calculate the number of bytes needed for the characters in the string | 3145 // Calculate the number of bytes needed for the characters in the string |
3146 // while observing object alignment. | 3146 // while observing object alignment. |
3147 ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 3147 DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |
3148 ASSERT(kCharSize == 1); | 3148 DCHECK(kCharSize == 1); |
3149 addiu(scratch1, length, kObjectAlignmentMask + SeqOneByteString::kHeaderSize); | 3149 addiu(scratch1, length, kObjectAlignmentMask + SeqOneByteString::kHeaderSize); |
3150 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); | 3150 And(scratch1, scratch1, Operand(~kObjectAlignmentMask)); |
3151 | 3151 |
3152 // Allocate ASCII string in new space. | 3152 // Allocate ASCII string in new space. |
3153 Allocate(scratch1, | 3153 Allocate(scratch1, |
3154 result, | 3154 result, |
3155 scratch2, | 3155 scratch2, |
3156 scratch3, | 3156 scratch3, |
3157 gc_required, | 3157 gc_required, |
3158 TAG_OBJECT); | 3158 TAG_OBJECT); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3282 AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required); | 3282 AllocateHeapNumber(result, scratch1, scratch2, t8, gc_required); |
3283 sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset)); | 3283 sdc1(value, FieldMemOperand(result, HeapNumber::kValueOffset)); |
3284 } | 3284 } |
3285 | 3285 |
3286 | 3286 |
3287 // Copies a fixed number of fields of heap objects from src to dst. | 3287 // Copies a fixed number of fields of heap objects from src to dst. |
3288 void MacroAssembler::CopyFields(Register dst, | 3288 void MacroAssembler::CopyFields(Register dst, |
3289 Register src, | 3289 Register src, |
3290 RegList temps, | 3290 RegList temps, |
3291 int field_count) { | 3291 int field_count) { |
3292 ASSERT((temps & dst.bit()) == 0); | 3292 DCHECK((temps & dst.bit()) == 0); |
3293 ASSERT((temps & src.bit()) == 0); | 3293 DCHECK((temps & src.bit()) == 0); |
3294 // Primitive implementation using only one temporary register. | 3294 // Primitive implementation using only one temporary register. |
3295 | 3295 |
3296 Register tmp = no_reg; | 3296 Register tmp = no_reg; |
3297 // Find a temp register in temps list. | 3297 // Find a temp register in temps list. |
3298 for (int i = 0; i < kNumRegisters; i++) { | 3298 for (int i = 0; i < kNumRegisters; i++) { |
3299 if ((temps & (1 << i)) != 0) { | 3299 if ((temps & (1 << i)) != 0) { |
3300 tmp.code_ = i; | 3300 tmp.code_ = i; |
3301 break; | 3301 break; |
3302 } | 3302 } |
3303 } | 3303 } |
3304 ASSERT(!tmp.is(no_reg)); | 3304 DCHECK(!tmp.is(no_reg)); |
3305 | 3305 |
3306 for (int i = 0; i < field_count; i++) { | 3306 for (int i = 0; i < field_count; i++) { |
3307 lw(tmp, FieldMemOperand(src, i * kPointerSize)); | 3307 lw(tmp, FieldMemOperand(src, i * kPointerSize)); |
3308 sw(tmp, FieldMemOperand(dst, i * kPointerSize)); | 3308 sw(tmp, FieldMemOperand(dst, i * kPointerSize)); |
3309 } | 3309 } |
3310 } | 3310 } |
3311 | 3311 |
3312 | 3312 |
3313 void MacroAssembler::CopyBytes(Register src, | 3313 void MacroAssembler::CopyBytes(Register src, |
3314 Register dst, | 3314 Register dst, |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3613 Move(v1, v0, src); | 3613 Move(v1, v0, src); |
3614 } | 3614 } |
3615 } | 3615 } |
3616 } | 3616 } |
3617 | 3617 |
3618 | 3618 |
3619 void MacroAssembler::MovToFloatParameters(DoubleRegister src1, | 3619 void MacroAssembler::MovToFloatParameters(DoubleRegister src1, |
3620 DoubleRegister src2) { | 3620 DoubleRegister src2) { |
3621 if (!IsMipsSoftFloatABI) { | 3621 if (!IsMipsSoftFloatABI) { |
3622 if (src2.is(f12)) { | 3622 if (src2.is(f12)) { |
3623 ASSERT(!src1.is(f14)); | 3623 DCHECK(!src1.is(f14)); |
3624 Move(f14, src2); | 3624 Move(f14, src2); |
3625 Move(f12, src1); | 3625 Move(f12, src1); |
3626 } else { | 3626 } else { |
3627 Move(f12, src1); | 3627 Move(f12, src1); |
3628 Move(f14, src2); | 3628 Move(f14, src2); |
3629 } | 3629 } |
3630 } else { | 3630 } else { |
3631 if (kArchEndian == kLittle) { | 3631 if (kArchEndian == kLittle) { |
3632 Move(a0, a1, src1); | 3632 Move(a0, a1, src1); |
3633 Move(a2, a3, src2); | 3633 Move(a2, a3, src2); |
(...skipping 22 matching lines...) Expand all Loading... |
3656 | 3656 |
3657 // Check whether the expected and actual arguments count match. If not, | 3657 // Check whether the expected and actual arguments count match. If not, |
3658 // setup registers according to contract with ArgumentsAdaptorTrampoline: | 3658 // setup registers according to contract with ArgumentsAdaptorTrampoline: |
3659 // a0: actual arguments count | 3659 // a0: actual arguments count |
3660 // a1: function (passed through to callee) | 3660 // a1: function (passed through to callee) |
3661 // a2: expected arguments count | 3661 // a2: expected arguments count |
3662 | 3662 |
3663 // The code below is made a lot easier because the calling code already sets | 3663 // The code below is made a lot easier because the calling code already sets |
3664 // up actual and expected registers according to the contract if values are | 3664 // up actual and expected registers according to the contract if values are |
3665 // passed in registers. | 3665 // passed in registers. |
3666 ASSERT(actual.is_immediate() || actual.reg().is(a0)); | 3666 DCHECK(actual.is_immediate() || actual.reg().is(a0)); |
3667 ASSERT(expected.is_immediate() || expected.reg().is(a2)); | 3667 DCHECK(expected.is_immediate() || expected.reg().is(a2)); |
3668 ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(a3)); | 3668 DCHECK((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(a3)); |
3669 | 3669 |
3670 if (expected.is_immediate()) { | 3670 if (expected.is_immediate()) { |
3671 ASSERT(actual.is_immediate()); | 3671 DCHECK(actual.is_immediate()); |
3672 if (expected.immediate() == actual.immediate()) { | 3672 if (expected.immediate() == actual.immediate()) { |
3673 definitely_matches = true; | 3673 definitely_matches = true; |
3674 } else { | 3674 } else { |
3675 li(a0, Operand(actual.immediate())); | 3675 li(a0, Operand(actual.immediate())); |
3676 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3676 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
3677 if (expected.immediate() == sentinel) { | 3677 if (expected.immediate() == sentinel) { |
3678 // Don't worry about adapting arguments for builtins that | 3678 // Don't worry about adapting arguments for builtins that |
3679 // don't want that done. Skip adaption code by making it look | 3679 // don't want that done. Skip adaption code by making it look |
3680 // like we have a match between expected and actual number of | 3680 // like we have a match between expected and actual number of |
3681 // arguments. | 3681 // arguments. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3714 } | 3714 } |
3715 } | 3715 } |
3716 | 3716 |
3717 | 3717 |
3718 void MacroAssembler::InvokeCode(Register code, | 3718 void MacroAssembler::InvokeCode(Register code, |
3719 const ParameterCount& expected, | 3719 const ParameterCount& expected, |
3720 const ParameterCount& actual, | 3720 const ParameterCount& actual, |
3721 InvokeFlag flag, | 3721 InvokeFlag flag, |
3722 const CallWrapper& call_wrapper) { | 3722 const CallWrapper& call_wrapper) { |
3723 // You can't call a function without a valid frame. | 3723 // You can't call a function without a valid frame. |
3724 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3724 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
3725 | 3725 |
3726 Label done; | 3726 Label done; |
3727 | 3727 |
3728 bool definitely_mismatches = false; | 3728 bool definitely_mismatches = false; |
3729 InvokePrologue(expected, actual, Handle<Code>::null(), code, | 3729 InvokePrologue(expected, actual, Handle<Code>::null(), code, |
3730 &done, &definitely_mismatches, flag, | 3730 &done, &definitely_mismatches, flag, |
3731 call_wrapper); | 3731 call_wrapper); |
3732 if (!definitely_mismatches) { | 3732 if (!definitely_mismatches) { |
3733 if (flag == CALL_FUNCTION) { | 3733 if (flag == CALL_FUNCTION) { |
3734 call_wrapper.BeforeCall(CallSize(code)); | 3734 call_wrapper.BeforeCall(CallSize(code)); |
3735 Call(code); | 3735 Call(code); |
3736 call_wrapper.AfterCall(); | 3736 call_wrapper.AfterCall(); |
3737 } else { | 3737 } else { |
3738 ASSERT(flag == JUMP_FUNCTION); | 3738 DCHECK(flag == JUMP_FUNCTION); |
3739 Jump(code); | 3739 Jump(code); |
3740 } | 3740 } |
3741 // Continue here if InvokePrologue does handle the invocation due to | 3741 // Continue here if InvokePrologue does handle the invocation due to |
3742 // mismatched parameter counts. | 3742 // mismatched parameter counts. |
3743 bind(&done); | 3743 bind(&done); |
3744 } | 3744 } |
3745 } | 3745 } |
3746 | 3746 |
3747 | 3747 |
3748 void MacroAssembler::InvokeFunction(Register function, | 3748 void MacroAssembler::InvokeFunction(Register function, |
3749 const ParameterCount& actual, | 3749 const ParameterCount& actual, |
3750 InvokeFlag flag, | 3750 InvokeFlag flag, |
3751 const CallWrapper& call_wrapper) { | 3751 const CallWrapper& call_wrapper) { |
3752 // You can't call a function without a valid frame. | 3752 // You can't call a function without a valid frame. |
3753 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3753 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
3754 | 3754 |
3755 // Contract with called JS functions requires that function is passed in a1. | 3755 // Contract with called JS functions requires that function is passed in a1. |
3756 ASSERT(function.is(a1)); | 3756 DCHECK(function.is(a1)); |
3757 Register expected_reg = a2; | 3757 Register expected_reg = a2; |
3758 Register code_reg = a3; | 3758 Register code_reg = a3; |
3759 | 3759 |
3760 lw(code_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 3760 lw(code_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
3761 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 3761 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
3762 lw(expected_reg, | 3762 lw(expected_reg, |
3763 FieldMemOperand(code_reg, | 3763 FieldMemOperand(code_reg, |
3764 SharedFunctionInfo::kFormalParameterCountOffset)); | 3764 SharedFunctionInfo::kFormalParameterCountOffset)); |
3765 sra(expected_reg, expected_reg, kSmiTagSize); | 3765 sra(expected_reg, expected_reg, kSmiTagSize); |
3766 lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 3766 lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
3767 | 3767 |
3768 ParameterCount expected(expected_reg); | 3768 ParameterCount expected(expected_reg); |
3769 InvokeCode(code_reg, expected, actual, flag, call_wrapper); | 3769 InvokeCode(code_reg, expected, actual, flag, call_wrapper); |
3770 } | 3770 } |
3771 | 3771 |
3772 | 3772 |
3773 void MacroAssembler::InvokeFunction(Register function, | 3773 void MacroAssembler::InvokeFunction(Register function, |
3774 const ParameterCount& expected, | 3774 const ParameterCount& expected, |
3775 const ParameterCount& actual, | 3775 const ParameterCount& actual, |
3776 InvokeFlag flag, | 3776 InvokeFlag flag, |
3777 const CallWrapper& call_wrapper) { | 3777 const CallWrapper& call_wrapper) { |
3778 // You can't call a function without a valid frame. | 3778 // You can't call a function without a valid frame. |
3779 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 3779 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
3780 | 3780 |
3781 // Contract with called JS functions requires that function is passed in a1. | 3781 // Contract with called JS functions requires that function is passed in a1. |
3782 ASSERT(function.is(a1)); | 3782 DCHECK(function.is(a1)); |
3783 | 3783 |
3784 // Get the function and setup the context. | 3784 // Get the function and setup the context. |
3785 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 3785 lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
3786 | 3786 |
3787 // We call indirectly through the code field in the function to | 3787 // We call indirectly through the code field in the function to |
3788 // allow recompilation to take effect without changing any of the | 3788 // allow recompilation to take effect without changing any of the |
3789 // call sites. | 3789 // call sites. |
3790 lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 3790 lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
3791 InvokeCode(a3, expected, actual, flag, call_wrapper); | 3791 InvokeCode(a3, expected, actual, flag, call_wrapper); |
3792 } | 3792 } |
(...skipping 23 matching lines...) Expand all Loading... |
3816 Label* fail) { | 3816 Label* fail) { |
3817 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 3817 lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
3818 Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 3818 Branch(fail, lt, scratch, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
3819 Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); | 3819 Branch(fail, gt, scratch, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); |
3820 } | 3820 } |
3821 | 3821 |
3822 | 3822 |
3823 void MacroAssembler::IsObjectJSStringType(Register object, | 3823 void MacroAssembler::IsObjectJSStringType(Register object, |
3824 Register scratch, | 3824 Register scratch, |
3825 Label* fail) { | 3825 Label* fail) { |
3826 ASSERT(kNotStringTag != 0); | 3826 DCHECK(kNotStringTag != 0); |
3827 | 3827 |
3828 lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3828 lw(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
3829 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 3829 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
3830 And(scratch, scratch, Operand(kIsNotStringMask)); | 3830 And(scratch, scratch, Operand(kIsNotStringMask)); |
3831 Branch(fail, ne, scratch, Operand(zero_reg)); | 3831 Branch(fail, ne, scratch, Operand(zero_reg)); |
3832 } | 3832 } |
3833 | 3833 |
3834 | 3834 |
3835 void MacroAssembler::IsObjectNameType(Register object, | 3835 void MacroAssembler::IsObjectNameType(Register object, |
3836 Register scratch, | 3836 Register scratch, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3915 | 3915 |
3916 // ----------------------------------------------------------------------------- | 3916 // ----------------------------------------------------------------------------- |
3917 // Runtime calls. | 3917 // Runtime calls. |
3918 | 3918 |
3919 void MacroAssembler::CallStub(CodeStub* stub, | 3919 void MacroAssembler::CallStub(CodeStub* stub, |
3920 TypeFeedbackId ast_id, | 3920 TypeFeedbackId ast_id, |
3921 Condition cond, | 3921 Condition cond, |
3922 Register r1, | 3922 Register r1, |
3923 const Operand& r2, | 3923 const Operand& r2, |
3924 BranchDelaySlot bd) { | 3924 BranchDelaySlot bd) { |
3925 ASSERT(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. | 3925 DCHECK(AllowThisStubCall(stub)); // Stub calls are not allowed in some stubs. |
3926 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, | 3926 Call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id, |
3927 cond, r1, r2, bd); | 3927 cond, r1, r2, bd); |
3928 } | 3928 } |
3929 | 3929 |
3930 | 3930 |
3931 void MacroAssembler::TailCallStub(CodeStub* stub, | 3931 void MacroAssembler::TailCallStub(CodeStub* stub, |
3932 Condition cond, | 3932 Condition cond, |
3933 Register r1, | 3933 Register r1, |
3934 const Operand& r2, | 3934 const Operand& r2, |
3935 BranchDelaySlot bd) { | 3935 BranchDelaySlot bd) { |
(...skipping 15 matching lines...) Expand all Loading... |
3951 ExternalReference next_address = | 3951 ExternalReference next_address = |
3952 ExternalReference::handle_scope_next_address(isolate()); | 3952 ExternalReference::handle_scope_next_address(isolate()); |
3953 const int kNextOffset = 0; | 3953 const int kNextOffset = 0; |
3954 const int kLimitOffset = AddressOffset( | 3954 const int kLimitOffset = AddressOffset( |
3955 ExternalReference::handle_scope_limit_address(isolate()), | 3955 ExternalReference::handle_scope_limit_address(isolate()), |
3956 next_address); | 3956 next_address); |
3957 const int kLevelOffset = AddressOffset( | 3957 const int kLevelOffset = AddressOffset( |
3958 ExternalReference::handle_scope_level_address(isolate()), | 3958 ExternalReference::handle_scope_level_address(isolate()), |
3959 next_address); | 3959 next_address); |
3960 | 3960 |
3961 ASSERT(function_address.is(a1) || function_address.is(a2)); | 3961 DCHECK(function_address.is(a1) || function_address.is(a2)); |
3962 | 3962 |
3963 Label profiler_disabled; | 3963 Label profiler_disabled; |
3964 Label end_profiler_check; | 3964 Label end_profiler_check; |
3965 li(t9, Operand(ExternalReference::is_profiling_address(isolate()))); | 3965 li(t9, Operand(ExternalReference::is_profiling_address(isolate()))); |
3966 lb(t9, MemOperand(t9, 0)); | 3966 lb(t9, MemOperand(t9, 0)); |
3967 Branch(&profiler_disabled, eq, t9, Operand(zero_reg)); | 3967 Branch(&profiler_disabled, eq, t9, Operand(zero_reg)); |
3968 | 3968 |
3969 // Additional parameter is the address of the actual callback. | 3969 // Additional parameter is the address of the actual callback. |
3970 li(t9, Operand(thunk_ref)); | 3970 li(t9, Operand(thunk_ref)); |
3971 jmp(&end_profiler_check); | 3971 jmp(&end_profiler_check); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4069 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { | 4069 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { |
4070 return has_frame_ || !stub->SometimesSetsUpAFrame(); | 4070 return has_frame_ || !stub->SometimesSetsUpAFrame(); |
4071 } | 4071 } |
4072 | 4072 |
4073 | 4073 |
4074 void MacroAssembler::IndexFromHash(Register hash, Register index) { | 4074 void MacroAssembler::IndexFromHash(Register hash, Register index) { |
4075 // If the hash field contains an array index pick it out. The assert checks | 4075 // If the hash field contains an array index pick it out. The assert checks |
4076 // that the constants for the maximum number of digits for an array index | 4076 // that the constants for the maximum number of digits for an array index |
4077 // cached in the hash field and the number of bits reserved for it does not | 4077 // cached in the hash field and the number of bits reserved for it does not |
4078 // conflict. | 4078 // conflict. |
4079 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 4079 DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) < |
4080 (1 << String::kArrayIndexValueBits)); | 4080 (1 << String::kArrayIndexValueBits)); |
4081 DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash); | 4081 DecodeFieldToSmi<String::ArrayIndexValueBits>(index, hash); |
4082 } | 4082 } |
4083 | 4083 |
4084 | 4084 |
4085 void MacroAssembler::ObjectToDoubleFPURegister(Register object, | 4085 void MacroAssembler::ObjectToDoubleFPURegister(Register object, |
4086 FPURegister result, | 4086 FPURegister result, |
4087 Register scratch1, | 4087 Register scratch1, |
4088 Register scratch2, | 4088 Register scratch2, |
4089 Register heap_number_map, | 4089 Register heap_number_map, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4126 mtc1(scratch1, value); | 4126 mtc1(scratch1, value); |
4127 cvt_d_w(value, value); | 4127 cvt_d_w(value, value); |
4128 } | 4128 } |
4129 | 4129 |
4130 | 4130 |
4131 void MacroAssembler::AdduAndCheckForOverflow(Register dst, | 4131 void MacroAssembler::AdduAndCheckForOverflow(Register dst, |
4132 Register left, | 4132 Register left, |
4133 Register right, | 4133 Register right, |
4134 Register overflow_dst, | 4134 Register overflow_dst, |
4135 Register scratch) { | 4135 Register scratch) { |
4136 ASSERT(!dst.is(overflow_dst)); | 4136 DCHECK(!dst.is(overflow_dst)); |
4137 ASSERT(!dst.is(scratch)); | 4137 DCHECK(!dst.is(scratch)); |
4138 ASSERT(!overflow_dst.is(scratch)); | 4138 DCHECK(!overflow_dst.is(scratch)); |
4139 ASSERT(!overflow_dst.is(left)); | 4139 DCHECK(!overflow_dst.is(left)); |
4140 ASSERT(!overflow_dst.is(right)); | 4140 DCHECK(!overflow_dst.is(right)); |
4141 | 4141 |
4142 if (left.is(right) && dst.is(left)) { | 4142 if (left.is(right) && dst.is(left)) { |
4143 ASSERT(!dst.is(t9)); | 4143 DCHECK(!dst.is(t9)); |
4144 ASSERT(!scratch.is(t9)); | 4144 DCHECK(!scratch.is(t9)); |
4145 ASSERT(!left.is(t9)); | 4145 DCHECK(!left.is(t9)); |
4146 ASSERT(!right.is(t9)); | 4146 DCHECK(!right.is(t9)); |
4147 ASSERT(!overflow_dst.is(t9)); | 4147 DCHECK(!overflow_dst.is(t9)); |
4148 mov(t9, right); | 4148 mov(t9, right); |
4149 right = t9; | 4149 right = t9; |
4150 } | 4150 } |
4151 | 4151 |
4152 if (dst.is(left)) { | 4152 if (dst.is(left)) { |
4153 mov(scratch, left); // Preserve left. | 4153 mov(scratch, left); // Preserve left. |
4154 addu(dst, left, right); // Left is overwritten. | 4154 addu(dst, left, right); // Left is overwritten. |
4155 xor_(scratch, dst, scratch); // Original left. | 4155 xor_(scratch, dst, scratch); // Original left. |
4156 xor_(overflow_dst, dst, right); | 4156 xor_(overflow_dst, dst, right); |
4157 and_(overflow_dst, overflow_dst, scratch); | 4157 and_(overflow_dst, overflow_dst, scratch); |
(...skipping 10 matching lines...) Expand all Loading... |
4168 and_(overflow_dst, scratch, overflow_dst); | 4168 and_(overflow_dst, scratch, overflow_dst); |
4169 } | 4169 } |
4170 } | 4170 } |
4171 | 4171 |
4172 | 4172 |
4173 void MacroAssembler::SubuAndCheckForOverflow(Register dst, | 4173 void MacroAssembler::SubuAndCheckForOverflow(Register dst, |
4174 Register left, | 4174 Register left, |
4175 Register right, | 4175 Register right, |
4176 Register overflow_dst, | 4176 Register overflow_dst, |
4177 Register scratch) { | 4177 Register scratch) { |
4178 ASSERT(!dst.is(overflow_dst)); | 4178 DCHECK(!dst.is(overflow_dst)); |
4179 ASSERT(!dst.is(scratch)); | 4179 DCHECK(!dst.is(scratch)); |
4180 ASSERT(!overflow_dst.is(scratch)); | 4180 DCHECK(!overflow_dst.is(scratch)); |
4181 ASSERT(!overflow_dst.is(left)); | 4181 DCHECK(!overflow_dst.is(left)); |
4182 ASSERT(!overflow_dst.is(right)); | 4182 DCHECK(!overflow_dst.is(right)); |
4183 ASSERT(!scratch.is(left)); | 4183 DCHECK(!scratch.is(left)); |
4184 ASSERT(!scratch.is(right)); | 4184 DCHECK(!scratch.is(right)); |
4185 | 4185 |
4186 // This happens with some crankshaft code. Since Subu works fine if | 4186 // This happens with some crankshaft code. Since Subu works fine if |
4187 // left == right, let's not make that restriction here. | 4187 // left == right, let's not make that restriction here. |
4188 if (left.is(right)) { | 4188 if (left.is(right)) { |
4189 mov(dst, zero_reg); | 4189 mov(dst, zero_reg); |
4190 mov(overflow_dst, zero_reg); | 4190 mov(overflow_dst, zero_reg); |
4191 return; | 4191 return; |
4192 } | 4192 } |
4193 | 4193 |
4194 if (dst.is(left)) { | 4194 if (dst.is(left)) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4275 zero_reg, | 4275 zero_reg, |
4276 Operand(zero_reg), | 4276 Operand(zero_reg), |
4277 bd); | 4277 bd); |
4278 } | 4278 } |
4279 | 4279 |
4280 | 4280 |
4281 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 4281 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
4282 InvokeFlag flag, | 4282 InvokeFlag flag, |
4283 const CallWrapper& call_wrapper) { | 4283 const CallWrapper& call_wrapper) { |
4284 // You can't call a builtin without a valid frame. | 4284 // You can't call a builtin without a valid frame. |
4285 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 4285 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
4286 | 4286 |
4287 GetBuiltinEntry(t9, id); | 4287 GetBuiltinEntry(t9, id); |
4288 if (flag == CALL_FUNCTION) { | 4288 if (flag == CALL_FUNCTION) { |
4289 call_wrapper.BeforeCall(CallSize(t9)); | 4289 call_wrapper.BeforeCall(CallSize(t9)); |
4290 Call(t9); | 4290 Call(t9); |
4291 call_wrapper.AfterCall(); | 4291 call_wrapper.AfterCall(); |
4292 } else { | 4292 } else { |
4293 ASSERT(flag == JUMP_FUNCTION); | 4293 DCHECK(flag == JUMP_FUNCTION); |
4294 Jump(t9); | 4294 Jump(t9); |
4295 } | 4295 } |
4296 } | 4296 } |
4297 | 4297 |
4298 | 4298 |
4299 void MacroAssembler::GetBuiltinFunction(Register target, | 4299 void MacroAssembler::GetBuiltinFunction(Register target, |
4300 Builtins::JavaScript id) { | 4300 Builtins::JavaScript id) { |
4301 // Load the builtins object into target register. | 4301 // Load the builtins object into target register. |
4302 lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 4302 lw(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
4303 lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); | 4303 lw(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); |
4304 // Load the JavaScript builtin function from the builtins object. | 4304 // Load the JavaScript builtin function from the builtins object. |
4305 lw(target, FieldMemOperand(target, | 4305 lw(target, FieldMemOperand(target, |
4306 JSBuiltinsObject::OffsetOfFunctionWithId(id))); | 4306 JSBuiltinsObject::OffsetOfFunctionWithId(id))); |
4307 } | 4307 } |
4308 | 4308 |
4309 | 4309 |
4310 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { | 4310 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { |
4311 ASSERT(!target.is(a1)); | 4311 DCHECK(!target.is(a1)); |
4312 GetBuiltinFunction(a1, id); | 4312 GetBuiltinFunction(a1, id); |
4313 // Load the code entry point from the builtins object. | 4313 // Load the code entry point from the builtins object. |
4314 lw(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 4314 lw(target, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
4315 } | 4315 } |
4316 | 4316 |
4317 | 4317 |
4318 void MacroAssembler::SetCounter(StatsCounter* counter, int value, | 4318 void MacroAssembler::SetCounter(StatsCounter* counter, int value, |
4319 Register scratch1, Register scratch2) { | 4319 Register scratch1, Register scratch2) { |
4320 if (FLAG_native_code_counters && counter->Enabled()) { | 4320 if (FLAG_native_code_counters && counter->Enabled()) { |
4321 li(scratch1, Operand(value)); | 4321 li(scratch1, Operand(value)); |
4322 li(scratch2, Operand(ExternalReference(counter))); | 4322 li(scratch2, Operand(ExternalReference(counter))); |
4323 sw(scratch1, MemOperand(scratch2)); | 4323 sw(scratch1, MemOperand(scratch2)); |
4324 } | 4324 } |
4325 } | 4325 } |
4326 | 4326 |
4327 | 4327 |
4328 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value, | 4328 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value, |
4329 Register scratch1, Register scratch2) { | 4329 Register scratch1, Register scratch2) { |
4330 ASSERT(value > 0); | 4330 DCHECK(value > 0); |
4331 if (FLAG_native_code_counters && counter->Enabled()) { | 4331 if (FLAG_native_code_counters && counter->Enabled()) { |
4332 li(scratch2, Operand(ExternalReference(counter))); | 4332 li(scratch2, Operand(ExternalReference(counter))); |
4333 lw(scratch1, MemOperand(scratch2)); | 4333 lw(scratch1, MemOperand(scratch2)); |
4334 Addu(scratch1, scratch1, Operand(value)); | 4334 Addu(scratch1, scratch1, Operand(value)); |
4335 sw(scratch1, MemOperand(scratch2)); | 4335 sw(scratch1, MemOperand(scratch2)); |
4336 } | 4336 } |
4337 } | 4337 } |
4338 | 4338 |
4339 | 4339 |
4340 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value, | 4340 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value, |
4341 Register scratch1, Register scratch2) { | 4341 Register scratch1, Register scratch2) { |
4342 ASSERT(value > 0); | 4342 DCHECK(value > 0); |
4343 if (FLAG_native_code_counters && counter->Enabled()) { | 4343 if (FLAG_native_code_counters && counter->Enabled()) { |
4344 li(scratch2, Operand(ExternalReference(counter))); | 4344 li(scratch2, Operand(ExternalReference(counter))); |
4345 lw(scratch1, MemOperand(scratch2)); | 4345 lw(scratch1, MemOperand(scratch2)); |
4346 Subu(scratch1, scratch1, Operand(value)); | 4346 Subu(scratch1, scratch1, Operand(value)); |
4347 sw(scratch1, MemOperand(scratch2)); | 4347 sw(scratch1, MemOperand(scratch2)); |
4348 } | 4348 } |
4349 } | 4349 } |
4350 | 4350 |
4351 | 4351 |
4352 // ----------------------------------------------------------------------------- | 4352 // ----------------------------------------------------------------------------- |
4353 // Debugging. | 4353 // Debugging. |
4354 | 4354 |
4355 void MacroAssembler::Assert(Condition cc, BailoutReason reason, | 4355 void MacroAssembler::Assert(Condition cc, BailoutReason reason, |
4356 Register rs, Operand rt) { | 4356 Register rs, Operand rt) { |
4357 if (emit_debug_code()) | 4357 if (emit_debug_code()) |
4358 Check(cc, reason, rs, rt); | 4358 Check(cc, reason, rs, rt); |
4359 } | 4359 } |
4360 | 4360 |
4361 | 4361 |
4362 void MacroAssembler::AssertFastElements(Register elements) { | 4362 void MacroAssembler::AssertFastElements(Register elements) { |
4363 if (emit_debug_code()) { | 4363 if (emit_debug_code()) { |
4364 ASSERT(!elements.is(at)); | 4364 DCHECK(!elements.is(at)); |
4365 Label ok; | 4365 Label ok; |
4366 push(elements); | 4366 push(elements); |
4367 lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset)); | 4367 lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset)); |
4368 LoadRoot(at, Heap::kFixedArrayMapRootIndex); | 4368 LoadRoot(at, Heap::kFixedArrayMapRootIndex); |
4369 Branch(&ok, eq, elements, Operand(at)); | 4369 Branch(&ok, eq, elements, Operand(at)); |
4370 LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); | 4370 LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); |
4371 Branch(&ok, eq, elements, Operand(at)); | 4371 Branch(&ok, eq, elements, Operand(at)); |
4372 LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex); | 4372 LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex); |
4373 Branch(&ok, eq, elements, Operand(at)); | 4373 Branch(&ok, eq, elements, Operand(at)); |
4374 Abort(kJSObjectWithFastElementsMapHasSlowElements); | 4374 Abort(kJSObjectWithFastElementsMapHasSlowElements); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4417 } | 4417 } |
4418 // Will not return here. | 4418 // Will not return here. |
4419 if (is_trampoline_pool_blocked()) { | 4419 if (is_trampoline_pool_blocked()) { |
4420 // If the calling code cares about the exact number of | 4420 // If the calling code cares about the exact number of |
4421 // instructions generated, we insert padding here to keep the size | 4421 // instructions generated, we insert padding here to keep the size |
4422 // of the Abort macro constant. | 4422 // of the Abort macro constant. |
4423 // Currently in debug mode with debug_code enabled the number of | 4423 // Currently in debug mode with debug_code enabled the number of |
4424 // generated instructions is 10, so we use this as a maximum value. | 4424 // generated instructions is 10, so we use this as a maximum value. |
4425 static const int kExpectedAbortInstructions = 10; | 4425 static const int kExpectedAbortInstructions = 10; |
4426 int abort_instructions = InstructionsGeneratedSince(&abort_start); | 4426 int abort_instructions = InstructionsGeneratedSince(&abort_start); |
4427 ASSERT(abort_instructions <= kExpectedAbortInstructions); | 4427 DCHECK(abort_instructions <= kExpectedAbortInstructions); |
4428 while (abort_instructions++ < kExpectedAbortInstructions) { | 4428 while (abort_instructions++ < kExpectedAbortInstructions) { |
4429 nop(); | 4429 nop(); |
4430 } | 4430 } |
4431 } | 4431 } |
4432 } | 4432 } |
4433 | 4433 |
4434 | 4434 |
4435 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 4435 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
4436 if (context_chain_length > 0) { | 4436 if (context_chain_length > 0) { |
4437 // Move up the chain of contexts to the context containing the slot. | 4437 // Move up the chain of contexts to the context containing the slot. |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4593 | 4593 |
4594 // Save the frame pointer and the context in top. | 4594 // Save the frame pointer and the context in top. |
4595 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 4595 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
4596 sw(fp, MemOperand(t8)); | 4596 sw(fp, MemOperand(t8)); |
4597 li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); | 4597 li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate()))); |
4598 sw(cp, MemOperand(t8)); | 4598 sw(cp, MemOperand(t8)); |
4599 | 4599 |
4600 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); | 4600 const int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
4601 if (save_doubles) { | 4601 if (save_doubles) { |
4602 // The stack must be allign to 0 modulo 8 for stores with sdc1. | 4602 // The stack must be allign to 0 modulo 8 for stores with sdc1. |
4603 ASSERT(kDoubleSize == frame_alignment); | 4603 DCHECK(kDoubleSize == frame_alignment); |
4604 if (frame_alignment > 0) { | 4604 if (frame_alignment > 0) { |
4605 ASSERT(IsPowerOf2(frame_alignment)); | 4605 DCHECK(IsPowerOf2(frame_alignment)); |
4606 And(sp, sp, Operand(-frame_alignment)); // Align stack. | 4606 And(sp, sp, Operand(-frame_alignment)); // Align stack. |
4607 } | 4607 } |
4608 int space = FPURegister::kMaxNumRegisters * kDoubleSize; | 4608 int space = FPURegister::kMaxNumRegisters * kDoubleSize; |
4609 Subu(sp, sp, Operand(space)); | 4609 Subu(sp, sp, Operand(space)); |
4610 // Remember: we only need to save every 2nd double FPU value. | 4610 // Remember: we only need to save every 2nd double FPU value. |
4611 for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) { | 4611 for (int i = 0; i < FPURegister::kMaxNumRegisters; i+=2) { |
4612 FPURegister reg = FPURegister::from_code(i); | 4612 FPURegister reg = FPURegister::from_code(i); |
4613 sdc1(reg, MemOperand(sp, i * kDoubleSize)); | 4613 sdc1(reg, MemOperand(sp, i * kDoubleSize)); |
4614 } | 4614 } |
4615 } | 4615 } |
4616 | 4616 |
4617 // Reserve place for the return address, stack space and an optional slot | 4617 // Reserve place for the return address, stack space and an optional slot |
4618 // (used by the DirectCEntryStub to hold the return value if a struct is | 4618 // (used by the DirectCEntryStub to hold the return value if a struct is |
4619 // returned) and align the frame preparing for calling the runtime function. | 4619 // returned) and align the frame preparing for calling the runtime function. |
4620 ASSERT(stack_space >= 0); | 4620 DCHECK(stack_space >= 0); |
4621 Subu(sp, sp, Operand((stack_space + 2) * kPointerSize)); | 4621 Subu(sp, sp, Operand((stack_space + 2) * kPointerSize)); |
4622 if (frame_alignment > 0) { | 4622 if (frame_alignment > 0) { |
4623 ASSERT(IsPowerOf2(frame_alignment)); | 4623 DCHECK(IsPowerOf2(frame_alignment)); |
4624 And(sp, sp, Operand(-frame_alignment)); // Align stack. | 4624 And(sp, sp, Operand(-frame_alignment)); // Align stack. |
4625 } | 4625 } |
4626 | 4626 |
4627 // Set the exit frame sp value to point just before the return address | 4627 // Set the exit frame sp value to point just before the return address |
4628 // location. | 4628 // location. |
4629 addiu(at, sp, kPointerSize); | 4629 addiu(at, sp, kPointerSize); |
4630 sw(at, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 4630 sw(at, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
4631 } | 4631 } |
4632 | 4632 |
4633 | 4633 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4708 } | 4708 } |
4709 | 4709 |
4710 | 4710 |
4711 void MacroAssembler::AssertStackIsAligned() { | 4711 void MacroAssembler::AssertStackIsAligned() { |
4712 if (emit_debug_code()) { | 4712 if (emit_debug_code()) { |
4713 const int frame_alignment = ActivationFrameAlignment(); | 4713 const int frame_alignment = ActivationFrameAlignment(); |
4714 const int frame_alignment_mask = frame_alignment - 1; | 4714 const int frame_alignment_mask = frame_alignment - 1; |
4715 | 4715 |
4716 if (frame_alignment > kPointerSize) { | 4716 if (frame_alignment > kPointerSize) { |
4717 Label alignment_as_expected; | 4717 Label alignment_as_expected; |
4718 ASSERT(IsPowerOf2(frame_alignment)); | 4718 DCHECK(IsPowerOf2(frame_alignment)); |
4719 andi(at, sp, frame_alignment_mask); | 4719 andi(at, sp, frame_alignment_mask); |
4720 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); | 4720 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); |
4721 // Don't use Check here, as it will call Runtime_Abort re-entering here. | 4721 // Don't use Check here, as it will call Runtime_Abort re-entering here. |
4722 stop("Unexpected stack alignment"); | 4722 stop("Unexpected stack alignment"); |
4723 bind(&alignment_as_expected); | 4723 bind(&alignment_as_expected); |
4724 } | 4724 } |
4725 } | 4725 } |
4726 } | 4726 } |
4727 | 4727 |
4728 | 4728 |
4729 void MacroAssembler::JumpIfNotPowerOfTwoOrZero( | 4729 void MacroAssembler::JumpIfNotPowerOfTwoOrZero( |
4730 Register reg, | 4730 Register reg, |
4731 Register scratch, | 4731 Register scratch, |
4732 Label* not_power_of_two_or_zero) { | 4732 Label* not_power_of_two_or_zero) { |
4733 Subu(scratch, reg, Operand(1)); | 4733 Subu(scratch, reg, Operand(1)); |
4734 Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt, | 4734 Branch(USE_DELAY_SLOT, not_power_of_two_or_zero, lt, |
4735 scratch, Operand(zero_reg)); | 4735 scratch, Operand(zero_reg)); |
4736 and_(at, scratch, reg); // In the delay slot. | 4736 and_(at, scratch, reg); // In the delay slot. |
4737 Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg)); | 4737 Branch(not_power_of_two_or_zero, ne, at, Operand(zero_reg)); |
4738 } | 4738 } |
4739 | 4739 |
4740 | 4740 |
4741 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) { | 4741 void MacroAssembler::SmiTagCheckOverflow(Register reg, Register overflow) { |
4742 ASSERT(!reg.is(overflow)); | 4742 DCHECK(!reg.is(overflow)); |
4743 mov(overflow, reg); // Save original value. | 4743 mov(overflow, reg); // Save original value. |
4744 SmiTag(reg); | 4744 SmiTag(reg); |
4745 xor_(overflow, overflow, reg); // Overflow if (value ^ 2 * value) < 0. | 4745 xor_(overflow, overflow, reg); // Overflow if (value ^ 2 * value) < 0. |
4746 } | 4746 } |
4747 | 4747 |
4748 | 4748 |
4749 void MacroAssembler::SmiTagCheckOverflow(Register dst, | 4749 void MacroAssembler::SmiTagCheckOverflow(Register dst, |
4750 Register src, | 4750 Register src, |
4751 Register overflow) { | 4751 Register overflow) { |
4752 if (dst.is(src)) { | 4752 if (dst.is(src)) { |
4753 // Fall back to slower case. | 4753 // Fall back to slower case. |
4754 SmiTagCheckOverflow(dst, overflow); | 4754 SmiTagCheckOverflow(dst, overflow); |
4755 } else { | 4755 } else { |
4756 ASSERT(!dst.is(src)); | 4756 DCHECK(!dst.is(src)); |
4757 ASSERT(!dst.is(overflow)); | 4757 DCHECK(!dst.is(overflow)); |
4758 ASSERT(!src.is(overflow)); | 4758 DCHECK(!src.is(overflow)); |
4759 SmiTag(dst, src); | 4759 SmiTag(dst, src); |
4760 xor_(overflow, dst, src); // Overflow if (value ^ 2 * value) < 0. | 4760 xor_(overflow, dst, src); // Overflow if (value ^ 2 * value) < 0. |
4761 } | 4761 } |
4762 } | 4762 } |
4763 | 4763 |
4764 | 4764 |
4765 void MacroAssembler::UntagAndJumpIfSmi(Register dst, | 4765 void MacroAssembler::UntagAndJumpIfSmi(Register dst, |
4766 Register src, | 4766 Register src, |
4767 Label* smi_case) { | 4767 Label* smi_case) { |
4768 JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT); | 4768 JumpIfSmi(src, smi_case, at, USE_DELAY_SLOT); |
4769 SmiUntag(dst, src); | 4769 SmiUntag(dst, src); |
4770 } | 4770 } |
4771 | 4771 |
4772 | 4772 |
4773 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst, | 4773 void MacroAssembler::UntagAndJumpIfNotSmi(Register dst, |
4774 Register src, | 4774 Register src, |
4775 Label* non_smi_case) { | 4775 Label* non_smi_case) { |
4776 JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT); | 4776 JumpIfNotSmi(src, non_smi_case, at, USE_DELAY_SLOT); |
4777 SmiUntag(dst, src); | 4777 SmiUntag(dst, src); |
4778 } | 4778 } |
4779 | 4779 |
4780 void MacroAssembler::JumpIfSmi(Register value, | 4780 void MacroAssembler::JumpIfSmi(Register value, |
4781 Label* smi_label, | 4781 Label* smi_label, |
4782 Register scratch, | 4782 Register scratch, |
4783 BranchDelaySlot bd) { | 4783 BranchDelaySlot bd) { |
4784 ASSERT_EQ(0, kSmiTag); | 4784 DCHECK_EQ(0, kSmiTag); |
4785 andi(scratch, value, kSmiTagMask); | 4785 andi(scratch, value, kSmiTagMask); |
4786 Branch(bd, smi_label, eq, scratch, Operand(zero_reg)); | 4786 Branch(bd, smi_label, eq, scratch, Operand(zero_reg)); |
4787 } | 4787 } |
4788 | 4788 |
4789 void MacroAssembler::JumpIfNotSmi(Register value, | 4789 void MacroAssembler::JumpIfNotSmi(Register value, |
4790 Label* not_smi_label, | 4790 Label* not_smi_label, |
4791 Register scratch, | 4791 Register scratch, |
4792 BranchDelaySlot bd) { | 4792 BranchDelaySlot bd) { |
4793 ASSERT_EQ(0, kSmiTag); | 4793 DCHECK_EQ(0, kSmiTag); |
4794 andi(scratch, value, kSmiTagMask); | 4794 andi(scratch, value, kSmiTagMask); |
4795 Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg)); | 4795 Branch(bd, not_smi_label, ne, scratch, Operand(zero_reg)); |
4796 } | 4796 } |
4797 | 4797 |
4798 | 4798 |
4799 void MacroAssembler::JumpIfNotBothSmi(Register reg1, | 4799 void MacroAssembler::JumpIfNotBothSmi(Register reg1, |
4800 Register reg2, | 4800 Register reg2, |
4801 Label* on_not_both_smi) { | 4801 Label* on_not_both_smi) { |
4802 STATIC_ASSERT(kSmiTag == 0); | 4802 STATIC_ASSERT(kSmiTag == 0); |
4803 ASSERT_EQ(1, kSmiTagMask); | 4803 DCHECK_EQ(1, kSmiTagMask); |
4804 or_(at, reg1, reg2); | 4804 or_(at, reg1, reg2); |
4805 JumpIfNotSmi(at, on_not_both_smi); | 4805 JumpIfNotSmi(at, on_not_both_smi); |
4806 } | 4806 } |
4807 | 4807 |
4808 | 4808 |
4809 void MacroAssembler::JumpIfEitherSmi(Register reg1, | 4809 void MacroAssembler::JumpIfEitherSmi(Register reg1, |
4810 Register reg2, | 4810 Register reg2, |
4811 Label* on_either_smi) { | 4811 Label* on_either_smi) { |
4812 STATIC_ASSERT(kSmiTag == 0); | 4812 STATIC_ASSERT(kSmiTag == 0); |
4813 ASSERT_EQ(1, kSmiTagMask); | 4813 DCHECK_EQ(1, kSmiTagMask); |
4814 // Both Smi tags must be 1 (not Smi). | 4814 // Both Smi tags must be 1 (not Smi). |
4815 and_(at, reg1, reg2); | 4815 and_(at, reg1, reg2); |
4816 JumpIfSmi(at, on_either_smi); | 4816 JumpIfSmi(at, on_either_smi); |
4817 } | 4817 } |
4818 | 4818 |
4819 | 4819 |
4820 void MacroAssembler::AssertNotSmi(Register object) { | 4820 void MacroAssembler::AssertNotSmi(Register object) { |
4821 if (emit_debug_code()) { | 4821 if (emit_debug_code()) { |
4822 STATIC_ASSERT(kSmiTag == 0); | 4822 STATIC_ASSERT(kSmiTag == 0); |
4823 andi(at, object, kSmiTagMask); | 4823 andi(at, object, kSmiTagMask); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4875 LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex); | 4875 LoadRoot(scratch, Heap::kAllocationSiteMapRootIndex); |
4876 Assert(eq, kExpectedUndefinedOrCell, object, Operand(scratch)); | 4876 Assert(eq, kExpectedUndefinedOrCell, object, Operand(scratch)); |
4877 pop(object); | 4877 pop(object); |
4878 bind(&done_checking); | 4878 bind(&done_checking); |
4879 } | 4879 } |
4880 } | 4880 } |
4881 | 4881 |
4882 | 4882 |
4883 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) { | 4883 void MacroAssembler::AssertIsRoot(Register reg, Heap::RootListIndex index) { |
4884 if (emit_debug_code()) { | 4884 if (emit_debug_code()) { |
4885 ASSERT(!reg.is(at)); | 4885 DCHECK(!reg.is(at)); |
4886 LoadRoot(at, index); | 4886 LoadRoot(at, index); |
4887 Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at)); | 4887 Check(eq, kHeapNumberMapRegisterClobbered, reg, Operand(at)); |
4888 } | 4888 } |
4889 } | 4889 } |
4890 | 4890 |
4891 | 4891 |
4892 void MacroAssembler::JumpIfNotHeapNumber(Register object, | 4892 void MacroAssembler::JumpIfNotHeapNumber(Register object, |
4893 Register heap_number_map, | 4893 Register heap_number_map, |
4894 Register scratch, | 4894 Register scratch, |
4895 Label* on_not_heap_number) { | 4895 Label* on_not_heap_number) { |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5020 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( | 5020 void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialAscii( |
5021 Register first, | 5021 Register first, |
5022 Register second, | 5022 Register second, |
5023 Register scratch1, | 5023 Register scratch1, |
5024 Register scratch2, | 5024 Register scratch2, |
5025 Label* failure) { | 5025 Label* failure) { |
5026 const int kFlatAsciiStringMask = | 5026 const int kFlatAsciiStringMask = |
5027 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 5027 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
5028 const int kFlatAsciiStringTag = | 5028 const int kFlatAsciiStringTag = |
5029 kStringTag | kOneByteStringTag | kSeqStringTag; | 5029 kStringTag | kOneByteStringTag | kSeqStringTag; |
5030 ASSERT(kFlatAsciiStringTag <= 0xffff); // Ensure this fits 16-bit immed. | 5030 DCHECK(kFlatAsciiStringTag <= 0xffff); // Ensure this fits 16-bit immed. |
5031 andi(scratch1, first, kFlatAsciiStringMask); | 5031 andi(scratch1, first, kFlatAsciiStringMask); |
5032 Branch(failure, ne, scratch1, Operand(kFlatAsciiStringTag)); | 5032 Branch(failure, ne, scratch1, Operand(kFlatAsciiStringTag)); |
5033 andi(scratch2, second, kFlatAsciiStringMask); | 5033 andi(scratch2, second, kFlatAsciiStringMask); |
5034 Branch(failure, ne, scratch2, Operand(kFlatAsciiStringTag)); | 5034 Branch(failure, ne, scratch2, Operand(kFlatAsciiStringTag)); |
5035 } | 5035 } |
5036 | 5036 |
5037 | 5037 |
5038 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type, | 5038 void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type, |
5039 Register scratch, | 5039 Register scratch, |
5040 Label* failure) { | 5040 Label* failure) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5085 Label index_tag_ok, index_tag_bad; | 5085 Label index_tag_ok, index_tag_bad; |
5086 TrySmiTag(index, scratch, &index_tag_bad); | 5086 TrySmiTag(index, scratch, &index_tag_bad); |
5087 Branch(&index_tag_ok); | 5087 Branch(&index_tag_ok); |
5088 bind(&index_tag_bad); | 5088 bind(&index_tag_bad); |
5089 Abort(kIndexIsTooLarge); | 5089 Abort(kIndexIsTooLarge); |
5090 bind(&index_tag_ok); | 5090 bind(&index_tag_ok); |
5091 | 5091 |
5092 lw(at, FieldMemOperand(string, String::kLengthOffset)); | 5092 lw(at, FieldMemOperand(string, String::kLengthOffset)); |
5093 Check(lt, kIndexIsTooLarge, index, Operand(at)); | 5093 Check(lt, kIndexIsTooLarge, index, Operand(at)); |
5094 | 5094 |
5095 ASSERT(Smi::FromInt(0) == 0); | 5095 DCHECK(Smi::FromInt(0) == 0); |
5096 Check(ge, kIndexIsNegative, index, Operand(zero_reg)); | 5096 Check(ge, kIndexIsNegative, index, Operand(zero_reg)); |
5097 | 5097 |
5098 SmiUntag(index, index); | 5098 SmiUntag(index, index); |
5099 } | 5099 } |
5100 | 5100 |
5101 | 5101 |
5102 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 5102 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
5103 int num_double_arguments, | 5103 int num_double_arguments, |
5104 Register scratch) { | 5104 Register scratch) { |
5105 int frame_alignment = ActivationFrameAlignment(); | 5105 int frame_alignment = ActivationFrameAlignment(); |
5106 | 5106 |
5107 // Up to four simple arguments are passed in registers a0..a3. | 5107 // Up to four simple arguments are passed in registers a0..a3. |
5108 // Those four arguments must have reserved argument slots on the stack for | 5108 // Those four arguments must have reserved argument slots on the stack for |
5109 // mips, even though those argument slots are not normally used. | 5109 // mips, even though those argument slots are not normally used. |
5110 // Remaining arguments are pushed on the stack, above (higher address than) | 5110 // Remaining arguments are pushed on the stack, above (higher address than) |
5111 // the argument slots. | 5111 // the argument slots. |
5112 int stack_passed_arguments = CalculateStackPassedWords( | 5112 int stack_passed_arguments = CalculateStackPassedWords( |
5113 num_reg_arguments, num_double_arguments); | 5113 num_reg_arguments, num_double_arguments); |
5114 if (frame_alignment > kPointerSize) { | 5114 if (frame_alignment > kPointerSize) { |
5115 // Make stack end at alignment and make room for num_arguments - 4 words | 5115 // Make stack end at alignment and make room for num_arguments - 4 words |
5116 // and the original value of sp. | 5116 // and the original value of sp. |
5117 mov(scratch, sp); | 5117 mov(scratch, sp); |
5118 Subu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); | 5118 Subu(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); |
5119 ASSERT(IsPowerOf2(frame_alignment)); | 5119 DCHECK(IsPowerOf2(frame_alignment)); |
5120 And(sp, sp, Operand(-frame_alignment)); | 5120 And(sp, sp, Operand(-frame_alignment)); |
5121 sw(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); | 5121 sw(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
5122 } else { | 5122 } else { |
5123 Subu(sp, sp, Operand(stack_passed_arguments * kPointerSize)); | 5123 Subu(sp, sp, Operand(stack_passed_arguments * kPointerSize)); |
5124 } | 5124 } |
5125 } | 5125 } |
5126 | 5126 |
5127 | 5127 |
5128 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 5128 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
5129 Register scratch) { | 5129 Register scratch) { |
(...skipping 24 matching lines...) Expand all Loading... |
5154 | 5154 |
5155 void MacroAssembler::CallCFunction(Register function, | 5155 void MacroAssembler::CallCFunction(Register function, |
5156 int num_arguments) { | 5156 int num_arguments) { |
5157 CallCFunction(function, num_arguments, 0); | 5157 CallCFunction(function, num_arguments, 0); |
5158 } | 5158 } |
5159 | 5159 |
5160 | 5160 |
5161 void MacroAssembler::CallCFunctionHelper(Register function, | 5161 void MacroAssembler::CallCFunctionHelper(Register function, |
5162 int num_reg_arguments, | 5162 int num_reg_arguments, |
5163 int num_double_arguments) { | 5163 int num_double_arguments) { |
5164 ASSERT(has_frame()); | 5164 DCHECK(has_frame()); |
5165 // Make sure that the stack is aligned before calling a C function unless | 5165 // Make sure that the stack is aligned before calling a C function unless |
5166 // running in the simulator. The simulator has its own alignment check which | 5166 // running in the simulator. The simulator has its own alignment check which |
5167 // provides more information. | 5167 // provides more information. |
5168 // The argument stots are presumed to have been set up by | 5168 // The argument stots are presumed to have been set up by |
5169 // PrepareCallCFunction. The C function must be called via t9, for mips ABI. | 5169 // PrepareCallCFunction. The C function must be called via t9, for mips ABI. |
5170 | 5170 |
5171 #if V8_HOST_ARCH_MIPS | 5171 #if V8_HOST_ARCH_MIPS |
5172 if (emit_debug_code()) { | 5172 if (emit_debug_code()) { |
5173 int frame_alignment = base::OS::ActivationFrameAlignment(); | 5173 int frame_alignment = base::OS::ActivationFrameAlignment(); |
5174 int frame_alignment_mask = frame_alignment - 1; | 5174 int frame_alignment_mask = frame_alignment - 1; |
5175 if (frame_alignment > kPointerSize) { | 5175 if (frame_alignment > kPointerSize) { |
5176 ASSERT(IsPowerOf2(frame_alignment)); | 5176 DCHECK(IsPowerOf2(frame_alignment)); |
5177 Label alignment_as_expected; | 5177 Label alignment_as_expected; |
5178 And(at, sp, Operand(frame_alignment_mask)); | 5178 And(at, sp, Operand(frame_alignment_mask)); |
5179 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); | 5179 Branch(&alignment_as_expected, eq, at, Operand(zero_reg)); |
5180 // Don't use Check here, as it will call Runtime_Abort possibly | 5180 // Don't use Check here, as it will call Runtime_Abort possibly |
5181 // re-entering here. | 5181 // re-entering here. |
5182 stop("Unexpected alignment in CallCFunction"); | 5182 stop("Unexpected alignment in CallCFunction"); |
5183 bind(&alignment_as_expected); | 5183 bind(&alignment_as_expected); |
5184 } | 5184 } |
5185 } | 5185 } |
5186 #endif // V8_HOST_ARCH_MIPS | 5186 #endif // V8_HOST_ARCH_MIPS |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5292 Branch(if_deprecated, ne, scratch, Operand(zero_reg)); | 5292 Branch(if_deprecated, ne, scratch, Operand(zero_reg)); |
5293 } | 5293 } |
5294 } | 5294 } |
5295 | 5295 |
5296 | 5296 |
5297 void MacroAssembler::JumpIfBlack(Register object, | 5297 void MacroAssembler::JumpIfBlack(Register object, |
5298 Register scratch0, | 5298 Register scratch0, |
5299 Register scratch1, | 5299 Register scratch1, |
5300 Label* on_black) { | 5300 Label* on_black) { |
5301 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. | 5301 HasColor(object, scratch0, scratch1, on_black, 1, 0); // kBlackBitPattern. |
5302 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 5302 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
5303 } | 5303 } |
5304 | 5304 |
5305 | 5305 |
5306 void MacroAssembler::HasColor(Register object, | 5306 void MacroAssembler::HasColor(Register object, |
5307 Register bitmap_scratch, | 5307 Register bitmap_scratch, |
5308 Register mask_scratch, | 5308 Register mask_scratch, |
5309 Label* has_color, | 5309 Label* has_color, |
5310 int first_bit, | 5310 int first_bit, |
5311 int second_bit) { | 5311 int second_bit) { |
5312 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t8)); | 5312 DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t8)); |
5313 ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, t9)); | 5313 DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, t9)); |
5314 | 5314 |
5315 GetMarkBits(object, bitmap_scratch, mask_scratch); | 5315 GetMarkBits(object, bitmap_scratch, mask_scratch); |
5316 | 5316 |
5317 Label other_color, word_boundary; | 5317 Label other_color, word_boundary; |
5318 lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5318 lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
5319 And(t8, t9, Operand(mask_scratch)); | 5319 And(t8, t9, Operand(mask_scratch)); |
5320 Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg)); | 5320 Branch(&other_color, first_bit == 1 ? eq : ne, t8, Operand(zero_reg)); |
5321 // Shift left 1 by adding. | 5321 // Shift left 1 by adding. |
5322 Addu(mask_scratch, mask_scratch, Operand(mask_scratch)); | 5322 Addu(mask_scratch, mask_scratch, Operand(mask_scratch)); |
5323 Branch(&word_boundary, eq, mask_scratch, Operand(zero_reg)); | 5323 Branch(&word_boundary, eq, mask_scratch, Operand(zero_reg)); |
5324 And(t8, t9, Operand(mask_scratch)); | 5324 And(t8, t9, Operand(mask_scratch)); |
5325 Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg)); | 5325 Branch(has_color, second_bit == 1 ? ne : eq, t8, Operand(zero_reg)); |
5326 jmp(&other_color); | 5326 jmp(&other_color); |
5327 | 5327 |
5328 bind(&word_boundary); | 5328 bind(&word_boundary); |
5329 lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize)); | 5329 lw(t9, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize)); |
5330 And(t9, t9, Operand(1)); | 5330 And(t9, t9, Operand(1)); |
5331 Branch(has_color, second_bit == 1 ? ne : eq, t9, Operand(zero_reg)); | 5331 Branch(has_color, second_bit == 1 ? ne : eq, t9, Operand(zero_reg)); |
5332 bind(&other_color); | 5332 bind(&other_color); |
5333 } | 5333 } |
5334 | 5334 |
5335 | 5335 |
5336 // Detect some, but not all, common pointer-free objects. This is used by the | 5336 // Detect some, but not all, common pointer-free objects. This is used by the |
5337 // incremental write barrier which doesn't care about oddballs (they are always | 5337 // incremental write barrier which doesn't care about oddballs (they are always |
5338 // marked black immediately so this code is not hit). | 5338 // marked black immediately so this code is not hit). |
5339 void MacroAssembler::JumpIfDataObject(Register value, | 5339 void MacroAssembler::JumpIfDataObject(Register value, |
5340 Register scratch, | 5340 Register scratch, |
5341 Label* not_data_object) { | 5341 Label* not_data_object) { |
5342 ASSERT(!AreAliased(value, scratch, t8, no_reg)); | 5342 DCHECK(!AreAliased(value, scratch, t8, no_reg)); |
5343 Label is_data_object; | 5343 Label is_data_object; |
5344 lw(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | 5344 lw(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); |
5345 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | 5345 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); |
5346 Branch(&is_data_object, eq, t8, Operand(scratch)); | 5346 Branch(&is_data_object, eq, t8, Operand(scratch)); |
5347 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | 5347 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); |
5348 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | 5348 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); |
5349 // If it's a string and it's not a cons string then it's an object containing | 5349 // If it's a string and it's not a cons string then it's an object containing |
5350 // no GC pointers. | 5350 // no GC pointers. |
5351 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 5351 lbu(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
5352 And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); | 5352 And(t8, scratch, Operand(kIsIndirectStringMask | kIsNotStringMask)); |
5353 Branch(not_data_object, ne, t8, Operand(zero_reg)); | 5353 Branch(not_data_object, ne, t8, Operand(zero_reg)); |
5354 bind(&is_data_object); | 5354 bind(&is_data_object); |
5355 } | 5355 } |
5356 | 5356 |
5357 | 5357 |
5358 void MacroAssembler::GetMarkBits(Register addr_reg, | 5358 void MacroAssembler::GetMarkBits(Register addr_reg, |
5359 Register bitmap_reg, | 5359 Register bitmap_reg, |
5360 Register mask_reg) { | 5360 Register mask_reg) { |
5361 ASSERT(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); | 5361 DCHECK(!AreAliased(addr_reg, bitmap_reg, mask_reg, no_reg)); |
5362 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); | 5362 And(bitmap_reg, addr_reg, Operand(~Page::kPageAlignmentMask)); |
5363 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); | 5363 Ext(mask_reg, addr_reg, kPointerSizeLog2, Bitmap::kBitsPerCellLog2); |
5364 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; | 5364 const int kLowBits = kPointerSizeLog2 + Bitmap::kBitsPerCellLog2; |
5365 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); | 5365 Ext(t8, addr_reg, kLowBits, kPageSizeBits - kLowBits); |
5366 sll(t8, t8, kPointerSizeLog2); | 5366 sll(t8, t8, kPointerSizeLog2); |
5367 Addu(bitmap_reg, bitmap_reg, t8); | 5367 Addu(bitmap_reg, bitmap_reg, t8); |
5368 li(t8, Operand(1)); | 5368 li(t8, Operand(1)); |
5369 sllv(mask_reg, t8, mask_reg); | 5369 sllv(mask_reg, t8, mask_reg); |
5370 } | 5370 } |
5371 | 5371 |
5372 | 5372 |
5373 void MacroAssembler::EnsureNotWhite( | 5373 void MacroAssembler::EnsureNotWhite( |
5374 Register value, | 5374 Register value, |
5375 Register bitmap_scratch, | 5375 Register bitmap_scratch, |
5376 Register mask_scratch, | 5376 Register mask_scratch, |
5377 Register load_scratch, | 5377 Register load_scratch, |
5378 Label* value_is_white_and_not_data) { | 5378 Label* value_is_white_and_not_data) { |
5379 ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); | 5379 DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, t8)); |
5380 GetMarkBits(value, bitmap_scratch, mask_scratch); | 5380 GetMarkBits(value, bitmap_scratch, mask_scratch); |
5381 | 5381 |
5382 // If the value is black or grey we don't need to do anything. | 5382 // If the value is black or grey we don't need to do anything. |
5383 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 5383 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
5384 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 5384 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
5385 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); | 5385 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); |
5386 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 5386 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
5387 | 5387 |
5388 Label done; | 5388 Label done; |
5389 | 5389 |
5390 // Since both black and grey have a 1 in the first position and white does | 5390 // Since both black and grey have a 1 in the first position and white does |
5391 // not have a 1 there we only need to check one bit. | 5391 // not have a 1 there we only need to check one bit. |
5392 lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 5392 lw(load_scratch, MemOperand(bitmap_scratch, MemoryChunk::kHeaderSize)); |
5393 And(t8, mask_scratch, load_scratch); | 5393 And(t8, mask_scratch, load_scratch); |
5394 Branch(&done, ne, t8, Operand(zero_reg)); | 5394 Branch(&done, ne, t8, Operand(zero_reg)); |
5395 | 5395 |
5396 if (emit_debug_code()) { | 5396 if (emit_debug_code()) { |
(...skipping 18 matching lines...) Expand all Loading... |
5415 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); | 5415 LoadRoot(t8, Heap::kHeapNumberMapRootIndex); |
5416 { | 5416 { |
5417 Label skip; | 5417 Label skip; |
5418 Branch(&skip, ne, t8, Operand(map)); | 5418 Branch(&skip, ne, t8, Operand(map)); |
5419 li(length, HeapNumber::kSize); | 5419 li(length, HeapNumber::kSize); |
5420 Branch(&is_data_object); | 5420 Branch(&is_data_object); |
5421 bind(&skip); | 5421 bind(&skip); |
5422 } | 5422 } |
5423 | 5423 |
5424 // Check for strings. | 5424 // Check for strings. |
5425 ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | 5425 DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); |
5426 ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | 5426 DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); |
5427 // If it's a string and it's not a cons string then it's an object containing | 5427 // If it's a string and it's not a cons string then it's an object containing |
5428 // no GC pointers. | 5428 // no GC pointers. |
5429 Register instance_type = load_scratch; | 5429 Register instance_type = load_scratch; |
5430 lbu(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 5430 lbu(instance_type, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
5431 And(t8, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask)); | 5431 And(t8, instance_type, Operand(kIsIndirectStringMask | kIsNotStringMask)); |
5432 Branch(value_is_white_and_not_data, ne, t8, Operand(zero_reg)); | 5432 Branch(value_is_white_and_not_data, ne, t8, Operand(zero_reg)); |
5433 // It's a non-indirect (non-cons and non-slice) string. | 5433 // It's a non-indirect (non-cons and non-slice) string. |
5434 // If it's external, the length is just ExternalString::kSize. | 5434 // If it's external, the length is just ExternalString::kSize. |
5435 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). | 5435 // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). |
5436 // External strings are the only ones with the kExternalStringTag bit | 5436 // External strings are the only ones with the kExternalStringTag bit |
5437 // set. | 5437 // set. |
5438 ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); | 5438 DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); |
5439 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); | 5439 DCHECK_EQ(0, kConsStringTag & kExternalStringTag); |
5440 And(t8, instance_type, Operand(kExternalStringTag)); | 5440 And(t8, instance_type, Operand(kExternalStringTag)); |
5441 { | 5441 { |
5442 Label skip; | 5442 Label skip; |
5443 Branch(&skip, eq, t8, Operand(zero_reg)); | 5443 Branch(&skip, eq, t8, Operand(zero_reg)); |
5444 li(length, ExternalString::kSize); | 5444 li(length, ExternalString::kSize); |
5445 Branch(&is_data_object); | 5445 Branch(&is_data_object); |
5446 bind(&skip); | 5446 bind(&skip); |
5447 } | 5447 } |
5448 | 5448 |
5449 // Sequential string, either ASCII or UC16. | 5449 // Sequential string, either ASCII or UC16. |
5450 // For ASCII (char-size of 1) we shift the smi tag away to get the length. | 5450 // For ASCII (char-size of 1) we shift the smi tag away to get the length. |
5451 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby | 5451 // For UC16 (char-size of 2) we just leave the smi tag in place, thereby |
5452 // getting the length multiplied by 2. | 5452 // getting the length multiplied by 2. |
5453 ASSERT(kOneByteStringTag == 4 && kStringEncodingMask == 4); | 5453 DCHECK(kOneByteStringTag == 4 && kStringEncodingMask == 4); |
5454 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 5454 DCHECK(kSmiTag == 0 && kSmiTagSize == 1); |
5455 lw(t9, FieldMemOperand(value, String::kLengthOffset)); | 5455 lw(t9, FieldMemOperand(value, String::kLengthOffset)); |
5456 And(t8, instance_type, Operand(kStringEncodingMask)); | 5456 And(t8, instance_type, Operand(kStringEncodingMask)); |
5457 { | 5457 { |
5458 Label skip; | 5458 Label skip; |
5459 Branch(&skip, eq, t8, Operand(zero_reg)); | 5459 Branch(&skip, eq, t8, Operand(zero_reg)); |
5460 srl(t9, t9, 1); | 5460 srl(t9, t9, 1); |
5461 bind(&skip); | 5461 bind(&skip); |
5462 } | 5462 } |
5463 Addu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); | 5463 Addu(length, t9, Operand(SeqString::kHeaderSize + kObjectAlignmentMask)); |
5464 And(length, length, Operand(~kObjectAlignmentMask)); | 5464 And(length, length, Operand(~kObjectAlignmentMask)); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5534 LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex); | 5534 LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex); |
5535 Branch(call_runtime, ne, a2, Operand(at)); | 5535 Branch(call_runtime, ne, a2, Operand(at)); |
5536 | 5536 |
5537 bind(&no_elements); | 5537 bind(&no_elements); |
5538 lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); | 5538 lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); |
5539 Branch(&next, ne, a2, Operand(null_value)); | 5539 Branch(&next, ne, a2, Operand(null_value)); |
5540 } | 5540 } |
5541 | 5541 |
5542 | 5542 |
5543 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { | 5543 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { |
5544 ASSERT(!output_reg.is(input_reg)); | 5544 DCHECK(!output_reg.is(input_reg)); |
5545 Label done; | 5545 Label done; |
5546 li(output_reg, Operand(255)); | 5546 li(output_reg, Operand(255)); |
5547 // Normal branch: nop in delay slot. | 5547 // Normal branch: nop in delay slot. |
5548 Branch(&done, gt, input_reg, Operand(output_reg)); | 5548 Branch(&done, gt, input_reg, Operand(output_reg)); |
5549 // Use delay slot in this branch. | 5549 // Use delay slot in this branch. |
5550 Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg)); | 5550 Branch(USE_DELAY_SLOT, &done, lt, input_reg, Operand(zero_reg)); |
5551 mov(output_reg, zero_reg); // In delay slot. | 5551 mov(output_reg, zero_reg); // In delay slot. |
5552 mov(output_reg, input_reg); // Value is in range 0..255. | 5552 mov(output_reg, input_reg); // Value is in range 0..255. |
5553 bind(&done); | 5553 bind(&done); |
5554 } | 5554 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5629 UNREACHABLE(); | 5629 UNREACHABLE(); |
5630 return no_reg; | 5630 return no_reg; |
5631 } | 5631 } |
5632 | 5632 |
5633 | 5633 |
5634 void MacroAssembler::JumpIfDictionaryInPrototypeChain( | 5634 void MacroAssembler::JumpIfDictionaryInPrototypeChain( |
5635 Register object, | 5635 Register object, |
5636 Register scratch0, | 5636 Register scratch0, |
5637 Register scratch1, | 5637 Register scratch1, |
5638 Label* found) { | 5638 Label* found) { |
5639 ASSERT(!scratch1.is(scratch0)); | 5639 DCHECK(!scratch1.is(scratch0)); |
5640 Factory* factory = isolate()->factory(); | 5640 Factory* factory = isolate()->factory(); |
5641 Register current = scratch0; | 5641 Register current = scratch0; |
5642 Label loop_again; | 5642 Label loop_again; |
5643 | 5643 |
5644 // Scratch contained elements pointer. | 5644 // Scratch contained elements pointer. |
5645 Move(current, object); | 5645 Move(current, object); |
5646 | 5646 |
5647 // Loop based on the map going up the prototype chain. | 5647 // Loop based on the map going up the prototype chain. |
5648 bind(&loop_again); | 5648 bind(&loop_again); |
5649 lw(current, FieldMemOperand(current, HeapObject::kMapOffset)); | 5649 lw(current, FieldMemOperand(current, HeapObject::kMapOffset)); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5685 CodePatcher::CodePatcher(byte* address, | 5685 CodePatcher::CodePatcher(byte* address, |
5686 int instructions, | 5686 int instructions, |
5687 FlushICache flush_cache) | 5687 FlushICache flush_cache) |
5688 : address_(address), | 5688 : address_(address), |
5689 size_(instructions * Assembler::kInstrSize), | 5689 size_(instructions * Assembler::kInstrSize), |
5690 masm_(NULL, address, size_ + Assembler::kGap), | 5690 masm_(NULL, address, size_ + Assembler::kGap), |
5691 flush_cache_(flush_cache) { | 5691 flush_cache_(flush_cache) { |
5692 // Create a new macro assembler pointing to the address of the code to patch. | 5692 // Create a new macro assembler pointing to the address of the code to patch. |
5693 // The size is adjusted with kGap on order for the assembler to generate size | 5693 // The size is adjusted with kGap on order for the assembler to generate size |
5694 // bytes of instructions without failing with buffer size constraints. | 5694 // bytes of instructions without failing with buffer size constraints. |
5695 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 5695 DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
5696 } | 5696 } |
5697 | 5697 |
5698 | 5698 |
5699 CodePatcher::~CodePatcher() { | 5699 CodePatcher::~CodePatcher() { |
5700 // Indicate that code has changed. | 5700 // Indicate that code has changed. |
5701 if (flush_cache_ == FLUSH) { | 5701 if (flush_cache_ == FLUSH) { |
5702 CpuFeatures::FlushICache(address_, size_); | 5702 CpuFeatures::FlushICache(address_, size_); |
5703 } | 5703 } |
5704 | 5704 |
5705 // Check that the code was patched as expected. | 5705 // Check that the code was patched as expected. |
5706 ASSERT(masm_.pc_ == address_ + size_); | 5706 DCHECK(masm_.pc_ == address_ + size_); |
5707 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 5707 DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
5708 } | 5708 } |
5709 | 5709 |
5710 | 5710 |
5711 void CodePatcher::Emit(Instr instr) { | 5711 void CodePatcher::Emit(Instr instr) { |
5712 masm()->emit(instr); | 5712 masm()->emit(instr); |
5713 } | 5713 } |
5714 | 5714 |
5715 | 5715 |
5716 void CodePatcher::Emit(Address addr) { | 5716 void CodePatcher::Emit(Address addr) { |
5717 masm()->emit(reinterpret_cast<Instr>(addr)); | 5717 masm()->emit(reinterpret_cast<Instr>(addr)); |
5718 } | 5718 } |
5719 | 5719 |
5720 | 5720 |
5721 void CodePatcher::ChangeBranchCondition(Condition cond) { | 5721 void CodePatcher::ChangeBranchCondition(Condition cond) { |
5722 Instr instr = Assembler::instr_at(masm_.pc_); | 5722 Instr instr = Assembler::instr_at(masm_.pc_); |
5723 ASSERT(Assembler::IsBranch(instr)); | 5723 DCHECK(Assembler::IsBranch(instr)); |
5724 uint32_t opcode = Assembler::GetOpcodeField(instr); | 5724 uint32_t opcode = Assembler::GetOpcodeField(instr); |
5725 // Currently only the 'eq' and 'ne' cond values are supported and the simple | 5725 // Currently only the 'eq' and 'ne' cond values are supported and the simple |
5726 // branch instructions (with opcode being the branch type). | 5726 // branch instructions (with opcode being the branch type). |
5727 // There are some special cases (see Assembler::IsBranch()) so extending this | 5727 // There are some special cases (see Assembler::IsBranch()) so extending this |
5728 // would be tricky. | 5728 // would be tricky. |
5729 ASSERT(opcode == BEQ || | 5729 DCHECK(opcode == BEQ || |
5730 opcode == BNE || | 5730 opcode == BNE || |
5731 opcode == BLEZ || | 5731 opcode == BLEZ || |
5732 opcode == BGTZ || | 5732 opcode == BGTZ || |
5733 opcode == BEQL || | 5733 opcode == BEQL || |
5734 opcode == BNEL || | 5734 opcode == BNEL || |
5735 opcode == BLEZL || | 5735 opcode == BLEZL || |
5736 opcode == BGTZL); | 5736 opcode == BGTZL); |
5737 opcode = (cond == eq) ? BEQ : BNE; | 5737 opcode = (cond == eq) ? BEQ : BNE; |
5738 instr = (instr & ~kOpcodeMask) | opcode; | 5738 instr = (instr & ~kOpcodeMask) | opcode; |
5739 masm_.emit(instr); | 5739 masm_.emit(instr); |
5740 } | 5740 } |
5741 | 5741 |
5742 | 5742 |
5743 void MacroAssembler::TruncatingDiv(Register result, | 5743 void MacroAssembler::TruncatingDiv(Register result, |
5744 Register dividend, | 5744 Register dividend, |
5745 int32_t divisor) { | 5745 int32_t divisor) { |
5746 ASSERT(!dividend.is(result)); | 5746 DCHECK(!dividend.is(result)); |
5747 ASSERT(!dividend.is(at)); | 5747 DCHECK(!dividend.is(at)); |
5748 ASSERT(!result.is(at)); | 5748 DCHECK(!result.is(at)); |
5749 MultiplierAndShift ms(divisor); | 5749 MultiplierAndShift ms(divisor); |
5750 li(at, Operand(ms.multiplier())); | 5750 li(at, Operand(ms.multiplier())); |
5751 Mult(dividend, Operand(at)); | 5751 Mult(dividend, Operand(at)); |
5752 mfhi(result); | 5752 mfhi(result); |
5753 if (divisor > 0 && ms.multiplier() < 0) { | 5753 if (divisor > 0 && ms.multiplier() < 0) { |
5754 Addu(result, result, Operand(dividend)); | 5754 Addu(result, result, Operand(dividend)); |
5755 } | 5755 } |
5756 if (divisor < 0 && ms.multiplier() > 0) { | 5756 if (divisor < 0 && ms.multiplier() > 0) { |
5757 Subu(result, result, Operand(dividend)); | 5757 Subu(result, result, Operand(dividend)); |
5758 } | 5758 } |
5759 if (ms.shift() > 0) sra(result, result, ms.shift()); | 5759 if (ms.shift() > 0) sra(result, result, ms.shift()); |
5760 srl(at, dividend, 31); | 5760 srl(at, dividend, 31); |
5761 Addu(result, result, Operand(at)); | 5761 Addu(result, result, Operand(at)); |
5762 } | 5762 } |
5763 | 5763 |
5764 | 5764 |
5765 } } // namespace v8::internal | 5765 } } // namespace v8::internal |
5766 | 5766 |
5767 #endif // V8_TARGET_ARCH_MIPS | 5767 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |