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 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 const Instr kLwSwOffsetMask = kImm16Mask; | 233 const Instr kLwSwOffsetMask = kImm16Mask; |
234 | 234 |
235 | 235 |
236 // Spare buffer. | 236 // Spare buffer. |
237 static const int kMinimalBufferSize = 4 * KB; | 237 static const int kMinimalBufferSize = 4 * KB; |
238 | 238 |
239 | 239 |
240 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) | 240 Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) |
241 : AssemblerBase(arg_isolate), | 241 : AssemblerBase(arg_isolate), |
242 positions_recorder_(this), | 242 positions_recorder_(this), |
243 allow_peephole_optimization_(false), | |
244 emit_debug_code_(FLAG_debug_code) { | 243 emit_debug_code_(FLAG_debug_code) { |
245 allow_peephole_optimization_ = FLAG_peephole_optimization; | |
246 if (buffer == NULL) { | 244 if (buffer == NULL) { |
247 // Do our own buffer management. | 245 // Do our own buffer management. |
248 if (buffer_size <= kMinimalBufferSize) { | 246 if (buffer_size <= kMinimalBufferSize) { |
249 buffer_size = kMinimalBufferSize; | 247 buffer_size = kMinimalBufferSize; |
250 | 248 |
251 if (isolate()->assembler_spare_buffer() != NULL) { | 249 if (isolate()->assembler_spare_buffer() != NULL) { |
252 buffer = isolate()->assembler_spare_buffer(); | 250 buffer = isolate()->assembler_spare_buffer(); |
253 isolate()->set_assembler_spare_buffer(NULL); | 251 isolate()->set_assembler_spare_buffer(NULL); |
254 } | 252 } |
255 } | 253 } |
(...skipping 16 matching lines...) Expand all Loading... |
272 // Setup buffer pointers. | 270 // Setup buffer pointers. |
273 ASSERT(buffer_ != NULL); | 271 ASSERT(buffer_ != NULL); |
274 pc_ = buffer_; | 272 pc_ = buffer_; |
275 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); | 273 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); |
276 | 274 |
277 last_trampoline_pool_end_ = 0; | 275 last_trampoline_pool_end_ = 0; |
278 no_trampoline_pool_before_ = 0; | 276 no_trampoline_pool_before_ = 0; |
279 trampoline_pool_blocked_nesting_ = 0; | 277 trampoline_pool_blocked_nesting_ = 0; |
280 next_buffer_check_ = kMaxBranchOffset - kTrampolineSize; | 278 next_buffer_check_ = kMaxBranchOffset - kTrampolineSize; |
281 internal_trampoline_exception_ = false; | 279 internal_trampoline_exception_ = false; |
| 280 last_bound_pos_ = 0; |
282 | 281 |
283 ast_id_for_reloc_info_ = kNoASTId; | 282 ast_id_for_reloc_info_ = kNoASTId; |
284 } | 283 } |
285 | 284 |
286 | 285 |
287 Assembler::~Assembler() { | 286 Assembler::~Assembler() { |
288 if (own_buffer_) { | 287 if (own_buffer_) { |
289 if (isolate()->assembler_spare_buffer() == NULL && | 288 if (isolate()->assembler_spare_buffer() == NULL && |
290 buffer_size_ == kMinimalBufferSize) { | 289 buffer_size_ == kMinimalBufferSize) { |
291 isolate()->set_assembler_spare_buffer(buffer_); | 290 isolate()->set_assembler_spare_buffer(buffer_); |
(...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1082 | 1081 |
1083 // Arithmetic. | 1082 // Arithmetic. |
1084 | 1083 |
1085 void Assembler::addu(Register rd, Register rs, Register rt) { | 1084 void Assembler::addu(Register rd, Register rs, Register rt) { |
1086 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); | 1085 GenInstrRegister(SPECIAL, rs, rt, rd, 0, ADDU); |
1087 } | 1086 } |
1088 | 1087 |
1089 | 1088 |
1090 void Assembler::addiu(Register rd, Register rs, int32_t j) { | 1089 void Assembler::addiu(Register rd, Register rs, int32_t j) { |
1091 GenInstrImmediate(ADDIU, rs, rd, j); | 1090 GenInstrImmediate(ADDIU, rs, rd, j); |
1092 | |
1093 // Eliminate pattern: push(r), pop(). | |
1094 // addiu(sp, sp, Operand(-kPointerSize)); | |
1095 // sw(src, MemOperand(sp, 0); | |
1096 // addiu(sp, sp, Operand(kPointerSize)); | |
1097 // Both instructions can be eliminated. | |
1098 if (can_peephole_optimize(3) && | |
1099 // Pattern. | |
1100 instr_at(pc_ - 1 * kInstrSize) == kPopInstruction && | |
1101 (instr_at(pc_ - 2 * kInstrSize) & ~kRtMask) == kPushRegPattern && | |
1102 (instr_at(pc_ - 3 * kInstrSize)) == kPushInstruction) { | |
1103 pc_ -= 3 * kInstrSize; | |
1104 if (FLAG_print_peephole_optimization) { | |
1105 PrintF("%x push(reg)/pop() eliminated\n", pc_offset()); | |
1106 } | |
1107 } | |
1108 | |
1109 // Eliminate pattern: push(ry), pop(rx). | |
1110 // addiu(sp, sp, -kPointerSize) | |
1111 // sw(ry, MemOperand(sp, 0) | |
1112 // lw(rx, MemOperand(sp, 0) | |
1113 // addiu(sp, sp, kPointerSize); | |
1114 // Both instructions can be eliminated if ry = rx. | |
1115 // If ry != rx, a register copy from ry to rx is inserted | |
1116 // after eliminating the push and the pop instructions. | |
1117 if (can_peephole_optimize(4)) { | |
1118 Instr pre_push_sp_set = instr_at(pc_ - 4 * kInstrSize); | |
1119 Instr push_instr = instr_at(pc_ - 3 * kInstrSize); | |
1120 Instr pop_instr = instr_at(pc_ - 2 * kInstrSize); | |
1121 Instr post_pop_sp_set = instr_at(pc_ - 1 * kInstrSize); | |
1122 | |
1123 if (IsPush(push_instr) && | |
1124 IsPop(pop_instr) && pre_push_sp_set == kPushInstruction && | |
1125 post_pop_sp_set == kPopInstruction) { | |
1126 if ((pop_instr & kRtMask) != (push_instr & kRtMask)) { | |
1127 // For consecutive push and pop on different registers, | |
1128 // we delete both the push & pop and insert a register move. | |
1129 // push ry, pop rx --> mov rx, ry. | |
1130 Register reg_pushed, reg_popped; | |
1131 reg_pushed = GetRtReg(push_instr); | |
1132 reg_popped = GetRtReg(pop_instr); | |
1133 pc_ -= 4 * kInstrSize; | |
1134 // Insert a mov instruction, which is better than a pair of push & pop. | |
1135 or_(reg_popped, reg_pushed, zero_reg); | |
1136 if (FLAG_print_peephole_optimization) { | |
1137 PrintF("%x push/pop (diff reg) replaced by a reg move\n", | |
1138 pc_offset()); | |
1139 } | |
1140 } else { | |
1141 // For consecutive push and pop on the same register, | |
1142 // both the push and the pop can be deleted. | |
1143 pc_ -= 4 * kInstrSize; | |
1144 if (FLAG_print_peephole_optimization) { | |
1145 PrintF("%x push/pop (same reg) eliminated\n", pc_offset()); | |
1146 } | |
1147 } | |
1148 } | |
1149 } | |
1150 | |
1151 if (can_peephole_optimize(5)) { | |
1152 Instr pre_push_sp_set = instr_at(pc_ - 5 * kInstrSize); | |
1153 Instr mem_write_instr = instr_at(pc_ - 4 * kInstrSize); | |
1154 Instr lw_instr = instr_at(pc_ - 3 * kInstrSize); | |
1155 Instr mem_read_instr = instr_at(pc_ - 2 * kInstrSize); | |
1156 Instr post_pop_sp_set = instr_at(pc_ - 1 * kInstrSize); | |
1157 | |
1158 if (IsPush(mem_write_instr) && | |
1159 pre_push_sp_set == kPushInstruction && | |
1160 IsPop(mem_read_instr) && | |
1161 post_pop_sp_set == kPopInstruction) { | |
1162 if ((IsLwRegFpOffset(lw_instr) || | |
1163 IsLwRegFpNegOffset(lw_instr))) { | |
1164 if ((mem_write_instr & kRtMask) == | |
1165 (mem_read_instr & kRtMask)) { | |
1166 // Pattern: push & pop from/to same register, | |
1167 // with a fp + offset lw in between. | |
1168 // | |
1169 // The following: | |
1170 // addiu sp, sp, -4 | |
1171 // sw rx, [sp, #0]! | |
1172 // lw rz, [fp, #-24] | |
1173 // lw rx, [sp, 0], | |
1174 // addiu sp, sp, 4 | |
1175 // | |
1176 // Becomes: | |
1177 // if(rx == rz) | |
1178 // delete all | |
1179 // else | |
1180 // lw rz, [fp, #-24] | |
1181 | |
1182 if ((mem_write_instr & kRtMask) == (lw_instr & kRtMask)) { | |
1183 pc_ -= 5 * kInstrSize; | |
1184 } else { | |
1185 pc_ -= 5 * kInstrSize; | |
1186 // Reinsert back the lw rz. | |
1187 emit(lw_instr); | |
1188 } | |
1189 if (FLAG_print_peephole_optimization) { | |
1190 PrintF("%x push/pop -dead ldr fp + offset in middle\n", | |
1191 pc_offset()); | |
1192 } | |
1193 } else { | |
1194 // Pattern: push & pop from/to different registers | |
1195 // with a fp + offset lw in between. | |
1196 // | |
1197 // The following: | |
1198 // addiu sp, sp ,-4 | |
1199 // sw rx, [sp, 0] | |
1200 // lw rz, [fp, #-24] | |
1201 // lw ry, [sp, 0] | |
1202 // addiu sp, sp, 4 | |
1203 // | |
1204 // Becomes: | |
1205 // if(ry == rz) | |
1206 // mov ry, rx; | |
1207 // else if(rx != rz) | |
1208 // lw rz, [fp, #-24] | |
1209 // mov ry, rx | |
1210 // else if((ry != rz) || (rx == rz)) becomes: | |
1211 // mov ry, rx | |
1212 // lw rz, [fp, #-24] | |
1213 | |
1214 Register reg_pushed, reg_popped; | |
1215 if ((mem_read_instr & kRtMask) == (lw_instr & kRtMask)) { | |
1216 reg_pushed = GetRtReg(mem_write_instr); | |
1217 reg_popped = GetRtReg(mem_read_instr); | |
1218 pc_ -= 5 * kInstrSize; | |
1219 or_(reg_popped, reg_pushed, zero_reg); // Move instruction. | |
1220 } else if ((mem_write_instr & kRtMask) | |
1221 != (lw_instr & kRtMask)) { | |
1222 reg_pushed = GetRtReg(mem_write_instr); | |
1223 reg_popped = GetRtReg(mem_read_instr); | |
1224 pc_ -= 5 * kInstrSize; | |
1225 emit(lw_instr); | |
1226 or_(reg_popped, reg_pushed, zero_reg); // Move instruction. | |
1227 } else if (((mem_read_instr & kRtMask) | |
1228 != (lw_instr & kRtMask)) || | |
1229 ((mem_write_instr & kRtMask) | |
1230 == (lw_instr & kRtMask)) ) { | |
1231 reg_pushed = GetRtReg(mem_write_instr); | |
1232 reg_popped = GetRtReg(mem_read_instr); | |
1233 pc_ -= 5 * kInstrSize; | |
1234 or_(reg_popped, reg_pushed, zero_reg); // Move instruction. | |
1235 emit(lw_instr); | |
1236 } | |
1237 if (FLAG_print_peephole_optimization) { | |
1238 PrintF("%x push/pop (ldr fp+off in middle)\n", pc_offset()); | |
1239 } | |
1240 } | |
1241 } | |
1242 } | |
1243 } | |
1244 } | 1091 } |
1245 | 1092 |
1246 | 1093 |
1247 void Assembler::subu(Register rd, Register rs, Register rt) { | 1094 void Assembler::subu(Register rd, Register rs, Register rt) { |
1248 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU); | 1095 GenInstrRegister(SPECIAL, rs, rt, rd, 0, SUBU); |
1249 } | 1096 } |
1250 | 1097 |
1251 | 1098 |
1252 void Assembler::mul(Register rd, Register rs, Register rt) { | 1099 void Assembler::mul(Register rd, Register rs, Register rt) { |
1253 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL); | 1100 GenInstrRegister(SPECIAL2, rs, rt, rd, 0, MUL); |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1421 } | 1268 } |
1422 | 1269 |
1423 | 1270 |
1424 void Assembler::lw(Register rd, const MemOperand& rs) { | 1271 void Assembler::lw(Register rd, const MemOperand& rs) { |
1425 if (is_int16(rs.offset_)) { | 1272 if (is_int16(rs.offset_)) { |
1426 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_); | 1273 GenInstrImmediate(LW, rs.rm(), rd, rs.offset_); |
1427 } else { // Offset > 16 bits, use multiple instructions to load. | 1274 } else { // Offset > 16 bits, use multiple instructions to load. |
1428 LoadRegPlusOffsetToAt(rs); | 1275 LoadRegPlusOffsetToAt(rs); |
1429 GenInstrImmediate(LW, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0)); | 1276 GenInstrImmediate(LW, at, rd, 0); // Equiv to lw(rd, MemOperand(at, 0)); |
1430 } | 1277 } |
1431 | |
1432 if (can_peephole_optimize(2)) { | |
1433 Instr sw_instr = instr_at(pc_ - 2 * kInstrSize); | |
1434 Instr lw_instr = instr_at(pc_ - 1 * kInstrSize); | |
1435 | |
1436 if ((IsSwRegFpOffset(sw_instr) && | |
1437 IsLwRegFpOffset(lw_instr)) || | |
1438 (IsSwRegFpNegOffset(sw_instr) && | |
1439 IsLwRegFpNegOffset(lw_instr))) { | |
1440 if ((lw_instr & kLwSwInstrArgumentMask) == | |
1441 (sw_instr & kLwSwInstrArgumentMask)) { | |
1442 // Pattern: Lw/sw same fp+offset, same register. | |
1443 // | |
1444 // The following: | |
1445 // sw rx, [fp, #-12] | |
1446 // lw rx, [fp, #-12] | |
1447 // | |
1448 // Becomes: | |
1449 // sw rx, [fp, #-12] | |
1450 | |
1451 pc_ -= 1 * kInstrSize; | |
1452 if (FLAG_print_peephole_optimization) { | |
1453 PrintF("%x sw/lw (fp + same offset), same reg\n", pc_offset()); | |
1454 } | |
1455 } else if ((lw_instr & kLwSwOffsetMask) == | |
1456 (sw_instr & kLwSwOffsetMask)) { | |
1457 // Pattern: Lw/sw same fp+offset, different register. | |
1458 // | |
1459 // The following: | |
1460 // sw rx, [fp, #-12] | |
1461 // lw ry, [fp, #-12] | |
1462 // | |
1463 // Becomes: | |
1464 // sw rx, [fp, #-12] | |
1465 // mov ry, rx | |
1466 | |
1467 Register reg_stored, reg_loaded; | |
1468 reg_stored = GetRtReg(sw_instr); | |
1469 reg_loaded = GetRtReg(lw_instr); | |
1470 pc_ -= 1 * kInstrSize; | |
1471 // Insert a mov instruction, which is better than lw. | |
1472 or_(reg_loaded, reg_stored, zero_reg); // Move instruction. | |
1473 if (FLAG_print_peephole_optimization) { | |
1474 PrintF("%x sw/lw (fp + same offset), diff reg \n", pc_offset()); | |
1475 } | |
1476 } | |
1477 } | |
1478 } | |
1479 } | 1278 } |
1480 | 1279 |
1481 | 1280 |
1482 void Assembler::lwl(Register rd, const MemOperand& rs) { | 1281 void Assembler::lwl(Register rd, const MemOperand& rs) { |
1483 GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_); | 1282 GenInstrImmediate(LWL, rs.rm(), rd, rs.offset_); |
1484 } | 1283 } |
1485 | 1284 |
1486 | 1285 |
1487 void Assembler::lwr(Register rd, const MemOperand& rs) { | 1286 void Assembler::lwr(Register rd, const MemOperand& rs) { |
1488 GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_); | 1287 GenInstrImmediate(LWR, rs.rm(), rd, rs.offset_); |
(...skipping 20 matching lines...) Expand all Loading... |
1509 } | 1308 } |
1510 | 1309 |
1511 | 1310 |
1512 void Assembler::sw(Register rd, const MemOperand& rs) { | 1311 void Assembler::sw(Register rd, const MemOperand& rs) { |
1513 if (is_int16(rs.offset_)) { | 1312 if (is_int16(rs.offset_)) { |
1514 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_); | 1313 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_); |
1515 } else { // Offset > 16 bits, use multiple instructions to store. | 1314 } else { // Offset > 16 bits, use multiple instructions to store. |
1516 LoadRegPlusOffsetToAt(rs); | 1315 LoadRegPlusOffsetToAt(rs); |
1517 GenInstrImmediate(SW, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0)); | 1316 GenInstrImmediate(SW, at, rd, 0); // Equiv to sw(rd, MemOperand(at, 0)); |
1518 } | 1317 } |
1519 | |
1520 // Eliminate pattern: pop(), push(r). | |
1521 // addiu sp, sp, Operand(kPointerSize); | |
1522 // addiu sp, sp, Operand(-kPointerSize); | |
1523 // -> sw r, MemOpernad(sp, 0); | |
1524 if (can_peephole_optimize(3) && | |
1525 // Pattern. | |
1526 instr_at(pc_ - 1 * kInstrSize) == | |
1527 (kPushRegPattern | (rd.code() << kRtShift)) && | |
1528 instr_at(pc_ - 2 * kInstrSize) == kPushInstruction && | |
1529 instr_at(pc_ - 3 * kInstrSize) == kPopInstruction) { | |
1530 pc_ -= 3 * kInstrSize; | |
1531 GenInstrImmediate(SW, rs.rm(), rd, rs.offset_); | |
1532 if (FLAG_print_peephole_optimization) { | |
1533 PrintF("%x pop()/push(reg) eliminated\n", pc_offset()); | |
1534 } | |
1535 } | |
1536 } | 1318 } |
1537 | 1319 |
1538 | 1320 |
1539 void Assembler::swl(Register rd, const MemOperand& rs) { | 1321 void Assembler::swl(Register rd, const MemOperand& rs) { |
1540 GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_); | 1322 GenInstrImmediate(SWL, rs.rm(), rd, rs.offset_); |
1541 } | 1323 } |
1542 | 1324 |
1543 | 1325 |
1544 void Assembler::swr(Register rd, const MemOperand& rs) { | 1326 void Assembler::swr(Register rd, const MemOperand& rs) { |
1545 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); | 1327 GenInstrImmediate(SWR, rs.rm(), rd, rs.offset_); |
(...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2169 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); | 1951 *p = LUI | rt_code | ((itarget & kHiMask) >> kLuiShift); |
2170 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); | 1952 *(p+1) = ORI | rt_code | (rt_code << 5) | (itarget & kImm16Mask); |
2171 | 1953 |
2172 CPU::FlushICache(pc, 2 * sizeof(int32_t)); | 1954 CPU::FlushICache(pc, 2 * sizeof(int32_t)); |
2173 } | 1955 } |
2174 | 1956 |
2175 | 1957 |
2176 } } // namespace v8::internal | 1958 } } // namespace v8::internal |
2177 | 1959 |
2178 #endif // V8_TARGET_ARCH_MIPS | 1960 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |