Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: src/arm/assembler-arm-inl.h

Issue 317653003: [Arm] Various cleanups to the Arm assembler backend. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/assembler-arm.cc ('k') | src/arm/constants-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) 112 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
113 || rmode_ == EMBEDDED_OBJECT 113 || rmode_ == EMBEDDED_OBJECT
114 || rmode_ == EXTERNAL_REFERENCE); 114 || rmode_ == EXTERNAL_REFERENCE);
115 if (FLAG_enable_ool_constant_pool || 115 if (FLAG_enable_ool_constant_pool ||
116 Assembler::IsMovW(Memory::int32_at(pc_))) { 116 Assembler::IsMovW(Memory::int32_at(pc_))) {
117 // We return the PC for ool constant pool since this function is used by the 117 // We return the PC for ool constant pool since this function is used by the
118 // serializerer and expects the address to reside within the code object. 118 // serializerer and expects the address to reside within the code object.
119 return reinterpret_cast<Address>(pc_); 119 return reinterpret_cast<Address>(pc_);
120 } else { 120 } else {
121 ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_))); 121 ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)));
122 return Assembler::target_pointer_address_at(pc_); 122 return constant_pool_entry_address();
123 } 123 }
124 } 124 }
125 125
126 126
127 Address RelocInfo::constant_pool_entry_address() { 127 Address RelocInfo::constant_pool_entry_address() {
128 ASSERT(IsInConstantPool()); 128 ASSERT(IsInConstantPool());
129 if (FLAG_enable_ool_constant_pool) { 129 return Assembler::constant_pool_entry_address(pc_, host_->constant_pool());
130 ASSERT(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc_)));
131 return Assembler::target_constant_pool_address_at(pc_,
132 host_->constant_pool());
133 } else {
134 ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc_)));
135 return Assembler::target_pointer_address_at(pc_);
136 }
137 } 130 }
138 131
139 132
140 int RelocInfo::target_address_size() { 133 int RelocInfo::target_address_size() {
141 return kPointerSize; 134 return kPointerSize;
142 } 135 }
143 136
144 137
145 void RelocInfo::set_target_address(Address target, 138 void RelocInfo::set_target_address(Address target,
146 WriteBarrierMode write_barrier_mode, 139 WriteBarrierMode write_barrier_mode,
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 Assembler::set_target_address_at(pc_, host_, NULL); 300 Assembler::set_target_address_at(pc_, host_, NULL);
308 } 301 }
309 302
310 303
311 bool RelocInfo::IsPatchedReturnSequence() { 304 bool RelocInfo::IsPatchedReturnSequence() {
312 Instr current_instr = Assembler::instr_at(pc_); 305 Instr current_instr = Assembler::instr_at(pc_);
313 Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize); 306 Instr next_instr = Assembler::instr_at(pc_ + Assembler::kInstrSize);
314 // A patched return sequence is: 307 // A patched return sequence is:
315 // ldr ip, [pc, #0] 308 // ldr ip, [pc, #0]
316 // blx ip 309 // blx ip
317 return ((current_instr & kLdrPCMask) == kLdrPCPattern) 310 return Assembler::IsLdrPcImmediateOffset(current_instr) &&
318 && ((next_instr & kBlxRegMask) == kBlxRegPattern); 311 Assembler::IsBlxReg(next_instr);
319 } 312 }
320 313
321 314
322 bool RelocInfo::IsPatchedDebugBreakSlotSequence() { 315 bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
323 Instr current_instr = Assembler::instr_at(pc_); 316 Instr current_instr = Assembler::instr_at(pc_);
324 return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP); 317 return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
325 } 318 }
326 319
327 320
328 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) { 321 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 } 414 }
422 415
423 416
424 void Assembler::emit(Instr x) { 417 void Assembler::emit(Instr x) {
425 CheckBuffer(); 418 CheckBuffer();
426 *reinterpret_cast<Instr*>(pc_) = x; 419 *reinterpret_cast<Instr*>(pc_) = x;
427 pc_ += kInstrSize; 420 pc_ += kInstrSize;
428 } 421 }
429 422
430 423
431 Address Assembler::target_pointer_address_at(Address pc) {
432 Instr instr = Memory::int32_at(pc);
433 return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta;
434 }
435
436
437 Address Assembler::target_constant_pool_address_at(
438 Address pc, ConstantPoolArray* constant_pool) {
439 ASSERT(constant_pool != NULL);
440 ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc)));
441 Instr instr = Memory::int32_at(pc);
442 return reinterpret_cast<Address>(constant_pool) +
443 GetLdrRegisterImmediateOffset(instr);
444 }
445
446
447 Address Assembler::target_address_at(Address pc,
448 ConstantPoolArray* constant_pool) {
449 if (IsMovW(Memory::int32_at(pc))) {
450 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
451 Instruction* instr = Instruction::At(pc);
452 Instruction* next_instr = Instruction::At(pc + kInstrSize);
453 return reinterpret_cast<Address>(
454 (next_instr->ImmedMovwMovtValue() << 16) |
455 instr->ImmedMovwMovtValue());
456 } else if (FLAG_enable_ool_constant_pool) {
457 ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc)));
458 return Memory::Address_at(
459 target_constant_pool_address_at(pc, constant_pool));
460 } else {
461 ASSERT(IsLdrPcImmediateOffset(Memory::int32_at(pc)));
462 return Memory::Address_at(target_pointer_address_at(pc));
463 }
464 }
465
466
467 Address Assembler::target_address_from_return_address(Address pc) { 424 Address Assembler::target_address_from_return_address(Address pc) {
468 // Returns the address of the call target from the return address that will 425 // Returns the address of the call target from the return address that will
469 // be returned to after a call. 426 // be returned to after a call.
470 // Call sequence on V7 or later is : 427 // Call sequence on V7 or later is :
471 // movw ip, #... @ call address low 16 428 // movw ip, #... @ call address low 16
472 // movt ip, #... @ call address high 16 429 // movt ip, #... @ call address high 16
473 // blx ip 430 // blx ip
474 // @ return address 431 // @ return address
475 // Or pre-V7 or cases that need frequent patching: 432 // Or pre-V7 or cases that need frequent patching:
476 // ldr ip, [pc, #...] @ call address 433 // ldr ip, [pc, #...] @ call address
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 return ((immediate & 0xf000) << 4) | (immediate & 0xfff); 473 return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
517 } 474 }
518 475
519 476
520 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate) { 477 static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate) {
521 instruction &= ~EncodeMovwImmediate(0xffff); 478 instruction &= ~EncodeMovwImmediate(0xffff);
522 return instruction | EncodeMovwImmediate(immediate); 479 return instruction | EncodeMovwImmediate(immediate);
523 } 480 }
524 481
525 482
483 static bool IsConstantPoolLoad(Address pc) {
484 return !Assembler::IsMovW(Memory::int32_at(pc));
485 }
486
487
488 Address Assembler::constant_pool_entry_address(
489 Address pc, ConstantPoolArray* constant_pool) {
490 if (FLAG_enable_ool_constant_pool) {
491 ASSERT(constant_pool != NULL);
492 ASSERT(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc)));
493 return reinterpret_cast<Address>(constant_pool) +
494 GetLdrRegisterImmediateOffset(Memory::int32_at(pc));
495 } else {
496 ASSERT(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc)));
497 Instr instr = Memory::int32_at(pc);
498 return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta;
499 }
500 }
501
502
503 Address Assembler::target_address_at(Address pc,
504 ConstantPoolArray* constant_pool) {
505 if (IsConstantPoolLoad(pc)) {
506 // This is a constant pool lookup. Return the value in the constant pool.
507 return Memory::Address_at(constant_pool_entry_address(pc, constant_pool));
508 } else {
509 // This is an movw_movt immediate load. Return the immediate.
510 ASSERT(IsMovW(Memory::int32_at(pc)) &&
511 IsMovT(Memory::int32_at(pc + kInstrSize)));
512 Instruction* movw_instr = Instruction::At(pc);
513 Instruction* movt_instr = Instruction::At(pc + kInstrSize);
514 return reinterpret_cast<Address>(
515 (movt_instr->ImmedMovwMovtValue() << 16) |
516 movw_instr->ImmedMovwMovtValue());
517 }
518 }
519
520
526 void Assembler::set_target_address_at(Address pc, 521 void Assembler::set_target_address_at(Address pc,
527 ConstantPoolArray* constant_pool, 522 ConstantPoolArray* constant_pool,
528 Address target, 523 Address target,
529 ICacheFlushMode icache_flush_mode) { 524 ICacheFlushMode icache_flush_mode) {
530 if (IsMovW(Memory::int32_at(pc))) { 525 if (IsConstantPoolLoad(pc)) {
526 // This is a constant pool lookup. Update the entry in the constant pool.
527 Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target;
528 // Intuitively, we would think it is necessary to always flush the
529 // instruction cache after patching a target address in the code as follows:
530 // CPU::FlushICache(pc, sizeof(target));
531 // However, on ARM, no instruction is actually patched in the case
532 // of embedded constants of the form:
533 // ldr ip, [pp, #...]
534 // since the instruction accessing this address in the constant pool remains
535 // unchanged.
536 } else {
537 // This is an movw_movt immediate load. Patch the immediate embedded in the
538 // instructions.
539 ASSERT(IsMovW(Memory::int32_at(pc)));
531 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); 540 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
532 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); 541 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
533 uint32_t immediate = reinterpret_cast<uint32_t>(target); 542 uint32_t immediate = reinterpret_cast<uint32_t>(target);
534 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF); 543 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF);
535 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16); 544 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16);
536 ASSERT(IsMovW(Memory::int32_at(pc))); 545 ASSERT(IsMovW(Memory::int32_at(pc)));
537 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize))); 546 ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
538 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { 547 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
539 CPU::FlushICache(pc, 2 * kInstrSize); 548 CPU::FlushICache(pc, 2 * kInstrSize);
540 } 549 }
541 } else if (FLAG_enable_ool_constant_pool) {
542 ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc)));
543 Memory::Address_at(
544 target_constant_pool_address_at(pc, constant_pool)) = target;
545 } else {
546 ASSERT(IsLdrPcImmediateOffset(Memory::int32_at(pc)));
547 Memory::Address_at(target_pointer_address_at(pc)) = target;
548 // Intuitively, we would think it is necessary to always flush the
549 // instruction cache after patching a target address in the code as follows:
550 // CPU::FlushICache(pc, sizeof(target));
551 // However, on ARM, no instruction is actually patched in the case
552 // of embedded constants of the form:
553 // ldr ip, [pc, #...]
554 // since the instruction accessing this address in the constant pool remains
555 // unchanged.
556 } 550 }
557 } 551 }
558 552
559 553
560 } } // namespace v8::internal 554 } } // namespace v8::internal
561 555
562 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ 556 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_
OLDNEW
« no previous file with comments | « src/arm/assembler-arm.cc ('k') | src/arm/constants-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698