From be837e6e61fa50e8a41aba6844564c393dea9131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Wed, 17 Jun 2026 08:20:01 +0000 Subject: [PATCH] 8386669: AArch64: Distinguish ldr and ldrw literal instructions in NativeInstruction Reviewed-by: aph, adinn --- .../gc/shared/barrierSetNMethod_aarch64.cpp | 11 ++++----- .../cpu/aarch64/nativeInst_aarch64.cpp | 20 ++++++++++++---- .../cpu/aarch64/nativeInst_aarch64.hpp | 22 ++++++++++++++---- src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp | 2 +- .../gtest/aarch64/test_assembler_aarch64.cpp | 23 +++++++++++++++++++ 5 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp index bb93cd9a9d6..89f33cf4529 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetNMethod_aarch64.cpp @@ -124,14 +124,13 @@ public: } }; -// The first instruction of the nmethod entry barrier is an ldr (literal) +// The first instruction of the nmethod entry barrier is an ldrw (literal) // instruction. Verify that it's really there, so the offsets are not skewed. bool NativeNMethodBarrier::check_barrier(err_msg& msg) const { - uint32_t* addr = (uint32_t*) instruction_address(); - uint32_t inst = *addr; - if ((inst & 0xff000000) != 0x18000000) { - msg.print("Nmethod entry barrier did not start with ldr (literal) as expected. " - "Addr: " PTR_FORMAT " Code: " UINT32_FORMAT, p2i(addr), inst); + NativeInstruction* ni = nativeInstruction_at(instruction_address()); + if (!ni->is_ldrw_gpr_literal()) { + msg.print("Nmethod entry barrier did not start with ldrw (literal) as expected. " + "Addr: " PTR_FORMAT " Code: " UINT32_FORMAT, p2i(instruction_address()), ni->encoding()); return false; } return true; diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp index 2ddea2fdcb5..e17993b4c8a 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp @@ -123,7 +123,7 @@ void NativeCall::insert(address code_pos, address entry) { Unimplemented(); } void NativeMovConstReg::verify() { if (! (nativeInstruction_at(instruction_address())->is_movz() || is_adrp_at(instruction_address()) || - is_ldr_literal_at(instruction_address())) ) { + is_load_literal_at(instruction_address())) ) { fatal("should be MOVZ or ADRP or LDR (literal)"); } } @@ -270,17 +270,17 @@ bool NativeInstruction::is_safepoint_poll() { // a safepoint_poll is implemented in two steps as either // // adrp(reg, polling_page); - // ldr(zr, [reg, #offset]); + // ldrw(zr, [reg, #offset]); // // or // // mov(reg, polling_page); - // ldr(zr, [reg, #offset]); + // ldrw(zr, [reg, #offset]); // // or // // ldr(reg, [rthread, #offset]); - // ldr(zr, [reg, #offset]); + // ldrw(zr, [reg, #offset]); // // however, we cannot rely on the polling page address load always // directly preceding the read from the page. C1 does that but C2 @@ -301,11 +301,21 @@ bool NativeInstruction::is_adrp_at(address instr) { return (Instruction_aarch64::extract(insn, 31, 24) & 0b10011111) == 0b10010000; } -bool NativeInstruction::is_ldr_literal_at(address instr) { +bool NativeInstruction::is_load_literal_at(address instr) { unsigned insn = *(unsigned*)instr; return (Instruction_aarch64::extract(insn, 29, 24) & 0b011011) == 0b00011000; } +bool NativeInstruction::is_ldr_gpr_literal_at(address instr) { + unsigned insn = *(unsigned*)instr; + return Instruction_aarch64::extract(insn, 31, 24) == 0b01011000; +} + +bool NativeInstruction::is_ldrw_gpr_literal_at(address instr) { + unsigned insn = *(unsigned*)instr; + return Instruction_aarch64::extract(insn, 31, 24) == 0b00011000; +} + bool NativeInstruction::is_ldrw_to_zr(address instr) { unsigned insn = *(unsigned*)instr; return (Instruction_aarch64::extract(insn, 31, 22) == 0b1011100101 && diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp index 57bb9a91533..c406b471f20 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp @@ -107,10 +107,22 @@ public: static bool is_adrp_at(address instr); - static bool is_ldr_literal_at(address instr); + static bool is_load_literal_at(address instr); - bool is_ldr_literal() { - return is_ldr_literal_at(addr_at(0)); + bool is_load_literal() { + return is_load_literal_at(addr_at(0)); + } + + static bool is_ldr_gpr_literal_at(address instr); + + bool is_ldr_gpr_literal() { + return is_ldr_gpr_literal_at(addr_at(0)); + } + + static bool is_ldrw_gpr_literal_at(address instr); + + bool is_ldrw_gpr_literal() { + return is_ldrw_gpr_literal_at(addr_at(0)); } static bool is_ldrw_to_zr(address instr); @@ -125,7 +137,7 @@ public: } static bool maybe_cpool_ref(address instr) { - return is_adrp_at(instr) || is_ldr_literal_at(instr); + return is_adrp_at(instr) || is_load_literal_at(instr); } bool is_Membar() { @@ -267,7 +279,7 @@ public: return addr_at(instruction_size); else if (is_adrp_at(instruction_address())) return addr_at(2*4); - else if (is_ldr_literal_at(instruction_address())) + else if (is_load_literal_at(instruction_address())) return(addr_at(4)); assert(false, "Unknown instruction in NativeMovConstReg"); return nullptr; diff --git a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp index f1b9fb213a2..5d6bcb45613 100644 --- a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp @@ -41,7 +41,7 @@ void Relocation::pd_set_data_value(address x, bool verify_only) { case relocInfo::oop_type: { oop_Relocation *reloc = (oop_Relocation *)this; - if (NativeInstruction::is_ldr_literal_at(addr())) { + if (NativeInstruction::is_load_literal_at(addr())) { address constptr = (address)code()->oop_addr_at(reloc->oop_index()); bytes = MacroAssembler::pd_patch_instruction_size(addr(), constptr); assert(*(address*)constptr == x, "error in oop relocation"); diff --git a/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp b/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp index a3d856de0df..63b8ddd865d 100644 --- a/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp +++ b/test/hotspot/gtest/aarch64/test_assembler_aarch64.cpp @@ -488,4 +488,27 @@ TEST_VM(AssemblerAArch64, merge_ldst_after_expand) { asm_check((const unsigned int *)code.insts()->start(), insns, sizeof insns / sizeof insns[0]); } +TEST_VM(AssemblerAArch64, native_instruction_load_predicates) { + static uint32_t insns[] = { + 0x58000000, // ldr x0, #0 + 0x18000000, // ldr w0, #0 + 0x1C000000, // ldr s0, #0 (VR bit set to 1, enabling SIMD/FP register) + }; + + NativeInstruction* ni_ldr = nativeInstruction_at(&insns[0]); + EXPECT_TRUE(ni_ldr->is_load_literal()); + EXPECT_TRUE(ni_ldr->is_ldr_gpr_literal()); + EXPECT_FALSE(ni_ldr->is_ldrw_gpr_literal()); + + NativeInstruction* ni_ldrw = nativeInstruction_at(&insns[1]); + EXPECT_TRUE(ni_ldrw->is_load_literal()); + EXPECT_FALSE(ni_ldrw->is_ldr_gpr_literal()); + EXPECT_TRUE(ni_ldrw->is_ldrw_gpr_literal()); + + NativeInstruction* ni_ldrs = nativeInstruction_at(&insns[2]); + EXPECT_TRUE(ni_ldrs->is_load_literal()); + EXPECT_FALSE(ni_ldrs->is_ldr_gpr_literal()); + EXPECT_FALSE(ni_ldrs->is_ldrw_gpr_literal()); +} + #endif // AARCH64