summaryrefslogtreecommitdiff
path: root/deps/v8/src/arm/macro-assembler-arm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/arm/macro-assembler-arm.cc')
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc430
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,