OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 | 272 |
273 // Clobber clobbered registers when running with the debug-code flag | 273 // Clobber clobbered registers when running with the debug-code flag |
274 // turned on to provoke errors. | 274 // turned on to provoke errors. |
275 if (emit_debug_code()) { | 275 if (emit_debug_code()) { |
276 li(address, Operand(BitCast<int32_t>(kZapValue + 12))); | 276 li(address, Operand(BitCast<int32_t>(kZapValue + 12))); |
277 li(value, Operand(BitCast<int32_t>(kZapValue + 16))); | 277 li(value, Operand(BitCast<int32_t>(kZapValue + 16))); |
278 } | 278 } |
279 } | 279 } |
280 | 280 |
281 | 281 |
282 void MacroAssembler::RememberedSetHelper(Register address, | 282 void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. |
| 283 Register address, |
283 Register scratch, | 284 Register scratch, |
284 SaveFPRegsMode fp_mode, | 285 SaveFPRegsMode fp_mode, |
285 RememberedSetFinalAction and_then) { | 286 RememberedSetFinalAction and_then) { |
286 Label done; | 287 Label done; |
| 288 if (FLAG_debug_code) { |
| 289 Label ok; |
| 290 JumpIfNotInNewSpace(object, scratch, &ok); |
| 291 stop("Remembered set pointer is in new space"); |
| 292 bind(&ok); |
| 293 } |
287 // Load store buffer top. | 294 // Load store buffer top. |
288 ExternalReference store_buffer = | 295 ExternalReference store_buffer = |
289 ExternalReference::store_buffer_top(isolate()); | 296 ExternalReference::store_buffer_top(isolate()); |
290 li(t8, Operand(store_buffer)); | 297 li(t8, Operand(store_buffer)); |
291 lw(scratch, MemOperand(t8)); | 298 lw(scratch, MemOperand(t8)); |
292 // Store pointer to buffer and increment buffer top. | 299 // Store pointer to buffer and increment buffer top. |
293 sw(address, MemOperand(scratch)); | 300 sw(address, MemOperand(scratch)); |
294 Addu(scratch, scratch, kPointerSize); | 301 Addu(scratch, scratch, kPointerSize); |
295 // Write back new top of buffer. | 302 // Write back new top of buffer. |
296 sw(scratch, MemOperand(t8)); | 303 sw(scratch, MemOperand(t8)); |
297 // Call stub on end of buffer. | 304 // Call stub on end of buffer. |
298 // Check for end of buffer. | 305 // Check for end of buffer. |
299 And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); | 306 And(t8, scratch, Operand(StoreBuffer::kStoreBufferOverflowBit)); |
300 if (and_then == kFallThroughAtEnd) { | 307 if (and_then == kFallThroughAtEnd) { |
301 Branch(&done, eq, t8, Operand(zero_reg)); | 308 Branch(&done, eq, t8, Operand(zero_reg)); |
302 } else { | 309 } else { |
303 ASSERT(and_then == kReturnAtEnd); | 310 ASSERT(and_then == kReturnAtEnd); |
304 Ret(ne, t8, Operand(zero_reg)); | 311 Ret(eq, t8, Operand(zero_reg)); |
305 } | 312 } |
306 push(ra); | 313 push(ra); |
307 StoreBufferOverflowStub store_buffer_overflow = | 314 StoreBufferOverflowStub store_buffer_overflow = |
308 StoreBufferOverflowStub(fp_mode); | 315 StoreBufferOverflowStub(fp_mode); |
309 CallStub(&store_buffer_overflow); | 316 CallStub(&store_buffer_overflow); |
310 pop(ra); | 317 pop(ra); |
311 bind(&done); | 318 bind(&done); |
312 if (and_then == kReturnAtEnd) { | 319 if (and_then == kReturnAtEnd) { |
313 Ret(); | 320 Ret(); |
314 } | 321 } |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 addiu(sp, sp, stack_offset); | 809 addiu(sp, sp, stack_offset); |
803 } | 810 } |
804 | 811 |
805 | 812 |
806 void MacroAssembler::MultiPushFPU(RegList regs) { | 813 void MacroAssembler::MultiPushFPU(RegList regs) { |
807 CpuFeatures::Scope scope(FPU); | 814 CpuFeatures::Scope scope(FPU); |
808 int16_t num_to_push = NumberOfBitsSet(regs); | 815 int16_t num_to_push = NumberOfBitsSet(regs); |
809 int16_t stack_offset = num_to_push * kDoubleSize; | 816 int16_t stack_offset = num_to_push * kDoubleSize; |
810 | 817 |
811 Subu(sp, sp, Operand(stack_offset)); | 818 Subu(sp, sp, Operand(stack_offset)); |
812 for (int16_t i = kNumRegisters; i > 0; i--) { | 819 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { |
813 if ((regs & (1 << i)) != 0) { | 820 if ((regs & (1 << i)) != 0) { |
814 stack_offset -= kDoubleSize; | 821 stack_offset -= kDoubleSize; |
815 sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); | 822 sdc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); |
816 } | 823 } |
817 } | 824 } |
818 } | 825 } |
819 | 826 |
820 | 827 |
821 void MacroAssembler::MultiPushReversedFPU(RegList regs) { | 828 void MacroAssembler::MultiPushReversedFPU(RegList regs) { |
822 CpuFeatures::Scope scope(FPU); | 829 CpuFeatures::Scope scope(FPU); |
(...skipping 21 matching lines...) Expand all Loading... |
844 } | 851 } |
845 } | 852 } |
846 addiu(sp, sp, stack_offset); | 853 addiu(sp, sp, stack_offset); |
847 } | 854 } |
848 | 855 |
849 | 856 |
850 void MacroAssembler::MultiPopReversedFPU(RegList regs) { | 857 void MacroAssembler::MultiPopReversedFPU(RegList regs) { |
851 CpuFeatures::Scope scope(FPU); | 858 CpuFeatures::Scope scope(FPU); |
852 int16_t stack_offset = 0; | 859 int16_t stack_offset = 0; |
853 | 860 |
854 for (int16_t i = kNumRegisters; i > 0; i--) { | 861 for (int16_t i = kNumRegisters - 1; i >= 0; i--) { |
855 if ((regs & (1 << i)) != 0) { | 862 if ((regs & (1 << i)) != 0) { |
856 ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); | 863 ldc1(FPURegister::from_code(i), MemOperand(sp, stack_offset)); |
857 stack_offset += kDoubleSize; | 864 stack_offset += kDoubleSize; |
858 } | 865 } |
859 } | 866 } |
860 addiu(sp, sp, stack_offset); | 867 addiu(sp, sp, stack_offset); |
861 } | 868 } |
862 | 869 |
863 | 870 |
864 void MacroAssembler::FlushICache(Register address, unsigned instructions) { | 871 void MacroAssembler::FlushICache(Register address, unsigned instructions) { |
(...skipping 2331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3196 lbu(scratch, MemOperand(src)); | 3203 lbu(scratch, MemOperand(src)); |
3197 Addu(src, src, 1); | 3204 Addu(src, src, 1); |
3198 sb(scratch, MemOperand(dst)); | 3205 sb(scratch, MemOperand(dst)); |
3199 Addu(dst, dst, 1); | 3206 Addu(dst, dst, 1); |
3200 Subu(length, length, Operand(1)); | 3207 Subu(length, length, Operand(1)); |
3201 Branch(&byte_loop_1, ne, length, Operand(zero_reg)); | 3208 Branch(&byte_loop_1, ne, length, Operand(zero_reg)); |
3202 bind(&done); | 3209 bind(&done); |
3203 } | 3210 } |
3204 | 3211 |
3205 | 3212 |
| 3213 void MacroAssembler::InitializeFieldsWithFiller(Register start_offset, |
| 3214 Register end_offset, |
| 3215 Register filler) { |
| 3216 Label loop, entry; |
| 3217 Branch(&entry); |
| 3218 bind(&loop); |
| 3219 sw(filler, MemOperand(start_offset)); |
| 3220 Addu(start_offset, start_offset, kPointerSize); |
| 3221 bind(&entry); |
| 3222 Branch(&loop, lt, start_offset, Operand(end_offset)); |
| 3223 } |
| 3224 |
| 3225 |
3206 void MacroAssembler::CheckFastElements(Register map, | 3226 void MacroAssembler::CheckFastElements(Register map, |
3207 Register scratch, | 3227 Register scratch, |
3208 Label* fail) { | 3228 Label* fail) { |
3209 STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); | 3229 STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); |
3210 STATIC_ASSERT(FAST_ELEMENTS == 1); | 3230 STATIC_ASSERT(FAST_ELEMENTS == 1); |
3211 lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset)); | 3231 lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset)); |
3212 Branch(fail, hi, scratch, Operand(Map::kMaximumBitField2FastElementValue)); | 3232 Branch(fail, hi, scratch, Operand(Map::kMaximumBitField2FastElementValue)); |
3213 } | 3233 } |
3214 | 3234 |
3215 | 3235 |
| 3236 void MacroAssembler::CheckFastObjectElements(Register map, |
| 3237 Register scratch, |
| 3238 Label* fail) { |
| 3239 STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); |
| 3240 STATIC_ASSERT(FAST_ELEMENTS == 1); |
| 3241 lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset)); |
| 3242 Branch(fail, ls, scratch, |
| 3243 Operand(Map::kMaximumBitField2FastSmiOnlyElementValue)); |
| 3244 Branch(fail, hi, scratch, |
| 3245 Operand(Map::kMaximumBitField2FastElementValue)); |
| 3246 } |
| 3247 |
| 3248 |
| 3249 void MacroAssembler::CheckFastSmiOnlyElements(Register map, |
| 3250 Register scratch, |
| 3251 Label* fail) { |
| 3252 STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0); |
| 3253 lbu(scratch, FieldMemOperand(map, Map::kBitField2Offset)); |
| 3254 Branch(fail, hi, scratch, |
| 3255 Operand(Map::kMaximumBitField2FastSmiOnlyElementValue)); |
| 3256 } |
| 3257 |
| 3258 |
| 3259 void MacroAssembler::StoreNumberToDoubleElements(Register value_reg, |
| 3260 Register key_reg, |
| 3261 Register receiver_reg, |
| 3262 Register elements_reg, |
| 3263 Register scratch1, |
| 3264 Register scratch2, |
| 3265 Register scratch3, |
| 3266 Register scratch4, |
| 3267 Label* fail) { |
| 3268 Label smi_value, maybe_nan, have_double_value, is_nan, done; |
| 3269 Register mantissa_reg = scratch2; |
| 3270 Register exponent_reg = scratch3; |
| 3271 |
| 3272 // Handle smi values specially. |
| 3273 JumpIfSmi(value_reg, &smi_value); |
| 3274 |
| 3275 // Ensure that the object is a heap number |
| 3276 CheckMap(value_reg, |
| 3277 scratch1, |
| 3278 isolate()->factory()->heap_number_map(), |
| 3279 fail, |
| 3280 DONT_DO_SMI_CHECK); |
| 3281 |
| 3282 // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000 |
| 3283 // in the exponent. |
| 3284 li(scratch1, Operand(kNaNOrInfinityLowerBoundUpper32)); |
| 3285 lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset)); |
| 3286 Branch(&maybe_nan, ge, exponent_reg, Operand(scratch1)); |
| 3287 |
| 3288 lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); |
| 3289 |
| 3290 bind(&have_double_value); |
| 3291 sll(scratch1, key_reg, kDoubleSizeLog2 - kSmiTagSize); |
| 3292 Addu(scratch1, scratch1, elements_reg); |
| 3293 sw(mantissa_reg, FieldMemOperand(scratch1, FixedDoubleArray::kHeaderSize)); |
| 3294 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); |
| 3295 sw(exponent_reg, FieldMemOperand(scratch1, offset)); |
| 3296 jmp(&done); |
| 3297 |
| 3298 bind(&maybe_nan); |
| 3299 // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise |
| 3300 // it's an Infinity, and the non-NaN code path applies. |
| 3301 Branch(&is_nan, gt, exponent_reg, Operand(scratch1)); |
| 3302 lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); |
| 3303 Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg)); |
| 3304 bind(&is_nan); |
| 3305 // Load canonical NaN for storing into the double array. |
| 3306 uint64_t nan_int64 = BitCast<uint64_t>( |
| 3307 FixedDoubleArray::canonical_not_the_hole_nan_as_double()); |
| 3308 li(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64))); |
| 3309 li(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32))); |
| 3310 jmp(&have_double_value); |
| 3311 |
| 3312 bind(&smi_value); |
| 3313 Addu(scratch1, elements_reg, |
| 3314 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag)); |
| 3315 sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize); |
| 3316 Addu(scratch1, scratch1, scratch2); |
| 3317 // scratch1 is now effective address of the double element |
| 3318 |
| 3319 FloatingPointHelper::Destination destination; |
| 3320 if (CpuFeatures::IsSupported(FPU)) { |
| 3321 destination = FloatingPointHelper::kFPURegisters; |
| 3322 } else { |
| 3323 destination = FloatingPointHelper::kCoreRegisters; |
| 3324 } |
| 3325 |
| 3326 Register untagged_value = receiver_reg; |
| 3327 SmiUntag(untagged_value, value_reg); |
| 3328 FloatingPointHelper::ConvertIntToDouble(this, |
| 3329 untagged_value, |
| 3330 destination, |
| 3331 f0, |
| 3332 mantissa_reg, |
| 3333 exponent_reg, |
| 3334 scratch4, |
| 3335 f2); |
| 3336 if (destination == FloatingPointHelper::kFPURegisters) { |
| 3337 CpuFeatures::Scope scope(FPU); |
| 3338 sdc1(f0, MemOperand(scratch1, 0)); |
| 3339 } else { |
| 3340 sw(mantissa_reg, MemOperand(scratch1, 0)); |
| 3341 sw(exponent_reg, MemOperand(scratch1, Register::kSizeInBytes)); |
| 3342 } |
| 3343 bind(&done); |
| 3344 } |
| 3345 |
| 3346 |
3216 void MacroAssembler::CheckMap(Register obj, | 3347 void MacroAssembler::CheckMap(Register obj, |
3217 Register scratch, | 3348 Register scratch, |
3218 Handle<Map> map, | 3349 Handle<Map> map, |
3219 Label* fail, | 3350 Label* fail, |
3220 SmiCheckType smi_check_type) { | 3351 SmiCheckType smi_check_type) { |
3221 if (smi_check_type == DO_SMI_CHECK) { | 3352 if (smi_check_type == DO_SMI_CHECK) { |
3222 JumpIfSmi(obj, fail); | 3353 JumpIfSmi(obj, fail); |
3223 } | 3354 } |
3224 lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); | 3355 lw(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); |
3225 li(at, Operand(map)); | 3356 li(at, Operand(map)); |
(...skipping 1340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4566 | 4697 |
4567 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 4698 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
4568 Register scratch) { | 4699 Register scratch) { |
4569 PrepareCallCFunction(num_reg_arguments, 0, scratch); | 4700 PrepareCallCFunction(num_reg_arguments, 0, scratch); |
4570 } | 4701 } |
4571 | 4702 |
4572 | 4703 |
4573 void MacroAssembler::CallCFunction(ExternalReference function, | 4704 void MacroAssembler::CallCFunction(ExternalReference function, |
4574 int num_reg_arguments, | 4705 int num_reg_arguments, |
4575 int num_double_arguments) { | 4706 int num_double_arguments) { |
4576 CallCFunctionHelper(no_reg, | 4707 li(t8, Operand(function)); |
4577 function, | 4708 CallCFunctionHelper(t8, num_reg_arguments, num_double_arguments); |
4578 t8, | |
4579 num_reg_arguments, | |
4580 num_double_arguments); | |
4581 } | 4709 } |
4582 | 4710 |
4583 | 4711 |
4584 void MacroAssembler::CallCFunction(Register function, | 4712 void MacroAssembler::CallCFunction(Register function, |
4585 Register scratch, | |
4586 int num_reg_arguments, | 4713 int num_reg_arguments, |
4587 int num_double_arguments) { | 4714 int num_double_arguments) { |
4588 CallCFunctionHelper(function, | 4715 CallCFunctionHelper(function, num_reg_arguments, num_double_arguments); |
4589 ExternalReference::the_hole_value_location(isolate()), | |
4590 scratch, | |
4591 num_reg_arguments, | |
4592 num_double_arguments); | |
4593 } | 4716 } |
4594 | 4717 |
4595 | 4718 |
4596 void MacroAssembler::CallCFunction(ExternalReference function, | 4719 void MacroAssembler::CallCFunction(ExternalReference function, |
4597 int num_arguments) { | 4720 int num_arguments) { |
4598 CallCFunction(function, num_arguments, 0); | 4721 CallCFunction(function, num_arguments, 0); |
4599 } | 4722 } |
4600 | 4723 |
4601 | 4724 |
4602 void MacroAssembler::CallCFunction(Register function, | 4725 void MacroAssembler::CallCFunction(Register function, |
4603 Register scratch, | |
4604 int num_arguments) { | 4726 int num_arguments) { |
4605 CallCFunction(function, scratch, num_arguments, 0); | 4727 CallCFunction(function, num_arguments, 0); |
4606 } | 4728 } |
4607 | 4729 |
4608 | 4730 |
4609 void MacroAssembler::CallCFunctionHelper(Register function, | 4731 void MacroAssembler::CallCFunctionHelper(Register function, |
4610 ExternalReference function_reference, | |
4611 Register scratch, | |
4612 int num_reg_arguments, | 4732 int num_reg_arguments, |
4613 int num_double_arguments) { | 4733 int num_double_arguments) { |
4614 ASSERT(has_frame()); | 4734 ASSERT(has_frame()); |
4615 // Make sure that the stack is aligned before calling a C function unless | 4735 // Make sure that the stack is aligned before calling a C function unless |
4616 // running in the simulator. The simulator has its own alignment check which | 4736 // running in the simulator. The simulator has its own alignment check which |
4617 // provides more information. | 4737 // provides more information. |
4618 // The argument stots are presumed to have been set up by | 4738 // The argument stots are presumed to have been set up by |
4619 // PrepareCallCFunction. The C function must be called via t9, for mips ABI. | 4739 // PrepareCallCFunction. The C function must be called via t9, for mips ABI. |
4620 | 4740 |
4621 #if defined(V8_HOST_ARCH_MIPS) | 4741 #if defined(V8_HOST_ARCH_MIPS) |
(...skipping 10 matching lines...) Expand all Loading... |
4632 stop("Unexpected alignment in CallCFunction"); | 4752 stop("Unexpected alignment in CallCFunction"); |
4633 bind(&alignment_as_expected); | 4753 bind(&alignment_as_expected); |
4634 } | 4754 } |
4635 } | 4755 } |
4636 #endif // V8_HOST_ARCH_MIPS | 4756 #endif // V8_HOST_ARCH_MIPS |
4637 | 4757 |
4638 // Just call directly. The function called cannot cause a GC, or | 4758 // Just call directly. The function called cannot cause a GC, or |
4639 // allow preemption, so the return address in the link register | 4759 // allow preemption, so the return address in the link register |
4640 // stays correct. | 4760 // stays correct. |
4641 | 4761 |
4642 if (function.is(no_reg)) { | 4762 if (!function.is(t9)) { |
4643 function = t9; | |
4644 li(function, Operand(function_reference)); | |
4645 } else if (!function.is(t9)) { | |
4646 mov(t9, function); | 4763 mov(t9, function); |
4647 function = t9; | 4764 function = t9; |
4648 } | 4765 } |
4649 | 4766 |
4650 Call(function); | 4767 Call(function); |
4651 | 4768 |
4652 int stack_passed_arguments = CalculateStackPassedWords( | 4769 int stack_passed_arguments = CalculateStackPassedWords( |
4653 num_reg_arguments, num_double_arguments); | 4770 num_reg_arguments, num_double_arguments); |
4654 | 4771 |
4655 if (OS::ActivationFrameAlignment() > kPointerSize) { | 4772 if (OS::ActivationFrameAlignment() > kPointerSize) { |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5007 opcode == BGTZL); | 5124 opcode == BGTZL); |
5008 opcode = (cond == eq) ? BEQ : BNE; | 5125 opcode = (cond == eq) ? BEQ : BNE; |
5009 instr = (instr & ~kOpcodeMask) | opcode; | 5126 instr = (instr & ~kOpcodeMask) | opcode; |
5010 masm_.emit(instr); | 5127 masm_.emit(instr); |
5011 } | 5128 } |
5012 | 5129 |
5013 | 5130 |
5014 } } // namespace v8::internal | 5131 } } // namespace v8::internal |
5015 | 5132 |
5016 #endif // V8_TARGET_ARCH_MIPS | 5133 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |