< prev index next >

src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp

Print this page

  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #include "precompiled.hpp"
  27 #include "asm/assembler.hpp"
  28 #include "asm/assembler.inline.hpp"
  29 #include "ci/ciEnv.hpp"


  30 #include "code/compiledIC.hpp"
  31 #include "compiler/compileTask.hpp"
  32 #include "compiler/disassembler.hpp"
  33 #include "compiler/oopMap.hpp"
  34 #include "gc/shared/barrierSet.hpp"
  35 #include "gc/shared/barrierSetAssembler.hpp"
  36 #include "gc/shared/cardTableBarrierSet.hpp"
  37 #include "gc/shared/cardTable.hpp"
  38 #include "gc/shared/collectedHeap.hpp"
  39 #include "gc/shared/tlab_globals.hpp"
  40 #include "interpreter/bytecodeHistogram.hpp"
  41 #include "interpreter/interpreter.hpp"
  42 #include "jvm.h"
  43 #include "memory/resourceArea.hpp"
  44 #include "memory/universe.hpp"
  45 #include "nativeInst_aarch64.hpp"
  46 #include "oops/accessDecorators.hpp"
  47 #include "oops/compressedKlass.inline.hpp"
  48 #include "oops/compressedOops.inline.hpp"
  49 #include "oops/klass.inline.hpp"

 331     uint32_t insn2 = insn_at(insn_addr, 1);
 332     uint32_t size = Instruction_aarch64::extract(insn2, 31, 30);
 333     Instruction_aarch64::patch(insn_addr + sizeof (uint32_t), 21, 10, offset_lo >> size);
 334     guarantee(((dest >> size) << size) == dest, "misaligned target");
 335     return 2;
 336   }
 337   static int adrpAdd_impl(address insn_addr, address &target) {
 338     uintptr_t dest = (uintptr_t)target;
 339     int offset_lo = dest & 0xfff;
 340     Instruction_aarch64::patch(insn_addr + sizeof (uint32_t), 21, 10, offset_lo);
 341     return 2;
 342   }
 343   static int adrpMovk_impl(address insn_addr, address &target) {
 344     uintptr_t dest = uintptr_t(target);
 345     Instruction_aarch64::patch(insn_addr + sizeof (uint32_t), 20, 5, (uintptr_t)target >> 32);
 346     dest = (dest & 0xffffffffULL) | (uintptr_t(insn_addr) & 0xffff00000000ULL);
 347     target = address(dest);
 348     return 2;
 349   }
 350   virtual int immediate(address insn_addr, address &target) {










 351     assert(Instruction_aarch64::extract(_insn, 31, 21) == 0b11010010100, "must be");
 352     uint64_t dest = (uint64_t)target;
 353     // Move wide constant
 354     assert(nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch");
 355     assert(nativeInstruction_at(insn_addr+8)->is_movk(), "wrong insns in patch");
 356     Instruction_aarch64::patch(insn_addr, 20, 5, dest & 0xffff);
 357     Instruction_aarch64::patch(insn_addr+4, 20, 5, (dest >>= 16) & 0xffff);
 358     Instruction_aarch64::patch(insn_addr+8, 20, 5, (dest >>= 16) & 0xffff);
 359     return 3;
 360   }
 361   virtual void verify(address insn_addr, address &target) {
 362 #ifdef ASSERT
 363     address address_is = MacroAssembler::target_addr_for_insn(insn_addr);
 364     if (!(address_is == target)) {
 365       tty->print_cr("%p at %p should be %p", address_is, insn_addr, target);
 366       disnm((intptr_t)insn_addr);
 367       assert(address_is == target, "should be");
 368     }
 369 #endif
 370   }

 461     uint32_t insn2 = insn_at(insn_addr, 1);
 462     uint64_t dest = uint64_t(target);
 463     dest = (dest & 0xffff0000ffffffff) |
 464       ((uint64_t)Instruction_aarch64::extract(insn2, 20, 5) << 32);
 465     target = address(dest);
 466 
 467     // We know the destination 4k page. Maybe we have a third
 468     // instruction.
 469     uint32_t insn = insn_at(insn_addr, 0);
 470     uint32_t insn3 = insn_at(insn_addr, 2);
 471     ptrdiff_t byte_offset;
 472     if (offset_for(insn, insn3, byte_offset)) {
 473       target += byte_offset;
 474       return 3;
 475     } else {
 476       return 2;
 477     }
 478   }
 479   virtual int immediate(address insn_addr, address &target) {
 480     uint32_t *insns = (uint32_t *)insn_addr;










 481     assert(Instruction_aarch64::extract(_insn, 31, 21) == 0b11010010100, "must be");
 482     // Move wide constant: movz, movk, movk.  See movptr().
 483     assert(nativeInstruction_at(insns+1)->is_movk(), "wrong insns in patch");
 484     assert(nativeInstruction_at(insns+2)->is_movk(), "wrong insns in patch");
 485     target = address(uint64_t(Instruction_aarch64::extract(_insn, 20, 5))
 486                  + (uint64_t(Instruction_aarch64::extract(insns[1], 20, 5)) << 16)
 487                  + (uint64_t(Instruction_aarch64::extract(insns[2], 20, 5)) << 32));
 488     assert(nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch");
 489     assert(nativeInstruction_at(insn_addr+8)->is_movk(), "wrong insns in patch");
 490     return 3;
 491   }
 492   virtual void verify(address insn_addr, address &target) {
 493   }
 494 };
 495 
 496 address MacroAssembler::target_addr_for_insn(address insn_addr, uint32_t insn) {
 497   Decoder decoder(insn_addr, insn);
 498   address target;
 499   decoder.run(insn_addr, target);
 500   return target;

 658                        JavaThread::frame_anchor_offset()
 659                        + JavaFrameAnchor::last_Java_pc_offset()));
 660 
 661   set_last_Java_frame(last_java_sp, last_java_fp, noreg, scratch);
 662 }
 663 
 664 void MacroAssembler::set_last_Java_frame(Register last_java_sp,
 665                                          Register last_java_fp,
 666                                          Label &L,
 667                                          Register scratch) {
 668   if (L.is_bound()) {
 669     set_last_Java_frame(last_java_sp, last_java_fp, target(L), scratch);
 670   } else {
 671     InstructionMark im(this);
 672     L.add_patch_at(code(), locator());
 673     set_last_Java_frame(last_java_sp, last_java_fp, pc() /* Patched later */, scratch);
 674   }
 675 }
 676 
 677 static inline bool target_needs_far_branch(address addr) {



 678   // codecache size <= 128M
 679   if (!MacroAssembler::far_branches()) {
 680     return false;
 681   }
 682   // codecache size > 240M
 683   if (MacroAssembler::codestub_branch_needs_far_jump()) {
 684     return true;
 685   }
 686   // codecache size: 128M..240M
 687   return !CodeCache::is_non_nmethod(addr);
 688 }
 689 
 690 void MacroAssembler::far_call(Address entry, Register tmp) {
 691   assert(ReservedCodeCacheSize < 4*G, "branch out of range");
 692   assert(CodeCache::find_blob(entry.target()) != nullptr,
 693          "destination of far call not found in code cache");
 694   assert(entry.rspec().type() == relocInfo::external_word_type
 695          || entry.rspec().type() == relocInfo::runtime_call_type
 696          || entry.rspec().type() == relocInfo::none, "wrong entry relocInfo type");
 697   if (target_needs_far_branch(entry.target())) {

1540 
1541   assert(sub_klass != r0, "killed reg"); // killed by mov(r0, super)
1542   assert(sub_klass != r2, "killed reg"); // killed by lea(r2, &pst_counter)
1543 
1544   RegSet pushed_registers;
1545   if (!IS_A_TEMP(r2))    pushed_registers += r2;
1546   if (!IS_A_TEMP(r5))    pushed_registers += r5;
1547 
1548   if (super_klass != r0) {
1549     if (!IS_A_TEMP(r0))   pushed_registers += r0;
1550   }
1551 
1552   push(pushed_registers, sp);
1553 
1554   // Get super_klass value into r0 (even if it was in r5 or r2).
1555   if (super_klass != r0) {
1556     mov(r0, super_klass);
1557   }
1558 
1559 #ifndef PRODUCT
1560   mov(rscratch2, (address)&SharedRuntime::_partial_subtype_ctr);





1561   Address pst_counter_addr(rscratch2);
1562   ldr(rscratch1, pst_counter_addr);
1563   add(rscratch1, rscratch1, 1);
1564   str(rscratch1, pst_counter_addr);
1565 #endif //PRODUCT
1566 
1567   // We will consult the secondary-super array.
1568   ldr(r5, secondary_supers_addr);
1569   // Load the array length.
1570   ldrw(r2, Address(r5, Array<Klass*>::length_offset_in_bytes()));
1571   // Skip to start of data.
1572   add(r5, r5, Array<Klass*>::base_offset_in_bytes());
1573 
1574   cmp(sp, zr); // Clear Z flag; SP is never zero
1575   // Scan R2 words at [R5] for an occurrence of R0.
1576   // Set NZ/Z based on last compare.
1577   repne_scan(r5, r0, r2, rscratch1);
1578 
1579   // Unspill the temp. registers:
1580   pop(pushed_registers, sp);

2755 
2756 void MacroAssembler::sub(Register Rd, Register Rn, RegisterOrConstant decrement) {
2757   if (decrement.is_register()) {
2758     sub(Rd, Rn, decrement.as_register());
2759   } else {
2760     sub(Rd, Rn, decrement.as_constant());
2761   }
2762 }
2763 
2764 void MacroAssembler::subw(Register Rd, Register Rn, RegisterOrConstant decrement) {
2765   if (decrement.is_register()) {
2766     subw(Rd, Rn, decrement.as_register());
2767   } else {
2768     subw(Rd, Rn, decrement.as_constant());
2769   }
2770 }
2771 
2772 void MacroAssembler::reinit_heapbase()
2773 {
2774   if (UseCompressedOops) {
2775     if (Universe::is_fully_initialized()) {
2776       mov(rheapbase, CompressedOops::ptrs_base());
2777     } else {
2778       lea(rheapbase, ExternalAddress(CompressedOops::ptrs_base_addr()));
2779       ldr(rheapbase, Address(rheapbase));
2780     }
2781   }
2782 }
2783 
2784 // this simulates the behaviour of the x86 cmpxchg instruction using a
2785 // load linked/store conditional pair. we use the acquire/release
2786 // versions of these instructions so that we flush pending writes as
2787 // per Java semantics.
2788 
2789 // n.b the x86 version assumes the old value to be compared against is
2790 // in rax and updates rax with the value located in memory if the
2791 // cmpxchg fails. we supply a register for the old value explicitly
2792 
2793 // the aarch64 load linked/store conditional instructions do not
2794 // accept an offset. so, unlike x86, we must provide a plain register
2795 // to identify the memory word to be compared/exchanged rather than a

5058   // the code cache so that if it is relocated we know it will still reach
5059   if (offset_high >= -(1<<20) && offset_low < (1<<20)) {
5060     _adrp(reg1, dest.target());
5061   } else {
5062     uint64_t target = (uint64_t)dest.target();
5063     uint64_t adrp_target
5064       = (target & 0xffffffffULL) | ((uint64_t)pc() & 0xffff00000000ULL);
5065 
5066     _adrp(reg1, (address)adrp_target);
5067     movk(reg1, target >> 32, 32);
5068   }
5069   byte_offset = (uint64_t)dest.target() & 0xfff;
5070 }
5071 
5072 void MacroAssembler::load_byte_map_base(Register reg) {
5073   CardTable::CardValue* byte_map_base =
5074     ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base();
5075 
5076   // Strictly speaking the byte_map_base isn't an address at all, and it might
5077   // even be negative. It is thus materialised as a constant.
5078   mov(reg, (uint64_t)byte_map_base);





5079 }
5080 
5081 void MacroAssembler::build_frame(int framesize) {
5082   assert(framesize >= 2 * wordSize, "framesize must include space for FP/LR");
5083   assert(framesize % (2*wordSize) == 0, "must preserve 2*wordSize alignment");
5084   protect_return_address();
5085   if (framesize < ((1 << 9) + 2 * wordSize)) {
5086     sub(sp, sp, framesize);
5087     stp(rfp, lr, Address(sp, framesize - 2 * wordSize));
5088     if (PreserveFramePointer) add(rfp, sp, framesize - 2 * wordSize);
5089   } else {
5090     stp(rfp, lr, Address(pre(sp, -2 * wordSize)));
5091     if (PreserveFramePointer) mov(rfp, sp);
5092     if (framesize < ((1 << 12) + 2 * wordSize))
5093       sub(sp, sp, framesize - 2 * wordSize);
5094     else {
5095       mov(rscratch1, framesize - 2 * wordSize);
5096       sub(sp, sp, rscratch1);
5097     }
5098   }

  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  *
  24  */
  25 
  26 #include "precompiled.hpp"
  27 #include "asm/assembler.hpp"
  28 #include "asm/assembler.inline.hpp"
  29 #include "ci/ciEnv.hpp"
  30 #include "ci/ciUtilities.hpp"
  31 #include "code/SCCache.hpp"
  32 #include "code/compiledIC.hpp"
  33 #include "compiler/compileTask.hpp"
  34 #include "compiler/disassembler.hpp"
  35 #include "compiler/oopMap.hpp"
  36 #include "gc/shared/barrierSet.hpp"
  37 #include "gc/shared/barrierSetAssembler.hpp"
  38 #include "gc/shared/cardTableBarrierSet.hpp"
  39 #include "gc/shared/cardTable.hpp"
  40 #include "gc/shared/collectedHeap.hpp"
  41 #include "gc/shared/tlab_globals.hpp"
  42 #include "interpreter/bytecodeHistogram.hpp"
  43 #include "interpreter/interpreter.hpp"
  44 #include "jvm.h"
  45 #include "memory/resourceArea.hpp"
  46 #include "memory/universe.hpp"
  47 #include "nativeInst_aarch64.hpp"
  48 #include "oops/accessDecorators.hpp"
  49 #include "oops/compressedKlass.inline.hpp"
  50 #include "oops/compressedOops.inline.hpp"
  51 #include "oops/klass.inline.hpp"

 333     uint32_t insn2 = insn_at(insn_addr, 1);
 334     uint32_t size = Instruction_aarch64::extract(insn2, 31, 30);
 335     Instruction_aarch64::patch(insn_addr + sizeof (uint32_t), 21, 10, offset_lo >> size);
 336     guarantee(((dest >> size) << size) == dest, "misaligned target");
 337     return 2;
 338   }
 339   static int adrpAdd_impl(address insn_addr, address &target) {
 340     uintptr_t dest = (uintptr_t)target;
 341     int offset_lo = dest & 0xfff;
 342     Instruction_aarch64::patch(insn_addr + sizeof (uint32_t), 21, 10, offset_lo);
 343     return 2;
 344   }
 345   static int adrpMovk_impl(address insn_addr, address &target) {
 346     uintptr_t dest = uintptr_t(target);
 347     Instruction_aarch64::patch(insn_addr + sizeof (uint32_t), 20, 5, (uintptr_t)target >> 32);
 348     dest = (dest & 0xffffffffULL) | (uintptr_t(insn_addr) & 0xffff00000000ULL);
 349     target = address(dest);
 350     return 2;
 351   }
 352   virtual int immediate(address insn_addr, address &target) {
 353     // Metadata pointers are either narrow (32 bits) or wide (48 bits).
 354     // We encode narrow ones by setting the upper 16 bits in the first
 355     // instruction.
 356     if (Instruction_aarch64::extract(_insn, 31, 21) == 0b11010010101) {
 357       assert(nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch");
 358       narrowKlass nk = CompressedKlassPointers::encode((Klass*)target);
 359       Instruction_aarch64::patch(insn_addr, 20, 5, nk >> 16);
 360       Instruction_aarch64::patch(insn_addr+4, 20, 5, nk & 0xffff);
 361       return 2;
 362     }
 363     assert(Instruction_aarch64::extract(_insn, 31, 21) == 0b11010010100, "must be");
 364     uint64_t dest = (uint64_t)target;
 365     // Move wide constant
 366     assert(nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch");
 367     assert(nativeInstruction_at(insn_addr+8)->is_movk(), "wrong insns in patch");
 368     Instruction_aarch64::patch(insn_addr, 20, 5, dest & 0xffff);
 369     Instruction_aarch64::patch(insn_addr+4, 20, 5, (dest >>= 16) & 0xffff);
 370     Instruction_aarch64::patch(insn_addr+8, 20, 5, (dest >>= 16) & 0xffff);
 371     return 3;
 372   }
 373   virtual void verify(address insn_addr, address &target) {
 374 #ifdef ASSERT
 375     address address_is = MacroAssembler::target_addr_for_insn(insn_addr);
 376     if (!(address_is == target)) {
 377       tty->print_cr("%p at %p should be %p", address_is, insn_addr, target);
 378       disnm((intptr_t)insn_addr);
 379       assert(address_is == target, "should be");
 380     }
 381 #endif
 382   }

 473     uint32_t insn2 = insn_at(insn_addr, 1);
 474     uint64_t dest = uint64_t(target);
 475     dest = (dest & 0xffff0000ffffffff) |
 476       ((uint64_t)Instruction_aarch64::extract(insn2, 20, 5) << 32);
 477     target = address(dest);
 478 
 479     // We know the destination 4k page. Maybe we have a third
 480     // instruction.
 481     uint32_t insn = insn_at(insn_addr, 0);
 482     uint32_t insn3 = insn_at(insn_addr, 2);
 483     ptrdiff_t byte_offset;
 484     if (offset_for(insn, insn3, byte_offset)) {
 485       target += byte_offset;
 486       return 3;
 487     } else {
 488       return 2;
 489     }
 490   }
 491   virtual int immediate(address insn_addr, address &target) {
 492     uint32_t *insns = (uint32_t *)insn_addr;
 493     // Metadata pointers are either narrow (32 bits) or wide (48 bits).
 494     // We encode narrow ones by setting the upper 16 bits in the first
 495     // instruction.
 496     if (Instruction_aarch64::extract(_insn, 31, 21) == 0b11010010101) {
 497       assert(nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch");
 498       narrowKlass nk = (narrowKlass)((uint32_t(Instruction_aarch64::extract(_insn, 20, 5)) << 16)
 499                                    +  uint32_t(Instruction_aarch64::extract(insns[1], 20, 5)));
 500       target = (address)CompressedKlassPointers::decode(nk);
 501       return 2;
 502     }
 503     assert(Instruction_aarch64::extract(_insn, 31, 21) == 0b11010010100, "must be");
 504     // Move wide constant: movz, movk, movk.  See movptr().
 505     assert(nativeInstruction_at(insns+1)->is_movk(), "wrong insns in patch");
 506     assert(nativeInstruction_at(insns+2)->is_movk(), "wrong insns in patch");
 507     target = address(uint64_t(Instruction_aarch64::extract(_insn, 20, 5))
 508                  + (uint64_t(Instruction_aarch64::extract(insns[1], 20, 5)) << 16)
 509                  + (uint64_t(Instruction_aarch64::extract(insns[2], 20, 5)) << 32));
 510     assert(nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch");
 511     assert(nativeInstruction_at(insn_addr+8)->is_movk(), "wrong insns in patch");
 512     return 3;
 513   }
 514   virtual void verify(address insn_addr, address &target) {
 515   }
 516 };
 517 
 518 address MacroAssembler::target_addr_for_insn(address insn_addr, uint32_t insn) {
 519   Decoder decoder(insn_addr, insn);
 520   address target;
 521   decoder.run(insn_addr, target);
 522   return target;

 680                        JavaThread::frame_anchor_offset()
 681                        + JavaFrameAnchor::last_Java_pc_offset()));
 682 
 683   set_last_Java_frame(last_java_sp, last_java_fp, noreg, scratch);
 684 }
 685 
 686 void MacroAssembler::set_last_Java_frame(Register last_java_sp,
 687                                          Register last_java_fp,
 688                                          Label &L,
 689                                          Register scratch) {
 690   if (L.is_bound()) {
 691     set_last_Java_frame(last_java_sp, last_java_fp, target(L), scratch);
 692   } else {
 693     InstructionMark im(this);
 694     L.add_patch_at(code(), locator());
 695     set_last_Java_frame(last_java_sp, last_java_fp, pc() /* Patched later */, scratch);
 696   }
 697 }
 698 
 699 static inline bool target_needs_far_branch(address addr) {
 700   if (SCCache::is_on_for_write()) {
 701     return true;
 702   }
 703   // codecache size <= 128M
 704   if (!MacroAssembler::far_branches()) {
 705     return false;
 706   }
 707   // codecache size > 240M
 708   if (MacroAssembler::codestub_branch_needs_far_jump()) {
 709     return true;
 710   }
 711   // codecache size: 128M..240M
 712   return !CodeCache::is_non_nmethod(addr);
 713 }
 714 
 715 void MacroAssembler::far_call(Address entry, Register tmp) {
 716   assert(ReservedCodeCacheSize < 4*G, "branch out of range");
 717   assert(CodeCache::find_blob(entry.target()) != nullptr,
 718          "destination of far call not found in code cache");
 719   assert(entry.rspec().type() == relocInfo::external_word_type
 720          || entry.rspec().type() == relocInfo::runtime_call_type
 721          || entry.rspec().type() == relocInfo::none, "wrong entry relocInfo type");
 722   if (target_needs_far_branch(entry.target())) {

1565 
1566   assert(sub_klass != r0, "killed reg"); // killed by mov(r0, super)
1567   assert(sub_klass != r2, "killed reg"); // killed by lea(r2, &pst_counter)
1568 
1569   RegSet pushed_registers;
1570   if (!IS_A_TEMP(r2))    pushed_registers += r2;
1571   if (!IS_A_TEMP(r5))    pushed_registers += r5;
1572 
1573   if (super_klass != r0) {
1574     if (!IS_A_TEMP(r0))   pushed_registers += r0;
1575   }
1576 
1577   push(pushed_registers, sp);
1578 
1579   // Get super_klass value into r0 (even if it was in r5 or r2).
1580   if (super_klass != r0) {
1581     mov(r0, super_klass);
1582   }
1583 
1584 #ifndef PRODUCT
1585   if (SCCache::is_on_for_write()) {
1586     // SCA needs relocation info for this
1587     lea(rscratch2, ExternalAddress((address)&SharedRuntime::_partial_subtype_ctr));
1588   } else {
1589     mov(rscratch2, (address)&SharedRuntime::_partial_subtype_ctr);
1590   }
1591   Address pst_counter_addr(rscratch2);
1592   ldr(rscratch1, pst_counter_addr);
1593   add(rscratch1, rscratch1, 1);
1594   str(rscratch1, pst_counter_addr);
1595 #endif //PRODUCT
1596 
1597   // We will consult the secondary-super array.
1598   ldr(r5, secondary_supers_addr);
1599   // Load the array length.
1600   ldrw(r2, Address(r5, Array<Klass*>::length_offset_in_bytes()));
1601   // Skip to start of data.
1602   add(r5, r5, Array<Klass*>::base_offset_in_bytes());
1603 
1604   cmp(sp, zr); // Clear Z flag; SP is never zero
1605   // Scan R2 words at [R5] for an occurrence of R0.
1606   // Set NZ/Z based on last compare.
1607   repne_scan(r5, r0, r2, rscratch1);
1608 
1609   // Unspill the temp. registers:
1610   pop(pushed_registers, sp);

2785 
2786 void MacroAssembler::sub(Register Rd, Register Rn, RegisterOrConstant decrement) {
2787   if (decrement.is_register()) {
2788     sub(Rd, Rn, decrement.as_register());
2789   } else {
2790     sub(Rd, Rn, decrement.as_constant());
2791   }
2792 }
2793 
2794 void MacroAssembler::subw(Register Rd, Register Rn, RegisterOrConstant decrement) {
2795   if (decrement.is_register()) {
2796     subw(Rd, Rn, decrement.as_register());
2797   } else {
2798     subw(Rd, Rn, decrement.as_constant());
2799   }
2800 }
2801 
2802 void MacroAssembler::reinit_heapbase()
2803 {
2804   if (UseCompressedOops) {
2805     if (Universe::is_fully_initialized() && !SCCache::is_on_for_write()) {
2806       mov(rheapbase, CompressedOops::ptrs_base());
2807     } else {
2808       lea(rheapbase, ExternalAddress(CompressedOops::ptrs_base_addr()));
2809       ldr(rheapbase, Address(rheapbase));
2810     }
2811   }
2812 }
2813 
2814 // this simulates the behaviour of the x86 cmpxchg instruction using a
2815 // load linked/store conditional pair. we use the acquire/release
2816 // versions of these instructions so that we flush pending writes as
2817 // per Java semantics.
2818 
2819 // n.b the x86 version assumes the old value to be compared against is
2820 // in rax and updates rax with the value located in memory if the
2821 // cmpxchg fails. we supply a register for the old value explicitly
2822 
2823 // the aarch64 load linked/store conditional instructions do not
2824 // accept an offset. so, unlike x86, we must provide a plain register
2825 // to identify the memory word to be compared/exchanged rather than a

5088   // the code cache so that if it is relocated we know it will still reach
5089   if (offset_high >= -(1<<20) && offset_low < (1<<20)) {
5090     _adrp(reg1, dest.target());
5091   } else {
5092     uint64_t target = (uint64_t)dest.target();
5093     uint64_t adrp_target
5094       = (target & 0xffffffffULL) | ((uint64_t)pc() & 0xffff00000000ULL);
5095 
5096     _adrp(reg1, (address)adrp_target);
5097     movk(reg1, target >> 32, 32);
5098   }
5099   byte_offset = (uint64_t)dest.target() & 0xfff;
5100 }
5101 
5102 void MacroAssembler::load_byte_map_base(Register reg) {
5103   CardTable::CardValue* byte_map_base =
5104     ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base();
5105 
5106   // Strictly speaking the byte_map_base isn't an address at all, and it might
5107   // even be negative. It is thus materialised as a constant.
5108   if (SCCache::is_on_for_write()) {
5109     // SCA needs relocation info for card table base
5110     lea(reg, ExternalAddress(reinterpret_cast<address>(byte_map_base)));
5111   } else {
5112     mov(reg, (uint64_t)byte_map_base);
5113   }
5114 }
5115 
5116 void MacroAssembler::build_frame(int framesize) {
5117   assert(framesize >= 2 * wordSize, "framesize must include space for FP/LR");
5118   assert(framesize % (2*wordSize) == 0, "must preserve 2*wordSize alignment");
5119   protect_return_address();
5120   if (framesize < ((1 << 9) + 2 * wordSize)) {
5121     sub(sp, sp, framesize);
5122     stp(rfp, lr, Address(sp, framesize - 2 * wordSize));
5123     if (PreserveFramePointer) add(rfp, sp, framesize - 2 * wordSize);
5124   } else {
5125     stp(rfp, lr, Address(pre(sp, -2 * wordSize)));
5126     if (PreserveFramePointer) mov(rfp, sp);
5127     if (framesize < ((1 << 12) + 2 * wordSize))
5128       sub(sp, sp, framesize - 2 * wordSize);
5129     else {
5130       mov(rscratch1, framesize - 2 * wordSize);
5131       sub(sp, sp, rscratch1);
5132     }
5133   }
< prev index next >