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 |