OLD | NEW |
1 // Copyright (c) 1994-2006 Sun Microsystems Inc. | 1 // Copyright (c) 1994-2006 Sun Microsystems Inc. |
2 // All Rights Reserved. | 2 // All Rights Reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // - Redistributions of source code must retain the above copyright notice, | 8 // - Redistributions of source code must retain the above copyright notice, |
9 // this list of conditions and the following disclaimer. | 9 // this list of conditions and the following disclaimer. |
10 // | 10 // |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 supported_ |= CpuFeaturesImpliedByCompiler(); | 91 supported_ |= CpuFeaturesImpliedByCompiler(); |
92 | 92 |
93 // Only use statically determined features for cross compile (snapshot). | 93 // Only use statically determined features for cross compile (snapshot). |
94 if (cross_compile) return; | 94 if (cross_compile) return; |
95 | 95 |
96 // If the compiler is allowed to use fpu then we can use fpu too in our | 96 // If the compiler is allowed to use fpu then we can use fpu too in our |
97 // code generation. | 97 // code generation. |
98 #ifndef __mips__ | 98 #ifndef __mips__ |
99 // For the simulator build, use FPU. | 99 // For the simulator build, use FPU. |
100 supported_ |= 1u << FPU; | 100 supported_ |= 1u << FPU; |
101 #if defined(_MIPS_ARCH_MIPS32R6) | |
102 // FP64 mode is implied on r6. | |
103 supported_ |= 1u << FP64; | |
104 #endif | |
105 #if defined(FPU_MODE_FP64) | |
106 supported_ |= 1u << FP64; | |
107 #endif | |
108 #else | 101 #else |
109 // Probe for additional features at runtime. | 102 // Probe for additional features at runtime. |
110 base::CPU cpu; | 103 base::CPU cpu; |
111 if (cpu.has_fpu()) supported_ |= 1u << FPU; | 104 if (cpu.has_fpu()) supported_ |= 1u << FPU; |
112 #if defined(FPU_MODE_FPXX) | |
113 if (cpu.is_fp64_mode()) supported_ |= 1u << FP64; | |
114 #elif defined(FPU_MODE_FP64) | |
115 supported_ |= 1u << FP64; | |
116 #endif | |
117 #if defined(_MIPS_ARCH_MIPS32RX) | |
118 if (cpu.architecture() == 6) { | |
119 supported_ |= 1u << MIPSr6; | |
120 } else if (cpu.architecture() == 2) { | |
121 supported_ |= 1u << MIPSr1; | |
122 supported_ |= 1u << MIPSr2; | |
123 } else { | |
124 supported_ |= 1u << MIPSr1; | |
125 } | |
126 #endif | |
127 #endif | 105 #endif |
128 } | 106 } |
129 | 107 |
130 | 108 |
131 void CpuFeatures::PrintTarget() { } | 109 void CpuFeatures::PrintTarget() { } |
132 void CpuFeatures::PrintFeatures() { } | 110 void CpuFeatures::PrintFeatures() { } |
133 | 111 |
134 | 112 |
135 int ToNumber(Register reg) { | 113 int ToNumber(Register reg) { |
136 DCHECK(reg.is_valid()); | 114 DCHECK(reg.is_valid()); |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 return opcode == BEQ || | 477 return opcode == BEQ || |
500 opcode == BNE || | 478 opcode == BNE || |
501 opcode == BLEZ || | 479 opcode == BLEZ || |
502 opcode == BGTZ || | 480 opcode == BGTZ || |
503 opcode == BEQL || | 481 opcode == BEQL || |
504 opcode == BNEL || | 482 opcode == BNEL || |
505 opcode == BLEZL || | 483 opcode == BLEZL || |
506 opcode == BGTZL || | 484 opcode == BGTZL || |
507 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || | 485 (opcode == REGIMM && (rt_field == BLTZ || rt_field == BGEZ || |
508 rt_field == BLTZAL || rt_field == BGEZAL)) || | 486 rt_field == BLTZAL || rt_field == BGEZAL)) || |
509 (opcode == COP1 && rs_field == BC1) || // Coprocessor branch. | 487 (opcode == COP1 && rs_field == BC1); // Coprocessor branch. |
510 (opcode == COP1 && rs_field == BC1EQZ) || | |
511 (opcode == COP1 && rs_field == BC1NEZ); | |
512 } | 488 } |
513 | 489 |
514 | 490 |
515 bool Assembler::IsEmittedConstant(Instr instr) { | 491 bool Assembler::IsEmittedConstant(Instr instr) { |
516 uint32_t label_constant = GetLabelConst(instr); | 492 uint32_t label_constant = GetLabelConst(instr); |
517 return label_constant == 0; // Emitted label const in reg-exp engine. | 493 return label_constant == 0; // Emitted label const in reg-exp engine. |
518 } | 494 } |
519 | 495 |
520 | 496 |
521 bool Assembler::IsBeq(Instr instr) { | 497 bool Assembler::IsBeq(Instr instr) { |
(...skipping 24 matching lines...) Expand all Loading... |
546 return opcode == J; | 522 return opcode == J; |
547 } | 523 } |
548 | 524 |
549 | 525 |
550 bool Assembler::IsJal(Instr instr) { | 526 bool Assembler::IsJal(Instr instr) { |
551 return GetOpcodeField(instr) == JAL; | 527 return GetOpcodeField(instr) == JAL; |
552 } | 528 } |
553 | 529 |
554 | 530 |
555 bool Assembler::IsJr(Instr instr) { | 531 bool Assembler::IsJr(Instr instr) { |
556 if (!IsMipsArchVariant(kMips32r6)) { | 532 return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR; |
557 return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JR; | |
558 } else { | |
559 return GetOpcodeField(instr) == SPECIAL && | |
560 GetRdField(instr) == 0 && GetFunctionField(instr) == JALR; | |
561 } | |
562 } | 533 } |
563 | 534 |
564 | 535 |
565 bool Assembler::IsJalr(Instr instr) { | 536 bool Assembler::IsJalr(Instr instr) { |
566 return GetOpcodeField(instr) == SPECIAL && | 537 return GetOpcodeField(instr) == SPECIAL && GetFunctionField(instr) == JALR; |
567 GetRdField(instr) != 0 && GetFunctionField(instr) == JALR; | |
568 } | 538 } |
569 | 539 |
570 | 540 |
571 bool Assembler::IsLui(Instr instr) { | 541 bool Assembler::IsLui(Instr instr) { |
572 uint32_t opcode = GetOpcodeField(instr); | 542 uint32_t opcode = GetOpcodeField(instr); |
573 // Checks if the instruction is a load upper immediate. | 543 // Checks if the instruction is a load upper immediate. |
574 return opcode == LUI; | 544 return opcode == LUI; |
575 } | 545 } |
576 | 546 |
577 | 547 |
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 } | 1012 } |
1043 | 1013 |
1044 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); | 1014 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); |
1045 DCHECK((offset & 3) == 0); | 1015 DCHECK((offset & 3) == 0); |
1046 DCHECK(is_int16(offset >> 2)); | 1016 DCHECK(is_int16(offset >> 2)); |
1047 | 1017 |
1048 return offset; | 1018 return offset; |
1049 } | 1019 } |
1050 | 1020 |
1051 | 1021 |
1052 int32_t Assembler::branch_offset_compact(Label* L, | |
1053 bool jump_elimination_allowed) { | |
1054 int32_t target_pos; | |
1055 if (L->is_bound()) { | |
1056 target_pos = L->pos(); | |
1057 } else { | |
1058 if (L->is_linked()) { | |
1059 target_pos = L->pos(); | |
1060 L->link_to(pc_offset()); | |
1061 } else { | |
1062 L->link_to(pc_offset()); | |
1063 if (!trampoline_emitted_) { | |
1064 unbound_labels_count_++; | |
1065 next_buffer_check_ -= kTrampolineSlotsSize; | |
1066 } | |
1067 return kEndOfChain; | |
1068 } | |
1069 } | |
1070 | |
1071 int32_t offset = target_pos - pc_offset(); | |
1072 DCHECK((offset & 3) == 0); | |
1073 DCHECK(is_int16(offset >> 2)); | |
1074 | |
1075 return offset; | |
1076 } | |
1077 | |
1078 | |
1079 int32_t Assembler::branch_offset21(Label* L, bool jump_elimination_allowed) { | |
1080 int32_t target_pos; | |
1081 | |
1082 if (L->is_bound()) { | |
1083 target_pos = L->pos(); | |
1084 } else { | |
1085 if (L->is_linked()) { | |
1086 target_pos = L->pos(); | |
1087 L->link_to(pc_offset()); | |
1088 } else { | |
1089 L->link_to(pc_offset()); | |
1090 if (!trampoline_emitted_) { | |
1091 unbound_labels_count_++; | |
1092 next_buffer_check_ -= kTrampolineSlotsSize; | |
1093 } | |
1094 return kEndOfChain; | |
1095 } | |
1096 } | |
1097 | |
1098 int32_t offset = target_pos - (pc_offset() + kBranchPCOffset); | |
1099 DCHECK((offset & 3) == 0); | |
1100 DCHECK(((offset >> 2) & 0xFFE00000) == 0); // Offset is 21bit width. | |
1101 | |
1102 return offset; | |
1103 } | |
1104 | |
1105 | |
1106 int32_t Assembler::branch_offset21_compact(Label* L, | |
1107 bool jump_elimination_allowed) { | |
1108 int32_t target_pos; | |
1109 | |
1110 if (L->is_bound()) { | |
1111 target_pos = L->pos(); | |
1112 } else { | |
1113 if (L->is_linked()) { | |
1114 target_pos = L->pos(); | |
1115 L->link_to(pc_offset()); | |
1116 } else { | |
1117 L->link_to(pc_offset()); | |
1118 if (!trampoline_emitted_) { | |
1119 unbound_labels_count_++; | |
1120 next_buffer_check_ -= kTrampolineSlotsSize; | |
1121 } | |
1122 return kEndOfChain; | |
1123 } | |
1124 } | |
1125 | |
1126 int32_t offset = target_pos - pc_offset(); | |
1127 DCHECK((offset & 3) == 0); | |
1128 DCHECK(((offset >> 2) & 0xFFe00000) == 0); // Offset is 21bit width. | |
1129 | |
1130 return offset; | |
1131 } | |
1132 | |
1133 | |
1134 void Assembler::label_at_put(Label* L, int at_offset) { | 1022 void Assembler::label_at_put(Label* L, int at_offset) { |
1135 int target_pos; | 1023 int target_pos; |
1136 if (L->is_bound()) { | 1024 if (L->is_bound()) { |
1137 target_pos = L->pos(); | 1025 target_pos = L->pos(); |
1138 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); | 1026 instr_at_put(at_offset, target_pos + (Code::kHeaderSize - kHeapObjectTag)); |
1139 } else { | 1027 } else { |
1140 if (L->is_linked()) { | 1028 if (L->is_linked()) { |
1141 target_pos = L->pos(); // L's link. | 1029 target_pos = L->pos(); // L's link. |
1142 int32_t imm18 = target_pos - at_offset; | 1030 int32_t imm18 = target_pos - at_offset; |
1143 DCHECK((imm18 & 3) == 0); | 1031 DCHECK((imm18 & 3) == 0); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1177 } | 1065 } |
1178 | 1066 |
1179 | 1067 |
1180 void Assembler::bgez(Register rs, int16_t offset) { | 1068 void Assembler::bgez(Register rs, int16_t offset) { |
1181 BlockTrampolinePoolScope block_trampoline_pool(this); | 1069 BlockTrampolinePoolScope block_trampoline_pool(this); |
1182 GenInstrImmediate(REGIMM, rs, BGEZ, offset); | 1070 GenInstrImmediate(REGIMM, rs, BGEZ, offset); |
1183 BlockTrampolinePoolFor(1); // For associated delay slot. | 1071 BlockTrampolinePoolFor(1); // For associated delay slot. |
1184 } | 1072 } |
1185 | 1073 |
1186 | 1074 |
1187 void Assembler::bgezc(Register rt, int16_t offset) { | |
1188 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1189 DCHECK(!(rt.is(zero_reg))); | |
1190 GenInstrImmediate(BLEZL, rt, rt, offset); | |
1191 } | |
1192 | |
1193 | |
1194 void Assembler::bgeuc(Register rs, Register rt, int16_t offset) { | |
1195 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1196 DCHECK(!(rs.is(zero_reg))); | |
1197 DCHECK(!(rt.is(zero_reg))); | |
1198 DCHECK(rs.code() != rt.code()); | |
1199 GenInstrImmediate(BLEZ, rs, rt, offset); | |
1200 } | |
1201 | |
1202 | |
1203 void Assembler::bgec(Register rs, Register rt, int16_t offset) { | |
1204 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1205 DCHECK(!(rs.is(zero_reg))); | |
1206 DCHECK(!(rt.is(zero_reg))); | |
1207 DCHECK(rs.code() != rt.code()); | |
1208 GenInstrImmediate(BLEZL, rs, rt, offset); | |
1209 } | |
1210 | |
1211 | |
1212 void Assembler::bgezal(Register rs, int16_t offset) { | 1075 void Assembler::bgezal(Register rs, int16_t offset) { |
1213 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg)); | |
1214 BlockTrampolinePoolScope block_trampoline_pool(this); | 1076 BlockTrampolinePoolScope block_trampoline_pool(this); |
1215 positions_recorder()->WriteRecordedPositions(); | 1077 positions_recorder()->WriteRecordedPositions(); |
1216 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); | 1078 GenInstrImmediate(REGIMM, rs, BGEZAL, offset); |
1217 BlockTrampolinePoolFor(1); // For associated delay slot. | 1079 BlockTrampolinePoolFor(1); // For associated delay slot. |
1218 } | 1080 } |
1219 | 1081 |
1220 | 1082 |
1221 void Assembler::bgtz(Register rs, int16_t offset) { | 1083 void Assembler::bgtz(Register rs, int16_t offset) { |
1222 BlockTrampolinePoolScope block_trampoline_pool(this); | 1084 BlockTrampolinePoolScope block_trampoline_pool(this); |
1223 GenInstrImmediate(BGTZ, rs, zero_reg, offset); | 1085 GenInstrImmediate(BGTZ, rs, zero_reg, offset); |
1224 BlockTrampolinePoolFor(1); // For associated delay slot. | 1086 BlockTrampolinePoolFor(1); // For associated delay slot. |
1225 } | 1087 } |
1226 | 1088 |
1227 | 1089 |
1228 void Assembler::bgtzc(Register rt, int16_t offset) { | |
1229 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1230 DCHECK(!(rt.is(zero_reg))); | |
1231 GenInstrImmediate(BGTZL, zero_reg, rt, offset); | |
1232 } | |
1233 | |
1234 | |
1235 void Assembler::blez(Register rs, int16_t offset) { | 1090 void Assembler::blez(Register rs, int16_t offset) { |
1236 BlockTrampolinePoolScope block_trampoline_pool(this); | 1091 BlockTrampolinePoolScope block_trampoline_pool(this); |
1237 GenInstrImmediate(BLEZ, rs, zero_reg, offset); | 1092 GenInstrImmediate(BLEZ, rs, zero_reg, offset); |
1238 BlockTrampolinePoolFor(1); // For associated delay slot. | 1093 BlockTrampolinePoolFor(1); // For associated delay slot. |
1239 } | 1094 } |
1240 | 1095 |
1241 | 1096 |
1242 void Assembler::blezc(Register rt, int16_t offset) { | |
1243 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1244 DCHECK(!(rt.is(zero_reg))); | |
1245 GenInstrImmediate(BLEZL, zero_reg, rt, offset); | |
1246 } | |
1247 | |
1248 | |
1249 void Assembler::bltzc(Register rt, int16_t offset) { | |
1250 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1251 DCHECK(!(rt.is(zero_reg))); | |
1252 GenInstrImmediate(BGTZL, rt, rt, offset); | |
1253 } | |
1254 | |
1255 | |
1256 void Assembler::bltuc(Register rs, Register rt, int16_t offset) { | |
1257 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1258 DCHECK(!(rs.is(zero_reg))); | |
1259 DCHECK(!(rt.is(zero_reg))); | |
1260 DCHECK(rs.code() != rt.code()); | |
1261 GenInstrImmediate(BGTZ, rs, rt, offset); | |
1262 } | |
1263 | |
1264 | |
1265 void Assembler::bltc(Register rs, Register rt, int16_t offset) { | |
1266 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1267 DCHECK(!(rs.is(zero_reg))); | |
1268 DCHECK(!(rt.is(zero_reg))); | |
1269 DCHECK(rs.code() != rt.code()); | |
1270 GenInstrImmediate(BGTZL, rs, rt, offset); | |
1271 } | |
1272 | |
1273 | |
1274 void Assembler::bltz(Register rs, int16_t offset) { | 1097 void Assembler::bltz(Register rs, int16_t offset) { |
1275 BlockTrampolinePoolScope block_trampoline_pool(this); | 1098 BlockTrampolinePoolScope block_trampoline_pool(this); |
1276 GenInstrImmediate(REGIMM, rs, BLTZ, offset); | 1099 GenInstrImmediate(REGIMM, rs, BLTZ, offset); |
1277 BlockTrampolinePoolFor(1); // For associated delay slot. | 1100 BlockTrampolinePoolFor(1); // For associated delay slot. |
1278 } | 1101 } |
1279 | 1102 |
1280 | 1103 |
1281 void Assembler::bltzal(Register rs, int16_t offset) { | 1104 void Assembler::bltzal(Register rs, int16_t offset) { |
1282 DCHECK(!IsMipsArchVariant(kMips32r6) || rs.is(zero_reg)); | |
1283 BlockTrampolinePoolScope block_trampoline_pool(this); | 1105 BlockTrampolinePoolScope block_trampoline_pool(this); |
1284 positions_recorder()->WriteRecordedPositions(); | 1106 positions_recorder()->WriteRecordedPositions(); |
1285 GenInstrImmediate(REGIMM, rs, BLTZAL, offset); | 1107 GenInstrImmediate(REGIMM, rs, BLTZAL, offset); |
1286 BlockTrampolinePoolFor(1); // For associated delay slot. | 1108 BlockTrampolinePoolFor(1); // For associated delay slot. |
1287 } | 1109 } |
1288 | 1110 |
1289 | 1111 |
1290 void Assembler::bne(Register rs, Register rt, int16_t offset) { | 1112 void Assembler::bne(Register rs, Register rt, int16_t offset) { |
1291 BlockTrampolinePoolScope block_trampoline_pool(this); | 1113 BlockTrampolinePoolScope block_trampoline_pool(this); |
1292 GenInstrImmediate(BNE, rs, rt, offset); | 1114 GenInstrImmediate(BNE, rs, rt, offset); |
1293 BlockTrampolinePoolFor(1); // For associated delay slot. | 1115 BlockTrampolinePoolFor(1); // For associated delay slot. |
1294 } | 1116 } |
1295 | 1117 |
1296 | 1118 |
1297 void Assembler::bovc(Register rs, Register rt, int16_t offset) { | |
1298 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1299 DCHECK(!(rs.is(zero_reg))); | |
1300 DCHECK(rs.code() >= rt.code()); | |
1301 GenInstrImmediate(ADDI, rs, rt, offset); | |
1302 } | |
1303 | |
1304 | |
1305 void Assembler::bnvc(Register rs, Register rt, int16_t offset) { | |
1306 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1307 DCHECK(!(rs.is(zero_reg))); | |
1308 DCHECK(rs.code() >= rt.code()); | |
1309 GenInstrImmediate(DADDI, rs, rt, offset); | |
1310 } | |
1311 | |
1312 | |
1313 void Assembler::blezalc(Register rt, int16_t offset) { | |
1314 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1315 DCHECK(!(rt.is(zero_reg))); | |
1316 GenInstrImmediate(BLEZ, zero_reg, rt, offset); | |
1317 } | |
1318 | |
1319 | |
1320 void Assembler::bgezalc(Register rt, int16_t offset) { | |
1321 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1322 DCHECK(!(rt.is(zero_reg))); | |
1323 GenInstrImmediate(BLEZ, rt, rt, offset); | |
1324 } | |
1325 | |
1326 | |
1327 void Assembler::bgezall(Register rs, int16_t offset) { | |
1328 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1329 DCHECK(!(rs.is(zero_reg))); | |
1330 GenInstrImmediate(REGIMM, rs, BGEZALL, offset); | |
1331 } | |
1332 | |
1333 | |
1334 void Assembler::bltzalc(Register rt, int16_t offset) { | |
1335 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1336 DCHECK(!(rt.is(zero_reg))); | |
1337 GenInstrImmediate(BGTZ, rt, rt, offset); | |
1338 } | |
1339 | |
1340 | |
1341 void Assembler::bgtzalc(Register rt, int16_t offset) { | |
1342 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1343 DCHECK(!(rt.is(zero_reg))); | |
1344 GenInstrImmediate(BGTZ, zero_reg, rt, offset); | |
1345 } | |
1346 | |
1347 | |
1348 void Assembler::beqzalc(Register rt, int16_t offset) { | |
1349 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1350 DCHECK(!(rt.is(zero_reg))); | |
1351 GenInstrImmediate(ADDI, zero_reg, rt, offset); | |
1352 } | |
1353 | |
1354 | |
1355 void Assembler::bnezalc(Register rt, int16_t offset) { | |
1356 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1357 DCHECK(!(rt.is(zero_reg))); | |
1358 GenInstrImmediate(DADDI, zero_reg, rt, offset); | |
1359 } | |
1360 | |
1361 | |
1362 void Assembler::beqc(Register rs, Register rt, int16_t offset) { | |
1363 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1364 DCHECK(rs.code() < rt.code()); | |
1365 GenInstrImmediate(ADDI, rs, rt, offset); | |
1366 } | |
1367 | |
1368 | |
1369 void Assembler::beqzc(Register rs, int32_t offset) { | |
1370 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1371 DCHECK(!(rs.is(zero_reg))); | |
1372 Instr instr = BEQZC | (rs.code() << kRsShift) | offset; | |
1373 emit(instr); | |
1374 } | |
1375 | |
1376 | |
1377 void Assembler::bnec(Register rs, Register rt, int16_t offset) { | |
1378 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1379 DCHECK(rs.code() < rt.code()); | |
1380 GenInstrImmediate(DADDI, rs, rt, offset); | |
1381 } | |
1382 | |
1383 | |
1384 void Assembler::bnezc(Register rs, int32_t offset) { | |
1385 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1386 DCHECK(!(rs.is(zero_reg))); | |
1387 Instr instr = BNEZC | (rs.code() << kRsShift) | offset; | |
1388 emit(instr); | |
1389 } | |
1390 | |
1391 | |
1392 void Assembler::j(int32_t target) { | 1119 void Assembler::j(int32_t target) { |
1393 #if DEBUG | 1120 #if DEBUG |
1394 // Get pc of delay slot. | 1121 // Get pc of delay slot. |
1395 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); | 1122 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); |
1396 bool in_range = (ipc ^ static_cast<uint32_t>(target) >> | 1123 bool in_range = (ipc ^ static_cast<uint32_t>(target) >> |
1397 (kImm26Bits + kImmFieldShift)) == 0; | 1124 (kImm26Bits + kImmFieldShift)) == 0; |
1398 DCHECK(in_range && ((target & 3) == 0)); | 1125 DCHECK(in_range && ((target & 3) == 0)); |
1399 #endif | 1126 #endif |
1400 GenInstrJump(J, target >> 2); | 1127 GenInstrJump(J, target >> 2); |
1401 } | 1128 } |
1402 | 1129 |
1403 | 1130 |
1404 void Assembler::jr(Register rs) { | 1131 void Assembler::jr(Register rs) { |
1405 if (!IsMipsArchVariant(kMips32r6)) { | 1132 BlockTrampolinePoolScope block_trampoline_pool(this); |
1406 BlockTrampolinePoolScope block_trampoline_pool(this); | 1133 if (rs.is(ra)) { |
1407 if (rs.is(ra)) { | 1134 positions_recorder()->WriteRecordedPositions(); |
1408 positions_recorder()->WriteRecordedPositions(); | |
1409 } | |
1410 GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR); | |
1411 BlockTrampolinePoolFor(1); // For associated delay slot. | |
1412 } else { | |
1413 jalr(rs, zero_reg); | |
1414 } | 1135 } |
| 1136 GenInstrRegister(SPECIAL, rs, zero_reg, zero_reg, 0, JR); |
| 1137 BlockTrampolinePoolFor(1); // For associated delay slot. |
1415 } | 1138 } |
1416 | 1139 |
1417 | 1140 |
1418 void Assembler::jal(int32_t target) { | 1141 void Assembler::jal(int32_t target) { |
1419 #ifdef DEBUG | 1142 #ifdef DEBUG |
1420 // Get pc of delay slot. | 1143 // Get pc of delay slot. |
1421 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); | 1144 uint32_t ipc = reinterpret_cast<uint32_t>(pc_ + 1 * kInstrSize); |
1422 bool in_range = (ipc ^ static_cast<uint32_t>(target) >> | 1145 bool in_range = (ipc ^ static_cast<uint32_t>(target) >> |
1423 (kImm26Bits + kImmFieldShift)) == 0; | 1146 (kImm26Bits + kImmFieldShift)) == 0; |
1424 DCHECK(in_range && ((target & 3) == 0)); | 1147 DCHECK(in_range && ((target & 3) == 0)); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1475 GenInstrImmediate(ADDIU, rs, rd, j); | 1198 GenInstrImmediate(ADDIU, rs, rd, j); |
1476 } | 1199 } |
1477 | 1200 |
1478 | 1201 |
1479 void Assembler::subu(Register rd, Register rs, Register rt) { | 1202 void Assembler::subu(Register rd, Register rs, Register rt) { |
1480 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU); | 1203 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU); |
1481 } | 1204 } |
1482 | 1205 |
1483 | 1206 |
1484 void Assembler::mul(Register rd, Register rs, Register rt) { | 1207 void Assembler::mul(Register rd, Register rs, Register rt) { |
1485 if (!IsMipsArchVariant(kMips32r6)) { | 1208 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL); |
1486 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL); | |
1487 } else { | |
1488 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH); | |
1489 } | |
1490 } | 1209 } |
1491 | 1210 |
1492 | 1211 |
1493 void Assembler::mulu(Register rd, Register rs, Register rt) { | |
1494 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1495 GenInstrRegister(SPECIAL, rs, rt, rd, MUL_OP, MUL_MUH_U); | |
1496 } | |
1497 | |
1498 | |
1499 void Assembler::muh(Register rd, Register rs, Register rt) { | |
1500 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1501 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH); | |
1502 } | |
1503 | |
1504 | |
1505 void Assembler::muhu(Register rd, Register rs, Register rt) { | |
1506 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1507 GenInstrRegister(SPECIAL, rs, rt, rd, MUH_OP, MUL_MUH_U); | |
1508 } | |
1509 | |
1510 | |
1511 void Assembler::mod(Register rd, Register rs, Register rt) { | |
1512 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1513 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD); | |
1514 } | |
1515 | |
1516 | |
1517 void Assembler::modu(Register rd, Register rs, Register rt) { | |
1518 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1519 GenInstrRegister(SPECIAL, rs, rt, rd, MOD_OP, DIV_MOD_U); | |
1520 } | |
1521 | |
1522 | |
1523 void Assembler::mult(Register rs, Register rt) { | 1212 void Assembler::mult(Register rs, Register rt) { |
1524 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT); | 1213 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULT); |
1525 } | 1214 } |
1526 | 1215 |
1527 | 1216 |
1528 void Assembler::multu(Register rs, Register rt) { | 1217 void Assembler::multu(Register rs, Register rt) { |
1529 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU); | 1218 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, MULTU); |
1530 } | 1219 } |
1531 | 1220 |
1532 | 1221 |
1533 void Assembler::div(Register rs, Register rt) { | 1222 void Assembler::div(Register rs, Register rt) { |
1534 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV); | 1223 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIV); |
1535 } | 1224 } |
1536 | 1225 |
1537 | 1226 |
1538 void Assembler::div(Register rd, Register rs, Register rt) { | |
1539 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1540 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD); | |
1541 } | |
1542 | |
1543 | |
1544 void Assembler::divu(Register rs, Register rt) { | 1227 void Assembler::divu(Register rs, Register rt) { |
1545 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU); | 1228 GenInstrRegister(SPECIAL, rs, rt, zero_reg, 0, DIVU); |
1546 } | 1229 } |
1547 | 1230 |
1548 | 1231 |
1549 void Assembler::divu(Register rd, Register rs, Register rt) { | |
1550 DCHECK(IsMipsArchVariant(kMips32r6)); | |
1551 GenInstrRegister(SPECIAL, rs, rt, rd, DIV_OP, DIV_MOD_U); | |
1552 } | |
1553 | |
1554 | |
1555 // Logical. | 1232 // Logical. |
1556 | 1233 |
1557 void Assembler::and_(Register rd, Register rs, Register rt) { | 1234 void Assembler::and_(Register rd, Register rs, Register rt) { |
1558 GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND); | 1235 GenInstrRegister(SPECIAL, rs, rt, rd, 0, AND); |
1559 } | 1236 } |
1560 | 1237 |
1561 | 1238 |
1562 void Assembler::andi(Register rt, Register rs, int32_t j) { | 1239 void Assembler::andi(Register rt, Register rs, int32_t j) { |
1563 DCHECK(is_uint16(j)); | 1240 DCHECK(is_uint16(j)); |
1564 GenInstrImmediate(ANDI, rs, rt, j); | 1241 GenInstrImmediate(ANDI, rs, rt, j); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1627 | 1304 |
1628 | 1305 |
1629 void Assembler::srav(Register rd, Register rt, Register rs) { | 1306 void Assembler::srav(Register rd, Register rt, Register rs) { |
1630 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV); | 1307 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SRAV); |
1631 } | 1308 } |
1632 | 1309 |
1633 | 1310 |
1634 void Assembler::rotr(Register rd, Register rt, uint16_t sa) { | 1311 void Assembler::rotr(Register rd, Register rt, uint16_t sa) { |
1635 // Should be called via MacroAssembler::Ror. | 1312 // Should be called via MacroAssembler::Ror. |
1636 DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa)); | 1313 DCHECK(rd.is_valid() && rt.is_valid() && is_uint5(sa)); |
1637 DCHECK(IsMipsArchVariant(kMips32r2)); | 1314 DCHECK(kArchVariant == kMips32r2); |
1638 Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) | 1315 Instr instr = SPECIAL | (1 << kRsShift) | (rt.code() << kRtShift) |
1639 | (rd.code() << kRdShift) | (sa << kSaShift) | SRL; | 1316 | (rd.code() << kRdShift) | (sa << kSaShift) | SRL; |
1640 emit(instr); | 1317 emit(instr); |
1641 } | 1318 } |
1642 | 1319 |
1643 | 1320 |
1644 void Assembler::rotrv(Register rd, Register rt, Register rs) { | 1321 void Assembler::rotrv(Register rd, Register rt, Register rs) { |
1645 // Should be called via MacroAssembler::Ror. | 1322 // Should be called via MacroAssembler::Ror. |
1646 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid() ); | 1323 DCHECK(rd.is_valid() && rt.is_valid() && rs.is_valid() ); |
1647 DCHECK(IsMipsArchVariant(kMips32r2)); | 1324 DCHECK(kArchVariant == kMips32r2); |
1648 Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) | 1325 Instr instr = SPECIAL | (rs.code() << kRsShift) | (rt.code() << kRtShift) |
1649 | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV; | 1326 | (rd.code() << kRdShift) | (1 << kSaShift) | SRLV; |
1650 emit(instr); | 1327 emit(instr); |
1651 } | 1328 } |
1652 | 1329 |
1653 | 1330 |
1654 // ------------Memory-instructions------------- | 1331 // ------------Memory-instructions------------- |
1655 | 1332 |
1656 // Helper for base-reg + offset, when offset is larger than int16. | 1333 // Helper for base-reg + offset, when offset is larger than int16. |
1657 void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) { | 1334 void Assembler::LoadRegPlusOffsetToAt(const MemOperand& src) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1761 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); | 1438 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); |
1762 } | 1439 } |
1763 | 1440 |
1764 | 1441 |
1765 void Assembler::lui(Register rd, int32_t j) { | 1442 void Assembler::lui(Register rd, int32_t j) { |
1766 DCHECK(is_uint16(j)); | 1443 DCHECK(is_uint16(j)); |
1767 GenInstrImmediate(LUI, zero_reg, rd, j); | 1444 GenInstrImmediate(LUI, zero_reg, rd, j); |
1768 } | 1445 } |
1769 | 1446 |
1770 | 1447 |
1771 void Assembler::aui(Register rs, Register rt, int32_t j) { | |
1772 // This instruction uses same opcode as 'lui'. The difference in encoding is | |
1773 // 'lui' has zero reg. for rs field. | |
1774 DCHECK(is_uint16(j)); | |
1775 GenInstrImmediate(LUI, rs, rt, j); | |
1776 } | |
1777 | |
1778 | |
1779 // -------------Misc-instructions-------------- | 1448 // -------------Misc-instructions-------------- |
1780 | 1449 |
1781 // Break / Trap instructions. | 1450 // Break / Trap instructions. |
1782 void Assembler::break_(uint32_t code, bool break_as_stop) { | 1451 void Assembler::break_(uint32_t code, bool break_as_stop) { |
1783 DCHECK((code & ~0xfffff) == 0); | 1452 DCHECK((code & ~0xfffff) == 0); |
1784 // We need to invalidate breaks that could be stops as well because the | 1453 // We need to invalidate breaks that could be stops as well because the |
1785 // simulator expects a char pointer after the stop instruction. | 1454 // simulator expects a char pointer after the stop instruction. |
1786 // See constants-mips.h for explanation. | 1455 // See constants-mips.h for explanation. |
1787 DCHECK((break_as_stop && | 1456 DCHECK((break_as_stop && |
1788 code <= kMaxStopCode && | 1457 code <= kMaxStopCode && |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1912 | 1581 |
1913 void Assembler::movf(Register rd, Register rs, uint16_t cc) { | 1582 void Assembler::movf(Register rd, Register rs, uint16_t cc) { |
1914 Register rt; | 1583 Register rt; |
1915 rt.code_ = (cc & 0x0007) << 2 | 0; | 1584 rt.code_ = (cc & 0x0007) << 2 | 0; |
1916 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); | 1585 GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI); |
1917 } | 1586 } |
1918 | 1587 |
1919 | 1588 |
1920 // Bit twiddling. | 1589 // Bit twiddling. |
1921 void Assembler::clz(Register rd, Register rs) { | 1590 void Assembler::clz(Register rd, Register rs) { |
1922 if (!IsMipsArchVariant(kMips32r6)) { | 1591 // Clz instr requires same GPR number in 'rd' and 'rt' fields. |
1923 // Clz instr requires same GPR number in 'rd' and 'rt' fields. | 1592 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ); |
1924 GenInstrRegister(SPECIAL2, rs, rd, rd, 0, CLZ); | |
1925 } else { | |
1926 GenInstrRegister(SPECIAL, rs, zero_reg, rd, 1, CLZ_R6); | |
1927 } | |
1928 } | 1593 } |
1929 | 1594 |
1930 | 1595 |
1931 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) { | 1596 void Assembler::ins_(Register rt, Register rs, uint16_t pos, uint16_t size) { |
1932 // Should be called via MacroAssembler::Ins. | 1597 // Should be called via MacroAssembler::Ins. |
1933 // Ins instr has 'rt' field as dest, and two uint5: msb, lsb. | 1598 // Ins instr has 'rt' field as dest, and two uint5: msb, lsb. |
1934 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 1599 DCHECK(kArchVariant == kMips32r2); |
1935 GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS); | 1600 GenInstrRegister(SPECIAL3, rs, rt, pos + size - 1, pos, INS); |
1936 } | 1601 } |
1937 | 1602 |
1938 | 1603 |
1939 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) { | 1604 void Assembler::ext_(Register rt, Register rs, uint16_t pos, uint16_t size) { |
1940 // Should be called via MacroAssembler::Ext. | 1605 // Should be called via MacroAssembler::Ext. |
1941 // Ext instr has 'rt' field as dest, and two uint5: msb, lsb. | 1606 // Ext instr has 'rt' field as dest, and two uint5: msb, lsb. |
1942 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 1607 DCHECK(kArchVariant == kMips32r2); |
1943 GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT); | 1608 GenInstrRegister(SPECIAL3, rs, rt, size - 1, pos, EXT); |
1944 } | 1609 } |
1945 | 1610 |
1946 | 1611 |
1947 void Assembler::pref(int32_t hint, const MemOperand& rs) { | 1612 void Assembler::pref(int32_t hint, const MemOperand& rs) { |
1948 DCHECK(!IsMipsArchVariant(kLoongson)); | 1613 DCHECK(kArchVariant != kLoongson); |
1949 DCHECK(is_uint5(hint) && is_uint16(rs.offset_)); | 1614 DCHECK(is_uint5(hint) && is_uint16(rs.offset_)); |
1950 Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift) | 1615 Instr instr = PREF | (rs.rm().code() << kRsShift) | (hint << kRtShift) |
1951 | (rs.offset_); | 1616 | (rs.offset_); |
1952 emit(instr); | 1617 emit(instr); |
1953 } | 1618 } |
1954 | 1619 |
1955 | 1620 |
1956 // --------Coprocessor-instructions---------------- | 1621 // --------Coprocessor-instructions---------------- |
1957 | 1622 |
1958 // Load, store, move. | 1623 // Load, store, move. |
1959 void Assembler::lwc1(FPURegister fd, const MemOperand& src) { | 1624 void Assembler::lwc1(FPURegister fd, const MemOperand& src) { |
1960 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_); | 1625 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_); |
1961 } | 1626 } |
1962 | 1627 |
1963 | 1628 |
1964 void Assembler::ldc1(FPURegister fd, const MemOperand& src) { | 1629 void Assembler::ldc1(FPURegister fd, const MemOperand& src) { |
1965 // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit | 1630 // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit |
1966 // load to two 32-bit loads. | 1631 // load to two 32-bit loads. |
1967 if (IsFp64Mode()) { | 1632 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_ + |
1968 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_ + | 1633 Register::kMantissaOffset); |
1969 Register::kMantissaOffset); | 1634 FPURegister nextfpreg; |
1970 GenInstrImmediate(LW, src.rm(), at, src.offset_ + | 1635 nextfpreg.setcode(fd.code() + 1); |
1971 Register::kExponentOffset); | 1636 GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ + |
1972 mthc1(at, fd); | 1637 Register::kExponentOffset); |
1973 } else { | |
1974 GenInstrImmediate(LWC1, src.rm(), fd, src.offset_ + | |
1975 Register::kMantissaOffset); | |
1976 FPURegister nextfpreg; | |
1977 nextfpreg.setcode(fd.code() + 1); | |
1978 GenInstrImmediate(LWC1, src.rm(), nextfpreg, src.offset_ + | |
1979 Register::kExponentOffset); | |
1980 } | |
1981 } | 1638 } |
1982 | 1639 |
1983 | 1640 |
1984 void Assembler::swc1(FPURegister fd, const MemOperand& src) { | 1641 void Assembler::swc1(FPURegister fd, const MemOperand& src) { |
1985 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_); | 1642 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_); |
1986 } | 1643 } |
1987 | 1644 |
1988 | 1645 |
1989 void Assembler::sdc1(FPURegister fd, const MemOperand& src) { | 1646 void Assembler::sdc1(FPURegister fd, const MemOperand& src) { |
1990 // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit | 1647 // Workaround for non-8-byte alignment of HeapNumber, convert 64-bit |
1991 // store to two 32-bit stores. | 1648 // store to two 32-bit stores. |
1992 if (IsFp64Mode()) { | 1649 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_ + |
1993 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_ + | 1650 Register::kMantissaOffset); |
1994 Register::kMantissaOffset); | 1651 FPURegister nextfpreg; |
1995 mfhc1(at, fd); | 1652 nextfpreg.setcode(fd.code() + 1); |
1996 GenInstrImmediate(SW, src.rm(), at, src.offset_ + | 1653 GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ + |
1997 Register::kExponentOffset); | 1654 Register::kExponentOffset); |
1998 } else { | |
1999 GenInstrImmediate(SWC1, src.rm(), fd, src.offset_ + | |
2000 Register::kMantissaOffset); | |
2001 FPURegister nextfpreg; | |
2002 nextfpreg.setcode(fd.code() + 1); | |
2003 GenInstrImmediate(SWC1, src.rm(), nextfpreg, src.offset_ + | |
2004 Register::kExponentOffset); | |
2005 } | |
2006 } | 1655 } |
2007 | 1656 |
2008 | 1657 |
2009 void Assembler::mtc1(Register rt, FPURegister fs) { | 1658 void Assembler::mtc1(Register rt, FPURegister fs) { |
2010 GenInstrRegister(COP1, MTC1, rt, fs, f0); | 1659 GenInstrRegister(COP1, MTC1, rt, fs, f0); |
2011 } | 1660 } |
2012 | 1661 |
2013 | 1662 |
2014 void Assembler::mthc1(Register rt, FPURegister fs) { | |
2015 GenInstrRegister(COP1, MTHC1, rt, fs, f0); | |
2016 } | |
2017 | |
2018 | |
2019 void Assembler::mfc1(Register rt, FPURegister fs) { | 1663 void Assembler::mfc1(Register rt, FPURegister fs) { |
2020 GenInstrRegister(COP1, MFC1, rt, fs, f0); | 1664 GenInstrRegister(COP1, MFC1, rt, fs, f0); |
2021 } | 1665 } |
2022 | 1666 |
2023 | 1667 |
2024 void Assembler::mfhc1(Register rt, FPURegister fs) { | |
2025 GenInstrRegister(COP1, MFHC1, rt, fs, f0); | |
2026 } | |
2027 | |
2028 | |
2029 void Assembler::ctc1(Register rt, FPUControlRegister fs) { | 1668 void Assembler::ctc1(Register rt, FPUControlRegister fs) { |
2030 GenInstrRegister(COP1, CTC1, rt, fs); | 1669 GenInstrRegister(COP1, CTC1, rt, fs); |
2031 } | 1670 } |
2032 | 1671 |
2033 | 1672 |
2034 void Assembler::cfc1(Register rt, FPUControlRegister fs) { | 1673 void Assembler::cfc1(Register rt, FPUControlRegister fs) { |
2035 GenInstrRegister(COP1, CFC1, rt, fs); | 1674 GenInstrRegister(COP1, CFC1, rt, fs); |
2036 } | 1675 } |
2037 | 1676 |
2038 | 1677 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2139 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S); | 1778 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_W_S); |
2140 } | 1779 } |
2141 | 1780 |
2142 | 1781 |
2143 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) { | 1782 void Assembler::ceil_w_d(FPURegister fd, FPURegister fs) { |
2144 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D); | 1783 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_W_D); |
2145 } | 1784 } |
2146 | 1785 |
2147 | 1786 |
2148 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) { | 1787 void Assembler::cvt_l_s(FPURegister fd, FPURegister fs) { |
2149 DCHECK(IsMipsArchVariant(kMips32r2)); | 1788 DCHECK(kArchVariant == kMips32r2); |
2150 GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S); | 1789 GenInstrRegister(COP1, S, f0, fs, fd, CVT_L_S); |
2151 } | 1790 } |
2152 | 1791 |
2153 | 1792 |
2154 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) { | 1793 void Assembler::cvt_l_d(FPURegister fd, FPURegister fs) { |
2155 DCHECK(IsMipsArchVariant(kMips32r2)); | 1794 DCHECK(kArchVariant == kMips32r2); |
2156 GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D); | 1795 GenInstrRegister(COP1, D, f0, fs, fd, CVT_L_D); |
2157 } | 1796 } |
2158 | 1797 |
2159 | 1798 |
2160 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) { | 1799 void Assembler::trunc_l_s(FPURegister fd, FPURegister fs) { |
2161 DCHECK(IsMipsArchVariant(kMips32r2)); | 1800 DCHECK(kArchVariant == kMips32r2); |
2162 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S); | 1801 GenInstrRegister(COP1, S, f0, fs, fd, TRUNC_L_S); |
2163 } | 1802 } |
2164 | 1803 |
2165 | 1804 |
2166 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) { | 1805 void Assembler::trunc_l_d(FPURegister fd, FPURegister fs) { |
2167 DCHECK(IsMipsArchVariant(kMips32r2)); | 1806 DCHECK(kArchVariant == kMips32r2); |
2168 GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D); | 1807 GenInstrRegister(COP1, D, f0, fs, fd, TRUNC_L_D); |
2169 } | 1808 } |
2170 | 1809 |
2171 | 1810 |
2172 void Assembler::round_l_s(FPURegister fd, FPURegister fs) { | 1811 void Assembler::round_l_s(FPURegister fd, FPURegister fs) { |
2173 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S); | 1812 GenInstrRegister(COP1, S, f0, fs, fd, ROUND_L_S); |
2174 } | 1813 } |
2175 | 1814 |
2176 | 1815 |
2177 void Assembler::round_l_d(FPURegister fd, FPURegister fs) { | 1816 void Assembler::round_l_d(FPURegister fd, FPURegister fs) { |
(...skipping 14 matching lines...) Expand all Loading... |
2192 void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) { | 1831 void Assembler::ceil_l_s(FPURegister fd, FPURegister fs) { |
2193 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S); | 1832 GenInstrRegister(COP1, S, f0, fs, fd, CEIL_L_S); |
2194 } | 1833 } |
2195 | 1834 |
2196 | 1835 |
2197 void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) { | 1836 void Assembler::ceil_l_d(FPURegister fd, FPURegister fs) { |
2198 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D); | 1837 GenInstrRegister(COP1, D, f0, fs, fd, CEIL_L_D); |
2199 } | 1838 } |
2200 | 1839 |
2201 | 1840 |
2202 void Assembler::min(SecondaryField fmt, FPURegister fd, FPURegister ft, | |
2203 FPURegister fs) { | |
2204 DCHECK(IsMipsArchVariant(kMips32r6)); | |
2205 DCHECK((fmt == D) || (fmt == S)); | |
2206 GenInstrRegister(COP1, fmt, ft, fs, fd, MIN); | |
2207 } | |
2208 | |
2209 | |
2210 void Assembler::mina(SecondaryField fmt, FPURegister fd, FPURegister ft, | |
2211 FPURegister fs) { | |
2212 DCHECK(IsMipsArchVariant(kMips32r6)); | |
2213 DCHECK((fmt == D) || (fmt == S)); | |
2214 GenInstrRegister(COP1, fmt, ft, fs, fd, MINA); | |
2215 } | |
2216 | |
2217 | |
2218 void Assembler::max(SecondaryField fmt, FPURegister fd, FPURegister ft, | |
2219 FPURegister fs) { | |
2220 DCHECK(IsMipsArchVariant(kMips32r6)); | |
2221 DCHECK((fmt == D) || (fmt == S)); | |
2222 GenInstrRegister(COP1, fmt, ft, fs, fd, MAX); | |
2223 } | |
2224 | |
2225 | |
2226 void Assembler::maxa(SecondaryField fmt, FPURegister fd, FPURegister ft, | |
2227 FPURegister fs) { | |
2228 DCHECK(IsMipsArchVariant(kMips32r6)); | |
2229 DCHECK((fmt == D) || (fmt == S)); | |
2230 GenInstrRegister(COP1, fmt, ft, fs, fd, MAXA); | |
2231 } | |
2232 | |
2233 | |
2234 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) { | 1841 void Assembler::cvt_s_w(FPURegister fd, FPURegister fs) { |
2235 GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W); | 1842 GenInstrRegister(COP1, W, f0, fs, fd, CVT_S_W); |
2236 } | 1843 } |
2237 | 1844 |
2238 | 1845 |
2239 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) { | 1846 void Assembler::cvt_s_l(FPURegister fd, FPURegister fs) { |
2240 DCHECK(IsMipsArchVariant(kMips32r2)); | 1847 DCHECK(kArchVariant == kMips32r2); |
2241 GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L); | 1848 GenInstrRegister(COP1, L, f0, fs, fd, CVT_S_L); |
2242 } | 1849 } |
2243 | 1850 |
2244 | 1851 |
2245 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) { | 1852 void Assembler::cvt_s_d(FPURegister fd, FPURegister fs) { |
2246 GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D); | 1853 GenInstrRegister(COP1, D, f0, fs, fd, CVT_S_D); |
2247 } | 1854 } |
2248 | 1855 |
2249 | 1856 |
2250 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) { | 1857 void Assembler::cvt_d_w(FPURegister fd, FPURegister fs) { |
2251 GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W); | 1858 GenInstrRegister(COP1, W, f0, fs, fd, CVT_D_W); |
2252 } | 1859 } |
2253 | 1860 |
2254 | 1861 |
2255 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) { | 1862 void Assembler::cvt_d_l(FPURegister fd, FPURegister fs) { |
2256 DCHECK(IsMipsArchVariant(kMips32r2)); | 1863 DCHECK(kArchVariant == kMips32r2); |
2257 GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L); | 1864 GenInstrRegister(COP1, L, f0, fs, fd, CVT_D_L); |
2258 } | 1865 } |
2259 | 1866 |
2260 | 1867 |
2261 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { | 1868 void Assembler::cvt_d_s(FPURegister fd, FPURegister fs) { |
2262 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S); | 1869 GenInstrRegister(COP1, S, f0, fs, fd, CVT_D_S); |
2263 } | 1870 } |
2264 | 1871 |
2265 | 1872 |
2266 // Conditions for >= MIPSr6. | 1873 // Conditions. |
2267 void Assembler::cmp(FPUCondition cond, SecondaryField fmt, | |
2268 FPURegister fd, FPURegister fs, FPURegister ft) { | |
2269 DCHECK(IsMipsArchVariant(kMips32r6)); | |
2270 DCHECK((fmt & ~(31 << kRsShift)) == 0); | |
2271 Instr instr = COP1 | fmt | ft.code() << kFtShift | | |
2272 fs.code() << kFsShift | fd.code() << kFdShift | (0 << 5) | cond; | |
2273 emit(instr); | |
2274 } | |
2275 | |
2276 | |
2277 void Assembler::bc1eqz(int16_t offset, FPURegister ft) { | |
2278 DCHECK(IsMipsArchVariant(kMips32r6)); | |
2279 Instr instr = COP1 | BC1EQZ | ft.code() << kFtShift | (offset & kImm16Mask); | |
2280 emit(instr); | |
2281 } | |
2282 | |
2283 | |
2284 void Assembler::bc1nez(int16_t offset, FPURegister ft) { | |
2285 DCHECK(IsMipsArchVariant(kMips32r6)); | |
2286 Instr instr = COP1 | BC1NEZ | ft.code() << kFtShift | (offset & kImm16Mask); | |
2287 emit(instr); | |
2288 } | |
2289 | |
2290 | |
2291 // Conditions for < MIPSr6. | |
2292 void Assembler::c(FPUCondition cond, SecondaryField fmt, | 1874 void Assembler::c(FPUCondition cond, SecondaryField fmt, |
2293 FPURegister fs, FPURegister ft, uint16_t cc) { | 1875 FPURegister fs, FPURegister ft, uint16_t cc) { |
2294 DCHECK(is_uint3(cc)); | 1876 DCHECK(is_uint3(cc)); |
2295 DCHECK((fmt & ~(31 << kRsShift)) == 0); | 1877 DCHECK((fmt & ~(31 << kRsShift)) == 0); |
2296 Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift | 1878 Instr instr = COP1 | fmt | ft.code() << 16 | fs.code() << kFsShift |
2297 | cc << 8 | 3 << 4 | cond; | 1879 | cc << 8 | 3 << 4 | cond; |
2298 emit(instr); | 1880 emit(instr); |
2299 } | 1881 } |
2300 | 1882 |
2301 | 1883 |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2595 #ifdef DEBUG | 2177 #ifdef DEBUG |
2596 // Check we have the result from a li macro-instruction, using instr pair. | 2178 // Check we have the result from a li macro-instruction, using instr pair. |
2597 Instr instr1 = instr_at(pc); | 2179 Instr instr1 = instr_at(pc); |
2598 CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI)); | 2180 CHECK((GetOpcodeField(instr1) == LUI && GetOpcodeField(instr2) == ORI)); |
2599 #endif | 2181 #endif |
2600 | 2182 |
2601 // Must use 2 instructions to insure patchable code => just use lui and ori. | 2183 // Must use 2 instructions to insure patchable code => just use lui and ori. |
2602 // lui rt, upper-16. | 2184 // lui rt, upper-16. |
2603 // ori rt rt, lower-16. | 2185 // ori rt rt, lower-16. |
2604 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); | 2186 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); |
2605 *(p + 1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); | 2187 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); |
2606 | 2188 |
2607 // The following code is an optimization for the common case of Call() | 2189 // The following code is an optimization for the common case of Call() |
2608 // or Jump() which is load to register, and jump through register: | 2190 // or Jump() which is load to register, and jump through register: |
2609 // li(t9, address); jalr(t9) (or jr(t9)). | 2191 // li(t9, address); jalr(t9) (or jr(t9)). |
2610 // If the destination address is in the same 256 MB page as the call, it | 2192 // If the destination address is in the same 256 MB page as the call, it |
2611 // is faster to do a direct jal, or j, rather than jump thru register, since | 2193 // is faster to do a direct jal, or j, rather than jump thru register, since |
2612 // that lets the cpu pipeline prefetch the target address. However each | 2194 // that lets the cpu pipeline prefetch the target address. However each |
2613 // time the address above is patched, we have to patch the direct jal/j | 2195 // time the address above is patched, we have to patch the direct jal/j |
2614 // instruction, as well as possibly revert to jalr/jr if we now cross a | 2196 // instruction, as well as possibly revert to jalr/jr if we now cross a |
2615 // 256 MB page. Note that with the jal/j instructions, we do not need to | 2197 // 256 MB page. Note that with the jal/j instructions, we do not need to |
(...skipping 22 matching lines...) Expand all Loading... |
2638 uint32_t segment_mask = ((256 * MB) - 1) ^ ((32 * KB) - 1); | 2220 uint32_t segment_mask = ((256 * MB) - 1) ^ ((32 * KB) - 1); |
2639 uint32_t ipc_segment_addr = ipc & segment_mask; | 2221 uint32_t ipc_segment_addr = ipc & segment_mask; |
2640 if (ipc_segment_addr == 0 || ipc_segment_addr == segment_mask) | 2222 if (ipc_segment_addr == 0 || ipc_segment_addr == segment_mask) |
2641 in_range = false; | 2223 in_range = false; |
2642 } | 2224 } |
2643 #endif | 2225 #endif |
2644 | 2226 |
2645 if (IsJalr(instr3)) { | 2227 if (IsJalr(instr3)) { |
2646 // Try to convert JALR to JAL. | 2228 // Try to convert JALR to JAL. |
2647 if (in_range && GetRt(instr2) == GetRs(instr3)) { | 2229 if (in_range && GetRt(instr2) == GetRs(instr3)) { |
2648 *(p + 2) = JAL | target_field; | 2230 *(p+2) = JAL | target_field; |
2649 patched_jump = true; | 2231 patched_jump = true; |
2650 } | 2232 } |
2651 } else if (IsJr(instr3)) { | 2233 } else if (IsJr(instr3)) { |
2652 // Try to convert JR to J, skip returns (jr ra). | 2234 // Try to convert JR to J, skip returns (jr ra). |
2653 bool is_ret = static_cast<int>(GetRs(instr3)) == ra.code(); | 2235 bool is_ret = static_cast<int>(GetRs(instr3)) == ra.code(); |
2654 if (in_range && !is_ret && GetRt(instr2) == GetRs(instr3)) { | 2236 if (in_range && !is_ret && GetRt(instr2) == GetRs(instr3)) { |
2655 *(p + 2) = J | target_field; | 2237 *(p+2) = J | target_field; |
2656 patched_jump = true; | 2238 patched_jump = true; |
2657 } | 2239 } |
2658 } else if (IsJal(instr3)) { | 2240 } else if (IsJal(instr3)) { |
2659 if (in_range) { | 2241 if (in_range) { |
2660 // We are patching an already converted JAL. | 2242 // We are patching an already converted JAL. |
2661 *(p + 2) = JAL | target_field; | 2243 *(p+2) = JAL | target_field; |
2662 } else { | 2244 } else { |
2663 // Patch JAL, but out of range, revert to JALR. | 2245 // Patch JAL, but out of range, revert to JALR. |
2664 // JALR rs reg is the rt reg specified in the ORI instruction. | 2246 // JALR rs reg is the rt reg specified in the ORI instruction. |
2665 uint32_t rs_field = GetRt(instr2) << kRsShift; | 2247 uint32_t rs_field = GetRt(instr2) << kRsShift; |
2666 uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. | 2248 uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. |
2667 *(p+2) = SPECIAL | rs_field | rd_field | JALR; | 2249 *(p+2) = SPECIAL | rs_field | rd_field | JALR; |
2668 } | 2250 } |
2669 patched_jump = true; | 2251 patched_jump = true; |
2670 } else if (IsJ(instr3)) { | 2252 } else if (IsJ(instr3)) { |
2671 if (in_range) { | 2253 if (in_range) { |
2672 // We are patching an already converted J (jump). | 2254 // We are patching an already converted J (jump). |
2673 *(p + 2) = J | target_field; | 2255 *(p+2) = J | target_field; |
2674 } else { | 2256 } else { |
2675 // Trying patch J, but out of range, just go back to JR. | 2257 // Trying patch J, but out of range, just go back to JR. |
2676 // JR 'rs' reg is the 'rt' reg specified in the ORI instruction (instr2). | 2258 // JR 'rs' reg is the 'rt' reg specified in the ORI instruction (instr2). |
2677 uint32_t rs_field = GetRt(instr2) << kRsShift; | 2259 uint32_t rs_field = GetRt(instr2) << kRsShift; |
2678 if (IsMipsArchVariant(kMips32r6)) { | 2260 *(p+2) = SPECIAL | rs_field | JR; |
2679 *(p + 2) = SPECIAL | rs_field | (zero_reg.code() << kRdShift) | JALR; | |
2680 } else { | |
2681 *(p + 2) = SPECIAL | rs_field | JR; | |
2682 } | |
2683 } | 2261 } |
2684 patched_jump = true; | 2262 patched_jump = true; |
2685 } | 2263 } |
2686 | 2264 |
2687 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { | 2265 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { |
2688 CpuFeatures::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t)); | 2266 CpuFeatures::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t)); |
2689 } | 2267 } |
2690 } | 2268 } |
2691 | 2269 |
2692 | 2270 |
2693 void Assembler::JumpLabelToJumpRegister(Address pc) { | 2271 void Assembler::JumpLabelToJumpRegister(Address pc) { |
2694 // Address pc points to lui/ori instructions. | 2272 // Address pc points to lui/ori instructions. |
2695 // Jump to label may follow at pc + 2 * kInstrSize. | 2273 // Jump to label may follow at pc + 2 * kInstrSize. |
2696 uint32_t* p = reinterpret_cast<uint32_t*>(pc); | 2274 uint32_t* p = reinterpret_cast<uint32_t*>(pc); |
2697 #ifdef DEBUG | 2275 #ifdef DEBUG |
2698 Instr instr1 = instr_at(pc); | 2276 Instr instr1 = instr_at(pc); |
2699 #endif | 2277 #endif |
2700 Instr instr2 = instr_at(pc + 1 * kInstrSize); | 2278 Instr instr2 = instr_at(pc + 1 * kInstrSize); |
2701 Instr instr3 = instr_at(pc + 2 * kInstrSize); | 2279 Instr instr3 = instr_at(pc + 2 * kInstrSize); |
2702 bool patched = false; | 2280 bool patched = false; |
2703 | 2281 |
2704 if (IsJal(instr3)) { | 2282 if (IsJal(instr3)) { |
2705 DCHECK(GetOpcodeField(instr1) == LUI); | 2283 DCHECK(GetOpcodeField(instr1) == LUI); |
2706 DCHECK(GetOpcodeField(instr2) == ORI); | 2284 DCHECK(GetOpcodeField(instr2) == ORI); |
2707 | 2285 |
2708 uint32_t rs_field = GetRt(instr2) << kRsShift; | 2286 uint32_t rs_field = GetRt(instr2) << kRsShift; |
2709 uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. | 2287 uint32_t rd_field = ra.code() << kRdShift; // Return-address (ra) reg. |
2710 *(p + 2) = SPECIAL | rs_field | rd_field | JALR; | 2288 *(p+2) = SPECIAL | rs_field | rd_field | JALR; |
2711 patched = true; | 2289 patched = true; |
2712 } else if (IsJ(instr3)) { | 2290 } else if (IsJ(instr3)) { |
2713 DCHECK(GetOpcodeField(instr1) == LUI); | 2291 DCHECK(GetOpcodeField(instr1) == LUI); |
2714 DCHECK(GetOpcodeField(instr2) == ORI); | 2292 DCHECK(GetOpcodeField(instr2) == ORI); |
2715 | 2293 |
2716 uint32_t rs_field = GetRt(instr2) << kRsShift; | 2294 uint32_t rs_field = GetRt(instr2) << kRsShift; |
2717 if (IsMipsArchVariant(kMips32r6)) { | 2295 *(p+2) = SPECIAL | rs_field | JR; |
2718 *(p + 2) = SPECIAL | rs_field | (zero_reg.code() << kRdShift) | JALR; | |
2719 } else { | |
2720 *(p + 2) = SPECIAL | rs_field | JR; | |
2721 } | |
2722 patched = true; | 2296 patched = true; |
2723 } | 2297 } |
2724 | 2298 |
2725 if (patched) { | 2299 if (patched) { |
2726 CpuFeatures::FlushICache(pc + 2, sizeof(Address)); | 2300 CpuFeatures::FlushICache(pc+2, sizeof(Address)); |
2727 } | 2301 } |
2728 } | 2302 } |
2729 | 2303 |
2730 | 2304 |
2731 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { | 2305 Handle<ConstantPoolArray> Assembler::NewConstantPool(Isolate* isolate) { |
2732 // No out-of-line constant pool support. | 2306 // No out-of-line constant pool support. |
2733 DCHECK(!FLAG_enable_ool_constant_pool); | 2307 DCHECK(!FLAG_enable_ool_constant_pool); |
2734 return isolate->factory()->empty_constant_pool_array(); | 2308 return isolate->factory()->empty_constant_pool_array(); |
2735 } | 2309 } |
2736 | 2310 |
2737 | 2311 |
2738 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { | 2312 void Assembler::PopulateConstantPool(ConstantPoolArray* constant_pool) { |
2739 // No out-of-line constant pool support. | 2313 // No out-of-line constant pool support. |
2740 DCHECK(!FLAG_enable_ool_constant_pool); | 2314 DCHECK(!FLAG_enable_ool_constant_pool); |
2741 return; | 2315 return; |
2742 } | 2316 } |
2743 | 2317 |
2744 | 2318 |
2745 } } // namespace v8::internal | 2319 } } // namespace v8::internal |
2746 | 2320 |
2747 #endif // V8_TARGET_ARCH_MIPS | 2321 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |