OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 Register LCodeGen::ToRegister(int index) const { | 373 Register LCodeGen::ToRegister(int index) const { |
374 return Register::FromAllocationIndex(index); | 374 return Register::FromAllocationIndex(index); |
375 } | 375 } |
376 | 376 |
377 | 377 |
378 XMMRegister LCodeGen::ToDoubleRegister(int index) const { | 378 XMMRegister LCodeGen::ToDoubleRegister(int index) const { |
379 return XMMRegister::FromAllocationIndex(index); | 379 return XMMRegister::FromAllocationIndex(index); |
380 } | 380 } |
381 | 381 |
382 | 382 |
| 383 XMMRegister LCodeGen::ToFloat32x4Register(int index) const { |
| 384 return Float32x4Register::FromAllocationIndex(index); |
| 385 } |
| 386 |
| 387 |
| 388 XMMRegister LCodeGen::ToInt32x4Register(int index) const { |
| 389 return Int32x4Register::FromAllocationIndex(index); |
| 390 } |
| 391 |
| 392 |
383 Register LCodeGen::ToRegister(LOperand* op) const { | 393 Register LCodeGen::ToRegister(LOperand* op) const { |
384 ASSERT(op->IsRegister()); | 394 ASSERT(op->IsRegister()); |
385 return ToRegister(op->index()); | 395 return ToRegister(op->index()); |
386 } | 396 } |
387 | 397 |
388 | 398 |
389 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { | 399 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { |
390 ASSERT(op->IsDoubleRegister()); | 400 ASSERT(op->IsDoubleRegister()); |
391 return ToDoubleRegister(op->index()); | 401 return ToDoubleRegister(op->index()); |
392 } | 402 } |
393 | 403 |
394 | 404 |
| 405 XMMRegister LCodeGen::ToFloat32x4Register(LOperand* op) const { |
| 406 ASSERT(op->IsFloat32x4Register()); |
| 407 return ToFloat32x4Register(op->index()); |
| 408 } |
| 409 |
| 410 |
| 411 XMMRegister LCodeGen::ToInt32x4Register(LOperand* op) const { |
| 412 ASSERT(op->IsInt32x4Register()); |
| 413 return ToInt32x4Register(op->index()); |
| 414 } |
| 415 |
| 416 |
395 bool LCodeGen::IsInteger32Constant(LConstantOperand* op) const { | 417 bool LCodeGen::IsInteger32Constant(LConstantOperand* op) const { |
396 return op->IsConstantOperand() && | 418 return op->IsConstantOperand() && |
397 chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); | 419 chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); |
398 } | 420 } |
399 | 421 |
400 | 422 |
401 bool LCodeGen::IsSmiConstant(LConstantOperand* op) const { | 423 bool LCodeGen::IsSmiConstant(LConstantOperand* op) const { |
402 return op->IsConstantOperand() && | 424 return op->IsConstantOperand() && |
403 chunk_->LookupLiteralRepresentation(op).IsSmi(); | 425 chunk_->LookupLiteralRepresentation(op).IsSmi(); |
404 } | 426 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 | 467 |
446 static int ArgumentsOffsetWithoutFrame(int index) { | 468 static int ArgumentsOffsetWithoutFrame(int index) { |
447 ASSERT(index < 0); | 469 ASSERT(index < 0); |
448 return -(index + 1) * kPointerSize + kPCOnStackSize; | 470 return -(index + 1) * kPointerSize + kPCOnStackSize; |
449 } | 471 } |
450 | 472 |
451 | 473 |
452 Operand LCodeGen::ToOperand(LOperand* op) const { | 474 Operand LCodeGen::ToOperand(LOperand* op) const { |
453 // Does not handle registers. In X64 assembler, plain registers are not | 475 // Does not handle registers. In X64 assembler, plain registers are not |
454 // representable as an Operand. | 476 // representable as an Operand. |
455 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); | 477 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot() || |
| 478 op->IsFloat32x4StackSlot() || op->IsInt32x4StackSlot()); |
456 if (NeedsEagerFrame()) { | 479 if (NeedsEagerFrame()) { |
457 return Operand(rbp, StackSlotOffset(op->index())); | 480 return Operand(rbp, StackSlotOffset(op->index())); |
458 } else { | 481 } else { |
459 // Retrieve parameter without eager stack-frame relative to the | 482 // Retrieve parameter without eager stack-frame relative to the |
460 // stack-pointer. | 483 // stack-pointer. |
461 return Operand(rsp, ArgumentsOffsetWithoutFrame(op->index())); | 484 return Operand(rsp, ArgumentsOffsetWithoutFrame(op->index())); |
462 } | 485 } |
463 } | 486 } |
464 | 487 |
465 | 488 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 if (op->IsStackSlot()) { | 581 if (op->IsStackSlot()) { |
559 if (is_tagged) { | 582 if (is_tagged) { |
560 translation->StoreStackSlot(op->index()); | 583 translation->StoreStackSlot(op->index()); |
561 } else if (is_uint32) { | 584 } else if (is_uint32) { |
562 translation->StoreUint32StackSlot(op->index()); | 585 translation->StoreUint32StackSlot(op->index()); |
563 } else { | 586 } else { |
564 translation->StoreInt32StackSlot(op->index()); | 587 translation->StoreInt32StackSlot(op->index()); |
565 } | 588 } |
566 } else if (op->IsDoubleStackSlot()) { | 589 } else if (op->IsDoubleStackSlot()) { |
567 translation->StoreDoubleStackSlot(op->index()); | 590 translation->StoreDoubleStackSlot(op->index()); |
| 591 } else if (op->IsFloat32x4StackSlot()) { |
| 592 translation->StoreFloat32x4StackSlot(op->index()); |
| 593 } else if (op->IsInt32x4StackSlot()) { |
| 594 translation->StoreInt32x4StackSlot(op->index()); |
568 } else if (op->IsArgument()) { | 595 } else if (op->IsArgument()) { |
569 ASSERT(is_tagged); | 596 ASSERT(is_tagged); |
570 int src_index = GetStackSlotCount() + op->index(); | 597 int src_index = GetStackSlotCount() + op->index(); |
571 translation->StoreStackSlot(src_index); | 598 translation->StoreStackSlot(src_index); |
572 } else if (op->IsRegister()) { | 599 } else if (op->IsRegister()) { |
573 Register reg = ToRegister(op); | 600 Register reg = ToRegister(op); |
574 if (is_tagged) { | 601 if (is_tagged) { |
575 translation->StoreRegister(reg); | 602 translation->StoreRegister(reg); |
576 } else if (is_uint32) { | 603 } else if (is_uint32) { |
577 translation->StoreUint32Register(reg); | 604 translation->StoreUint32Register(reg); |
578 } else { | 605 } else { |
579 translation->StoreInt32Register(reg); | 606 translation->StoreInt32Register(reg); |
580 } | 607 } |
581 } else if (op->IsDoubleRegister()) { | 608 } else if (op->IsDoubleRegister()) { |
582 XMMRegister reg = ToDoubleRegister(op); | 609 XMMRegister reg = ToDoubleRegister(op); |
583 translation->StoreDoubleRegister(reg); | 610 translation->StoreDoubleRegister(reg); |
| 611 } else if (op->IsFloat32x4Register()) { |
| 612 XMMRegister reg = ToFloat32x4Register(op); |
| 613 translation->StoreFloat32x4Register(reg); |
| 614 } else if (op->IsInt32x4Register()) { |
| 615 XMMRegister reg = ToInt32x4Register(op); |
| 616 translation->StoreInt32x4Register(reg); |
584 } else if (op->IsConstantOperand()) { | 617 } else if (op->IsConstantOperand()) { |
585 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); | 618 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); |
586 int src_index = DefineDeoptimizationLiteral(constant->handle(isolate())); | 619 int src_index = DefineDeoptimizationLiteral(constant->handle(isolate())); |
587 translation->StoreLiteral(src_index); | 620 translation->StoreLiteral(src_index); |
588 } else { | 621 } else { |
589 UNREACHABLE(); | 622 UNREACHABLE(); |
590 } | 623 } |
591 } | 624 } |
592 | 625 |
593 | 626 |
(...skipping 2385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2979 // Even though the HLoad/StoreKeyed (in this case) instructions force | 3012 // Even though the HLoad/StoreKeyed (in this case) instructions force |
2980 // the input representation for the key to be an integer, the input | 3013 // the input representation for the key to be an integer, the input |
2981 // gets replaced during bound check elimination with the index argument | 3014 // gets replaced during bound check elimination with the index argument |
2982 // to the bounds check, which can be tagged, so that case must be | 3015 // to the bounds check, which can be tagged, so that case must be |
2983 // handled here, too. | 3016 // handled here, too. |
2984 if (instr->hydrogen()->IsDehoisted()) { | 3017 if (instr->hydrogen()->IsDehoisted()) { |
2985 // Sign extend key because it could be a 32 bit negative value | 3018 // Sign extend key because it could be a 32 bit negative value |
2986 // and the dehoisted address computation happens in 64 bits | 3019 // and the dehoisted address computation happens in 64 bits |
2987 __ movsxlq(key_reg, key_reg); | 3020 __ movsxlq(key_reg, key_reg); |
2988 } | 3021 } |
| 3022 |
| 3023 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS || |
| 3024 elements_kind == EXTERNAL_INT32x4_ELEMENTS) { |
| 3025 // Double the index and use scale 8. Float32x4 and Int32x4 need scale 16. |
| 3026 __ shl(key_reg, Immediate(0x1)); |
| 3027 } |
2989 } | 3028 } |
2990 Operand operand(BuildFastArrayOperand( | 3029 Operand operand(BuildFastArrayOperand( |
2991 instr->elements(), | 3030 instr->elements(), |
2992 key, | 3031 key, |
2993 elements_kind, | 3032 elements_kind, |
2994 0, | 3033 0, |
2995 instr->additional_index())); | 3034 instr->additional_index())); |
2996 | 3035 |
2997 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 3036 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
2998 XMMRegister result(ToDoubleRegister(instr->result())); | 3037 XMMRegister result(ToDoubleRegister(instr->result())); |
2999 __ movss(result, operand); | 3038 __ movss(result, operand); |
3000 __ cvtss2sd(result, result); | 3039 __ cvtss2sd(result, result); |
3001 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 3040 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
3002 __ movsd(ToDoubleRegister(instr->result()), operand); | 3041 __ movsd(ToDoubleRegister(instr->result()), operand); |
| 3042 } else if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) { |
| 3043 __ movups(ToFloat32x4Register(instr->result()), operand); |
| 3044 if (!key->IsConstantOperand()) { |
| 3045 // Restore the index register. |
| 3046 __ shr(ToRegister(key), Immediate(0x1)); |
| 3047 } |
| 3048 } else if (elements_kind == EXTERNAL_INT32x4_ELEMENTS) { |
| 3049 __ movups(ToInt32x4Register(instr->result()), operand); |
| 3050 if (!key->IsConstantOperand()) { |
| 3051 // Restore the index register. |
| 3052 __ shr(ToRegister(key), Immediate(0x1)); |
| 3053 } |
3003 } else { | 3054 } else { |
3004 Register result(ToRegister(instr->result())); | 3055 Register result(ToRegister(instr->result())); |
3005 switch (elements_kind) { | 3056 switch (elements_kind) { |
3006 case EXTERNAL_BYTE_ELEMENTS: | 3057 case EXTERNAL_BYTE_ELEMENTS: |
3007 __ movsxbq(result, operand); | 3058 __ movsxbq(result, operand); |
3008 break; | 3059 break; |
3009 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3060 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
3010 case EXTERNAL_PIXEL_ELEMENTS: | 3061 case EXTERNAL_PIXEL_ELEMENTS: |
3011 __ movzxbq(result, operand); | 3062 __ movzxbq(result, operand); |
3012 break; | 3063 break; |
3013 case EXTERNAL_SHORT_ELEMENTS: | 3064 case EXTERNAL_SHORT_ELEMENTS: |
3014 __ movsxwq(result, operand); | 3065 __ movsxwq(result, operand); |
3015 break; | 3066 break; |
3016 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3067 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3017 __ movzxwq(result, operand); | 3068 __ movzxwq(result, operand); |
3018 break; | 3069 break; |
3019 case EXTERNAL_INT_ELEMENTS: | 3070 case EXTERNAL_INT_ELEMENTS: |
3020 __ movsxlq(result, operand); | 3071 __ movsxlq(result, operand); |
3021 break; | 3072 break; |
3022 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3073 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3023 __ movl(result, operand); | 3074 __ movl(result, operand); |
3024 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3075 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
3025 __ testl(result, result); | 3076 __ testl(result, result); |
3026 DeoptimizeIf(negative, instr->environment()); | 3077 DeoptimizeIf(negative, instr->environment()); |
3027 } | 3078 } |
3028 break; | 3079 break; |
3029 case EXTERNAL_FLOAT_ELEMENTS: | 3080 case EXTERNAL_FLOAT_ELEMENTS: |
3030 case EXTERNAL_DOUBLE_ELEMENTS: | 3081 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3082 case EXTERNAL_FLOAT32x4_ELEMENTS: |
| 3083 case EXTERNAL_INT32x4_ELEMENTS: |
3031 case FAST_ELEMENTS: | 3084 case FAST_ELEMENTS: |
3032 case FAST_SMI_ELEMENTS: | 3085 case FAST_SMI_ELEMENTS: |
3033 case FAST_DOUBLE_ELEMENTS: | 3086 case FAST_DOUBLE_ELEMENTS: |
3034 case FAST_HOLEY_ELEMENTS: | 3087 case FAST_HOLEY_ELEMENTS: |
3035 case FAST_HOLEY_SMI_ELEMENTS: | 3088 case FAST_HOLEY_SMI_ELEMENTS: |
3036 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3089 case FAST_HOLEY_DOUBLE_ELEMENTS: |
3037 case DICTIONARY_ELEMENTS: | 3090 case DICTIONARY_ELEMENTS: |
3038 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3091 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3039 UNREACHABLE(); | 3092 UNREACHABLE(); |
3040 break; | 3093 break; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3132 | 3185 |
3133 | 3186 |
3134 Operand LCodeGen::BuildFastArrayOperand( | 3187 Operand LCodeGen::BuildFastArrayOperand( |
3135 LOperand* elements_pointer, | 3188 LOperand* elements_pointer, |
3136 LOperand* key, | 3189 LOperand* key, |
3137 ElementsKind elements_kind, | 3190 ElementsKind elements_kind, |
3138 uint32_t offset, | 3191 uint32_t offset, |
3139 uint32_t additional_index) { | 3192 uint32_t additional_index) { |
3140 Register elements_pointer_reg = ToRegister(elements_pointer); | 3193 Register elements_pointer_reg = ToRegister(elements_pointer); |
3141 int shift_size = ElementsKindToShiftSize(elements_kind); | 3194 int shift_size = ElementsKindToShiftSize(elements_kind); |
| 3195 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS || |
| 3196 elements_kind == EXTERNAL_INT32x4_ELEMENTS) { |
| 3197 // Double the index and use scale 8. Float32x4 and Int32x4 need scale 16. |
| 3198 additional_index *= 2; |
| 3199 } |
3142 if (key->IsConstantOperand()) { | 3200 if (key->IsConstantOperand()) { |
3143 int32_t constant_value = ToInteger32(LConstantOperand::cast(key)); | 3201 int32_t constant_value = ToInteger32(LConstantOperand::cast(key)); |
3144 if (constant_value & 0xF0000000) { | 3202 if (constant_value & 0xF0000000) { |
3145 Abort(kArrayIndexConstantValueTooBig); | 3203 Abort(kArrayIndexConstantValueTooBig); |
3146 } | 3204 } |
| 3205 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS || |
| 3206 elements_kind == EXTERNAL_INT32x4_ELEMENTS) { |
| 3207 // Double the index and use scale 8. Float32x4 and Int32x4 need scale 16. |
| 3208 constant_value *= 2; |
| 3209 } |
3147 return Operand(elements_pointer_reg, | 3210 return Operand(elements_pointer_reg, |
3148 ((constant_value + additional_index) << shift_size) | 3211 ((constant_value + additional_index) << shift_size) |
3149 + offset); | 3212 + offset); |
3150 } else { | 3213 } else { |
3151 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); | 3214 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
| 3215 // For Float32x4, make sure the index register is doubled before |
| 3216 // calling this function and restored after its usage. |
3152 return Operand(elements_pointer_reg, | 3217 return Operand(elements_pointer_reg, |
3153 ToRegister(key), | 3218 ToRegister(key), |
3154 scale_factor, | 3219 scale_factor, |
3155 offset + (additional_index << shift_size)); | 3220 offset + (additional_index << shift_size)); |
3156 } | 3221 } |
3157 } | 3222 } |
3158 | 3223 |
3159 | 3224 |
3160 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 3225 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
3161 ASSERT(ToRegister(instr->context()).is(rsi)); | 3226 ASSERT(ToRegister(instr->context()).is(rsi)); |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3691 | 3756 |
3692 // Square root. | 3757 // Square root. |
3693 __ bind(&sqrt); | 3758 __ bind(&sqrt); |
3694 __ xorps(xmm_scratch, xmm_scratch); | 3759 __ xorps(xmm_scratch, xmm_scratch); |
3695 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. | 3760 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. |
3696 __ sqrtsd(input_reg, input_reg); | 3761 __ sqrtsd(input_reg, input_reg); |
3697 __ bind(&done); | 3762 __ bind(&done); |
3698 } | 3763 } |
3699 | 3764 |
3700 | 3765 |
| 3766 void LCodeGen::DoNullarySIMDOperation(LNullarySIMDOperation* instr) { |
| 3767 switch (instr->op()) { |
| 3768 case kFloat32x4Zero: { |
| 3769 XMMRegister result_reg = ToFloat32x4Register(instr->result()); |
| 3770 __ xorps(result_reg, result_reg); |
| 3771 return; |
| 3772 } |
| 3773 default: |
| 3774 UNREACHABLE(); |
| 3775 return; |
| 3776 } |
| 3777 } |
| 3778 |
| 3779 |
| 3780 void LCodeGen::DoUnarySIMDOperation(LUnarySIMDOperation* instr) { |
| 3781 uint8_t select = 0; |
| 3782 switch (instr->op()) { |
| 3783 case kFloat32x4OrInt32x4Change: { |
| 3784 Comment(";;; deoptimize: can not perform representation change" |
| 3785 "for float32x4 or int32x4"); |
| 3786 DeoptimizeIf(no_condition, instr->environment()); |
| 3787 return; |
| 3788 } |
| 3789 case kSIMDAbs: |
| 3790 case kSIMDNeg: |
| 3791 case kSIMDReciprocal: |
| 3792 case kSIMDReciprocalSqrt: |
| 3793 case kSIMDSqrt: { |
| 3794 ASSERT(instr->value()->Equals(instr->result())); |
| 3795 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4()); |
| 3796 XMMRegister input_reg = ToFloat32x4Register(instr->value()); |
| 3797 switch (instr->op()) { |
| 3798 case kSIMDAbs: |
| 3799 __ absps(input_reg); |
| 3800 break; |
| 3801 case kSIMDNeg: |
| 3802 __ negateps(input_reg); |
| 3803 break; |
| 3804 case kSIMDReciprocal: |
| 3805 __ rcpps(input_reg, input_reg); |
| 3806 break; |
| 3807 case kSIMDReciprocalSqrt: |
| 3808 __ rsqrtps(input_reg, input_reg); |
| 3809 break; |
| 3810 case kSIMDSqrt: |
| 3811 __ sqrtps(input_reg, input_reg); |
| 3812 break; |
| 3813 default: |
| 3814 UNREACHABLE(); |
| 3815 break; |
| 3816 } |
| 3817 return; |
| 3818 } |
| 3819 case kSIMDNot: |
| 3820 case kSIMDNegU32: { |
| 3821 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4()); |
| 3822 XMMRegister input_reg = ToInt32x4Register(instr->value()); |
| 3823 switch (instr->op()) { |
| 3824 case kSIMDNot: |
| 3825 __ notps(input_reg); |
| 3826 break; |
| 3827 case kSIMDNegU32: |
| 3828 __ pnegd(input_reg); |
| 3829 break; |
| 3830 default: |
| 3831 UNREACHABLE(); |
| 3832 break; |
| 3833 } |
| 3834 return; |
| 3835 } |
| 3836 case kSIMDBitsToFloat32x4: |
| 3837 case kSIMDToFloat32x4: { |
| 3838 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4()); |
| 3839 XMMRegister input_reg = ToInt32x4Register(instr->value()); |
| 3840 XMMRegister result_reg = ToFloat32x4Register(instr->result()); |
| 3841 if (instr->op() == kSIMDBitsToFloat32x4) { |
| 3842 if (!result_reg.is(input_reg)) { |
| 3843 __ movaps(result_reg, input_reg); |
| 3844 } |
| 3845 } else { |
| 3846 ASSERT(instr->op() == kSIMDToFloat32x4); |
| 3847 __ cvtdq2ps(result_reg, input_reg); |
| 3848 } |
| 3849 return; |
| 3850 } |
| 3851 case kSIMDBitsToInt32x4: |
| 3852 case kSIMDToInt32x4: { |
| 3853 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4()); |
| 3854 XMMRegister input_reg = ToFloat32x4Register(instr->value()); |
| 3855 XMMRegister result_reg = ToInt32x4Register(instr->result()); |
| 3856 if (instr->op() == kSIMDBitsToInt32x4) { |
| 3857 if (!result_reg.is(input_reg)) { |
| 3858 __ movaps(result_reg, input_reg); |
| 3859 } |
| 3860 } else { |
| 3861 ASSERT(instr->op() == kSIMDToInt32x4); |
| 3862 __ cvtps2dq(result_reg, input_reg); |
| 3863 } |
| 3864 return; |
| 3865 } |
| 3866 case kFloat32x4Splat: { |
| 3867 ASSERT(instr->hydrogen()->value()->representation().IsDouble()); |
| 3868 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3869 XMMRegister result_reg = ToFloat32x4Register(instr->result()); |
| 3870 XMMRegister xmm_scratch = xmm0; |
| 3871 __ xorps(xmm_scratch, xmm_scratch); |
| 3872 __ cvtsd2ss(xmm_scratch, input_reg); |
| 3873 __ shufps(xmm_scratch, xmm_scratch, 0x0); |
| 3874 __ movaps(result_reg, xmm_scratch); |
| 3875 return; |
| 3876 } |
| 3877 case kInt32x4Splat: { |
| 3878 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
| 3879 Register input_reg = ToRegister(instr->value()); |
| 3880 XMMRegister result_reg = ToInt32x4Register(instr->result()); |
| 3881 __ movd(result_reg, input_reg); |
| 3882 __ shufps(result_reg, result_reg, 0x0); |
| 3883 return; |
| 3884 } |
| 3885 case kInt32x4SignMask: { |
| 3886 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4()); |
| 3887 XMMRegister input_reg = ToInt32x4Register(instr->value()); |
| 3888 Register result = ToRegister(instr->result()); |
| 3889 __ movmskps(result, input_reg); |
| 3890 return; |
| 3891 } |
| 3892 case kFloat32x4SignMask: { |
| 3893 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4()); |
| 3894 XMMRegister input_reg = ToFloat32x4Register(instr->value()); |
| 3895 Register result = ToRegister(instr->result()); |
| 3896 __ movmskps(result, input_reg); |
| 3897 return; |
| 3898 } |
| 3899 case kFloat32x4W: |
| 3900 select++; |
| 3901 case kFloat32x4Z: |
| 3902 select++; |
| 3903 case kFloat32x4Y: |
| 3904 select++; |
| 3905 case kFloat32x4X: { |
| 3906 ASSERT(instr->hydrogen()->value()->representation().IsFloat32x4()); |
| 3907 XMMRegister input_reg = ToFloat32x4Register(instr->value()); |
| 3908 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3909 XMMRegister xmm_scratch = result.is(input_reg) ? xmm0 : result; |
| 3910 |
| 3911 if (select == 0x0) { |
| 3912 __ xorps(xmm_scratch, xmm_scratch); |
| 3913 __ cvtss2sd(xmm_scratch, input_reg); |
| 3914 if (!xmm_scratch.is(result)) { |
| 3915 __ movaps(result, xmm_scratch); |
| 3916 } |
| 3917 } else { |
| 3918 __ pshufd(xmm_scratch, input_reg, select); |
| 3919 if (!xmm_scratch.is(result)) { |
| 3920 __ xorps(result, result); |
| 3921 } |
| 3922 __ cvtss2sd(result, xmm_scratch); |
| 3923 } |
| 3924 return; |
| 3925 } |
| 3926 case kInt32x4X: |
| 3927 case kInt32x4Y: |
| 3928 case kInt32x4Z: |
| 3929 case kInt32x4W: |
| 3930 case kInt32x4FlagX: |
| 3931 case kInt32x4FlagY: |
| 3932 case kInt32x4FlagZ: |
| 3933 case kInt32x4FlagW: { |
| 3934 ASSERT(instr->hydrogen()->value()->representation().IsInt32x4()); |
| 3935 bool flag = false; |
| 3936 switch (instr->op()) { |
| 3937 case kInt32x4FlagX: |
| 3938 flag = true; |
| 3939 case kInt32x4X: |
| 3940 break; |
| 3941 case kInt32x4FlagY: |
| 3942 flag = true; |
| 3943 case kInt32x4Y: |
| 3944 select = 0x1; |
| 3945 break; |
| 3946 case kInt32x4FlagZ: |
| 3947 flag = true; |
| 3948 case kInt32x4Z: |
| 3949 select = 0x2; |
| 3950 break; |
| 3951 case kInt32x4FlagW: |
| 3952 flag = true; |
| 3953 case kInt32x4W: |
| 3954 select = 0x3; |
| 3955 break; |
| 3956 default: |
| 3957 UNREACHABLE(); |
| 3958 } |
| 3959 |
| 3960 XMMRegister input_reg = ToInt32x4Register(instr->value()); |
| 3961 Register result = ToRegister(instr->result()); |
| 3962 if (select == 0x0) { |
| 3963 __ movd(result, input_reg); |
| 3964 } else { |
| 3965 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 3966 CpuFeatureScope scope(masm(), SSE4_1); |
| 3967 __ extractps(result, input_reg, select); |
| 3968 } else { |
| 3969 XMMRegister xmm_scratch = xmm0; |
| 3970 __ pshufd(xmm_scratch, input_reg, select); |
| 3971 __ movd(result, xmm_scratch); |
| 3972 } |
| 3973 } |
| 3974 |
| 3975 if (flag) { |
| 3976 Label false_value, done; |
| 3977 __ testl(result, result); |
| 3978 __ j(zero, &false_value, Label::kNear); |
| 3979 __ LoadRoot(result, Heap::kTrueValueRootIndex); |
| 3980 __ jmp(&done, Label::kNear); |
| 3981 __ bind(&false_value); |
| 3982 __ LoadRoot(result, Heap::kFalseValueRootIndex); |
| 3983 __ bind(&done); |
| 3984 } |
| 3985 return; |
| 3986 } |
| 3987 default: |
| 3988 UNREACHABLE(); |
| 3989 return; |
| 3990 } |
| 3991 } |
| 3992 |
| 3993 |
| 3994 void LCodeGen::DoBinarySIMDOperation(LBinarySIMDOperation* instr) { |
| 3995 uint8_t imm8 = 0; // for with operation |
| 3996 switch (instr->op()) { |
| 3997 case kSIMDAdd: |
| 3998 case kSIMDSub: |
| 3999 case kSIMDMul: |
| 4000 case kSIMDDiv: |
| 4001 case kSIMDMin: |
| 4002 case kSIMDMax: { |
| 4003 ASSERT(instr->left()->Equals(instr->result())); |
| 4004 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4()); |
| 4005 ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4()); |
| 4006 XMMRegister left_reg = ToFloat32x4Register(instr->left()); |
| 4007 XMMRegister right_reg = ToFloat32x4Register(instr->right()); |
| 4008 switch (instr->op()) { |
| 4009 case kSIMDAdd: |
| 4010 __ addps(left_reg, right_reg); |
| 4011 break; |
| 4012 case kSIMDSub: |
| 4013 __ subps(left_reg, right_reg); |
| 4014 break; |
| 4015 case kSIMDMul: |
| 4016 __ mulps(left_reg, right_reg); |
| 4017 break; |
| 4018 case kSIMDDiv: |
| 4019 __ divps(left_reg, right_reg); |
| 4020 break; |
| 4021 case kSIMDMin: |
| 4022 __ minps(left_reg, right_reg); |
| 4023 break; |
| 4024 case kSIMDMax: |
| 4025 __ maxps(left_reg, right_reg); |
| 4026 break; |
| 4027 default: |
| 4028 UNREACHABLE(); |
| 4029 break; |
| 4030 } |
| 4031 return; |
| 4032 } |
| 4033 case kSIMDScale: { |
| 4034 ASSERT(instr->left()->Equals(instr->result())); |
| 4035 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4()); |
| 4036 ASSERT(instr->hydrogen()->right()->representation().IsDouble()); |
| 4037 XMMRegister left_reg = ToFloat32x4Register(instr->left()); |
| 4038 XMMRegister right_reg = ToDoubleRegister(instr->right()); |
| 4039 XMMRegister scratch_reg = xmm0; |
| 4040 __ xorps(scratch_reg, scratch_reg); |
| 4041 __ cvtsd2ss(scratch_reg, right_reg); |
| 4042 __ shufps(scratch_reg, scratch_reg, 0x0); |
| 4043 __ mulps(left_reg, scratch_reg); |
| 4044 return; |
| 4045 } |
| 4046 case kSIMDShuffle: { |
| 4047 ASSERT(instr->left()->Equals(instr->result())); |
| 4048 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4()); |
| 4049 if (instr->hydrogen()->right()->IsConstant() && |
| 4050 HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) { |
| 4051 int32_t value = ToInteger32(LConstantOperand::cast(instr->right())); |
| 4052 uint8_t select = static_cast<uint8_t>(value & 0xFF); |
| 4053 XMMRegister left_reg = ToFloat32x4Register(instr->left()); |
| 4054 __ shufps(left_reg, left_reg, select); |
| 4055 return; |
| 4056 } else { |
| 4057 Comment(";;; deoptimize: non-constant selector for shuffle"); |
| 4058 DeoptimizeIf(no_condition, instr->environment()); |
| 4059 return; |
| 4060 } |
| 4061 } |
| 4062 case kSIMDShuffleU32: { |
| 4063 ASSERT(instr->left()->Equals(instr->result())); |
| 4064 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4()); |
| 4065 if (instr->hydrogen()->right()->IsConstant() && |
| 4066 HConstant::cast(instr->hydrogen()->right())->HasInteger32Value()) { |
| 4067 int32_t value = ToInteger32(LConstantOperand::cast(instr->right())); |
| 4068 uint8_t select = static_cast<uint8_t>(value & 0xFF); |
| 4069 XMMRegister left_reg = ToInt32x4Register(instr->left()); |
| 4070 __ pshufd(left_reg, left_reg, select); |
| 4071 return; |
| 4072 } else { |
| 4073 Comment(";;; deoptimize: non-constant selector for shuffle"); |
| 4074 DeoptimizeIf(no_condition, instr->environment()); |
| 4075 return; |
| 4076 } |
| 4077 } |
| 4078 case kSIMDLessThan: |
| 4079 case kSIMDLessThanOrEqual: |
| 4080 case kSIMDEqual: |
| 4081 case kSIMDNotEqual: |
| 4082 case kSIMDGreaterThanOrEqual: |
| 4083 case kSIMDGreaterThan: { |
| 4084 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4()); |
| 4085 ASSERT(instr->hydrogen()->right()->representation().IsFloat32x4()); |
| 4086 XMMRegister left_reg = ToFloat32x4Register(instr->left()); |
| 4087 XMMRegister right_reg = ToFloat32x4Register(instr->right()); |
| 4088 XMMRegister result_reg = ToInt32x4Register(instr->result()); |
| 4089 switch (instr->op()) { |
| 4090 case kSIMDLessThan: |
| 4091 if (result_reg.is(left_reg)) { |
| 4092 __ cmpltps(result_reg, right_reg); |
| 4093 } else if (result_reg.is(right_reg)) { |
| 4094 __ cmpnltps(result_reg, left_reg); |
| 4095 } else { |
| 4096 __ movaps(result_reg, left_reg); |
| 4097 __ cmpltps(result_reg, right_reg); |
| 4098 } |
| 4099 break; |
| 4100 case kSIMDLessThanOrEqual: |
| 4101 if (result_reg.is(left_reg)) { |
| 4102 __ cmpleps(result_reg, right_reg); |
| 4103 } else if (result_reg.is(right_reg)) { |
| 4104 __ cmpnleps(result_reg, left_reg); |
| 4105 } else { |
| 4106 __ movaps(result_reg, left_reg); |
| 4107 __ cmpleps(result_reg, right_reg); |
| 4108 } |
| 4109 break; |
| 4110 case kSIMDEqual: |
| 4111 if (result_reg.is(left_reg)) { |
| 4112 __ cmpeqps(result_reg, right_reg); |
| 4113 } else if (result_reg.is(right_reg)) { |
| 4114 __ cmpeqps(result_reg, left_reg); |
| 4115 } else { |
| 4116 __ movaps(result_reg, left_reg); |
| 4117 __ cmpeqps(result_reg, right_reg); |
| 4118 } |
| 4119 break; |
| 4120 case kSIMDNotEqual: |
| 4121 if (result_reg.is(left_reg)) { |
| 4122 __ cmpneqps(result_reg, right_reg); |
| 4123 } else if (result_reg.is(right_reg)) { |
| 4124 __ cmpneqps(result_reg, left_reg); |
| 4125 } else { |
| 4126 __ movaps(result_reg, left_reg); |
| 4127 __ cmpneqps(result_reg, right_reg); |
| 4128 } |
| 4129 break; |
| 4130 case kSIMDGreaterThanOrEqual: |
| 4131 if (result_reg.is(left_reg)) { |
| 4132 __ cmpnltps(result_reg, right_reg); |
| 4133 } else if (result_reg.is(right_reg)) { |
| 4134 __ cmpltps(result_reg, left_reg); |
| 4135 } else { |
| 4136 __ movaps(result_reg, left_reg); |
| 4137 __ cmpnltps(result_reg, right_reg); |
| 4138 } |
| 4139 break; |
| 4140 case kSIMDGreaterThan: |
| 4141 if (result_reg.is(left_reg)) { |
| 4142 __ cmpnleps(result_reg, right_reg); |
| 4143 } else if (result_reg.is(right_reg)) { |
| 4144 __ cmpleps(result_reg, left_reg); |
| 4145 } else { |
| 4146 __ movaps(result_reg, left_reg); |
| 4147 __ cmpnleps(result_reg, right_reg); |
| 4148 } |
| 4149 break; |
| 4150 default: |
| 4151 UNREACHABLE(); |
| 4152 break; |
| 4153 } |
| 4154 return; |
| 4155 } |
| 4156 case kSIMDAnd: |
| 4157 case kSIMDOr: |
| 4158 case kSIMDXor: |
| 4159 case kSIMDAddU32: |
| 4160 case kSIMDSubU32: |
| 4161 case kSIMDMulU32: { |
| 4162 ASSERT(instr->left()->Equals(instr->result())); |
| 4163 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4()); |
| 4164 ASSERT(instr->hydrogen()->right()->representation().IsInt32x4()); |
| 4165 XMMRegister left_reg = ToInt32x4Register(instr->left()); |
| 4166 XMMRegister right_reg = ToInt32x4Register(instr->right()); |
| 4167 switch (instr->op()) { |
| 4168 case kSIMDAnd: |
| 4169 __ andps(left_reg, right_reg); |
| 4170 break; |
| 4171 case kSIMDOr: |
| 4172 __ orps(left_reg, right_reg); |
| 4173 break; |
| 4174 case kSIMDXor: |
| 4175 __ xorps(left_reg, right_reg); |
| 4176 break; |
| 4177 case kSIMDAddU32: |
| 4178 __ paddd(left_reg, right_reg); |
| 4179 break; |
| 4180 case kSIMDSubU32: |
| 4181 __ psubd(left_reg, right_reg); |
| 4182 break; |
| 4183 case kSIMDMulU32: |
| 4184 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 4185 CpuFeatureScope scope(masm(), SSE4_1); |
| 4186 __ pmulld(left_reg, right_reg); |
| 4187 } else { |
| 4188 // The algorithm is from http://stackoverflow.com/questions/10500766
/sse-multiplication-of-4-32-bit-integers |
| 4189 XMMRegister xmm_scratch = xmm0; |
| 4190 __ movups(xmm_scratch, left_reg); |
| 4191 __ pmuludq(left_reg, right_reg); |
| 4192 __ psrldq(xmm_scratch, 4); |
| 4193 __ psrldq(right_reg, 4); |
| 4194 __ pmuludq(xmm_scratch, right_reg); |
| 4195 __ pshufd(left_reg, left_reg, 8); |
| 4196 __ pshufd(xmm_scratch, xmm_scratch, 8); |
| 4197 __ punpackldq(left_reg, xmm_scratch); |
| 4198 } |
| 4199 break; |
| 4200 default: |
| 4201 UNREACHABLE(); |
| 4202 break; |
| 4203 } |
| 4204 return; |
| 4205 } |
| 4206 case kSIMDWithW: |
| 4207 imm8++; |
| 4208 case kSIMDWithZ: |
| 4209 imm8++; |
| 4210 case kSIMDWithY: |
| 4211 imm8++; |
| 4212 case kSIMDWithX: { |
| 4213 ASSERT(instr->left()->Equals(instr->result())); |
| 4214 ASSERT(instr->hydrogen()->left()->representation().IsFloat32x4()); |
| 4215 ASSERT(instr->hydrogen()->right()->representation().IsDouble()); |
| 4216 XMMRegister left_reg = ToFloat32x4Register(instr->left()); |
| 4217 XMMRegister right_reg = ToDoubleRegister(instr->right()); |
| 4218 XMMRegister xmm_scratch = xmm0; |
| 4219 __ xorps(xmm_scratch, xmm_scratch); |
| 4220 __ cvtsd2ss(xmm_scratch, right_reg); |
| 4221 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 4222 imm8 = imm8 << 4; |
| 4223 CpuFeatureScope scope(masm(), SSE4_1); |
| 4224 __ insertps(left_reg, xmm_scratch, imm8); |
| 4225 } else { |
| 4226 __ subq(rsp, Immediate(kFloat32x4Size)); |
| 4227 __ movups(Operand(rsp, 0), left_reg); |
| 4228 __ movss(Operand(rsp, imm8 * kFloatSize), xmm_scratch); |
| 4229 __ movups(left_reg, Operand(rsp, 0)); |
| 4230 __ addq(rsp, Immediate(kFloat32x4Size)); |
| 4231 } |
| 4232 return; |
| 4233 } |
| 4234 case kSIMDWithWu32: |
| 4235 imm8++; |
| 4236 case kSIMDWithZu32: |
| 4237 imm8++; |
| 4238 case kSIMDWithYu32: |
| 4239 imm8++; |
| 4240 case kSIMDWithXu32: { |
| 4241 ASSERT(instr->left()->Equals(instr->result())); |
| 4242 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4()); |
| 4243 ASSERT(instr->hydrogen()->right()->representation().IsInteger32()); |
| 4244 XMMRegister left_reg = ToInt32x4Register(instr->left()); |
| 4245 Register right_reg = ToRegister(instr->right()); |
| 4246 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 4247 CpuFeatureScope scope(masm(), SSE4_1); |
| 4248 __ pinsrd(left_reg, right_reg, imm8); |
| 4249 } else { |
| 4250 __ subq(rsp, Immediate(kInt32x4Size)); |
| 4251 __ movdqu(Operand(rsp, 0), left_reg); |
| 4252 __ movl(Operand(rsp, imm8 * kFloatSize), right_reg); |
| 4253 __ movdqu(left_reg, Operand(rsp, 0)); |
| 4254 __ addq(rsp, Immediate(kInt32x4Size)); |
| 4255 } |
| 4256 return; |
| 4257 } |
| 4258 case kSIMDWithFlagW: |
| 4259 imm8++; |
| 4260 case kSIMDWithFlagZ: |
| 4261 imm8++; |
| 4262 case kSIMDWithFlagY: |
| 4263 imm8++; |
| 4264 case kSIMDWithFlagX: { |
| 4265 ASSERT(instr->left()->Equals(instr->result())); |
| 4266 ASSERT(instr->hydrogen()->left()->representation().IsInt32x4()); |
| 4267 ASSERT(instr->hydrogen()->right()->representation().IsTagged()); |
| 4268 HType type = instr->hydrogen()->right()->type(); |
| 4269 XMMRegister left_reg = ToInt32x4Register(instr->left()); |
| 4270 Register right_reg = ToRegister(instr->right()); |
| 4271 Label load_false_value, done; |
| 4272 if (type.IsBoolean()) { |
| 4273 __ subq(rsp, Immediate(kInt32x4Size)); |
| 4274 __ movups(Operand(rsp, 0), left_reg); |
| 4275 __ CompareRoot(right_reg, Heap::kTrueValueRootIndex); |
| 4276 __ j(not_equal, &load_false_value, Label::kNear); |
| 4277 } else { |
| 4278 Comment(";;; deoptimize: other types for SIMD.withFlagX/Y/Z/W."); |
| 4279 DeoptimizeIf(no_condition, instr->environment()); |
| 4280 return; |
| 4281 } |
| 4282 // load true value. |
| 4283 __ movl(Operand(rsp, imm8 * kFloatSize), Immediate(0xFFFFFFFF)); |
| 4284 __ jmp(&done, Label::kNear); |
| 4285 __ bind(&load_false_value); |
| 4286 __ movl(Operand(rsp, imm8 * kFloatSize), Immediate(0x0)); |
| 4287 __ bind(&done); |
| 4288 __ movups(left_reg, Operand(rsp, 0)); |
| 4289 __ addq(rsp, Immediate(kInt32x4Size)); |
| 4290 return; |
| 4291 } |
| 4292 default: |
| 4293 UNREACHABLE(); |
| 4294 return; |
| 4295 } |
| 4296 } |
| 4297 |
| 4298 |
| 4299 void LCodeGen::DoTernarySIMDOperation(LTernarySIMDOperation* instr) { |
| 4300 switch (instr->op()) { |
| 4301 case kSIMDSelect: { |
| 4302 ASSERT(instr->hydrogen()->first()->representation().IsInt32x4()); |
| 4303 ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4()); |
| 4304 ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4()); |
| 4305 |
| 4306 XMMRegister mask_reg = ToInt32x4Register(instr->first()); |
| 4307 XMMRegister left_reg = ToFloat32x4Register(instr->second()); |
| 4308 XMMRegister right_reg = ToFloat32x4Register(instr->third()); |
| 4309 XMMRegister result_reg = ToFloat32x4Register(instr->result()); |
| 4310 XMMRegister temp_reg = xmm0; |
| 4311 |
| 4312 // Copy mask. |
| 4313 __ movaps(temp_reg, mask_reg); |
| 4314 // Invert it. |
| 4315 __ notps(temp_reg); |
| 4316 // temp_reg = temp_reg & falseValue. |
| 4317 __ andps(temp_reg, right_reg); |
| 4318 |
| 4319 if (!result_reg.is(mask_reg)) { |
| 4320 if (result_reg.is(left_reg)) { |
| 4321 // result_reg = result_reg & trueValue. |
| 4322 __ andps(result_reg, mask_reg); |
| 4323 // out = result_reg | temp_reg. |
| 4324 __ orps(result_reg, temp_reg); |
| 4325 } else { |
| 4326 __ movaps(result_reg, mask_reg); |
| 4327 // result_reg = result_reg & trueValue. |
| 4328 __ andps(result_reg, left_reg); |
| 4329 // out = result_reg | temp_reg. |
| 4330 __ orps(result_reg, temp_reg); |
| 4331 } |
| 4332 } else { |
| 4333 // result_reg = result_reg & trueValue. |
| 4334 __ andps(result_reg, left_reg); |
| 4335 // out = result_reg | temp_reg. |
| 4336 __ orps(result_reg, temp_reg); |
| 4337 } |
| 4338 return; |
| 4339 } |
| 4340 case kSIMDShuffleMix: { |
| 4341 ASSERT(instr->first()->Equals(instr->result())); |
| 4342 ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4()); |
| 4343 ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4()); |
| 4344 ASSERT(instr->hydrogen()->third()->representation().IsInteger32()); |
| 4345 if (instr->hydrogen()->third()->IsConstant() && |
| 4346 HConstant::cast(instr->hydrogen()->third())->HasInteger32Value()) { |
| 4347 int32_t value = ToInteger32(LConstantOperand::cast(instr->third())); |
| 4348 uint8_t select = static_cast<uint8_t>(value & 0xFF); |
| 4349 XMMRegister first_reg = ToFloat32x4Register(instr->first()); |
| 4350 XMMRegister second_reg = ToFloat32x4Register(instr->second()); |
| 4351 __ shufps(first_reg, second_reg, select); |
| 4352 return; |
| 4353 } else { |
| 4354 Comment(";;; deoptimize: non-constant selector for shuffle"); |
| 4355 DeoptimizeIf(no_condition, instr->environment()); |
| 4356 return; |
| 4357 } |
| 4358 } |
| 4359 case kSIMDClamp: { |
| 4360 ASSERT(instr->first()->Equals(instr->result())); |
| 4361 ASSERT(instr->hydrogen()->first()->representation().IsFloat32x4()); |
| 4362 ASSERT(instr->hydrogen()->second()->representation().IsFloat32x4()); |
| 4363 ASSERT(instr->hydrogen()->third()->representation().IsFloat32x4()); |
| 4364 |
| 4365 XMMRegister value_reg = ToFloat32x4Register(instr->first()); |
| 4366 XMMRegister lower_reg = ToFloat32x4Register(instr->second()); |
| 4367 XMMRegister upper_reg = ToFloat32x4Register(instr->third()); |
| 4368 __ minps(value_reg, upper_reg); |
| 4369 __ maxps(value_reg, lower_reg); |
| 4370 return; |
| 4371 } |
| 4372 default: |
| 4373 UNREACHABLE(); |
| 4374 return; |
| 4375 } |
| 4376 } |
| 4377 |
| 4378 |
| 4379 void LCodeGen::DoQuarternarySIMDOperation(LQuarternarySIMDOperation* instr) { |
| 4380 switch (instr->op()) { |
| 4381 case kFloat32x4Constructor: { |
| 4382 ASSERT(instr->hydrogen()->x()->representation().IsDouble()); |
| 4383 ASSERT(instr->hydrogen()->y()->representation().IsDouble()); |
| 4384 ASSERT(instr->hydrogen()->z()->representation().IsDouble()); |
| 4385 ASSERT(instr->hydrogen()->w()->representation().IsDouble()); |
| 4386 XMMRegister x_reg = ToDoubleRegister(instr->x()); |
| 4387 XMMRegister y_reg = ToDoubleRegister(instr->y()); |
| 4388 XMMRegister z_reg = ToDoubleRegister(instr->z()); |
| 4389 XMMRegister w_reg = ToDoubleRegister(instr->w()); |
| 4390 XMMRegister result_reg = ToFloat32x4Register(instr->result()); |
| 4391 __ subq(rsp, Immediate(kFloat32x4Size)); |
| 4392 __ xorps(xmm0, xmm0); |
| 4393 __ cvtsd2ss(xmm0, x_reg); |
| 4394 __ movss(Operand(rsp, 0 * kFloatSize), xmm0); |
| 4395 __ xorps(xmm0, xmm0); |
| 4396 __ cvtsd2ss(xmm0, y_reg); |
| 4397 __ movss(Operand(rsp, 1 * kFloatSize), xmm0); |
| 4398 __ xorps(xmm0, xmm0); |
| 4399 __ cvtsd2ss(xmm0, z_reg); |
| 4400 __ movss(Operand(rsp, 2 * kFloatSize), xmm0); |
| 4401 __ xorps(xmm0, xmm0); |
| 4402 __ cvtsd2ss(xmm0, w_reg); |
| 4403 __ movss(Operand(rsp, 3 * kFloatSize), xmm0); |
| 4404 __ movups(result_reg, Operand(rsp, 0 * kFloatSize)); |
| 4405 __ addq(rsp, Immediate(kFloat32x4Size)); |
| 4406 return; |
| 4407 } |
| 4408 case kInt32x4Constructor: { |
| 4409 ASSERT(instr->hydrogen()->x()->representation().IsInteger32()); |
| 4410 ASSERT(instr->hydrogen()->y()->representation().IsInteger32()); |
| 4411 ASSERT(instr->hydrogen()->z()->representation().IsInteger32()); |
| 4412 ASSERT(instr->hydrogen()->w()->representation().IsInteger32()); |
| 4413 Register x_reg = ToRegister(instr->x()); |
| 4414 Register y_reg = ToRegister(instr->y()); |
| 4415 Register z_reg = ToRegister(instr->z()); |
| 4416 Register w_reg = ToRegister(instr->w()); |
| 4417 XMMRegister result_reg = ToInt32x4Register(instr->result()); |
| 4418 __ subq(rsp, Immediate(kInt32x4Size)); |
| 4419 __ movl(Operand(rsp, 0 * kInt32Size), x_reg); |
| 4420 __ movl(Operand(rsp, 1 * kInt32Size), y_reg); |
| 4421 __ movl(Operand(rsp, 2 * kInt32Size), z_reg); |
| 4422 __ movl(Operand(rsp, 3 * kInt32Size), w_reg); |
| 4423 __ movups(result_reg, Operand(rsp, 0 * kInt32Size)); |
| 4424 __ addq(rsp, Immediate(kInt32x4Size)); |
| 4425 return; |
| 4426 } |
| 4427 case kInt32x4Bool: { |
| 4428 ASSERT(instr->hydrogen()->x()->representation().IsTagged()); |
| 4429 ASSERT(instr->hydrogen()->y()->representation().IsTagged()); |
| 4430 ASSERT(instr->hydrogen()->z()->representation().IsTagged()); |
| 4431 ASSERT(instr->hydrogen()->w()->representation().IsTagged()); |
| 4432 HType x_type = instr->hydrogen()->x()->type(); |
| 4433 HType y_type = instr->hydrogen()->y()->type(); |
| 4434 HType z_type = instr->hydrogen()->z()->type(); |
| 4435 HType w_type = instr->hydrogen()->w()->type(); |
| 4436 if (!x_type.IsBoolean() || !y_type.IsBoolean() || |
| 4437 !z_type.IsBoolean() || !w_type.IsBoolean()) { |
| 4438 Comment(";;; deoptimize: other types for int32x4.bool."); |
| 4439 DeoptimizeIf(no_condition, instr->environment()); |
| 4440 return; |
| 4441 } |
| 4442 XMMRegister result_reg = ToInt32x4Register(instr->result()); |
| 4443 Register x_reg = ToRegister(instr->x()); |
| 4444 Register y_reg = ToRegister(instr->y()); |
| 4445 Register z_reg = ToRegister(instr->z()); |
| 4446 Register w_reg = ToRegister(instr->w()); |
| 4447 Label load_false_x, done_x, load_false_y, done_y, |
| 4448 load_false_z, done_z, load_false_w, done_w; |
| 4449 __ subq(rsp, Immediate(kInt32x4Size)); |
| 4450 |
| 4451 __ CompareRoot(x_reg, Heap::kTrueValueRootIndex); |
| 4452 __ j(not_equal, &load_false_x, Label::kNear); |
| 4453 __ movl(Operand(rsp, 0 * kInt32Size), Immediate(-1)); |
| 4454 __ jmp(&done_x, Label::kNear); |
| 4455 __ bind(&load_false_x); |
| 4456 __ movl(Operand(rsp, 0 * kInt32Size), Immediate(0x0)); |
| 4457 __ bind(&done_x); |
| 4458 |
| 4459 __ CompareRoot(y_reg, Heap::kTrueValueRootIndex); |
| 4460 __ j(not_equal, &load_false_y, Label::kNear); |
| 4461 __ movl(Operand(rsp, 1 * kInt32Size), Immediate(-1)); |
| 4462 __ jmp(&done_y, Label::kNear); |
| 4463 __ bind(&load_false_y); |
| 4464 __ movl(Operand(rsp, 1 * kInt32Size), Immediate(0x0)); |
| 4465 __ bind(&done_y); |
| 4466 |
| 4467 __ CompareRoot(z_reg, Heap::kTrueValueRootIndex); |
| 4468 __ j(not_equal, &load_false_z, Label::kNear); |
| 4469 __ movl(Operand(rsp, 2 * kInt32Size), Immediate(-1)); |
| 4470 __ jmp(&done_z, Label::kNear); |
| 4471 __ bind(&load_false_z); |
| 4472 __ movl(Operand(rsp, 2 * kInt32Size), Immediate(0x0)); |
| 4473 __ bind(&done_z); |
| 4474 |
| 4475 __ CompareRoot(w_reg, Heap::kTrueValueRootIndex); |
| 4476 __ j(not_equal, &load_false_w, Label::kNear); |
| 4477 __ movl(Operand(rsp, 3 * kInt32Size), Immediate(-1)); |
| 4478 __ jmp(&done_w, Label::kNear); |
| 4479 __ bind(&load_false_w); |
| 4480 __ movl(Operand(rsp, 3 * kInt32Size), Immediate(0x0)); |
| 4481 __ bind(&done_w); |
| 4482 |
| 4483 __ movups(result_reg, Operand(rsp, 0)); |
| 4484 __ addq(rsp, Immediate(kInt32x4Size)); |
| 4485 return; |
| 4486 } |
| 4487 default: |
| 4488 UNREACHABLE(); |
| 4489 return; |
| 4490 } |
| 4491 } |
| 4492 |
| 4493 |
3701 void LCodeGen::DoPower(LPower* instr) { | 4494 void LCodeGen::DoPower(LPower* instr) { |
3702 Representation exponent_type = instr->hydrogen()->right()->representation(); | 4495 Representation exponent_type = instr->hydrogen()->right()->representation(); |
3703 // Having marked this as a call, we can use any registers. | 4496 // Having marked this as a call, we can use any registers. |
3704 // Just make sure that the input/output registers are the expected ones. | 4497 // Just make sure that the input/output registers are the expected ones. |
3705 | 4498 |
3706 Register exponent = rdx; | 4499 Register exponent = rdx; |
3707 ASSERT(!instr->right()->IsRegister() || | 4500 ASSERT(!instr->right()->IsRegister() || |
3708 ToRegister(instr->right()).is(exponent)); | 4501 ToRegister(instr->right()).is(exponent)); |
3709 ASSERT(!instr->right()->IsDoubleRegister() || | 4502 ASSERT(!instr->right()->IsDoubleRegister() || |
3710 ToDoubleRegister(instr->right()).is(xmm1)); | 4503 ToDoubleRegister(instr->right()).is(xmm1)); |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4168 // Even though the HLoad/StoreKeyedFastElement instructions force | 4961 // Even though the HLoad/StoreKeyedFastElement instructions force |
4169 // the input representation for the key to be an integer, the input | 4962 // the input representation for the key to be an integer, the input |
4170 // gets replaced during bound check elimination with the index | 4963 // gets replaced during bound check elimination with the index |
4171 // argument to the bounds check, which can be tagged, so that case | 4964 // argument to the bounds check, which can be tagged, so that case |
4172 // must be handled here, too. | 4965 // must be handled here, too. |
4173 if (instr->hydrogen()->IsDehoisted()) { | 4966 if (instr->hydrogen()->IsDehoisted()) { |
4174 // Sign extend key because it could be a 32 bit negative value | 4967 // Sign extend key because it could be a 32 bit negative value |
4175 // and the dehoisted address computation happens in 64 bits | 4968 // and the dehoisted address computation happens in 64 bits |
4176 __ movsxlq(key_reg, key_reg); | 4969 __ movsxlq(key_reg, key_reg); |
4177 } | 4970 } |
| 4971 |
| 4972 if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS || |
| 4973 elements_kind == EXTERNAL_INT32x4_ELEMENTS) { |
| 4974 // Double the index and use scale 8. Float32x4 and Int32x4 need scale 16. |
| 4975 __ shl(key_reg, Immediate(0x1)); |
| 4976 } |
4178 } | 4977 } |
4179 Operand operand(BuildFastArrayOperand( | 4978 Operand operand(BuildFastArrayOperand( |
4180 instr->elements(), | 4979 instr->elements(), |
4181 key, | 4980 key, |
4182 elements_kind, | 4981 elements_kind, |
4183 0, | 4982 0, |
4184 instr->additional_index())); | 4983 instr->additional_index())); |
4185 | 4984 |
4186 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | 4985 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
4187 XMMRegister value(ToDoubleRegister(instr->value())); | 4986 XMMRegister value(ToDoubleRegister(instr->value())); |
4188 __ cvtsd2ss(value, value); | 4987 __ cvtsd2ss(value, value); |
4189 __ movss(operand, value); | 4988 __ movss(operand, value); |
4190 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | 4989 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
4191 __ movsd(operand, ToDoubleRegister(instr->value())); | 4990 __ movsd(operand, ToDoubleRegister(instr->value())); |
| 4991 } else if (elements_kind == EXTERNAL_FLOAT32x4_ELEMENTS) { |
| 4992 __ movups(operand, ToFloat32x4Register(instr->value())); |
| 4993 if (!key->IsConstantOperand()) { |
| 4994 // Restore the index register. |
| 4995 __ shr(ToRegister(key), Immediate(0x1)); |
| 4996 } |
| 4997 } else if (elements_kind == EXTERNAL_INT32x4_ELEMENTS) { |
| 4998 __ movups(operand, ToInt32x4Register(instr->value())); |
| 4999 if (!key->IsConstantOperand()) { |
| 5000 // Restore the index register. |
| 5001 __ shr(ToRegister(key), Immediate(0x1)); |
| 5002 } |
4192 } else { | 5003 } else { |
4193 Register value(ToRegister(instr->value())); | 5004 Register value(ToRegister(instr->value())); |
4194 switch (elements_kind) { | 5005 switch (elements_kind) { |
4195 case EXTERNAL_PIXEL_ELEMENTS: | 5006 case EXTERNAL_PIXEL_ELEMENTS: |
4196 case EXTERNAL_BYTE_ELEMENTS: | 5007 case EXTERNAL_BYTE_ELEMENTS: |
4197 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 5008 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
4198 __ movb(operand, value); | 5009 __ movb(operand, value); |
4199 break; | 5010 break; |
4200 case EXTERNAL_SHORT_ELEMENTS: | 5011 case EXTERNAL_SHORT_ELEMENTS: |
4201 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 5012 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
4202 __ movw(operand, value); | 5013 __ movw(operand, value); |
4203 break; | 5014 break; |
4204 case EXTERNAL_INT_ELEMENTS: | 5015 case EXTERNAL_INT_ELEMENTS: |
4205 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 5016 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4206 __ movl(operand, value); | 5017 __ movl(operand, value); |
4207 break; | 5018 break; |
4208 case EXTERNAL_FLOAT_ELEMENTS: | 5019 case EXTERNAL_FLOAT_ELEMENTS: |
| 5020 case EXTERNAL_FLOAT32x4_ELEMENTS: |
| 5021 case EXTERNAL_INT32x4_ELEMENTS: |
4209 case EXTERNAL_DOUBLE_ELEMENTS: | 5022 case EXTERNAL_DOUBLE_ELEMENTS: |
4210 case FAST_ELEMENTS: | 5023 case FAST_ELEMENTS: |
4211 case FAST_SMI_ELEMENTS: | 5024 case FAST_SMI_ELEMENTS: |
4212 case FAST_DOUBLE_ELEMENTS: | 5025 case FAST_DOUBLE_ELEMENTS: |
4213 case FAST_HOLEY_ELEMENTS: | 5026 case FAST_HOLEY_ELEMENTS: |
4214 case FAST_HOLEY_SMI_ELEMENTS: | 5027 case FAST_HOLEY_SMI_ELEMENTS: |
4215 case FAST_HOLEY_DOUBLE_ELEMENTS: | 5028 case FAST_HOLEY_DOUBLE_ELEMENTS: |
4216 case DICTIONARY_ELEMENTS: | 5029 case DICTIONARY_ELEMENTS: |
4217 case NON_STRICT_ARGUMENTS_ELEMENTS: | 5030 case NON_STRICT_ARGUMENTS_ELEMENTS: |
4218 UNREACHABLE(); | 5031 UNREACHABLE(); |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4691 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 5504 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
4692 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 5505 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
4693 RecordSafepointWithRegisters( | 5506 RecordSafepointWithRegisters( |
4694 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 5507 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
4695 __ movq(kScratchRegister, rax); | 5508 __ movq(kScratchRegister, rax); |
4696 } | 5509 } |
4697 __ movq(reg, kScratchRegister); | 5510 __ movq(reg, kScratchRegister); |
4698 } | 5511 } |
4699 | 5512 |
4700 | 5513 |
| 5514 void LCodeGen::DoFloat32x4ToTagged(LFloat32x4ToTagged* instr) { |
| 5515 class DeferredFloat32x4ToTagged V8_FINAL : public LDeferredCode { |
| 5516 public: |
| 5517 DeferredFloat32x4ToTagged(LCodeGen* codegen, LFloat32x4ToTagged* instr) |
| 5518 : LDeferredCode(codegen), instr_(instr) { } |
| 5519 virtual void Generate() V8_OVERRIDE { |
| 5520 codegen()->DoDeferredFloat32x4ToTagged(instr_); |
| 5521 } |
| 5522 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5523 private: |
| 5524 LFloat32x4ToTagged* instr_; |
| 5525 }; |
| 5526 |
| 5527 XMMRegister input_reg = ToFloat32x4Register(instr->value()); |
| 5528 Register reg = ToRegister(instr->result()); |
| 5529 Register tmp = ToRegister(instr->temp()); |
| 5530 |
| 5531 DeferredFloat32x4ToTagged* deferred = |
| 5532 new(zone()) DeferredFloat32x4ToTagged(this, instr); |
| 5533 if (FLAG_inline_new) { |
| 5534 __ AllocateFloat32x4(reg, tmp, deferred->entry()); |
| 5535 } else { |
| 5536 __ jmp(deferred->entry()); |
| 5537 } |
| 5538 __ bind(deferred->exit()); |
| 5539 __ movups(FieldOperand(reg, Float32x4::kValueOffset), input_reg); |
| 5540 } |
| 5541 |
| 5542 |
| 5543 void LCodeGen::DoDeferredFloat32x4ToTagged(LFloat32x4ToTagged* instr) { |
| 5544 // TODO(3095996): Get rid of this. For now, we need to make the |
| 5545 // result register contain a valid pointer because it is already |
| 5546 // contained in the register pointer map. |
| 5547 Register reg = ToRegister(instr->result()); |
| 5548 __ Move(reg, Smi::FromInt(0)); |
| 5549 |
| 5550 { |
| 5551 PushSafepointRegistersScope scope(this); |
| 5552 // Float32x4ToTagged uses the context from the frame, rather than |
| 5553 // the environment's HContext or HInlinedContext value. |
| 5554 // They only call Runtime::kAllocateFloat32x4. |
| 5555 // The corresponding HChange instructions are added in a phase that does |
| 5556 // not have easy access to the local context. |
| 5557 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 5558 __ CallRuntimeSaveDoubles(Runtime::kAllocateFloat32x4); |
| 5559 RecordSafepointWithRegisters( |
| 5560 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 5561 __ movq(kScratchRegister, rax); |
| 5562 } |
| 5563 __ movq(reg, kScratchRegister); |
| 5564 } |
| 5565 |
| 5566 |
| 5567 void LCodeGen::DoInt32x4ToTagged(LInt32x4ToTagged* instr) { |
| 5568 class DeferredInt32x4ToTagged V8_FINAL : public LDeferredCode { |
| 5569 public: |
| 5570 DeferredInt32x4ToTagged(LCodeGen* codegen, LInt32x4ToTagged* instr) |
| 5571 : LDeferredCode(codegen), instr_(instr) { } |
| 5572 virtual void Generate() V8_OVERRIDE { |
| 5573 codegen()->DoDeferredInt32x4ToTagged(instr_); |
| 5574 } |
| 5575 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5576 private: |
| 5577 LInt32x4ToTagged* instr_; |
| 5578 }; |
| 5579 |
| 5580 XMMRegister input_reg = ToInt32x4Register(instr->value()); |
| 5581 Register reg = ToRegister(instr->result()); |
| 5582 Register tmp = ToRegister(instr->temp()); |
| 5583 |
| 5584 DeferredInt32x4ToTagged* deferred = |
| 5585 new(zone()) DeferredInt32x4ToTagged(this, instr); |
| 5586 if (FLAG_inline_new) { |
| 5587 __ AllocateInt32x4(reg, tmp, deferred->entry()); |
| 5588 } else { |
| 5589 __ jmp(deferred->entry()); |
| 5590 } |
| 5591 __ bind(deferred->exit()); |
| 5592 __ movups(FieldOperand(reg, Int32x4::kValueOffset), input_reg); |
| 5593 } |
| 5594 |
| 5595 |
| 5596 void LCodeGen::DoDeferredInt32x4ToTagged(LInt32x4ToTagged* instr) { |
| 5597 // TODO(3095996): Get rid of this. For now, we need to make the |
| 5598 // result register contain a valid pointer because it is already |
| 5599 // contained in the register pointer map. |
| 5600 Register reg = ToRegister(instr->result()); |
| 5601 __ Move(reg, Smi::FromInt(0)); |
| 5602 |
| 5603 { |
| 5604 PushSafepointRegistersScope scope(this); |
| 5605 // Int32x4ToTagged uses the context from the frame, rather than |
| 5606 // the environment's HContext or HInlinedContext value. |
| 5607 // They only call Runtime::kAllocateInt32x4. |
| 5608 // The corresponding HChange instructions are added in a phase that does |
| 5609 // not have easy access to the local context. |
| 5610 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 5611 __ CallRuntimeSaveDoubles(Runtime::kAllocateInt32x4); |
| 5612 RecordSafepointWithRegisters( |
| 5613 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 5614 __ movq(kScratchRegister, rax); |
| 5615 } |
| 5616 |
| 5617 __ movq(reg, kScratchRegister); |
| 5618 } |
| 5619 |
| 5620 |
4701 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 5621 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4702 ASSERT(instr->value()->Equals(instr->result())); | 5622 ASSERT(instr->value()->Equals(instr->result())); |
4703 Register input = ToRegister(instr->value()); | 5623 Register input = ToRegister(instr->value()); |
4704 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 5624 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
4705 __ Integer32ToSmi(input, input); | 5625 __ Integer32ToSmi(input, input); |
4706 } | 5626 } |
4707 | 5627 |
4708 | 5628 |
4709 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 5629 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
4710 ASSERT(instr->value()->Equals(instr->result())); | 5630 ASSERT(instr->value()->Equals(instr->result())); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4868 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; | 5788 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
4869 | 5789 |
4870 EmitNumberUntagD(input_reg, result_reg, | 5790 EmitNumberUntagD(input_reg, result_reg, |
4871 instr->hydrogen()->can_convert_undefined_to_nan(), | 5791 instr->hydrogen()->can_convert_undefined_to_nan(), |
4872 instr->hydrogen()->deoptimize_on_minus_zero(), | 5792 instr->hydrogen()->deoptimize_on_minus_zero(), |
4873 instr->environment(), | 5793 instr->environment(), |
4874 mode); | 5794 mode); |
4875 } | 5795 } |
4876 | 5796 |
4877 | 5797 |
| 5798 void LCodeGen::DoTaggedToFloat32x4(LTaggedToFloat32x4* instr) { |
| 5799 LOperand* input = instr->value(); |
| 5800 ASSERT(input->IsRegister()); |
| 5801 LOperand* result = instr->result(); |
| 5802 ASSERT(result->IsFloat32x4Register()); |
| 5803 |
| 5804 Register input_reg = ToRegister(input); |
| 5805 XMMRegister result_reg = ToFloat32x4Register(result); |
| 5806 |
| 5807 Condition cc = masm()->CheckSmi(input_reg); |
| 5808 DeoptimizeIf(cc, instr->environment()); |
| 5809 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5810 Heap::kFloat32x4MapRootIndex); |
| 5811 DeoptimizeIf(not_equal, instr->environment()); |
| 5812 __ movups(result_reg, FieldOperand(input_reg, Float32x4::kValueOffset)); |
| 5813 } |
| 5814 |
| 5815 |
| 5816 void LCodeGen::DoTaggedToInt32x4(LTaggedToInt32x4* instr) { |
| 5817 LOperand* input = instr->value(); |
| 5818 ASSERT(input->IsRegister()); |
| 5819 LOperand* result = instr->result(); |
| 5820 ASSERT(result->IsInt32x4Register()); |
| 5821 |
| 5822 Register input_reg = ToRegister(input); |
| 5823 XMMRegister result_reg = ToInt32x4Register(result); |
| 5824 |
| 5825 Condition cc = masm()->CheckSmi(input_reg); |
| 5826 DeoptimizeIf(cc, instr->environment()); |
| 5827 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5828 Heap::kInt32x4MapRootIndex); |
| 5829 DeoptimizeIf(not_equal, instr->environment()); |
| 5830 __ movups(result_reg, FieldOperand(input_reg, Int32x4::kValueOffset)); |
| 5831 } |
| 5832 |
| 5833 |
4878 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5834 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
4879 LOperand* input = instr->value(); | 5835 LOperand* input = instr->value(); |
4880 ASSERT(input->IsDoubleRegister()); | 5836 ASSERT(input->IsDoubleRegister()); |
4881 LOperand* result = instr->result(); | 5837 LOperand* result = instr->result(); |
4882 ASSERT(result->IsRegister()); | 5838 ASSERT(result->IsRegister()); |
4883 | 5839 |
4884 XMMRegister input_reg = ToDoubleRegister(input); | 5840 XMMRegister input_reg = ToDoubleRegister(input); |
4885 Register result_reg = ToRegister(result); | 5841 Register result_reg = ToRegister(result); |
4886 | 5842 |
4887 if (instr->truncating()) { | 5843 if (instr->truncating()) { |
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5329 Label::Distance false_distance = right_block == next_block ? Label::kNear | 6285 Label::Distance false_distance = right_block == next_block ? Label::kNear |
5330 : Label::kFar; | 6286 : Label::kFar; |
5331 Condition final_branch_condition = no_condition; | 6287 Condition final_branch_condition = no_condition; |
5332 if (type_name->Equals(heap()->number_string())) { | 6288 if (type_name->Equals(heap()->number_string())) { |
5333 __ JumpIfSmi(input, true_label, true_distance); | 6289 __ JumpIfSmi(input, true_label, true_distance); |
5334 __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset), | 6290 __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset), |
5335 Heap::kHeapNumberMapRootIndex); | 6291 Heap::kHeapNumberMapRootIndex); |
5336 | 6292 |
5337 final_branch_condition = equal; | 6293 final_branch_condition = equal; |
5338 | 6294 |
| 6295 } else if (type_name->Equals(heap()->float32x4_string())) { |
| 6296 __ JumpIfSmi(input, false_label, false_distance); |
| 6297 __ CmpObjectType(input, FLOAT32x4_TYPE, input); |
| 6298 final_branch_condition = equal; |
| 6299 |
| 6300 } else if (type_name->Equals(heap()->int32x4_string())) { |
| 6301 __ JumpIfSmi(input, false_label, false_distance); |
| 6302 __ CmpObjectType(input, INT32x4_TYPE, input); |
| 6303 final_branch_condition = equal; |
| 6304 |
5339 } else if (type_name->Equals(heap()->string_string())) { | 6305 } else if (type_name->Equals(heap()->string_string())) { |
5340 __ JumpIfSmi(input, false_label, false_distance); | 6306 __ JumpIfSmi(input, false_label, false_distance); |
5341 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); | 6307 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); |
5342 __ j(above_equal, false_label, false_distance); | 6308 __ j(above_equal, false_label, false_distance); |
5343 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 6309 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
5344 Immediate(1 << Map::kIsUndetectable)); | 6310 Immediate(1 << Map::kIsUndetectable)); |
5345 final_branch_condition = zero; | 6311 final_branch_condition = zero; |
5346 | 6312 |
5347 } else if (type_name->Equals(heap()->symbol_string())) { | 6313 } else if (type_name->Equals(heap()->symbol_string())) { |
5348 __ JumpIfSmi(input, false_label, false_distance); | 6314 __ JumpIfSmi(input, false_label, false_distance); |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5639 FixedArray::kHeaderSize - kPointerSize)); | 6605 FixedArray::kHeaderSize - kPointerSize)); |
5640 __ bind(&done); | 6606 __ bind(&done); |
5641 } | 6607 } |
5642 | 6608 |
5643 | 6609 |
5644 #undef __ | 6610 #undef __ |
5645 | 6611 |
5646 } } // namespace v8::internal | 6612 } } // namespace v8::internal |
5647 | 6613 |
5648 #endif // V8_TARGET_ARCH_X64 | 6614 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |