| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_ASSEMBLER_MIPS_H_ | 5 #ifndef VM_ASSEMBLER_MIPS_H_ |
| 6 #define VM_ASSEMBLER_MIPS_H_ | 6 #define VM_ASSEMBLER_MIPS_H_ |
| 7 | 7 |
| 8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_mips.h directly; use assembler.h instead. | 9 #error Do not include assembler_mips.h directly; use assembler.h instead. |
| 10 #endif | 10 #endif |
| (...skipping 750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 // from the other registers is needed. | 761 // from the other registers is needed. |
| 762 void AdduDetectOverflow(Register rd, Register rs, Register rt, Register ro, | 762 void AdduDetectOverflow(Register rd, Register rs, Register rt, Register ro, |
| 763 Register scratch = kNoRegister); | 763 Register scratch = kNoRegister); |
| 764 | 764 |
| 765 // ro must be different from rd and rs. | 765 // ro must be different from rd and rs. |
| 766 // rd and ro must not be TMP. | 766 // rd and ro must not be TMP. |
| 767 // If rd and rs are the same, a scratch register different from the other | 767 // If rd and rs are the same, a scratch register different from the other |
| 768 // registers is needed. | 768 // registers is needed. |
| 769 void AddImmediateDetectOverflow(Register rd, Register rs, int32_t imm, | 769 void AddImmediateDetectOverflow(Register rd, Register rs, int32_t imm, |
| 770 Register ro, Register scratch = kNoRegister) { | 770 Register ro, Register scratch = kNoRegister) { |
| 771 ASSERT(!in_delay_slot_); |
| 771 LoadImmediate(rd, imm); | 772 LoadImmediate(rd, imm); |
| 772 AdduDetectOverflow(rd, rs, rd, ro, scratch); | 773 AdduDetectOverflow(rd, rs, rd, ro, scratch); |
| 773 } | 774 } |
| 774 | 775 |
| 775 // Subtraction of rt from rs (rs - rt) with the result placed in rd. | 776 // Subtraction of rt from rs (rs - rt) with the result placed in rd. |
| 776 // After, ro < 0 if there was signed overflow, ro >= 0 otherwise. | 777 // After, ro < 0 if there was signed overflow, ro >= 0 otherwise. |
| 777 // None of rd, rs, rt, or ro may be TMP. | 778 // None of rd, rs, rt, or ro may be TMP. |
| 778 // ro must be different from the other registers. | 779 // ro must be different from the other registers. |
| 779 void SubuDetectOverflow(Register rd, Register rs, Register rt, Register ro); | 780 void SubuDetectOverflow(Register rd, Register rs, Register rt, Register ro); |
| 780 | 781 |
| 781 // ro must be different from rd and rs. | 782 // ro must be different from rd and rs. |
| 782 // None of rd, rs, rt, or ro may be TMP. | 783 // None of rd, rs, rt, or ro may be TMP. |
| 783 void SubImmediateDetectOverflow(Register rd, Register rs, int32_t imm, | 784 void SubImmediateDetectOverflow(Register rd, Register rs, int32_t imm, |
| 784 Register ro) { | 785 Register ro) { |
| 786 ASSERT(!in_delay_slot_); |
| 785 LoadImmediate(rd, imm); | 787 LoadImmediate(rd, imm); |
| 786 SubuDetectOverflow(rd, rs, rd, ro); | 788 SubuDetectOverflow(rd, rs, rd, ro); |
| 787 } | 789 } |
| 788 | 790 |
| 789 void Branch(const ExternalLabel* label) { | 791 void Branch(const ExternalLabel* label) { |
| 792 ASSERT(!in_delay_slot_); |
| 790 LoadImmediate(TMP, label->address()); | 793 LoadImmediate(TMP, label->address()); |
| 791 jr(TMP); | 794 jr(TMP); |
| 792 } | 795 } |
| 793 | 796 |
| 794 void BranchPatchable(const ExternalLabel* label) { | 797 void BranchPatchable(const ExternalLabel* label) { |
| 798 ASSERT(!in_delay_slot_); |
| 795 const uint16_t low = Utils::Low16Bits(label->address()); | 799 const uint16_t low = Utils::Low16Bits(label->address()); |
| 796 const uint16_t high = Utils::High16Bits(label->address()); | 800 const uint16_t high = Utils::High16Bits(label->address()); |
| 797 lui(T9, Immediate(high)); | 801 lui(T9, Immediate(high)); |
| 798 ori(T9, T9, Immediate(low)); | 802 ori(T9, T9, Immediate(low)); |
| 799 jr(T9); | 803 jr(T9); |
| 800 delay_slot_available_ = false; // CodePatcher expects a nop. | 804 delay_slot_available_ = false; // CodePatcher expects a nop. |
| 801 } | 805 } |
| 802 | 806 |
| 803 void BranchLink(const ExternalLabel* label) { | 807 void BranchLink(const ExternalLabel* label) { |
| 808 ASSERT(!in_delay_slot_); |
| 804 LoadImmediate(T9, label->address()); | 809 LoadImmediate(T9, label->address()); |
| 805 jalr(T9); | 810 jalr(T9); |
| 806 } | 811 } |
| 807 | 812 |
| 808 void BranchLinkPatchable(const ExternalLabel* label) { | 813 void BranchLinkPatchable(const ExternalLabel* label) { |
| 814 ASSERT(!in_delay_slot_); |
| 809 const int32_t offset = | 815 const int32_t offset = |
| 810 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; | 816 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; |
| 811 LoadWordFromPoolOffset(T9, offset); | 817 LoadWordFromPoolOffset(T9, offset); |
| 812 jalr(T9); | 818 jalr(T9); |
| 813 delay_slot_available_ = false; // CodePatcher expects a nop. | 819 delay_slot_available_ = false; // CodePatcher expects a nop. |
| 814 } | 820 } |
| 815 | 821 |
| 816 void Drop(intptr_t stack_elements) { | 822 void Drop(intptr_t stack_elements) { |
| 817 ASSERT(stack_elements >= 0); | 823 ASSERT(stack_elements >= 0); |
| 818 if (stack_elements > 0) { | 824 if (stack_elements > 0) { |
| 819 addiu(SP, SP, Immediate(stack_elements * kWordSize)); | 825 addiu(SP, SP, Immediate(stack_elements * kWordSize)); |
| 820 } | 826 } |
| 821 } | 827 } |
| 822 | 828 |
| 823 void LoadPoolPointer() { | 829 void LoadPoolPointer() { |
| 830 ASSERT(!in_delay_slot_); |
| 824 GetNextPC(TMP); // TMP gets the address of the next instruction. | 831 GetNextPC(TMP); // TMP gets the address of the next instruction. |
| 825 const intptr_t object_pool_pc_dist = | 832 const intptr_t object_pool_pc_dist = |
| 826 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 833 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 827 CodeSize(); | 834 CodeSize(); |
| 828 lw(PP, Address(TMP, -object_pool_pc_dist)); | 835 lw(PP, Address(TMP, -object_pool_pc_dist)); |
| 829 } | 836 } |
| 830 | 837 |
| 831 void LoadImmediate(Register rd, int32_t value) { | 838 void LoadImmediate(Register rd, int32_t value) { |
| 839 ASSERT(!in_delay_slot_); |
| 832 if (Utils::IsInt(kImmBits, value)) { | 840 if (Utils::IsInt(kImmBits, value)) { |
| 833 addiu(rd, ZR, Immediate(value)); | 841 addiu(rd, ZR, Immediate(value)); |
| 834 } else { | 842 } else { |
| 835 const uint16_t low = Utils::Low16Bits(value); | 843 const uint16_t low = Utils::Low16Bits(value); |
| 836 const uint16_t high = Utils::High16Bits(value); | 844 const uint16_t high = Utils::High16Bits(value); |
| 837 lui(rd, Immediate(high)); | 845 lui(rd, Immediate(high)); |
| 838 ori(rd, rd, Immediate(low)); | 846 ori(rd, rd, Immediate(low)); |
| 839 } | 847 } |
| 840 } | 848 } |
| 841 | 849 |
| 842 void LoadImmediate(DRegister rd, double value) { | 850 void LoadImmediate(DRegister rd, double value) { |
| 851 ASSERT(!in_delay_slot_); |
| 843 FRegister frd = static_cast<FRegister>(rd * 2); | 852 FRegister frd = static_cast<FRegister>(rd * 2); |
| 844 const int64_t ival = bit_cast<uint64_t, double>(value); | 853 const int64_t ival = bit_cast<uint64_t, double>(value); |
| 845 const int32_t low = Utils::Low32Bits(ival); | 854 const int32_t low = Utils::Low32Bits(ival); |
| 846 const int32_t high = Utils::High32Bits(ival); | 855 const int32_t high = Utils::High32Bits(ival); |
| 847 if (low != 0) { | 856 if (low != 0) { |
| 848 LoadImmediate(TMP, low); | 857 LoadImmediate(TMP, low); |
| 849 mtc1(TMP, frd); | 858 mtc1(TMP, frd); |
| 850 } else { | 859 } else { |
| 851 mtc1(ZR, frd); | 860 mtc1(ZR, frd); |
| 852 } | 861 } |
| 853 | 862 |
| 854 if (high != 0) { | 863 if (high != 0) { |
| 855 LoadImmediate(TMP, high); | 864 LoadImmediate(TMP, high); |
| 856 mtc1(TMP, static_cast<FRegister>(frd + 1)); | 865 mtc1(TMP, static_cast<FRegister>(frd + 1)); |
| 857 } else { | 866 } else { |
| 858 mtc1(ZR, static_cast<FRegister>(frd + 1)); | 867 mtc1(ZR, static_cast<FRegister>(frd + 1)); |
| 859 } | 868 } |
| 860 } | 869 } |
| 861 | 870 |
| 862 void LoadImmediate(FRegister rd, float value) { | 871 void LoadImmediate(FRegister rd, float value) { |
| 872 ASSERT(!in_delay_slot_); |
| 863 const int32_t ival = bit_cast<int32_t, float>(value); | 873 const int32_t ival = bit_cast<int32_t, float>(value); |
| 864 if (ival == 0) { | 874 if (ival == 0) { |
| 865 mtc1(ZR, rd); | 875 mtc1(ZR, rd); |
| 866 } else { | 876 } else { |
| 867 LoadImmediate(TMP, ival); | 877 LoadImmediate(TMP, ival); |
| 868 mtc1(TMP, rd); | 878 mtc1(TMP, rd); |
| 869 } | 879 } |
| 870 } | 880 } |
| 871 | 881 |
| 872 void AddImmediate(Register rd, Register rs, int32_t value) { | 882 void AddImmediate(Register rd, Register rs, int32_t value) { |
| 883 ASSERT(!in_delay_slot_); |
| 873 if ((value == 0) && (rd == rs)) return; | 884 if ((value == 0) && (rd == rs)) return; |
| 874 // If value is 0, we still want to move rs to rd if they aren't the same. | 885 // If value is 0, we still want to move rs to rd if they aren't the same. |
| 875 if (Utils::IsInt(kImmBits, value)) { | 886 if (Utils::IsInt(kImmBits, value)) { |
| 876 addiu(rd, rs, Immediate(value)); | 887 addiu(rd, rs, Immediate(value)); |
| 877 } else { | 888 } else { |
| 878 LoadImmediate(TMP, value); | 889 LoadImmediate(TMP, value); |
| 879 addu(rd, rs, TMP); | 890 addu(rd, rs, TMP); |
| 880 } | 891 } |
| 881 } | 892 } |
| 882 | 893 |
| 883 void AddImmediate(Register rd, int32_t value) { | 894 void AddImmediate(Register rd, int32_t value) { |
| 895 ASSERT(!in_delay_slot_); |
| 884 AddImmediate(rd, rd, value); | 896 AddImmediate(rd, rd, value); |
| 885 } | 897 } |
| 886 | 898 |
| 887 void AndImmediate(Register rd, Register rs, int32_t imm) { | 899 void AndImmediate(Register rd, Register rs, int32_t imm) { |
| 900 ASSERT(!in_delay_slot_); |
| 888 if (imm == 0) { | 901 if (imm == 0) { |
| 889 mov(rd, ZR); | 902 mov(rd, ZR); |
| 890 return; | 903 return; |
| 891 } | 904 } |
| 892 | 905 |
| 893 if (Utils::IsUint(kImmBits, imm)) { | 906 if (Utils::IsUint(kImmBits, imm)) { |
| 894 andi(rd, rs, Immediate(imm)); | 907 andi(rd, rs, Immediate(imm)); |
| 895 } else { | 908 } else { |
| 896 LoadImmediate(TMP, imm); | 909 LoadImmediate(TMP, imm); |
| 897 and_(rd, rs, TMP); | 910 and_(rd, rs, TMP); |
| 898 } | 911 } |
| 899 } | 912 } |
| 900 | 913 |
| 901 void BranchEqual(Register rd, int32_t value, Label* l) { | 914 void BranchEqual(Register rd, int32_t value, Label* l) { |
| 915 ASSERT(!in_delay_slot_); |
| 902 if (value == 0) { | 916 if (value == 0) { |
| 903 beq(rd, ZR, l); | 917 beq(rd, ZR, l); |
| 904 } else { | 918 } else { |
| 905 ASSERT(rd != CMPRES2); | 919 ASSERT(rd != CMPRES2); |
| 906 LoadImmediate(CMPRES2, value); | 920 LoadImmediate(CMPRES2, value); |
| 907 beq(rd, CMPRES2, l); | 921 beq(rd, CMPRES2, l); |
| 908 } | 922 } |
| 909 } | 923 } |
| 910 | 924 |
| 911 void BranchEqual(Register rd, const Object& object, Label* l) { | 925 void BranchEqual(Register rd, const Object& object, Label* l) { |
| 926 ASSERT(!in_delay_slot_); |
| 912 ASSERT(rd != CMPRES2); | 927 ASSERT(rd != CMPRES2); |
| 913 LoadObject(CMPRES2, object); | 928 LoadObject(CMPRES2, object); |
| 914 beq(rd, CMPRES2, l); | 929 beq(rd, CMPRES2, l); |
| 915 } | 930 } |
| 916 | 931 |
| 917 void BranchNotEqual(Register rd, int32_t value, Label* l) { | 932 void BranchNotEqual(Register rd, int32_t value, Label* l) { |
| 933 ASSERT(!in_delay_slot_); |
| 918 if (value == 0) { | 934 if (value == 0) { |
| 919 bne(rd, ZR, l); | 935 bne(rd, ZR, l); |
| 920 } else { | 936 } else { |
| 921 ASSERT(rd != CMPRES2); | 937 ASSERT(rd != CMPRES2); |
| 922 LoadImmediate(CMPRES2, value); | 938 LoadImmediate(CMPRES2, value); |
| 923 bne(rd, CMPRES2, l); | 939 bne(rd, CMPRES2, l); |
| 924 } | 940 } |
| 925 } | 941 } |
| 926 | 942 |
| 927 void BranchNotEqual(Register rd, const Object& object, Label* l) { | 943 void BranchNotEqual(Register rd, const Object& object, Label* l) { |
| 944 ASSERT(!in_delay_slot_); |
| 928 ASSERT(rd != CMPRES2); | 945 ASSERT(rd != CMPRES2); |
| 929 LoadObject(CMPRES2, object); | 946 LoadObject(CMPRES2, object); |
| 930 bne(rd, CMPRES2, l); | 947 bne(rd, CMPRES2, l); |
| 931 } | 948 } |
| 932 | 949 |
| 933 void BranchSignedGreater(Register rd, Register rs, Label* l) { | 950 void BranchSignedGreater(Register rd, Register rs, Label* l) { |
| 951 ASSERT(!in_delay_slot_); |
| 934 slt(CMPRES2, rs, rd); // CMPRES2 = rd > rs ? 1 : 0. | 952 slt(CMPRES2, rs, rd); // CMPRES2 = rd > rs ? 1 : 0. |
| 935 bne(CMPRES2, ZR, l); | 953 bne(CMPRES2, ZR, l); |
| 936 } | 954 } |
| 937 | 955 |
| 938 void BranchSignedGreater(Register rd, int32_t value, Label* l) { | 956 void BranchSignedGreater(Register rd, int32_t value, Label* l) { |
| 957 ASSERT(!in_delay_slot_); |
| 939 if (value == 0) { | 958 if (value == 0) { |
| 940 bgtz(rd, l); | 959 bgtz(rd, l); |
| 941 } else { | 960 } else { |
| 942 ASSERT(rd != CMPRES2); | 961 ASSERT(rd != CMPRES2); |
| 943 LoadImmediate(CMPRES2, value); | 962 LoadImmediate(CMPRES2, value); |
| 944 BranchSignedGreater(rd, CMPRES2, l); | 963 BranchSignedGreater(rd, CMPRES2, l); |
| 945 } | 964 } |
| 946 } | 965 } |
| 947 | 966 |
| 948 void BranchUnsignedGreater(Register rd, Register rs, Label* l) { | 967 void BranchUnsignedGreater(Register rd, Register rs, Label* l) { |
| 968 ASSERT(!in_delay_slot_); |
| 949 sltu(CMPRES2, rs, rd); | 969 sltu(CMPRES2, rs, rd); |
| 950 bne(CMPRES2, ZR, l); | 970 bne(CMPRES2, ZR, l); |
| 951 } | 971 } |
| 952 | 972 |
| 953 void BranchUnsignedGreater(Register rd, int32_t value, Label* l) { | 973 void BranchUnsignedGreater(Register rd, int32_t value, Label* l) { |
| 974 ASSERT(!in_delay_slot_); |
| 954 if (value == 0) { | 975 if (value == 0) { |
| 955 BranchNotEqual(rd, 0, l); | 976 BranchNotEqual(rd, 0, l); |
| 956 } else { | 977 } else { |
| 957 ASSERT(rd != CMPRES2); | 978 ASSERT(rd != CMPRES2); |
| 958 LoadImmediate(CMPRES2, value); | 979 LoadImmediate(CMPRES2, value); |
| 959 BranchUnsignedGreater(rd, CMPRES2, l); | 980 BranchUnsignedGreater(rd, CMPRES2, l); |
| 960 } | 981 } |
| 961 } | 982 } |
| 962 | 983 |
| 963 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) { | 984 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) { |
| 985 ASSERT(!in_delay_slot_); |
| 964 slt(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. | 986 slt(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. |
| 965 beq(CMPRES2, ZR, l); // If CMPRES2 = 0, then rd >= rs. | 987 beq(CMPRES2, ZR, l); // If CMPRES2 = 0, then rd >= rs. |
| 966 } | 988 } |
| 967 | 989 |
| 968 void BranchSignedGreaterEqual(Register rd, int32_t value, Label* l) { | 990 void BranchSignedGreaterEqual(Register rd, int32_t value, Label* l) { |
| 991 ASSERT(!in_delay_slot_); |
| 969 if (value == 0) { | 992 if (value == 0) { |
| 970 bgez(rd, l); | 993 bgez(rd, l); |
| 971 } else { | 994 } else { |
| 972 if (Utils::IsInt(kImmBits, value)) { | 995 if (Utils::IsInt(kImmBits, value)) { |
| 973 slti(CMPRES2, rd, Immediate(value)); | 996 slti(CMPRES2, rd, Immediate(value)); |
| 974 beq(CMPRES2, ZR, l); | 997 beq(CMPRES2, ZR, l); |
| 975 } else { | 998 } else { |
| 976 ASSERT(rd != CMPRES2); | 999 ASSERT(rd != CMPRES2); |
| 977 LoadImmediate(CMPRES2, value); | 1000 LoadImmediate(CMPRES2, value); |
| 978 BranchSignedGreaterEqual(rd, CMPRES2, l); | 1001 BranchSignedGreaterEqual(rd, CMPRES2, l); |
| 979 } | 1002 } |
| 980 } | 1003 } |
| 981 } | 1004 } |
| 982 | 1005 |
| 983 void BranchUnsignedGreaterEqual(Register rd, Register rs, Label* l) { | 1006 void BranchUnsignedGreaterEqual(Register rd, Register rs, Label* l) { |
| 1007 ASSERT(!in_delay_slot_); |
| 984 sltu(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. | 1008 sltu(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. |
| 985 beq(CMPRES2, ZR, l); | 1009 beq(CMPRES2, ZR, l); |
| 986 } | 1010 } |
| 987 | 1011 |
| 988 void BranchUnsignedGreaterEqual(Register rd, int32_t value, Label* l) { | 1012 void BranchUnsignedGreaterEqual(Register rd, int32_t value, Label* l) { |
| 1013 ASSERT(!in_delay_slot_); |
| 989 if (value == 0) { | 1014 if (value == 0) { |
| 990 b(l); | 1015 b(l); |
| 991 } else { | 1016 } else { |
| 992 if (Utils::IsUint(kImmBits, value)) { | 1017 if (Utils::IsUint(kImmBits, value)) { |
| 993 sltiu(CMPRES2, rd, Immediate(value)); | 1018 sltiu(CMPRES2, rd, Immediate(value)); |
| 994 beq(CMPRES2, ZR, l); | 1019 beq(CMPRES2, ZR, l); |
| 995 } else { | 1020 } else { |
| 996 ASSERT(rd != CMPRES2); | 1021 ASSERT(rd != CMPRES2); |
| 997 LoadImmediate(CMPRES2, value); | 1022 LoadImmediate(CMPRES2, value); |
| 998 BranchUnsignedGreaterEqual(rd, CMPRES2, l); | 1023 BranchUnsignedGreaterEqual(rd, CMPRES2, l); |
| 999 } | 1024 } |
| 1000 } | 1025 } |
| 1001 } | 1026 } |
| 1002 | 1027 |
| 1003 void BranchSignedLess(Register rd, Register rs, Label* l) { | 1028 void BranchSignedLess(Register rd, Register rs, Label* l) { |
| 1029 ASSERT(!in_delay_slot_); |
| 1004 BranchSignedGreater(rs, rd, l); | 1030 BranchSignedGreater(rs, rd, l); |
| 1005 } | 1031 } |
| 1006 | 1032 |
| 1007 void BranchSignedLess(Register rd, int32_t value, Label* l) { | 1033 void BranchSignedLess(Register rd, int32_t value, Label* l) { |
| 1034 ASSERT(!in_delay_slot_); |
| 1008 if (value == 0) { | 1035 if (value == 0) { |
| 1009 bltz(rd, l); | 1036 bltz(rd, l); |
| 1010 } else { | 1037 } else { |
| 1011 if (Utils::IsInt(kImmBits, value)) { | 1038 if (Utils::IsInt(kImmBits, value)) { |
| 1012 slti(CMPRES2, rd, Immediate(value)); | 1039 slti(CMPRES2, rd, Immediate(value)); |
| 1013 bne(CMPRES2, ZR, l); | 1040 bne(CMPRES2, ZR, l); |
| 1014 } else { | 1041 } else { |
| 1015 ASSERT(rd != CMPRES2); | 1042 ASSERT(rd != CMPRES2); |
| 1016 LoadImmediate(CMPRES2, value); | 1043 LoadImmediate(CMPRES2, value); |
| 1017 BranchSignedGreater(CMPRES2, rd, l); | 1044 BranchSignedGreater(CMPRES2, rd, l); |
| 1018 } | 1045 } |
| 1019 } | 1046 } |
| 1020 } | 1047 } |
| 1021 | 1048 |
| 1022 void BranchUnsignedLess(Register rd, Register rs, Label* l) { | 1049 void BranchUnsignedLess(Register rd, Register rs, Label* l) { |
| 1050 ASSERT(!in_delay_slot_); |
| 1023 BranchUnsignedGreater(rs, rd, l); | 1051 BranchUnsignedGreater(rs, rd, l); |
| 1024 } | 1052 } |
| 1025 | 1053 |
| 1026 void BranchUnsignedLess(Register rd, int32_t value, Label* l) { | 1054 void BranchUnsignedLess(Register rd, int32_t value, Label* l) { |
| 1055 ASSERT(!in_delay_slot_); |
| 1027 ASSERT(value != 0); | 1056 ASSERT(value != 0); |
| 1028 if (Utils::IsUint(kImmBits, value)) { | 1057 if (Utils::IsUint(kImmBits, value)) { |
| 1029 sltiu(CMPRES2, rd, Immediate(value)); | 1058 sltiu(CMPRES2, rd, Immediate(value)); |
| 1030 bne(CMPRES2, ZR, l); | 1059 bne(CMPRES2, ZR, l); |
| 1031 } else { | 1060 } else { |
| 1032 ASSERT(rd != CMPRES2); | 1061 ASSERT(rd != CMPRES2); |
| 1033 LoadImmediate(CMPRES2, value); | 1062 LoadImmediate(CMPRES2, value); |
| 1034 BranchUnsignedGreater(CMPRES2, rd, l); | 1063 BranchUnsignedGreater(CMPRES2, rd, l); |
| 1035 } | 1064 } |
| 1036 } | 1065 } |
| 1037 | 1066 |
| 1038 void BranchSignedLessEqual(Register rd, Register rs, Label* l) { | 1067 void BranchSignedLessEqual(Register rd, Register rs, Label* l) { |
| 1068 ASSERT(!in_delay_slot_); |
| 1039 BranchSignedGreaterEqual(rs, rd, l); | 1069 BranchSignedGreaterEqual(rs, rd, l); |
| 1040 } | 1070 } |
| 1041 | 1071 |
| 1042 void BranchSignedLessEqual(Register rd, int32_t value, Label* l) { | 1072 void BranchSignedLessEqual(Register rd, int32_t value, Label* l) { |
| 1073 ASSERT(!in_delay_slot_); |
| 1043 if (value == 0) { | 1074 if (value == 0) { |
| 1044 blez(rd, l); | 1075 blez(rd, l); |
| 1045 } else { | 1076 } else { |
| 1046 ASSERT(rd != CMPRES2); | 1077 ASSERT(rd != CMPRES2); |
| 1047 LoadImmediate(CMPRES2, value); | 1078 LoadImmediate(CMPRES2, value); |
| 1048 BranchSignedGreaterEqual(CMPRES2, rd, l); | 1079 BranchSignedGreaterEqual(CMPRES2, rd, l); |
| 1049 } | 1080 } |
| 1050 } | 1081 } |
| 1051 | 1082 |
| 1052 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) { | 1083 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) { |
| 1084 ASSERT(!in_delay_slot_); |
| 1053 BranchUnsignedGreaterEqual(rs, rd, l); | 1085 BranchUnsignedGreaterEqual(rs, rd, l); |
| 1054 } | 1086 } |
| 1055 | 1087 |
| 1056 void BranchUnsignedLessEqual(Register rd, int32_t value, Label* l) { | 1088 void BranchUnsignedLessEqual(Register rd, int32_t value, Label* l) { |
| 1089 ASSERT(!in_delay_slot_); |
| 1057 ASSERT(rd != CMPRES2); | 1090 ASSERT(rd != CMPRES2); |
| 1058 LoadImmediate(CMPRES2, value); | 1091 LoadImmediate(CMPRES2, value); |
| 1059 BranchUnsignedGreaterEqual(CMPRES2, rd, l); | 1092 BranchUnsignedGreaterEqual(CMPRES2, rd, l); |
| 1060 } | 1093 } |
| 1061 | 1094 |
| 1062 void Push(Register rt) { | 1095 void Push(Register rt) { |
| 1096 ASSERT(!in_delay_slot_); |
| 1063 addiu(SP, SP, Immediate(-kWordSize)); | 1097 addiu(SP, SP, Immediate(-kWordSize)); |
| 1064 sw(rt, Address(SP)); | 1098 sw(rt, Address(SP)); |
| 1065 } | 1099 } |
| 1066 | 1100 |
| 1067 void Pop(Register rt) { | 1101 void Pop(Register rt) { |
| 1102 ASSERT(!in_delay_slot_); |
| 1068 lw(rt, Address(SP)); | 1103 lw(rt, Address(SP)); |
| 1069 addiu(SP, SP, Immediate(kWordSize)); | 1104 addiu(SP, SP, Immediate(kWordSize)); |
| 1070 } | 1105 } |
| 1071 | 1106 |
| 1072 void Ret() { | 1107 void Ret() { |
| 1073 jr(RA); | 1108 jr(RA); |
| 1074 } | 1109 } |
| 1075 | 1110 |
| 1076 void SmiTag(Register reg) { | 1111 void SmiTag(Register reg) { |
| 1077 sll(reg, reg, kSmiTagSize); | 1112 sll(reg, reg, kSmiTagSize); |
| 1078 } | 1113 } |
| 1079 | 1114 |
| 1080 void SmiUntag(Register reg) { | 1115 void SmiUntag(Register reg) { |
| 1081 sra(reg, reg, kSmiTagSize); | 1116 sra(reg, reg, kSmiTagSize); |
| 1082 } | 1117 } |
| 1083 | 1118 |
| 1084 void LoadFromOffset(Register reg, Register base, int32_t offset) { | 1119 void LoadFromOffset(Register reg, Register base, int32_t offset) { |
| 1120 ASSERT(!in_delay_slot_); |
| 1085 if (Utils::IsInt(kImmBits, offset)) { | 1121 if (Utils::IsInt(kImmBits, offset)) { |
| 1086 lw(reg, Address(base, offset)); | 1122 lw(reg, Address(base, offset)); |
| 1087 } else { | 1123 } else { |
| 1088 LoadImmediate(TMP, offset); | 1124 LoadImmediate(TMP, offset); |
| 1089 addu(TMP, base, TMP); | 1125 addu(TMP, base, TMP); |
| 1090 lw(reg, Address(TMP, 0)); | 1126 lw(reg, Address(TMP, 0)); |
| 1091 } | 1127 } |
| 1092 } | 1128 } |
| 1093 | 1129 |
| 1094 void StoreToOffset(Register reg, Register base, int32_t offset) { | 1130 void StoreToOffset(Register reg, Register base, int32_t offset) { |
| 1131 ASSERT(!in_delay_slot_); |
| 1095 if (Utils::IsInt(kImmBits, offset)) { | 1132 if (Utils::IsInt(kImmBits, offset)) { |
| 1096 sw(reg, Address(base, offset)); | 1133 sw(reg, Address(base, offset)); |
| 1097 } else { | 1134 } else { |
| 1098 LoadImmediate(TMP, offset); | 1135 LoadImmediate(TMP, offset); |
| 1099 addu(TMP, base, TMP); | 1136 addu(TMP, base, TMP); |
| 1100 sw(reg, Address(TMP, 0)); | 1137 sw(reg, Address(TMP, 0)); |
| 1101 } | 1138 } |
| 1102 } | 1139 } |
| 1103 | 1140 |
| 1104 void StoreDToOffset(DRegister reg, Register base, int32_t offset) { | 1141 void StoreDToOffset(DRegister reg, Register base, int32_t offset) { |
| 1142 ASSERT(!in_delay_slot_); |
| 1105 FRegister lo = static_cast<FRegister>(reg * 2); | 1143 FRegister lo = static_cast<FRegister>(reg * 2); |
| 1106 FRegister hi = static_cast<FRegister>(reg * 2 + 1); | 1144 FRegister hi = static_cast<FRegister>(reg * 2 + 1); |
| 1107 swc1(lo, Address(base, offset)); | 1145 swc1(lo, Address(base, offset)); |
| 1108 swc1(hi, Address(base, offset + kWordSize)); | 1146 swc1(hi, Address(base, offset + kWordSize)); |
| 1109 } | 1147 } |
| 1110 | 1148 |
| 1111 void LoadDFromOffset(DRegister reg, Register base, int32_t offset) { | 1149 void LoadDFromOffset(DRegister reg, Register base, int32_t offset) { |
| 1150 ASSERT(!in_delay_slot_); |
| 1112 FRegister lo = static_cast<FRegister>(reg * 2); | 1151 FRegister lo = static_cast<FRegister>(reg * 2); |
| 1113 FRegister hi = static_cast<FRegister>(reg * 2 + 1); | 1152 FRegister hi = static_cast<FRegister>(reg * 2 + 1); |
| 1114 lwc1(lo, Address(base, offset)); | 1153 lwc1(lo, Address(base, offset)); |
| 1115 lwc1(hi, Address(base, offset + kWordSize)); | 1154 lwc1(hi, Address(base, offset + kWordSize)); |
| 1116 } | 1155 } |
| 1117 | 1156 |
| 1118 // dest gets the address of the following instruction. If temp is given, | 1157 // dest gets the address of the following instruction. If temp is given, |
| 1119 // RA is preserved using it as a temporary. | 1158 // RA is preserved using it as a temporary. |
| 1120 void GetNextPC(Register dest, Register temp = kNoRegister); | 1159 void GetNextPC(Register dest, Register temp = kNoRegister); |
| 1121 | 1160 |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1300 Register value, | 1339 Register value, |
| 1301 Label* no_update); | 1340 Label* no_update); |
| 1302 | 1341 |
| 1303 DISALLOW_ALLOCATION(); | 1342 DISALLOW_ALLOCATION(); |
| 1304 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1343 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 1305 }; | 1344 }; |
| 1306 | 1345 |
| 1307 } // namespace dart | 1346 } // namespace dart |
| 1308 | 1347 |
| 1309 #endif // VM_ASSEMBLER_MIPS_H_ | 1348 #endif // VM_ASSEMBLER_MIPS_H_ |
| OLD | NEW |