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

Side by Side Diff: runtime/vm/assembler_mips.h

Issue 20369003: Implements far branch targets for MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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 | « no previous file | runtime/vm/assembler_mips.cc » ('j') | runtime/vm/assembler_mips.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 11
12 #include "platform/assert.h" 12 #include "platform/assert.h"
13 #include "platform/utils.h" 13 #include "platform/utils.h"
14 #include "vm/constants_mips.h" 14 #include "vm/constants_mips.h"
15 #include "vm/simulator.h" 15 #include "vm/simulator.h"
16 16
17 // References to documentation in this file refer to: 17 // References to documentation in this file refer to:
18 // "MIPS® Architecture For Programmers Volume I-A: 18 // "MIPS® Architecture For Programmers Volume I-A:
19 // Introduction to the MIPS32® Architecture" in short "VolI-A" 19 // Introduction to the MIPS32® Architecture" in short "VolI-A"
20 // and 20 // and
21 // "MIPS® Architecture For Programmers Volume II-A: 21 // "MIPS® Architecture For Programmers Volume II-A:
22 // The MIPS32® Instruction Set" in short "VolII-A" 22 // The MIPS32® Instruction Set" in short "VolII-A"
23 namespace dart { 23 namespace dart {
24 24
25 DECLARE_FLAG(bool, mips_far_branches);
regis 2013/07/26 22:30:38 'mips_' is not really needed, but since I understa
zra 2013/07/26 23:29:03 Changed to use_far_branches, and I'll use the same
26
25 // Forward declarations. 27 // Forward declarations.
26 class RuntimeEntry; 28 class RuntimeEntry;
27 29
28 class Immediate : public ValueObject { 30 class Immediate : public ValueObject {
29 public: 31 public:
30 explicit Immediate(int32_t value) : value_(value) { } 32 explicit Immediate(int32_t value) : value_(value) { }
31 33
32 Immediate(const Immediate& other) : ValueObject(), value_(other.value_) { } 34 Immediate(const Immediate& other) : ValueObject(), value_(other.value_) { }
33 Immediate& operator=(const Immediate& other) { 35 Immediate& operator=(const Immediate& other) {
34 value_ = other.value_; 36 value_ = other.value_;
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 LoadImmediate(TMP1, value); 849 LoadImmediate(TMP1, value);
848 addu(rd, rs, TMP1); 850 addu(rd, rs, TMP1);
849 } 851 }
850 } 852 }
851 853
852 void AddImmediate(Register rd, int32_t value) { 854 void AddImmediate(Register rd, int32_t value) {
853 AddImmediate(rd, rd, value); 855 AddImmediate(rd, rd, value);
854 } 856 }
855 857
856 void BranchEqual(Register rd, int32_t value, Label* l) { 858 void BranchEqual(Register rd, int32_t value, Label* l) {
857 ASSERT(rd != CMPRES); 859 ASSERT(rd != CMPRES2);
858 LoadImmediate(CMPRES, value); 860 LoadImmediate(CMPRES2, value);
859 beq(rd, CMPRES, l); 861 beq(rd, CMPRES2, l);
860 } 862 }
861 863
862 void BranchEqual(Register rd, const Object& object, Label* l) { 864 void BranchEqual(Register rd, const Object& object, Label* l) {
863 ASSERT(rd != CMPRES); 865 ASSERT(rd != CMPRES2);
864 LoadObject(CMPRES, object); 866 LoadObject(CMPRES2, object);
865 beq(rd, CMPRES, l); 867 beq(rd, CMPRES2, l);
866 } 868 }
867 869
868 void BranchNotEqual(Register rd, int32_t value, Label* l) { 870 void BranchNotEqual(Register rd, int32_t value, Label* l) {
869 ASSERT(rd != CMPRES); 871 ASSERT(rd != CMPRES2);
870 LoadImmediate(CMPRES, value); 872 LoadImmediate(CMPRES2, value);
871 bne(rd, CMPRES, l); 873 bne(rd, CMPRES2, l);
872 } 874 }
873 875
874 void BranchNotEqual(Register rd, const Object& object, Label* l) { 876 void BranchNotEqual(Register rd, const Object& object, Label* l) {
875 ASSERT(rd != CMPRES); 877 ASSERT(rd != CMPRES2);
876 LoadObject(CMPRES, object); 878 LoadObject(CMPRES2, object);
877 bne(rd, CMPRES, l); 879 bne(rd, CMPRES2, l);
878 } 880 }
879 881
880 void BranchSignedGreater(Register rd, Register rs, Label* l) { 882 void BranchSignedGreater(Register rd, Register rs, Label* l) {
881 slt(CMPRES, rs, rd); // CMPRES = rd > rs ? 1 : 0. 883 slt(CMPRES2, rs, rd); // CMPRES2 = rd > rs ? 1 : 0.
882 bne(CMPRES, ZR, l); 884 bne(CMPRES2, ZR, l);
883 } 885 }
884 886
885 void BranchSignedGreater(Register rd, int32_t value, Label* l) { 887 void BranchSignedGreater(Register rd, int32_t value, Label* l) {
886 LoadImmediate(CMPRES, value); 888 ASSERT(rd != CMPRES2);
887 BranchSignedGreater(rd, CMPRES, l); 889 LoadImmediate(CMPRES2, value);
890 BranchSignedGreater(rd, CMPRES2, l);
888 } 891 }
889 892
890 void BranchUnsignedGreater(Register rd, Register rs, Label* l) { 893 void BranchUnsignedGreater(Register rd, Register rs, Label* l) {
891 sltu(CMPRES, rs, rd); 894 sltu(CMPRES2, rs, rd);
892 bne(CMPRES, ZR, l); 895 bne(CMPRES2, ZR, l);
893 } 896 }
894 897
895 void BranchUnsignedGreater(Register rd, int32_t value, Label* l) { 898 void BranchUnsignedGreater(Register rd, int32_t value, Label* l) {
896 LoadImmediate(CMPRES, value); 899 ASSERT(rd != CMPRES2);
897 BranchUnsignedGreater(rd, CMPRES, l); 900 LoadImmediate(CMPRES2, value);
901 BranchUnsignedGreater(rd, CMPRES2, l);
898 } 902 }
899 903
900 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) { 904 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) {
901 slt(CMPRES, rd, rs); // CMPRES = rd < rs ? 1 : 0. 905 slt(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0.
902 beq(CMPRES, ZR, l); // If CMPRES = 0, then rd >= rs. 906 beq(CMPRES2, ZR, l); // If CMPRES2 = 0, then rd >= rs.
903 } 907 }
904 908
905 void BranchSignedGreaterEqual(Register rd, int32_t value, Label* l) { 909 void BranchSignedGreaterEqual(Register rd, int32_t value, Label* l) {
906 if (Utils::IsInt(kImmBits, value)) { 910 if (Utils::IsInt(kImmBits, value)) {
907 slti(CMPRES, rd, Immediate(value)); 911 slti(CMPRES2, rd, Immediate(value));
908 beq(CMPRES, ZR, l); 912 beq(CMPRES2, ZR, l);
909 } else { 913 } else {
910 LoadImmediate(CMPRES, value); 914 ASSERT(rd != CMPRES2);
911 BranchSignedGreaterEqual(rd, CMPRES, l); 915 LoadImmediate(CMPRES2, value);
916 BranchSignedGreaterEqual(rd, CMPRES2, l);
912 } 917 }
913 } 918 }
914 919
915 void BranchUnsignedGreaterEqual(Register rd, Register rs, Label* l) { 920 void BranchUnsignedGreaterEqual(Register rd, Register rs, Label* l) {
916 sltu(CMPRES, rd, rs); // CMPRES = rd < rs ? 1 : 0. 921 sltu(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0.
917 beq(CMPRES, ZR, l); 922 beq(CMPRES2, ZR, l);
918 } 923 }
919 924
920 void BranchUnsignedGreaterEqual(Register rd, int32_t value, Label* l) { 925 void BranchUnsignedGreaterEqual(Register rd, int32_t value, Label* l) {
921 if (Utils::IsUint(kImmBits, value)) { 926 if (Utils::IsUint(kImmBits, value)) {
922 sltiu(CMPRES, rd, Immediate(value)); 927 sltiu(CMPRES2, rd, Immediate(value));
923 beq(CMPRES, ZR, l); 928 beq(CMPRES2, ZR, l);
924 } else { 929 } else {
925 LoadImmediate(CMPRES, value); 930 ASSERT(rd != CMPRES2);
926 BranchUnsignedGreaterEqual(rd, CMPRES, l); 931 LoadImmediate(CMPRES2, value);
932 BranchUnsignedGreaterEqual(rd, CMPRES2, l);
927 } 933 }
928 } 934 }
929 935
930 void BranchSignedLess(Register rd, Register rs, Label* l) { 936 void BranchSignedLess(Register rd, Register rs, Label* l) {
931 BranchSignedGreater(rs, rd, l); 937 BranchSignedGreater(rs, rd, l);
932 } 938 }
933 939
934 void BranchSignedLess(Register rd, int32_t value, Label* l) { 940 void BranchSignedLess(Register rd, int32_t value, Label* l) {
935 if (Utils::IsInt(kImmBits, value)) { 941 if (Utils::IsInt(kImmBits, value)) {
936 slti(CMPRES, rd, Immediate(value)); 942 slti(CMPRES2, rd, Immediate(value));
937 bne(CMPRES, ZR, l); 943 bne(CMPRES2, ZR, l);
938 } else { 944 } else {
939 LoadImmediate(CMPRES, value); 945 ASSERT(rd != CMPRES2);
940 BranchSignedGreater(CMPRES, rd, l); 946 LoadImmediate(CMPRES2, value);
947 BranchSignedGreater(CMPRES2, rd, l);
941 } 948 }
942 } 949 }
943 950
944 void BranchUnsignedLess(Register rd, Register rs, Label* l) { 951 void BranchUnsignedLess(Register rd, Register rs, Label* l) {
945 BranchUnsignedGreater(rs, rd, l); 952 BranchUnsignedGreater(rs, rd, l);
946 } 953 }
947 954
948 void BranchUnsignedLess(Register rd, int32_t value, Label* l) { 955 void BranchUnsignedLess(Register rd, int32_t value, Label* l) {
949 if (Utils::IsUint(kImmBits, value)) { 956 if (Utils::IsUint(kImmBits, value)) {
950 sltiu(CMPRES, rd, Immediate(value)); 957 sltiu(CMPRES2, rd, Immediate(value));
951 bne(CMPRES, ZR, l); 958 bne(CMPRES2, ZR, l);
952 } else { 959 } else {
953 LoadImmediate(CMPRES, value); 960 ASSERT(rd != CMPRES2);
954 BranchUnsignedGreater(CMPRES, rd, l); 961 LoadImmediate(CMPRES2, value);
962 BranchUnsignedGreater(CMPRES2, rd, l);
955 } 963 }
956 } 964 }
957 965
958 void BranchSignedLessEqual(Register rd, Register rs, Label* l) { 966 void BranchSignedLessEqual(Register rd, Register rs, Label* l) {
959 BranchSignedGreaterEqual(rs, rd, l); 967 BranchSignedGreaterEqual(rs, rd, l);
960 } 968 }
961 969
962 void BranchSignedLessEqual(Register rd, int32_t value, Label* l) { 970 void BranchSignedLessEqual(Register rd, int32_t value, Label* l) {
963 LoadImmediate(CMPRES, value); 971 ASSERT(rd != CMPRES2);
964 BranchSignedGreaterEqual(CMPRES, rd, l); 972 LoadImmediate(CMPRES2, value);
973 BranchSignedGreaterEqual(CMPRES2, rd, l);
965 } 974 }
966 975
967 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) { 976 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) {
968 BranchUnsignedGreaterEqual(rs, rd, l); 977 BranchUnsignedGreaterEqual(rs, rd, l);
969 } 978 }
970 979
971 void BranchUnsignedLessEqual(Register rd, int32_t value, Label* l) { 980 void BranchUnsignedLessEqual(Register rd, int32_t value, Label* l) {
972 LoadImmediate(CMPRES, value); 981 ASSERT(rd != CMPRES2);
973 BranchUnsignedGreaterEqual(CMPRES, rd, l); 982 LoadImmediate(CMPRES2, value);
983 BranchUnsignedGreaterEqual(CMPRES2, rd, l);
974 } 984 }
975 985
976 void Push(Register rt) { 986 void Push(Register rt) {
977 addiu(SP, SP, Immediate(-kWordSize)); 987 addiu(SP, SP, Immediate(-kWordSize));
978 sw(rt, Address(SP)); 988 sw(rt, Address(SP));
979 } 989 }
980 990
981 void Pop(Register rt) { 991 void Pop(Register rt) {
982 lw(rt, Address(SP)); 992 lw(rt, Address(SP));
983 addiu(SP, SP, Immediate(kWordSize)); 993 addiu(SP, SP, Immediate(kWordSize));
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 swc1(hi, Address(base, offset + kWordSize)); 1032 swc1(hi, Address(base, offset + kWordSize));
1023 } 1033 }
1024 1034
1025 void LoadDFromOffset(DRegister reg, Register base, int32_t offset) { 1035 void LoadDFromOffset(DRegister reg, Register base, int32_t offset) {
1026 FRegister lo = static_cast<FRegister>(reg * 2); 1036 FRegister lo = static_cast<FRegister>(reg * 2);
1027 FRegister hi = static_cast<FRegister>(reg * 2 + 1); 1037 FRegister hi = static_cast<FRegister>(reg * 2 + 1);
1028 lwc1(lo, Address(base, offset)); 1038 lwc1(lo, Address(base, offset));
1029 lwc1(hi, Address(base, offset + kWordSize)); 1039 lwc1(hi, Address(base, offset + kWordSize));
1030 } 1040 }
1031 1041
1042 // dest gets the address of the following instruction. If preserve ra is true
1043 // RA is preserved using CMPRES1 as a temporary.
1044 void GetNextPC(Register dest, bool preserve_ra) {
regis 2013/07/26 22:30:38 The caller does not see that CMPRES1 is trashed. I
zra 2013/07/26 23:29:03 Done.
1045 if (preserve_ra) {
1046 mov(CMPRES1, RA);
1047 }
1048 EmitRegImmType(REGIMM, R0, BGEZAL, 1);
1049 mov(dest, RA);
1050 if (preserve_ra) {
1051 mov(RA, CMPRES1);
1052 }
1053 }
1054
1032 void ReserveAlignedFrameSpace(intptr_t frame_space); 1055 void ReserveAlignedFrameSpace(intptr_t frame_space);
1033 1056
1034 // Create a frame for calling into runtime that preserves all volatile 1057 // Create a frame for calling into runtime that preserves all volatile
1035 // registers. Frame's SP is guaranteed to be correctly aligned and 1058 // registers. Frame's SP is guaranteed to be correctly aligned and
1036 // frame_space bytes are reserved under it. 1059 // frame_space bytes are reserved under it.
1037 void EnterCallRuntimeFrame(intptr_t frame_space); 1060 void EnterCallRuntimeFrame(intptr_t frame_space);
1038 void LeaveCallRuntimeFrame(); 1061 void LeaveCallRuntimeFrame();
1039 1062
1040 void LoadWordFromPoolOffset(Register rd, int32_t offset); 1063 void LoadWordFromPoolOffset(Register rd, int32_t offset);
1041 void LoadObject(Register rd, const Object& object); 1064 void LoadObject(Register rd, const Object& object);
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1175 FRegister fd, 1198 FRegister fd,
1176 Cop1Function func) { 1199 Cop1Function func) {
1177 Emit(opcode << kOpcodeShift | 1200 Emit(opcode << kOpcodeShift |
1178 fmt << kFmtShift | 1201 fmt << kFmtShift |
1179 ft << kFtShift | 1202 ft << kFtShift |
1180 fs << kFsShift | 1203 fs << kFsShift |
1181 fd << kFdShift | 1204 fd << kFdShift |
1182 func << kCop1FnShift); 1205 func << kCop1FnShift);
1183 } 1206 }
1184 1207
1185 void EmitBranch(Opcode b, Register rs, Register rt, Label* label) {
1186 if (label->IsBound()) {
1187 // Relative destination from an instruction after the branch.
1188 const int32_t dest =
1189 label->Position() - (buffer_.Size() + Instr::kInstrSize);
1190 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
1191 EmitIType(b, rs, rt, dest_off);
1192 } else {
1193 const int position = buffer_.Size();
1194 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
1195 EmitIType(b, rs, rt, dest_off);
1196 label->LinkTo(position);
1197 }
1198 }
1199 1208
1200 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { 1209 void EmitFarJump(int32_t offset, bool link);
1201 if (label->IsBound()) { 1210 void EmitFarBranch(Opcode b, Register rs, Register rt, int32_t offset);
1202 // Relative destination from an instruction after the branch. 1211 void EmitFarRegImmBranch(RtRegImm b, Register rs, int32_t offset);
1203 const int32_t dest = 1212 void EmitFarFpuBranch(bool kind, int32_t offset);
1204 label->Position() - (buffer_.Size() + Instr::kInstrSize); 1213 void EmitBranch(Opcode b, Register rs, Register rt, Label* label);
1205 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 1214 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label);
1206 EmitRegImmType(REGIMM, rs, b, dest_off); 1215 void EmitFpuBranch(bool kind, Label *label);
1207 } else {
1208 const int position = buffer_.Size();
1209 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
1210 EmitRegImmType(REGIMM, rs, b, dest_off);
1211 label->LinkTo(position);
1212 }
1213 }
1214
1215 void EmitFpuBranch(bool kind, Label *label) {
1216 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true.
1217 if (label->IsBound()) {
1218 // Relative destination from an instruction after the branch.
1219 const int32_t dest =
1220 label->Position() - (buffer_.Size() + Instr::kInstrSize);
1221 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
1222 Emit(COP1 << kOpcodeShift |
1223 COP1_BC << kCop1SubShift |
1224 b16 |
1225 dest_off);
1226 } else {
1227 const int position = buffer_.Size();
1228 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
1229 Emit(COP1 << kOpcodeShift |
1230 COP1_BC << kCop1SubShift |
1231 b16 |
1232 dest_off);
1233 label->LinkTo(position);
1234 }
1235 }
1236
1237 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr);
1238 static int DecodeBranchOffset(int32_t instr);
1239 1216
1240 void EmitBranchDelayNop() { 1217 void EmitBranchDelayNop() {
1241 Emit(Instr::kNopInstruction); // Branch delay NOP. 1218 Emit(Instr::kNopInstruction); // Branch delay NOP.
1242 delay_slot_available_ = true; 1219 delay_slot_available_ = true;
1243 } 1220 }
1244 1221
1245 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); 1222 void StoreIntoObjectFilter(Register object, Register value, Label* no_update);
1246 1223
1247 // Shorter filtering sequence that assumes that value is not a smi. 1224 // Shorter filtering sequence that assumes that value is not a smi.
1248 void StoreIntoObjectFilterNoSmi(Register object, 1225 void StoreIntoObjectFilterNoSmi(Register object,
1249 Register value, 1226 Register value,
1250 Label* no_update); 1227 Label* no_update);
1251 1228
1252 DISALLOW_ALLOCATION(); 1229 DISALLOW_ALLOCATION();
1253 DISALLOW_COPY_AND_ASSIGN(Assembler); 1230 DISALLOW_COPY_AND_ASSIGN(Assembler);
1254 }; 1231 };
1255 1232
1256 } // namespace dart 1233 } // namespace dart
1257 1234
1258 #endif // VM_ASSEMBLER_MIPS_H_ 1235 #endif // VM_ASSEMBLER_MIPS_H_
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/assembler_mips.cc » ('j') | runtime/vm/assembler_mips.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698