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

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') | no next file with comments »
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);
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(CMPRES1, rs, rd); // CMPRES1 = rd > rs ? 1 : 0.
regis 2013/07/25 20:07:43 It's awkward that some branch instructions use CMP
zra 2013/07/26 21:26:15 Done.
882 bne(CMPRES, ZR, l); 884 bne(CMPRES1, 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(CMPRES1, rs, rd);
892 bne(CMPRES, ZR, l); 895 bne(CMPRES1, 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(CMPRES1, rd, rs); // CMPRES1 = rd < rs ? 1 : 0.
902 beq(CMPRES, ZR, l); // If CMPRES = 0, then rd >= rs. 906 beq(CMPRES1, ZR, l); // If CMPRES1 = 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(CMPRES1, rd, Immediate(value));
908 beq(CMPRES, ZR, l); 912 beq(CMPRES1, 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(CMPRES1, rd, rs); // CMPRES1 = rd < rs ? 1 : 0.
917 beq(CMPRES, ZR, l); 922 beq(CMPRES1, 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(CMPRES1, rd, Immediate(value));
923 beq(CMPRES, ZR, l); 928 beq(CMPRES1, 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(CMPRES1, rd, Immediate(value));
937 bne(CMPRES, ZR, l); 943 bne(CMPRES1, 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(CMPRES1, rd, Immediate(value));
951 bne(CMPRES, ZR, l); 958 bne(CMPRES1, 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 LoadImmediate(CMPRES1, value);
964 BranchSignedGreaterEqual(CMPRES, rd, l); 972 BranchSignedGreaterEqual(CMPRES1, rd, l);
965 } 973 }
966 974
967 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) { 975 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) {
968 BranchUnsignedGreaterEqual(rs, rd, l); 976 BranchUnsignedGreaterEqual(rs, rd, l);
969 } 977 }
970 978
971 void BranchUnsignedLessEqual(Register rd, int32_t value, Label* l) { 979 void BranchUnsignedLessEqual(Register rd, int32_t value, Label* l) {
972 LoadImmediate(CMPRES, value); 980 LoadImmediate(CMPRES1, value);
973 BranchUnsignedGreaterEqual(CMPRES, rd, l); 981 BranchUnsignedGreaterEqual(CMPRES1, rd, l);
974 } 982 }
975 983
976 void Push(Register rt) { 984 void Push(Register rt) {
977 addiu(SP, SP, Immediate(-kWordSize)); 985 addiu(SP, SP, Immediate(-kWordSize));
978 sw(rt, Address(SP)); 986 sw(rt, Address(SP));
979 } 987 }
980 988
981 void Pop(Register rt) { 989 void Pop(Register rt) {
982 lw(rt, Address(SP)); 990 lw(rt, Address(SP));
983 addiu(SP, SP, Immediate(kWordSize)); 991 addiu(SP, SP, Immediate(kWordSize));
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 swc1(hi, Address(base, offset + kWordSize)); 1030 swc1(hi, Address(base, offset + kWordSize));
1023 } 1031 }
1024 1032
1025 void LoadDFromOffset(DRegister reg, Register base, int32_t offset) { 1033 void LoadDFromOffset(DRegister reg, Register base, int32_t offset) {
1026 FRegister lo = static_cast<FRegister>(reg * 2); 1034 FRegister lo = static_cast<FRegister>(reg * 2);
1027 FRegister hi = static_cast<FRegister>(reg * 2 + 1); 1035 FRegister hi = static_cast<FRegister>(reg * 2 + 1);
1028 lwc1(lo, Address(base, offset)); 1036 lwc1(lo, Address(base, offset));
1029 lwc1(hi, Address(base, offset + kWordSize)); 1037 lwc1(hi, Address(base, offset + kWordSize));
1030 } 1038 }
1031 1039
1040 // dest gets the address of the following instruction. If preserve ra is true
1041 // RA is preserved using CMPRES1 as a temporary.
1042 void GetNextPC(Register dest, bool preserve_ra) {
1043 if (preserve_ra) {
1044 mov(CMPRES1, RA);
1045 }
1046 EmitRegImmType(REGIMM, R0, BGEZAL, 1);
1047 mov(dest, RA);
1048 if (preserve_ra) {
1049 mov(RA, CMPRES1);
1050 }
1051 }
1052
1032 void ReserveAlignedFrameSpace(intptr_t frame_space); 1053 void ReserveAlignedFrameSpace(intptr_t frame_space);
1033 1054
1034 // Create a frame for calling into runtime that preserves all volatile 1055 // Create a frame for calling into runtime that preserves all volatile
1035 // registers. Frame's SP is guaranteed to be correctly aligned and 1056 // registers. Frame's SP is guaranteed to be correctly aligned and
1036 // frame_space bytes are reserved under it. 1057 // frame_space bytes are reserved under it.
1037 void EnterCallRuntimeFrame(intptr_t frame_space); 1058 void EnterCallRuntimeFrame(intptr_t frame_space);
1038 void LeaveCallRuntimeFrame(); 1059 void LeaveCallRuntimeFrame();
1039 1060
1040 void LoadWordFromPoolOffset(Register rd, int32_t offset); 1061 void LoadWordFromPoolOffset(Register rd, int32_t offset);
1041 void LoadObject(Register rd, const Object& object); 1062 void LoadObject(Register rd, const Object& object);
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1175 FRegister fd, 1196 FRegister fd,
1176 Cop1Function func) { 1197 Cop1Function func) {
1177 Emit(opcode << kOpcodeShift | 1198 Emit(opcode << kOpcodeShift |
1178 fmt << kFmtShift | 1199 fmt << kFmtShift |
1179 ft << kFtShift | 1200 ft << kFtShift |
1180 fs << kFsShift | 1201 fs << kFsShift |
1181 fd << kFdShift | 1202 fd << kFdShift |
1182 func << kCop1FnShift); 1203 func << kCop1FnShift);
1183 } 1204 }
1184 1205
1206 int32_t DecodeLoadImmediate(int32_t low, int32_t high);
1207 int32_t EncodeLoadImmediate(int32_t dest, int32_t instr);
1208
1209 Opcode OppositeBranchOpcode(Opcode b) {
1210 switch (b) {
1211 case BEQ: return BNE;
1212 case BNE: return BEQ;
1213 case BGTZ: return BLEZ;
1214 case BLEZ: return BGTZ;
1215 case BEQL: return BNEL;
1216 case BNEL: return BEQL;
1217 case BGTZL: return BLEZL;
1218 case BLEZL: return BGTZL;
1219 default:
1220 UNREACHABLE();
1221 break;
1222 }
1223 return BNE;
1224 }
1225
1226 void EmitFarBranch(Opcode b, Register rs, Register rt, int32_t offset) {
1227 ASSERT(rs != TMP);
1228 ASSERT(rt != TMP);
1229
1230 const uint16_t low = Utils::Low16Bits(offset);
1231 const uint16_t high = Utils::High16Bits(offset);
1232 lui(TMP, Immediate(high));
1233 ori(TMP, TMP, Immediate(low));
1234
1235 addiu(SP, SP, Immediate(-1 * kWordSize));
1236 sw(CMPRES1, Address(SP, -0 * kWordSize));
1237
1238 mov(CMPRES1, RA);
1239 EmitRegImmType(REGIMM, R0, BGEZAL, 1);
regis 2013/07/25 20:07:43 You are not using GetNextPC. Still needed? OK, I s
1240 addu(TMP, TMP, RA);
1241 mov(RA, CMPRES1);
1242
1243 lw(CMPRES1, Address(SP, -0 * kWordSize));
1244 addiu(SP, SP, Immediate(1 * kWordSize));
regis 2013/07/25 20:07:43 Preserving and restoring CMPRES1 in order to, in t
1245
1246 EmitIType(OppositeBranchOpcode(b), rs, rt, 2);
regis 2013/07/25 20:07:43 You should have an unconditional EmitFarBranch(off
zra 2013/07/26 21:26:15 Done.
1247 nop();
1248 EmitRType(SPECIAL, TMP, R0, R0, 0, JR);
1249 }
1250
1251 RtRegImm OppositeBranchNoLink(RtRegImm b) {
1252 switch (b) {
1253 case BLTZ: return BGEZ;
1254 case BGEZ: return BLTZ;
1255 case BLTZAL: return BGEZ;
1256 case BGEZAL: return BLTZ;
1257 default:
1258 UNREACHABLE();
1259 break;
1260 }
1261 return BLTZ;
1262 }
1263
1264 void EmitFarRegImmBranch(RtRegImm b, Register rs, int32_t offset) {
1265 ASSERT(rs != TMP);
1266
1267 const uint16_t low = Utils::Low16Bits(offset);
1268 const uint16_t high = Utils::High16Bits(offset);
1269 lui(TMP, Immediate(high));
1270 ori(TMP, TMP, Immediate(low));
1271
1272 addiu(SP, SP, Immediate(-1 * kWordSize));
1273 sw(CMPRES1, Address(SP, -0 * kWordSize));
1274
1275 mov(CMPRES1, RA);
1276 EmitRegImmType(REGIMM, R0, BGEZAL, 1);
1277 addu(TMP, TMP, RA);
1278 mov(RA, CMPRES1);
1279
1280 lw(CMPRES1, Address(SP, -0 * kWordSize));
1281 addiu(SP, SP, Immediate(1 * kWordSize));
1282
1283 EmitRegImmType(REGIMM, rs, OppositeBranchNoLink(b), 2);
1284 nop();
1285 if ((b == BLTZAL) || (b == BGEZAL)) {
1286 EmitRType(SPECIAL, TMP, R0, RA, 0, JALR);
1287 } else {
1288 EmitRType(SPECIAL, TMP, R0, R0, 0, JR);
1289 }
1290 }
1291
1292
1293 void EmitFarFpuBranch(bool kind, int32_t offset) {
1294 const uint32_t b16 = kind ? 0 : (1 << 16);
1295
1296 const uint16_t low = Utils::Low16Bits(offset);
1297 const uint16_t high = Utils::High16Bits(offset);
1298 lui(TMP, Immediate(high));
1299 ori(TMP, TMP, Immediate(low));
1300
1301 addiu(SP, SP, Immediate(-1 * kWordSize));
1302 sw(CMPRES1, Address(SP, -0 * kWordSize));
1303
1304 mov(CMPRES1, RA);
1305 EmitRegImmType(REGIMM, R0, BGEZAL, 1);
1306 addu(TMP, TMP, RA);
1307 mov(RA, CMPRES1);
1308
1309 lw(CMPRES1, Address(SP, -0 * kWordSize));
1310 addiu(SP, SP, Immediate(1 * kWordSize));
1311
1312 Emit(COP1 << kOpcodeShift | COP1_BC << kCop1SubShift | b16 | 2);
1313 nop();
1314 EmitRType(SPECIAL, TMP, R0, R0, 0, JR);
1315 }
1316
1317
1185 void EmitBranch(Opcode b, Register rs, Register rt, Label* label) { 1318 void EmitBranch(Opcode b, Register rs, Register rt, Label* label) {
1186 if (label->IsBound()) { 1319 if (label->IsBound()) {
regis 2013/07/25 20:07:43 If the label is bound, you know the offset and you
zra 2013/07/26 21:26:15 Done.
1187 // Relative destination from an instruction after the branch. 1320 // Relative destination from an instruction after the branch.
1188 const int32_t dest = 1321 if (FLAG_mips_far_branches) {
1189 label->Position() - (buffer_.Size() + Instr::kInstrSize); 1322 const int32_t dest =
1190 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 1323 label->Position() - (buffer_.Size() + 7 * Instr::kInstrSize);
1191 EmitIType(b, rs, rt, dest_off); 1324 EmitFarBranch(b, rs, rt, dest);
1325 } else {
1326 const int32_t dest =
1327 label->Position() - (buffer_.Size() + Instr::kInstrSize);
1328 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
1329 EmitIType(b, rs, rt, dest_off);
1330 }
1192 } else { 1331 } else {
1193 const int position = buffer_.Size(); 1332 const int position = buffer_.Size();
1194 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); 1333 if (FLAG_mips_far_branches) {
1195 EmitIType(b, rs, rt, dest_off); 1334 const uint32_t dest_off = label->position_;
1335 EmitFarBranch(b, rs, rt, dest_off);
1336 } else {
1337 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
1338 EmitIType(b, rs, rt, dest_off);
1339 }
1196 label->LinkTo(position); 1340 label->LinkTo(position);
1197 } 1341 }
1198 } 1342 }
1199 1343
1200 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { 1344 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) {
1201 if (label->IsBound()) { 1345 if (label->IsBound()) {
regis 2013/07/25 20:07:43 ditto
zra 2013/07/26 21:26:15 Done.
1202 // Relative destination from an instruction after the branch. 1346 // Relative destination from an instruction after the branch.
1203 const int32_t dest = 1347 if (FLAG_mips_far_branches) {
1204 label->Position() - (buffer_.Size() + Instr::kInstrSize); 1348 const int32_t dest =
1205 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 1349 label->Position() - (buffer_.Size() + 7 * Instr::kInstrSize);
1206 EmitRegImmType(REGIMM, rs, b, dest_off); 1350 EmitFarRegImmBranch(b, rs, dest);
1351 } else {
1352 const int32_t dest =
1353 label->Position() - (buffer_.Size() + Instr::kInstrSize);
1354 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
1355 EmitRegImmType(REGIMM, rs, b, dest_off);
1356 }
1207 } else { 1357 } else {
1208 const int position = buffer_.Size(); 1358 const int position = buffer_.Size();
1209 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); 1359 if (FLAG_mips_far_branches) {
1210 EmitRegImmType(REGIMM, rs, b, dest_off); 1360 const uint32_t dest_off = label->position_;
1361 EmitFarRegImmBranch(b, rs, dest_off);
1362 } else {
1363 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
1364 EmitRegImmType(REGIMM, rs, b, dest_off);
1365 }
1211 label->LinkTo(position); 1366 label->LinkTo(position);
1212 } 1367 }
1213 } 1368 }
1214 1369
1215 void EmitFpuBranch(bool kind, Label *label) { 1370 void EmitFpuBranch(bool kind, Label *label) {
1216 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true. 1371 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true.
1217 if (label->IsBound()) { 1372 if (label->IsBound()) {
regis 2013/07/25 20:07:43 ditto
zra 2013/07/26 21:26:15 Done.
1218 // Relative destination from an instruction after the branch. 1373 // Relative destination from an instruction after the branch.
1219 const int32_t dest = 1374 if (FLAG_mips_far_branches) {
1220 label->Position() - (buffer_.Size() + Instr::kInstrSize); 1375 const int32_t dest =
1221 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 1376 label->Position() - (buffer_.Size() + 7 * Instr::kInstrSize);
1222 Emit(COP1 << kOpcodeShift | 1377 EmitFarFpuBranch(kind, dest);
1223 COP1_BC << kCop1SubShift | 1378 } else {
1224 b16 | 1379 const int32_t dest =
1225 dest_off); 1380 label->Position() - (buffer_.Size() + Instr::kInstrSize);
1381 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
1382 Emit(COP1 << kOpcodeShift |
1383 COP1_BC << kCop1SubShift |
1384 b16 |
1385 dest_off);
1386 }
1226 } else { 1387 } else {
1227 const int position = buffer_.Size(); 1388 const int position = buffer_.Size();
1228 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); 1389 if (FLAG_mips_far_branches) {
1229 Emit(COP1 << kOpcodeShift | 1390 const uint32_t dest_off = label->position_;
1230 COP1_BC << kCop1SubShift | 1391 EmitFarFpuBranch(kind, dest_off);
1231 b16 | 1392 } else {
1232 dest_off); 1393 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
1394 Emit(COP1 << kOpcodeShift |
1395 COP1_BC << kCop1SubShift |
1396 b16 |
1397 dest_off);
1398 }
1233 label->LinkTo(position); 1399 label->LinkTo(position);
1234 } 1400 }
1235 } 1401 }
1236 1402
1237 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr); 1403 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr);
1238 static int DecodeBranchOffset(int32_t instr); 1404 static int DecodeBranchOffset(int32_t instr);
1239 1405
1240 void EmitBranchDelayNop() { 1406 void EmitBranchDelayNop() {
1241 Emit(Instr::kNopInstruction); // Branch delay NOP. 1407 Emit(Instr::kNopInstruction); // Branch delay NOP.
1242 delay_slot_available_ = true; 1408 delay_slot_available_ = true;
1243 } 1409 }
1244 1410
1245 void StoreIntoObjectFilter(Register object, Register value, Label* no_update); 1411 void StoreIntoObjectFilter(Register object, Register value, Label* no_update);
1246 1412
1247 // Shorter filtering sequence that assumes that value is not a smi. 1413 // Shorter filtering sequence that assumes that value is not a smi.
1248 void StoreIntoObjectFilterNoSmi(Register object, 1414 void StoreIntoObjectFilterNoSmi(Register object,
1249 Register value, 1415 Register value,
1250 Label* no_update); 1416 Label* no_update);
1251 1417
1252 DISALLOW_ALLOCATION(); 1418 DISALLOW_ALLOCATION();
1253 DISALLOW_COPY_AND_ASSIGN(Assembler); 1419 DISALLOW_COPY_AND_ASSIGN(Assembler);
1254 }; 1420 };
1255 1421
1256 } // namespace dart 1422 } // namespace dart
1257 1423
1258 #endif // VM_ASSEMBLER_MIPS_H_ 1424 #endif // VM_ASSEMBLER_MIPS_H_
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/assembler_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698