diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp index 7f7f19957e92a..8fbeaa45371d1 100644 --- a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp @@ -629,7 +629,7 @@ void ZBarrierSetAssembler::patch_barrier_relocation(address addr, int format) { case ZBarrierRelocationFormatMarkBadMask: case ZBarrierRelocationFormatStoreGoodBits: case ZBarrierRelocationFormatStoreBadMask: - assert(NativeInstruction::is_li16u_at(addr), "invalide zgc barrier"); + assert(MacroAssembler::is_li16u_at(addr), "invalide zgc barrier"); bytes = MacroAssembler::pd_patch_instruction_size(addr, (address)(uintptr_t)value); break; default: diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 20a0cf5680f41..9961ce8e6dd39 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -38,7 +38,6 @@ #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" -#include "nativeInst_riscv.hpp" #include "oops/accessDecorators.hpp" #include "oops/compressedKlass.inline.hpp" #include "oops/compressedOops.inline.hpp" @@ -65,6 +64,138 @@ #define STOP(str) stop(str); #define BIND(label) bind(label); __ BLOCK_COMMENT(#label ":") + + +Register MacroAssembler::extract_rs1(address instr) { + assert_cond(instr != nullptr); + return as_Register(Assembler::extract(Assembler::ld_instr(instr), 19, 15)); +} + +Register MacroAssembler::extract_rs2(address instr) { + assert_cond(instr != nullptr); + return as_Register(Assembler::extract(Assembler::ld_instr(instr), 24, 20)); +} + +Register MacroAssembler::extract_rd(address instr) { + assert_cond(instr != nullptr); + return as_Register(Assembler::extract(Assembler::ld_instr(instr), 11, 7)); +} + +uint32_t MacroAssembler::extract_opcode(address instr) { + assert_cond(instr != nullptr); + return Assembler::extract(Assembler::ld_instr(instr), 6, 0); +} + +uint32_t MacroAssembler::extract_funct3(address instr) { + assert_cond(instr != nullptr); + return Assembler::extract(Assembler::ld_instr(instr), 14, 12); +} + +bool MacroAssembler::is_pc_relative_at(address instr) { + // auipc + jalr + // auipc + addi + // auipc + load + // auipc + fload_load + return (is_auipc_at(instr)) && + (is_addi_at(instr + instruction_size) || + is_jalr_at(instr + instruction_size) || + is_load_at(instr + instruction_size) || + is_float_load_at(instr + instruction_size)) && + check_pc_relative_data_dependency(instr); +} + +// ie:ld(Rd, Label) +bool MacroAssembler::is_load_pc_relative_at(address instr) { + return is_auipc_at(instr) && // auipc + is_ld_at(instr + instruction_size) && // ld + check_load_pc_relative_data_dependency(instr); +} + +bool MacroAssembler::is_movptr1_at(address instr) { + return is_lui_at(instr) && // Lui + is_addi_at(instr + instruction_size) && // Addi + is_slli_shift_at(instr + instruction_size * 2, 11) && // Slli Rd, Rs, 11 + is_addi_at(instr + instruction_size * 3) && // Addi + is_slli_shift_at(instr + instruction_size * 4, 6) && // Slli Rd, Rs, 6 + (is_addi_at(instr + instruction_size * 5) || + is_jalr_at(instr + instruction_size * 5) || + is_load_at(instr + instruction_size * 5)) && // Addi/Jalr/Load + check_movptr1_data_dependency(instr); +} + +bool MacroAssembler::is_movptr2_at(address instr) { + return is_lui_at(instr) && // lui + is_lui_at(instr + instruction_size) && // lui + is_slli_shift_at(instr + instruction_size * 2, 18) && // slli Rd, Rs, 18 + is_add_at(instr + instruction_size * 3) && + (is_addi_at(instr + instruction_size * 4) || + is_jalr_at(instr + instruction_size * 4) || + is_load_at(instr + instruction_size * 4)) && // Addi/Jalr/Load + check_movptr2_data_dependency(instr); +} + +bool MacroAssembler::is_li16u_at(address instr) { + return is_lui_at(instr) && // lui + is_srli_at(instr + instruction_size) && // srli + check_li16u_data_dependency(instr); +} + +bool MacroAssembler::is_li32_at(address instr) { + return is_lui_at(instr) && // lui + is_addiw_at(instr + instruction_size) && // addiw + check_li32_data_dependency(instr); +} + +bool MacroAssembler::is_li64_at(address instr) { + return is_lui_at(instr) && // lui + is_addi_at(instr + instruction_size) && // addi + is_slli_shift_at(instr + instruction_size * 2, 12) && // Slli Rd, Rs, 12 + is_addi_at(instr + instruction_size * 3) && // addi + is_slli_shift_at(instr + instruction_size * 4, 12) && // Slli Rd, Rs, 12 + is_addi_at(instr + instruction_size * 5) && // addi + is_slli_shift_at(instr + instruction_size * 6, 8) && // Slli Rd, Rs, 8 + is_addi_at(instr + instruction_size * 7) && // addi + check_li64_data_dependency(instr); +} + +bool MacroAssembler::is_lwu_to_zr(address instr) { + assert_cond(instr != nullptr); + return (extract_opcode(instr) == 0b0000011 && + extract_funct3(instr) == 0b110 && + extract_rd(instr) == zr); // zr +} + +uint32_t MacroAssembler::get_membar_kind(address addr) { + assert_cond(addr != nullptr); + assert(is_membar(addr), "no membar found"); + + uint32_t insn = Bytes::get_native_u4(addr); + + uint32_t predecessor = Assembler::extract(insn, 27, 24); + uint32_t successor = Assembler::extract(insn, 23, 20); + + return MacroAssembler::pred_succ_to_membar_mask(predecessor, successor); +} + +void MacroAssembler::set_membar_kind(address addr, uint32_t order_kind) { + assert_cond(addr != nullptr); + assert(is_membar(addr), "no membar found"); + + uint32_t predecessor = 0; + uint32_t successor = 0; + + MacroAssembler::membar_mask_to_pred_succ(order_kind, predecessor, successor); + + uint32_t insn = Bytes::get_native_u4(addr); + address pInsn = (address) &insn; + Assembler::patch(pInsn, 27, 24, predecessor); + Assembler::patch(pInsn, 23, 20, successor); + + address membar = addr; + Assembler::sd_instr(membar, insn); +} + + static void pass_arg0(MacroAssembler* masm, Register arg) { if (c_rarg0 != arg) { masm->mv(c_rarg0, arg); @@ -1405,7 +1536,7 @@ static int patch_offset_in_jal(address branch, int64_t offset) { Assembler::patch(branch, 30, 21, (offset >> 1) & 0x3ff); // offset[10:1] ==> branch[30:21] Assembler::patch(branch, 20, 20, (offset >> 11) & 0x1); // offset[11] ==> branch[20] Assembler::patch(branch, 19, 12, (offset >> 12) & 0xff); // offset[19:12] ==> branch[19:12] - return NativeInstruction::instruction_size; // only one instruction + return MacroAssembler::instruction_size; // only one instruction } static int patch_offset_in_conditional_branch(address branch, int64_t offset) { @@ -1415,14 +1546,14 @@ static int patch_offset_in_conditional_branch(address branch, int64_t offset) { Assembler::patch(branch, 30, 25, (offset >> 5) & 0x3f); // offset[10:5] ==> branch[30:25] Assembler::patch(branch, 7, 7, (offset >> 11) & 0x1); // offset[11] ==> branch[7] Assembler::patch(branch, 11, 8, (offset >> 1) & 0xf); // offset[4:1] ==> branch[11:8] - return NativeInstruction::instruction_size; // only one instruction + return MacroAssembler::instruction_size; // only one instruction } static int patch_offset_in_pc_relative(address branch, int64_t offset) { const int PC_RELATIVE_INSTRUCTION_NUM = 2; // auipc, addi/jalr/load Assembler::patch(branch, 31, 12, ((offset + 0x800) >> 12) & 0xfffff); // Auipc. offset[31:12] ==> branch[31:12] Assembler::patch(branch + 4, 31, 20, offset & 0xfff); // Addi/Jalr/Load. offset[11:0] ==> branch[31:20] - return PC_RELATIVE_INSTRUCTION_NUM * NativeInstruction::instruction_size; + return PC_RELATIVE_INSTRUCTION_NUM * MacroAssembler::instruction_size; } static int patch_addr_in_movptr1(address branch, address target) { @@ -1432,7 +1563,7 @@ static int patch_addr_in_movptr1(address branch, address target) { Assembler::patch(branch + 4, 31, 20, (lower >> 17) & 0xfff); // Addi. target[28:17] ==> branch[31:20] Assembler::patch(branch + 12, 31, 20, (lower >> 6) & 0x7ff); // Addi. target[16: 6] ==> branch[31:20] Assembler::patch(branch + 20, 31, 20, lower & 0x3f); // Addi/Jalr/Load. target[ 5: 0] ==> branch[31:20] - return NativeMovConstReg::movptr1_instruction_size; + return MacroAssembler::movptr1_instruction_size; } static int patch_addr_in_movptr2(address instruction_address, address target) { @@ -1444,15 +1575,15 @@ static int patch_addr_in_movptr2(address instruction_address, address target) { int low12 = (lower30 << 20) >> 20; int mid18 = ((lower30 - low12) >> 12); - Assembler::patch(instruction_address + (NativeInstruction::instruction_size * 0), 31, 12, (upper18 & 0xfffff)); // Lui - Assembler::patch(instruction_address + (NativeInstruction::instruction_size * 1), 31, 12, (mid18 & 0xfffff)); // Lui + Assembler::patch(instruction_address + (MacroAssembler::instruction_size * 0), 31, 12, (upper18 & 0xfffff)); // Lui + Assembler::patch(instruction_address + (MacroAssembler::instruction_size * 1), 31, 12, (mid18 & 0xfffff)); // Lui // Slli // Add - Assembler::patch(instruction_address + (NativeInstruction::instruction_size * 4), 31, 20, low12 & 0xfff); // Addi/Jalr/Load + Assembler::patch(instruction_address + (MacroAssembler::instruction_size * 4), 31, 20, low12 & 0xfff); // Addi/Jalr/Load assert(MacroAssembler::target_addr_for_insn(instruction_address) == target, "Must be"); - return NativeMovConstReg::movptr2_instruction_size; + return MacroAssembler::movptr2_instruction_size; } static int patch_imm_in_li64(address branch, address target) { @@ -1473,12 +1604,12 @@ static int patch_imm_in_li64(address branch, address target) { Assembler::patch(branch + 12, 31, 20, ((int32_t)lower >> 20) & 0xfff); // Addi. Assembler::patch(branch + 20, 31, 20, (((intptr_t)target << 44) >> 52) & 0xfff); // Addi. Assembler::patch(branch + 28, 31, 20, (intptr_t)target & 0xff); // Addi. - return LI64_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; + return LI64_INSTRUCTIONS_NUM * MacroAssembler::instruction_size; } static int patch_imm_in_li16u(address branch, uint16_t target) { Assembler::patch(branch, 31, 12, target); // patch lui only - return NativeInstruction::instruction_size; + return MacroAssembler::instruction_size; } int MacroAssembler::patch_imm_in_li32(address branch, int32_t target) { @@ -1489,7 +1620,7 @@ int MacroAssembler::patch_imm_in_li32(address branch, int32_t target) { upper = (int32_t)upper; Assembler::patch(branch + 0, 31, 12, (upper >> 12) & 0xfffff); // Lui. Assembler::patch(branch + 4, 31, 20, lower & 0xfff); // Addiw. - return LI32_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; + return LI32_INSTRUCTIONS_NUM * MacroAssembler::instruction_size; } static long get_offset_of_jal(address insn_addr) { @@ -1537,11 +1668,11 @@ static address get_target_of_movptr1(address insn_addr) { static address get_target_of_movptr2(address insn_addr) { assert_cond(insn_addr != nullptr); - int32_t upper18 = ((Assembler::sextract(Assembler::ld_instr(insn_addr + NativeInstruction::instruction_size * 0), 31, 12)) & 0xfffff); // Lui - int32_t mid18 = ((Assembler::sextract(Assembler::ld_instr(insn_addr + NativeInstruction::instruction_size * 1), 31, 12)) & 0xfffff); // Lui + int32_t upper18 = ((Assembler::sextract(Assembler::ld_instr(insn_addr + MacroAssembler::instruction_size * 0), 31, 12)) & 0xfffff); // Lui + int32_t mid18 = ((Assembler::sextract(Assembler::ld_instr(insn_addr + MacroAssembler::instruction_size * 1), 31, 12)) & 0xfffff); // Lui // 2 // Slli // 3 // Add - int32_t low12 = ((Assembler::sextract(Assembler::ld_instr(insn_addr + NativeInstruction::instruction_size * 4), 31, 20))); // Addi/Jalr/Load. + int32_t low12 = ((Assembler::sextract(Assembler::ld_instr(insn_addr + MacroAssembler::instruction_size * 4), 31, 20))); // Addi/Jalr/Load. address ret = (address)(((intptr_t)upper18<<30ll) + ((intptr_t)mid18<<12ll) + low12); return ret; } @@ -1568,22 +1699,22 @@ address MacroAssembler::get_target_of_li32(address insn_addr) { int MacroAssembler::pd_patch_instruction_size(address instruction_address, address target) { assert_cond(instruction_address != nullptr); int64_t offset = target - instruction_address; - if (NativeInstruction::is_jal_at(instruction_address)) { // jal + if (MacroAssembler::is_jal_at(instruction_address)) { // jal return patch_offset_in_jal(instruction_address, offset); - } else if (NativeInstruction::is_branch_at(instruction_address)) { // beq/bge/bgeu/blt/bltu/bne + } else if (MacroAssembler::is_branch_at(instruction_address)) { // beq/bge/bgeu/blt/bltu/bne return patch_offset_in_conditional_branch(instruction_address, offset); - } else if (NativeInstruction::is_pc_relative_at(instruction_address)) { // auipc, addi/jalr/load + } else if (MacroAssembler::is_pc_relative_at(instruction_address)) { // auipc, addi/jalr/load return patch_offset_in_pc_relative(instruction_address, offset); - } else if (NativeInstruction::is_movptr1_at(instruction_address)) { // movptr1 + } else if (MacroAssembler::is_movptr1_at(instruction_address)) { // movptr1 return patch_addr_in_movptr1(instruction_address, target); - } else if (NativeInstruction::is_movptr2_at(instruction_address)) { // movptr2 + } else if (MacroAssembler::is_movptr2_at(instruction_address)) { // movptr2 return patch_addr_in_movptr2(instruction_address, target); - } else if (NativeInstruction::is_li64_at(instruction_address)) { // li64 + } else if (MacroAssembler::is_li64_at(instruction_address)) { // li64 return patch_imm_in_li64(instruction_address, target); - } else if (NativeInstruction::is_li32_at(instruction_address)) { // li32 + } else if (MacroAssembler::is_li32_at(instruction_address)) { // li32 int64_t imm = (intptr_t)target; return patch_imm_in_li32(instruction_address, (int32_t)imm); - } else if (NativeInstruction::is_li16u_at(instruction_address)) { + } else if (MacroAssembler::is_li16u_at(instruction_address)) { int64_t imm = (intptr_t)target; return patch_imm_in_li16u(instruction_address, (uint16_t)imm); } else { @@ -1600,19 +1731,19 @@ int MacroAssembler::pd_patch_instruction_size(address instruction_address, addre address MacroAssembler::target_addr_for_insn(address insn_addr) { long offset = 0; assert_cond(insn_addr != nullptr); - if (NativeInstruction::is_jal_at(insn_addr)) { // jal + if (MacroAssembler::is_jal_at(insn_addr)) { // jal offset = get_offset_of_jal(insn_addr); - } else if (NativeInstruction::is_branch_at(insn_addr)) { // beq/bge/bgeu/blt/bltu/bne + } else if (MacroAssembler::is_branch_at(insn_addr)) { // beq/bge/bgeu/blt/bltu/bne offset = get_offset_of_conditional_branch(insn_addr); - } else if (NativeInstruction::is_pc_relative_at(insn_addr)) { // auipc, addi/jalr/load + } else if (MacroAssembler::is_pc_relative_at(insn_addr)) { // auipc, addi/jalr/load offset = get_offset_of_pc_relative(insn_addr); - } else if (NativeInstruction::is_movptr1_at(insn_addr)) { // movptr1 + } else if (MacroAssembler::is_movptr1_at(insn_addr)) { // movptr1 return get_target_of_movptr1(insn_addr); - } else if (NativeInstruction::is_movptr2_at(insn_addr)) { // movptr2 + } else if (MacroAssembler::is_movptr2_at(insn_addr)) { // movptr2 return get_target_of_movptr2(insn_addr); - } else if (NativeInstruction::is_li64_at(insn_addr)) { // li64 + } else if (MacroAssembler::is_li64_at(insn_addr)) { // li64 return get_target_of_li64(insn_addr); - } else if (NativeInstruction::is_li32_at(insn_addr)) { // li32 + } else if (MacroAssembler::is_li32_at(insn_addr)) { // li32 return get_target_of_li32(insn_addr); } else { ShouldNotReachHere(); @@ -1624,14 +1755,14 @@ int MacroAssembler::patch_oop(address insn_addr, address o) { // OOPs are either narrow (32 bits) or wide (48 bits). We encode // narrow OOPs by setting the upper 16 bits in the first // instruction. - if (NativeInstruction::is_li32_at(insn_addr)) { + if (MacroAssembler::is_li32_at(insn_addr)) { // Move narrow OOP uint32_t n = CompressedOops::narrow_oop_value(cast_to_oop(o)); return patch_imm_in_li32(insn_addr, (int32_t)n); - } else if (NativeInstruction::is_movptr1_at(insn_addr)) { + } else if (MacroAssembler::is_movptr1_at(insn_addr)) { // Move wide OOP return patch_addr_in_movptr1(insn_addr, o); - } else if (NativeInstruction::is_movptr2_at(insn_addr)) { + } else if (MacroAssembler::is_movptr2_at(insn_addr)) { // Move wide OOP return patch_addr_in_movptr2(insn_addr, o); } @@ -2779,14 +2910,13 @@ void MacroAssembler::lookup_virtual_method(Register recv_klass, } void MacroAssembler::membar(uint32_t order_constraint) { - address prev = pc() - NativeMembar::instruction_size; + address prev = pc() - MacroAssembler::instruction_size; address last = code()->last_insn(); - if (last != nullptr && nativeInstruction_at(last)->is_membar() && prev == last) { - NativeMembar *bar = NativeMembar_at(prev); + if (last != nullptr && is_membar(last) && prev == last) { // We are merging two memory barrier instructions. On RISCV we // can do this simply by ORing them together. - bar->set_kind(bar->get_kind() | order_constraint); + set_membar_kind(prev, get_membar_kind(prev) | order_constraint); BLOCK_COMMENT("merged membar"); } else { code()->set_last_insn(pc()); @@ -3653,7 +3783,7 @@ address MacroAssembler::ic_call(address entry, jint method_index) { int MacroAssembler::ic_check_size() { // No compressed - return (NativeInstruction::instruction_size * (2 /* 2 loads */ + 1 /* branch */)) + + return (MacroAssembler::instruction_size * (2 /* 2 loads */ + 1 /* branch */)) + far_branch_size(); } @@ -3720,7 +3850,7 @@ address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset, // instructions code-section. // Make sure the address of destination 8-byte aligned after 3 instructions. - align(wordSize, NativeCallTrampolineStub::data_offset); + align(wordSize, MacroAssembler::trampoline_stub_data_offset); RelocationHolder rh = trampoline_stub_Relocation::spec(code()->insts()->start() + insts_call_instruction_offset); @@ -3733,7 +3863,7 @@ address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset, ld(t0, target); // auipc + ld jr(t0); // jalr bind(target); - assert(offset() - stub_start_offset == NativeCallTrampolineStub::data_offset, + assert(offset() - stub_start_offset == MacroAssembler::trampoline_stub_data_offset, "should be"); assert(offset() % wordSize == 0, "bad alignment"); emit_int64((int64_t)dest); @@ -3741,7 +3871,7 @@ address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset, const address stub_start_addr = addr_at(stub_start_offset); - assert(is_NativeCallTrampolineStub_at(stub_start_addr), "doesn't look like a trampoline"); + assert(MacroAssembler::is_trampoline_stub_at(stub_start_addr), "doesn't look like a trampoline"); end_a_stub(); return stub_start_addr; @@ -3749,12 +3879,12 @@ address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset, int MacroAssembler::max_trampoline_stub_size() { // Max stub size: alignment nop, TrampolineStub. - return NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size; + return MacroAssembler::instruction_size + MacroAssembler::trampoline_stub_instruction_size; } int MacroAssembler::static_call_stub_size() { // (lui, addi, slli, addi, slli, addi) + (lui + lui + slli + add) + jalr - return 11 * NativeInstruction::instruction_size; + return 11 * MacroAssembler::instruction_size; } Address MacroAssembler::add_memory_helper(const Address dst, Register tmp) { diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index e5800b0aa916d..4e9a41625ad46 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -30,7 +30,6 @@ #include "asm/assembler.inline.hpp" #include "code/vmreg.hpp" #include "metaprogramming/enableIf.hpp" -#include "nativeInst_riscv.hpp" #include "oops/compressedOops.hpp" #include "utilities/powerOfTwo.hpp" @@ -42,6 +41,7 @@ class MacroAssembler: public Assembler { public: + MacroAssembler(CodeBuffer* code) : Assembler(code) {} void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod); @@ -49,7 +49,7 @@ class MacroAssembler: public Assembler { // Alignment int align(int modulus, int extra_offset = 0); - static inline void assert_alignment(address pc, int alignment = NativeInstruction::instruction_size) { + static inline void assert_alignment(address pc, int alignment = MacroAssembler::instruction_size) { assert(is_aligned(pc, alignment), "bad alignment"); } @@ -1232,7 +1232,7 @@ class MacroAssembler: public Assembler { address ic_call(address entry, jint method_index = 0); static int ic_check_size(); - int ic_check(int end_alignment = NativeInstruction::instruction_size); + int ic_check(int end_alignment = MacroAssembler::instruction_size); // Support for memory inc/dec // n.b. increment/decrement calls with an Address destination will @@ -1542,6 +1542,226 @@ class MacroAssembler: public Assembler { public: void lightweight_lock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow); void lightweight_unlock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow); + +public: + enum { + // Refer to function emit_trampoline_stub. + trampoline_stub_instruction_size = 3 * instruction_size + wordSize, // auipc + ld + jr + target address + trampoline_stub_data_offset = 3 * instruction_size, // auipc + ld + jr + + // movptr + movptr1_instruction_size = 6 * instruction_size, // lui, addi, slli, addi, slli, addi. See movptr1(). + movptr2_instruction_size = 5 * instruction_size, // lui, lui, slli, add, addi. See movptr2(). + load_pc_relative_instruction_size = 2 * instruction_size // auipc, ld + }; + + static bool is_load_pc_relative_at(address branch); + static bool is_li16u_at(address instr); + + static bool is_trampoline_stub_at(address addr) { + // Ensure that the stub is exactly + // ld t0, L--->auipc + ld + // jr t0 + // L: + + // judge inst + register + imm + // 1). check the instructions: auipc + ld + jalr + // 2). check if auipc[11:7] == t0 and ld[11:7] == t0 and ld[19:15] == t0 && jr[19:15] == t0 + // 3). check if the offset in ld[31:20] equals the data_offset + assert_cond(addr != nullptr); + const int instr_size = instruction_size; + if (is_auipc_at(addr) && + is_ld_at(addr + instr_size) && + is_jalr_at(addr + 2 * instr_size) && + (extract_rd(addr) == x5) && + (extract_rd(addr + instr_size) == x5) && + (extract_rs1(addr + instr_size) == x5) && + (extract_rs1(addr + 2 * instr_size) == x5) && + (Assembler::extract(Assembler::ld_instr(addr + 4), 31, 20) == trampoline_stub_data_offset)) { + return true; + } + return false; + } + + static bool is_call_at(address instr) { + if (is_jal_at(instr) || is_jalr_at(instr)) { + return true; + } + return false; + } + + static bool is_jal_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b1101111; } + static bool is_jalr_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b1100111 && extract_funct3(instr) == 0b000; } + static bool is_branch_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b1100011; } + static bool is_ld_at(address instr) { assert_cond(instr != nullptr); return is_load_at(instr) && extract_funct3(instr) == 0b011; } + static bool is_load_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0000011; } + static bool is_float_load_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0000111; } + static bool is_auipc_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0010111; } + static bool is_jump_at(address instr) { assert_cond(instr != nullptr); return is_branch_at(instr) || is_jal_at(instr) || is_jalr_at(instr); } + static bool is_add_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0110011 && extract_funct3(instr) == 0b000; } + static bool is_addi_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0010011 && extract_funct3(instr) == 0b000; } + static bool is_addiw_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0011011 && extract_funct3(instr) == 0b000; } + static bool is_addiw_to_zr_at(address instr){ assert_cond(instr != nullptr); return is_addiw_at(instr) && extract_rd(instr) == zr; } + static bool is_lui_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0110111; } + static bool is_lui_to_zr_at(address instr) { assert_cond(instr != nullptr); return is_lui_at(instr) && extract_rd(instr) == zr; } + + static bool is_srli_at(address instr) { + assert_cond(instr != nullptr); + return extract_opcode(instr) == 0b0010011 && + extract_funct3(instr) == 0b101 && + Assembler::extract(((unsigned*)instr)[0], 31, 26) == 0b000000; + } + + static bool is_slli_shift_at(address instr, uint32_t shift) { + assert_cond(instr != nullptr); + return (extract_opcode(instr) == 0b0010011 && // opcode field + extract_funct3(instr) == 0b001 && // funct3 field, select the type of operation + Assembler::extract(Assembler::ld_instr(instr), 25, 20) == shift); // shamt field + } + + static bool is_movptr1_at(address instr); + static bool is_movptr2_at(address instr); + + static bool is_lwu_to_zr(address instr); + +private: + static Register extract_rs1(address instr); + static Register extract_rs2(address instr); + static Register extract_rd(address instr); + static uint32_t extract_opcode(address instr); + static uint32_t extract_funct3(address instr); + + // the instruction sequence of movptr is as below: + // lui + // addi + // slli + // addi + // slli + // addi/jalr/load + static bool check_movptr1_data_dependency(address instr) { + address lui = instr; + address addi1 = lui + instruction_size; + address slli1 = addi1 + instruction_size; + address addi2 = slli1 + instruction_size; + address slli2 = addi2 + instruction_size; + address last_instr = slli2 + instruction_size; + return extract_rs1(addi1) == extract_rd(lui) && + extract_rs1(addi1) == extract_rd(addi1) && + extract_rs1(slli1) == extract_rd(addi1) && + extract_rs1(slli1) == extract_rd(slli1) && + extract_rs1(addi2) == extract_rd(slli1) && + extract_rs1(addi2) == extract_rd(addi2) && + extract_rs1(slli2) == extract_rd(addi2) && + extract_rs1(slli2) == extract_rd(slli2) && + extract_rs1(last_instr) == extract_rd(slli2); + } + + // the instruction sequence of movptr2 is as below: + // lui + // lui + // slli + // add + // addi/jalr/load + static bool check_movptr2_data_dependency(address instr) { + address lui1 = instr; + address lui2 = lui1 + instruction_size; + address slli = lui2 + instruction_size; + address add = slli + instruction_size; + address last_instr = add + instruction_size; + return extract_rd(add) == extract_rd(lui2) && + extract_rs1(add) == extract_rd(lui2) && + extract_rs2(add) == extract_rd(slli) && + extract_rs1(slli) == extract_rd(lui1) && + extract_rd(slli) == extract_rd(lui1) && + extract_rs1(last_instr) == extract_rd(add); + } + + // the instruction sequence of li64 is as below: + // lui + // addi + // slli + // addi + // slli + // addi + // slli + // addi + static bool check_li64_data_dependency(address instr) { + address lui = instr; + address addi1 = lui + instruction_size; + address slli1 = addi1 + instruction_size; + address addi2 = slli1 + instruction_size; + address slli2 = addi2 + instruction_size; + address addi3 = slli2 + instruction_size; + address slli3 = addi3 + instruction_size; + address addi4 = slli3 + instruction_size; + return extract_rs1(addi1) == extract_rd(lui) && + extract_rs1(addi1) == extract_rd(addi1) && + extract_rs1(slli1) == extract_rd(addi1) && + extract_rs1(slli1) == extract_rd(slli1) && + extract_rs1(addi2) == extract_rd(slli1) && + extract_rs1(addi2) == extract_rd(addi2) && + extract_rs1(slli2) == extract_rd(addi2) && + extract_rs1(slli2) == extract_rd(slli2) && + extract_rs1(addi3) == extract_rd(slli2) && + extract_rs1(addi3) == extract_rd(addi3) && + extract_rs1(slli3) == extract_rd(addi3) && + extract_rs1(slli3) == extract_rd(slli3) && + extract_rs1(addi4) == extract_rd(slli3) && + extract_rs1(addi4) == extract_rd(addi4); + } + + // the instruction sequence of li16u is as below: + // lui + // srli + static bool check_li16u_data_dependency(address instr) { + address lui = instr; + address srli = lui + instruction_size; + + return extract_rs1(srli) == extract_rd(lui) && + extract_rs1(srli) == extract_rd(srli); + } + + // the instruction sequence of li32 is as below: + // lui + // addiw + static bool check_li32_data_dependency(address instr) { + address lui = instr; + address addiw = lui + instruction_size; + + return extract_rs1(addiw) == extract_rd(lui) && + extract_rs1(addiw) == extract_rd(addiw); + } + + // the instruction sequence of pc-relative is as below: + // auipc + // jalr/addi/load/float_load + static bool check_pc_relative_data_dependency(address instr) { + address auipc = instr; + address last_instr = auipc + instruction_size; + + return extract_rs1(last_instr) == extract_rd(auipc); + } + + // the instruction sequence of load_label is as below: + // auipc + // load + static bool check_load_pc_relative_data_dependency(address instr) { + address auipc = instr; + address load = auipc + instruction_size; + + return extract_rd(load) == extract_rd(auipc) && + extract_rs1(load) == extract_rd(load); + } + + static bool is_li32_at(address instr); + static bool is_li64_at(address instr); + static bool is_pc_relative_at(address branch); + + static bool is_membar(address addr) { + return (Bytes::get_native_u4(addr) & 0x7f) == 0b1111 && extract_funct3(addr) == 0; + } + static uint32_t get_membar_kind(address addr); + static void set_membar_kind(address addr, uint32_t order_kind); }; #ifdef ASSERT diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index dd54329e521d5..348a00b6767f9 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -39,112 +39,20 @@ #include "c1/c1_Runtime1.hpp" #endif -Register NativeInstruction::extract_rs1(address instr) { - assert_cond(instr != nullptr); - return as_Register(Assembler::extract(Assembler::ld_instr(instr), 19, 15)); -} - -Register NativeInstruction::extract_rs2(address instr) { - assert_cond(instr != nullptr); - return as_Register(Assembler::extract(Assembler::ld_instr(instr), 24, 20)); -} - -Register NativeInstruction::extract_rd(address instr) { - assert_cond(instr != nullptr); - return as_Register(Assembler::extract(Assembler::ld_instr(instr), 11, 7)); -} - -uint32_t NativeInstruction::extract_opcode(address instr) { - assert_cond(instr != nullptr); - return Assembler::extract(Assembler::ld_instr(instr), 6, 0); -} - -uint32_t NativeInstruction::extract_funct3(address instr) { - assert_cond(instr != nullptr); - return Assembler::extract(Assembler::ld_instr(instr), 14, 12); -} - -bool NativeInstruction::is_pc_relative_at(address instr) { - // auipc + jalr - // auipc + addi - // auipc + load - // auipc + fload_load - return (is_auipc_at(instr)) && - (is_addi_at(instr + instruction_size) || - is_jalr_at(instr + instruction_size) || - is_load_at(instr + instruction_size) || - is_float_load_at(instr + instruction_size)) && - check_pc_relative_data_dependency(instr); -} - -// ie:ld(Rd, Label) -bool NativeInstruction::is_load_pc_relative_at(address instr) { - return is_auipc_at(instr) && // auipc - is_ld_at(instr + instruction_size) && // ld - check_load_pc_relative_data_dependency(instr); -} - -bool NativeInstruction::is_movptr1_at(address instr) { - return is_lui_at(instr) && // Lui - is_addi_at(instr + instruction_size) && // Addi - is_slli_shift_at(instr + instruction_size * 2, 11) && // Slli Rd, Rs, 11 - is_addi_at(instr + instruction_size * 3) && // Addi - is_slli_shift_at(instr + instruction_size * 4, 6) && // Slli Rd, Rs, 6 - (is_addi_at(instr + instruction_size * 5) || - is_jalr_at(instr + instruction_size * 5) || - is_load_at(instr + instruction_size * 5)) && // Addi/Jalr/Load - check_movptr1_data_dependency(instr); -} - -bool NativeInstruction::is_movptr2_at(address instr) { - return is_lui_at(instr) && // lui - is_lui_at(instr + instruction_size) && // lui - is_slli_shift_at(instr + instruction_size * 2, 18) && // slli Rd, Rs, 18 - is_add_at(instr + instruction_size * 3) && - (is_addi_at(instr + instruction_size * 4) || - is_jalr_at(instr + instruction_size * 4) || - is_load_at(instr + instruction_size * 4)) && // Addi/Jalr/Load - check_movptr2_data_dependency(instr); -} - -bool NativeInstruction::is_li16u_at(address instr) { - return is_lui_at(instr) && // lui - is_srli_at(instr + instruction_size) && // srli - check_li16u_data_dependency(instr); -} - -bool NativeInstruction::is_li32_at(address instr) { - return is_lui_at(instr) && // lui - is_addiw_at(instr + instruction_size) && // addiw - check_li32_data_dependency(instr); -} - -bool NativeInstruction::is_li64_at(address instr) { - return is_lui_at(instr) && // lui - is_addi_at(instr + instruction_size) && // addi - is_slli_shift_at(instr + instruction_size * 2, 12) && // Slli Rd, Rs, 12 - is_addi_at(instr + instruction_size * 3) && // addi - is_slli_shift_at(instr + instruction_size * 4, 12) && // Slli Rd, Rs, 12 - is_addi_at(instr + instruction_size * 5) && // addi - is_slli_shift_at(instr + instruction_size * 6, 8) && // Slli Rd, Rs, 8 - is_addi_at(instr + instruction_size * 7) && // addi - check_li64_data_dependency(instr); -} - void NativeCall::verify() { - assert(NativeCall::is_call_at((address)this), "unexpected code at call site"); + assert(MacroAssembler::is_call_at((address)this), "unexpected code at call site"); } address NativeCall::destination() const { address addr = (address)this; - assert(NativeInstruction::is_jal_at(instruction_address()), "inst must be jal."); + assert(MacroAssembler::is_jal_at(instruction_address()), "inst must be jal."); address destination = MacroAssembler::target_addr_for_insn(instruction_address()); // Do we use a trampoline stub for this call? CodeBlob* cb = CodeCache::find_blob(addr); assert(cb && cb->is_nmethod(), "sanity"); nmethod *nm = (nmethod *)cb; - if (nm != nullptr && nm->stub_contains(destination) && is_NativeCallTrampolineStub_at(destination)) { + if (nm != nullptr && nm->stub_contains(destination) && MacroAssembler::is_trampoline_stub_at(destination)) { // Yes we do, so get the destination from the trampoline stub. const address trampoline_stub_addr = destination; destination = nativeCallTrampolineStub_at(trampoline_stub_addr)->destination(); @@ -168,12 +76,12 @@ void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { "concurrent code patching"); address addr_call = addr_at(0); - assert(NativeCall::is_call_at(addr_call), "unexpected code at call site"); + assert(MacroAssembler::is_call_at(addr_call), "unexpected code at call site"); // Patch the constant in the call's trampoline stub. address trampoline_stub_addr = get_trampoline(); if (trampoline_stub_addr != nullptr) { - assert (!is_NativeCallTrampolineStub_at(dest), "chained trampolines"); + assert (!MacroAssembler::is_trampoline_stub_at(dest), "chained trampolines"); nativeCallTrampolineStub_at(trampoline_stub_addr)->set_destination(dest); } @@ -195,7 +103,7 @@ address NativeCall::get_trampoline() { assert(code != nullptr, "Could not find the containing code blob"); address jal_destination = MacroAssembler::pd_call_destination(call_addr); - if (code != nullptr && code->contains(jal_destination) && is_NativeCallTrampolineStub_at(jal_destination)) { + if (code != nullptr && code->contains(jal_destination) && MacroAssembler::is_trampoline_stub_at(jal_destination)) { return jal_destination; } @@ -341,14 +249,7 @@ address NativeGeneralJump::jump_destination() const { //------------------------------------------------------------------- bool NativeInstruction::is_safepoint_poll() { - return is_lwu_to_zr(address(this)); -} - -bool NativeInstruction::is_lwu_to_zr(address instr) { - assert_cond(instr != nullptr); - return (extract_opcode(instr) == 0b0000011 && - extract_funct3(instr) == 0b110 && - extract_rd(instr) == zr); // zr + return MacroAssembler::is_lwu_to_zr(address(this)); } // A 16-bit instruction with all bits ones is permanently reserved as an illegal instruction. @@ -435,30 +336,6 @@ void NativeCallTrampolineStub::set_destination(address new_destination) { OrderAccess::release(); } -uint32_t NativeMembar::get_kind() { - uint32_t insn = uint_at(0); - - uint32_t predecessor = Assembler::extract(insn, 27, 24); - uint32_t successor = Assembler::extract(insn, 23, 20); - - return MacroAssembler::pred_succ_to_membar_mask(predecessor, successor); -} - -void NativeMembar::set_kind(uint32_t order_kind) { - uint32_t predecessor = 0; - uint32_t successor = 0; - - MacroAssembler::membar_mask_to_pred_succ(order_kind, predecessor, successor); - - uint32_t insn = uint_at(0); - address pInsn = (address) &insn; - Assembler::patch(pInsn, 27, 24, predecessor); - Assembler::patch(pInsn, 23, 20, successor); - - address membar = addr_at(0); - Assembler::sd_instr(membar, insn); -} - void NativePostCallNop::make_deopt() { MacroAssembler::assert_alignment(addr_at(0)); NativeDeoptInstruction::insert(addr_at(0)); @@ -481,7 +358,7 @@ bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) { } int32_t data = (oopmap_slot << 24) | cb_offset; assert(data != 0, "must be"); - assert(is_lui_to_zr_at(addr_at(4)) && is_addiw_to_zr_at(addr_at(8)), "must be"); + assert(MacroAssembler::is_lui_to_zr_at(addr_at(4)) && MacroAssembler::is_addiw_to_zr_at(addr_at(8)), "must be"); MacroAssembler::patch_imm_in_li32(addr_at(4), data); return true; // successfully encoded diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index dcdf525aafb9e..e9b3624d9d29d 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -27,6 +27,7 @@ #ifndef CPU_RISCV_NATIVEINST_RISCV_HPP #define CPU_RISCV_NATIVEINST_RISCV_HPP +#include "macroAssembler_riscv.hpp" #include "asm/assembler.hpp" #include "runtime/continuation.hpp" #include "runtime/icache.hpp" @@ -52,198 +53,24 @@ class NativeCall; class NativeInstruction { friend class Relocation; - friend bool is_NativeCallTrampolineStub_at(address); public: enum { - instruction_size = 4, - compressed_instruction_size = 2, + instruction_size = MacroAssembler::instruction_size, + compressed_instruction_size = MacroAssembler::compressed_instruction_size, }; juint encoding() const { return uint_at(0); } - bool is_jal() const { return is_jal_at(addr_at(0)); } - bool is_movptr() const { return is_movptr1_at(addr_at(0)) || - is_movptr2_at(addr_at(0)); } - bool is_movptr1() const { return is_movptr1_at(addr_at(0)); } - bool is_movptr2() const { return is_movptr2_at(addr_at(0)); } - bool is_auipc() const { return is_auipc_at(addr_at(0)); } - bool is_call() const { return is_call_at(addr_at(0)); } - bool is_jump() const { return is_jump_at(addr_at(0)); } - - static bool is_jal_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b1101111; } - static bool is_jalr_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b1100111 && extract_funct3(instr) == 0b000; } - static bool is_branch_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b1100011; } - static bool is_ld_at(address instr) { assert_cond(instr != nullptr); return is_load_at(instr) && extract_funct3(instr) == 0b011; } - static bool is_load_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0000011; } - static bool is_float_load_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0000111; } - static bool is_auipc_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0010111; } - static bool is_jump_at(address instr) { assert_cond(instr != nullptr); return is_branch_at(instr) || is_jal_at(instr) || is_jalr_at(instr); } - static bool is_add_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0110011 && extract_funct3(instr) == 0b000; } - static bool is_addi_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0010011 && extract_funct3(instr) == 0b000; } - static bool is_addiw_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0011011 && extract_funct3(instr) == 0b000; } - static bool is_addiw_to_zr_at(address instr){ assert_cond(instr != nullptr); return is_addiw_at(instr) && extract_rd(instr) == zr; } - static bool is_lui_at(address instr) { assert_cond(instr != nullptr); return extract_opcode(instr) == 0b0110111; } - static bool is_lui_to_zr_at(address instr) { assert_cond(instr != nullptr); return is_lui_at(instr) && extract_rd(instr) == zr; } - - static bool is_srli_at(address instr) { - assert_cond(instr != nullptr); - return extract_opcode(instr) == 0b0010011 && - extract_funct3(instr) == 0b101 && - Assembler::extract(((unsigned*)instr)[0], 31, 26) == 0b000000; - } - - static bool is_slli_shift_at(address instr, uint32_t shift) { - assert_cond(instr != nullptr); - return (extract_opcode(instr) == 0b0010011 && // opcode field - extract_funct3(instr) == 0b001 && // funct3 field, select the type of operation - Assembler::extract(Assembler::ld_instr(instr), 25, 20) == shift); // shamt field - } - - static Register extract_rs1(address instr); - static Register extract_rs2(address instr); - static Register extract_rd(address instr); - static uint32_t extract_opcode(address instr); - static uint32_t extract_funct3(address instr); - - // the instruction sequence of movptr is as below: - // lui - // addi - // slli - // addi - // slli - // addi/jalr/load - static bool check_movptr1_data_dependency(address instr) { - address lui = instr; - address addi1 = lui + instruction_size; - address slli1 = addi1 + instruction_size; - address addi2 = slli1 + instruction_size; - address slli2 = addi2 + instruction_size; - address last_instr = slli2 + instruction_size; - return extract_rs1(addi1) == extract_rd(lui) && - extract_rs1(addi1) == extract_rd(addi1) && - extract_rs1(slli1) == extract_rd(addi1) && - extract_rs1(slli1) == extract_rd(slli1) && - extract_rs1(addi2) == extract_rd(slli1) && - extract_rs1(addi2) == extract_rd(addi2) && - extract_rs1(slli2) == extract_rd(addi2) && - extract_rs1(slli2) == extract_rd(slli2) && - extract_rs1(last_instr) == extract_rd(slli2); - } - - // the instruction sequence of movptr2 is as below: - // lui - // lui - // slli - // add - // addi/jalr/load - static bool check_movptr2_data_dependency(address instr) { - address lui1 = instr; - address lui2 = lui1 + instruction_size; - address slli = lui2 + instruction_size; - address add = slli + instruction_size; - address last_instr = add + instruction_size; - return extract_rd(add) == extract_rd(lui2) && - extract_rs1(add) == extract_rd(lui2) && - extract_rs2(add) == extract_rd(slli) && - extract_rs1(slli) == extract_rd(lui1) && - extract_rd(slli) == extract_rd(lui1) && - extract_rs1(last_instr) == extract_rd(add); - } - - // the instruction sequence of li64 is as below: - // lui - // addi - // slli - // addi - // slli - // addi - // slli - // addi - static bool check_li64_data_dependency(address instr) { - address lui = instr; - address addi1 = lui + instruction_size; - address slli1 = addi1 + instruction_size; - address addi2 = slli1 + instruction_size; - address slli2 = addi2 + instruction_size; - address addi3 = slli2 + instruction_size; - address slli3 = addi3 + instruction_size; - address addi4 = slli3 + instruction_size; - return extract_rs1(addi1) == extract_rd(lui) && - extract_rs1(addi1) == extract_rd(addi1) && - extract_rs1(slli1) == extract_rd(addi1) && - extract_rs1(slli1) == extract_rd(slli1) && - extract_rs1(addi2) == extract_rd(slli1) && - extract_rs1(addi2) == extract_rd(addi2) && - extract_rs1(slli2) == extract_rd(addi2) && - extract_rs1(slli2) == extract_rd(slli2) && - extract_rs1(addi3) == extract_rd(slli2) && - extract_rs1(addi3) == extract_rd(addi3) && - extract_rs1(slli3) == extract_rd(addi3) && - extract_rs1(slli3) == extract_rd(slli3) && - extract_rs1(addi4) == extract_rd(slli3) && - extract_rs1(addi4) == extract_rd(addi4); - } - - // the instruction sequence of li16u is as below: - // lui - // srli - static bool check_li16u_data_dependency(address instr) { - address lui = instr; - address srli = lui + instruction_size; - - return extract_rs1(srli) == extract_rd(lui) && - extract_rs1(srli) == extract_rd(srli); - } - - // the instruction sequence of li32 is as below: - // lui - // addiw - static bool check_li32_data_dependency(address instr) { - address lui = instr; - address addiw = lui + instruction_size; - - return extract_rs1(addiw) == extract_rd(lui) && - extract_rs1(addiw) == extract_rd(addiw); - } - - // the instruction sequence of pc-relative is as below: - // auipc - // jalr/addi/load/float_load - static bool check_pc_relative_data_dependency(address instr) { - address auipc = instr; - address last_instr = auipc + instruction_size; - - return extract_rs1(last_instr) == extract_rd(auipc); - } - - // the instruction sequence of load_label is as below: - // auipc - // load - static bool check_load_pc_relative_data_dependency(address instr) { - address auipc = instr; - address load = auipc + instruction_size; - - return extract_rd(load) == extract_rd(auipc) && - extract_rs1(load) == extract_rd(load); - } - - static bool is_movptr1_at(address instr); - static bool is_movptr2_at(address instr); - static bool is_li16u_at(address instr); - static bool is_li32_at(address instr); - static bool is_li64_at(address instr); - static bool is_pc_relative_at(address branch); - static bool is_load_pc_relative_at(address branch); - - static bool is_call_at(address instr) { - if (is_jal_at(instr) || is_jalr_at(instr)) { - return true; - } - return false; - } - static bool is_lwu_to_zr(address instr); + bool is_jal() const { return MacroAssembler::is_jal_at(addr_at(0)); } + bool is_movptr() const { return MacroAssembler::is_movptr1_at(addr_at(0)) || + MacroAssembler::is_movptr2_at(addr_at(0)); } + bool is_movptr1() const { return MacroAssembler::is_movptr1_at(addr_at(0)); } + bool is_movptr2() const { return MacroAssembler::is_movptr2_at(addr_at(0)); } + bool is_auipc() const { return MacroAssembler::is_auipc_at(addr_at(0)); } + bool is_call() const { return MacroAssembler::is_call_at(addr_at(0)); } + bool is_jump() const { return MacroAssembler::is_jump_at(addr_at(0)); } inline bool is_nop() const; inline bool is_jump_or_nop(); @@ -272,11 +99,7 @@ class NativeInstruction { inline friend NativeInstruction* nativeInstruction_at(address addr); static bool maybe_cpool_ref(address instr) { - return is_auipc_at(instr); - } - - bool is_membar() { - return (uint_at(0) & 0x7f) == 0b1111 && extract_funct3(addr_at(0)) == 0; + return MacroAssembler::is_auipc_at(instr); } }; @@ -332,7 +155,7 @@ class NativeCall: public NativeInstruction { inline friend NativeCall* nativeCall_before(address return_address); static bool is_call_before(address return_address) { - return is_call_at(return_address - NativeCall::return_address_offset); + return MacroAssembler::is_call_at(return_address - NativeCall::return_address_offset); } // MT-safe patching of a call instruction. @@ -377,9 +200,9 @@ inline NativeCall* nativeCall_before(address return_address) { class NativeMovConstReg: public NativeInstruction { public: enum RISCV_specific_constants { - movptr1_instruction_size = 6 * NativeInstruction::instruction_size, // lui, addi, slli, addi, slli, addi. See movptr1(). - movptr2_instruction_size = 5 * NativeInstruction::instruction_size, // lui, lui, slli, add, addi. See movptr2(). - load_pc_relative_instruction_size = 2 * NativeInstruction::instruction_size // auipc, ld + movptr1_instruction_size = MacroAssembler::movptr1_instruction_size, // lui, addi, slli, addi, slli, addi. See movptr1(). + movptr2_instruction_size = MacroAssembler::movptr2_instruction_size, // lui, lui, slli, add, addi. See movptr2(). + load_pc_relative_instruction_size = MacroAssembler::load_pc_relative_instruction_size // auipc, ld }; address instruction_address() const { return addr_at(0); } @@ -389,23 +212,23 @@ class NativeMovConstReg: public NativeInstruction { // and the next instruction address should be addr_at(6 * instruction_size). // However, when the instruction at 5 * instruction_size isn't addi, // the next instruction address should be addr_at(5 * instruction_size) - if (is_movptr1_at(instruction_address())) { - if (is_addi_at(addr_at(movptr1_instruction_size - NativeInstruction::instruction_size))) { + if (MacroAssembler::is_movptr1_at(instruction_address())) { + if (MacroAssembler::is_addi_at(addr_at(movptr1_instruction_size - NativeInstruction::instruction_size))) { // Assume: lui, addi, slli, addi, slli, addi return addr_at(movptr1_instruction_size); } else { // Assume: lui, addi, slli, addi, slli return addr_at(movptr1_instruction_size - NativeInstruction::instruction_size); } - } else if (is_movptr2_at(instruction_address())) { - if (is_addi_at(addr_at(movptr2_instruction_size - NativeInstruction::instruction_size))) { + } else if (MacroAssembler::is_movptr2_at(instruction_address())) { + if (MacroAssembler::is_addi_at(addr_at(movptr2_instruction_size - NativeInstruction::instruction_size))) { // Assume: lui, lui, slli, add, addi return addr_at(movptr2_instruction_size); } else { // Assume: lui, lui, slli, add return addr_at(movptr2_instruction_size - NativeInstruction::instruction_size); } - } else if (is_load_pc_relative_at(instruction_address())) { + } else if (MacroAssembler::is_load_pc_relative_at(instruction_address())) { // Assume: auipc, ld return addr_at(load_pc_relative_instruction_size); } @@ -548,8 +371,8 @@ class NativeCallTrampolineStub : public NativeInstruction { enum RISCV_specific_constants { // Refer to function emit_trampoline_stub. - instruction_size = 3 * NativeInstruction::instruction_size + wordSize, // auipc + ld + jr + target address - data_offset = 3 * NativeInstruction::instruction_size, // auipc + ld + jr + instruction_size = MacroAssembler::trampoline_stub_instruction_size, // auipc + ld + jr + target address + data_offset = MacroAssembler::trampoline_stub_data_offset, // auipc + ld + jr }; address destination(nmethod *nm = nullptr) const; @@ -557,49 +380,12 @@ class NativeCallTrampolineStub : public NativeInstruction { ptrdiff_t destination_offset() const; }; -inline bool is_NativeCallTrampolineStub_at(address addr) { - // Ensure that the stub is exactly - // ld t0, L--->auipc + ld - // jr t0 - // L: - - // judge inst + register + imm - // 1). check the instructions: auipc + ld + jalr - // 2). check if auipc[11:7] == t0 and ld[11:7] == t0 and ld[19:15] == t0 && jr[19:15] == t0 - // 3). check if the offset in ld[31:20] equals the data_offset - assert_cond(addr != nullptr); - const int instr_size = NativeInstruction::instruction_size; - if (NativeInstruction::is_auipc_at(addr) && - NativeInstruction::is_ld_at(addr + instr_size) && - NativeInstruction::is_jalr_at(addr + 2 * instr_size) && - (NativeInstruction::extract_rd(addr) == x5) && - (NativeInstruction::extract_rd(addr + instr_size) == x5) && - (NativeInstruction::extract_rs1(addr + instr_size) == x5) && - (NativeInstruction::extract_rs1(addr + 2 * instr_size) == x5) && - (Assembler::extract(Assembler::ld_instr(addr + 4), 31, 20) == NativeCallTrampolineStub::data_offset)) { - return true; - } - return false; -} - inline NativeCallTrampolineStub* nativeCallTrampolineStub_at(address addr) { assert_cond(addr != nullptr); - assert(is_NativeCallTrampolineStub_at(addr), "no call trampoline found"); + assert(MacroAssembler::is_trampoline_stub_at(addr), "no call trampoline found"); return (NativeCallTrampolineStub*)addr; } -class NativeMembar : public NativeInstruction { -public: - uint32_t get_kind(); - void set_kind(uint32_t order_kind); -}; - -inline NativeMembar *NativeMembar_at(address addr) { - assert_cond(addr != nullptr); - assert(nativeInstruction_at(addr)->is_membar(), "no membar found"); - return (NativeMembar*)addr; -} - // A NativePostCallNop takes the form of three instructions: // nop; lui zr, hi20; addiw zr, lo12 // @@ -613,7 +399,7 @@ class NativePostCallNop: public NativeInstruction { // These instructions only ever appear together in a post-call // NOP, so it's unnecessary to check that the third instruction is // an addiw as well. - return is_nop() && is_lui_to_zr_at(addr_at(4)); + return is_nop() && MacroAssembler::is_lui_to_zr_at(addr_at(4)); } bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const; bool patch(int32_t oopmap_slot, int32_t cb_offset); diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp index b3cdb93a979d8..43a9b8f89aeaa 100644 --- a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp +++ b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp @@ -42,7 +42,7 @@ void Relocation::pd_set_data_value(address x, bool verify_only) { case relocInfo::oop_type: { oop_Relocation *reloc = (oop_Relocation *)this; // in movoop when BarrierSet::barrier_set()->barrier_set_nmethod() isn't null - if (NativeInstruction::is_load_pc_relative_at(addr())) { + if (MacroAssembler::is_load_pc_relative_at(addr())) { address constptr = (address)code()->oop_addr_at(reloc->oop_index()); bytes = MacroAssembler::pd_patch_instruction_size(addr(), constptr); assert((address)Bytes::get_native_u8(constptr) == x, "error in oop relocation"); @@ -60,7 +60,7 @@ void Relocation::pd_set_data_value(address x, bool verify_only) { address Relocation::pd_call_destination(address orig_addr) { assert(is_call(), "should be an address instruction here"); - if (NativeCall::is_call_at(addr())) { + if (MacroAssembler::is_call_at(addr())) { address trampoline = nativeCall_at(addr())->get_trampoline(); if (trampoline != nullptr) { return nativeCallTrampolineStub_at(trampoline)->destination(); @@ -81,7 +81,7 @@ address Relocation::pd_call_destination(address orig_addr) { void Relocation::pd_set_call_destination(address x) { assert(is_call(), "should be an address instruction here"); - if (NativeCall::is_call_at(addr())) { + if (MacroAssembler::is_call_at(addr())) { address trampoline = nativeCall_at(addr())->get_trampoline(); if (trampoline != nullptr) { nativeCall_at(addr())->set_destination_mt_safe(x, /* assert_lock */false); @@ -94,7 +94,7 @@ void Relocation::pd_set_call_destination(address x) { } address* Relocation::pd_address_in_code() { - assert(NativeCall::is_load_pc_relative_at(addr()), "Not the expected instruction sequence!"); + assert(MacroAssembler::is_load_pc_relative_at(addr()), "Not the expected instruction sequence!"); return (address*)(MacroAssembler::target_addr_for_insn(addr())); }