// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <sstream>
+
#include "src/v8.h"
#if V8_TARGET_ARCH_IA32
int LPlatformChunk::GetNextSpillIndex(RegisterKind kind) {
- // Skip a slot if for a double-width slot.
- if (kind == DOUBLE_REGISTERS) {
- spill_slot_count_++;
- spill_slot_count_ |= 1;
- num_double_slots_++;
+ switch (kind) {
+ case GENERAL_REGISTERS: return spill_slot_count_++;
+ case DOUBLE_REGISTERS: {
+ // Skip a slot if for a double-width slot.
+ spill_slot_count_++;
+ spill_slot_count_ |= 1;
+ num_double_slots_++;
+ return spill_slot_count_++;
+ }
+ case FLOAT32x4_REGISTERS:
+ case FLOAT64x2_REGISTERS:
+ case INT32x4_REGISTERS: {
+ // Skip three slots if for a quad-width slot.
+ spill_slot_count_ += 3;
+ num_double_slots_ += 2; // for dynamic frame alignment
+ return spill_slot_count_++;
+ }
+ default:
+ UNREACHABLE();
+ return -1;
}
- return spill_slot_count_++;
}
LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
int index = GetNextSpillIndex(kind);
- if (kind == DOUBLE_REGISTERS) {
- return LDoubleStackSlot::Create(index, zone());
- } else {
- DCHECK(kind == GENERAL_REGISTERS);
- return LStackSlot::Create(index, zone());
+ switch (kind) {
+ case GENERAL_REGISTERS: return LStackSlot::Create(index, zone());
+ case DOUBLE_REGISTERS: return LDoubleStackSlot::Create(index, zone());
+ case FLOAT32x4_REGISTERS: return LFloat32x4StackSlot::Create(index, zone());
+ case FLOAT64x2_REGISTERS: return LFloat64x2StackSlot::Create(index, zone());
+ case INT32x4_REGISTERS: return LInt32x4StackSlot::Create(index, zone());
+ default:
+ UNREACHABLE();
+ return NULL;
}
}
void LStoreNamedField::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
- OStringStream os;
+ std::ostringstream os;
os << hydrogen()->access() << " <- ";
- stream->Add(os.c_str());
+ stream->Add(os.str().c_str());
value()->PrintTo(stream);
}
}
-void LChunkBuilder::Abort(BailoutReason reason) {
- info()->set_bailout_reason(reason);
- status_ = ABORTED;
-}
-
-
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
Register::ToAllocationIndex(reg));
HEnvironment* hydrogen_env = current_block_->last_environment();
int argument_index_accumulator = 0;
ZoneList<HValue*> objects_to_materialize(0, zone());
- instr->set_environment(CreateEnvironment(hydrogen_env,
- &argument_index_accumulator,
- &objects_to_materialize));
+ instr->set_environment(CreateEnvironment(
+ hydrogen_env, &argument_index_accumulator, &objects_to_materialize));
return instr;
}
// Shift operations can only deoptimize if we do a logical shift by 0 and
// the result cannot be truncated to int32.
if (op == Token::SHR && constant_value == 0) {
- if (FLAG_opt_safe_uint32_operations) {
- does_deopt = !instr->CheckFlag(HInstruction::kUint32);
- } else {
- does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
- }
+ does_deopt = !instr->CheckFlag(HInstruction::kUint32);
}
LInstruction* result =
bool easy_case = !r.IsTagged() || type.IsBoolean() || type.IsSmi() ||
type.IsJSArray() || type.IsHeapNumber() || type.IsString();
+
LOperand* temp = !easy_case && expected.NeedsMap() ? TempRegister() : NULL;
LInstruction* branch = new(zone()) LBranch(UseRegister(value), temp);
if (!easy_case &&
LInstruction* LChunkBuilder::DoCallWithDescriptor(
HCallWithDescriptor* instr) {
- const InterfaceDescriptor* descriptor = instr->descriptor();
+ CallInterfaceDescriptor descriptor = instr->descriptor();
LOperand* target = UseRegisterOrConstantAtStart(instr->target());
ZoneList<LOperand*> ops(instr->OperandCount(), zone());
ops.Add(target, zone());
for (int i = 1; i < instr->OperandCount(); i++) {
- LOperand* op = UseFixed(instr->OperandAt(i),
- descriptor->GetParameterRegister(i - 1));
+ LOperand* op =
+ UseFixed(instr->OperandAt(i), descriptor.GetParameterRegister(i - 1));
ops.Add(op, zone());
}
}
+LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
+ HTailCallThroughMegamorphicCache* instr) {
+ LOperand* context = UseFixed(instr->context(), esi);
+ LOperand* receiver_register =
+ UseFixed(instr->receiver(), LoadDescriptor::ReceiverRegister());
+ LOperand* name_register =
+ UseFixed(instr->name(), LoadDescriptor::NameRegister());
+ // Not marked as call. It can't deoptimize, and it never returns.
+ return new (zone()) LTailCallThroughMegamorphicCache(
+ context, receiver_register, name_register);
+}
+
+
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* context = UseFixed(instr->context(), esi);
LOperand* function = UseFixed(instr->function(), edi);
Representation exponent_type = instr->right()->representation();
DCHECK(instr->left()->representation().IsDouble());
LOperand* left = UseFixedDouble(instr->left(), xmm2);
- LOperand* right = exponent_type.IsDouble() ?
- UseFixedDouble(instr->right(), xmm1) :
- UseFixed(instr->right(), eax);
+ LOperand* right =
+ exponent_type.IsDouble()
+ ? UseFixedDouble(instr->right(), xmm1)
+ : UseFixed(instr->right(), MathPowTaggedDescriptor::exponent());
LPower* result = new(zone()) LPower(left, right);
return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
CAN_DEOPTIMIZE_EAGERLY);
LOperand* length = !index->IsConstantOperand()
? UseOrConstantAtStart(instr->length())
: UseAtStart(instr->length());
- LInstruction* result = new(zone()) LBoundsCheck(index, length);
+ LOperand* temp0 = TempRegister();
+ LOperand* temp1 = TempRegister();
+ LInstruction* result = new(zone()) LBoundsCheck(index, length, temp0, temp1);
if (!FLAG_debug_code || !instr->skip_check()) {
result = AssignEnvironment(result);
}
DefineAsRegister(new(zone()) LNumberUntagD(value, temp));
if (!val->representation().IsSmi()) result = AssignEnvironment(result);
return result;
+ } else if (to.IsSIMD128()) {
+ LOperand* value = UseRegister(instr->value());
+ LOperand* temp = TempRegister();
+ LTaggedToSIMD128* res = new(zone()) LTaggedToSIMD128(value, temp, to);
+ return AssignEnvironment(DefineAsRegister(res));
} else if (to.IsSmi()) {
LOperand* value = UseRegister(val);
if (val->type().IsSmi()) {
return DefineAsRegister(new(zone()) LInteger32ToDouble(Use(val)));
}
}
+ } else if (from.IsSIMD128()) {
+ DCHECK(to.IsTagged());
+ info()->MarkAsDeferredCalling();
+ LOperand* value = UseRegister(instr->value());
+ LOperand* temp = TempRegister();
+ LOperand* temp2 = TempRegister();
+
+ // Make sure that temp and result_temp are different registers.
+ LUnallocated* result_temp = TempRegister();
+ LSIMD128ToTagged* result = new(zone()) LSIMD128ToTagged(value, temp, temp2);
+ return AssignPointerMap(Define(result, result_temp));
}
UNREACHABLE();
return NULL;
return DefineAsRegister(new(zone()) LConstantI);
} else if (r.IsDouble()) {
double value = instr->DoubleValue();
- bool value_is_zero = BitCast<uint64_t, double>(value) == 0;
+ bool value_is_zero = bit_cast<uint64_t, double>(value) == 0;
LOperand* temp = value_is_zero ? NULL : TempRegister();
return DefineAsRegister(new(zone()) LConstantD(temp));
} else if (r.IsExternal()) {
LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
- LOperand* global_object = UseFixed(instr->global_object(),
- LoadIC::ReceiverRegister());
+ LOperand* global_object =
+ UseFixed(instr->global_object(), LoadDescriptor::ReceiverRegister());
LOperand* vector = NULL;
if (FLAG_vector_ics) {
- vector = FixedTemp(LoadIC::VectorRegister());
+ vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
}
LLoadGlobalGeneric* result =
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
- LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
+ LOperand* object =
+ UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
LOperand* vector = NULL;
if (FLAG_vector_ics) {
- vector = FixedTemp(LoadIC::VectorRegister());
+ vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
}
LLoadNamedGeneric* result = new(zone()) LLoadNamedGeneric(
context, object, vector);
(instr->representation().IsInteger32() &&
!(IsDoubleOrFloatElementsKind(instr->elements_kind()))) ||
(instr->representation().IsDouble() &&
- (IsDoubleOrFloatElementsKind(instr->elements_kind()))));
+ (IsDoubleOrFloatElementsKind(instr->elements_kind()))) ||
+ (CpuFeatures::SupportsSIMD128InCrankshaft()
+ ? instr->representation().IsFloat32x4()
+ : instr->representation().IsTagged() &&
+ (IsFloat32x4ElementsKind(instr->elements_kind()))) ||
+ (CpuFeatures::SupportsSIMD128InCrankshaft()
+ ? instr->representation().IsFloat64x2()
+ : instr->representation().IsTagged() &&
+ (IsFloat64x2ElementsKind(instr->elements_kind()))) ||
+ (CpuFeatures::SupportsSIMD128InCrankshaft()
+ ? instr->representation().IsInt32x4()
+ : instr->representation().IsTagged() &&
+ (IsInt32x4ElementsKind(instr->elements_kind()))));
LOperand* backing_store = UseRegister(instr->elements());
result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key));
}
LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
- LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
- LOperand* key = UseFixed(instr->key(), LoadIC::NameRegister());
+ LOperand* object =
+ UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
LOperand* vector = NULL;
if (FLAG_vector_ics) {
- vector = FixedTemp(LoadIC::VectorRegister());
+ vector = FixedTemp(VectorLoadICDescriptor::VectorRegister());
}
LLoadKeyedGeneric* result =
new(zone()) LLoadKeyedGeneric(context, object, key, vector);
LOperand* LChunkBuilder::GetStoreKeyedValueOperand(HStoreKeyed* instr) {
ElementsKind elements_kind = instr->elements_kind();
+ BuiltinFunctionId op = instr->op();
// Determine if we need a byte register in this case for the value.
bool val_is_fixed_register =
- elements_kind == EXTERNAL_INT8_ELEMENTS ||
+ (elements_kind == EXTERNAL_INT8_ELEMENTS ||
elements_kind == EXTERNAL_UINT8_ELEMENTS ||
elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
elements_kind == UINT8_ELEMENTS ||
elements_kind == INT8_ELEMENTS ||
- elements_kind == UINT8_CLAMPED_ELEMENTS;
+ elements_kind == UINT8_CLAMPED_ELEMENTS) &&
+ (op != kInt8ArraySetFloat32x4XYZW &&
+ op != kInt8ArraySetFloat32x4X &&
+ op != kInt8ArraySetFloat32x4XY &&
+ op != kInt8ArraySetFloat32x4XYZ &&
+ op != kInt8ArraySetInt32x4XYZW &&
+ op != kInt8ArraySetInt32x4X &&
+ op != kInt8ArraySetInt32x4XY &&
+ op != kInt8ArraySetInt32x4XYZ &&
+ op != kInt8ArraySetFloat64x2XY &&
+ op != kInt8ArraySetFloat64x2X);
if (val_is_fixed_register) {
return UseFixed(instr->value(), eax);
}
(instr->value()->representation().IsInteger32() &&
!IsDoubleOrFloatElementsKind(elements_kind)) ||
(instr->value()->representation().IsDouble() &&
- IsDoubleOrFloatElementsKind(elements_kind)));
+ IsDoubleOrFloatElementsKind(elements_kind)) ||
+ (CpuFeatures::SupportsSIMD128InCrankshaft()
+ ? instr->value()->representation().IsFloat32x4()
+ : instr->value()->representation().IsTagged() &&
+ IsFloat32x4ElementsKind(elements_kind)) ||
+ (CpuFeatures::SupportsSIMD128InCrankshaft()
+ ? instr->value()->representation().IsFloat64x2()
+ : instr->value()->representation().IsTagged() &&
+ IsFloat64x2ElementsKind(elements_kind)) ||
+ (CpuFeatures::SupportsSIMD128InCrankshaft()
+ ? instr->value()->representation().IsInt32x4()
+ : instr->value()->representation().IsTagged() &&
+ IsInt32x4ElementsKind(elements_kind)));
DCHECK((instr->is_fixed_typed_array() &&
instr->elements()->representation().IsTagged()) ||
(instr->is_external() &&
LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
- LOperand* object = UseFixed(instr->object(),
- KeyedStoreIC::ReceiverRegister());
- LOperand* key = UseFixed(instr->key(), KeyedStoreIC::NameRegister());
- LOperand* value = UseFixed(instr->value(), KeyedStoreIC::ValueRegister());
+ LOperand* object =
+ UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
+ LOperand* key = UseFixed(instr->key(), StoreDescriptor::NameRegister());
+ LOperand* value = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
DCHECK(instr->object()->representation().IsTagged());
DCHECK(instr->key()->representation().IsTagged());
val = UseTempRegister(instr->value());
} else if (can_be_constant) {
val = UseRegisterOrConstant(instr->value());
- } else if (instr->field_representation().IsSmi()) {
- val = UseTempRegister(instr->value());
} else if (instr->field_representation().IsDouble()) {
val = UseRegisterAtStart(instr->value());
} else {
LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
LOperand* context = UseFixed(instr->context(), esi);
- LOperand* object = UseFixed(instr->object(), StoreIC::ReceiverRegister());
- LOperand* value = UseFixed(instr->value(), StoreIC::ValueRegister());
+ LOperand* object =
+ UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
+ LOperand* value = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
LStoreNamedGeneric* result =
new(zone()) LStoreNamedGeneric(context, object, value);
return DefineAsSpilled(result, spill_index);
} else {
DCHECK(info()->IsStub());
- CodeStubInterfaceDescriptor* descriptor =
- info()->code_stub()->GetInterfaceDescriptor();
+ CallInterfaceDescriptor descriptor =
+ info()->code_stub()->GetCallInterfaceDescriptor();
int index = static_cast<int>(instr->index());
- Register reg = descriptor->GetEnvironmentParameterRegister(index);
+ Register reg = descriptor.GetEnvironmentParameterRegister(index);
return DefineFixed(result, reg);
}
}
} else {
spill_index = env_index - instr->environment()->first_local_index();
if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
- Abort(kNotEnoughSpillSlotsForOsr);
+ Retry(kNotEnoughSpillSlotsForOsr);
spill_index = 0;
}
if (spill_index == 0) {
if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
inner->Bind(instr->arguments_var(), instr->arguments_object());
}
+ inner->BindContext(instr->closure_context());
inner->set_entry(instr);
current_block_->UpdateEnvironment(inner);
chunk_->AddInlinedClosure(instr->closure());
}
+const char* LNullarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+#define SIMD_NULLARY_OPERATION_CASE_ITEM(module, function, name, p4) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_NULLARY_OPERATIONS(SIMD_NULLARY_OPERATION_CASE_ITEM)
+#undef SIMD_NULLARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoNullarySIMDOperation(
+ HNullarySIMDOperation* instr) {
+ LNullarySIMDOperation* result =
+ new(zone()) LNullarySIMDOperation(instr->op());
+ switch (instr->op()) {
+#define SIMD_NULLARY_OPERATION_CASE_ITEM(module, function, name, p4) \
+ case k##name:
+SIMD_NULLARY_OPERATIONS(SIMD_NULLARY_OPERATION_CASE_ITEM)
+#undef SIMD_NULLARY_OPERATION_CASE_ITEM
+ return DefineAsRegister(result);
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LUnarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+ case kSIMD128Change: return "SIMD128-change";
+#define SIMD_UNARY_OPERATION_CASE_ITEM(module, function, name, p4, p5) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_UNARY_OPERATIONS(SIMD_UNARY_OPERATION_CASE_ITEM)
+SIMD_UNARY_OPERATIONS_FOR_PROPERTY_ACCESS(SIMD_UNARY_OPERATION_CASE_ITEM)
+#undef SIMD_UNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoUnarySIMDOperation(HUnarySIMDOperation* instr) {
+ LOperand* input = UseRegisterAtStart(instr->value());
+ LUnarySIMDOperation* result =
+ new(zone()) LUnarySIMDOperation(input, instr->op());
+ switch (instr->op()) {
+ case kSIMD128Change:
+ return AssignEnvironment(DefineAsRegister(result));
+ case kFloat32x4Abs:
+ case kFloat32x4Neg:
+ case kFloat32x4Reciprocal:
+ case kFloat32x4ReciprocalSqrt:
+ case kFloat32x4Sqrt:
+ case kFloat64x2Abs:
+ case kFloat64x2Neg:
+ case kFloat64x2Sqrt:
+ case kInt32x4Neg:
+ case kInt32x4Not:
+ return DefineSameAsFirst(result);
+ case kFloat32x4Coercion:
+ case kFloat64x2Coercion:
+ case kInt32x4Coercion:
+ case kFloat32x4BitsToInt32x4:
+ case kFloat32x4ToInt32x4:
+ case kInt32x4BitsToFloat32x4:
+ case kInt32x4ToFloat32x4:
+ case kFloat32x4Splat:
+ case kInt32x4Splat:
+ case kFloat32x4GetSignMask:
+ case kFloat32x4GetX:
+ case kFloat32x4GetY:
+ case kFloat32x4GetZ:
+ case kFloat32x4GetW:
+ case kFloat64x2GetSignMask:
+ case kFloat64x2GetX:
+ case kFloat64x2GetY:
+ case kInt32x4GetSignMask:
+ case kInt32x4GetX:
+ case kInt32x4GetY:
+ case kInt32x4GetZ:
+ case kInt32x4GetW:
+ case kInt32x4GetFlagX:
+ case kInt32x4GetFlagY:
+ case kInt32x4GetFlagZ:
+ case kInt32x4GetFlagW:
+ return DefineAsRegister(result);
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LBinarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+#define SIMD_BINARY_OPERATION_CASE_ITEM(module, function, name, p4, p5, p6) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_BINARY_OPERATIONS(SIMD_BINARY_OPERATION_CASE_ITEM)
+#undef SIMD_BINARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoBinarySIMDOperation(
+ HBinarySIMDOperation* instr) {
+ switch (instr->op()) {
+ case kFloat32x4Add:
+ case kFloat32x4Div:
+ case kFloat32x4Max:
+ case kFloat32x4Min:
+ case kFloat32x4Mul:
+ case kFloat32x4Sub:
+ case kFloat32x4Scale:
+ case kFloat32x4WithX:
+ case kFloat32x4WithY:
+ case kFloat32x4WithZ:
+ case kFloat32x4WithW:
+ case kFloat64x2Add:
+ case kFloat64x2Div:
+ case kFloat64x2Max:
+ case kFloat64x2Min:
+ case kFloat64x2Mul:
+ case kFloat64x2Sub:
+ case kFloat64x2Scale:
+ case kFloat64x2WithX:
+ case kFloat64x2WithY:
+ case kInt32x4Add:
+ case kInt32x4And:
+ case kInt32x4Mul:
+ case kInt32x4Or:
+ case kInt32x4Sub:
+ case kInt32x4Xor:
+ case kInt32x4WithX:
+ case kInt32x4WithY:
+ case kInt32x4WithZ:
+ case kInt32x4WithW:
+ case kInt32x4WithFlagX:
+ case kInt32x4WithFlagY:
+ case kInt32x4WithFlagZ:
+ case kInt32x4WithFlagW:
+ case kInt32x4GreaterThan:
+ case kInt32x4Equal:
+ case kInt32x4LessThan: {
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseRegisterAtStart(instr->right());
+ LBinarySIMDOperation* result =
+ new(zone()) LBinarySIMDOperation(left, right, instr->op());
+ if (instr->op() == kInt32x4WithFlagX ||
+ instr->op() == kInt32x4WithFlagY ||
+ instr->op() == kInt32x4WithFlagZ ||
+ instr->op() == kInt32x4WithFlagW) {
+ return AssignEnvironment(DefineSameAsFirst(result));
+ } else {
+ return DefineSameAsFirst(result);
+ }
+ }
+ case kFloat64x2Constructor: {
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseRegisterAtStart(instr->right());
+ LBinarySIMDOperation* result =
+ new(zone()) LBinarySIMDOperation(left, right, instr->op());
+ return DefineAsRegister(result);
+ }
+ case kFloat32x4Shuffle:
+ case kInt32x4Shuffle:
+ case kInt32x4ShiftLeft:
+ case kInt32x4ShiftRight:
+ case kInt32x4ShiftRightArithmetic: {
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseOrConstant(instr->right());
+ LBinarySIMDOperation* result =
+ new(zone()) LBinarySIMDOperation(left, right, instr->op());
+ return AssignEnvironment(DefineSameAsFirst(result));
+ }
+ case kFloat32x4LessThan:
+ case kFloat32x4LessThanOrEqual:
+ case kFloat32x4Equal:
+ case kFloat32x4NotEqual:
+ case kFloat32x4GreaterThanOrEqual:
+ case kFloat32x4GreaterThan: {
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseRegisterAtStart(instr->right());
+ LBinarySIMDOperation* result =
+ new(zone()) LBinarySIMDOperation(left, right, instr->op());
+ return DefineAsRegister(result);
+ }
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LTernarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+#define SIMD_TERNARY_OPERATION_CASE_ITEM(module, function, name, p4, p5, p6, \
+ p7) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_TERNARY_OPERATIONS(SIMD_TERNARY_OPERATION_CASE_ITEM)
+#undef SIMD_TERNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoTernarySIMDOperation(
+ HTernarySIMDOperation* instr) {
+ LOperand* first = UseRegisterAtStart(instr->first());
+ LOperand* second = UseRegisterAtStart(instr->second());
+ LOperand* third = instr->op() == kFloat32x4ShuffleMix
+ ? UseOrConstant(instr->third())
+ : UseRegisterAtStart(instr->third());
+ LTernarySIMDOperation* result =
+ new(zone()) LTernarySIMDOperation(first, second, third, instr->op());
+ switch (instr->op()) {
+ case kInt32x4Select:
+ case kFloat32x4Select: {
+ return DefineAsRegister(result);
+ }
+ case kFloat32x4ShuffleMix: {
+ return AssignEnvironment(DefineSameAsFirst(result));
+ }
+ case kFloat32x4Clamp:
+ case kFloat64x2Clamp: {
+ return DefineSameAsFirst(result);
+ }
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+const char* LQuarternarySIMDOperation::Mnemonic() const {
+ switch (op()) {
+#define SIMD_QUARTERNARY_OPERATION_CASE_ITEM(module, function, name, p4, p5, \
+ p6, p7, p8) \
+ case k##name: \
+ return #module "-" #function;
+SIMD_QUARTERNARY_OPERATIONS(SIMD_QUARTERNARY_OPERATION_CASE_ITEM)
+#undef SIMD_QUARTERNARY_OPERATION_CASE_ITEM
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+
+LInstruction* LChunkBuilder::DoQuarternarySIMDOperation(
+ HQuarternarySIMDOperation* instr) {
+ LOperand* x = UseRegisterAtStart(instr->x());
+ LOperand* y = UseRegisterAtStart(instr->y());
+ LOperand* z = UseRegisterAtStart(instr->z());
+ LOperand* w = UseRegisterAtStart(instr->w());
+ LQuarternarySIMDOperation* result =
+ new(zone()) LQuarternarySIMDOperation(x, y, z, w, instr->op());
+ if (instr->op() == kInt32x4Bool) {
+ return AssignEnvironment(DefineAsRegister(result));
+ } else {
+ return DefineAsRegister(result);
+ }
+}
+
+
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_IA32