| 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 | 5 // modification, are permitted provided that the following conditions |
| 6 // are met: | 6 // are 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 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 // Implementation of Operand and MemOperand | 157 // Implementation of Operand and MemOperand |
| 158 // See assembler-arm-inl.h for inlined constructors | 158 // See assembler-arm-inl.h for inlined constructors |
| 159 | 159 |
| 160 Operand::Operand(Handle<Object> handle) { | 160 Operand::Operand(Handle<Object> handle) { |
| 161 rm_ = no_reg; | 161 rm_ = no_reg; |
| 162 // Verify all Objects referred by code are NOT in new space. | 162 // Verify all Objects referred by code are NOT in new space. |
| 163 Object* obj = *handle; | 163 Object* obj = *handle; |
| 164 ASSERT(!Heap::InNewSpace(obj)); | 164 ASSERT(!Heap::InNewSpace(obj)); |
| 165 if (obj->IsHeapObject()) { | 165 if (obj->IsHeapObject()) { |
| 166 imm32_ = reinterpret_cast<intptr_t>(handle.location()); | 166 imm32_ = reinterpret_cast<intptr_t>(handle.location()); |
| 167 rmode_ = embedded_object; | 167 rmode_ = RelocInfo::EMBEDDED_OBJECT; |
| 168 } else { | 168 } else { |
| 169 // no relocation needed | 169 // no relocation needed |
| 170 imm32_ = reinterpret_cast<intptr_t>(obj); | 170 imm32_ = reinterpret_cast<intptr_t>(obj); |
| 171 rmode_ = no_reloc; | 171 rmode_ = RelocInfo::NONE; |
| 172 } | 172 } |
| 173 } | 173 } |
| 174 | 174 |
| 175 | 175 |
| 176 Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) { | 176 Operand::Operand(Register rm, ShiftOp shift_op, int shift_imm) { |
| 177 ASSERT(is_uint5(shift_imm)); | 177 ASSERT(is_uint5(shift_imm)); |
| 178 ASSERT(shift_op != ROR || shift_imm != 0); // use RRX if you mean it | 178 ASSERT(shift_op != ROR || shift_imm != 0); // use RRX if you mean it |
| 179 rm_ = rm; | 179 rm_ = rm; |
| 180 rs_ = no_reg; | 180 rs_ = no_reg; |
| 181 shift_op_ = shift_op; | 181 shift_op_ = shift_op; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 | 313 |
| 314 // setup buffer pointers | 314 // setup buffer pointers |
| 315 ASSERT(buffer_ != NULL); | 315 ASSERT(buffer_ != NULL); |
| 316 pc_ = buffer_; | 316 pc_ = buffer_; |
| 317 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); | 317 reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); |
| 318 num_prinfo_ = 0; | 318 num_prinfo_ = 0; |
| 319 next_buffer_check_ = 0; | 319 next_buffer_check_ = 0; |
| 320 no_const_pool_before_ = 0; | 320 no_const_pool_before_ = 0; |
| 321 last_const_pool_end_ = 0; | 321 last_const_pool_end_ = 0; |
| 322 last_bound_pos_ = 0; | 322 last_bound_pos_ = 0; |
| 323 last_position_ = kNoPosition; | 323 last_position_ = RelocInfo::kNoPosition; |
| 324 last_position_is_statement_ = false; | 324 last_position_is_statement_ = false; |
| 325 } | 325 } |
| 326 | 326 |
| 327 | 327 |
| 328 Assembler::~Assembler() { | 328 Assembler::~Assembler() { |
| 329 if (own_buffer_) { | 329 if (own_buffer_) { |
| 330 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { | 330 if (spare_buffer_ == NULL && buffer_size_ == kMinimalBufferSize) { |
| 331 spare_buffer_ = buffer_; | 331 spare_buffer_ = buffer_; |
| 332 } else { | 332 } else { |
| 333 DeleteArray(buffer_); | 333 DeleteArray(buffer_); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 void Assembler::addrmod1(Instr instr, | 581 void Assembler::addrmod1(Instr instr, |
| 582 Register rn, | 582 Register rn, |
| 583 Register rd, | 583 Register rd, |
| 584 const Operand& x) { | 584 const Operand& x) { |
| 585 CheckBuffer(); | 585 CheckBuffer(); |
| 586 ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0); | 586 ASSERT((instr & ~(CondMask | OpCodeMask | S)) == 0); |
| 587 if (!x.rm_.is_valid()) { | 587 if (!x.rm_.is_valid()) { |
| 588 // immediate | 588 // immediate |
| 589 uint32_t rotate_imm; | 589 uint32_t rotate_imm; |
| 590 uint32_t immed_8; | 590 uint32_t immed_8; |
| 591 if ((x.rmode_ != no_reloc && x.rmode_ != external_reference) || | 591 if ((x.rmode_ != RelocInfo::NONE && |
| 592 x.rmode_ != RelocInfo::EXTERNAL_REFERENCE) || |
| 592 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { | 593 !fits_shifter(x.imm32_, &rotate_imm, &immed_8, &instr)) { |
| 593 // The immediate operand cannot be encoded as a shifter operand, so load | 594 // The immediate operand cannot be encoded as a shifter operand, so load |
| 594 // it first to register ip and change the original instruction to use ip. | 595 // it first to register ip and change the original instruction to use ip. |
| 595 // However, if the original instruction is a 'mov rd, x' (not setting the | 596 // However, if the original instruction is a 'mov rd, x' (not setting the |
| 596 // condition code), then replace it with a 'ldr rd, [pc]' | 597 // condition code), then replace it with a 'ldr rd, [pc]' |
| 597 RecordRelocInfo(x.rmode_, x.imm32_); | 598 RecordRelocInfo(x.rmode_, x.imm32_); |
| 598 ASSERT(!rn.is(ip)); // rn should never be ip, or will be trashed | 599 ASSERT(!rn.is(ip)); // rn should never be ip, or will be trashed |
| 599 Condition cond = static_cast<Condition>(instr & CondMask); | 600 Condition cond = static_cast<Condition>(instr & CondMask); |
| 600 if ((instr & ~CondMask) == 13*B21) { // mov, S not set | 601 if ((instr & ~CondMask) == 13*B21) { // mov, S not set |
| 601 ldr(rd, MemOperand(pc, 0), cond); | 602 ldr(rd, MemOperand(pc, 0), cond); |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 | 1000 |
| 1000 | 1001 |
| 1001 void Assembler::msr(SRegisterFieldMask fields, const Operand& src, | 1002 void Assembler::msr(SRegisterFieldMask fields, const Operand& src, |
| 1002 Condition cond) { | 1003 Condition cond) { |
| 1003 ASSERT(fields >= B16 && fields < B20); // at least one field set | 1004 ASSERT(fields >= B16 && fields < B20); // at least one field set |
| 1004 Instr instr; | 1005 Instr instr; |
| 1005 if (!src.rm_.is_valid()) { | 1006 if (!src.rm_.is_valid()) { |
| 1006 // immediate | 1007 // immediate |
| 1007 uint32_t rotate_imm; | 1008 uint32_t rotate_imm; |
| 1008 uint32_t immed_8; | 1009 uint32_t immed_8; |
| 1009 if ((src.rmode_ != no_reloc && src.rmode_ != external_reference)|| | 1010 if ((src.rmode_ != RelocInfo::NONE && |
| 1011 src.rmode_ != RelocInfo::EXTERNAL_REFERENCE)|| |
| 1010 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { | 1012 !fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) { |
| 1011 // immediate operand cannot be encoded, load it first to register ip | 1013 // immediate operand cannot be encoded, load it first to register ip |
| 1012 RecordRelocInfo(src.rmode_, src.imm32_); | 1014 RecordRelocInfo(src.rmode_, src.imm32_); |
| 1013 ldr(ip, MemOperand(pc, 0), cond); | 1015 ldr(ip, MemOperand(pc, 0), cond); |
| 1014 msr(fields, Operand(ip), cond); | 1016 msr(fields, Operand(ip), cond); |
| 1015 return; | 1017 return; |
| 1016 } | 1018 } |
| 1017 instr = I | rotate_imm*B8 | immed_8; | 1019 instr = I | rotate_imm*B8 | immed_8; |
| 1018 } else { | 1020 } else { |
| 1019 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed | 1021 ASSERT(!src.rs_.is_valid() && src.shift_imm_ == 0); // only rm allowed |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 else | 1348 else |
| 1347 add(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond); | 1349 add(dst, x.rn_, Operand(x.rm_, x.shift_op_, x.shift_imm_), s, cond); |
| 1348 } | 1350 } |
| 1349 } | 1351 } |
| 1350 | 1352 |
| 1351 | 1353 |
| 1352 // Debugging | 1354 // Debugging |
| 1353 void Assembler::RecordComment(const char* msg) { | 1355 void Assembler::RecordComment(const char* msg) { |
| 1354 if (FLAG_debug_code) { | 1356 if (FLAG_debug_code) { |
| 1355 CheckBuffer(); | 1357 CheckBuffer(); |
| 1356 RecordRelocInfo(comment, reinterpret_cast<intptr_t>(msg)); | 1358 RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg)); |
| 1357 } | 1359 } |
| 1358 } | 1360 } |
| 1359 | 1361 |
| 1360 | 1362 |
| 1361 void Assembler::RecordPosition(int pos) { | 1363 void Assembler::RecordPosition(int pos) { |
| 1362 if (pos == kNoPosition) return; | 1364 if (pos == RelocInfo::kNoPosition) return; |
| 1363 ASSERT(position >= 0); | 1365 ASSERT(pos >= 0); |
| 1364 if (pos == last_position_) return; | 1366 if (pos == last_position_) return; |
| 1365 CheckBuffer(); | 1367 CheckBuffer(); |
| 1366 RecordRelocInfo(position, pos); | 1368 RecordRelocInfo(RelocInfo::POSITION, pos); |
| 1367 last_position_ = pos; | 1369 last_position_ = pos; |
| 1368 last_position_is_statement_ = false; | 1370 last_position_is_statement_ = false; |
| 1369 } | 1371 } |
| 1370 | 1372 |
| 1371 | 1373 |
| 1372 void Assembler::RecordStatementPosition(int pos) { | 1374 void Assembler::RecordStatementPosition(int pos) { |
| 1373 if (pos == last_position_) return; | 1375 if (pos == last_position_) return; |
| 1374 CheckBuffer(); | 1376 CheckBuffer(); |
| 1375 RecordRelocInfo(statement_position, pos); | 1377 RecordRelocInfo(RelocInfo::STATEMENT_POSITION, pos); |
| 1376 last_position_ = pos; | 1378 last_position_ = pos; |
| 1377 last_position_is_statement_ = true; | 1379 last_position_is_statement_ = true; |
| 1378 } | 1380 } |
| 1379 | 1381 |
| 1380 | 1382 |
| 1381 void Assembler::GrowBuffer() { | 1383 void Assembler::GrowBuffer() { |
| 1382 if (!own_buffer_) FATAL("external code buffer is too small"); | 1384 if (!own_buffer_) FATAL("external code buffer is too small"); |
| 1383 | 1385 |
| 1384 // compute new buffer size | 1386 // compute new buffer size |
| 1385 CodeDesc desc; // the new buffer | 1387 CodeDesc desc; // the new buffer |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1413 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, | 1415 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, |
| 1414 reloc_info_writer.last_pc() + pc_delta); | 1416 reloc_info_writer.last_pc() + pc_delta); |
| 1415 | 1417 |
| 1416 // none of our relocation types are pc relative pointing outside the code | 1418 // none of our relocation types are pc relative pointing outside the code |
| 1417 // buffer nor pc absolute pointing inside the code buffer, so there is no need | 1419 // buffer nor pc absolute pointing inside the code buffer, so there is no need |
| 1418 // to relocate any emitted relocation entries | 1420 // to relocate any emitted relocation entries |
| 1419 | 1421 |
| 1420 // relocate pending relocation entries | 1422 // relocate pending relocation entries |
| 1421 for (int i = 0; i < num_prinfo_; i++) { | 1423 for (int i = 0; i < num_prinfo_; i++) { |
| 1422 RelocInfo& rinfo = prinfo_[i]; | 1424 RelocInfo& rinfo = prinfo_[i]; |
| 1423 ASSERT(rinfo.rmode() != comment && rinfo.rmode() != position); | 1425 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && |
| 1426 rinfo.rmode() != RelocInfo::POSITION); |
| 1424 rinfo.set_pc(rinfo.pc() + pc_delta); | 1427 rinfo.set_pc(rinfo.pc() + pc_delta); |
| 1425 } | 1428 } |
| 1426 } | 1429 } |
| 1427 | 1430 |
| 1428 | 1431 |
| 1429 void Assembler::RecordRelocInfo(RelocMode rmode, intptr_t data) { | 1432 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
| 1430 RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants | 1433 RelocInfo rinfo(pc_, rmode, data); // we do not try to reuse pool constants |
| 1431 if (rmode >= comment && rmode <= statement_position) { | 1434 if (rmode >= RelocInfo::COMMENT && rmode <= RelocInfo::STATEMENT_POSITION) { |
| 1432 // adjust code for new modes | 1435 // adjust code for new modes |
| 1433 ASSERT(is_comment(rmode) || is_position(rmode)); | 1436 ASSERT(RelocInfo::IsComment(rmode) || RelocInfo::IsPosition(rmode)); |
| 1434 // these modes do not need an entry in the constant pool | 1437 // these modes do not need an entry in the constant pool |
| 1435 } else { | 1438 } else { |
| 1436 ASSERT(num_prinfo_ < kMaxNumPRInfo); | 1439 ASSERT(num_prinfo_ < kMaxNumPRInfo); |
| 1437 prinfo_[num_prinfo_++] = rinfo; | 1440 prinfo_[num_prinfo_++] = rinfo; |
| 1438 // Make sure the constant pool is not emitted in place of the next | 1441 // Make sure the constant pool is not emitted in place of the next |
| 1439 // instruction for which we just recorded relocation info | 1442 // instruction for which we just recorded relocation info |
| 1440 BlockConstPoolBefore(pc_offset() + kInstrSize); | 1443 BlockConstPoolBefore(pc_offset() + kInstrSize); |
| 1441 } | 1444 } |
| 1442 if (rinfo.rmode() != no_reloc) { | 1445 if (rinfo.rmode() != RelocInfo::NONE) { |
| 1443 // Don't record external references unless the heap will be serialized. | 1446 // Don't record external references unless the heap will be serialized. |
| 1444 if (rmode == external_reference && | 1447 if (rmode == RelocInfo::EXTERNAL_REFERENCE && |
| 1445 !Serializer::enabled() && | 1448 !Serializer::enabled() && |
| 1446 !FLAG_debug_code) { | 1449 !FLAG_debug_code) { |
| 1447 return; | 1450 return; |
| 1448 } | 1451 } |
| 1449 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here | 1452 ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here |
| 1450 reloc_info_writer.Write(&rinfo); | 1453 reloc_info_writer.Write(&rinfo); |
| 1451 } | 1454 } |
| 1452 } | 1455 } |
| 1453 | 1456 |
| 1454 | 1457 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 | 1516 |
| 1514 RecordComment("[ Constant Pool"); | 1517 RecordComment("[ Constant Pool"); |
| 1515 | 1518 |
| 1516 // Put down constant pool marker | 1519 // Put down constant pool marker |
| 1517 // "Undefined instruction" as specified by A3.1 Instruction set encoding | 1520 // "Undefined instruction" as specified by A3.1 Instruction set encoding |
| 1518 emit(0x03000000 | num_prinfo_); | 1521 emit(0x03000000 | num_prinfo_); |
| 1519 | 1522 |
| 1520 // Emit constant pool entries | 1523 // Emit constant pool entries |
| 1521 for (int i = 0; i < num_prinfo_; i++) { | 1524 for (int i = 0; i < num_prinfo_; i++) { |
| 1522 RelocInfo& rinfo = prinfo_[i]; | 1525 RelocInfo& rinfo = prinfo_[i]; |
| 1523 ASSERT(rinfo.rmode() != comment && rinfo.rmode() != position && | 1526 ASSERT(rinfo.rmode() != RelocInfo::COMMENT && |
| 1524 rinfo.rmode() != statement_position); | 1527 rinfo.rmode() != RelocInfo::POSITION && |
| 1528 rinfo.rmode() != RelocInfo::STATEMENT_POSITION); |
| 1525 Instr instr = instr_at(rinfo.pc()); | 1529 Instr instr = instr_at(rinfo.pc()); |
| 1526 // Instruction to patch must be a ldr/str [pc, #offset] | 1530 // Instruction to patch must be a ldr/str [pc, #offset] |
| 1527 // P and U set, B and W clear, Rn == pc, offset12 still 0 | 1531 // P and U set, B and W clear, Rn == pc, offset12 still 0 |
| 1528 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) == | 1532 ASSERT((instr & (7*B25 | P | U | B | W | 15*B16 | Off12Mask)) == |
| 1529 (2*B25 | P | U | pc.code()*B16)); | 1533 (2*B25 | P | U | pc.code()*B16)); |
| 1530 int delta = pc_ - rinfo.pc() - 8; | 1534 int delta = pc_ - rinfo.pc() - 8; |
| 1531 ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32 | 1535 ASSERT(delta >= -4); // instr could be ldr pc, [pc, #-4] followed by targ32 |
| 1532 if (delta < 0) { | 1536 if (delta < 0) { |
| 1533 instr &= ~U; | 1537 instr &= ~U; |
| 1534 delta = -delta; | 1538 delta = -delta; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1546 bind(&after_pool); | 1550 bind(&after_pool); |
| 1547 } | 1551 } |
| 1548 | 1552 |
| 1549 // Since a constant pool was just emitted, move the check offset forward by | 1553 // Since a constant pool was just emitted, move the check offset forward by |
| 1550 // the standard interval. | 1554 // the standard interval. |
| 1551 next_buffer_check_ = pc_offset() + kCheckConstInterval; | 1555 next_buffer_check_ = pc_offset() + kCheckConstInterval; |
| 1552 } | 1556 } |
| 1553 | 1557 |
| 1554 | 1558 |
| 1555 } } // namespace v8::internal | 1559 } } // namespace v8::internal |
| OLD | NEW |