OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |