diff options
Diffstat (limited to 'deps/v8/src/arm/macro-assembler-arm.cc')
-rw-r--r-- | deps/v8/src/arm/macro-assembler-arm.cc | 430 |
1 files changed, 153 insertions, 277 deletions
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index c67fad8e1d..c3d825b87b 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -264,6 +264,35 @@ void MacroAssembler::Move(DwVfpRegister dst, DwVfpRegister src, } } +void MacroAssembler::Move(QwNeonRegister dst, QwNeonRegister src) { + if (!dst.is(src)) { + vmov(dst, src); + } +} + +void MacroAssembler::Swap(DwVfpRegister srcdst0, DwVfpRegister srcdst1) { + if (srcdst0.is(srcdst1)) return; // Swapping aliased registers emits nothing. + + DCHECK(VfpRegisterIsAvailable(srcdst0)); + DCHECK(VfpRegisterIsAvailable(srcdst1)); + + if (CpuFeatures::IsSupported(NEON)) { + vswp(srcdst0, srcdst1); + } else { + DCHECK(!srcdst0.is(kScratchDoubleReg)); + DCHECK(!srcdst1.is(kScratchDoubleReg)); + vmov(kScratchDoubleReg, srcdst0); + vmov(srcdst0, srcdst1); + vmov(srcdst1, kScratchDoubleReg); + } +} + +void MacroAssembler::Swap(QwNeonRegister srcdst0, QwNeonRegister srcdst1) { + if (!srcdst0.is(srcdst1)) { + vswp(srcdst0, srcdst1); + } +} + void MacroAssembler::Mls(Register dst, Register src1, Register src2, Register srcA, Condition cond) { if (CpuFeatures::IsSupported(ARMv7)) { @@ -1052,8 +1081,8 @@ void MacroAssembler::VmovLow(DwVfpRegister dst, Register src) { } void MacroAssembler::VmovExtended(Register dst, int src_code) { - DCHECK_LE(32, src_code); - DCHECK_GT(64, src_code); + DCHECK_LE(SwVfpRegister::kMaxNumRegisters, src_code); + DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, src_code); if (src_code & 0x1) { VmovHigh(dst, DwVfpRegister::from_code(src_code / 2)); } else { @@ -1062,8 +1091,8 @@ void MacroAssembler::VmovExtended(Register dst, int src_code) { } void MacroAssembler::VmovExtended(int dst_code, Register src) { - DCHECK_LE(32, dst_code); - DCHECK_GT(64, dst_code); + DCHECK_LE(SwVfpRegister::kMaxNumRegisters, dst_code); + DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, dst_code); if (dst_code & 0x1) { VmovHigh(DwVfpRegister::from_code(dst_code / 2), src); } else { @@ -1073,22 +1102,23 @@ void MacroAssembler::VmovExtended(int dst_code, Register src) { void MacroAssembler::VmovExtended(int dst_code, int src_code, Register scratch) { - if (src_code < 32 && dst_code < 32) { + if (src_code < SwVfpRegister::kMaxNumRegisters && + dst_code < SwVfpRegister::kMaxNumRegisters) { // src and dst are both s-registers. vmov(SwVfpRegister::from_code(dst_code), SwVfpRegister::from_code(src_code)); - } else if (src_code < 32) { + } else if (src_code < SwVfpRegister::kMaxNumRegisters) { // src is an s-register. vmov(scratch, SwVfpRegister::from_code(src_code)); VmovExtended(dst_code, scratch); - } else if (dst_code < 32) { + } else if (dst_code < SwVfpRegister::kMaxNumRegisters) { // dst is an s-register. VmovExtended(scratch, src_code); vmov(SwVfpRegister::from_code(dst_code), scratch); } else { // Neither src or dst are s-registers. - DCHECK_GT(64, src_code); - DCHECK_GT(64, dst_code); + DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, src_code); + DCHECK_GT(SwVfpRegister::kMaxNumRegisters * 2, dst_code); VmovExtended(scratch, src_code); VmovExtended(dst_code, scratch); } @@ -1096,7 +1126,7 @@ void MacroAssembler::VmovExtended(int dst_code, int src_code, void MacroAssembler::VmovExtended(int dst_code, const MemOperand& src, Register scratch) { - if (dst_code >= 32) { + if (dst_code >= SwVfpRegister::kMaxNumRegisters) { ldr(scratch, src); VmovExtended(dst_code, scratch); } else { @@ -1106,7 +1136,7 @@ void MacroAssembler::VmovExtended(int dst_code, const MemOperand& src, void MacroAssembler::VmovExtended(const MemOperand& dst, int src_code, Register scratch) { - if (src_code >= 32) { + if (src_code >= SwVfpRegister::kMaxNumRegisters) { VmovExtended(scratch, src_code); str(scratch, dst); } else { @@ -1114,6 +1144,105 @@ void MacroAssembler::VmovExtended(const MemOperand& dst, int src_code, } } +void MacroAssembler::ExtractLane(Register dst, QwNeonRegister src, + NeonDataType dt, int lane) { + int bytes_per_lane = dt & NeonDataTypeSizeMask; // 1, 2, 4 + int log2_bytes_per_lane = bytes_per_lane / 2; // 0, 1, 2 + int byte = lane << log2_bytes_per_lane; + int double_word = byte >> kDoubleSizeLog2; + int double_byte = byte & (kDoubleSize - 1); + int double_lane = double_byte >> log2_bytes_per_lane; + DwVfpRegister double_source = + DwVfpRegister::from_code(src.code() * 2 + double_word); + vmov(dt, dst, double_source, double_lane); +} + +void MacroAssembler::ExtractLane(SwVfpRegister dst, QwNeonRegister src, + Register scratch, int lane) { + int s_code = src.code() * 4 + lane; + VmovExtended(dst.code(), s_code, scratch); +} + +void MacroAssembler::ReplaceLane(QwNeonRegister dst, QwNeonRegister src, + Register src_lane, NeonDataType dt, int lane) { + Move(dst, src); + int bytes_per_lane = dt & NeonDataTypeSizeMask; // 1, 2, 4 + int log2_bytes_per_lane = bytes_per_lane / 2; // 0, 1, 2 + int byte = lane << log2_bytes_per_lane; + int double_word = byte >> kDoubleSizeLog2; + int double_byte = byte & (kDoubleSize - 1); + int double_lane = double_byte >> log2_bytes_per_lane; + DwVfpRegister double_dst = + DwVfpRegister::from_code(dst.code() * 2 + double_word); + vmov(dt, double_dst, double_lane, src_lane); +} + +void MacroAssembler::ReplaceLane(QwNeonRegister dst, QwNeonRegister src, + SwVfpRegister src_lane, Register scratch, + int lane) { + Move(dst, src); + int s_code = dst.code() * 4 + lane; + VmovExtended(s_code, src_lane.code(), scratch); +} + +void MacroAssembler::Swizzle(QwNeonRegister dst, QwNeonRegister src, + Register scratch, NeonSize size, uint32_t lanes) { + // TODO(bbudge) Handle Int16x8, Int8x16 vectors. + DCHECK_EQ(Neon32, size); + DCHECK_IMPLIES(size == Neon32, lanes < 0xFFFFu); + if (size == Neon32) { + switch (lanes) { + // TODO(bbudge) Handle more special cases. + case 0x3210: // Identity. + Move(dst, src); + return; + case 0x1032: // Swap top and bottom. + vext(dst, src, src, 8); + return; + case 0x2103: // Rotation. + vext(dst, src, src, 12); + return; + case 0x0321: // Rotation. + vext(dst, src, src, 4); + return; + case 0x0000: // Equivalent to vdup. + case 0x1111: + case 0x2222: + case 0x3333: { + int lane_code = src.code() * 4 + (lanes & 0xF); + if (lane_code >= SwVfpRegister::kMaxNumRegisters) { + // TODO(bbudge) use vdup (vdup.32 dst, D<src>[lane]) once implemented. + int temp_code = kScratchDoubleReg.code() * 2; + VmovExtended(temp_code, lane_code, scratch); + lane_code = temp_code; + } + vdup(dst, SwVfpRegister::from_code(lane_code)); + return; + } + case 0x2301: // Swap lanes 0, 1 and lanes 2, 3. + vrev64(Neon32, dst, src); + return; + default: // Handle all other cases with vmovs. + int src_code = src.code() * 4; + int dst_code = dst.code() * 4; + bool in_place = src.is(dst); + if (in_place) { + vmov(kScratchQuadReg, src); + src_code = kScratchQuadReg.code() * 4; + } + for (int i = 0; i < 4; i++) { + int lane = (lanes >> (i * 4) & 0xF); + VmovExtended(dst_code + i, src_code + lane, scratch); + } + if (in_place) { + // Restore zero reg. + veor(kDoubleRegZero, kDoubleRegZero, kDoubleRegZero); + } + return; + } + } +} + void MacroAssembler::LslPair(Register dst_low, Register dst_high, Register src_low, Register src_high, Register scratch, Register shift) { @@ -1629,18 +1758,16 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, } } - -void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, - const ParameterCount& expected, - const ParameterCount& actual) { - Label skip_flooding; - ExternalReference last_step_action = - ExternalReference::debug_last_step_action_address(isolate()); - STATIC_ASSERT(StepFrame > StepIn); - mov(r4, Operand(last_step_action)); +void MacroAssembler::CheckDebugHook(Register fun, Register new_target, + const ParameterCount& expected, + const ParameterCount& actual) { + Label skip_hook; + ExternalReference debug_hook_avtive = + ExternalReference::debug_hook_on_function_call_address(isolate()); + mov(r4, Operand(debug_hook_avtive)); ldrsb(r4, MemOperand(r4)); - cmp(r4, Operand(StepIn)); - b(lt, &skip_flooding); + cmp(r4, Operand(0)); + b(eq, &skip_hook); { FrameScope frame(this, has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); @@ -1657,7 +1784,7 @@ void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, } Push(fun); Push(fun); - CallRuntime(Runtime::kDebugPrepareStepInIfStepping); + CallRuntime(Runtime::kDebugOnFunctionCall); Pop(fun); if (new_target.is_valid()) { Pop(new_target); @@ -1671,7 +1798,7 @@ void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, SmiUntag(expected.reg()); } } - bind(&skip_flooding); + bind(&skip_hook); } @@ -1685,8 +1812,8 @@ void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, DCHECK(function.is(r1)); DCHECK_IMPLIES(new_target.is_valid(), new_target.is(r3)); - if (call_wrapper.NeedsDebugStepCheck()) { - FloodFunctionIfStepping(function, new_target, expected, actual); + if (call_wrapper.NeedsDebugHookCheck()) { + CheckDebugHook(function, new_target, expected, actual); } // Clear the new.target register if not given. @@ -2177,112 +2304,6 @@ void MacroAssembler::FastAllocate(int object_size, Register result, add(result, result, Operand(kHeapObjectTag)); } -void MacroAssembler::AllocateTwoByteString(Register result, - Register length, - Register scratch1, - Register scratch2, - Register scratch3, - Label* gc_required) { - // Calculate the number of bytes needed for the characters in the string while - // observing object alignment. - DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); - mov(scratch1, Operand(length, LSL, 1)); // Length in bytes, not chars. - add(scratch1, scratch1, - Operand(kObjectAlignmentMask + SeqTwoByteString::kHeaderSize)); - and_(scratch1, scratch1, Operand(~kObjectAlignmentMask)); - - // Allocate two-byte string in new space. - Allocate(scratch1, result, scratch2, scratch3, gc_required, - NO_ALLOCATION_FLAGS); - - // Set the map, length and hash field. - InitializeNewString(result, - length, - Heap::kStringMapRootIndex, - scratch1, - scratch2); -} - - -void MacroAssembler::AllocateOneByteString(Register result, Register length, - Register scratch1, Register scratch2, - Register scratch3, - Label* gc_required) { - // Calculate the number of bytes needed for the characters in the string while - // observing object alignment. - DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); - DCHECK(kCharSize == 1); - add(scratch1, length, - Operand(kObjectAlignmentMask + SeqOneByteString::kHeaderSize)); - and_(scratch1, scratch1, Operand(~kObjectAlignmentMask)); - - // Allocate one-byte string in new space. - Allocate(scratch1, result, scratch2, scratch3, gc_required, - NO_ALLOCATION_FLAGS); - - // Set the map, length and hash field. - InitializeNewString(result, length, Heap::kOneByteStringMapRootIndex, - scratch1, scratch2); -} - - -void MacroAssembler::AllocateTwoByteConsString(Register result, - Register length, - Register scratch1, - Register scratch2, - Label* gc_required) { - Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, - NO_ALLOCATION_FLAGS); - - InitializeNewString(result, - length, - Heap::kConsStringMapRootIndex, - scratch1, - scratch2); -} - - -void MacroAssembler::AllocateOneByteConsString(Register result, Register length, - Register scratch1, - Register scratch2, - Label* gc_required) { - Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required, - NO_ALLOCATION_FLAGS); - - InitializeNewString(result, length, Heap::kConsOneByteStringMapRootIndex, - scratch1, scratch2); -} - - -void MacroAssembler::AllocateTwoByteSlicedString(Register result, - Register length, - Register scratch1, - Register scratch2, - Label* gc_required) { - Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, - NO_ALLOCATION_FLAGS); - - InitializeNewString(result, - length, - Heap::kSlicedStringMapRootIndex, - scratch1, - scratch2); -} - - -void MacroAssembler::AllocateOneByteSlicedString(Register result, - Register length, - Register scratch1, - Register scratch2, - Label* gc_required) { - Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required, - NO_ALLOCATION_FLAGS); - - InitializeNewString(result, length, Heap::kSlicedOneByteStringMapRootIndex, - scratch1, scratch2); -} - - void MacroAssembler::CompareObjectType(Register object, Register map, Register type_reg, @@ -2314,68 +2335,6 @@ void MacroAssembler::CompareRoot(Register obj, cmp(obj, ip); } -void MacroAssembler::CheckFastObjectElements(Register map, - Register scratch, - Label* fail) { - STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); - STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); - STATIC_ASSERT(FAST_ELEMENTS == 2); - STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); - ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset)); - cmp(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue)); - b(ls, fail); - cmp(scratch, Operand(Map::kMaximumBitField2FastHoleyElementValue)); - b(hi, fail); -} - - -void MacroAssembler::CheckFastSmiElements(Register map, - Register scratch, - Label* fail) { - STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); - STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); - ldrb(scratch, FieldMemOperand(map, Map::kBitField2Offset)); - cmp(scratch, Operand(Map::kMaximumBitField2FastHoleySmiElementValue)); - b(hi, fail); -} - - -void MacroAssembler::StoreNumberToDoubleElements( - Register value_reg, - Register key_reg, - Register elements_reg, - Register scratch1, - LowDwVfpRegister double_scratch, - Label* fail, - int elements_offset) { - DCHECK(!AreAliased(value_reg, key_reg, elements_reg, scratch1)); - Label smi_value, store; - - // Handle smi values specially. - JumpIfSmi(value_reg, &smi_value); - - // Ensure that the object is a heap number - CheckMap(value_reg, - scratch1, - isolate()->factory()->heap_number_map(), - fail, - DONT_DO_SMI_CHECK); - - vldr(double_scratch, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); - VFPCanonicalizeNaN(double_scratch); - b(&store); - - bind(&smi_value); - SmiToDouble(double_scratch, value_reg); - - bind(&store); - add(scratch1, elements_reg, Operand::DoubleOffsetFromSmiKey(key_reg)); - vstr(double_scratch, - FieldMemOperand(scratch1, - FixedDoubleArray::kHeaderSize - elements_offset)); -} - - void MacroAssembler::CompareMap(Register obj, Register scratch, Handle<Map> map, @@ -2878,28 +2837,6 @@ void MacroAssembler::LoadContext(Register dst, int context_chain_length) { } } - -void MacroAssembler::LoadTransitionedArrayMapConditional( - ElementsKind expected_kind, - ElementsKind transitioned_kind, - Register map_in_out, - Register scratch, - Label* no_map_match) { - DCHECK(IsFastElementsKind(expected_kind)); - DCHECK(IsFastElementsKind(transitioned_kind)); - - // Check that the function's map is the same as the expected cached map. - ldr(scratch, NativeContextMemOperand()); - ldr(ip, ContextMemOperand(scratch, Context::ArrayMapIndex(expected_kind))); - cmp(map_in_out, ip); - b(ne, no_map_match); - - // Use the transitioned cached map. - ldr(map_in_out, - ContextMemOperand(scratch, Context::ArrayMapIndex(transitioned_kind))); -} - - void MacroAssembler::LoadNativeContextSlot(int index, Register dst) { ldr(dst, NativeContextMemOperand()); ldr(dst, ContextMemOperand(dst, index)); @@ -2962,15 +2899,6 @@ void MacroAssembler::UntagAndJumpIfSmi( b(cc, smi_case); // Shifter carry is not set for a smi. } - -void MacroAssembler::UntagAndJumpIfNotSmi( - Register dst, Register src, Label* non_smi_case) { - STATIC_ASSERT(kSmiTag == 0); - SmiUntag(dst, src, SetCC); - b(cs, non_smi_case); // Shifter carry is set for a non-smi. -} - - void MacroAssembler::JumpIfEitherSmi(Register reg1, Register reg2, Label* on_either_smi) { @@ -3411,19 +3339,6 @@ void MacroAssembler::JumpIfBothInstanceTypesAreNotSequentialOneByte( b(ne, failure); } - -void MacroAssembler::JumpIfInstanceTypeIsNotSequentialOneByte(Register type, - Register scratch, - Label* failure) { - const int kFlatOneByteStringMask = - kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; - const int kFlatOneByteStringTag = - kStringTag | kOneByteStringTag | kSeqStringTag; - and_(scratch, type, Operand(kFlatOneByteStringMask)); - cmp(scratch, Operand(kFlatOneByteStringTag)); - b(ne, failure); -} - static const int kRegisterPassedArguments = 4; @@ -3861,45 +3776,6 @@ Register GetRegisterThatIsNotOneOf(Register reg1, return no_reg; } - -void MacroAssembler::JumpIfDictionaryInPrototypeChain( - Register object, - Register scratch0, - Register scratch1, - Label* found) { - DCHECK(!scratch1.is(scratch0)); - Register current = scratch0; - Label loop_again, end; - - // scratch contained elements pointer. - mov(current, object); - ldr(current, FieldMemOperand(current, HeapObject::kMapOffset)); - ldr(current, FieldMemOperand(current, Map::kPrototypeOffset)); - CompareRoot(current, Heap::kNullValueRootIndex); - b(eq, &end); - - // Loop based on the map going up the prototype chain. - bind(&loop_again); - ldr(current, FieldMemOperand(current, HeapObject::kMapOffset)); - - STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE); - STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE); - ldrb(scratch1, FieldMemOperand(current, Map::kInstanceTypeOffset)); - cmp(scratch1, Operand(JS_OBJECT_TYPE)); - b(lo, found); - - ldr(scratch1, FieldMemOperand(current, Map::kBitField2Offset)); - DecodeField<Map::ElementsKindBits>(scratch1); - cmp(scratch1, Operand(DICTIONARY_ELEMENTS)); - b(eq, found); - ldr(current, FieldMemOperand(current, Map::kPrototypeOffset)); - CompareRoot(current, Heap::kNullValueRootIndex); - b(ne, &loop_again); - - bind(&end); -} - - #ifdef DEBUG bool AreAliased(Register reg1, Register reg2, |