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

Side by Side Diff: src/arm/codegen-arm.cc

Issue 1606019: Make binary op stubs in both r0-r1 and r1-r0 versions to reduce... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/full-codegen-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 734 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 case Token::DIV: 745 case Token::DIV:
746 case Token::MOD: 746 case Token::MOD:
747 case Token::BIT_OR: 747 case Token::BIT_OR:
748 case Token::BIT_AND: 748 case Token::BIT_AND:
749 case Token::BIT_XOR: 749 case Token::BIT_XOR:
750 case Token::SHL: 750 case Token::SHL:
751 case Token::SHR: 751 case Token::SHR:
752 case Token::SAR: { 752 case Token::SAR: {
753 frame_->EmitPop(r0); // r0 : y 753 frame_->EmitPop(r0); // r0 : y
754 frame_->EmitPop(r1); // r1 : x 754 frame_->EmitPop(r1); // r1 : x
755 GenericBinaryOpStub stub(op, overwrite_mode, constant_rhs); 755 GenericBinaryOpStub stub(op, overwrite_mode, r1, r0, constant_rhs);
756 frame_->CallStub(&stub, 0); 756 frame_->CallStub(&stub, 0);
757 break; 757 break;
758 } 758 }
759 759
760 case Token::COMMA: 760 case Token::COMMA:
761 frame_->EmitPop(r0); 761 frame_->EmitPop(r0);
762 // Simply discard left value. 762 // Simply discard left value.
763 frame_->Drop(); 763 frame_->Drop();
764 break; 764 break;
765 765
(...skipping 18 matching lines...) Expand all
784 case Token::SUB: // fall through. 784 case Token::SUB: // fall through.
785 case Token::MUL: 785 case Token::MUL:
786 case Token::DIV: 786 case Token::DIV:
787 case Token::MOD: 787 case Token::MOD:
788 case Token::BIT_OR: 788 case Token::BIT_OR:
789 case Token::BIT_AND: 789 case Token::BIT_AND:
790 case Token::BIT_XOR: 790 case Token::BIT_XOR:
791 case Token::SHL: 791 case Token::SHL:
792 case Token::SHR: 792 case Token::SHR:
793 case Token::SAR: { 793 case Token::SAR: {
794 frame_->PopToR1R0(); // Pop y to r0 and x to r1. 794 Register rhs = frame_->PopToRegister();
795 Register lhs = frame_->PopToRegister(rhs); // Don't pop to rhs register.
795 { 796 {
796 VirtualFrame::SpilledScope spilled_scope(frame_); 797 VirtualFrame::SpilledScope spilled_scope(frame_);
797 GenericBinaryOpStub stub(op, overwrite_mode, constant_rhs); 798 GenericBinaryOpStub stub(op, overwrite_mode, lhs, rhs, constant_rhs);
798 frame_->CallStub(&stub, 0); 799 frame_->CallStub(&stub, 0);
799 } 800 }
800 frame_->EmitPush(r0); 801 frame_->EmitPush(r0);
801 break; 802 break;
802 } 803 }
803 804
804 case Token::COMMA: { 805 case Token::COMMA: {
805 Register scratch = frame_->PopToRegister(); 806 Register scratch = frame_->PopToRegister();
806 // Simply discard left value. 807 // Simply discard left value.
807 frame_->Drop(); 808 frame_->Drop();
(...skipping 29 matching lines...) Expand all
837 private: 838 private:
838 Token::Value op_; 839 Token::Value op_;
839 int value_; 840 int value_;
840 bool reversed_; 841 bool reversed_;
841 OverwriteMode overwrite_mode_; 842 OverwriteMode overwrite_mode_;
842 Register tos_register_; 843 Register tos_register_;
843 }; 844 };
844 845
845 846
846 void DeferredInlineSmiOperation::Generate() { 847 void DeferredInlineSmiOperation::Generate() {
848 Register lhs = r1;
849 Register rhs = r0;
847 switch (op_) { 850 switch (op_) {
848 case Token::ADD: { 851 case Token::ADD: {
849 // Revert optimistic add. 852 // Revert optimistic add.
850 if (reversed_) { 853 if (reversed_) {
851 __ sub(r0, tos_register_, Operand(Smi::FromInt(value_))); 854 __ sub(r0, tos_register_, Operand(Smi::FromInt(value_)));
852 __ mov(r1, Operand(Smi::FromInt(value_))); 855 __ mov(r1, Operand(Smi::FromInt(value_)));
853 } else { 856 } else {
854 __ sub(r1, tos_register_, Operand(Smi::FromInt(value_))); 857 __ sub(r1, tos_register_, Operand(Smi::FromInt(value_)));
855 __ mov(r0, Operand(Smi::FromInt(value_))); 858 __ mov(r0, Operand(Smi::FromInt(value_)));
856 } 859 }
(...skipping 13 matching lines...) Expand all
870 } 873 }
871 874
872 // For these operations there is no optimistic operation that needs to be 875 // For these operations there is no optimistic operation that needs to be
873 // reverted. 876 // reverted.
874 case Token::MUL: 877 case Token::MUL:
875 case Token::MOD: 878 case Token::MOD:
876 case Token::BIT_OR: 879 case Token::BIT_OR:
877 case Token::BIT_XOR: 880 case Token::BIT_XOR:
878 case Token::BIT_AND: { 881 case Token::BIT_AND: {
879 if (reversed_) { 882 if (reversed_) {
880 __ Move(r0, tos_register_); 883 if (tos_register_.is(r0)) {
881 __ mov(r1, Operand(Smi::FromInt(value_))); 884 __ mov(r1, Operand(Smi::FromInt(value_)));
885 } else {
886 ASSERT(tos_register_.is(r1));
887 __ mov(r0, Operand(Smi::FromInt(value_)));
888 lhs = r0;
889 rhs = r1;
890 }
882 } else { 891 } else {
883 __ Move(r1, tos_register_); 892 if (tos_register_.is(r1)) {
884 __ mov(r0, Operand(Smi::FromInt(value_))); 893 __ mov(r0, Operand(Smi::FromInt(value_)));
894 } else {
895 ASSERT(tos_register_.is(r0));
896 __ mov(r1, Operand(Smi::FromInt(value_)));
897 lhs = r0;
898 rhs = r1;
899 }
885 } 900 }
886 break; 901 break;
887 } 902 }
888 903
889 case Token::SHL: 904 case Token::SHL:
890 case Token::SHR: 905 case Token::SHR:
891 case Token::SAR: { 906 case Token::SAR: {
892 if (!reversed_) { 907 if (!reversed_) {
893 __ Move(r1, tos_register_); 908 if (tos_register_.is(r1)) {
894 __ mov(r0, Operand(Smi::FromInt(value_))); 909 __ mov(r0, Operand(Smi::FromInt(value_)));
910 } else {
911 ASSERT(tos_register_.is(r0));
912 __ mov(r1, Operand(Smi::FromInt(value_)));
913 lhs = r0;
914 rhs = r1;
915 }
895 } else { 916 } else {
896 UNREACHABLE(); // Should have been handled in SmiOperation. 917 UNREACHABLE(); // Should have been handled in SmiOperation.
897 } 918 }
898 break; 919 break;
899 } 920 }
900 921
901 default: 922 default:
902 // Other cases should have been handled before this point. 923 // Other cases should have been handled before this point.
903 UNREACHABLE(); 924 UNREACHABLE();
904 break; 925 break;
905 } 926 }
906 927
907 GenericBinaryOpStub stub(op_, overwrite_mode_, value_); 928 GenericBinaryOpStub stub(op_, overwrite_mode_, lhs, rhs, value_);
908 __ CallStub(&stub); 929 __ CallStub(&stub);
909 // The generic stub returns its value in r0, but that's not 930 // The generic stub returns its value in r0, but that's not
910 // necessarily what we want. We want whatever the inlined code 931 // necessarily what we want. We want whatever the inlined code
911 // expected, which is that the answer is in the same register as 932 // expected, which is that the answer is in the same register as
912 // the operand was. 933 // the operand was.
913 __ Move(tos_register_, r0); 934 __ Move(tos_register_, r0);
914 } 935 }
915 936
916 937
917 static bool PopCountLessThanEqual2(unsigned int x) { 938 static bool PopCountLessThanEqual2(unsigned int x) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 break; 999 break;
979 } 1000 }
980 default: { 1001 default: {
981 something_to_inline = false; 1002 something_to_inline = false;
982 break; 1003 break;
983 } 1004 }
984 } 1005 }
985 1006
986 if (!something_to_inline) { 1007 if (!something_to_inline) {
987 if (!reversed) { 1008 if (!reversed) {
988 // Move the lhs to r1. 1009 Register rhs = frame_->GetTOSRegister();
989 frame_->PopToR1(); 1010 __ mov(rhs, Operand(value));
990 // Flush any other registers to the stack. 1011 frame_->EmitPush(rhs);
991 frame_->SpillAll();
992 // Tell the virtual frame that TOS is in r1 (no code emitted).
993 frame_->EmitPush(r1);
994 // We know that r0 is free.
995 __ mov(r0, Operand(value));
996 // Push r0 on the virtual frame (no code emitted).
997 frame_->EmitPush(r0);
998 // This likes having r1 and r0 on top of the stack. It pushes
999 // the answer on the virtual frame.
1000 VirtualFrameBinaryOperation(op, mode, int_value); 1012 VirtualFrameBinaryOperation(op, mode, int_value);
1001 } else { 1013 } else {
1002 // Move the rhs to r0. 1014 // Move the rhs to r0.
Søren Thygesen Gjesse 2010/04/09 13:22:36 Does this comment still hold?
1003 frame_->PopToR0(); 1015 Register lhs = frame_->GetTOSRegister(); // Get reg for pushing.
1004 // Flush any other registers to the stack. 1016 Register rhs = frame_->PopToRegister(lhs); // Don't use lhs for this.
1005 frame_->SpillAll(); 1017 __ mov(lhs, Operand(value));
1006 // We know that r1 is free. 1018 frame_->EmitPush(lhs);
1007 __ mov(r1, Operand(value)); 1019 frame_->EmitPush(rhs);
1008 // Tell the virtual frame that TOS is in r1 (no code emitted).
1009 frame_->EmitPush(r1);
1010 // Push r0 on the virtual frame (no code emitted).
1011 frame_->EmitPush(r0);
1012 // This likes having r1 and r0 on top of the stack. It pushes
1013 // the answer on the virtual frame.
1014 VirtualFrameBinaryOperation(op, mode, kUnknownIntValue); 1020 VirtualFrameBinaryOperation(op, mode, kUnknownIntValue);
1015 } 1021 }
1016 return; 1022 return;
1017 } 1023 }
1018 1024
1019 // We move the top of stack to a register (normally no move is invoved). 1025 // We move the top of stack to a register (normally no move is invoved).
1020 Register tos = frame_->PopToRegister(); 1026 Register tos = frame_->PopToRegister();
1021 // All other registers are spilled. The deferred code expects one argument 1027 // All other registers are spilled. The deferred code expects one argument
1022 // in a register and all other values are flushed to the stack. The 1028 // in a register and all other values are flushed to the stack. The
1023 // answer is returned in the same register that the top of stack argument was 1029 // answer is returned in the same register that the top of stack argument was
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 DeferredCode* deferred = 1090 DeferredCode* deferred =
1085 new DeferredInlineSmiOperation(op, shift_value, false, mode, tos); 1091 new DeferredInlineSmiOperation(op, shift_value, false, mode, tos);
1086 __ tst(tos, Operand(kSmiTagMask)); 1092 __ tst(tos, Operand(kSmiTagMask));
1087 deferred->Branch(ne); 1093 deferred->Branch(ne);
1088 __ mov(scratch, Operand(tos, ASR, kSmiTagSize)); // remove tags 1094 __ mov(scratch, Operand(tos, ASR, kSmiTagSize)); // remove tags
1089 switch (op) { 1095 switch (op) {
1090 case Token::SHL: { 1096 case Token::SHL: {
1091 if (shift_value != 0) { 1097 if (shift_value != 0) {
1092 __ mov(scratch, Operand(scratch, LSL, shift_value)); 1098 __ mov(scratch, Operand(scratch, LSL, shift_value));
1093 } 1099 }
1094 // check that the *unsigned* result fits in a smi 1100 // check that the *signed* result fits in a smi
1095 __ add(scratch2, scratch, Operand(0x40000000), SetCC); 1101 __ add(scratch2, scratch, Operand(0x40000000), SetCC);
1096 deferred->Branch(mi); 1102 deferred->Branch(mi);
1097 break; 1103 break;
1098 } 1104 }
1099 case Token::SHR: { 1105 case Token::SHR: {
1100 // LSR by immediate 0 means shifting 32 bits. 1106 // LSR by immediate 0 means shifting 32 bits.
1101 if (shift_value != 0) { 1107 if (shift_value != 0) {
1102 __ mov(scratch, Operand(scratch, LSR, shift_value)); 1108 __ mov(scratch, Operand(scratch, LSR, shift_value));
1103 } 1109 }
1104 // check that the *unsigned* result fits in a smi 1110 // check that the *unsigned* result fits in a smi
1105 // neither of the two high-order bits can be set: 1111 // neither of the two high-order bits can be set:
1106 // - 0x80000000: high bit would be lost when smi tagging 1112 // - 0x80000000: high bit would be lost when smi tagging
1107 // - 0x40000000: this number would convert to negative when 1113 // - 0x40000000: this number would convert to negative when
1108 // smi tagging these two cases can only happen with shifts 1114 // smi tagging these two cases can only happen with shifts
1109 // by 0 or 1 when handed a valid smi 1115 // by 0 or 1 when handed a valid smi
1110 __ and_(scratch2, scratch, Operand(0xc0000000), SetCC); 1116 __ tst(scratch, Operand(0xc0000000));
1111 deferred->Branch(ne); 1117 deferred->Branch(ne);
1112 break; 1118 break;
1113 } 1119 }
1114 case Token::SAR: { 1120 case Token::SAR: {
1115 if (shift_value != 0) { 1121 if (shift_value != 0) {
1116 // ASR by immediate 0 means shifting 32 bits. 1122 // ASR by immediate 0 means shifting 32 bits.
1117 __ mov(scratch, Operand(scratch, ASR, shift_value)); 1123 __ mov(scratch, Operand(scratch, ASR, shift_value));
1118 } 1124 }
1119 break; 1125 break;
1120 } 1126 }
(...skipping 4652 matching lines...) Expand 10 before | Expand all | Expand 10 after
5773 __ InvokeBuiltin(native, JUMP_JS); 5779 __ InvokeBuiltin(native, JUMP_JS);
5774 } 5780 }
5775 5781
5776 5782
5777 // We fall into this code if the operands were Smis, but the result was 5783 // We fall into this code if the operands were Smis, but the result was
5778 // not (eg. overflow). We branch into this code (to the not_smi label) if 5784 // not (eg. overflow). We branch into this code (to the not_smi label) if
5779 // the operands were not both Smi. The operands are in r0 and r1. In order 5785 // the operands were not both Smi. The operands are in r0 and r1. In order
5780 // to call the C-implemented binary fp operation routines we need to end up 5786 // to call the C-implemented binary fp operation routines we need to end up
5781 // with the double precision floating point operands in r0 and r1 (for the 5787 // with the double precision floating point operands in r0 and r1 (for the
5782 // value in r1) and r2 and r3 (for the value in r0). 5788 // value in r1) and r2 and r3 (for the value in r0).
5783 void GenericBinaryOpStub::HandleBinaryOpSlowCases(MacroAssembler* masm, 5789 void GenericBinaryOpStub::HandleBinaryOpSlowCases(
5784 Label* not_smi, 5790 MacroAssembler* masm,
5785 const Builtins::JavaScript& builtin) { 5791 Label* not_smi,
5792 Register lhs,
5793 Register rhs,
5794 const Builtins::JavaScript& builtin) {
5786 Label slow, slow_pop_2_first, do_the_call; 5795 Label slow, slow_pop_2_first, do_the_call;
5787 Label r0_is_smi, r1_is_smi, finished_loading_r0, finished_loading_r1; 5796 Label r0_is_smi, r1_is_smi, finished_loading_r0, finished_loading_r1;
5788 bool use_fp_registers = CpuFeatures::IsSupported(VFP3) && Token::MOD != op_; 5797 bool use_fp_registers = CpuFeatures::IsSupported(VFP3) && Token::MOD != op_;
5789 5798
5799 ASSERT((lhs.is(r0) && rhs.is(r1)) || lhs.is(r1) && rhs.is(r0));
5800
5790 if (ShouldGenerateSmiCode()) { 5801 if (ShouldGenerateSmiCode()) {
5791 // Smi-smi case (overflow). 5802 // Smi-smi case (overflow).
5792 // Since both are Smis there is no heap number to overwrite, so allocate. 5803 // Since both are Smis there is no heap number to overwrite, so allocate.
5793 // The new heap number is in r5. r6 and r7 are scratch. 5804 // The new heap number is in r5. r6 and r7 are scratch.
5794 __ AllocateHeapNumber(r5, r6, r7, &slow); 5805 __ AllocateHeapNumber(r5, r6, r7, &slow);
5795 5806
5796 // If we have floating point hardware, inline ADD, SUB, MUL, and DIV, 5807 // If we have floating point hardware, inline ADD, SUB, MUL, and DIV,
5797 // using registers d7 and d6 for the double values. 5808 // using registers d7 and d6 for the double values.
5798 if (use_fp_registers) { 5809 if (use_fp_registers) {
5799 CpuFeatures::Scope scope(VFP3); 5810 CpuFeatures::Scope scope(VFP3);
5800 __ mov(r7, Operand(r0, ASR, kSmiTagSize)); 5811 __ mov(r7, Operand(rhs, ASR, kSmiTagSize));
5801 __ vmov(s15, r7); 5812 __ vmov(s15, r7);
5802 __ vcvt_f64_s32(d7, s15); 5813 __ vcvt_f64_s32(d7, s15);
5803 __ mov(r7, Operand(r1, ASR, kSmiTagSize)); 5814 __ mov(r7, Operand(lhs, ASR, kSmiTagSize));
5804 __ vmov(s13, r7); 5815 __ vmov(s13, r7);
5805 __ vcvt_f64_s32(d6, s13); 5816 __ vcvt_f64_s32(d6, s13);
5806 } else { 5817 } else {
5807 // Write Smi from r0 to r3 and r2 in double format. r6 is scratch. 5818 // Write Smi from rhs to r3 and r2 in double format. r6 is scratch.
5808 __ mov(r7, Operand(r0)); 5819 __ mov(r7, Operand(rhs));
5809 ConvertToDoubleStub stub1(r3, r2, r7, r6); 5820 ConvertToDoubleStub stub1(r3, r2, r7, r6);
5810 __ push(lr); 5821 __ push(lr);
5811 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET); 5822 __ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
5812 // Write Smi from r1 to r1 and r0 in double format. r6 is scratch. 5823 // Write Smi from lhs to r1 and r0 in double format. r6 is scratch.
5813 __ mov(r7, Operand(r1)); 5824 __ mov(r7, Operand(lhs));
5814 ConvertToDoubleStub stub2(r1, r0, r7, r6); 5825 ConvertToDoubleStub stub2(r1, r0, r7, r6);
5815 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET); 5826 __ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
5816 __ pop(lr); 5827 __ pop(lr);
5817 } 5828 }
5818 __ jmp(&do_the_call); // Tail call. No return. 5829 __ jmp(&do_the_call); // Tail call. No return.
5819 } 5830 }
5820 5831
5821 // We branch here if at least one of r0 and r1 is not a Smi. 5832 // We branch here if at least one of r0 and r1 is not a Smi.
5822 __ bind(not_smi); 5833 __ bind(not_smi);
5823 5834
5835 if (lhs.is(r0)) {
5836 __ Swap(r0, r1, ip);
5837 }
5838
5824 if (ShouldGenerateFPCode()) { 5839 if (ShouldGenerateFPCode()) {
5825 if (runtime_operands_type_ == BinaryOpIC::DEFAULT) { 5840 if (runtime_operands_type_ == BinaryOpIC::DEFAULT) {
5826 switch (op_) { 5841 switch (op_) {
5827 case Token::ADD: 5842 case Token::ADD:
5828 case Token::SUB: 5843 case Token::SUB:
5829 case Token::MUL: 5844 case Token::MUL:
5830 case Token::DIV: 5845 case Token::DIV:
5831 GenerateTypeTransition(masm); 5846 GenerateTypeTransition(masm);
5832 break; 5847 break;
5833 5848
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
6130 } 6145 }
6131 __ bind(&done); 6146 __ bind(&done);
6132 } 6147 }
6133 6148
6134 // For bitwise ops where the inputs are not both Smis we here try to determine 6149 // For bitwise ops where the inputs are not both Smis we here try to determine
6135 // whether both inputs are either Smis or at least heap numbers that can be 6150 // whether both inputs are either Smis or at least heap numbers that can be
6136 // represented by a 32 bit signed value. We truncate towards zero as required 6151 // represented by a 32 bit signed value. We truncate towards zero as required
6137 // by the ES spec. If this is the case we do the bitwise op and see if the 6152 // by the ES spec. If this is the case we do the bitwise op and see if the
6138 // result is a Smi. If so, great, otherwise we try to find a heap number to 6153 // result is a Smi. If so, great, otherwise we try to find a heap number to
6139 // write the answer into (either by allocating or by overwriting). 6154 // write the answer into (either by allocating or by overwriting).
6140 // On entry the operands are in r0 and r1. On exit the answer is in r0. 6155 // On entry the operands are in lhs and rhs. On exit the answer is in r0.
6141 void GenericBinaryOpStub::HandleNonSmiBitwiseOp(MacroAssembler* masm) { 6156 void GenericBinaryOpStub::HandleNonSmiBitwiseOp(MacroAssembler* masm,
6157 Register lhs,
6158 Register rhs) {
6142 Label slow, result_not_a_smi; 6159 Label slow, result_not_a_smi;
6143 Label r0_is_smi, r1_is_smi; 6160 Label rhs_is_smi, lhs_is_smi;
6144 Label done_checking_r0, done_checking_r1; 6161 Label done_checking_rhs, done_checking_lhs;
6145 6162
6146 __ tst(r1, Operand(kSmiTagMask)); 6163 __ tst(lhs, Operand(kSmiTagMask));
6147 __ b(eq, &r1_is_smi); // It's a Smi so don't check it's a heap number. 6164 __ b(eq, &lhs_is_smi); // It's a Smi so don't check it's a heap number.
6148 __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE); 6165 __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE);
6149 __ b(ne, &slow); 6166 __ b(ne, &slow);
6150 GetInt32(masm, r1, r3, r5, r4, &slow); 6167 GetInt32(masm, lhs, r3, r5, r4, &slow);
6151 __ jmp(&done_checking_r1); 6168 __ jmp(&done_checking_lhs);
6152 __ bind(&r1_is_smi); 6169 __ bind(&lhs_is_smi);
6153 __ mov(r3, Operand(r1, ASR, 1)); 6170 __ mov(r3, Operand(lhs, ASR, 1));
6154 __ bind(&done_checking_r1); 6171 __ bind(&done_checking_lhs);
6155 6172
6156 __ tst(r0, Operand(kSmiTagMask)); 6173 __ tst(rhs, Operand(kSmiTagMask));
6157 __ b(eq, &r0_is_smi); // It's a Smi so don't check it's a heap number. 6174 __ b(eq, &rhs_is_smi); // It's a Smi so don't check it's a heap number.
6158 __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE); 6175 __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE);
6159 __ b(ne, &slow); 6176 __ b(ne, &slow);
6160 GetInt32(masm, r0, r2, r5, r4, &slow); 6177 GetInt32(masm, rhs, r2, r5, r4, &slow);
6161 __ jmp(&done_checking_r0); 6178 __ jmp(&done_checking_rhs);
6162 __ bind(&r0_is_smi); 6179 __ bind(&rhs_is_smi);
6163 __ mov(r2, Operand(r0, ASR, 1)); 6180 __ mov(r2, Operand(rhs, ASR, 1));
6164 __ bind(&done_checking_r0); 6181 __ bind(&done_checking_rhs);
6182
6183 ASSERT(((lhs.is(r0) && rhs.is(r1)) || (lhs.is(r1) && rhs.is(r0))));
6165 6184
6166 // r0 and r1: Original operands (Smi or heap numbers). 6185 // r0 and r1: Original operands (Smi or heap numbers).
6167 // r2 and r3: Signed int32 operands. 6186 // r2 and r3: Signed int32 operands.
6168 switch (op_) { 6187 switch (op_) {
6169 case Token::BIT_OR: __ orr(r2, r2, Operand(r3)); break; 6188 case Token::BIT_OR: __ orr(r2, r2, Operand(r3)); break;
6170 case Token::BIT_XOR: __ eor(r2, r2, Operand(r3)); break; 6189 case Token::BIT_XOR: __ eor(r2, r2, Operand(r3)); break;
6171 case Token::BIT_AND: __ and_(r2, r2, Operand(r3)); break; 6190 case Token::BIT_AND: __ and_(r2, r2, Operand(r3)); break;
6172 case Token::SAR: 6191 case Token::SAR:
6173 // Use only the 5 least significant bits of the shift count. 6192 // Use only the 5 least significant bits of the shift count.
6174 __ and_(r2, r2, Operand(0x1f)); 6193 __ and_(r2, r2, Operand(0x1f));
(...skipping 19 matching lines...) Expand all
6194 // check that the *signed* result fits in a smi 6213 // check that the *signed* result fits in a smi
6195 __ add(r3, r2, Operand(0x40000000), SetCC); 6214 __ add(r3, r2, Operand(0x40000000), SetCC);
6196 __ b(mi, &result_not_a_smi); 6215 __ b(mi, &result_not_a_smi);
6197 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); 6216 __ mov(r0, Operand(r2, LSL, kSmiTagSize));
6198 __ Ret(); 6217 __ Ret();
6199 6218
6200 Label have_to_allocate, got_a_heap_number; 6219 Label have_to_allocate, got_a_heap_number;
6201 __ bind(&result_not_a_smi); 6220 __ bind(&result_not_a_smi);
6202 switch (mode_) { 6221 switch (mode_) {
6203 case OVERWRITE_RIGHT: { 6222 case OVERWRITE_RIGHT: {
6204 __ tst(r0, Operand(kSmiTagMask)); 6223 __ tst(rhs, Operand(kSmiTagMask));
6205 __ b(eq, &have_to_allocate); 6224 __ b(eq, &have_to_allocate);
6206 __ mov(r5, Operand(r0)); 6225 __ mov(r5, Operand(rhs));
6207 break; 6226 break;
6208 } 6227 }
6209 case OVERWRITE_LEFT: { 6228 case OVERWRITE_LEFT: {
6210 __ tst(r1, Operand(kSmiTagMask)); 6229 __ tst(lhs, Operand(kSmiTagMask));
6211 __ b(eq, &have_to_allocate); 6230 __ b(eq, &have_to_allocate);
6212 __ mov(r5, Operand(r1)); 6231 __ mov(r5, Operand(lhs));
6213 break; 6232 break;
6214 } 6233 }
6215 case NO_OVERWRITE: { 6234 case NO_OVERWRITE: {
6216 // Get a new heap number in r5. r6 and r7 are scratch. 6235 // Get a new heap number in r5. r6 and r7 are scratch.
6217 __ AllocateHeapNumber(r5, r6, r7, &slow); 6236 __ AllocateHeapNumber(r5, r6, r7, &slow);
6218 } 6237 }
6219 default: break; 6238 default: break;
6220 } 6239 }
6221 __ bind(&got_a_heap_number); 6240 __ bind(&got_a_heap_number);
6222 // r2: Answer as signed int32. 6241 // r2: Answer as signed int32.
(...skipping 10 matching lines...) Expand all
6233 6252
6234 if (mode_ != NO_OVERWRITE) { 6253 if (mode_ != NO_OVERWRITE) {
6235 __ bind(&have_to_allocate); 6254 __ bind(&have_to_allocate);
6236 // Get a new heap number in r5. r6 and r7 are scratch. 6255 // Get a new heap number in r5. r6 and r7 are scratch.
6237 __ AllocateHeapNumber(r5, r6, r7, &slow); 6256 __ AllocateHeapNumber(r5, r6, r7, &slow);
6238 __ jmp(&got_a_heap_number); 6257 __ jmp(&got_a_heap_number);
6239 } 6258 }
6240 6259
6241 // If all else failed then we go to the runtime system. 6260 // If all else failed then we go to the runtime system.
6242 __ bind(&slow); 6261 __ bind(&slow);
6243 __ push(r1); // restore stack 6262 __ push(lhs); // restore stack
6244 __ push(r0); 6263 __ push(rhs);
6245 switch (op_) { 6264 switch (op_) {
6246 case Token::BIT_OR: 6265 case Token::BIT_OR:
6247 __ InvokeBuiltin(Builtins::BIT_OR, JUMP_JS); 6266 __ InvokeBuiltin(Builtins::BIT_OR, JUMP_JS);
6248 break; 6267 break;
6249 case Token::BIT_AND: 6268 case Token::BIT_AND:
6250 __ InvokeBuiltin(Builtins::BIT_AND, JUMP_JS); 6269 __ InvokeBuiltin(Builtins::BIT_AND, JUMP_JS);
6251 break; 6270 break;
6252 case Token::BIT_XOR: 6271 case Token::BIT_XOR:
6253 __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_JS); 6272 __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_JS);
6254 break; 6273 break;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
6364 "GenericBinaryOpStub_%s_%s%s", 6383 "GenericBinaryOpStub_%s_%s%s",
6365 op_name, 6384 op_name,
6366 overwrite_name, 6385 overwrite_name,
6367 specialized_on_rhs_ ? "_ConstantRhs" : 0); 6386 specialized_on_rhs_ ? "_ConstantRhs" : 0);
6368 return name_; 6387 return name_;
6369 } 6388 }
6370 6389
6371 6390
6372 6391
6373 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 6392 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
6374 // r1 : x 6393 // lhs_ : x
6375 // r0 : y 6394 // rhs_ : y
6376 // result : r0 6395 // r0 : result
6396
6397 Register result = r0;
6398 Register lhs = lhs_;
6399 Register rhs = rhs_;
6377 6400
Søren Thygesen Gjesse 2010/04/09 13:22:36 How about having scratch registers here as well, a
6378 // All ops need to know whether we are dealing with two Smis. Set up r2 to 6401 // All ops need to know whether we are dealing with two Smis. Set up r2 to
6379 // tell us that. 6402 // tell us that.
6380 if (ShouldGenerateSmiCode()) { 6403 if (ShouldGenerateSmiCode()) {
6381 __ orr(r2, r1, Operand(r0)); // r2 = x | y; 6404 __ orr(r2, lhs, Operand(rhs)); // r2 = x | y;
6382 } 6405 }
6383 6406
6384 switch (op_) { 6407 switch (op_) {
6385 case Token::ADD: { 6408 case Token::ADD: {
6386 Label not_smi; 6409 Label not_smi;
6387 // Fast path. 6410 // Fast path.
6388 if (ShouldGenerateSmiCode()) { 6411 if (ShouldGenerateSmiCode()) {
6389 ASSERT(kSmiTag == 0); // Adjust code below. 6412 ASSERT(kSmiTag == 0); // Adjust code below.
6413 // This code can't cope with other register allocations yet.
Søren Thygesen Gjesse 2010/04/09 13:22:36 Doesn't this assert apply for the GenericBinaryOpS
6414 ASSERT(result.is(r0) &&
6415 ((lhs.is(r0) && rhs.is(r1)) ||
6416 (lhs.is(r1) && rhs.is(r0))));
6390 __ tst(r2, Operand(kSmiTagMask)); 6417 __ tst(r2, Operand(kSmiTagMask));
6391 __ b(ne, &not_smi); 6418 __ b(ne, &not_smi);
6392 __ add(r0, r1, Operand(r0), SetCC); // Add y optimistically. 6419 __ add(r0, r1, Operand(r0), SetCC); // Add y optimistically.
6393 // Return if no overflow. 6420 // Return if no overflow.
6394 __ Ret(vc); 6421 __ Ret(vc);
6395 __ sub(r0, r0, Operand(r1)); // Revert optimistic add. 6422 __ sub(r0, r0, Operand(r1)); // Revert optimistic add.
6396 } 6423 }
6397 HandleBinaryOpSlowCases(masm, &not_smi, Builtins::ADD); 6424 HandleBinaryOpSlowCases(masm, &not_smi, lhs, rhs, Builtins::ADD);
6398 break; 6425 break;
6399 } 6426 }
6400 6427
6401 case Token::SUB: { 6428 case Token::SUB: {
6402 Label not_smi; 6429 Label not_smi;
6403 // Fast path. 6430 // Fast path.
6404 if (ShouldGenerateSmiCode()) { 6431 if (ShouldGenerateSmiCode()) {
6405 ASSERT(kSmiTag == 0); // Adjust code below. 6432 ASSERT(kSmiTag == 0); // Adjust code below.
6433 // This code can't cope with other register allocations yet.
Søren Thygesen Gjesse 2010/04/09 13:22:36 Ditto.
6434 ASSERT(result.is(r0) &&
6435 ((lhs.is(r0) && rhs.is(r1)) ||
6436 (lhs.is(r1) && rhs.is(r0))));
6406 __ tst(r2, Operand(kSmiTagMask)); 6437 __ tst(r2, Operand(kSmiTagMask));
6407 __ b(ne, &not_smi); 6438 __ b(ne, &not_smi);
6408 __ sub(r0, r1, Operand(r0), SetCC); // Subtract y optimistically. 6439 if (lhs.is(r1)) {
Søren Thygesen Gjesse 2010/04/09 13:22:36 Can't you just drop the if/else and use: __ sub(r
6409 // Return if no overflow. 6440 __ sub(r0, r1, Operand(r0), SetCC); // Subtract y optimistically.
6410 __ Ret(vc); 6441 // Return if no overflow.
6411 __ sub(r0, r1, Operand(r0)); // Revert optimistic subtract. 6442 __ Ret(vc);
6443 __ sub(r0, r1, Operand(r0)); // Revert optimistic subtract.
6444 } else {
6445 __ sub(r0, r0, Operand(r1), SetCC); // Subtract y optimistically.
6446 // Return if no overflow.
6447 __ Ret(vc);
6448 __ add(r0, r0, Operand(r1)); // Revert optimistic subtract.
6449 }
6412 } 6450 }
6413 HandleBinaryOpSlowCases(masm, &not_smi, Builtins::SUB); 6451 HandleBinaryOpSlowCases(masm, &not_smi, lhs, rhs, Builtins::SUB);
6414 break; 6452 break;
6415 } 6453 }
6416 6454
6417 case Token::MUL: { 6455 case Token::MUL: {
6418 Label not_smi, slow; 6456 Label not_smi, slow;
6419 if (ShouldGenerateSmiCode()) { 6457 if (ShouldGenerateSmiCode()) {
6420 ASSERT(kSmiTag == 0); // adjust code below 6458 ASSERT(kSmiTag == 0); // adjust code below
6421 __ tst(r2, Operand(kSmiTagMask)); 6459 __ tst(r2, Operand(kSmiTagMask));
6422 __ b(ne, &not_smi); 6460 __ b(ne, &not_smi);
6423 // Remove tag from one operand (but keep sign), so that result is Smi. 6461 // Remove tag from one operand (but keep sign), so that result is Smi.
6424 __ mov(ip, Operand(r0, ASR, kSmiTagSize)); 6462 __ mov(ip, Operand(rhs, ASR, kSmiTagSize));
6425 // Do multiplication 6463 // Do multiplication
6426 __ smull(r3, r2, r1, ip); // r3 = lower 32 bits of ip*r1. 6464 __ smull(r3, r2, lhs, ip); // r3 = lower 32 bits of ip*r1.
6427 // Go slow on overflows (overflow bit is not set). 6465 // Go slow on overflows (overflow bit is not set).
6428 __ mov(ip, Operand(r3, ASR, 31)); 6466 __ mov(ip, Operand(r3, ASR, 31));
6429 __ cmp(ip, Operand(r2)); // no overflow if higher 33 bits are identical 6467 __ cmp(ip, Operand(r2)); // no overflow if higher 33 bits are identical
6430 __ b(ne, &slow); 6468 __ b(ne, &slow);
6431 // Go slow on zero result to handle -0. 6469 // Go slow on zero result to handle -0.
6432 __ tst(r3, Operand(r3)); 6470 __ tst(r3, Operand(r3));
6433 __ mov(r0, Operand(r3), LeaveCC, ne); 6471 __ mov(result, Operand(r3), LeaveCC, ne);
6434 __ Ret(ne); 6472 __ Ret(ne);
6435 // We need -0 if we were multiplying a negative number with 0 to get 0. 6473 // We need -0 if we were multiplying a negative number with 0 to get 0.
6436 // We know one of them was zero. 6474 // We know one of them was zero.
6437 __ add(r2, r0, Operand(r1), SetCC); 6475 __ add(r2, rhs, Operand(lhs), SetCC);
6438 __ mov(r0, Operand(Smi::FromInt(0)), LeaveCC, pl); 6476 __ mov(result, Operand(Smi::FromInt(0)), LeaveCC, pl);
6439 __ Ret(pl); // Return Smi 0 if the non-zero one was positive. 6477 __ Ret(pl); // Return Smi 0 if the non-zero one was positive.
6440 // Slow case. We fall through here if we multiplied a negative number 6478 // Slow case. We fall through here if we multiplied a negative number
6441 // with 0, because that would mean we should produce -0. 6479 // with 0, because that would mean we should produce -0.
6442 __ bind(&slow); 6480 __ bind(&slow);
6443 } 6481 }
6444 HandleBinaryOpSlowCases(masm, &not_smi, Builtins::MUL); 6482 HandleBinaryOpSlowCases(masm, &not_smi, lhs, rhs, Builtins::MUL);
6445 break; 6483 break;
6446 } 6484 }
6447 6485
6448 case Token::DIV: 6486 case Token::DIV:
6449 case Token::MOD: { 6487 case Token::MOD: {
6450 Label not_smi; 6488 Label not_smi;
6451 if (ShouldGenerateSmiCode()) { 6489 if (ShouldGenerateSmiCode() && specialized_on_rhs_) {
6452 Label smi_is_unsuitable; 6490 Label smi_is_unsuitable;
6453 __ BranchOnNotSmi(r1, &not_smi); 6491 __ BranchOnNotSmi(lhs, &not_smi);
6454 if (IsPowerOf2(constant_rhs_)) { 6492 if (IsPowerOf2(constant_rhs_)) {
6455 if (op_ == Token::MOD) { 6493 if (op_ == Token::MOD) {
6456 __ and_(r0, 6494 __ and_(rhs,
6457 r1, 6495 lhs,
6458 Operand(0x80000000u | ((constant_rhs_ << kSmiTagSize) - 1)), 6496 Operand(0x80000000u | ((constant_rhs_ << kSmiTagSize) - 1)),
6459 SetCC); 6497 SetCC);
6460 // We now have the answer, but if the input was negative we also 6498 // We now have the answer, but if the input was negative we also
6461 // have the sign bit. Our work is done if the result is 6499 // have the sign bit. Our work is done if the result is
6462 // positive or zero: 6500 // positive or zero:
6501 if (!rhs.is(r0)) {
6502 __ mov(r0, rhs, LeaveCC, pl);
6503 }
6463 __ Ret(pl); 6504 __ Ret(pl);
6464 // A mod of a negative left hand side must return a negative number. 6505 // A mod of a negative left hand side must return a negative number.
6465 // Unfortunately if the answer is 0 then we must return -0. And we 6506 // Unfortunately if the answer is 0 then we must return -0. And we
6466 // already optimistically trashed r0 so we may need to restore it. 6507 // already optimistically trashed rhs so we may need to restore it.
6467 __ eor(r0, r0, Operand(0x80000000u), SetCC); 6508 __ eor(rhs, rhs, Operand(0x80000000u), SetCC);
6468 // Next two instructions are conditional on the answer being -0. 6509 // Next two instructions are conditional on the answer being -0.
6469 __ mov(r0, Operand(Smi::FromInt(constant_rhs_)), LeaveCC, eq); 6510 __ mov(rhs, Operand(Smi::FromInt(constant_rhs_)), LeaveCC, eq);
6470 __ b(eq, &smi_is_unsuitable); 6511 __ b(eq, &smi_is_unsuitable);
6471 // We need to subtract the dividend. Eg. -3 % 4 == -3. 6512 // We need to subtract the dividend. Eg. -3 % 4 == -3.
6472 __ sub(r0, r0, Operand(Smi::FromInt(constant_rhs_))); 6513 __ sub(result, rhs, Operand(Smi::FromInt(constant_rhs_)));
6473 } else { 6514 } else {
6474 ASSERT(op_ == Token::DIV); 6515 ASSERT(op_ == Token::DIV);
6475 __ tst(r1, 6516 __ tst(lhs,
6476 Operand(0x80000000u | ((constant_rhs_ << kSmiTagSize) - 1))); 6517 Operand(0x80000000u | ((constant_rhs_ << kSmiTagSize) - 1)));
6477 __ b(ne, &smi_is_unsuitable); // Go slow on negative or remainder. 6518 __ b(ne, &smi_is_unsuitable); // Go slow on negative or remainder.
6478 int shift = 0; 6519 int shift = 0;
6479 int d = constant_rhs_; 6520 int d = constant_rhs_;
6480 while ((d & 1) == 0) { 6521 while ((d & 1) == 0) {
6481 d >>= 1; 6522 d >>= 1;
6482 shift++; 6523 shift++;
6483 } 6524 }
6484 __ mov(r0, Operand(r1, LSR, shift)); 6525 __ mov(r0, Operand(lhs, LSR, shift));
6485 __ bic(r0, r0, Operand(kSmiTagMask)); 6526 __ bic(r0, r0, Operand(kSmiTagMask));
6486 } 6527 }
6487 } else { 6528 } else {
6488 // Not a power of 2. 6529 // Not a power of 2.
6489 __ tst(r1, Operand(0x80000000u)); 6530 __ tst(lhs, Operand(0x80000000u));
6490 __ b(ne, &smi_is_unsuitable); 6531 __ b(ne, &smi_is_unsuitable);
6491 // Find a fixed point reciprocal of the divisor so we can divide by 6532 // Find a fixed point reciprocal of the divisor so we can divide by
6492 // multiplying. 6533 // multiplying.
6493 double divisor = 1.0 / constant_rhs_; 6534 double divisor = 1.0 / constant_rhs_;
6494 int shift = 32; 6535 int shift = 32;
6495 double scale = 4294967296.0; // 1 << 32. 6536 double scale = 4294967296.0; // 1 << 32.
6496 uint32_t mul; 6537 uint32_t mul;
6497 // Maximise the precision of the fixed point reciprocal. 6538 // Maximise the precision of the fixed point reciprocal.
6498 while (true) { 6539 while (true) {
6499 mul = static_cast<uint32_t>(scale * divisor); 6540 mul = static_cast<uint32_t>(scale * divisor);
6500 if (mul >= 0x7fffffff) break; 6541 if (mul >= 0x7fffffff) break;
6501 scale *= 2.0; 6542 scale *= 2.0;
6502 shift++; 6543 shift++;
6503 } 6544 }
6504 mul++; 6545 mul++;
6505 __ mov(r2, Operand(mul)); 6546 __ mov(r2, Operand(mul));
6506 __ umull(r3, r2, r2, r1); 6547 __ umull(r3, r2, r2, lhs);
6507 __ mov(r2, Operand(r2, LSR, shift - 31)); 6548 __ mov(r2, Operand(r2, LSR, shift - 31));
6508 // r2 is r1 / rhs. r2 is not Smi tagged. 6549 // r2 is lhs / rhs. r2 is not Smi tagged.
6509 // r0 is still the known rhs. r0 is Smi tagged. 6550 // rhs is still the known rhs. rhs is Smi tagged.
6510 // r1 is still the unkown lhs. r1 is Smi tagged. 6551 // lhs is still the unkown lhs. lhs is Smi tagged.
6511 int required_r4_shift = 0; // Including the Smi tag shift of 1. 6552 int required_r4_shift = 0; // Including the Smi tag shift of 1.
6512 // r4 = r2 * r0. 6553 // r4 = r2 * rhs.
6513 MultiplyByKnownInt2(masm, 6554 MultiplyByKnownInt2(masm,
6514 r4, 6555 r4,
6515 r2, 6556 r2,
6516 r0, 6557 rhs,
6517 constant_rhs_, 6558 constant_rhs_,
6518 &required_r4_shift); 6559 &required_r4_shift);
6519 // r4 << required_r4_shift is now the Smi tagged rhs * (r1 / rhs). 6560 // r4 << required_r4_shift is now the Smi tagged rhs * (r1 / rhs).
6520 if (op_ == Token::DIV) { 6561 if (op_ == Token::DIV) {
6521 __ sub(r3, r1, Operand(r4, LSL, required_r4_shift), SetCC); 6562 __ sub(r3, lhs, Operand(r4, LSL, required_r4_shift), SetCC);
6522 __ b(ne, &smi_is_unsuitable); // There was a remainder. 6563 __ b(ne, &smi_is_unsuitable); // There was a remainder.
6523 __ mov(r0, Operand(r2, LSL, kSmiTagSize)); 6564 __ mov(result, Operand(r2, LSL, kSmiTagSize));
6524 } else { 6565 } else {
6525 ASSERT(op_ == Token::MOD); 6566 ASSERT(op_ == Token::MOD);
6526 __ sub(r0, r1, Operand(r4, LSL, required_r4_shift)); 6567 __ sub(result, lhs, Operand(r4, LSL, required_r4_shift));
6527 } 6568 }
6528 } 6569 }
6529 __ Ret(); 6570 __ Ret();
6530 __ bind(&smi_is_unsuitable); 6571 __ bind(&smi_is_unsuitable);
6531 } 6572 }
6532 HandleBinaryOpSlowCases( 6573 HandleBinaryOpSlowCases(
6533 masm, 6574 masm,
6534 &not_smi, 6575 &not_smi,
6576 lhs,
6577 rhs,
6535 op_ == Token::MOD ? Builtins::MOD : Builtins::DIV); 6578 op_ == Token::MOD ? Builtins::MOD : Builtins::DIV);
6536 break; 6579 break;
6537 } 6580 }
6538 6581
6539 case Token::BIT_OR: 6582 case Token::BIT_OR:
6540 case Token::BIT_AND: 6583 case Token::BIT_AND:
6541 case Token::BIT_XOR: 6584 case Token::BIT_XOR:
6542 case Token::SAR: 6585 case Token::SAR:
6543 case Token::SHR: 6586 case Token::SHR:
6544 case Token::SHL: { 6587 case Token::SHL: {
6545 Label slow; 6588 Label slow;
6546 ASSERT(kSmiTag == 0); // adjust code below 6589 ASSERT(kSmiTag == 0); // adjust code below
6547 __ tst(r2, Operand(kSmiTagMask)); 6590 __ tst(r2, Operand(kSmiTagMask));
6548 __ b(ne, &slow); 6591 __ b(ne, &slow);
6549 switch (op_) { 6592 switch (op_) {
6550 case Token::BIT_OR: __ orr(r0, r0, Operand(r1)); break; 6593 case Token::BIT_OR: __ orr(result, rhs, Operand(lhs)); break;
6551 case Token::BIT_AND: __ and_(r0, r0, Operand(r1)); break; 6594 case Token::BIT_AND: __ and_(result, rhs, Operand(lhs)); break;
6552 case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break; 6595 case Token::BIT_XOR: __ eor(result, rhs, Operand(lhs)); break;
6553 case Token::SAR: 6596 case Token::SAR:
6554 // Remove tags from right operand. 6597 // Remove tags from right operand.
6555 __ GetLeastBitsFromSmi(r2, r0, 5); 6598 __ GetLeastBitsFromSmi(r2, rhs, 5);
6556 __ mov(r0, Operand(r1, ASR, r2)); 6599 __ mov(result, Operand(lhs, ASR, r2));
6557 // Smi tag result. 6600 // Smi tag result.
6558 __ bic(r0, r0, Operand(kSmiTagMask)); 6601 __ bic(result, result, Operand(kSmiTagMask));
6559 break; 6602 break;
6560 case Token::SHR: 6603 case Token::SHR:
6561 // Remove tags from operands. We can't do this on a 31 bit number 6604 // Remove tags from operands. We can't do this on a 31 bit number
6562 // because then the 0s get shifted into bit 30 instead of bit 31. 6605 // because then the 0s get shifted into bit 30 instead of bit 31.
6563 __ mov(r3, Operand(r1, ASR, kSmiTagSize)); // x 6606 __ mov(r3, Operand(lhs, ASR, kSmiTagSize)); // x
6564 __ GetLeastBitsFromSmi(r2, r0, 5); 6607 __ GetLeastBitsFromSmi(r2, rhs, 5);
6565 __ mov(r3, Operand(r3, LSR, r2)); 6608 __ mov(r3, Operand(r3, LSR, r2));
6566 // Unsigned shift is not allowed to produce a negative number, so 6609 // Unsigned shift is not allowed to produce a negative number, so
6567 // check the sign bit and the sign bit after Smi tagging. 6610 // check the sign bit and the sign bit after Smi tagging.
6568 __ tst(r3, Operand(0xc0000000)); 6611 __ tst(r3, Operand(0xc0000000));
6569 __ b(ne, &slow); 6612 __ b(ne, &slow);
6570 // Smi tag result. 6613 // Smi tag result.
6571 __ mov(r0, Operand(r3, LSL, kSmiTagSize)); 6614 __ mov(result, Operand(r3, LSL, kSmiTagSize));
6572 break; 6615 break;
6573 case Token::SHL: 6616 case Token::SHL:
6574 // Remove tags from operands. 6617 // Remove tags from operands.
6575 __ mov(r3, Operand(r1, ASR, kSmiTagSize)); // x 6618 __ mov(r3, Operand(lhs, ASR, kSmiTagSize)); // x
6576 __ GetLeastBitsFromSmi(r2, r0, 5); 6619 __ GetLeastBitsFromSmi(r2, rhs, 5);
6577 __ mov(r3, Operand(r3, LSL, r2)); 6620 __ mov(r3, Operand(r3, LSL, r2));
6578 // Check that the signed result fits in a Smi. 6621 // Check that the signed result fits in a Smi.
6579 __ add(r2, r3, Operand(0x40000000), SetCC); 6622 __ add(r2, r3, Operand(0x40000000), SetCC);
6580 __ b(mi, &slow); 6623 __ b(mi, &slow);
6581 __ mov(r0, Operand(r3, LSL, kSmiTagSize)); 6624 __ mov(result, Operand(r3, LSL, kSmiTagSize));
6582 break; 6625 break;
6583 default: UNREACHABLE(); 6626 default: UNREACHABLE();
6584 } 6627 }
6585 __ Ret(); 6628 __ Ret();
6586 __ bind(&slow); 6629 __ bind(&slow);
6587 HandleNonSmiBitwiseOp(masm); 6630 HandleNonSmiBitwiseOp(masm, lhs, rhs);
6588 break; 6631 break;
6589 } 6632 }
6590 6633
6591 default: UNREACHABLE(); 6634 default: UNREACHABLE();
6592 } 6635 }
6593 // This code should be unreachable. 6636 // This code should be unreachable.
6594 __ stop("Unreachable"); 6637 __ stop("Unreachable");
6595 6638
6596 // Generate an unreachable reference to the DEFAULT stub so that it can be 6639 // Generate an unreachable reference to the DEFAULT stub so that it can be
6597 // found at the end of this stub when clearing ICs at GC. 6640 // found at the end of this stub when clearing ICs at GC.
(...skipping 1731 matching lines...) Expand 10 before | Expand all | Expand 10 after
8329 8372
8330 // Just jump to runtime to add the two strings. 8373 // Just jump to runtime to add the two strings.
8331 __ bind(&string_add_runtime); 8374 __ bind(&string_add_runtime);
8332 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 8375 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
8333 } 8376 }
8334 8377
8335 8378
8336 #undef __ 8379 #undef __
8337 8380
8338 } } // namespace v8::internal 8381 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/full-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698