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

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

Issue 496443003: Add ARMv6 support for the out-of-line constant pool. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: kImmed8 Created 6 years, 4 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 405 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 void Assembler::emit(Instr x) { 416 void Assembler::emit(Instr x) {
417 CheckBuffer(); 417 CheckBuffer();
418 *reinterpret_cast<Instr*>(pc_) = x; 418 *reinterpret_cast<Instr*>(pc_) = x;
419 pc_ += kInstrSize; 419 pc_ += kInstrSize;
420 } 420 }
421 421
422 422
423 Address Assembler::target_address_from_return_address(Address pc) { 423 Address Assembler::target_address_from_return_address(Address pc) {
424 // Returns the address of the call target from the return address that will 424 // Returns the address of the call target from the return address that will
425 // be returned to after a call. 425 // be returned to after a call.
426 // Call sequence on V7 or later is : 426 // Call sequence on V7 or later is:
427 // movw ip, #... @ call address low 16 427 // movw ip, #... @ call address low 16
428 // movt ip, #... @ call address high 16 428 // movt ip, #... @ call address high 16
429 // blx ip 429 // blx ip
430 // @ return address 430 // @ return address
431 // Or pre-V7 or cases that need frequent patching, the address is in the 431 // For V6 when the constant pool is unavailable, it is:
432 // mov ip, #... @ call address low 8
433 // orr ip, ip, #... @ call address 2nd 8
434 // orr ip, ip, #... @ call address 3rd 8
435 // orr ip, ip, #... @ call address high 8
436 // blx ip
437 // @ return address
438 // In cases that need frequent patching, the address is in the
432 // constant pool. It could be a small constant pool load: 439 // constant pool. It could be a small constant pool load:
433 // ldr ip, [pc / pp, #...] @ call address 440 // ldr ip, [pc / pp, #...] @ call address
434 // blx ip 441 // blx ip
435 // @ return address 442 // @ return address
436 // Or an extended constant pool load: 443 // Or an extended constant pool load (ARMv7):
437 // movw ip, #... 444 // movw ip, #...
438 // movt ip, #... 445 // movt ip, #...
439 // ldr ip, [pc, ip] @ call address 446 // ldr ip, [pc, ip] @ call address
440 // blx ip 447 // blx ip
441 // @ return address 448 // @ return address
449 // Or an extended constant pool load (ARMv6):
450 // mov ip, #...
451 // orr ip, ip, #...
452 // orr ip, ip, #...
453 // orr ip, ip, #...
454 // ldr ip, [pc, ip] @ call address
455 // blx ip
456 // @ return address
442 Address candidate = pc - 2 * Assembler::kInstrSize; 457 Address candidate = pc - 2 * Assembler::kInstrSize;
443 Instr candidate_instr(Memory::int32_at(candidate)); 458 Instr candidate_instr(Memory::int32_at(candidate));
444 if (IsLdrPcImmediateOffset(candidate_instr) | 459 if (IsLdrPcImmediateOffset(candidate_instr) |
445 IsLdrPpImmediateOffset(candidate_instr)) { 460 IsLdrPpImmediateOffset(candidate_instr)) {
446 return candidate; 461 return candidate;
447 } else if (IsLdrPpRegOffset(candidate_instr)) {
448 candidate = pc - 4 * Assembler::kInstrSize;
449 DCHECK(IsMovW(Memory::int32_at(candidate)) &&
450 IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize)));
451 return candidate;
452 } else { 462 } else {
453 candidate = pc - 3 * Assembler::kInstrSize; 463 if (IsLdrPpRegOffset(candidate_instr)) {
454 DCHECK(IsMovW(Memory::int32_at(candidate)) && 464 candidate -= Assembler::kInstrSize;
455 IsMovT(Memory::int32_at(candidate + kInstrSize))); 465 }
466 if (CpuFeatures::IsSupported(ARMv7)) {
467 candidate -= 1 * Assembler::kInstrSize;
468 DCHECK(IsMovW(Memory::int32_at(candidate)) &&
469 IsMovT(Memory::int32_at(candidate + Assembler::kInstrSize)));
470 } else {
471 candidate -= 3 * Assembler::kInstrSize;
472 DCHECK(
473 IsMovImmed(Memory::int32_at(candidate)) &&
474 IsOrrImmed(Memory::int32_at(candidate + Assembler::kInstrSize)) &&
475 IsOrrImmed(Memory::int32_at(candidate + 2 * Assembler::kInstrSize)) &&
476 IsOrrImmed(Memory::int32_at(candidate + 3 * Assembler::kInstrSize)));
477 }
456 return candidate; 478 return candidate;
457 } 479 }
458 } 480 }
459 481
460 482
461 Address Assembler::break_address_from_return_address(Address pc) { 483 Address Assembler::break_address_from_return_address(Address pc) {
462 return pc - Assembler::kPatchDebugBreakSlotReturnOffset; 484 return pc - Assembler::kPatchDebugBreakSlotReturnOffset;
463 } 485 }
464 486
465 487
466 Address Assembler::return_address_from_call_start(Address pc) { 488 Address Assembler::return_address_from_call_start(Address pc) {
467 if (IsLdrPcImmediateOffset(Memory::int32_at(pc)) | 489 if (IsLdrPcImmediateOffset(Memory::int32_at(pc)) |
468 IsLdrPpImmediateOffset(Memory::int32_at(pc))) { 490 IsLdrPpImmediateOffset(Memory::int32_at(pc))) {
469 // Load from constant pool, small section. 491 // Load from constant pool, small section.
470 return pc + kInstrSize * 2; 492 return pc + kInstrSize * 2;
471 } else { 493 } else {
472 DCHECK(IsMovW(Memory::int32_at(pc))); 494 if (CpuFeatures::IsSupported(ARMv7)) {
473 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); 495 DCHECK(IsMovW(Memory::int32_at(pc)));
474 if (IsLdrPpRegOffset(Memory::int32_at(pc + kInstrSize))) { 496 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
475 // Load from constant pool, extended section. 497 if (IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))) {
476 return pc + kInstrSize * 4; 498 // Load from constant pool, extended section.
499 return pc + kInstrSize * 4;
500 } else {
501 // A movw / movt load immediate.
502 return pc + kInstrSize * 3;
503 }
477 } else { 504 } else {
478 // A movw / movt load immediate. 505 DCHECK(IsMovImmed(Memory::int32_at(pc)));
479 return pc + kInstrSize * 3; 506 DCHECK(IsOrrImmed(Memory::int32_at(pc + kInstrSize)));
507 DCHECK(IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)));
508 DCHECK(IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
509 if (IsLdrPpRegOffset(Memory::int32_at(pc + 4 * kInstrSize))) {
510 // Load from constant pool, extended section.
511 return pc + kInstrSize * 6;
512 } else {
513 // A mov / orr load immediate.
514 return pc + kInstrSize * 5;
515 }
480 } 516 }
481 } 517 }
482 } 518 }
483 519
484 520
485 void Assembler::deserialization_set_special_target_at( 521 void Assembler::deserialization_set_special_target_at(
486 Address constant_pool_entry, Code* code, Address target) { 522 Address constant_pool_entry, Code* code, Address target) {
487 if (FLAG_enable_ool_constant_pool) { 523 if (FLAG_enable_ool_constant_pool) {
488 set_target_address_at(constant_pool_entry, code, target); 524 set_target_address_at(constant_pool_entry, code, target);
489 } else { 525 } else {
490 Memory::Address_at(constant_pool_entry) = target; 526 Memory::Address_at(constant_pool_entry) = target;
491 } 527 }
492 } 528 }
493 529
494 530
495 bool Assembler::is_constant_pool_load(Address pc) { 531 bool Assembler::is_constant_pool_load(Address pc) {
496 return !Assembler::IsMovW(Memory::int32_at(pc)) || 532 if (CpuFeatures::IsSupported(ARMv7)) {
497 (FLAG_enable_ool_constant_pool && 533 return !Assembler::IsMovW(Memory::int32_at(pc)) ||
498 Assembler::IsLdrPpRegOffset( 534 (FLAG_enable_ool_constant_pool &&
499 Memory::int32_at(pc + 2 * Assembler::kInstrSize))); 535 Assembler::IsLdrPpRegOffset(
536 Memory::int32_at(pc + 2 * Assembler::kInstrSize)));
537 } else {
538 return !Assembler::IsMovImmed(Memory::int32_at(pc)) ||
539 (FLAG_enable_ool_constant_pool &&
540 Assembler::IsLdrPpRegOffset(
541 Memory::int32_at(pc + 4 * Assembler::kInstrSize)));
542 }
500 } 543 }
501 544
502 545
503 Address Assembler::constant_pool_entry_address( 546 Address Assembler::constant_pool_entry_address(
504 Address pc, ConstantPoolArray* constant_pool) { 547 Address pc, ConstantPoolArray* constant_pool) {
505 if (FLAG_enable_ool_constant_pool) { 548 if (FLAG_enable_ool_constant_pool) {
506 DCHECK(constant_pool != NULL); 549 DCHECK(constant_pool != NULL);
507 int cp_offset; 550 int cp_offset;
508 if (IsMovW(Memory::int32_at(pc))) { 551 if (!CpuFeatures::IsSupported(ARMv7) && IsMovImmed(Memory::int32_at(pc))) {
552 DCHECK(IsOrrImmed(Memory::int32_at(pc + kInstrSize)) &&
553 IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
554 IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)) &&
555 IsLdrPpRegOffset(Memory::int32_at(pc + 4 * kInstrSize)));
556 // This is an extended constant pool lookup (ARMv6).
557 Instr mov_instr = instr_at(pc);
558 Instr orr_instr_1 = instr_at(pc + kInstrSize);
559 Instr orr_instr_2 = instr_at(pc + 2 * kInstrSize);
560 Instr orr_instr_3 = instr_at(pc + 3 * kInstrSize);
561 cp_offset = DecodeShiftImm(mov_instr) | DecodeShiftImm(orr_instr_1) |
562 DecodeShiftImm(orr_instr_2) | DecodeShiftImm(orr_instr_3);
563 } else if (IsMovW(Memory::int32_at(pc))) {
509 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)) && 564 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)) &&
510 IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize))); 565 IsLdrPpRegOffset(Memory::int32_at(pc + 2 * kInstrSize)));
511 // This is an extended constant pool lookup. 566 // This is an extended constant pool lookup (ARMv7).
512 Instruction* movw_instr = Instruction::At(pc); 567 Instruction* movw_instr = Instruction::At(pc);
513 Instruction* movt_instr = Instruction::At(pc + kInstrSize); 568 Instruction* movt_instr = Instruction::At(pc + kInstrSize);
514 cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) | 569 cp_offset = (movt_instr->ImmedMovwMovtValue() << 16) |
515 movw_instr->ImmedMovwMovtValue(); 570 movw_instr->ImmedMovwMovtValue();
516 } else { 571 } else {
517 // This is a small constant pool lookup. 572 // This is a small constant pool lookup.
518 DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc))); 573 DCHECK(Assembler::IsLdrPpImmediateOffset(Memory::int32_at(pc)));
519 cp_offset = GetLdrRegisterImmediateOffset(Memory::int32_at(pc)); 574 cp_offset = GetLdrRegisterImmediateOffset(Memory::int32_at(pc));
520 } 575 }
521 return reinterpret_cast<Address>(constant_pool) + cp_offset; 576 return reinterpret_cast<Address>(constant_pool) + cp_offset;
522 } else { 577 } else {
523 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc))); 578 DCHECK(Assembler::IsLdrPcImmediateOffset(Memory::int32_at(pc)));
524 Instr instr = Memory::int32_at(pc); 579 Instr instr = Memory::int32_at(pc);
525 return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta; 580 return pc + GetLdrRegisterImmediateOffset(instr) + kPcLoadDelta;
526 } 581 }
527 } 582 }
528 583
529 584
530 Address Assembler::target_address_at(Address pc, 585 Address Assembler::target_address_at(Address pc,
531 ConstantPoolArray* constant_pool) { 586 ConstantPoolArray* constant_pool) {
532 if (is_constant_pool_load(pc)) { 587 if (is_constant_pool_load(pc)) {
533 // This is a constant pool lookup. Return the value in the constant pool. 588 // This is a constant pool lookup. Return the value in the constant pool.
534 return Memory::Address_at(constant_pool_entry_address(pc, constant_pool)); 589 return Memory::Address_at(constant_pool_entry_address(pc, constant_pool));
535 } else { 590 } else if (CpuFeatures::IsSupported(ARMv7)) {
536 // This is an movw_movt immediate load. Return the immediate. 591 // This is an movw / movt immediate load. Return the immediate.
537 DCHECK(IsMovW(Memory::int32_at(pc)) && 592 DCHECK(IsMovW(Memory::int32_at(pc)) &&
538 IsMovT(Memory::int32_at(pc + kInstrSize))); 593 IsMovT(Memory::int32_at(pc + kInstrSize)));
539 Instruction* movw_instr = Instruction::At(pc); 594 Instruction* movw_instr = Instruction::At(pc);
540 Instruction* movt_instr = Instruction::At(pc + kInstrSize); 595 Instruction* movt_instr = Instruction::At(pc + kInstrSize);
541 return reinterpret_cast<Address>( 596 return reinterpret_cast<Address>(
542 (movt_instr->ImmedMovwMovtValue() << 16) | 597 (movt_instr->ImmedMovwMovtValue() << 16) |
543 movw_instr->ImmedMovwMovtValue()); 598 movw_instr->ImmedMovwMovtValue());
599 } else {
600 // This is an mov / orr immediate load. Return the immediate.
601 DCHECK(IsMovImmed(Memory::int32_at(pc)) &&
602 IsOrrImmed(Memory::int32_at(pc + kInstrSize)) &&
603 IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
604 IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
605 Instr mov_instr = instr_at(pc);
606 Instr orr_instr_1 = instr_at(pc + kInstrSize);
607 Instr orr_instr_2 = instr_at(pc + 2 * kInstrSize);
608 Instr orr_instr_3 = instr_at(pc + 3 * kInstrSize);
609 Address ret = reinterpret_cast<Address>(
610 DecodeShiftImm(mov_instr) | DecodeShiftImm(orr_instr_1) |
611 DecodeShiftImm(orr_instr_2) | DecodeShiftImm(orr_instr_3));
612 return ret;
544 } 613 }
545 } 614 }
546 615
547 616
548 void Assembler::set_target_address_at(Address pc, 617 void Assembler::set_target_address_at(Address pc,
549 ConstantPoolArray* constant_pool, 618 ConstantPoolArray* constant_pool,
550 Address target, 619 Address target,
551 ICacheFlushMode icache_flush_mode) { 620 ICacheFlushMode icache_flush_mode) {
552 if (is_constant_pool_load(pc)) { 621 if (is_constant_pool_load(pc)) {
553 // This is a constant pool lookup. Update the entry in the constant pool. 622 // This is a constant pool lookup. Update the entry in the constant pool.
554 Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target; 623 Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target;
555 // Intuitively, we would think it is necessary to always flush the 624 // Intuitively, we would think it is necessary to always flush the
556 // instruction cache after patching a target address in the code as follows: 625 // instruction cache after patching a target address in the code as follows:
557 // CpuFeatures::FlushICache(pc, sizeof(target)); 626 // CpuFeatures::FlushICache(pc, sizeof(target));
558 // However, on ARM, no instruction is actually patched in the case 627 // However, on ARM, no instruction is actually patched in the case
559 // of embedded constants of the form: 628 // of embedded constants of the form:
560 // ldr ip, [pp, #...] 629 // ldr ip, [pp, #...]
561 // since the instruction accessing this address in the constant pool remains 630 // since the instruction accessing this address in the constant pool remains
562 // unchanged. 631 // unchanged.
563 } else { 632 } else if (CpuFeatures::IsSupported(ARMv7)) {
564 // This is an movw_movt immediate load. Patch the immediate embedded in the 633 // This is an movw / movt immediate load. Patch the immediate embedded in
565 // instructions. 634 // the instructions.
566 DCHECK(IsMovW(Memory::int32_at(pc))); 635 DCHECK(IsMovW(Memory::int32_at(pc)));
567 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); 636 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
568 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc); 637 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
569 uint32_t immediate = reinterpret_cast<uint32_t>(target); 638 uint32_t immediate = reinterpret_cast<uint32_t>(target);
570 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF); 639 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF);
571 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16); 640 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16);
572 DCHECK(IsMovW(Memory::int32_at(pc))); 641 DCHECK(IsMovW(Memory::int32_at(pc)));
573 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize))); 642 DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
574 if (icache_flush_mode != SKIP_ICACHE_FLUSH) { 643 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
575 CpuFeatures::FlushICache(pc, 2 * kInstrSize); 644 CpuFeatures::FlushICache(pc, 2 * kInstrSize);
576 } 645 }
646 } else {
647 // This is an mov / orr immediate load. Patch the immediate embedded in
648 // the instructions.
649 DCHECK(IsMovImmed(Memory::int32_at(pc)) &&
650 IsOrrImmed(Memory::int32_at(pc + kInstrSize)) &&
651 IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
652 IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
653 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
654 uint32_t immediate = reinterpret_cast<uint32_t>(target);
655 instr_ptr[0] = PatchShiftImm(instr_ptr[0], immediate & kImm8Mask);
656 instr_ptr[1] = PatchShiftImm(instr_ptr[1], immediate & (kImm8Mask << 8));
657 instr_ptr[2] = PatchShiftImm(instr_ptr[2], immediate & (kImm8Mask << 16));
658 instr_ptr[3] = PatchShiftImm(instr_ptr[3], immediate & (kImm8Mask << 24));
659 DCHECK(IsMovImmed(Memory::int32_at(pc)) &&
660 IsOrrImmed(Memory::int32_at(pc + kInstrSize)) &&
661 IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
662 IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
663 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
664 CpuFeatures::FlushICache(pc, 4 * kInstrSize);
665 }
577 } 666 }
578 } 667 }
579 668
580 669
581 } } // namespace v8::internal 670 } } // namespace v8::internal
582 671
583 #endif // V8_ARM_ASSEMBLER_ARM_INL_H_ 672 #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