Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 90643003: Experimental implementation: Exposing SIMD instructions into JavaScript Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 X87Register LCodeGen::ToX87Register(int index) const { 534 X87Register LCodeGen::ToX87Register(int index) const {
535 return X87Register::FromAllocationIndex(index); 535 return X87Register::FromAllocationIndex(index);
536 } 536 }
537 537
538 538
539 XMMRegister LCodeGen::ToDoubleRegister(int index) const { 539 XMMRegister LCodeGen::ToDoubleRegister(int index) const {
540 return XMMRegister::FromAllocationIndex(index); 540 return XMMRegister::FromAllocationIndex(index);
541 } 541 }
542 542
543 543
544 XMMRegister LCodeGen::ToXMMRegister(int index) const {
545 return XMMRegister::FromAllocationIndex(index);
546 }
547
548
549 XMMRegister LCodeGen::ToFloat32x4Register(int index) const {
550 return Float32x4Register::FromAllocationIndex(index);
551 }
552
553
554 XMMRegister LCodeGen::ToInt32x4Register(int index) const {
555 return Int32x4Register::FromAllocationIndex(index);
556 }
557
558
544 void LCodeGen::X87LoadForUsage(X87Register reg) { 559 void LCodeGen::X87LoadForUsage(X87Register reg) {
545 ASSERT(x87_stack_.Contains(reg)); 560 ASSERT(x87_stack_.Contains(reg));
546 x87_stack_.Fxch(reg); 561 x87_stack_.Fxch(reg);
547 x87_stack_.pop(); 562 x87_stack_.pop();
548 } 563 }
549 564
550 565
551 void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) { 566 void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) {
552 ASSERT(x87_stack_.Contains(reg1)); 567 ASSERT(x87_stack_.Contains(reg1));
553 ASSERT(x87_stack_.Contains(reg2)); 568 ASSERT(x87_stack_.Contains(reg2));
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 return ToX87Register(op->index()); 771 return ToX87Register(op->index());
757 } 772 }
758 773
759 774
760 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { 775 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
761 ASSERT(op->IsDoubleRegister()); 776 ASSERT(op->IsDoubleRegister());
762 return ToDoubleRegister(op->index()); 777 return ToDoubleRegister(op->index());
763 } 778 }
764 779
765 780
781 XMMRegister LCodeGen::ToFloat32x4Register(LOperand* op) const {
782 ASSERT(op->IsFloat32x4Register());
783 return ToFloat32x4Register(op->index());
784 }
785
786
787 XMMRegister LCodeGen::ToInt32x4Register(LOperand* op) const {
788 ASSERT(op->IsInt32x4Register());
789 return ToInt32x4Register(op->index());
790 }
791
792
793 XMMRegister LCodeGen::ToXMMRegister(LOperand* op) const {
794 ASSERT(op->IsFloat32x4Register() || op->IsInt32x4Register());
795 return ToXMMRegister(op->index());
796 }
797
798
766 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { 799 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
767 return ToRepresentation(op, Representation::Integer32()); 800 return ToRepresentation(op, Representation::Integer32());
768 } 801 }
769 802
770 803
771 int32_t LCodeGen::ToRepresentation(LConstantOperand* op, 804 int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
772 const Representation& r) const { 805 const Representation& r) const {
773 HConstant* constant = chunk_->LookupConstant(op); 806 HConstant* constant = chunk_->LookupConstant(op);
774 int32_t value = constant->Integer32Value(); 807 int32_t value = constant->Integer32Value();
775 if (r.IsInteger32()) return value; 808 if (r.IsInteger32()) return value;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 844
812 static int ArgumentsOffsetWithoutFrame(int index) { 845 static int ArgumentsOffsetWithoutFrame(int index) {
813 ASSERT(index < 0); 846 ASSERT(index < 0);
814 return -(index + 1) * kPointerSize + kPCOnStackSize; 847 return -(index + 1) * kPointerSize + kPCOnStackSize;
815 } 848 }
816 849
817 850
818 Operand LCodeGen::ToOperand(LOperand* op) const { 851 Operand LCodeGen::ToOperand(LOperand* op) const {
819 if (op->IsRegister()) return Operand(ToRegister(op)); 852 if (op->IsRegister()) return Operand(ToRegister(op));
820 if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op)); 853 if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op));
821 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 854 if (op->IsFloat32x4Register()) return Operand(ToFloat32x4Register(op));
855 if (op->IsInt32x4Register()) return Operand(ToInt32x4Register(op));
856 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot() ||
857 op->IsFloat32x4StackSlot() || op->IsInt32x4StackSlot());
822 if (NeedsEagerFrame()) { 858 if (NeedsEagerFrame()) {
823 return Operand(ebp, StackSlotOffset(op->index())); 859 return Operand(ebp, StackSlotOffset(op->index()));
824 } else { 860 } else {
825 // Retrieve parameter without eager stack-frame relative to the 861 // Retrieve parameter without eager stack-frame relative to the
826 // stack-pointer. 862 // stack-pointer.
827 return Operand(esp, ArgumentsOffsetWithoutFrame(op->index())); 863 return Operand(esp, ArgumentsOffsetWithoutFrame(op->index()));
828 } 864 }
829 } 865 }
830 866
831 867
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 if (op->IsStackSlot()) { 974 if (op->IsStackSlot()) {
939 if (is_tagged) { 975 if (is_tagged) {
940 translation->StoreStackSlot(op->index()); 976 translation->StoreStackSlot(op->index());
941 } else if (is_uint32) { 977 } else if (is_uint32) {
942 translation->StoreUint32StackSlot(op->index()); 978 translation->StoreUint32StackSlot(op->index());
943 } else { 979 } else {
944 translation->StoreInt32StackSlot(op->index()); 980 translation->StoreInt32StackSlot(op->index());
945 } 981 }
946 } else if (op->IsDoubleStackSlot()) { 982 } else if (op->IsDoubleStackSlot()) {
947 translation->StoreDoubleStackSlot(op->index()); 983 translation->StoreDoubleStackSlot(op->index());
984 } else if (op->IsFloat32x4StackSlot()) {
985 translation->StoreFloat32x4StackSlot(op->index());
986 } else if (op->IsInt32x4StackSlot()) {
987 translation->StoreInt32x4StackSlot(op->index());
948 } else if (op->IsArgument()) { 988 } else if (op->IsArgument()) {
949 ASSERT(is_tagged); 989 ASSERT(is_tagged);
950 int src_index = GetStackSlotCount() + op->index(); 990 int src_index = GetStackSlotCount() + op->index();
951 translation->StoreStackSlot(src_index); 991 translation->StoreStackSlot(src_index);
952 } else if (op->IsRegister()) { 992 } else if (op->IsRegister()) {
953 Register reg = ToRegister(op); 993 Register reg = ToRegister(op);
954 if (is_tagged) { 994 if (is_tagged) {
955 translation->StoreRegister(reg); 995 translation->StoreRegister(reg);
956 } else if (is_uint32) { 996 } else if (is_uint32) {
957 translation->StoreUint32Register(reg); 997 translation->StoreUint32Register(reg);
958 } else { 998 } else {
959 translation->StoreInt32Register(reg); 999 translation->StoreInt32Register(reg);
960 } 1000 }
961 } else if (op->IsDoubleRegister()) { 1001 } else if (op->IsDoubleRegister()) {
962 XMMRegister reg = ToDoubleRegister(op); 1002 XMMRegister reg = ToDoubleRegister(op);
963 translation->StoreDoubleRegister(reg); 1003 translation->StoreDoubleRegister(reg);
1004 } else if (op->IsFloat32x4Register()) {
1005 XMMRegister reg = ToFloat32x4Register(op);
1006 translation->StoreFloat32x4Register(reg);
1007 } else if (op->IsInt32x4Register()) {
1008 XMMRegister reg = ToInt32x4Register(op);
1009 translation->StoreInt32x4Register(reg);
964 } else if (op->IsConstantOperand()) { 1010 } else if (op->IsConstantOperand()) {
965 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); 1011 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
966 int src_index = DefineDeoptimizationLiteral(constant->handle(isolate())); 1012 int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
967 translation->StoreLiteral(src_index); 1013 translation->StoreLiteral(src_index);
968 } else { 1014 } else {
969 UNREACHABLE(); 1015 UNREACHABLE();
970 } 1016 }
971 } 1017 }
972 1018
973 1019
(...skipping 2458 matching lines...) Expand 10 before | Expand all | Expand 10 after
3432 Operand index = ToOperand(instr->index()); 3478 Operand index = ToOperand(instr->index());
3433 // There are two words between the frame pointer and the last argument. 3479 // There are two words between the frame pointer and the last argument.
3434 // Subtracting from length accounts for one of them add one more. 3480 // Subtracting from length accounts for one of them add one more.
3435 __ sub(length, index); 3481 __ sub(length, index);
3436 __ mov(result, Operand(arguments, length, times_4, kPointerSize)); 3482 __ mov(result, Operand(arguments, length, times_4, kPointerSize));
3437 } 3483 }
3438 } 3484 }
3439 3485
3440 3486
3441 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { 3487 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
3488 class DeferredFloat32x4ToTagged V8_FINAL : public LDeferredCode {
3489 public:
3490 DeferredFloat32x4ToTagged(LCodeGen* codegen,
3491 LInstruction* instr,
3492 const X87Stack& x87_stack)
3493 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
3494 virtual void Generate() V8_OVERRIDE {
3495 codegen()->DoDeferredFloat32x4ToTagged(instr_);
3496 }
3497 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
3498 private:
3499 LInstruction* instr_;
3500 };
3501
3502 class DeferredInt32x4ToTagged V8_FINAL : public LDeferredCode {
3503 public:
3504 DeferredInt32x4ToTagged(LCodeGen* codegen,
3505 LInstruction* instr,
3506 const X87Stack& x87_stack)
3507 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
3508 virtual void Generate() V8_OVERRIDE {
3509 codegen()->DoDeferredInt32x4ToTagged(instr_);
3510 }
3511 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
3512 private:
3513 LInstruction* instr_;
3514 };
3515
3442 ElementsKind elements_kind = instr->elements_kind(); 3516 ElementsKind elements_kind = instr->elements_kind();
3443 LOperand* key = instr->key(); 3517 LOperand* key = instr->key();
3444 if (!key->IsConstantOperand() && 3518 if (!key->IsConstantOperand()) {
3445 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), 3519 if (ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
3446 elements_kind)) { 3520 elements_kind)) {
3447 __ SmiUntag(ToRegister(key)); 3521 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
3522 elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
3523 // Double the index as Float32x4 and Int32x4 need scale 16.
3524 __ shl(ToRegister(key), 1);
3525 } else {
3526 __ SmiUntag(ToRegister(key));
3527 }
3528 }
3448 } 3529 }
3530
3449 Operand operand(BuildFastArrayOperand( 3531 Operand operand(BuildFastArrayOperand(
3450 instr->elements(), 3532 instr->elements(),
3451 key, 3533 key,
3452 instr->hydrogen()->key()->representation(), 3534 instr->hydrogen()->key()->representation(),
3453 elements_kind, 3535 elements_kind,
3454 0, 3536 0,
3455 instr->additional_index())); 3537 instr->additional_index()));
3456 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 3538 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
3457 if (CpuFeatures::IsSupported(SSE2)) { 3539 if (CpuFeatures::IsSupported(SSE2)) {
3458 CpuFeatureScope scope(masm(), SSE2); 3540 CpuFeatureScope scope(masm(), SSE2);
3459 XMMRegister result(ToDoubleRegister(instr->result())); 3541 XMMRegister result(ToDoubleRegister(instr->result()));
3460 __ movss(result, operand); 3542 __ movss(result, operand);
3461 __ cvtss2sd(result, result); 3543 __ cvtss2sd(result, result);
3462 } else { 3544 } else {
3463 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand); 3545 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
3464 } 3546 }
3465 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3547 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3466 if (CpuFeatures::IsSupported(SSE2)) { 3548 if (CpuFeatures::IsSupported(SSE2)) {
3467 CpuFeatureScope scope(masm(), SSE2); 3549 CpuFeatureScope scope(masm(), SSE2);
3468 __ movsd(ToDoubleRegister(instr->result()), operand); 3550 __ movsd(ToDoubleRegister(instr->result()), operand);
3469 } else { 3551 } else {
3470 X87Mov(ToX87Register(instr->result()), operand); 3552 X87Mov(ToX87Register(instr->result()), operand);
3471 } 3553 }
3554 } else if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) {
3555 if (CpuFeatures::IsSupported(SSE2)) {
3556 CpuFeatureScope scope(masm(), SSE2);
3557 __ movups(ToFloat32x4Register(instr->result()), operand);
3558 } else {
3559 Register reg = ToRegister(instr->result());
3560 Register tmp = ToRegister(instr->temp());
3561 DeferredFloat32x4ToTagged* deferred =
3562 new(zone()) DeferredFloat32x4ToTagged(this, instr, x87_stack_);
3563 if (FLAG_inline_new) {
3564 __ AllocateFloat32x4(reg, tmp, deferred->entry());
3565 } else {
3566 __ jmp(deferred->entry());
3567 }
3568 __ bind(deferred->exit());
3569 for (int offset = 0; offset < kFloat32x4Size; offset += kFloatSize) {
3570 __ mov(tmp, Operand(operand, offset));
3571 __ mov(Operand(FieldOperand(reg, Float32x4::kValueOffset), offset),
3572 tmp);
3573 }
3574 }
3575 } else if (elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
3576 if (CpuFeatures::IsSupported(SSE2)) {
3577 CpuFeatureScope scope(masm(), SSE2);
3578 __ movups(ToInt32x4Register(instr->result()), operand);
3579 } else {
3580 Register reg = ToRegister(instr->result());
3581 Register tmp = ToRegister(instr->temp());
3582 DeferredInt32x4ToTagged* deferred =
3583 new(zone()) DeferredInt32x4ToTagged(this, instr, x87_stack_);
3584 if (FLAG_inline_new) {
3585 __ AllocateInt32x4(reg, tmp, deferred->entry());
3586 } else {
3587 __ jmp(deferred->entry());
3588 }
3589 __ bind(deferred->exit());
3590 for (int offset = 0; offset < kInt32x4Size; offset += kInt32Size) {
3591 __ mov(tmp, Operand(operand, offset));
3592 __ mov(Operand(FieldOperand(reg, Int32x4::kValueOffset), offset), tmp);
3593 }
3594 }
3472 } else { 3595 } else {
3473 Register result(ToRegister(instr->result())); 3596 Register result(ToRegister(instr->result()));
3474 switch (elements_kind) { 3597 switch (elements_kind) {
3475 case EXTERNAL_BYTE_ELEMENTS: 3598 case EXTERNAL_BYTE_ELEMENTS:
3476 __ movsx_b(result, operand); 3599 __ movsx_b(result, operand);
3477 break; 3600 break;
3478 case EXTERNAL_PIXEL_ELEMENTS: 3601 case EXTERNAL_PIXEL_ELEMENTS:
3479 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3602 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3480 __ movzx_b(result, operand); 3603 __ movzx_b(result, operand);
3481 break; 3604 break;
3482 case EXTERNAL_SHORT_ELEMENTS: 3605 case EXTERNAL_SHORT_ELEMENTS:
3483 __ movsx_w(result, operand); 3606 __ movsx_w(result, operand);
3484 break; 3607 break;
3485 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3608 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3486 __ movzx_w(result, operand); 3609 __ movzx_w(result, operand);
3487 break; 3610 break;
3488 case EXTERNAL_INT_ELEMENTS: 3611 case EXTERNAL_INT_ELEMENTS:
3489 __ mov(result, operand); 3612 __ mov(result, operand);
3490 break; 3613 break;
3491 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3614 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3492 __ mov(result, operand); 3615 __ mov(result, operand);
3493 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3616 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3494 __ test(result, Operand(result)); 3617 __ test(result, Operand(result));
3495 DeoptimizeIf(negative, instr->environment()); 3618 DeoptimizeIf(negative, instr->environment());
3496 } 3619 }
3497 break; 3620 break;
3498 case EXTERNAL_FLOAT_ELEMENTS: 3621 case EXTERNAL_FLOAT_ELEMENTS:
3499 case EXTERNAL_DOUBLE_ELEMENTS: 3622 case EXTERNAL_DOUBLE_ELEMENTS:
3623 case EXTERNAL_FLOAT32x4_ELEMENTS:
3624 case EXTERNAL_INT32x4_ELEMENTS:
3500 case FAST_SMI_ELEMENTS: 3625 case FAST_SMI_ELEMENTS:
3501 case FAST_ELEMENTS: 3626 case FAST_ELEMENTS:
3502 case FAST_DOUBLE_ELEMENTS: 3627 case FAST_DOUBLE_ELEMENTS:
3503 case FAST_HOLEY_SMI_ELEMENTS: 3628 case FAST_HOLEY_SMI_ELEMENTS:
3504 case FAST_HOLEY_ELEMENTS: 3629 case FAST_HOLEY_ELEMENTS:
3505 case FAST_HOLEY_DOUBLE_ELEMENTS: 3630 case FAST_HOLEY_DOUBLE_ELEMENTS:
3506 case DICTIONARY_ELEMENTS: 3631 case DICTIONARY_ELEMENTS:
3507 case NON_STRICT_ARGUMENTS_ELEMENTS: 3632 case NON_STRICT_ARGUMENTS_ELEMENTS:
3508 UNREACHABLE(); 3633 UNREACHABLE();
3509 break; 3634 break;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
3582 Operand LCodeGen::BuildFastArrayOperand( 3707 Operand LCodeGen::BuildFastArrayOperand(
3583 LOperand* elements_pointer, 3708 LOperand* elements_pointer,
3584 LOperand* key, 3709 LOperand* key,
3585 Representation key_representation, 3710 Representation key_representation,
3586 ElementsKind elements_kind, 3711 ElementsKind elements_kind,
3587 uint32_t offset, 3712 uint32_t offset,
3588 uint32_t additional_index) { 3713 uint32_t additional_index) {
3589 Register elements_pointer_reg = ToRegister(elements_pointer); 3714 Register elements_pointer_reg = ToRegister(elements_pointer);
3590 int element_shift_size = ElementsKindToShiftSize(elements_kind); 3715 int element_shift_size = ElementsKindToShiftSize(elements_kind);
3591 int shift_size = element_shift_size; 3716 int shift_size = element_shift_size;
3717 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
3718 elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
3719 // Double the index and use scale 8. Float32x4 needs scale 16.
3720 additional_index *= 2;
3721 }
3592 if (key->IsConstantOperand()) { 3722 if (key->IsConstantOperand()) {
3593 int constant_value = ToInteger32(LConstantOperand::cast(key)); 3723 int constant_value = ToInteger32(LConstantOperand::cast(key));
3594 if (constant_value & 0xF0000000) { 3724 if (constant_value & 0xF0000000) {
3595 Abort(kArrayIndexConstantValueTooBig); 3725 Abort(kArrayIndexConstantValueTooBig);
3596 } 3726 }
3727 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
3728 elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
3729 // Double the index and use scale 8. Float32x4 needs scale 16.
3730 constant_value *= 2;
3731 }
3597 return Operand(elements_pointer_reg, 3732 return Operand(elements_pointer_reg,
3598 ((constant_value + additional_index) << shift_size) 3733 ((constant_value + additional_index) << shift_size)
3599 + offset); 3734 + offset);
3600 } else { 3735 } else {
3601 // Take the tag bit into account while computing the shift size. 3736 // Take the tag bit into account while computing the shift size.
3602 if (key_representation.IsSmi() && (shift_size >= 1)) { 3737 if (key_representation.IsSmi() && (shift_size >= 1)) {
3603 shift_size -= kSmiTagSize; 3738 shift_size -= kSmiTagSize;
3604 } 3739 }
3605 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); 3740 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
3741 // For Float32x4, make sure the index register is doubled before
3742 // calling this function and restored after its usage.
3606 return Operand(elements_pointer_reg, 3743 return Operand(elements_pointer_reg,
3607 ToRegister(key), 3744 ToRegister(key),
3608 scale_factor, 3745 scale_factor,
3609 offset + (additional_index << element_shift_size)); 3746 offset + (additional_index << element_shift_size));
3610 } 3747 }
3611 } 3748 }
3612 3749
3613 3750
3614 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { 3751 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
3615 ASSERT(ToRegister(instr->context()).is(esi)); 3752 ASSERT(ToRegister(instr->context()).is(esi));
(...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after
4596 Condition condition = 4733 Condition condition =
4597 instr->hydrogen()->allow_equality() ? above : above_equal; 4734 instr->hydrogen()->allow_equality() ? above : above_equal;
4598 ApplyCheckIf(condition, instr); 4735 ApplyCheckIf(condition, instr);
4599 } 4736 }
4600 } 4737 }
4601 4738
4602 4739
4603 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4740 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4604 ElementsKind elements_kind = instr->elements_kind(); 4741 ElementsKind elements_kind = instr->elements_kind();
4605 LOperand* key = instr->key(); 4742 LOperand* key = instr->key();
4606 if (!key->IsConstantOperand() && 4743 if (!key->IsConstantOperand()) {
4607 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), 4744 if (ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
4608 elements_kind)) { 4745 elements_kind)) {
4609 __ SmiUntag(ToRegister(key)); 4746 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS ||
4747 elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
4748 // Double the index as Float32x4 and Int32x4 need scale 16.
4749 __ shl(ToRegister(key), 1);
4750 } else {
4751 __ SmiUntag(ToRegister(key));
4752 }
4753 }
4610 } 4754 }
4755
4611 Operand operand(BuildFastArrayOperand( 4756 Operand operand(BuildFastArrayOperand(
4612 instr->elements(), 4757 instr->elements(),
4613 key, 4758 key,
4614 instr->hydrogen()->key()->representation(), 4759 instr->hydrogen()->key()->representation(),
4615 elements_kind, 4760 elements_kind,
4616 0, 4761 0,
4617 instr->additional_index())); 4762 instr->additional_index()));
4618 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 4763 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
4619 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { 4764 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
4620 CpuFeatureScope scope(masm(), SSE2); 4765 CpuFeatureScope scope(masm(), SSE2);
4621 XMMRegister xmm_scratch = double_scratch0(); 4766 XMMRegister xmm_scratch = double_scratch0();
4622 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); 4767 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value()));
4623 __ movss(operand, xmm_scratch); 4768 __ movss(operand, xmm_scratch);
4624 } else { 4769 } else {
4625 __ fld(0); 4770 __ fld(0);
4626 __ fstp_s(operand); 4771 __ fstp_s(operand);
4627 } 4772 }
4628 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 4773 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
4629 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { 4774 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
4630 CpuFeatureScope scope(masm(), SSE2); 4775 CpuFeatureScope scope(masm(), SSE2);
4631 __ movsd(operand, ToDoubleRegister(instr->value())); 4776 __ movsd(operand, ToDoubleRegister(instr->value()));
4632 } else { 4777 } else {
4633 X87Mov(operand, ToX87Register(instr->value())); 4778 X87Mov(operand, ToX87Register(instr->value()));
4634 } 4779 }
4780 } else if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) {
4781 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
4782 CpuFeatureScope scope(masm(), SSE2);
4783 __ movups(operand, ToFloat32x4Register(instr->value()));
4784 } else {
4785 ASSERT(instr->value()->IsRegister());
4786 Register temp = ToRegister(instr->temp());
4787 Register input_reg = ToRegister(instr->value());
4788 __ test(input_reg, Immediate(kSmiTagMask));
4789 DeoptimizeIf(zero, instr->environment());
4790 __ CmpObjectType(input_reg, FLOAT32x4_TYPE, temp);
4791 DeoptimizeIf(not_equal, instr->environment());
4792 for (int offset = 0; offset < kFloat32x4Size; offset += kFloatSize) {
4793 __ mov(temp,
4794 Operand(FieldOperand(input_reg, Float32x4::kValueOffset), offset));
4795 __ mov(Operand(operand, offset), temp);
4796 }
4797 }
4798 } else if (elements_kind == EXTERNAL_INT32x4_ELEMENTS) {
4799 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
4800 CpuFeatureScope scope(masm(), SSE2);
4801 __ movups(operand, ToInt32x4Register(instr->value()));
4802 } else {
4803 ASSERT(instr->value()->IsRegister());
4804 Register temp = ToRegister(instr->temp());
4805 Register input_reg = ToRegister(instr->value());
4806 __ test(input_reg, Immediate(kSmiTagMask));
4807 DeoptimizeIf(zero, instr->environment());
4808 __ CmpObjectType(input_reg, INT32x4_TYPE, temp);
4809 DeoptimizeIf(not_equal, instr->environment());
4810 for (int offset = 0; offset < kInt32x4Size; offset += kInt32Size) {
4811 __ mov(temp,
4812 Operand(FieldOperand(input_reg, Int32x4::kValueOffset), offset));
4813 __ mov(Operand(operand, offset), temp);
4814 }
4815 }
4635 } else { 4816 } else {
4636 Register value = ToRegister(instr->value()); 4817 Register value = ToRegister(instr->value());
4637 switch (elements_kind) { 4818 switch (elements_kind) {
4638 case EXTERNAL_PIXEL_ELEMENTS: 4819 case EXTERNAL_PIXEL_ELEMENTS:
4639 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4820 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4640 case EXTERNAL_BYTE_ELEMENTS: 4821 case EXTERNAL_BYTE_ELEMENTS:
4641 __ mov_b(operand, value); 4822 __ mov_b(operand, value);
4642 break; 4823 break;
4643 case EXTERNAL_SHORT_ELEMENTS: 4824 case EXTERNAL_SHORT_ELEMENTS:
4644 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4825 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4645 __ mov_w(operand, value); 4826 __ mov_w(operand, value);
4646 break; 4827 break;
4647 case EXTERNAL_INT_ELEMENTS: 4828 case EXTERNAL_INT_ELEMENTS:
4648 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4829 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
4649 __ mov(operand, value); 4830 __ mov(operand, value);
4650 break; 4831 break;
4651 case EXTERNAL_FLOAT_ELEMENTS: 4832 case EXTERNAL_FLOAT_ELEMENTS:
4833 case EXTERNAL_FLOAT32x4_ELEMENTS:
4834 case EXTERNAL_INT32x4_ELEMENTS:
4652 case EXTERNAL_DOUBLE_ELEMENTS: 4835 case EXTERNAL_DOUBLE_ELEMENTS:
4653 case FAST_SMI_ELEMENTS: 4836 case FAST_SMI_ELEMENTS:
4654 case FAST_ELEMENTS: 4837 case FAST_ELEMENTS:
4655 case FAST_DOUBLE_ELEMENTS: 4838 case FAST_DOUBLE_ELEMENTS:
4656 case FAST_HOLEY_SMI_ELEMENTS: 4839 case FAST_HOLEY_SMI_ELEMENTS:
4657 case FAST_HOLEY_ELEMENTS: 4840 case FAST_HOLEY_ELEMENTS:
4658 case FAST_HOLEY_DOUBLE_ELEMENTS: 4841 case FAST_HOLEY_DOUBLE_ELEMENTS:
4659 case DICTIONARY_ELEMENTS: 4842 case DICTIONARY_ELEMENTS:
4660 case NON_STRICT_ARGUMENTS_ELEMENTS: 4843 case NON_STRICT_ARGUMENTS_ELEMENTS:
4661 UNREACHABLE(); 4844 UNREACHABLE();
(...skipping 1457 matching lines...) Expand 10 before | Expand all | Expand 10 after
6119 : Label::kFar; 6302 : Label::kFar;
6120 Label::Distance false_distance = right_block == next_block ? Label::kNear 6303 Label::Distance false_distance = right_block == next_block ? Label::kNear
6121 : Label::kFar; 6304 : Label::kFar;
6122 Condition final_branch_condition = no_condition; 6305 Condition final_branch_condition = no_condition;
6123 if (type_name->Equals(heap()->number_string())) { 6306 if (type_name->Equals(heap()->number_string())) {
6124 __ JumpIfSmi(input, true_label, true_distance); 6307 __ JumpIfSmi(input, true_label, true_distance);
6125 __ cmp(FieldOperand(input, HeapObject::kMapOffset), 6308 __ cmp(FieldOperand(input, HeapObject::kMapOffset),
6126 factory()->heap_number_map()); 6309 factory()->heap_number_map());
6127 final_branch_condition = equal; 6310 final_branch_condition = equal;
6128 6311
6312 } else if (type_name->Equals(heap()->float32x4_string())) {
6313 __ JumpIfSmi(input, false_label, false_distance);
6314 __ CmpObjectType(input, FLOAT32x4_TYPE, input);
6315 final_branch_condition = equal;
6316
6317 } else if (type_name->Equals(heap()->int32x4_string())) {
6318 __ JumpIfSmi(input, false_label, false_distance);
6319 __ CmpObjectType(input, INT32x4_TYPE, input);
6320 final_branch_condition = equal;
6321
6129 } else if (type_name->Equals(heap()->string_string())) { 6322 } else if (type_name->Equals(heap()->string_string())) {
6130 __ JumpIfSmi(input, false_label, false_distance); 6323 __ JumpIfSmi(input, false_label, false_distance);
6131 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); 6324 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
6132 __ j(above_equal, false_label, false_distance); 6325 __ j(above_equal, false_label, false_distance);
6133 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 6326 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
6134 1 << Map::kIsUndetectable); 6327 1 << Map::kIsUndetectable);
6135 final_branch_condition = zero; 6328 final_branch_condition = zero;
6136 6329
6137 } else if (type_name->Equals(heap()->symbol_string())) { 6330 } else if (type_name->Equals(heap()->symbol_string())) {
6138 __ JumpIfSmi(input, false_label, false_distance); 6331 __ JumpIfSmi(input, false_label, false_distance);
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
6426 __ neg(index); 6619 __ neg(index);
6427 // Index is now equal to out of object property index plus 1. 6620 // Index is now equal to out of object property index plus 1.
6428 __ mov(object, FieldOperand(object, 6621 __ mov(object, FieldOperand(object,
6429 index, 6622 index,
6430 times_half_pointer_size, 6623 times_half_pointer_size,
6431 FixedArray::kHeaderSize - kPointerSize)); 6624 FixedArray::kHeaderSize - kPointerSize));
6432 __ bind(&done); 6625 __ bind(&done);
6433 } 6626 }
6434 6627
6435 6628
6629 void LCodeGen::DoFloat32x4ToTagged(LFloat32x4ToTagged* instr) {
6630 class DeferredFloat32x4ToTagged V8_FINAL : public LDeferredCode {
6631 public:
6632 DeferredFloat32x4ToTagged(LCodeGen* codegen,
6633 LInstruction* instr,
6634 const X87Stack& x87_stack)
6635 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
6636 virtual void Generate() V8_OVERRIDE {
6637 codegen()->DoDeferredFloat32x4ToTagged(instr_);
6638 }
6639 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
6640 private:
6641 LInstruction* instr_;
6642 };
6643
6644 CpuFeatureScope scope(masm(), SSE2);
6645 XMMRegister input_reg = ToFloat32x4Register(instr->value());
6646 Register reg = ToRegister(instr->result());
6647 Register tmp = ToRegister(instr->temp());
6648
6649 DeferredFloat32x4ToTagged* deferred =
6650 new(zone()) DeferredFloat32x4ToTagged(this, instr, x87_stack_);
6651 if (FLAG_inline_new) {
6652 __ AllocateFloat32x4(reg, tmp, deferred->entry());
6653 } else {
6654 __ jmp(deferred->entry());
6655 }
6656 __ bind(deferred->exit());
6657 __ movups(FieldOperand(reg, Float32x4::kValueOffset), input_reg);
6658 }
6659
6660
6661 void LCodeGen::DoDeferredFloat32x4ToTagged(LInstruction* instr) {
6662 // TODO(3095996): Get rid of this. For now, we need to make the
6663 // result register contain a valid pointer because it is already
6664 // contained in the register pointer map.
6665 Register reg = ToRegister(instr->result());
6666 __ Set(reg, Immediate(0));
6667
6668 PushSafepointRegistersScope scope(this);
6669 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
6670 __ CallRuntimeSaveDoubles(Runtime::kAllocateFloat32x4);
6671 RecordSafepointWithRegisters(
6672 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
6673 __ StoreToSafepointRegisterSlot(reg, eax);
6674 }
6675
6676
6677 void LCodeGen::DoTaggedToFloat32x4(LTaggedToFloat32x4* instr) {
6678 CpuFeatureScope scope(masm(), SSE2);
6679 Register input_reg = ToRegister(instr->value());
6680 Register scratch = ToRegister(instr->temp());
6681 XMMRegister result_reg = ToFloat32x4Register(instr->result());
6682
6683 __ test(input_reg, Immediate(kSmiTagMask));
6684 DeoptimizeIf(zero, instr->environment());
6685 __ CmpObjectType(input_reg, FLOAT32x4_TYPE, scratch);
6686 DeoptimizeIf(not_equal, instr->environment());
6687 __ movups(result_reg, FieldOperand(input_reg, Float32x4::kValueOffset));
6688 }
6689
6690
6691 void LCodeGen::DoInt32x4ToTagged(LInt32x4ToTagged* instr) {
6692 class DeferredInt32x4ToTagged V8_FINAL : public LDeferredCode {
6693 public:
6694 DeferredInt32x4ToTagged(LCodeGen* codegen,
6695 LInstruction* instr,
6696 const X87Stack& x87_stack)
6697 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
6698 virtual void Generate() V8_OVERRIDE {
6699 codegen()->DoDeferredInt32x4ToTagged(instr_);
6700 }
6701 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
6702 private:
6703 LInstruction* instr_;
6704 };
6705
6706 CpuFeatureScope scope(masm(), SSE2);
6707 XMMRegister input_reg = ToInt32x4Register(instr->value());
6708 Register reg = ToRegister(instr->result());
6709 Register tmp = ToRegister(instr->temp());
6710
6711 DeferredInt32x4ToTagged* deferred =
6712 new(zone()) DeferredInt32x4ToTagged(this, instr, x87_stack_);
6713 if (FLAG_inline_new) {
6714 __ AllocateInt32x4(reg, tmp, deferred->entry());
6715 } else {
6716 __ jmp(deferred->entry());
6717 }
6718 __ bind(deferred->exit());
6719 __ movups(FieldOperand(reg, Int32x4::kValueOffset), input_reg);
6720 }
6721
6722
6723 void LCodeGen::DoDeferredInt32x4ToTagged(LInstruction* instr) {
6724 // TODO(3095996): Get rid of this. For now, we need to make the
6725 // result register contain a valid pointer because it is already
6726 // contained in the register pointer map.
6727 Register reg = ToRegister(instr->result());
6728 __ Set(reg, Immediate(0));
6729
6730 PushSafepointRegistersScope scope(this);
6731 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
6732 __ CallRuntimeSaveDoubles(Runtime::kAllocateInt32x4);
6733 // Ensure that value in rax survives popping registers.
6734 RecordSafepointWithRegisters(
6735 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
6736 __ StoreToSafepointRegisterSlot(reg, eax);
6737 }
6738
6739
6740 void LCodeGen::DoTaggedToInt32x4(LTaggedToInt32x4* instr) {
6741 LOperand* input = instr->value();
6742 ASSERT(input->IsRegister());
6743 LOperand* result = instr->result();
6744 ASSERT(result->IsInt32x4Register());
6745
6746 Register input_reg = ToRegister(input);
6747 Register scratch = ToRegister(instr->temp());
6748 XMMRegister result_reg = ToInt32x4Register(result);
6749
6750 CpuFeatureScope scope(masm(), SSE2);
6751 __ test(input_reg, Immediate(kSmiTagMask));
6752 DeoptimizeIf(zero, instr->environment());
6753 __ CmpObjectType(input_reg, INT32x4_TYPE, scratch);
6754 DeoptimizeIf(not_equal, instr->environment());
6755 __ movups(result_reg, FieldOperand(input_reg, Int32x4::kValueOffset));
6756 }
6757
6758
6759 void LCodeGen::DoNullarySIMDOperation(LNullarySIMDOperation* instr) {
6760 CpuFeatureScope scope(masm(), SSE2);
6761 switch (instr->op()) {
6762 case kFloat32x4Zero: {
6763 XMMRegister result_reg = ToFloat32x4Register(instr->result());
6764 __ xorps(result_reg, result_reg);
6765 return;
6766 }
6767 default:
6768 UNREACHABLE();
6769 return;
6770 }
6771 }
6772
6773
6774 void LCodeGen::DoUnarySIMDOperation(LUnarySIMDOperation* instr) {
6775 CpuFeatureScope scope(masm(), SSE2);
6776 uint8_t select = 0;
6777 switch (instr->op()) {
6778 case kFloat32x4OrInt32x4Change: {
6779 Comment(";;; deoptimize: can not perform representation change"
6780 "for float32x4 or int32x4");
6781 DeoptimizeIf(no_condition, instr->environment());
6782 return;
6783 }
6784 case kSIMDAbs:
6785 case kSIMDNeg:
6786 case kSIMDReciprocal:
6787 case kSIMDReciprocalSqrt:
6788 case kSIMDSqrt: {
6789 ASSERT(instr->value()->Equals(instr->result()));
6790 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
6791 XMMRegister input_reg = ToFloat32x4Register(instr->value());
6792 switch (instr->op()) {
6793 case kSIMDAbs:
6794 __ absps(input_reg);
6795 break;
6796 case kSIMDNeg:
6797 __ negateps(input_reg);
6798 break;
6799 case kSIMDReciprocal:
6800 __ rcpps(input_reg, input_reg);
6801 break;
6802 case kSIMDReciprocalSqrt:
6803 __ rsqrtps(input_reg, input_reg);
6804 break;
6805 case kSIMDSqrt:
6806 __ sqrtps(input_reg, input_reg);
6807 break;
6808 default:
6809 UNREACHABLE();
6810 break;
6811 }
6812 return;
6813 }
6814 case kSIMDNot:
6815 case kSIMDNegU32: {
6816 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
6817 XMMRegister input_reg = ToInt32x4Register(instr->value());
6818 switch (instr->op()) {
6819 case kSIMDNot:
6820 __ notps(input_reg);
6821 break;
6822 case kSIMDNegU32:
6823 __ pnegd(input_reg);
6824 break;
6825 default:
6826 UNREACHABLE();
6827 break;
6828 }
6829 return;
6830 }
6831 case kSIMDBitsToFloat32x4:
6832 case kSIMDToFloat32x4: {
6833 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
6834 XMMRegister input_reg = ToInt32x4Register(instr->value());
6835 XMMRegister result_reg = ToFloat32x4Register(instr->result());
6836 if (instr->op() == kSIMDBitsToFloat32x4) {
6837 if (!result_reg.is(input_reg)) {
6838 __ movaps(result_reg, input_reg);
6839 }
6840 } else {
6841 ASSERT(instr->op() == kSIMDToFloat32x4);
6842 __ cvtdq2ps(result_reg, input_reg);
6843 }
6844 return;
6845 }
6846 case kSIMDBitsToInt32x4:
6847 case kSIMDToInt32x4: {
6848 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
6849 XMMRegister input_reg = ToFloat32x4Register(instr->value());
6850 XMMRegister result_reg = ToInt32x4Register(instr->result());
6851 if (instr->op() == kSIMDBitsToInt32x4) {
6852 if (!result_reg.is(input_reg)) {
6853 __ movaps(result_reg, input_reg);
6854 }
6855 } else {
6856 ASSERT(instr->op() == kSIMDToInt32x4);
6857 __ cvtps2dq(result_reg, input_reg);
6858 }
6859 return;
6860 }
6861 case kFloat32x4Splat: {
6862 ASSERT(instr->hydrogen()->value()->representation().IsDouble());
6863 XMMRegister input_reg = ToDoubleRegister(instr->value());
6864 XMMRegister result_reg = ToFloat32x4Register(instr->result());
6865 XMMRegister xmm_scratch = xmm0;
6866 __ xorps(xmm_scratch, xmm_scratch);
6867 __ cvtsd2ss(xmm_scratch, input_reg);
6868 __ shufps(xmm_scratch, xmm_scratch, 0x0);
6869 __ movaps(result_reg, xmm_scratch);
6870 return;
6871 }
6872 case kInt32x4Splat: {
6873 ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
6874 Register input_reg = ToRegister(instr->value());
6875 XMMRegister result_reg = ToInt32x4Register(instr->result());
6876 __ movd(result_reg, input_reg);
6877 __ shufps(result_reg, result_reg, 0x0);
6878 return;
6879 }
6880 case kInt32x4SignMask: {
6881 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
6882 XMMRegister input_reg = ToInt32x4Register(instr->value());
6883 Register result = ToRegister(instr->result());
6884 __ movmskps(result, input_reg);
6885 return;
6886 }
6887 case kFloat32x4SignMask: {
6888 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
6889 XMMRegister input_reg = ToFloat32x4Register(instr->value());
6890 Register result = ToRegister(instr->result());
6891 __ movmskps(result, input_reg);
6892 return;
6893 }
6894 case kFloat32x4W:
6895 select++;
6896 case kFloat32x4Z:
6897 select++;
6898 case kFloat32x4Y:
6899 select++;
6900 case kFloat32x4X: {
6901 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4());
6902 XMMRegister input_reg = ToFloat32x4Register(instr->value());
6903 XMMRegister result = ToDoubleRegister(instr->result());
6904 XMMRegister xmm_scratch = result.is(input_reg) ? xmm0 : result;
6905
6906 if (select == 0x0) {
6907 __ xorps(xmm_scratch, xmm_scratch);
6908 __ cvtss2sd(xmm_scratch, input_reg);
6909 if (!xmm_scratch.is(result)) {
6910 __ movaps(result, xmm_scratch);
6911 }
6912 } else {
6913 __ pshufd(xmm_scratch, input_reg, select);
6914 if (!xmm_scratch.is(result)) {
6915 __ xorps(result, result);
6916 }
6917 __ cvtss2sd(result, xmm_scratch);
6918 }
6919 return;
6920 }
6921 case kInt32x4X:
6922 case kInt32x4Y:
6923 case kInt32x4Z:
6924 case kInt32x4W:
6925 case kInt32x4FlagX:
6926 case kInt32x4FlagY:
6927 case kInt32x4FlagZ:
6928 case kInt32x4FlagW: {
6929 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4());
6930 bool flag = false;
6931 switch (instr->op()) {
6932 case kInt32x4FlagX:
6933 flag = true;
6934 case kInt32x4X:
6935 break;
6936 case kInt32x4FlagY:
6937 flag = true;
6938 case kInt32x4Y:
6939 select = 0x1;
6940 break;
6941 case kInt32x4FlagZ:
6942 flag = true;
6943 case kInt32x4Z:
6944 select = 0x2;
6945 break;
6946 case kInt32x4FlagW:
6947 flag = true;
6948 case kInt32x4W:
6949 select = 0x3;
6950 break;
6951 default:
6952 UNREACHABLE();
6953 }
6954
6955 XMMRegister input_reg = ToInt32x4Register(instr->value());
6956 Register result = ToRegister(instr->result());
6957 if (select == 0x0) {
6958 __ movd(result, input_reg);
6959 } else {
6960 if (CpuFeatures::IsSupported(SSE4_1)) {
6961 CpuFeatureScope scope(masm(), SSE4_1);
6962 __ extractps(result, input_reg, select);
6963 } else {
6964 XMMRegister xmm_scratch = xmm0;
6965 __ pshufd(xmm_scratch, input_reg, select);
6966 __ movd(result, xmm_scratch);
6967 }
6968 }
6969
6970 if (flag) {
6971 Label false_value, done;
6972 __ test(result, result);
6973 __ j(zero, &false_value, Label::kNear);
6974 __ LoadRoot(result, Heap::kTrueValueRootIndex);
6975 __ jmp(&done, Label::kNear);
6976 __ bind(&false_value);
6977 __ LoadRoot(result, Heap::kFalseValueRootIndex);
6978 __ bind(&done);
6979 }
6980 return;
6981 }
6982 default:
6983 UNREACHABLE();
6984 return;
6985 }
6986 }
6987
6988
6989 void LCodeGen::DoBinarySIMDOperation(LBinarySIMDOperation* instr) {
6990 CpuFeatureScope scope(masm(), SSE2);
6991 uint8_t imm8 = 0; // for with operation
6992 switch (instr->op()) {
6993 case kSIMDAdd:
6994 case kSIMDSub:
6995 case kSIMDMul:
6996 case kSIMDDiv:
6997 case kSIMDMin:
6998 case kSIMDMax: {
6999 ASSERT(instr->left()->Equals(instr->result()));
7000 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
7001 ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4());
7002 XMMRegister left_reg = ToFloat32x4Register(instr->left());
7003 XMMRegister right_reg = ToFloat32x4Register(instr->right());
7004 switch (instr->op()) {
7005 case kSIMDAdd:
7006 __ addps(left_reg, right_reg);
7007 break;
7008 case kSIMDSub:
7009 __ subps(left_reg, right_reg);
7010 break;
7011 case kSIMDMul:
7012 __ mulps(left_reg, right_reg);
7013 break;
7014 case kSIMDDiv:
7015 __ divps(left_reg, right_reg);
7016 break;
7017 case kSIMDMin:
7018 __ minps(left_reg, right_reg);
7019 break;
7020 case kSIMDMax:
7021 __ maxps(left_reg, right_reg);
7022 break;
7023 default:
7024 UNREACHABLE();
7025 break;
7026 }
7027 return;
7028 }
7029 case kSIMDScale: {
7030 ASSERT(instr->left()->Equals(instr->result()));
7031 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
7032 ASSERT(instr->hydrogen()->right()->representation().IsDouble());
7033 XMMRegister left_reg = ToFloat32x4Register(instr->left());
7034 XMMRegister right_reg = ToDoubleRegister(instr->right());
7035 XMMRegister scratch_reg = xmm0;
7036 __ xorps(scratch_reg, scratch_reg);
7037 __ cvtsd2ss(scratch_reg, right_reg);
7038 __ shufps(scratch_reg, scratch_reg, 0x0);
7039 __ mulps(left_reg, scratch_reg);
7040 return;
7041 }
7042 case kSIMDShuffle: {
7043 ASSERT(instr->left()->Equals(instr->result()));
7044 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
7045 if (instr->hydrogen()->right()->IsConstant() &&
7046 HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
7047 int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
7048 uint8_t select = static_cast<uint8_t>(value & 0xFF);
7049 XMMRegister left_reg = ToFloat32x4Register(instr->left());
7050 __ shufps(left_reg, left_reg, select);
7051 return;
7052 } else {
7053 Comment(";;; deoptimize: non-constant selector for shuffle");
7054 DeoptimizeIf(no_condition, instr->environment());
7055 return;
7056 }
7057 }
7058 case kSIMDShuffleU32: {
7059 ASSERT(instr->left()->Equals(instr->result()));
7060 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
7061 if (instr->hydrogen()->right()->IsConstant() &&
7062 HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) {
7063 int32_t value = ToInteger32(LConstantOperand::cast(instr->right()));
7064 uint8_t select = static_cast<uint8_t>(value & 0xFF);
7065 XMMRegister left_reg = ToInt32x4Register(instr->left());
7066 __ pshufd(left_reg, left_reg, select);
7067 return;
7068 } else {
7069 Comment(";;; deoptimize: non-constant selector for shuffle");
7070 DeoptimizeIf(no_condition, instr->environment());
7071 return;
7072 }
7073 }
7074 case kSIMDLessThan:
7075 case kSIMDLessThanOrEqual:
7076 case kSIMDEqual:
7077 case kSIMDNotEqual:
7078 case kSIMDGreaterThanOrEqual:
7079 case kSIMDGreaterThan: {
7080 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
7081 ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4());
7082 XMMRegister left_reg = ToFloat32x4Register(instr->left());
7083 XMMRegister right_reg = ToFloat32x4Register(instr->right());
7084 XMMRegister result_reg = ToInt32x4Register(instr->result());
7085 switch (instr->op()) {
7086 case kSIMDLessThan:
7087 if (result_reg.is(left_reg)) {
7088 __ cmpltps(result_reg, right_reg);
7089 } else if (result_reg.is(right_reg)) {
7090 __ cmpnltps(result_reg, left_reg);
7091 } else {
7092 __ movaps(result_reg, left_reg);
7093 __ cmpltps(result_reg, right_reg);
7094 }
7095 break;
7096 case kSIMDLessThanOrEqual:
7097 if (result_reg.is(left_reg)) {
7098 __ cmpleps(result_reg, right_reg);
7099 } else if (result_reg.is(right_reg)) {
7100 __ cmpnleps(result_reg, left_reg);
7101 } else {
7102 __ movaps(result_reg, left_reg);
7103 __ cmpleps(result_reg, right_reg);
7104 }
7105 break;
7106 case kSIMDEqual:
7107 if (result_reg.is(left_reg)) {
7108 __ cmpeqps(result_reg, right_reg);
7109 } else if (result_reg.is(right_reg)) {
7110 __ cmpeqps(result_reg, left_reg);
7111 } else {
7112 __ movaps(result_reg, left_reg);
7113 __ cmpeqps(result_reg, right_reg);
7114 }
7115 break;
7116 case kSIMDNotEqual:
7117 if (result_reg.is(left_reg)) {
7118 __ cmpneqps(result_reg, right_reg);
7119 } else if (result_reg.is(right_reg)) {
7120 __ cmpneqps(result_reg, left_reg);
7121 } else {
7122 __ movaps(result_reg, left_reg);
7123 __ cmpneqps(result_reg, right_reg);
7124 }
7125 break;
7126 case kSIMDGreaterThanOrEqual:
7127 if (result_reg.is(left_reg)) {
7128 __ cmpnltps(result_reg, right_reg);
7129 } else if (result_reg.is(right_reg)) {
7130 __ cmpltps(result_reg, left_reg);
7131 } else {
7132 __ movaps(result_reg, left_reg);
7133 __ cmpnltps(result_reg, right_reg);
7134 }
7135 break;
7136 case kSIMDGreaterThan:
7137 if (result_reg.is(left_reg)) {
7138 __ cmpnleps(result_reg, right_reg);
7139 } else if (result_reg.is(right_reg)) {
7140 __ cmpleps(result_reg, left_reg);
7141 } else {
7142 __ movaps(result_reg, left_reg);
7143 __ cmpnleps(result_reg, right_reg);
7144 }
7145 break;
7146 default:
7147 UNREACHABLE();
7148 break;
7149 }
7150 return;
7151 }
7152 case kSIMDAnd:
7153 case kSIMDOr:
7154 case kSIMDXor:
7155 case kSIMDAddU32:
7156 case kSIMDSubU32:
7157 case kSIMDMulU32: {
7158 ASSERT(instr->left()->Equals(instr->result()));
7159 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
7160 ASSERT(instr->hydrogen()->right()->representation().IsInt32x4());
7161 XMMRegister left_reg = ToInt32x4Register(instr->left());
7162 XMMRegister right_reg = ToInt32x4Register(instr->right());
7163 switch (instr->op()) {
7164 case kSIMDAnd:
7165 __ andps(left_reg, right_reg);
7166 break;
7167 case kSIMDOr:
7168 __ orps(left_reg, right_reg);
7169 break;
7170 case kSIMDXor:
7171 __ xorps(left_reg, right_reg);
7172 break;
7173 case kSIMDAddU32:
7174 __ paddd(left_reg, right_reg);
7175 break;
7176 case kSIMDSubU32:
7177 __ psubd(left_reg, right_reg);
7178 break;
7179 case kSIMDMulU32:
7180 if (CpuFeatures::IsSupported(SSE4_1)) {
7181 CpuFeatureScope scope(masm(), SSE4_1);
7182 __ pmulld(left_reg, right_reg);
7183 } else {
7184 // The algorithm is from http://stackoverflow.com/questions/10500766 /sse-multiplication-of-4-32-bit-integers
7185 XMMRegister xmm_scratch = xmm0;
7186 __ movaps(xmm_scratch, left_reg);
7187 __ pmuludq(left_reg, right_reg);
7188 __ psrlq(xmm_scratch, 4);
7189 __ psrlq(right_reg, 4);
7190 __ pmuludq(xmm_scratch, right_reg);
7191 __ pshufd(left_reg, left_reg, 8);
7192 __ pshufd(xmm_scratch, xmm_scratch, 8);
7193 __ punpackldq(left_reg, xmm_scratch);
7194 }
7195 break;
7196 default:
7197 UNREACHABLE();
7198 break;
7199 }
7200 return;
7201 }
7202 case kSIMDWithW:
7203 imm8++;
7204 case kSIMDWithZ:
7205 imm8++;
7206 case kSIMDWithY:
7207 imm8++;
7208 case kSIMDWithX: {
7209 ASSERT(instr->left()->Equals(instr->result()));
7210 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4());
7211 ASSERT(instr->hydrogen()->right()->representation().IsDouble());
7212 XMMRegister left_reg = ToFloat32x4Register(instr->left());
7213 XMMRegister right_reg = ToDoubleRegister(instr->right());
7214 XMMRegister xmm_scratch = xmm0;
7215 __ xorps(xmm_scratch, xmm_scratch);
7216 __ cvtsd2ss(xmm_scratch, right_reg);
7217 if (CpuFeatures::IsSupported(SSE4_1)) {
7218 imm8 = imm8 << 4;
7219 CpuFeatureScope scope(masm(), SSE4_1);
7220 __ insertps(left_reg, xmm_scratch, imm8);
7221 } else {
7222 __ sub(esp, Immediate(kFloat32x4Size));
7223 __ movups(Operand(esp, 0), left_reg);
7224 __ movss(Operand(esp, imm8 * kFloatSize), xmm_scratch);
7225 __ movups(left_reg, Operand(esp, 0));
7226 __ add(esp, Immediate(kFloat32x4Size));
7227 }
7228 return;
7229 }
7230 case kSIMDWithWu32:
7231 imm8++;
7232 case kSIMDWithZu32:
7233 imm8++;
7234 case kSIMDWithYu32:
7235 imm8++;
7236 case kSIMDWithXu32: {
7237 ASSERT(instr->left()->Equals(instr->result()));
7238 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
7239 ASSERT(instr->hydrogen()->right()->representation().IsInteger32());
7240 XMMRegister left_reg = ToInt32x4Register(instr->left());
7241 Register right_reg = ToRegister(instr->right());
7242 if (CpuFeatures::IsSupported(SSE4_1)) {
7243 CpuFeatureScope scope(masm(), SSE4_1);
7244 __ pinsrd(left_reg, right_reg, imm8);
7245 } else {
7246 __ sub(esp, Immediate(kInt32x4Size));
7247 __ movdqu(Operand(esp, 0), left_reg);
7248 __ mov(Operand(esp, imm8 * kFloatSize), right_reg);
7249 __ movdqu(left_reg, Operand(esp, 0));
7250 __ add(esp, Immediate(kInt32x4Size));
7251 }
7252 return;
7253 }
7254 case kSIMDWithFlagW:
7255 imm8++;
7256 case kSIMDWithFlagZ:
7257 imm8++;
7258 case kSIMDWithFlagY:
7259 imm8++;
7260 case kSIMDWithFlagX: {
7261 ASSERT(instr->left()->Equals(instr->result()));
7262 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4());
7263 ASSERT(instr->hydrogen()->right()->representation().IsTagged());
7264 HType type = instr->hydrogen()->right()->type();
7265 XMMRegister left_reg = ToInt32x4Register(instr->left());
7266 Register right_reg = ToRegister(instr->right());
7267 Label load_false_value, done;
7268 if (type.IsBoolean()) {
7269 __ sub(esp, Immediate(kInt32x4Size));
7270 __ movups(Operand(esp, 0), left_reg);
7271 __ CompareRoot(right_reg, Heap::kTrueValueRootIndex);
7272 __ j(not_equal, &load_false_value, Label::kNear);
7273 } else {
7274 Comment(";;; deoptimize: other types for SIMD.withFlagX/Y/Z/W.");
7275 DeoptimizeIf(no_condition, instr->environment());
7276 return;
7277 }
7278 // load true value.
7279 __ mov(Operand(esp, imm8 * kFloatSize), Immediate(0xFFFFFFFF));
7280 __ jmp(&done, Label::kNear);
7281 __ bind(&load_false_value);
7282 __ mov(Operand(esp, imm8 * kFloatSize), Immediate(0x0));
7283 __ bind(&done);
7284 __ movups(left_reg, Operand(esp, 0));
7285 __ add(esp, Immediate(kInt32x4Size));
7286 return;
7287 }
7288 default:
7289 UNREACHABLE();
7290 return;
7291 }
7292 }
7293
7294
7295 void LCodeGen::DoTernarySIMDOperation(LTernarySIMDOperation* instr) {
7296 CpuFeatureScope scope(masm(), SSE2);
7297 switch (instr->op()) {
7298 case kSIMDSelect: {
7299 ASSERT(instr->hydrogen()->first()->representation().IsInt32x4());
7300 ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
7301 ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4());
7302
7303 XMMRegister mask_reg = ToInt32x4Register(instr->first());
7304 XMMRegister left_reg = ToFloat32x4Register(instr->second());
7305 XMMRegister right_reg = ToFloat32x4Register(instr->third());
7306 XMMRegister result_reg = ToFloat32x4Register(instr->result());
7307 XMMRegister temp_reg = xmm0;
7308
7309 // Copy mask.
7310 __ movaps(temp_reg, mask_reg);
7311 // Invert it.
7312 __ notps(temp_reg);
7313 // temp_reg = temp_reg & falseValue.
7314 __ andps(temp_reg, right_reg);
7315
7316 if (!result_reg.is(mask_reg)) {
7317 if (result_reg.is(left_reg)) {
7318 // result_reg = result_reg & trueValue.
7319 __ andps(result_reg, mask_reg);
7320 // out = result_reg | temp_reg.
7321 __ orps(result_reg, temp_reg);
7322 } else {
7323 __ movaps(result_reg, mask_reg);
7324 // result_reg = result_reg & trueValue.
7325 __ andps(result_reg, left_reg);
7326 // out = result_reg | temp_reg.
7327 __ orps(result_reg, temp_reg);
7328 }
7329 } else {
7330 // result_reg = result_reg & trueValue.
7331 __ andps(result_reg, left_reg);
7332 // out = result_reg | temp_reg.
7333 __ orps(result_reg, temp_reg);
7334 }
7335 return;
7336 }
7337 case kSIMDShuffleMix: {
7338 ASSERT(instr->first()->Equals(instr->result()));
7339 ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4());
7340 ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
7341 ASSERT(instr->hydrogen()->third()->representation().IsInteger32());
7342 if (instr->hydrogen()->third()->IsConstant() &&
7343 HConstant::cast(instr->hydrogen()->third())->HasInteger32Value()) {
7344 int32_t value = ToInteger32(LConstantOperand::cast(instr->third()));
7345 uint8_t select = static_cast<uint8_t>(value & 0xFF);
7346 XMMRegister first_reg = ToFloat32x4Register(instr->first());
7347 XMMRegister second_reg = ToFloat32x4Register(instr->second());
7348 __ shufps(first_reg, second_reg, select);
7349 return;
7350 } else {
7351 Comment(";;; deoptimize: non-constant selector for shuffle");
7352 DeoptimizeIf(no_condition, instr->environment());
7353 return;
7354 }
7355 }
7356 case kSIMDClamp: {
7357 ASSERT(instr->first()->Equals(instr->result()));
7358 ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4());
7359 ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4());
7360 ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4());
7361
7362 XMMRegister value_reg = ToFloat32x4Register(instr->first());
7363 XMMRegister lower_reg = ToFloat32x4Register(instr->second());
7364 XMMRegister upper_reg = ToFloat32x4Register(instr->third());
7365 __ minps(value_reg, upper_reg);
7366 __ maxps(value_reg, lower_reg);
7367 return;
7368 }
7369 default:
7370 UNREACHABLE();
7371 return;
7372 }
7373 }
7374
7375
7376 void LCodeGen::DoQuarternarySIMDOperation(LQuarternarySIMDOperation* instr) {
7377 CpuFeatureScope scope(masm(), SSE2);
7378 switch (instr->op()) {
7379 case kFloat32x4Constructor: {
7380 ASSERT(instr->hydrogen()->x()->representation().IsDouble());
7381 ASSERT(instr->hydrogen()->y()->representation().IsDouble());
7382 ASSERT(instr->hydrogen()->z()->representation().IsDouble());
7383 ASSERT(instr->hydrogen()->w()->representation().IsDouble());
7384 XMMRegister x_reg = ToDoubleRegister(instr->x());
7385 XMMRegister y_reg = ToDoubleRegister(instr->y());
7386 XMMRegister z_reg = ToDoubleRegister(instr->z());
7387 XMMRegister w_reg = ToDoubleRegister(instr->w());
7388 XMMRegister result_reg = ToFloat32x4Register(instr->result());
7389 __ sub(esp, Immediate(kFloat32x4Size));
7390 __ xorps(xmm0, xmm0);
7391 __ cvtsd2ss(xmm0, x_reg);
7392 __ movss(Operand(esp, 0 * kFloatSize), xmm0);
7393 __ xorps(xmm0, xmm0);
7394 __ cvtsd2ss(xmm0, y_reg);
7395 __ movss(Operand(esp, 1 * kFloatSize), xmm0);
7396 __ xorps(xmm0, xmm0);
7397 __ cvtsd2ss(xmm0, z_reg);
7398 __ movss(Operand(esp, 2 * kFloatSize), xmm0);
7399 __ xorps(xmm0, xmm0);
7400 __ cvtsd2ss(xmm0, w_reg);
7401 __ movss(Operand(esp, 3 * kFloatSize), xmm0);
7402 __ movups(result_reg, Operand(esp, 0 * kFloatSize));
7403 __ add(esp, Immediate(kFloat32x4Size));
7404 return;
7405 }
7406 case kInt32x4Constructor: {
7407 ASSERT(instr->hydrogen()->x()->representation().IsInteger32());
7408 ASSERT(instr->hydrogen()->y()->representation().IsInteger32());
7409 ASSERT(instr->hydrogen()->z()->representation().IsInteger32());
7410 ASSERT(instr->hydrogen()->w()->representation().IsInteger32());
7411 Register x_reg = ToRegister(instr->x());
7412 Register y_reg = ToRegister(instr->y());
7413 Register z_reg = ToRegister(instr->z());
7414 Register w_reg = ToRegister(instr->w());
7415 XMMRegister result_reg = ToInt32x4Register(instr->result());
7416 __ sub(esp, Immediate(kInt32x4Size));
7417 __ mov(Operand(esp, 0 * kInt32Size), x_reg);
7418 __ mov(Operand(esp, 1 * kInt32Size), y_reg);
7419 __ mov(Operand(esp, 2 * kInt32Size), z_reg);
7420 __ mov(Operand(esp, 3 * kInt32Size), w_reg);
7421 __ movups(result_reg, Operand(esp, 0 * kInt32Size));
7422 __ add(esp, Immediate(kInt32x4Size));
7423 return;
7424 }
7425 case kInt32x4Bool: {
7426 ASSERT(instr->hydrogen()->x()->representation().IsTagged());
7427 ASSERT(instr->hydrogen()->y()->representation().IsTagged());
7428 ASSERT(instr->hydrogen()->z()->representation().IsTagged());
7429 ASSERT(instr->hydrogen()->w()->representation().IsTagged());
7430 HType x_type = instr->hydrogen()->x()->type();
7431 HType y_type = instr->hydrogen()->y()->type();
7432 HType z_type = instr->hydrogen()->z()->type();
7433 HType w_type = instr->hydrogen()->w()->type();
7434 if (!x_type.IsBoolean() || !y_type.IsBoolean() ||
7435 !z_type.IsBoolean() || !w_type.IsBoolean()) {
7436 Comment(";;; deoptimize: other types for int32x4.bool.");
7437 DeoptimizeIf(no_condition, instr->environment());
7438 return;
7439 }
7440 XMMRegister result_reg = ToInt32x4Register(instr->result());
7441 Register x_reg = ToRegister(instr->x());
7442 Register y_reg = ToRegister(instr->y());
7443 Register z_reg = ToRegister(instr->z());
7444 Register w_reg = ToRegister(instr->w());
7445 Label load_false_x, done_x, load_false_y, done_y,
7446 load_false_z, done_z, load_false_w, done_w;
7447 __ sub(esp, Immediate(kInt32x4Size));
7448
7449 __ CompareRoot(x_reg, Heap::kTrueValueRootIndex);
7450 __ j(not_equal, &load_false_x, Label::kNear);
7451 __ mov(Operand(esp, 0 * kInt32Size), Immediate(-1));
7452 __ jmp(&done_x, Label::kNear);
7453 __ bind(&load_false_x);
7454 __ mov(Operand(esp, 0 * kInt32Size), Immediate(0x0));
7455 __ bind(&done_x);
7456
7457 __ CompareRoot(y_reg, Heap::kTrueValueRootIndex);
7458 __ j(not_equal, &load_false_y, Label::kNear);
7459 __ mov(Operand(esp, 1 * kInt32Size), Immediate(-1));
7460 __ jmp(&done_y, Label::kNear);
7461 __ bind(&load_false_y);
7462 __ mov(Operand(esp, 1 * kInt32Size), Immediate(0x0));
7463 __ bind(&done_y);
7464
7465 __ CompareRoot(z_reg, Heap::kTrueValueRootIndex);
7466 __ j(not_equal, &load_false_z, Label::kNear);
7467 __ mov(Operand(esp, 2 * kInt32Size), Immediate(-1));
7468 __ jmp(&done_z, Label::kNear);
7469 __ bind(&load_false_z);
7470 __ mov(Operand(esp, 2 * kInt32Size), Immediate(0x0));
7471 __ bind(&done_z);
7472
7473 __ CompareRoot(w_reg, Heap::kTrueValueRootIndex);
7474 __ j(not_equal, &load_false_w, Label::kNear);
7475 __ mov(Operand(esp, 3 * kInt32Size), Immediate(-1));
7476 __ jmp(&done_w, Label::kNear);
7477 __ bind(&load_false_w);
7478 __ mov(Operand(esp, 3 * kInt32Size), Immediate(0x0));
7479 __ bind(&done_w);
7480
7481 __ movups(result_reg, Operand(esp, 0));
7482 __ add(esp, Immediate(kInt32x4Size));
7483 return;
7484 }
7485 default:
7486 UNREACHABLE();
7487 return;
7488 }
7489 }
7490
7491
6436 #undef __ 7492 #undef __
6437 7493
6438 } } // namespace v8::internal 7494 } } // namespace v8::internal
6439 7495
6440 #endif // V8_TARGET_ARCH_IA32 7496 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698