From 3d75e88eb25f56ed2214496826004578c2c75012 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Fri, 14 Oct 2022 07:53:56 +0000 Subject: [PATCH] 8295270: RISC-V: Clean up and refactoring for assembler functions Reviewed-by: fjiang, yadongwang, shade --- src/hotspot/cpu/riscv/assembler_riscv.cpp | 261 ----------- src/hotspot/cpu/riscv/assembler_riscv.hpp | 424 ++---------------- .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 22 +- .../cpu/riscv/c1_MacroAssembler_riscv.cpp | 19 +- .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 28 +- src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 4 +- .../cpu/riscv/macroAssembler_riscv.cpp | 347 +++++++++++++- .../cpu/riscv/macroAssembler_riscv.hpp | 343 +++++++++++++- src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 4 +- src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 2 +- .../templateInterpreterGenerator_riscv.cpp | 2 +- src/hotspot/cpu/riscv/templateTable_riscv.cpp | 8 +- 12 files changed, 751 insertions(+), 713 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.cpp b/src/hotspot/cpu/riscv/assembler_riscv.cpp index 2ebd9dd7618..2fb75c802cf 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.cpp @@ -40,267 +40,6 @@ int AbstractAssembler::code_fill_byte() { return 0; } -void Assembler::add(Register Rd, Register Rn, int64_t increment, Register temp) { - if (is_imm_in_range(increment, 12, 0)) { - addi(Rd, Rn, increment); - } else { - assert_different_registers(Rn, temp); - li(temp, increment); - add(Rd, Rn, temp); - } -} - -void Assembler::addw(Register Rd, Register Rn, int32_t increment, Register temp) { - if (is_imm_in_range(increment, 12, 0)) { - addiw(Rd, Rn, increment); - } else { - assert_different_registers(Rn, temp); - li(temp, increment); - addw(Rd, Rn, temp); - } -} - -void Assembler::sub(Register Rd, Register Rn, int64_t decrement, Register temp) { - if (is_imm_in_range(-decrement, 12, 0)) { - addi(Rd, Rn, -decrement); - } else { - assert_different_registers(Rn, temp); - li(temp, decrement); - sub(Rd, Rn, temp); - } -} - -void Assembler::subw(Register Rd, Register Rn, int32_t decrement, Register temp) { - if (is_imm_in_range(-decrement, 12, 0)) { - addiw(Rd, Rn, -decrement); - } else { - assert_different_registers(Rn, temp); - li(temp, decrement); - subw(Rd, Rn, temp); - } -} - -void Assembler::zext_w(Register Rd, Register Rs) { - add_uw(Rd, Rs, zr); -} - -void Assembler::_li(Register Rd, int64_t imm) { - // int64_t is in range 0x8000 0000 0000 0000 ~ 0x7fff ffff ffff ffff - int shift = 12; - int64_t upper = imm, lower = imm; - // Split imm to a lower 12-bit sign-extended part and the remainder, - // because addi will sign-extend the lower imm. - lower = ((int32_t)imm << 20) >> 20; - upper -= lower; - - // Test whether imm is a 32-bit integer. - if (!(((imm) & ~(int64_t)0x7fffffff) == 0 || - (((imm) & ~(int64_t)0x7fffffff) == ~(int64_t)0x7fffffff))) { - while (((upper >> shift) & 1) == 0) { shift++; } - upper >>= shift; - li(Rd, upper); - slli(Rd, Rd, shift); - if (lower != 0) { - addi(Rd, Rd, lower); - } - } else { - // 32-bit integer - Register hi_Rd = zr; - if (upper != 0) { - lui(Rd, (int32_t)upper); - hi_Rd = Rd; - } - if (lower != 0 || hi_Rd == zr) { - addiw(Rd, hi_Rd, lower); - } - } -} - -void Assembler::li64(Register Rd, int64_t imm) { - // Load upper 32 bits. upper = imm[63:32], but if imm[31] == 1 or - // (imm[31:20] == 0x7ff && imm[19] == 1), upper = imm[63:32] + 1. - int64_t lower = imm & 0xffffffff; - lower -= ((lower << 44) >> 44); - int64_t tmp_imm = ((uint64_t)(imm & 0xffffffff00000000)) + (uint64_t)lower; - int32_t upper = (tmp_imm - (int32_t)lower) >> 32; - - // Load upper 32 bits - int64_t up = upper, lo = upper; - lo = (lo << 52) >> 52; - up -= lo; - up = (int32_t)up; - lui(Rd, up); - addi(Rd, Rd, lo); - - // Load the rest 32 bits. - slli(Rd, Rd, 12); - addi(Rd, Rd, (int32_t)lower >> 20); - slli(Rd, Rd, 12); - lower = ((int32_t)imm << 12) >> 20; - addi(Rd, Rd, lower); - slli(Rd, Rd, 8); - lower = imm & 0xff; - addi(Rd, Rd, lower); -} - -void Assembler::li32(Register Rd, int32_t imm) { - // int32_t is in range 0x8000 0000 ~ 0x7fff ffff, and imm[31] is the sign bit - int64_t upper = imm, lower = imm; - lower = (imm << 20) >> 20; - upper -= lower; - upper = (int32_t)upper; - // lui Rd, imm[31:12] + imm[11] - lui(Rd, upper); - // use addiw to distinguish li32 to li64 - addiw(Rd, Rd, lower); -} - -#define INSN(NAME, REGISTER) \ - void Assembler::NAME(const address &dest, Register temp) { \ - assert_cond(dest != NULL); \ - int64_t distance = dest - pc(); \ - if (is_imm_in_range(distance, 20, 1)) { \ - jal(REGISTER, distance); \ - } else { \ - assert(temp != noreg, "temp must not be empty register!"); \ - int32_t offset = 0; \ - movptr(temp, dest, offset); \ - jalr(REGISTER, temp, offset); \ - } \ - } \ - void Assembler::NAME(Label &l, Register temp) { \ - jal(REGISTER, l, temp); \ - } \ - - INSN(j, x0); - INSN(jal, x1); - -#undef INSN - -#define INSN(NAME, REGISTER) \ - void Assembler::NAME(Register Rs) { \ - jalr(REGISTER, Rs, 0); \ - } - - INSN(jr, x0); - INSN(jalr, x1); - -#undef INSN - -#define INSN(NAME, REGISTER) \ - void Assembler::NAME(const Address &adr, Register temp) { \ - switch (adr.getMode()) { \ - case Address::literal: { \ - relocate(adr.rspec()); \ - NAME(adr.target(), temp); \ - break; \ - } \ - case Address::base_plus_offset: { \ - int32_t offset = 0; \ - baseOffset(temp, adr, offset); \ - jalr(REGISTER, temp, offset); \ - break; \ - } \ - default: \ - ShouldNotReachHere(); \ - } \ - } - - INSN(j, x0); - INSN(jal, x1); - -#undef INSN - -void Assembler::wrap_label(Register r1, Register r2, Label &L, compare_and_branch_insn insn, - compare_and_branch_label_insn neg_insn, bool is_far) { - if (is_far) { - Label done; - (this->*neg_insn)(r1, r2, done, /* is_far */ false); - j(L); - bind(done); - } else { - if (L.is_bound()) { - (this->*insn)(r1, r2, target(L)); - } else { - L.add_patch_at(code(), locator()); - (this->*insn)(r1, r2, pc()); - } - } -} - -void Assembler::wrap_label(Register Rt, Label &L, Register tmp, load_insn_by_temp insn) { - if (L.is_bound()) { - (this->*insn)(Rt, target(L), tmp); - } else { - L.add_patch_at(code(), locator()); - (this->*insn)(Rt, pc(), tmp); - } -} - -void Assembler::wrap_label(Register Rt, Label &L, jal_jalr_insn insn) { - if (L.is_bound()) { - (this->*insn)(Rt, target(L)); - } else { - L.add_patch_at(code(), locator()); - (this->*insn)(Rt, pc()); - } -} - -void Assembler::movptr(Register Rd, address addr, int32_t &offset) { - int64_t imm64 = (int64_t)addr; -#ifndef PRODUCT - { - char buffer[64]; - snprintf(buffer, sizeof(buffer), "0x%" PRIx64, imm64); - block_comment(buffer); - } -#endif - assert(is_unsigned_imm_in_range(imm64, 47, 0) || (imm64 == (int64_t)-1), - "bit 47 overflows in address constant"); - // Load upper 31 bits - int64_t imm = imm64 >> 17; - int64_t upper = imm, lower = imm; - lower = (lower << 52) >> 52; - upper -= lower; - upper = (int32_t)upper; - lui(Rd, upper); - addi(Rd, Rd, lower); - - // Load the rest 17 bits. - slli(Rd, Rd, 11); - addi(Rd, Rd, (imm64 >> 6) & 0x7ff); - slli(Rd, Rd, 6); - - // This offset will be used by following jalr/ld. - offset = imm64 & 0x3f; -} - -void Assembler::movptr(Register Rd, uintptr_t imm64) { - movptr(Rd, (address)imm64); -} - -void Assembler::movptr(Register Rd, address addr) { - int offset = 0; - movptr(Rd, addr, offset); - addi(Rd, Rd, offset); -} - -#define INSN(NAME, NEG_INSN) \ - void Assembler::NAME(Register Rs, Register Rt, const address &dest) { \ - NEG_INSN(Rt, Rs, dest); \ - } \ - void Assembler::NAME(Register Rs, Register Rt, Label &l, bool is_far) { \ - NEG_INSN(Rt, Rs, l, is_far); \ - } - - INSN(bgt, blt); - INSN(ble, bge); - INSN(bgtu, bltu); - INSN(bleu, bgeu); -#undef INSN - -#undef __ - Address::Address(address target, relocInfo::relocType rtype) : _base(noreg), _offset(0), _mode(literal) { _target = target; switch (rtype) { diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 53853bcce35..104277a183e 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -171,6 +171,7 @@ class Address { public: Address() : _base(noreg), _index(noreg), _offset(0), _mode(no_mode), _target(NULL) { } + Address(Register r) : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(NULL) { } @@ -180,6 +181,7 @@ class Address { Address(Register r, ByteSize disp) : Address(r, in_bytes(disp)) {} + Address(address target, RelocationHolder const& rspec) : _base(noreg), _index(noreg), @@ -187,6 +189,7 @@ class Address { _mode(literal), _rspec(rspec), _target(target) { } + Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type); const Register base() const { @@ -291,48 +294,6 @@ public: rdy = 0b111, // in instruction's rm field, selects dynamic rounding mode.In Rounding Mode register, Invalid. }; - void baseOffset32(Register Rd, const Address &adr, int32_t &offset) { - assert(Rd != noreg, "Rd must not be empty register!"); - guarantee(Rd != adr.base(), "should use different registers!"); - if (is_offset_in_range(adr.offset(), 32)) { - int32_t imm = adr.offset(); - int32_t upper = imm, lower = imm; - lower = (imm << 20) >> 20; - upper -= lower; - lui(Rd, upper); - offset = lower; - } else { - offset = ((int32_t)adr.offset() << 20) >> 20; - li(Rd, adr.offset() - offset); - } - add(Rd, Rd, adr.base()); - } - - void baseOffset(Register Rd, const Address &adr, int32_t &offset) { - if (is_offset_in_range(adr.offset(), 12)) { - assert(Rd != noreg, "Rd must not be empty register!"); - addi(Rd, adr.base(), adr.offset()); - offset = 0; - } else { - baseOffset32(Rd, adr, offset); - } - } - - void _li(Register Rd, int64_t imm); // optimized load immediate - void li32(Register Rd, int32_t imm); - void li64(Register Rd, int64_t imm); - void movptr(Register Rd, address addr); - void movptr(Register Rd, address addr, int32_t &offset); - void movptr(Register Rd, uintptr_t imm64); - void j(const address &dest, Register temp = t0); - void j(const Address &adr, Register temp = t0); - void j(Label &l, Register temp = t0); - void jal(Label &l, Register temp = t0); - void jal(const address &dest, Register temp = t0); - void jal(const Address &adr, Register temp = t0); - void jr(Register Rs); - void jalr(Register Rs); - static inline uint32_t extract(uint32_t val, unsigned msb, unsigned lsb) { assert_cond(msb >= lsb && msb <= 31); unsigned nbits = msb - lsb + 1; @@ -474,13 +435,7 @@ public: #undef INSN -#define INSN_ENTRY_RELOC(result_type, header) \ - result_type header { \ - guarantee(rtype == relocInfo::internal_word_type, \ - "only internal_word_type relocs make sense here"); \ - relocate(InternalAddress(dest).rspec()); - - // Load/store register (all modes) +// Load/store register (all modes) #define INSN(NAME, op, funct3) \ void NAME(Register Rd, Register Rs, const int32_t offset) { \ guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \ @@ -504,62 +459,6 @@ public: #undef INSN -#define INSN(NAME) \ - void NAME(Register Rd, address dest) { \ - assert_cond(dest != NULL); \ - int64_t distance = (dest - pc()); \ - if (is_offset_in_range(distance, 32)) { \ - auipc(Rd, (int32_t)distance + 0x800); \ - NAME(Rd, Rd, ((int32_t)distance << 20) >> 20); \ - } else { \ - int32_t offset = 0; \ - movptr(Rd, dest, offset); \ - NAME(Rd, Rd, offset); \ - } \ - } \ - INSN_ENTRY_RELOC(void, NAME(Register Rd, address dest, relocInfo::relocType rtype)) \ - NAME(Rd, dest); \ - } \ - void NAME(Register Rd, const Address &adr, Register temp = t0) { \ - switch (adr.getMode()) { \ - case Address::literal: { \ - relocate(adr.rspec()); \ - NAME(Rd, adr.target()); \ - break; \ - } \ - case Address::base_plus_offset: { \ - if (is_offset_in_range(adr.offset(), 12)) { \ - NAME(Rd, adr.base(), adr.offset()); \ - } else { \ - int32_t offset = 0; \ - if (Rd == adr.base()) { \ - baseOffset32(temp, adr, offset); \ - NAME(Rd, temp, offset); \ - } else { \ - baseOffset32(Rd, adr, offset); \ - NAME(Rd, Rd, offset); \ - } \ - } \ - break; \ - } \ - default: \ - ShouldNotReachHere(); \ - } \ - } \ - void NAME(Register Rd, Label &L) { \ - wrap_label(Rd, L, &Assembler::NAME); \ - } - - INSN(lb); - INSN(lbu); - INSN(lh); - INSN(lhu); - INSN(lw); - INSN(lwu); - INSN(ld); - -#undef INSN - #define INSN(NAME, op, funct3) \ void NAME(FloatRegister Rd, Register Rs, const int32_t offset) { \ guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \ @@ -578,48 +477,6 @@ public: #undef INSN -#define INSN(NAME) \ - void NAME(FloatRegister Rd, address dest, Register temp = t0) { \ - assert_cond(dest != NULL); \ - int64_t distance = (dest - pc()); \ - if (is_offset_in_range(distance, 32)) { \ - auipc(temp, (int32_t)distance + 0x800); \ - NAME(Rd, temp, ((int32_t)distance << 20) >> 20); \ - } else { \ - int32_t offset = 0; \ - movptr(temp, dest, offset); \ - NAME(Rd, temp, offset); \ - } \ - } \ - INSN_ENTRY_RELOC(void, NAME(FloatRegister Rd, address dest, relocInfo::relocType rtype, Register temp = t0)) \ - NAME(Rd, dest, temp); \ - } \ - void NAME(FloatRegister Rd, const Address &adr, Register temp = t0) { \ - switch (adr.getMode()) { \ - case Address::literal: { \ - relocate(adr.rspec()); \ - NAME(Rd, adr.target(), temp); \ - break; \ - } \ - case Address::base_plus_offset: { \ - if (is_offset_in_range(adr.offset(), 12)) { \ - NAME(Rd, adr.base(), adr.offset()); \ - } else { \ - int32_t offset = 0; \ - baseOffset32(temp, adr, offset); \ - NAME(Rd, temp, offset); \ - } \ - break; \ - } \ - default: \ - ShouldNotReachHere(); \ - } \ - } - - INSN(flw); - INSN(fld); -#undef INSN - #define INSN(NAME, op, funct3) \ void NAME(Register Rs1, Register Rs2, const int64_t offset) { \ guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid."); \ @@ -640,8 +497,8 @@ public: emit(insn); \ } - INSN(beq, 0b1100011, 0b000); - INSN(bne, 0b1100011, 0b001); + INSN(beq, 0b1100011, 0b000); + INSN(bne, 0b1100011, 0b001); INSN(bge, 0b1100011, 0b101); INSN(bgeu, 0b1100011, 0b111); INSN(blt, 0b1100011, 0b100); @@ -649,40 +506,6 @@ public: #undef INSN -#define INSN(NAME) \ - void NAME(Register Rs1, Register Rs2, const address dest) { \ - assert_cond(dest != NULL); \ - int64_t offset = (dest - pc()); \ - guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid."); \ - NAME(Rs1, Rs2, offset); \ - } \ - INSN_ENTRY_RELOC(void, NAME(Register Rs1, Register Rs2, address dest, relocInfo::relocType rtype)) \ - NAME(Rs1, Rs2, dest); \ - } - - INSN(beq); - INSN(bne); - INSN(bge); - INSN(bgeu); - INSN(blt); - INSN(bltu); - -#undef INSN - -#define INSN(NAME, NEG_INSN) \ - void NAME(Register Rs1, Register Rs2, Label &L, bool is_far = false) { \ - wrap_label(Rs1, Rs2, L, &Assembler::NAME, &Assembler::NEG_INSN, is_far); \ - } - - INSN(beq, bne); - INSN(bne, beq); - INSN(blt, bge); - INSN(bge, blt); - INSN(bltu, bgeu); - INSN(bgeu, bltu); - -#undef INSN - #define INSN(NAME, REGISTER, op, funct3) \ void NAME(REGISTER Rs1, Register Rs2, const int32_t offset) { \ guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \ @@ -708,105 +531,6 @@ public: #undef INSN -#define INSN(NAME, REGISTER) \ - INSN_ENTRY_RELOC(void, NAME(REGISTER Rs, address dest, relocInfo::relocType rtype, Register temp = t0)) \ - NAME(Rs, dest, temp); \ - } - - INSN(sb, Register); - INSN(sh, Register); - INSN(sw, Register); - INSN(sd, Register); - INSN(fsw, FloatRegister); - INSN(fsd, FloatRegister); - -#undef INSN - -#define INSN(NAME) \ - void NAME(Register Rs, address dest, Register temp = t0) { \ - assert_cond(dest != NULL); \ - assert_different_registers(Rs, temp); \ - int64_t distance = (dest - pc()); \ - if (is_offset_in_range(distance, 32)) { \ - auipc(temp, (int32_t)distance + 0x800); \ - NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \ - } else { \ - int32_t offset = 0; \ - movptr(temp, dest, offset); \ - NAME(Rs, temp, offset); \ - } \ - } \ - void NAME(Register Rs, const Address &adr, Register temp = t0) { \ - switch (adr.getMode()) { \ - case Address::literal: { \ - assert_different_registers(Rs, temp); \ - relocate(adr.rspec()); \ - NAME(Rs, adr.target(), temp); \ - break; \ - } \ - case Address::base_plus_offset: { \ - if (is_offset_in_range(adr.offset(), 12)) { \ - NAME(Rs, adr.base(), adr.offset()); \ - } else { \ - int32_t offset= 0; \ - assert_different_registers(Rs, temp); \ - baseOffset32(temp, adr, offset); \ - NAME(Rs, temp, offset); \ - } \ - break; \ - } \ - default: \ - ShouldNotReachHere(); \ - } \ - } - - INSN(sb); - INSN(sh); - INSN(sw); - INSN(sd); - -#undef INSN - -#define INSN(NAME) \ - void NAME(FloatRegister Rs, address dest, Register temp = t0) { \ - assert_cond(dest != NULL); \ - int64_t distance = (dest - pc()); \ - if (is_offset_in_range(distance, 32)) { \ - auipc(temp, (int32_t)distance + 0x800); \ - NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \ - } else { \ - int32_t offset = 0; \ - movptr(temp, dest, offset); \ - NAME(Rs, temp, offset); \ - } \ - } \ - void NAME(FloatRegister Rs, const Address &adr, Register temp = t0) { \ - switch (adr.getMode()) { \ - case Address::literal: { \ - relocate(adr.rspec()); \ - NAME(Rs, adr.target(), temp); \ - break; \ - } \ - case Address::base_plus_offset: { \ - if (is_offset_in_range(adr.offset(), 12)) { \ - NAME(Rs, adr.base(), adr.offset()); \ - } else { \ - int32_t offset = 0; \ - baseOffset32(temp, adr, offset); \ - NAME(Rs, temp, offset); \ - } \ - break; \ - } \ - default: \ - ShouldNotReachHere(); \ - } \ - } - - INSN(fsw); - INSN(fsd); - -#undef INSN - #define INSN(NAME, op, funct3) \ void NAME(Register Rd, const uint32_t csr, Register Rs1) { \ guarantee(is_unsigned_imm_in_range(csr, 12, 0), "csr is invalid"); \ @@ -845,58 +569,34 @@ public: #undef INSN -#define INSN(NAME, op) \ - void NAME(Register Rd, const int32_t offset) { \ - guarantee(is_imm_in_range(offset, 20, 1), "offset is invalid."); \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch_reg((address)&insn, 7, Rd); \ - patch((address)&insn, 19, 12, (uint32_t)((offset >> 12) & 0xff)); \ - patch((address)&insn, 20, (uint32_t)((offset >> 11) & 0x1)); \ - patch((address)&insn, 30, 21, (uint32_t)((offset >> 1) & 0x3ff)); \ - patch((address)&insn, 31, (uint32_t)((offset >> 20) & 0x1)); \ - emit(insn); \ +#define INSN(NAME, op) \ + void NAME(Register Rd, const int32_t offset) { \ + guarantee(is_imm_in_range(offset, 20, 1), "offset is invalid."); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch_reg((address)&insn, 7, Rd); \ + patch((address)&insn, 19, 12, (uint32_t)((offset >> 12) & 0xff)); \ + patch((address)&insn, 20, (uint32_t)((offset >> 11) & 0x1)); \ + patch((address)&insn, 30, 21, (uint32_t)((offset >> 1) & 0x3ff)); \ + patch((address)&insn, 31, (uint32_t)((offset >> 20) & 0x1)); \ + emit(insn); \ } INSN(jal, 0b1101111); #undef INSN -#define INSN(NAME) \ - void NAME(Register Rd, const address dest, Register temp = t0) { \ - assert_cond(dest != NULL); \ - int64_t offset = dest - pc(); \ - if (is_imm_in_range(offset, 20, 1)) { \ - NAME(Rd, offset); \ - } else { \ - assert_different_registers(Rd, temp); \ - int32_t off = 0; \ - movptr(temp, dest, off); \ - jalr(Rd, temp, off); \ - } \ - } \ - void NAME(Register Rd, Label &L, Register temp = t0) { \ - assert_different_registers(Rd, temp); \ - wrap_label(Rd, L, temp, &Assembler::NAME); \ - } - - INSN(jal); - -#undef INSN - -#undef INSN_ENTRY_RELOC - -#define INSN(NAME, op, funct) \ - void NAME(Register Rd, Register Rs, const int32_t offset) { \ - guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch_reg((address)&insn, 7, Rd); \ - patch((address)&insn, 14, 12, funct); \ - patch_reg((address)&insn, 15, Rs); \ - int32_t val = offset & 0xfff; \ - patch((address)&insn, 31, 20, val); \ - emit(insn); \ +#define INSN(NAME, op, funct) \ + void NAME(Register Rd, Register Rs, const int32_t offset) { \ + guarantee(is_offset_in_range(offset, 12), "offset is invalid."); \ + unsigned insn = 0; \ + patch((address)&insn, 6, 0, op); \ + patch_reg((address)&insn, 7, Rd); \ + patch((address)&insn, 14, 12, funct); \ + patch_reg((address)&insn, 15, Rs); \ + int32_t val = offset & 0xfff; \ + patch((address)&insn, 31, 20, val); \ + emit(insn); \ } INSN(_jalr, 0b1100111, 0b000); @@ -1024,10 +724,10 @@ enum operand_size { int8, int16, int32, uint32, int64 }; emit(insn); \ } - INSN(fsqrt_s, 0b1010011, 0b00000, 0b0101100); - INSN(fsqrt_d, 0b1010011, 0b00000, 0b0101101); - INSN(fcvt_s_d, 0b1010011, 0b00001, 0b0100000); - INSN(fcvt_d_s, 0b1010011, 0b00000, 0b0100001); + INSN(fsqrt_s, 0b1010011, 0b00000, 0b0101100); + INSN(fsqrt_d, 0b1010011, 0b00000, 0b0101101); + INSN(fcvt_s_d, 0b1010011, 0b00001, 0b0100000); + INSN(fcvt_d_s, 0b1010011, 0b00000, 0b0100001); #undef INSN // Immediate Instruction @@ -2676,10 +2376,6 @@ public: private: // some helper functions - bool do_compress() const { - return UseRVC && in_compressible_region(); - } - #define FUNC(NAME, funct3, bits) \ bool NAME(Register rs1, Register rd_rs2, int32_t imm12, bool ld) { \ return rs1 == sp && \ @@ -2719,6 +2415,10 @@ private: #undef FUNC public: + bool do_compress() const { + return UseRVC && in_compressible_region(); + } + // -------------------------- // Load/store register // -------------------------- @@ -2882,21 +2582,6 @@ public: // -------------------------- // Immediate Instructions -// -------------------------- -#define INSN(NAME) \ - void NAME(Register Rd, int64_t imm) { \ - /* li -> c.li */ \ - if (do_compress() && (is_imm_in_range(imm, 6, 0) && Rd != x0)) { \ - c_li(Rd, imm); \ - return; \ - } \ - _li(Rd, imm); \ - } - - INSN(li); - -#undef INSN - // -------------------------- #define INSN(NAME) \ void NAME(Register Rd, Register Rs1, int32_t imm) { \ @@ -3008,37 +2693,20 @@ public: // --------------------------------------------------------------------------------------- - void bgt(Register Rs, Register Rt, const address &dest); - void ble(Register Rs, Register Rt, const address &dest); - void bgtu(Register Rs, Register Rt, const address &dest); - void bleu(Register Rs, Register Rt, const address &dest); - void bgt(Register Rs, Register Rt, Label &l, bool is_far = false); - void ble(Register Rs, Register Rt, Label &l, bool is_far = false); - void bgtu(Register Rs, Register Rt, Label &l, bool is_far = false); - void bleu(Register Rs, Register Rt, Label &l, bool is_far = false); +#define INSN(NAME, REGISTER) \ + void NAME(Register Rs) { \ + jalr(REGISTER, Rs, 0); \ + } - typedef void (Assembler::* jal_jalr_insn)(Register Rt, address dest); - typedef void (Assembler::* load_insn_by_temp)(Register Rt, address dest, Register temp); - typedef void (Assembler::* compare_and_branch_insn)(Register Rs1, Register Rs2, const address dest); - typedef void (Assembler::* compare_and_branch_label_insn)(Register Rs1, Register Rs2, Label &L, bool is_far); + INSN(jr, x0); + INSN(jalr, x1); - void wrap_label(Register r1, Register r2, Label &L, compare_and_branch_insn insn, - compare_and_branch_label_insn neg_insn, bool is_far); - void wrap_label(Register r, Label &L, Register t, load_insn_by_temp insn); - void wrap_label(Register r, Label &L, jal_jalr_insn insn); - - // Computational pseudo instructions - void add(Register Rd, Register Rn, int64_t increment, Register temp = t0); - void addw(Register Rd, Register Rn, int32_t increment, Register temp = t0); - - void sub(Register Rd, Register Rn, int64_t decrement, Register temp = t0); - void subw(Register Rd, Register Rn, int32_t decrement, Register temp = t0); +#undef INSN // RVB pseudo instructions // zero extend word - void zext_w(Register Rd, Register Rs); - - Assembler(CodeBuffer* code) : AbstractAssembler(code), _in_compressible_region(false) { + void zext_w(Register Rd, Register Rs) { + add_uw(Rd, Rs, zr); } // Stack overflow checking @@ -3055,6 +2723,8 @@ public: return uabs(target - branch) < branch_range; } + Assembler(CodeBuffer* code) : AbstractAssembler(code), _in_compressible_region(false) {} + virtual ~Assembler() {} }; diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index 66154603013..b1f1718dd45 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -543,44 +543,44 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi assert(dest->is_address(), "should not call otherwise"); LIR_Const* c = src->as_constant_ptr(); LIR_Address* to_addr = dest->as_address_ptr(); - void (Assembler::* insn)(Register Rt, const Address &adr, Register temp); + void (MacroAssembler::* insn)(Register Rt, const Address &adr, Register temp); switch (type) { case T_ADDRESS: assert(c->as_jint() == 0, "should be"); - insn = &Assembler::sd; break; + insn = &MacroAssembler::sd; break; case T_LONG: assert(c->as_jlong() == 0, "should be"); - insn = &Assembler::sd; break; + insn = &MacroAssembler::sd; break; case T_DOUBLE: assert(c->as_jdouble() == 0.0, "should be"); - insn = &Assembler::sd; break; + insn = &MacroAssembler::sd; break; case T_INT: assert(c->as_jint() == 0, "should be"); - insn = &Assembler::sw; break; + insn = &MacroAssembler::sw; break; case T_FLOAT: assert(c->as_jfloat() == 0.0f, "should be"); - insn = &Assembler::sw; break; + insn = &MacroAssembler::sw; break; case T_OBJECT: // fall through case T_ARRAY: assert(c->as_jobject() == 0, "should be"); if (UseCompressedOops && !wide) { - insn = &Assembler::sw; + insn = &MacroAssembler::sw; } else { - insn = &Assembler::sd; + insn = &MacroAssembler::sd; } break; case T_CHAR: // fall through case T_SHORT: assert(c->as_jint() == 0, "should be"); - insn = &Assembler::sh; + insn = &MacroAssembler::sh; break; case T_BOOLEAN: // fall through case T_BYTE: assert(c->as_jint() == 0, "should be"); - insn = &Assembler::sb; break; + insn = &MacroAssembler::sb; break; default: ShouldNotReachHere(); - insn = &Assembler::sd; // unreachable + insn = &MacroAssembler::sd; // unreachable } if (info != NULL) { add_debug_info_for_null_check_here(info); diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp index 27ab8dae47c..e1715d20eb5 100644 --- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp @@ -41,8 +41,7 @@ void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result, FloatRegister freg0, FloatRegister freg1, - Register result) -{ + Register result) { if (is_float) { float_compare(result, freg0, freg1, unordered_result); } else { @@ -375,14 +374,14 @@ typedef void (C1_MacroAssembler::*c1_float_cond_branch_insn)(FloatRegister op1, static c1_cond_branch_insn c1_cond_branch[] = { /* SHORT branches */ - (c1_cond_branch_insn)&Assembler::beq, - (c1_cond_branch_insn)&Assembler::bne, - (c1_cond_branch_insn)&Assembler::blt, - (c1_cond_branch_insn)&Assembler::ble, - (c1_cond_branch_insn)&Assembler::bge, - (c1_cond_branch_insn)&Assembler::bgt, - (c1_cond_branch_insn)&Assembler::bleu, // lir_cond_belowEqual - (c1_cond_branch_insn)&Assembler::bgeu // lir_cond_aboveEqual + (c1_cond_branch_insn)&MacroAssembler::beq, + (c1_cond_branch_insn)&MacroAssembler::bne, + (c1_cond_branch_insn)&MacroAssembler::blt, + (c1_cond_branch_insn)&MacroAssembler::ble, + (c1_cond_branch_insn)&MacroAssembler::bge, + (c1_cond_branch_insn)&MacroAssembler::bgt, + (c1_cond_branch_insn)&MacroAssembler::bleu, // lir_cond_belowEqual + (c1_cond_branch_insn)&MacroAssembler::bgeu // lir_cond_aboveEqual }; static c1_float_cond_branch_insn c1_float_cond_branch[] = diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index 70c419ec50b..c9205db16ba 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -1207,8 +1207,8 @@ void C2_MacroAssembler::string_equals(Register a1, Register a2, andi(t0, cnt1, 1); beqz(t0, SAME); { - lbu(tmp1, a1, 0); - lbu(tmp2, a2, 0); + lbu(tmp1, Address(a1, 0)); + lbu(tmp2, Address(a2, 0)); bne(tmp1, tmp2, DONE); } } @@ -1229,24 +1229,24 @@ typedef void (MacroAssembler::*float_conditional_branch_insn)(FloatRegister op1, static conditional_branch_insn conditional_branches[] = { /* SHORT branches */ - (conditional_branch_insn)&Assembler::beq, - (conditional_branch_insn)&Assembler::bgt, + (conditional_branch_insn)&MacroAssembler::beq, + (conditional_branch_insn)&MacroAssembler::bgt, NULL, // BoolTest::overflow - (conditional_branch_insn)&Assembler::blt, - (conditional_branch_insn)&Assembler::bne, - (conditional_branch_insn)&Assembler::ble, + (conditional_branch_insn)&MacroAssembler::blt, + (conditional_branch_insn)&MacroAssembler::bne, + (conditional_branch_insn)&MacroAssembler::ble, NULL, // BoolTest::no_overflow - (conditional_branch_insn)&Assembler::bge, + (conditional_branch_insn)&MacroAssembler::bge, /* UNSIGNED branches */ - (conditional_branch_insn)&Assembler::beq, - (conditional_branch_insn)&Assembler::bgtu, + (conditional_branch_insn)&MacroAssembler::beq, + (conditional_branch_insn)&MacroAssembler::bgtu, NULL, - (conditional_branch_insn)&Assembler::bltu, - (conditional_branch_insn)&Assembler::bne, - (conditional_branch_insn)&Assembler::bleu, + (conditional_branch_insn)&MacroAssembler::bltu, + (conditional_branch_insn)&MacroAssembler::bne, + (conditional_branch_insn)&MacroAssembler::bleu, NULL, - (conditional_branch_insn)&Assembler::bgeu + (conditional_branch_insn)&MacroAssembler::bgeu }; static float_conditional_branch_insn float_conditional_branches[] = diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp index cacc80fc56d..7287c684742 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -368,12 +368,12 @@ void InterpreterMacroAssembler::push_l(Register r) { } void InterpreterMacroAssembler::pop_f(FloatRegister r) { - flw(r, esp, 0); + flw(r, Address(esp, 0)); addi(esp, esp, wordSize); } void InterpreterMacroAssembler::pop_d(FloatRegister r) { - fld(r, esp, 0); + fld(r, Address(esp, 0)); addi(esp, esp, 2 * Interpreter::stackElementSize); } diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index debfcfb4cf9..0f31a00a21f 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -719,7 +719,34 @@ void MacroAssembler::vfneg_v(VectorRegister vd, VectorRegister vs) { vfsgnjn_vv(vd, vs, vs); } -void MacroAssembler::la(Register Rd, const address &dest) { +void MacroAssembler::baseOffset32(Register Rd, const Address &adr, int32_t &offset) { + assert(Rd != noreg, "Rd must not be empty register!"); + guarantee(Rd != adr.base(), "should use different registers!"); + if (is_offset_in_range(adr.offset(), 32)) { + int32_t imm = adr.offset(); + int32_t upper = imm, lower = imm; + lower = (imm << 20) >> 20; + upper -= lower; + lui(Rd, upper); + offset = lower; + } else { + offset = ((int32_t)adr.offset() << 20) >> 20; + li(Rd, adr.offset() - offset); + } + add(Rd, Rd, adr.base()); +} + +void MacroAssembler::baseOffset(Register Rd, const Address &adr, int32_t &offset) { + if (is_offset_in_range(adr.offset(), 12)) { + assert(Rd != noreg, "Rd must not be empty register!"); + addi(Rd, adr.base(), adr.offset()); + offset = 0; + } else { + baseOffset32(Rd, adr, offset); + } +} + +void MacroAssembler::la(Register Rd, const address dest) { int64_t offset = dest - pc(); if (is_offset_in_range(offset, 32)) { auipc(Rd, (int32_t)offset + 0x800); //0x800, Note:the 11th sign bit @@ -757,8 +784,210 @@ void MacroAssembler::la(Register Rd, Label &label) { la(Rd, target(label)); } +void MacroAssembler::li32(Register Rd, int32_t imm) { + // int32_t is in range 0x8000 0000 ~ 0x7fff ffff, and imm[31] is the sign bit + int64_t upper = imm, lower = imm; + lower = (imm << 20) >> 20; + upper -= lower; + upper = (int32_t)upper; + // lui Rd, imm[31:12] + imm[11] + lui(Rd, upper); + // use addiw to distinguish li32 to li64 + addiw(Rd, Rd, lower); +} + +void MacroAssembler::li64(Register Rd, int64_t imm) { + // Load upper 32 bits. upper = imm[63:32], but if imm[31] == 1 or + // (imm[31:20] == 0x7ff && imm[19] == 1), upper = imm[63:32] + 1. + int64_t lower = imm & 0xffffffff; + lower -= ((lower << 44) >> 44); + int64_t tmp_imm = ((uint64_t)(imm & 0xffffffff00000000)) + (uint64_t)lower; + int32_t upper = (tmp_imm - (int32_t)lower) >> 32; + + // Load upper 32 bits + int64_t up = upper, lo = upper; + lo = (lo << 52) >> 52; + up -= lo; + up = (int32_t)up; + lui(Rd, up); + addi(Rd, Rd, lo); + + // Load the rest 32 bits. + slli(Rd, Rd, 12); + addi(Rd, Rd, (int32_t)lower >> 20); + slli(Rd, Rd, 12); + lower = ((int32_t)imm << 12) >> 20; + addi(Rd, Rd, lower); + slli(Rd, Rd, 8); + lower = imm & 0xff; + addi(Rd, Rd, lower); +} + +void MacroAssembler::li(Register Rd, int64_t imm) { + // int64_t is in range 0x8000 0000 0000 0000 ~ 0x7fff ffff ffff ffff + // li -> c.li + if (do_compress() && (is_imm_in_range(imm, 6, 0) && Rd != x0)) { + c_li(Rd, imm); + return; + } + + int shift = 12; + int64_t upper = imm, lower = imm; + // Split imm to a lower 12-bit sign-extended part and the remainder, + // because addi will sign-extend the lower imm. + lower = ((int32_t)imm << 20) >> 20; + upper -= lower; + + // Test whether imm is a 32-bit integer. + if (!(((imm) & ~(int64_t)0x7fffffff) == 0 || + (((imm) & ~(int64_t)0x7fffffff) == ~(int64_t)0x7fffffff))) { + while (((upper >> shift) & 1) == 0) { shift++; } + upper >>= shift; + li(Rd, upper); + slli(Rd, Rd, shift); + if (lower != 0) { + addi(Rd, Rd, lower); + } + } else { + // 32-bit integer + Register hi_Rd = zr; + if (upper != 0) { + lui(Rd, (int32_t)upper); + hi_Rd = Rd; + } + if (lower != 0 || hi_Rd == zr) { + addiw(Rd, hi_Rd, lower); + } + } +} + +#define INSN(NAME, REGISTER) \ + void MacroAssembler::NAME(const address dest, Register temp) { \ + assert_cond(dest != NULL); \ + int64_t distance = dest - pc(); \ + if (is_imm_in_range(distance, 20, 1)) { \ + Assembler::jal(REGISTER, distance); \ + } else { \ + assert(temp != noreg, "temp must not be empty register!"); \ + int32_t offset = 0; \ + movptr(temp, dest, offset); \ + Assembler::jalr(REGISTER, temp, offset); \ + } \ + } \ + + INSN(j, x0); + INSN(jal, x1); + +#undef INSN + +#define INSN(NAME, REGISTER) \ + void MacroAssembler::NAME(const Address &adr, Register temp) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + relocate(adr.rspec()); \ + NAME(adr.target(), temp); \ + break; \ + } \ + case Address::base_plus_offset: { \ + int32_t offset = 0; \ + baseOffset(temp, adr, offset); \ + Assembler::jalr(REGISTER, temp, offset); \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } + + INSN(j, x0); + INSN(jal, x1); + +#undef INSN + +#define INSN(NAME) \ + void MacroAssembler::NAME(Register Rd, const address dest, Register temp) { \ + assert_cond(dest != NULL); \ + int64_t distance = dest - pc(); \ + if (is_imm_in_range(distance, 20, 1)) { \ + Assembler::NAME(Rd, distance); \ + } else { \ + assert_different_registers(Rd, temp); \ + int32_t offset = 0; \ + movptr(temp, dest, offset); \ + jalr(Rd, temp, offset); \ + } \ + } \ + void MacroAssembler::NAME(Register Rd, Label &L, Register temp) { \ + assert_different_registers(Rd, temp); \ + wrap_label(Rd, L, temp, &MacroAssembler::NAME); \ + } + + INSN(jal); + +#undef INSN + +#define INSN(NAME, REGISTER) \ + void MacroAssembler::NAME(Label &l, Register temp) { \ + jal(REGISTER, l, temp); \ + } \ + + INSN(j, x0); + INSN(jal, x1); + +#undef INSN + +void MacroAssembler::wrap_label(Register Rt, Label &L, Register tmp, load_insn_by_temp insn) { + if (L.is_bound()) { + (this->*insn)(Rt, target(L), tmp); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(Rt, pc(), tmp); + } +} + +void MacroAssembler::wrap_label(Register Rt, Label &L, jal_jalr_insn insn) { + if (L.is_bound()) { + (this->*insn)(Rt, target(L)); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(Rt, pc()); + } +} + +void MacroAssembler::wrap_label(Register r1, Register r2, Label &L, + compare_and_branch_insn insn, + compare_and_branch_label_insn neg_insn, bool is_far) { + if (is_far) { + Label done; + (this->*neg_insn)(r1, r2, done, /* is_far */ false); + j(L); + bind(done); + } else { + if (L.is_bound()) { + (this->*insn)(r1, r2, target(L)); + } else { + L.add_patch_at(code(), locator()); + (this->*insn)(r1, r2, pc()); + } + } +} + +#define INSN(NAME, NEG_INSN) \ + void MacroAssembler::NAME(Register Rs1, Register Rs2, Label &L, bool is_far) { \ + wrap_label(Rs1, Rs2, L, &MacroAssembler::NAME, &MacroAssembler::NEG_INSN, is_far); \ + } + + INSN(beq, bne); + INSN(bne, beq); + INSN(blt, bge); + INSN(bge, blt); + INSN(bltu, bgeu); + INSN(bgeu, bltu); + +#undef INSN + #define INSN(NAME) \ - void MacroAssembler::NAME##z(Register Rs, const address &dest) { \ + void MacroAssembler::NAME##z(Register Rs, const address dest) { \ NAME(Rs, zr, dest); \ } \ void MacroAssembler::NAME##z(Register Rs, Label &l, bool is_far) { \ @@ -774,16 +1003,31 @@ void MacroAssembler::la(Register Rd, Label &label) { #undef INSN +#define INSN(NAME, NEG_INSN) \ + void MacroAssembler::NAME(Register Rs, Register Rt, const address dest) { \ + NEG_INSN(Rt, Rs, dest); \ + } \ + void MacroAssembler::NAME(Register Rs, Register Rt, Label &l, bool is_far) { \ + NEG_INSN(Rt, Rs, l, is_far); \ + } + + INSN(bgt, blt); + INSN(ble, bge); + INSN(bgtu, bltu); + INSN(bleu, bgeu); + +#undef INSN + // Float compare branch instructions -#define INSN(NAME, FLOATCMP, BRANCH) \ - void MacroAssembler::float_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \ - FLOATCMP##_s(t0, Rs1, Rs2); \ - BRANCH(t0, l, is_far); \ - } \ - void MacroAssembler::double_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \ - FLOATCMP##_d(t0, Rs1, Rs2); \ - BRANCH(t0, l, is_far); \ +#define INSN(NAME, FLOATCMP, BRANCH) \ + void MacroAssembler::float_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \ + FLOATCMP##_s(t0, Rs1, Rs2); \ + BRANCH(t0, l, is_far); \ + } \ + void MacroAssembler::double_##NAME(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far, bool is_unordered) { \ + FLOATCMP##_d(t0, Rs1, Rs2); \ + BRANCH(t0, l, is_far); \ } INSN(beq, feq, bnez); @@ -928,7 +1172,7 @@ void MacroAssembler::push_reg(Register Rs) void MacroAssembler::pop_reg(Register Rd) { - ld(Rd, esp, 0); + ld(Rd, Address(esp, 0)); addi(esp, esp, wordSize); } @@ -1361,6 +1605,85 @@ void MacroAssembler::mv(Register Rd, RegisterOrConstant src) { } } +void MacroAssembler::movptr(Register Rd, address addr, int32_t &offset) { + int64_t imm64 = (int64_t)addr; +#ifndef PRODUCT + { + char buffer[64]; + snprintf(buffer, sizeof(buffer), "0x%" PRIx64, imm64); + block_comment(buffer); + } +#endif + assert(is_unsigned_imm_in_range(imm64, 47, 0) || (imm64 == (int64_t)-1), + "bit 47 overflows in address constant"); + // Load upper 31 bits + int64_t imm = imm64 >> 17; + int64_t upper = imm, lower = imm; + lower = (lower << 52) >> 52; + upper -= lower; + upper = (int32_t)upper; + lui(Rd, upper); + addi(Rd, Rd, lower); + + // Load the rest 17 bits. + slli(Rd, Rd, 11); + addi(Rd, Rd, (imm64 >> 6) & 0x7ff); + slli(Rd, Rd, 6); + + // This offset will be used by following jalr/ld. + offset = imm64 & 0x3f; +} + +void MacroAssembler::movptr(Register Rd, uintptr_t imm64) { + movptr(Rd, (address)imm64); +} + +void MacroAssembler::movptr(Register Rd, address addr) { + int offset = 0; + movptr(Rd, addr, offset); + addi(Rd, Rd, offset); +} + +void MacroAssembler::add(Register Rd, Register Rn, int64_t increment, Register temp) { + if (is_imm_in_range(increment, 12, 0)) { + addi(Rd, Rn, increment); + } else { + assert_different_registers(Rn, temp); + li(temp, increment); + add(Rd, Rn, temp); + } +} + +void MacroAssembler::addw(Register Rd, Register Rn, int32_t increment, Register temp) { + if (is_imm_in_range(increment, 12, 0)) { + addiw(Rd, Rn, increment); + } else { + assert_different_registers(Rn, temp); + li(temp, increment); + addw(Rd, Rn, temp); + } +} + +void MacroAssembler::sub(Register Rd, Register Rn, int64_t decrement, Register temp) { + if (is_imm_in_range(-decrement, 12, 0)) { + addi(Rd, Rn, -decrement); + } else { + assert_different_registers(Rn, temp); + li(temp, decrement); + sub(Rd, Rn, temp); + } +} + +void MacroAssembler::subw(Register Rd, Register Rn, int32_t decrement, Register temp) { + if (is_imm_in_range(-decrement, 12, 0)) { + addiw(Rd, Rn, -decrement); + } else { + assert_different_registers(Rn, temp); + li(temp, decrement); + subw(Rd, Rn, temp); + } +} + void MacroAssembler::andrw(Register Rd, Register Rs1, Register Rs2) { andr(Rd, Rs1, Rs2); // addw: The result is clipped to 32 bits, then the sign bit is extended, @@ -3858,7 +4181,7 @@ void MacroAssembler::zero_memory(Register addr, Register len, Register tmp) { bind(loop); sub(len, len, unroll); for (int i = -unroll; i < 0; i++) { - Assembler::sd(zr, Address(tmp, i * wordSize)); + sd(zr, Address(tmp, i * wordSize)); } bind(entry); add(tmp, tmp, unroll * wordSize); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 3fe21bfc442..aa3881c5401 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -42,14 +42,15 @@ class MacroAssembler: public Assembler { public: - MacroAssembler(CodeBuffer* code) : Assembler(code) { - } + MacroAssembler(CodeBuffer* code) : Assembler(code) {} + virtual ~MacroAssembler() {} void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod); // Alignment int align(int modulus, int extra_offset = 0); + static inline void assert_alignment(address pc, int alignment = NativeInstruction::instruction_size) { assert(is_aligned(pc, alignment), "bad alignment"); } @@ -271,7 +272,7 @@ class MacroAssembler: public Assembler { Register tmp1, // temp register Register tmp2, // temp register Label& slow_case, // continuation point of fast allocation fails - bool is_far = false + bool is_far = false ); // Test sub_klass against super_klass, with fast and slow paths. @@ -401,7 +402,7 @@ class MacroAssembler: public Assembler { void store_sized_value(Address dst, Register src, size_t size_in_bytes, Register src2 = noreg); public: - // Standard pseudoinstruction + // Standard pseudo instructions void nop(); void mv(Register Rd, Register Rs); void notr(Register Rd, Register Rs); @@ -414,17 +415,15 @@ class MacroAssembler: public Assembler { void sltz(Register Rd, Register Rs); // set if < zero void sgtz(Register Rd, Register Rs); // set if > zero - // Float pseudoinstruction + // Floating-point data-processing pseudo instructions void fmv_s(FloatRegister Rd, FloatRegister Rs); - void fabs_s(FloatRegister Rd, FloatRegister Rs); // single-precision absolute value + void fabs_s(FloatRegister Rd, FloatRegister Rs); void fneg_s(FloatRegister Rd, FloatRegister Rs); - - // Double pseudoinstruction void fmv_d(FloatRegister Rd, FloatRegister Rs); void fabs_d(FloatRegister Rd, FloatRegister Rs); void fneg_d(FloatRegister Rd, FloatRegister Rs); - // Pseudoinstruction for control and status register + // Control and status pseudo instructions void rdinstret(Register Rd); // read instruction-retired counter void rdcycle(Register Rd); // read cycle counter void rdtime(Register Rd); // read time @@ -449,15 +448,23 @@ class MacroAssembler: public Assembler { void fsflagsi(Register Rd, unsigned imm); void fsflagsi(unsigned imm); - void beqz(Register Rs, const address &dest); - void bnez(Register Rs, const address &dest); - void blez(Register Rs, const address &dest); - void bgez(Register Rs, const address &dest); - void bltz(Register Rs, const address &dest); - void bgtz(Register Rs, const address &dest); - void la(Register Rd, Label &label); - void la(Register Rd, const address &dest); - void la(Register Rd, const Address &adr); + // Control transfer pseudo instructions + void beqz(Register Rs, const address dest); + void bnez(Register Rs, const address dest); + void blez(Register Rs, const address dest); + void bgez(Register Rs, const address dest); + void bltz(Register Rs, const address dest); + void bgtz(Register Rs, const address dest); + + void j(Label &l, Register temp = t0); + void j(const address dest, Register temp = t0); + void j(const Address &adr, Register temp = t0); + void jal(Label &l, Register temp = t0); + void jal(const address dest, Register temp = t0); + void jal(const Address &adr, Register temp = t0); + void jal(Register Rd, Label &L, Register temp = t0); + void jal(Register Rd, const address dest, Register temp = t0); + //label void beqz(Register Rs, Label &l, bool is_far = false); void bnez(Register Rs, Label &l, bool is_far = false); @@ -465,12 +472,59 @@ class MacroAssembler: public Assembler { void bgez(Register Rs, Label &l, bool is_far = false); void bltz(Register Rs, Label &l, bool is_far = false); void bgtz(Register Rs, Label &l, bool is_far = false); + + void beq (Register Rs1, Register Rs2, Label &L, bool is_far = false); + void bne (Register Rs1, Register Rs2, Label &L, bool is_far = false); + void blt (Register Rs1, Register Rs2, Label &L, bool is_far = false); + void bge (Register Rs1, Register Rs2, Label &L, bool is_far = false); + void bltu(Register Rs1, Register Rs2, Label &L, bool is_far = false); + void bgeu(Register Rs1, Register Rs2, Label &L, bool is_far = false); + + void bgt (Register Rs, Register Rt, const address dest); + void ble (Register Rs, Register Rt, const address dest); + void bgtu(Register Rs, Register Rt, const address dest); + void bleu(Register Rs, Register Rt, const address dest); + + void bgt (Register Rs, Register Rt, Label &l, bool is_far = false); + void ble (Register Rs, Register Rt, Label &l, bool is_far = false); + void bgtu(Register Rs, Register Rt, Label &l, bool is_far = false); + void bleu(Register Rs, Register Rt, Label &l, bool is_far = false); + +#define INSN_ENTRY_RELOC(result_type, header) \ + result_type header { \ + guarantee(rtype == relocInfo::internal_word_type, \ + "only internal_word_type relocs make sense here"); \ + relocate(InternalAddress(dest).rspec()); + +#define INSN(NAME) \ + void NAME(Register Rs1, Register Rs2, const address dest) { \ + assert_cond(dest != NULL); \ + int64_t offset = dest - pc(); \ + guarantee(is_imm_in_range(offset, 12, 1), "offset is invalid."); \ + Assembler::NAME(Rs1, Rs2, offset); \ + } \ + INSN_ENTRY_RELOC(void, NAME(Register Rs1, Register Rs2, address dest, relocInfo::relocType rtype)) \ + NAME(Rs1, Rs2, dest); \ + } + + INSN(beq); + INSN(bne); + INSN(bge); + INSN(bgeu); + INSN(blt); + INSN(bltu); + +#undef INSN + +#undef INSN_ENTRY_RELOC + void float_beq(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); void float_bne(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); void float_ble(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); void float_bge(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); void float_blt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); void float_bgt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void double_beq(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); void double_bne(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); void double_ble(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); @@ -526,6 +580,28 @@ public: code()->clear_last_insn(); } + typedef void (MacroAssembler::* compare_and_branch_insn)(Register Rs1, Register Rs2, const address dest); + typedef void (MacroAssembler::* compare_and_branch_label_insn)(Register Rs1, Register Rs2, Label &L, bool is_far); + typedef void (MacroAssembler::* jal_jalr_insn)(Register Rt, address dest); + typedef void (MacroAssembler::* load_insn_by_temp)(Register Rt, address dest, Register temp); + + void wrap_label(Register r, Label &L, Register t, load_insn_by_temp insn); + void wrap_label(Register r, Label &L, jal_jalr_insn insn); + void wrap_label(Register r1, Register r2, Label &L, + compare_and_branch_insn insn, + compare_and_branch_label_insn neg_insn, bool is_far = false); + + void baseOffset(Register Rd, const Address &adr, int32_t &offset); + void baseOffset32(Register Rd, const Address &adr, int32_t &offset); + + void la(Register Rd, Label &label); + void la(Register Rd, const address dest); + void la(Register Rd, const Address &adr); + + void li32(Register Rd, int32_t imm); + void li64(Register Rd, int64_t imm); + void li(Register Rd, int64_t imm); // optimized load immediate + // mv void mv(Register Rd, address addr) { li(Rd, (int64_t)addr); } void mv(Register Rd, address addr, int32_t &offset) { @@ -543,6 +619,28 @@ public: void mv(Register Rd, Address dest); void mv(Register Rd, RegisterOrConstant src); + void movptr(Register Rd, address addr); + void movptr(Register Rd, address addr, int32_t &offset); + void movptr(Register Rd, uintptr_t imm64); + + // arith + void add (Register Rd, Register Rn, int64_t increment, Register temp = t0); + void addw(Register Rd, Register Rn, int32_t increment, Register temp = t0); + void sub (Register Rd, Register Rn, int64_t decrement, Register temp = t0); + void subw(Register Rd, Register Rn, int32_t decrement, Register temp = t0); + +#define INSN(NAME) \ + inline void NAME(Register Rd, Register Rs1, Register Rs2) { \ + Assembler::NAME(Rd, Rs1, Rs2); \ + } + + INSN(add); + INSN(addw); + INSN(sub); + INSN(subw); + +#undef INSN + // logic void andrw(Register Rd, Register Rs1, Register Rs2); void orrw(Register Rd, Register Rs1, Register Rs2); @@ -562,6 +660,215 @@ public: void andi(Register Rd, Register Rn, int64_t imm, Register tmp = t0); void orptr(Address adr, RegisterOrConstant src, Register tmp1 = t0, Register tmp2 = t1); +// Load and Store Instructions +#define INSN_ENTRY_RELOC(result_type, header) \ + result_type header { \ + guarantee(rtype == relocInfo::internal_word_type, \ + "only internal_word_type relocs make sense here"); \ + relocate(InternalAddress(dest).rspec()); + +#define INSN(NAME) \ + void NAME(Register Rd, address dest) { \ + assert_cond(dest != NULL); \ + int64_t distance = dest - pc(); \ + if (is_offset_in_range(distance, 32)) { \ + auipc(Rd, (int32_t)distance + 0x800); \ + Assembler::NAME(Rd, Rd, ((int32_t)distance << 20) >> 20); \ + } else { \ + int32_t offset = 0; \ + movptr(Rd, dest, offset); \ + Assembler::NAME(Rd, Rd, offset); \ + } \ + } \ + INSN_ENTRY_RELOC(void, NAME(Register Rd, address dest, relocInfo::relocType rtype)) \ + NAME(Rd, dest); \ + } \ + void NAME(Register Rd, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + relocate(adr.rspec()); \ + NAME(Rd, adr.target()); \ + break; \ + } \ + case Address::base_plus_offset: { \ + if (is_offset_in_range(adr.offset(), 12)) { \ + Assembler::NAME(Rd, adr.base(), adr.offset()); \ + } else { \ + int32_t offset = 0; \ + if (Rd == adr.base()) { \ + baseOffset32(temp, adr, offset); \ + Assembler::NAME(Rd, temp, offset); \ + } else { \ + baseOffset32(Rd, adr, offset); \ + Assembler::NAME(Rd, Rd, offset); \ + } \ + } \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } \ + void NAME(Register Rd, Label &L) { \ + wrap_label(Rd, L, &MacroAssembler::NAME); \ + } + + INSN(lb); + INSN(lbu); + INSN(lh); + INSN(lhu); + INSN(lw); + INSN(lwu); + INSN(ld); + +#undef INSN + +#define INSN(NAME) \ + void NAME(FloatRegister Rd, address dest, Register temp = t0) { \ + assert_cond(dest != NULL); \ + int64_t distance = dest - pc(); \ + if (is_offset_in_range(distance, 32)) { \ + auipc(temp, (int32_t)distance + 0x800); \ + Assembler::NAME(Rd, temp, ((int32_t)distance << 20) >> 20); \ + } else { \ + int32_t offset = 0; \ + movptr(temp, dest, offset); \ + Assembler::NAME(Rd, temp, offset); \ + } \ + } \ + INSN_ENTRY_RELOC(void, NAME(FloatRegister Rd, address dest, \ + relocInfo::relocType rtype, Register temp = t0)) \ + NAME(Rd, dest, temp); \ + } \ + void NAME(FloatRegister Rd, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + relocate(adr.rspec()); \ + NAME(Rd, adr.target(), temp); \ + break; \ + } \ + case Address::base_plus_offset: { \ + if (is_offset_in_range(adr.offset(), 12)) { \ + Assembler::NAME(Rd, adr.base(), adr.offset()); \ + } else { \ + int32_t offset = 0; \ + baseOffset32(temp, adr, offset); \ + Assembler::NAME(Rd, temp, offset); \ + } \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } + + INSN(flw); + INSN(fld); + +#undef INSN + +#define INSN(NAME, REGISTER) \ + INSN_ENTRY_RELOC(void, NAME(REGISTER Rs, address dest, \ + relocInfo::relocType rtype, Register temp = t0)) \ + NAME(Rs, dest, temp); \ + } + + INSN(sb, Register); + INSN(sh, Register); + INSN(sw, Register); + INSN(sd, Register); + INSN(fsw, FloatRegister); + INSN(fsd, FloatRegister); + +#undef INSN + +#define INSN(NAME) \ + void NAME(Register Rs, address dest, Register temp = t0) { \ + assert_cond(dest != NULL); \ + assert_different_registers(Rs, temp); \ + int64_t distance = dest - pc(); \ + if (is_offset_in_range(distance, 32)) { \ + auipc(temp, (int32_t)distance + 0x800); \ + Assembler::NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \ + } else { \ + int32_t offset = 0; \ + movptr(temp, dest, offset); \ + Assembler::NAME(Rs, temp, offset); \ + } \ + } \ + void NAME(Register Rs, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + assert_different_registers(Rs, temp); \ + relocate(adr.rspec()); \ + NAME(Rs, adr.target(), temp); \ + break; \ + } \ + case Address::base_plus_offset: { \ + if (is_offset_in_range(adr.offset(), 12)) { \ + Assembler::NAME(Rs, adr.base(), adr.offset()); \ + } else { \ + int32_t offset= 0; \ + assert_different_registers(Rs, temp); \ + baseOffset32(temp, adr, offset); \ + Assembler::NAME(Rs, temp, offset); \ + } \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } + + INSN(sb); + INSN(sh); + INSN(sw); + INSN(sd); + +#undef INSN + +#define INSN(NAME) \ + void NAME(FloatRegister Rs, address dest, Register temp = t0) { \ + assert_cond(dest != NULL); \ + int64_t distance = dest - pc(); \ + if (is_offset_in_range(distance, 32)) { \ + auipc(temp, (int32_t)distance + 0x800); \ + Assembler::NAME(Rs, temp, ((int32_t)distance << 20) >> 20); \ + } else { \ + int32_t offset = 0; \ + movptr(temp, dest, offset); \ + Assembler::NAME(Rs, temp, offset); \ + } \ + } \ + void NAME(FloatRegister Rs, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ + relocate(adr.rspec()); \ + NAME(Rs, adr.target(), temp); \ + break; \ + } \ + case Address::base_plus_offset: { \ + if (is_offset_in_range(adr.offset(), 12)) { \ + Assembler::NAME(Rs, adr.base(), adr.offset()); \ + } else { \ + int32_t offset = 0; \ + baseOffset32(temp, adr, offset); \ + Assembler::NAME(Rs, temp, offset); \ + } \ + break; \ + } \ + default: \ + ShouldNotReachHere(); \ + } \ + } + + INSN(fsw); + INSN(fsd); + +#undef INSN + +#undef INSN_ENTRY_RELOC + void cmpxchg_obj_header(Register oldv, Register newv, Register obj, Register tmp, Label &succeed, Label *fail); void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp, Label &succeed, Label *fail); void cmpxchg(Register addr, Register expected, diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 6516d52d1ce..ac262115241 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -2173,8 +2173,8 @@ void SharedRuntime::generate_uncommon_trap_blob() { size_of_deoptimized_frame_offset_in_bytes())); __ sub(x12, x12, 2 * wordSize); __ add(sp, sp, x12); - __ ld(fp, sp, 0); - __ ld(ra, sp, wordSize); + __ ld(fp, Address(sp, 0)); + __ ld(ra, Address(sp, wordSize)); __ addi(sp, sp, 2 * wordSize); // RA should now be the return address to the caller (3) frame diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index b409581cc46..563ab7c8fc1 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -329,7 +329,7 @@ class StubGenerator: public StubCodeGenerator { __ beqz(c_rarg6, parameters_done); address loop = __ pc(); - __ ld(t0, c_rarg5, 0); + __ ld(t0, Address(c_rarg5, 0)); __ addi(c_rarg5, c_rarg5, wordSize); __ addi(c_rarg6, c_rarg6, -1); __ push_reg(t0); diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index 16df4733cd0..5a6ee1de1db 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -1075,7 +1075,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ ld(x28, Address(xmethod, Method::native_function_offset())); address unsatisfied = (SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); __ mv(t1, unsatisfied); - __ ld(t1, t1); + __ ld(t1, Address(t1, 0)); __ bne(x28, t1, L); __ call_VM(noreg, CAST_FROM_FN_PTR(address, diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp index cb74efd226a..a591839960c 100644 --- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp @@ -244,10 +244,10 @@ void TemplateTable::fconst(int value) { __ fmv_w_x(f10, zr); break; case 1: - __ flw(f10, t0, 0); + __ flw(f10, Address(t0, 0)); break; case 2: - __ flw(f10, t0, sizeof(float)); + __ flw(f10, Address(t0, sizeof(float))); break; default: ShouldNotReachHere(); @@ -263,10 +263,10 @@ void TemplateTable::dconst(int value) { __ fmv_d_x(f10, zr); break; case 1: - __ fld(f10, t0, 0); + __ fld(f10, Address(t0, 0)); break; case 2: - __ fld(f10, t0, sizeof(double)); + __ fld(f10, Address(t0, sizeof(double))); break; default: ShouldNotReachHere();