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 916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
927 } | 927 } |
928 | 928 |
929 if (Utils::IsUint(kImmBits, imm)) { | 929 if (Utils::IsUint(kImmBits, imm)) { |
930 andi(rd, rs, Immediate(imm)); | 930 andi(rd, rs, Immediate(imm)); |
931 } else { | 931 } else { |
932 LoadImmediate(TMP, imm); | 932 LoadImmediate(TMP, imm); |
933 and_(rd, rs, TMP); | 933 and_(rd, rs, TMP); |
934 } | 934 } |
935 } | 935 } |
936 | 936 |
937 void OrImmediate(Register rd, Register rs, int32_t imm) { | |
938 ASSERT(!in_delay_slot_); | |
939 if (imm == 0) { | |
940 mov(rd, rs); | |
941 return; | |
942 } | |
943 | |
944 if (Utils::IsUint(kImmBits, imm)) { | |
945 ori(rd, rs, Immediate(imm)); | |
946 } else { | |
947 LoadImmediate(TMP, imm); | |
948 or_(rd, rs, TMP); | |
949 } | |
950 } | |
951 | |
952 void XorImmediate(Register rd, Register rs, int32_t imm) { | |
953 ASSERT(!in_delay_slot_); | |
954 if (imm == 0) { | |
955 mov(rd, rs); | |
956 return; | |
957 } | |
958 | |
959 if (Utils::IsUint(kImmBits, imm)) { | |
960 xori(rd, rs, Immediate(imm)); | |
961 } else { | |
962 LoadImmediate(TMP, imm); | |
963 xor_(rd, rs, TMP); | |
964 } | |
965 } | |
966 | |
967 // Branch to label if condition is true. | |
968 void BranchOnCondition(Condition cond, Label* l) { | |
969 ASSERT(!in_delay_slot_); | |
970 Register left = cond.left(); | |
971 Register right = cond.right(); | |
972 RelationOperator rel_op = cond.rel_op(); | |
973 switch (rel_op) { | |
974 case NV: return; | |
975 case AL: b(l); return; | |
976 case EQ: // fall through. | |
977 case NE: { | |
978 if (left == IMM) { | |
979 addiu(AT, ZR, Immediate(cond.imm())); | |
zra
2014/12/19 17:49:47
Why not LoadImmediate?
regis
2014/12/22 20:17:34
I like to see exactly what instruction we generate
| |
980 left = AT; | |
981 } else if (right == IMM) { | |
982 addiu(AT, ZR, Immediate(cond.imm())); | |
983 right = AT; | |
984 } | |
985 if (rel_op == EQ) { | |
986 beq(left, right, l); | |
987 } else { | |
988 bne(left, right, l); | |
989 } | |
990 break; | |
991 } | |
992 case GT: { | |
993 if (left == ZR) { | |
994 bltz(right, l); | |
995 } else if (right == ZR) { | |
996 bgtz(left, l); | |
997 } else if (left == IMM) { | |
998 slti(AT, right, Immediate(cond.imm())); | |
999 bne(AT, ZR, l); | |
1000 } else if (right == IMM) { | |
1001 slti(AT, left, Immediate(cond.imm() + 1)); | |
1002 beq(AT, ZR, l); | |
1003 } else { | |
1004 slt(AT, right, left); | |
1005 bne(AT, ZR, l); | |
1006 } | |
1007 break; | |
1008 } | |
1009 case GE: { | |
1010 if (left == ZR) { | |
1011 blez(right, l); | |
1012 } else if (right == ZR) { | |
1013 bgez(left, l); | |
1014 } else if (left == IMM) { | |
1015 slti(AT, right, Immediate(cond.imm() + 1)); | |
1016 bne(AT, ZR, l); | |
1017 } else if (right == IMM) { | |
1018 slti(AT, left, Immediate(cond.imm())); | |
1019 beq(AT, ZR, l); | |
1020 } else { | |
1021 slt(AT, left, right); | |
1022 beq(AT, ZR, l); | |
1023 } | |
1024 break; | |
1025 } | |
1026 case LT: { | |
1027 if (left == ZR) { | |
1028 bgtz(right, l); | |
1029 } else if (right == ZR) { | |
1030 bltz(left, l); | |
1031 } else if (left == IMM) { | |
1032 slti(AT, right, Immediate(cond.imm() + 1)); | |
1033 beq(AT, ZR, l); | |
1034 } else if (right == IMM) { | |
1035 slti(AT, left, Immediate(cond.imm())); | |
1036 bne(AT, ZR, l); | |
1037 } else { | |
1038 slt(AT, left, right); | |
1039 bne(AT, ZR, l); | |
1040 } | |
1041 break; | |
1042 } | |
1043 case LE: { | |
1044 if (left == ZR) { | |
1045 bgez(right, l); | |
1046 } else if (right == ZR) { | |
1047 blez(left, l); | |
1048 } else if (left == IMM) { | |
1049 slti(AT, right, Immediate(cond.imm())); | |
1050 beq(AT, ZR, l); | |
1051 } else if (right == IMM) { | |
1052 slti(AT, left, Immediate(cond.imm() + 1)); | |
1053 bne(AT, ZR, l); | |
1054 } else { | |
1055 slt(AT, right, left); | |
1056 beq(AT, ZR, l); | |
1057 } | |
1058 break; | |
1059 } | |
1060 case UGT: { | |
1061 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. | |
zra
2014/12/19 17:49:47
What do you do if you want to branch on an unsigne
regis
2014/12/22 20:17:34
This does not come up. The compiler will always al
| |
1062 if (left == ZR) { | |
1063 // NV: Never branch. Fall through. | |
1064 } else if (right == ZR) { | |
1065 bne(left, ZR, l); | |
1066 } else { | |
1067 sltu(AT, right, left); | |
1068 bne(AT, ZR, l); | |
1069 } | |
1070 break; | |
1071 } | |
1072 case UGE: { | |
1073 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. | |
1074 if (left == ZR) { | |
1075 beq(right, ZR, l); | |
1076 } else if (right == ZR) { | |
1077 // AL: Always branch to l. | |
1078 beq(ZR, ZR, l); | |
1079 } else { | |
1080 sltu(AT, left, right); | |
1081 beq(AT, ZR, l); | |
1082 } | |
1083 break; | |
1084 } | |
1085 case ULT: { | |
1086 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. | |
1087 if (left == ZR) { | |
1088 bne(right, ZR, l); | |
1089 } else if (right == ZR) { | |
1090 // NV: Never branch. Fall through. | |
1091 } else { | |
1092 sltu(AT, left, right); | |
1093 bne(AT, ZR, l); | |
1094 } | |
1095 break; | |
1096 } | |
1097 case ULE: { | |
1098 ASSERT((left != IMM) && (right != IMM)); // No unsigned constants used. | |
1099 if (left == ZR) { | |
1100 // AL: Always branch to l. | |
1101 beq(ZR, ZR, l); | |
1102 } else if (right == ZR) { | |
1103 beq(left, ZR, l); | |
1104 } else { | |
1105 sltu(AT, right, left); | |
1106 beq(AT, ZR, l); | |
1107 } | |
1108 break; | |
1109 } | |
1110 default: | |
1111 UNREACHABLE(); | |
1112 } | |
1113 } | |
1114 | |
937 void BranchEqual(Register rd, Register rn, Label* l) { | 1115 void BranchEqual(Register rd, Register rn, Label* l) { |
938 beq(rd, rn, l); | 1116 beq(rd, rn, l); |
939 } | 1117 } |
940 | 1118 |
941 void BranchEqual(Register rd, const Immediate& imm, Label* l) { | 1119 void BranchEqual(Register rd, const Immediate& imm, Label* l) { |
942 ASSERT(!in_delay_slot_); | 1120 ASSERT(!in_delay_slot_); |
943 if (imm.value() == 0) { | 1121 if (imm.value() == 0) { |
944 beq(rd, ZR, l); | 1122 beq(rd, ZR, l); |
945 } else { | 1123 } else { |
946 ASSERT(rd != CMPRES2); | 1124 ASSERT(rd != CMPRES2); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
982 ASSERT(!in_delay_slot_); | 1160 ASSERT(!in_delay_slot_); |
983 slt(CMPRES2, rs, rd); // CMPRES2 = rd > rs ? 1 : 0. | 1161 slt(CMPRES2, rs, rd); // CMPRES2 = rd > rs ? 1 : 0. |
984 bne(CMPRES2, ZR, l); | 1162 bne(CMPRES2, ZR, l); |
985 } | 1163 } |
986 | 1164 |
987 void BranchSignedGreater(Register rd, const Immediate& imm, Label* l) { | 1165 void BranchSignedGreater(Register rd, const Immediate& imm, Label* l) { |
988 ASSERT(!in_delay_slot_); | 1166 ASSERT(!in_delay_slot_); |
989 if (imm.value() == 0) { | 1167 if (imm.value() == 0) { |
990 bgtz(rd, l); | 1168 bgtz(rd, l); |
991 } else { | 1169 } else { |
992 ASSERT(rd != CMPRES2); | 1170 if (Utils::IsInt(kImmBits, imm.value() + 1)) { |
993 LoadImmediate(CMPRES2, imm.value()); | 1171 slti(CMPRES2, rd, Immediate(imm.value() + 1)); |
994 BranchSignedGreater(rd, CMPRES2, l); | 1172 beq(CMPRES2, ZR, l); |
1173 } else { | |
1174 ASSERT(rd != CMPRES2); | |
1175 LoadImmediate(CMPRES2, imm.value()); | |
1176 BranchSignedGreater(rd, CMPRES2, l); | |
1177 } | |
995 } | 1178 } |
996 } | 1179 } |
997 | 1180 |
998 void BranchUnsignedGreater(Register rd, Register rs, Label* l) { | 1181 void BranchUnsignedGreater(Register rd, Register rs, Label* l) { |
999 ASSERT(!in_delay_slot_); | 1182 ASSERT(!in_delay_slot_); |
1000 sltu(CMPRES2, rs, rd); | 1183 sltu(CMPRES2, rs, rd); |
1001 bne(CMPRES2, ZR, l); | 1184 bne(CMPRES2, ZR, l); |
1002 } | 1185 } |
1003 | 1186 |
1004 void BranchUnsignedGreater(Register rd, const Immediate& imm, Label* l) { | 1187 void BranchUnsignedGreater(Register rd, const Immediate& imm, Label* l) { |
1005 ASSERT(!in_delay_slot_); | 1188 ASSERT(!in_delay_slot_); |
1006 if (imm.value() == 0) { | 1189 if (imm.value() == 0) { |
1007 BranchNotEqual(rd, Immediate(0), l); | 1190 BranchNotEqual(rd, Immediate(0), l); |
1008 } else { | 1191 } else { |
1009 ASSERT(rd != CMPRES2); | 1192 if ((imm.value() != -1) && Utils::IsInt(kImmBits, imm.value() + 1)) { |
1010 LoadImmediate(CMPRES2, imm.value()); | 1193 sltiu(CMPRES2, rd, Immediate(imm.value() + 1)); |
1011 BranchUnsignedGreater(rd, CMPRES2, l); | 1194 beq(CMPRES2, ZR, l); |
1195 } else { | |
1196 ASSERT(rd != CMPRES2); | |
1197 LoadImmediate(CMPRES2, imm.value()); | |
1198 BranchUnsignedGreater(rd, CMPRES2, l); | |
1199 } | |
1012 } | 1200 } |
1013 } | 1201 } |
1014 | 1202 |
1015 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) { | 1203 void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) { |
1016 ASSERT(!in_delay_slot_); | 1204 ASSERT(!in_delay_slot_); |
1017 slt(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. | 1205 slt(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. |
1018 beq(CMPRES2, ZR, l); // If CMPRES2 = 0, then rd >= rs. | 1206 beq(CMPRES2, ZR, l); // If CMPRES2 = 0, then rd >= rs. |
1019 } | 1207 } |
1020 | 1208 |
1021 void BranchSignedGreaterEqual(Register rd, const Immediate& imm, Label* l) { | 1209 void BranchSignedGreaterEqual(Register rd, const Immediate& imm, Label* l) { |
(...skipping 16 matching lines...) Expand all Loading... | |
1038 ASSERT(!in_delay_slot_); | 1226 ASSERT(!in_delay_slot_); |
1039 sltu(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. | 1227 sltu(CMPRES2, rd, rs); // CMPRES2 = rd < rs ? 1 : 0. |
1040 beq(CMPRES2, ZR, l); | 1228 beq(CMPRES2, ZR, l); |
1041 } | 1229 } |
1042 | 1230 |
1043 void BranchUnsignedGreaterEqual(Register rd, const Immediate& imm, Label* l) { | 1231 void BranchUnsignedGreaterEqual(Register rd, const Immediate& imm, Label* l) { |
1044 ASSERT(!in_delay_slot_); | 1232 ASSERT(!in_delay_slot_); |
1045 if (imm.value() == 0) { | 1233 if (imm.value() == 0) { |
1046 b(l); | 1234 b(l); |
1047 } else { | 1235 } else { |
1048 if (Utils::IsUint(kImmBits, imm.value())) { | 1236 if (Utils::IsInt(kImmBits, imm.value())) { |
1049 sltiu(CMPRES2, rd, imm); | 1237 sltiu(CMPRES2, rd, imm); |
1050 beq(CMPRES2, ZR, l); | 1238 beq(CMPRES2, ZR, l); |
1051 } else { | 1239 } else { |
1052 ASSERT(rd != CMPRES2); | 1240 ASSERT(rd != CMPRES2); |
1053 LoadImmediate(CMPRES2, imm.value()); | 1241 LoadImmediate(CMPRES2, imm.value()); |
1054 BranchUnsignedGreaterEqual(rd, CMPRES2, l); | 1242 BranchUnsignedGreaterEqual(rd, CMPRES2, l); |
1055 } | 1243 } |
1056 } | 1244 } |
1057 } | 1245 } |
1058 | 1246 |
(...skipping 18 matching lines...) Expand all Loading... | |
1077 } | 1265 } |
1078 } | 1266 } |
1079 | 1267 |
1080 void BranchUnsignedLess(Register rd, Register rs, Label* l) { | 1268 void BranchUnsignedLess(Register rd, Register rs, Label* l) { |
1081 ASSERT(!in_delay_slot_); | 1269 ASSERT(!in_delay_slot_); |
1082 BranchUnsignedGreater(rs, rd, l); | 1270 BranchUnsignedGreater(rs, rd, l); |
1083 } | 1271 } |
1084 | 1272 |
1085 void BranchUnsignedLess(Register rd, const Immediate& imm, Label* l) { | 1273 void BranchUnsignedLess(Register rd, const Immediate& imm, Label* l) { |
1086 ASSERT(!in_delay_slot_); | 1274 ASSERT(!in_delay_slot_); |
1087 ASSERT(imm.value() != 0); | 1275 if (imm.value() == 0) { |
1088 if (Utils::IsInt(kImmBits, imm.value())) { | 1276 // Never branch. Fall through. |
1089 sltiu(CMPRES2, rd, imm); | |
1090 bne(CMPRES2, ZR, l); | |
1091 } else { | 1277 } else { |
1092 ASSERT(rd != CMPRES2); | 1278 if (Utils::IsInt(kImmBits, imm.value())) { |
1093 LoadImmediate(CMPRES2, imm.value()); | 1279 sltiu(CMPRES2, rd, imm); |
1094 BranchUnsignedGreater(CMPRES2, rd, l); | 1280 bne(CMPRES2, ZR, l); |
1281 } else { | |
1282 ASSERT(rd != CMPRES2); | |
1283 LoadImmediate(CMPRES2, imm.value()); | |
1284 BranchUnsignedGreater(CMPRES2, rd, l); | |
1285 } | |
1095 } | 1286 } |
1096 } | 1287 } |
1097 | 1288 |
1098 void BranchSignedLessEqual(Register rd, Register rs, Label* l) { | 1289 void BranchSignedLessEqual(Register rd, Register rs, Label* l) { |
1099 ASSERT(!in_delay_slot_); | 1290 ASSERT(!in_delay_slot_); |
1100 BranchSignedGreaterEqual(rs, rd, l); | 1291 BranchSignedGreaterEqual(rs, rd, l); |
1101 } | 1292 } |
1102 | 1293 |
1103 void BranchSignedLessEqual(Register rd, const Immediate& imm, Label* l) { | 1294 void BranchSignedLessEqual(Register rd, const Immediate& imm, Label* l) { |
1104 ASSERT(!in_delay_slot_); | 1295 ASSERT(!in_delay_slot_); |
1105 if (imm.value() == 0) { | 1296 if (imm.value() == 0) { |
1106 blez(rd, l); | 1297 blez(rd, l); |
1107 } else { | 1298 } else { |
1108 ASSERT(rd != CMPRES2); | 1299 if (Utils::IsInt(kImmBits, imm.value() + 1)) { |
1109 LoadImmediate(CMPRES2, imm.value()); | 1300 slti(CMPRES2, rd, Immediate(imm.value() + 1)); |
1110 BranchSignedGreaterEqual(CMPRES2, rd, l); | 1301 bne(CMPRES2, ZR, l); |
1302 } else { | |
1303 ASSERT(rd != CMPRES2); | |
1304 LoadImmediate(CMPRES2, imm.value()); | |
1305 BranchSignedGreaterEqual(CMPRES2, rd, l); | |
1306 } | |
1111 } | 1307 } |
1112 } | 1308 } |
1113 | 1309 |
1114 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) { | 1310 void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) { |
1115 ASSERT(!in_delay_slot_); | 1311 ASSERT(!in_delay_slot_); |
1116 BranchUnsignedGreaterEqual(rs, rd, l); | 1312 BranchUnsignedGreaterEqual(rs, rd, l); |
1117 } | 1313 } |
1118 | 1314 |
1119 void BranchUnsignedLessEqual(Register rd, const Immediate& imm, Label* l) { | 1315 void BranchUnsignedLessEqual(Register rd, const Immediate& imm, Label* l) { |
1120 ASSERT(!in_delay_slot_); | 1316 ASSERT(!in_delay_slot_); |
1121 ASSERT(rd != CMPRES2); | 1317 if (imm.value() == 0) { |
1122 LoadImmediate(CMPRES2, imm.value()); | 1318 beq(rd, ZR, l); |
1123 BranchUnsignedGreaterEqual(CMPRES2, rd, l); | 1319 } else { |
1320 if ((imm.value() != -1) && Utils::IsInt(kImmBits, imm.value() + 1)) { | |
1321 sltiu(CMPRES2, rd, Immediate(imm.value() + 1)); | |
1322 bne(CMPRES2, ZR, l); | |
1323 } else { | |
1324 ASSERT(rd != CMPRES2); | |
1325 LoadImmediate(CMPRES2, imm.value()); | |
1326 BranchUnsignedGreaterEqual(CMPRES2, rd, l); | |
1327 } | |
1328 } | |
1124 } | 1329 } |
1125 | 1330 |
1126 void Push(Register rt) { | 1331 void Push(Register rt) { |
1127 ASSERT(!in_delay_slot_); | 1332 ASSERT(!in_delay_slot_); |
1128 addiu(SP, SP, Immediate(-kWordSize)); | 1333 addiu(SP, SP, Immediate(-kWordSize)); |
1129 sw(rt, Address(SP)); | 1334 sw(rt, Address(SP)); |
1130 } | 1335 } |
1131 | 1336 |
1132 void Pop(Register rt) { | 1337 void Pop(Register rt) { |
1133 ASSERT(!in_delay_slot_); | 1338 ASSERT(!in_delay_slot_); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1211 // Create a frame for calling into runtime that preserves all volatile | 1416 // Create a frame for calling into runtime that preserves all volatile |
1212 // registers. Frame's SP is guaranteed to be correctly aligned and | 1417 // registers. Frame's SP is guaranteed to be correctly aligned and |
1213 // frame_space bytes are reserved under it. | 1418 // frame_space bytes are reserved under it. |
1214 void EnterCallRuntimeFrame(intptr_t frame_space); | 1419 void EnterCallRuntimeFrame(intptr_t frame_space); |
1215 void LeaveCallRuntimeFrame(); | 1420 void LeaveCallRuntimeFrame(); |
1216 | 1421 |
1217 void LoadWordFromPoolOffset(Register rd, int32_t offset); | 1422 void LoadWordFromPoolOffset(Register rd, int32_t offset); |
1218 void LoadObject(Register rd, const Object& object); | 1423 void LoadObject(Register rd, const Object& object); |
1219 void PushObject(const Object& object); | 1424 void PushObject(const Object& object); |
1220 | 1425 |
1221 // Compares rn with the object. Returns results in rd1 and rd2. | |
1222 // rd1 is 1 if rn < object. rd2 is 1 if object < rn. Since both cannot be | |
1223 // 1, rd1 == rd2 (== 0) iff rn == object. | |
1224 void CompareObject(Register rd1, Register rd2, | |
1225 Register rn, const Object& object); | |
1226 | |
1227 void LoadIsolate(Register result); | 1426 void LoadIsolate(Register result); |
1228 | 1427 |
1229 void LoadClassId(Register result, Register object); | 1428 void LoadClassId(Register result, Register object); |
1230 void LoadClassById(Register result, Register class_id); | 1429 void LoadClassById(Register result, Register class_id); |
1231 void LoadClass(Register result, Register object); | 1430 void LoadClass(Register result, Register object); |
1232 void LoadTaggedClassIdMayBeSmi(Register result, Register object); | 1431 void LoadTaggedClassIdMayBeSmi(Register result, Register object); |
1233 | 1432 |
1234 void ComputeRange(Register result, | 1433 void ComputeRange(Register result, |
1235 Register value, | 1434 Register value, |
1236 Label* miss); | 1435 Label* miss); |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1431 Register value, | 1630 Register value, |
1432 Label* no_update); | 1631 Label* no_update); |
1433 | 1632 |
1434 DISALLOW_ALLOCATION(); | 1633 DISALLOW_ALLOCATION(); |
1435 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1634 DISALLOW_COPY_AND_ASSIGN(Assembler); |
1436 }; | 1635 }; |
1437 | 1636 |
1438 } // namespace dart | 1637 } // namespace dart |
1439 | 1638 |
1440 #endif // VM_ASSEMBLER_MIPS_H_ | 1639 #endif // VM_ASSEMBLER_MIPS_H_ |
OLD | NEW |