diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index a15405f5323..b3168310e56 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -135,7 +135,7 @@ static jlong as_long(LIR_Opr data) { Address LIR_Assembler::as_Address(LIR_Address* addr, Register tmp) { if (addr->base()->is_illegal()) { assert(addr->index()->is_illegal(), "must be illegal too"); - __ movptr(tmp, addr->disp()); + __ movptr(tmp, (address)addr->disp()); return Address(tmp, 0); } diff --git a/src/hotspot/cpu/riscv/jvmciCodeInstaller_riscv.cpp b/src/hotspot/cpu/riscv/jvmciCodeInstaller_riscv.cpp index a7160bd7241..35bfbb1df8e 100644 --- a/src/hotspot/cpu/riscv/jvmciCodeInstaller_riscv.cpp +++ b/src/hotspot/cpu/riscv/jvmciCodeInstaller_riscv.cpp @@ -42,8 +42,10 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, JVMC return pc_offset + NativeCall::instruction_size; } else if (inst->is_jump()) { return pc_offset + NativeJump::instruction_size; - } else if (inst->is_movptr()) { - return pc_offset + NativeMovConstReg::movptr_instruction_size; + } else if (inst->is_movptr1()) { + return pc_offset + NativeMovConstReg::movptr1_instruction_size; + } else if (inst->is_movptr2()) { + return pc_offset + NativeMovConstReg::movptr2_instruction_size; } else { JVMCI_ERROR_0("unsupported type of instruction for call site"); } diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 836faccc0f6..78ea3af28be 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -640,7 +640,7 @@ void MacroAssembler::emit_static_call_stub() { // Jump to the entry point of the c2i stub. int32_t offset = 0; - movptr(t0, 0, offset); + movptr(t0, 0, offset, t1); // lui + lui + slli + add jr(t0, offset); } @@ -1425,15 +1425,34 @@ static int patch_offset_in_pc_relative(address branch, int64_t offset) { return PC_RELATIVE_INSTRUCTION_NUM * NativeInstruction::instruction_size; } -static int patch_addr_in_movptr(address branch, address target) { - const int MOVPTR_INSTRUCTIONS_NUM = 6; // lui + addi + slli + addi + slli + addi/jalr/load +static int patch_addr_in_movptr1(address branch, address target) { int32_t lower = ((intptr_t)target << 35) >> 35; int64_t upper = ((intptr_t)target - lower) >> 29; Assembler::patch(branch + 0, 31, 12, upper & 0xfffff); // Lui. target[48:29] + target[28] ==> branch[31:12] 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 MOVPTR_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; + return NativeMovConstReg::movptr1_instruction_size; +} + +static int patch_addr_in_movptr2(address instruction_address, address target) { + uintptr_t addr = (uintptr_t)target; + + assert(addr < (1ull << 48), "48-bit overflow in address constant"); + unsigned int upper18 = (addr >> 30ull); + int lower30 = (addr & 0x3fffffffu); + 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 + // Slli + // Add + Assembler::patch(instruction_address + (NativeInstruction::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; } static int patch_imm_in_li64(address branch, address target) { @@ -1507,7 +1526,7 @@ static long get_offset_of_pc_relative(address insn_addr) { return offset; } -static address get_target_of_movptr(address insn_addr) { +static address get_target_of_movptr1(address insn_addr) { assert_cond(insn_addr != nullptr); intptr_t target_address = (((int64_t)Assembler::sextract(Assembler::ld_instr(insn_addr), 31, 12)) & 0xfffff) << 29; // Lui. target_address += ((int64_t)Assembler::sextract(Assembler::ld_instr(insn_addr + 4), 31, 20)) << 17; // Addi. @@ -1516,6 +1535,17 @@ static address get_target_of_movptr(address insn_addr) { return (address) target_address; } +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 + // 2 // Slli + // 3 // Add + int32_t low12 = ((Assembler::sextract(Assembler::ld_instr(insn_addr + NativeInstruction::instruction_size * 4), 31, 20))); // Addi/Jalr/Load. + address ret = (address)(((intptr_t)upper18<<30ll) + ((intptr_t)mid18<<12ll) + low12); + return ret; +} + static address get_target_of_li64(address insn_addr) { assert_cond(insn_addr != nullptr); intptr_t target_address = (((int64_t)Assembler::sextract(Assembler::ld_instr(insn_addr), 31, 12)) & 0xfffff) << 44; // Lui. @@ -1535,30 +1565,32 @@ address MacroAssembler::get_target_of_li32(address insn_addr) { // Patch any kind of instruction; there may be several instructions. // Return the total length (in bytes) of the instructions. -int MacroAssembler::pd_patch_instruction_size(address branch, address target) { - assert_cond(branch != nullptr); - int64_t offset = target - branch; - if (NativeInstruction::is_jal_at(branch)) { // jal - return patch_offset_in_jal(branch, offset); - } else if (NativeInstruction::is_branch_at(branch)) { // beq/bge/bgeu/blt/bltu/bne - return patch_offset_in_conditional_branch(branch, offset); - } else if (NativeInstruction::is_pc_relative_at(branch)) { // auipc, addi/jalr/load - return patch_offset_in_pc_relative(branch, offset); - } else if (NativeInstruction::is_movptr_at(branch)) { // movptr - return patch_addr_in_movptr(branch, target); - } else if (NativeInstruction::is_li64_at(branch)) { // li64 - return patch_imm_in_li64(branch, target); - } else if (NativeInstruction::is_li32_at(branch)) { // li32 +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 + return patch_offset_in_jal(instruction_address, offset); + } else if (NativeInstruction::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 + return patch_offset_in_pc_relative(instruction_address, offset); + } else if (NativeInstruction::is_movptr1_at(instruction_address)) { // movptr1 + return patch_addr_in_movptr1(instruction_address, target); + } else if (NativeInstruction::is_movptr2_at(instruction_address)) { // movptr2 + return patch_addr_in_movptr2(instruction_address, target); + } else if (NativeInstruction::is_li64_at(instruction_address)) { // li64 + return patch_imm_in_li64(instruction_address, target); + } else if (NativeInstruction::is_li32_at(instruction_address)) { // li32 int64_t imm = (intptr_t)target; - return patch_imm_in_li32(branch, (int32_t)imm); - } else if (NativeInstruction::is_li16u_at(branch)) { + return patch_imm_in_li32(instruction_address, (int32_t)imm); + } else if (NativeInstruction::is_li16u_at(instruction_address)) { int64_t imm = (intptr_t)target; - return patch_imm_in_li16u(branch, (uint16_t)imm); + return patch_imm_in_li16u(instruction_address, (uint16_t)imm); } else { #ifdef ASSERT tty->print_cr("pd_patch_instruction_size: instruction 0x%x at " INTPTR_FORMAT " could not be patched!\n", - Assembler::ld_instr(branch), p2i(branch)); - Disassembler::decode(branch - 16, branch + 16); + Assembler::ld_instr(instruction_address), p2i(instruction_address)); + Disassembler::decode(instruction_address - 16, instruction_address + 16); #endif ShouldNotReachHere(); return -1; @@ -1574,8 +1606,10 @@ address MacroAssembler::target_addr_for_insn(address insn_addr) { offset = get_offset_of_conditional_branch(insn_addr); } else if (NativeInstruction::is_pc_relative_at(insn_addr)) { // auipc, addi/jalr/load offset = get_offset_of_pc_relative(insn_addr); - } else if (NativeInstruction::is_movptr_at(insn_addr)) { // movptr - return get_target_of_movptr(insn_addr); + } else if (NativeInstruction::is_movptr1_at(insn_addr)) { // movptr1 + return get_target_of_movptr1(insn_addr); + } else if (NativeInstruction::is_movptr2_at(insn_addr)) { // movptr2 + return get_target_of_movptr2(insn_addr); } else if (NativeInstruction::is_li64_at(insn_addr)) { // li64 return get_target_of_li64(insn_addr); } else if (NativeInstruction::is_li32_at(insn_addr)) { // li32 @@ -1594,9 +1628,12 @@ int MacroAssembler::patch_oop(address insn_addr, address o) { // 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_movptr_at(insn_addr)) { + } else if (NativeInstruction::is_movptr1_at(insn_addr)) { // Move wide OOP - return patch_addr_in_movptr(insn_addr, o); + return patch_addr_in_movptr1(insn_addr, o); + } else if (NativeInstruction::is_movptr2_at(insn_addr)) { + // Move wide OOP + return patch_addr_in_movptr2(insn_addr, o); } ShouldNotReachHere(); return -1; @@ -1617,16 +1654,31 @@ void MacroAssembler::reinit_heapbase() { } } -void MacroAssembler::movptr(Register Rd, address addr, int32_t &offset) { - int64_t imm64 = (int64_t)addr; +void MacroAssembler::movptr(Register Rd, address addr, Register temp) { + int offset = 0; + movptr(Rd, addr, offset, temp); + addi(Rd, Rd, offset); +} + +void MacroAssembler::movptr(Register Rd, address addr, int32_t &offset, Register temp) { + uint64_t uimm64 = (uint64_t)addr; #ifndef PRODUCT { char buffer[64]; - snprintf(buffer, sizeof(buffer), "0x%" PRIx64, imm64); + snprintf(buffer, sizeof(buffer), "0x%" PRIx64, uimm64); block_comment(buffer); } #endif - assert((uintptr_t)imm64 < (1ull << 48), "48-bit overflow in address constant"); + assert(uimm64 < (1ull << 48), "48-bit overflow in address constant"); + + if (temp == noreg) { + movptr1(Rd, uimm64, offset); + } else { + movptr2(Rd, uimm64, offset, temp); + } +} + +void MacroAssembler::movptr1(Register Rd, uint64_t imm64, int32_t &offset) { // Load upper 31 bits int64_t imm = imm64 >> 17; int64_t upper = imm, lower = imm; @@ -1645,6 +1697,23 @@ void MacroAssembler::movptr(Register Rd, address addr, int32_t &offset) { offset = imm64 & 0x3f; } +void MacroAssembler::movptr2(Register Rd, uint64_t addr, int32_t &offset, Register tmp) { + assert_different_registers(Rd, tmp, noreg); + + uint32_t upper18 = (addr >> 30ull); + int32_t lower30 = (addr & 0x3fffffffu); + int32_t low12 = (lower30 << 20) >> 20; + int32_t mid18 = ((lower30 - low12) >> 12); + + lui(tmp, upper18 << 12); + lui(Rd, mid18 << 12); + + slli(tmp, tmp, 18); + add(Rd, Rd, tmp); + + offset = low12; +} + void MacroAssembler::add(Register Rd, Register Rn, int64_t increment, Register temp) { if (is_simm12(increment)) { addi(Rd, Rn, increment); @@ -2120,6 +2189,7 @@ void MacroAssembler::movoop(Register dst, jobject obj) { // Move a metadata address into a register. void MacroAssembler::mov_metadata(Register dst, Metadata* obj) { + assert((uintptr_t)obj < (1ull << 48), "48-bit overflow in metadata"); int oop_index; if (obj == nullptr) { oop_index = oop_recorder()->allocate_metadata_index(obj); @@ -3554,7 +3624,7 @@ address MacroAssembler::trampoline_call(Address entry) { address MacroAssembler::ic_call(address entry, jint method_index) { RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index); IncompressibleRegion ir(this); // relocations - movptr(t1, (address)Universe::non_oop_word()); + movptr(t1, (address)Universe::non_oop_word(), t0); assert_cond(entry != nullptr); return trampoline_call(Address(entry, rh)); } @@ -3661,8 +3731,8 @@ int MacroAssembler::max_trampoline_stub_size() { } int MacroAssembler::static_call_stub_size() { - // (lui, addi, slli, addi, slli, addi) + (lui, addi, slli, addi, slli) + jalr - return 12 * NativeInstruction::instruction_size; + // (lui, addi, slli, addi, slli, addi) + (lui + lui + slli + add) + jalr + return 11 * NativeInstruction::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 4e52cdaee38..e5800b0aa91 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -804,17 +804,16 @@ public: } } - void movptr(Register Rd, address addr, int32_t &offset); - - void movptr(Register Rd, address addr) { - int offset = 0; - movptr(Rd, addr, offset); - addi(Rd, Rd, offset); - } - - inline void movptr(Register Rd, uintptr_t imm64) { - movptr(Rd, (address)imm64); - } + // Generates a load of a 48-bit constant which can be + // patched to any 48-bit constant, i.e. address. + // If common case supply additional temp register + // to shorten the instruction sequence. + void movptr(Register Rd, address addr, Register tmp = noreg); + void movptr(Register Rd, address addr, int32_t &offset, Register tmp = noreg); + private: + void movptr1(Register Rd, uintptr_t addr, int32_t &offset); + void movptr2(Register Rd, uintptr_t addr, int32_t &offset, Register tmp); + public: // arith void add (Register Rd, Register Rn, int64_t increment, Register temp = t0); diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index 399de3a2805..dd54329e521 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -84,7 +84,7 @@ bool NativeInstruction::is_load_pc_relative_at(address instr) { check_load_pc_relative_data_dependency(instr); } -bool NativeInstruction::is_movptr_at(address 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 @@ -93,7 +93,18 @@ bool NativeInstruction::is_movptr_at(address instr) { (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_movptr_data_dependency(instr); + 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) { @@ -201,10 +212,11 @@ void NativeCall::insert(address code_pos, address entry) { Unimplemented(); } //------------------------------------------------------------------- void NativeMovConstReg::verify() { - if (!(nativeInstruction_at(instruction_address())->is_movptr() || - is_auipc_at(instruction_address()))) { - fatal("should be MOVPTR or AUIPC"); + NativeInstruction* ni = nativeInstruction_at(instruction_address()); + if (ni->is_movptr() || ni->is_auipc()) { + return; } + fatal("should be MOVPTR or AUIPC"); } intptr_t NativeMovConstReg::data() const { @@ -223,7 +235,7 @@ void NativeMovConstReg::set_data(intptr_t x) { } else { // Store x into the instruction stream. MacroAssembler::pd_patch_instruction_size(instruction_address(), (address)x); - ICache::invalidate_range(instruction_address(), movptr_instruction_size); + ICache::invalidate_range(instruction_address(), movptr1_instruction_size /* > movptr2_instruction_size */ ); } // Find and replace the oop/metadata corresponding to this @@ -393,13 +405,15 @@ void NativeJump::patch_verified_entry(address entry, address verified_entry, add ICache::invalidate_range(verified_entry, instruction_size); } +//------------------------------------------------------------------- + void NativeGeneralJump::insert_unconditional(address code_pos, address entry) { CodeBuffer cb(code_pos, instruction_size); MacroAssembler a(&cb); Assembler::IncompressibleRegion ir(&a); // Fixed length: see NativeGeneralJump::get_instruction_size() int32_t offset = 0; - a.movptr(t0, entry, offset); // lui, addi, slli, addi, slli + a.movptr(t0, entry, offset, t1); // lui, lui, slli, add a.jr(t0, offset); // jalr ICache::invalidate_range(code_pos, instruction_size); @@ -410,6 +424,8 @@ void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer) ShouldNotCallThis(); } +//------------------------------------------------------------------- + address NativeCallTrampolineStub::destination(nmethod *nm) const { return ptr_at(data_offset); } diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index 48bbb2b3b18..dcdf525aafb 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -64,7 +64,11 @@ class NativeInstruction { } bool is_jal() const { return is_jal_at(addr_at(0)); } - bool is_movptr() const { return is_movptr_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)); } @@ -76,9 +80,10 @@ class NativeInstruction { 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_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; } @@ -109,7 +114,7 @@ class NativeInstruction { // addi // slli // addi/jalr/load - static bool check_movptr_data_dependency(address instr) { + static bool check_movptr1_data_dependency(address instr) { address lui = instr; address addi1 = lui + instruction_size; address slli1 = addi1 + instruction_size; @@ -127,6 +132,26 @@ class NativeInstruction { 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 @@ -204,7 +229,8 @@ class NativeInstruction { extract_rs1(load) == extract_rd(load); } - static bool is_movptr_at(address instr); + 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); @@ -351,26 +377,33 @@ inline NativeCall* nativeCall_before(address return_address) { class NativeMovConstReg: public NativeInstruction { public: enum RISCV_specific_constants { - movptr_instruction_size = 6 * NativeInstruction::instruction_size, // lui, addi, slli, addi, slli, addi. See movptr(). - load_pc_relative_instruction_size = 2 * NativeInstruction::instruction_size, // auipc, ld - instruction_offset = 0, - displacement_offset = 0 + 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 }; - address instruction_address() const { return addr_at(instruction_offset); } + address instruction_address() const { return addr_at(0); } address next_instruction_address() const { // if the instruction at 5 * instruction_size is addi, // it means a lui + addi + slli + addi + slli + addi instruction sequence, // 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 (nativeInstruction_at(instruction_address())->is_movptr()) { - if (is_addi_at(addr_at(movptr_instruction_size - NativeInstruction::instruction_size))) { + if (is_movptr1_at(instruction_address())) { + if (is_addi_at(addr_at(movptr1_instruction_size - NativeInstruction::instruction_size))) { // Assume: lui, addi, slli, addi, slli, addi - return addr_at(movptr_instruction_size); + return addr_at(movptr1_instruction_size); } else { // Assume: lui, addi, slli, addi, slli - return addr_at(movptr_instruction_size - NativeInstruction::instruction_size); + 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))) { + // 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())) { // Assume: auipc, ld @@ -383,12 +416,6 @@ class NativeMovConstReg: public NativeInstruction { intptr_t data() const; void set_data(intptr_t x); - void flush() { - if (!maybe_cpool_ref(instruction_address())) { - ICache::invalidate_range(instruction_address(), movptr_instruction_size); - } - } - void verify(); void print(); @@ -399,14 +426,14 @@ class NativeMovConstReg: public NativeInstruction { inline NativeMovConstReg* nativeMovConstReg_at(address addr) { assert_cond(addr != nullptr); - NativeMovConstReg* test = (NativeMovConstReg*)(addr - NativeMovConstReg::instruction_offset); + NativeMovConstReg* test = (NativeMovConstReg*)(addr); DEBUG_ONLY(test->verify()); return test; } inline NativeMovConstReg* nativeMovConstReg_before(address addr) { assert_cond(addr != nullptr); - NativeMovConstReg* test = (NativeMovConstReg*)(addr - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset); + NativeMovConstReg* test = (NativeMovConstReg*)(addr - NativeMovConstReg::instruction_size); DEBUG_ONLY(test->verify()); return test; } @@ -484,10 +511,7 @@ inline NativeJump* nativeJump_at(address addr) { class NativeGeneralJump: public NativeJump { public: enum RISCV_specific_constants { - instruction_size = 6 * NativeInstruction::instruction_size, // lui, addi, slli, addi, slli, jalr - instruction_offset = 0, - data_offset = 0, - next_instruction_offset = 6 * NativeInstruction::instruction_size // lui, addi, slli, addi, slli, jalr + instruction_size = 5 * NativeInstruction::instruction_size, // lui, lui, slli, add, jalr }; address jump_destination() const; diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index a0d1b1921cd..8b28ec88efd 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1244,7 +1244,7 @@ int MachCallStaticJavaNode::ret_addr_offset() int MachCallDynamicJavaNode::ret_addr_offset() { - return 7 * NativeInstruction::instruction_size; // movptr, jal + return NativeMovConstReg::movptr2_instruction_size + NativeInstruction::instruction_size; // movptr2, jal } int MachCallRuntimeNode::ret_addr_offset() { @@ -1285,12 +1285,11 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const // ensure that it does not span a cache line so that it can be patched. int CallDynamicJavaDirectNode::compute_padding(int current_offset) const { - // skip the movptr in MacroAssembler::ic_call(): - // lui + addi + slli + addi + slli + addi - // Though movptr() has already 4-byte aligned with or without RVC, + // skip the movptr2 in MacroAssembler::ic_call(): + // lui, lui, slli, add, addi + // Though movptr2() has already 4-byte aligned with or without RVC, // We need to prevent from further changes by explicitly calculating the size. - const int movptr_size = 6 * NativeInstruction::instruction_size; - current_offset += movptr_size; + current_offset += NativeMovConstReg::movptr2_instruction_size; // to make sure the address of jal 4-byte aligned. return align_up(current_offset, alignment_required()) - current_offset; } @@ -10014,7 +10013,7 @@ instruct CallDynamicJavaDirect(method meth, rFlagsReg cr) effect(USE meth, KILL cr); - ins_cost(BRANCH_COST + ALU_COST * 6); + ins_cost(BRANCH_COST + ALU_COST * 5); format %{ "CALL,dynamic $meth\t#@CallDynamicJavaDirect" %} diff --git a/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp b/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp index 8a6557dde93..383f332f8fd 100644 --- a/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp +++ b/src/hotspot/cpu/riscv/upcallLinker_riscv.cpp @@ -223,7 +223,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, __ block_comment("{ on_entry"); __ la(c_rarg0, Address(sp, frame_data_offset)); - __ movptr(c_rarg1, (intptr_t) receiver); + __ movptr(c_rarg1, (address) receiver); __ rt_call(CAST_FROM_FN_PTR(address, UpcallLinker::on_entry)); __ mv(xthread, x10); __ reinit_heapbase();