| 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 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 Object** RelocInfo::call_object_address() { | 259 Object** RelocInfo::call_object_address() { |
| 260 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 260 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| 261 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 261 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| 262 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); | 262 return reinterpret_cast<Object**>(pc_ + 2 * Assembler::kInstrSize); |
| 263 } | 263 } |
| 264 | 264 |
| 265 | 265 |
| 266 bool RelocInfo::IsPatchedReturnSequence() { | 266 bool RelocInfo::IsPatchedReturnSequence() { |
| 267 Instr current_instr = Assembler::instr_at(pc_); | 267 Instr current_instr = Assembler::instr_at(pc_); |
| 268 Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); | 268 Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); |
| 269 #ifdef USE_BLX | |
| 270 // A patched return sequence is: | 269 // A patched return sequence is: |
| 271 // ldr ip, [pc, #0] | 270 // ldr ip, [pc, #0] |
| 272 // blx ip | 271 // blx ip |
| 273 return ((current_instr & kLdrPCMask) == kLdrPCPattern) | 272 return ((current_instr & kLdrPCMask) == kLdrPCPattern) |
| 274 && ((next_instr & kBlxRegMask) == kBlxRegPattern); | 273 && ((next_instr & kBlxRegMask) == kBlxRegPattern); |
| 275 #else | |
| 276 // A patched return sequence is: | |
| 277 // mov lr, pc | |
| 278 // ldr pc, [pc, #-4] | |
| 279 return (current_instr == kMovLrPc) | |
| 280 && ((next_instr & kLdrPCMask) == kLdrPCPattern); | |
| 281 #endif | |
| 282 } | 274 } |
| 283 | 275 |
| 284 | 276 |
| 285 bool RelocInfo::IsPatchedDebugBreakSlotSequence() { | 277 bool RelocInfo::IsPatchedDebugBreakSlotSequence() { |
| 286 Instr current_instr = Assembler::instr_at(pc_); | 278 Instr current_instr = Assembler::instr_at(pc_); |
| 287 return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP); | 279 return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP); |
| 288 } | 280 } |
| 289 | 281 |
| 290 | 282 |
| 291 void RelocInfo::Visit(ObjectVisitor* visitor) { | 283 void RelocInfo::Visit(ObjectVisitor* visitor) { |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 Instr instr = Memory::int32_at(target_pc); | 393 Instr instr = Memory::int32_at(target_pc); |
| 402 // If we have a bx instruction, the instruction before the bx is | 394 // If we have a bx instruction, the instruction before the bx is |
| 403 // what we need to patch. | 395 // what we need to patch. |
| 404 static const int32_t kBxInstMask = 0x0ffffff0; | 396 static const int32_t kBxInstMask = 0x0ffffff0; |
| 405 static const int32_t kBxInstPattern = 0x012fff10; | 397 static const int32_t kBxInstPattern = 0x012fff10; |
| 406 if ((instr & kBxInstMask) == kBxInstPattern) { | 398 if ((instr & kBxInstMask) == kBxInstPattern) { |
| 407 target_pc -= kInstrSize; | 399 target_pc -= kInstrSize; |
| 408 instr = Memory::int32_at(target_pc); | 400 instr = Memory::int32_at(target_pc); |
| 409 } | 401 } |
| 410 | 402 |
| 411 #ifdef USE_BLX | 403 // With a blx instruction, the instruction before is what needs to be patched. |
| 412 // If we have a blx instruction, the instruction before it is | |
| 413 // what needs to be patched. | |
| 414 if ((instr & kBlxRegMask) == kBlxRegPattern) { | 404 if ((instr & kBlxRegMask) == kBlxRegPattern) { |
| 415 target_pc -= kInstrSize; | 405 target_pc -= kInstrSize; |
| 416 instr = Memory::int32_at(target_pc); | 406 instr = Memory::int32_at(target_pc); |
| 417 } | 407 } |
| 418 #endif | |
| 419 | 408 |
| 420 ASSERT(IsLdrPcImmediateOffset(instr)); | 409 ASSERT(IsLdrPcImmediateOffset(instr)); |
| 421 int offset = instr & 0xfff; // offset_12 is unsigned | 410 int offset = instr & 0xfff; // offset_12 is unsigned |
| 422 if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign | 411 if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign |
| 423 // Verify that the constant pool comes after the instruction referencing it. | 412 // Verify that the constant pool comes after the instruction referencing it. |
| 424 ASSERT(offset >= -4); | 413 ASSERT(offset >= -4); |
| 425 return target_pc + offset + 8; | 414 return target_pc + offset + 8; |
| 426 } | 415 } |
| 427 | 416 |
| 428 | 417 |
| 429 Address Assembler::target_pointer_at(Address pc) { | 418 Address Assembler::target_pointer_at(Address pc) { |
| 430 if (IsMovW(Memory::int32_at(pc))) { | 419 if (IsMovW(Memory::int32_at(pc))) { |
| 431 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 420 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); |
| 432 Instruction* instr = Instruction::At(pc); | 421 Instruction* instr = Instruction::At(pc); |
| 433 Instruction* next_instr = Instruction::At(pc + kInstrSize); | 422 Instruction* next_instr = Instruction::At(pc + kInstrSize); |
| 434 return reinterpret_cast<Address>( | 423 return reinterpret_cast<Address>( |
| 435 (next_instr->ImmedMovwMovtValue() << 16) | | 424 (next_instr->ImmedMovwMovtValue() << 16) | |
| 436 instr->ImmedMovwMovtValue()); | 425 instr->ImmedMovwMovtValue()); |
| 437 } | 426 } |
| 438 return Memory::Address_at(target_pointer_address_at(pc)); | 427 return Memory::Address_at(target_pointer_address_at(pc)); |
| 439 } | 428 } |
| 440 | 429 |
| 441 | 430 |
| 442 Address Assembler::target_address_from_return_address(Address pc) { | 431 Address Assembler::target_address_from_return_address(Address pc) { |
| 443 // Returns the address of the call target from the return address that will | 432 // Returns the address of the call target from the return address that will |
| 444 // be returned to after a call. | 433 // be returned to after a call. |
| 445 #ifdef USE_BLX | |
| 446 // Call sequence on V7 or later is : | 434 // Call sequence on V7 or later is : |
| 447 // movw ip, #... @ call address low 16 | 435 // movw ip, #... @ call address low 16 |
| 448 // movt ip, #... @ call address high 16 | 436 // movt ip, #... @ call address high 16 |
| 449 // blx ip | 437 // blx ip |
| 450 // @ return address | 438 // @ return address |
| 451 // Or pre-V7 or cases that need frequent patching: | 439 // Or pre-V7 or cases that need frequent patching: |
| 452 // ldr ip, [pc, #...] @ call address | 440 // ldr ip, [pc, #...] @ call address |
| 453 // blx ip | 441 // blx ip |
| 454 // @ return address | 442 // @ return address |
| 455 Address candidate = pc - 2 * Assembler::kInstrSize; | 443 Address candidate = pc - 2 * Assembler::kInstrSize; |
| 456 Instr candidate_instr(Memory::int32_at(candidate)); | 444 Instr candidate_instr(Memory::int32_at(candidate)); |
| 457 if (IsLdrPcImmediateOffset(candidate_instr)) { | 445 if (IsLdrPcImmediateOffset(candidate_instr)) { |
| 458 return candidate; | 446 return candidate; |
| 459 } | 447 } |
| 460 candidate = pc - 3 * Assembler::kInstrSize; | 448 candidate = pc - 3 * Assembler::kInstrSize; |
| 461 ASSERT(IsMovW(Memory::int32_at(candidate)) && | 449 ASSERT(IsMovW(Memory::int32_at(candidate)) && |
| 462 IsMovT(Memory::int32_at(candidate + kInstrSize))); | 450 IsMovT(Memory::int32_at(candidate + kInstrSize))); |
| 463 return candidate; | 451 return candidate; |
| 464 #else | |
| 465 // Call sequence is: | |
| 466 // mov lr, pc | |
| 467 // ldr pc, [pc, #...] @ call address | |
| 468 // @ return address | |
| 469 return pc - kInstrSize; | |
| 470 #endif | |
| 471 } | 452 } |
| 472 | 453 |
| 473 | 454 |
| 474 Address Assembler::return_address_from_call_start(Address pc) { | 455 Address Assembler::return_address_from_call_start(Address pc) { |
| 475 #ifdef USE_BLX | |
| 476 if (IsLdrPcImmediateOffset(Memory::int32_at(pc))) { | 456 if (IsLdrPcImmediateOffset(Memory::int32_at(pc))) { |
| 477 return pc + kInstrSize * 2; | 457 return pc + kInstrSize * 2; |
| 478 } else { | 458 } else { |
| 479 ASSERT(IsMovW(Memory::int32_at(pc))); | 459 ASSERT(IsMovW(Memory::int32_at(pc))); |
| 480 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); | 460 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); |
| 481 return pc + kInstrSize * 3; | 461 return pc + kInstrSize * 3; |
| 482 } | 462 } |
| 483 #else | |
| 484 return pc + kInstrSize; | |
| 485 #endif | |
| 486 } | 463 } |
| 487 | 464 |
| 488 | 465 |
| 489 void Assembler::deserialization_set_special_target_at( | 466 void Assembler::deserialization_set_special_target_at( |
| 490 Address constant_pool_entry, Address target) { | 467 Address constant_pool_entry, Address target) { |
| 491 Memory::Address_at(constant_pool_entry) = target; | 468 Memory::Address_at(constant_pool_entry) = target; |
| 492 } | 469 } |
| 493 | 470 |
| 494 | 471 |
| 495 void Assembler::set_external_target_at(Address constant_pool_entry, | 472 void Assembler::set_external_target_at(Address constant_pool_entry, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 | 518 |
| 542 | 519 |
| 543 void Assembler::set_target_address_at(Address pc, Address target) { | 520 void Assembler::set_target_address_at(Address pc, Address target) { |
| 544 set_target_pointer_at(pc, target); | 521 set_target_pointer_at(pc, target); |
| 545 } | 522 } |
| 546 | 523 |
| 547 | 524 |
| 548 } } // namespace v8::internal | 525 } } // namespace v8::internal |
| 549 | 526 |
| 550 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ | 527 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ |
| OLD | NEW |