< prev index next >

src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp

Print this page

   9  *
  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 "asm/assembler.hpp"
  27 #include "asm/assembler.inline.hpp"
  28 #include "ci/ciEnv.hpp"

  29 #include "code/compiledIC.hpp"
  30 #include "compiler/compileTask.hpp"
  31 #include "compiler/disassembler.hpp"
  32 #include "compiler/oopMap.hpp"
  33 #include "gc/shared/barrierSet.hpp"
  34 #include "gc/shared/barrierSetAssembler.hpp"
  35 #include "gc/shared/cardTableBarrierSet.hpp"
  36 #include "gc/shared/cardTable.hpp"
  37 #include "gc/shared/collectedHeap.hpp"
  38 #include "gc/shared/tlab_globals.hpp"
  39 #include "interpreter/bytecodeHistogram.hpp"
  40 #include "interpreter/interpreter.hpp"
  41 #include "interpreter/interpreterRuntime.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"

 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   AArch64Decoder decoder(insn_addr, insn);
 498   address target;
 499   decoder.run(insn_addr, target);
 500   return target;

3324 
3325 void MacroAssembler::sub(Register Rd, Register Rn, RegisterOrConstant decrement) {
3326   if (decrement.is_register()) {
3327     sub(Rd, Rn, decrement.as_register());
3328   } else {
3329     sub(Rd, Rn, decrement.as_constant());
3330   }
3331 }
3332 
3333 void MacroAssembler::subw(Register Rd, Register Rn, RegisterOrConstant decrement) {
3334   if (decrement.is_register()) {
3335     subw(Rd, Rn, decrement.as_register());
3336   } else {
3337     subw(Rd, Rn, decrement.as_constant());
3338   }
3339 }
3340 
3341 void MacroAssembler::reinit_heapbase()
3342 {
3343   if (UseCompressedOops) {
3344     if (Universe::is_fully_initialized()) {
3345       mov(rheapbase, CompressedOops::base());
3346     } else {
3347       lea(rheapbase, ExternalAddress(CompressedOops::base_addr()));
3348       ldr(rheapbase, Address(rheapbase));
3349     }
3350   }
3351 }
3352 
3353 // this simulates the behaviour of the x86 cmpxchg instruction using a
3354 // load linked/store conditional pair. we use the acquire/release
3355 // versions of these instructions so that we flush pending writes as
3356 // per Java semantics.
3357 
3358 // n.b the x86 version assumes the old value to be compared against is
3359 // in rax and updates rax with the value located in memory if the
3360 // cmpxchg fails. we supply a register for the old value explicitly
3361 
3362 // the aarch64 load linked/store conditional instructions do not
3363 // accept an offset. so, unlike x86, we must provide a plain register
3364 // to identify the memory word to be compared/exchanged rather than a

5692   // the code cache so that if it is relocated we know it will still reach
5693   if (offset_high >= -(1<<20) && offset_low < (1<<20)) {
5694     _adrp(reg1, dest.target());
5695   } else {
5696     uint64_t target = (uint64_t)dest.target();
5697     uint64_t adrp_target
5698       = (target & 0xffffffffULL) | ((uint64_t)pc() & 0xffff00000000ULL);
5699 
5700     _adrp(reg1, (address)adrp_target);
5701     movk(reg1, target >> 32, 32);
5702   }
5703   byte_offset = (uint64_t)dest.target() & 0xfff;
5704 }
5705 
5706 void MacroAssembler::load_byte_map_base(Register reg) {
5707   CardTable::CardValue* byte_map_base =
5708     ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base();
5709 
5710   // Strictly speaking the byte_map_base isn't an address at all, and it might
5711   // even be negative. It is thus materialised as a constant.
5712   mov(reg, (uint64_t)byte_map_base);























5713 }
5714 
5715 void MacroAssembler::build_frame(int framesize) {
5716   assert(framesize >= 2 * wordSize, "framesize must include space for FP/LR");
5717   assert(framesize % (2*wordSize) == 0, "must preserve 2*wordSize alignment");
5718   protect_return_address();
5719   if (framesize < ((1 << 9) + 2 * wordSize)) {
5720     sub(sp, sp, framesize);
5721     stp(rfp, lr, Address(sp, framesize - 2 * wordSize));
5722     if (PreserveFramePointer) add(rfp, sp, framesize - 2 * wordSize);
5723   } else {
5724     stp(rfp, lr, Address(pre(sp, -2 * wordSize)));
5725     if (PreserveFramePointer) mov(rfp, sp);
5726     if (framesize < ((1 << 12) + 2 * wordSize))
5727       sub(sp, sp, framesize - 2 * wordSize);
5728     else {
5729       mov(rscratch1, framesize - 2 * wordSize);
5730       sub(sp, sp, rscratch1);
5731     }
5732   }

   9  *
  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 "asm/assembler.hpp"
  27 #include "asm/assembler.inline.hpp"
  28 #include "ci/ciEnv.hpp"
  29 #include "ci/ciUtilities.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 "interpreter/interpreterRuntime.hpp"
  43 #include "jvm.h"
  44 #include "memory/resourceArea.hpp"
  45 #include "memory/universe.hpp"
  46 #include "nativeInst_aarch64.hpp"
  47 #include "oops/accessDecorators.hpp"
  48 #include "oops/compressedKlass.inline.hpp"
  49 #include "oops/compressedOops.inline.hpp"

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

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

3345 
3346 void MacroAssembler::sub(Register Rd, Register Rn, RegisterOrConstant decrement) {
3347   if (decrement.is_register()) {
3348     sub(Rd, Rn, decrement.as_register());
3349   } else {
3350     sub(Rd, Rn, decrement.as_constant());
3351   }
3352 }
3353 
3354 void MacroAssembler::subw(Register Rd, Register Rn, RegisterOrConstant decrement) {
3355   if (decrement.is_register()) {
3356     subw(Rd, Rn, decrement.as_register());
3357   } else {
3358     subw(Rd, Rn, decrement.as_constant());
3359   }
3360 }
3361 
3362 void MacroAssembler::reinit_heapbase()
3363 {
3364   if (UseCompressedOops) {
3365     if (Universe::is_fully_initialized() && !AOTCodeCache::is_on_for_dump()) {
3366       mov(rheapbase, CompressedOops::base());
3367     } else {
3368       lea(rheapbase, ExternalAddress(CompressedOops::base_addr()));
3369       ldr(rheapbase, Address(rheapbase));
3370     }
3371   }
3372 }
3373 
3374 // this simulates the behaviour of the x86 cmpxchg instruction using a
3375 // load linked/store conditional pair. we use the acquire/release
3376 // versions of these instructions so that we flush pending writes as
3377 // per Java semantics.
3378 
3379 // n.b the x86 version assumes the old value to be compared against is
3380 // in rax and updates rax with the value located in memory if the
3381 // cmpxchg fails. we supply a register for the old value explicitly
3382 
3383 // the aarch64 load linked/store conditional instructions do not
3384 // accept an offset. so, unlike x86, we must provide a plain register
3385 // to identify the memory word to be compared/exchanged rather than a

5713   // the code cache so that if it is relocated we know it will still reach
5714   if (offset_high >= -(1<<20) && offset_low < (1<<20)) {
5715     _adrp(reg1, dest.target());
5716   } else {
5717     uint64_t target = (uint64_t)dest.target();
5718     uint64_t adrp_target
5719       = (target & 0xffffffffULL) | ((uint64_t)pc() & 0xffff00000000ULL);
5720 
5721     _adrp(reg1, (address)adrp_target);
5722     movk(reg1, target >> 32, 32);
5723   }
5724   byte_offset = (uint64_t)dest.target() & 0xfff;
5725 }
5726 
5727 void MacroAssembler::load_byte_map_base(Register reg) {
5728   CardTable::CardValue* byte_map_base =
5729     ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base();
5730 
5731   // Strictly speaking the byte_map_base isn't an address at all, and it might
5732   // even be negative. It is thus materialised as a constant.
5733 #if INCLUDE_CDS
5734   if (AOTCodeCache::is_on_for_dump()) {
5735     // AOT code needs relocation info for card table base
5736     lea(reg, ExternalAddress(reinterpret_cast<address>(byte_map_base)));
5737   } else {
5738 #endif
5739     mov(reg, (uint64_t)byte_map_base);
5740 #if INCLUDE_CDS
5741   }
5742 #endif
5743 }
5744 
5745 void MacroAssembler::load_aotrc_address(Register reg, address a) {
5746 #if INCLUDE_CDS
5747   assert(AOTRuntimeConstants::contains(a), "address out of range for data area");
5748   if (AOTCodeCache::is_on_for_dump()) {
5749     // all aotrc field addresses should be registered in the AOTCodeCache address table
5750     lea(reg, ExternalAddress(a));
5751   } else {
5752     mov(reg, (uint64_t)a);
5753   }
5754 #else
5755   ShouldNotReachHere();
5756 #endif
5757 }
5758 
5759 void MacroAssembler::build_frame(int framesize) {
5760   assert(framesize >= 2 * wordSize, "framesize must include space for FP/LR");
5761   assert(framesize % (2*wordSize) == 0, "must preserve 2*wordSize alignment");
5762   protect_return_address();
5763   if (framesize < ((1 << 9) + 2 * wordSize)) {
5764     sub(sp, sp, framesize);
5765     stp(rfp, lr, Address(sp, framesize - 2 * wordSize));
5766     if (PreserveFramePointer) add(rfp, sp, framesize - 2 * wordSize);
5767   } else {
5768     stp(rfp, lr, Address(pre(sp, -2 * wordSize)));
5769     if (PreserveFramePointer) mov(rfp, sp);
5770     if (framesize < ((1 << 12) + 2 * wordSize))
5771       sub(sp, sp, framesize - 2 * wordSize);
5772     else {
5773       mov(rscratch1, framesize - 2 * wordSize);
5774       sub(sp, sp, rscratch1);
5775     }
5776   }
< prev index next >