From 586225e3158f0bbc83073485cbfb4d33334fdbb3 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Mon, 13 Jan 2025 10:25:27 +0100 Subject: [PATCH] Baseline --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 610 +++++++++++------- .../cpu/riscv/assembler_riscv.inline.hpp | 1 + .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 6 +- src/hotspot/cpu/riscv/globals_riscv.hpp | 1 + .../cpu/riscv/macroAssembler_riscv.cpp | 2 +- src/hotspot/cpu/riscv/riscv.ad | 10 +- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 3 + .../os_cpu/linux_riscv/riscv_hwprobe.cpp | 3 + 8 files changed, 403 insertions(+), 233 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 883170315622b..ddfdcec743e51 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -552,24 +552,6 @@ class Assembler : public AbstractAssembler { #undef INSN -#define INSN(NAME, op, funct3) \ - void NAME(FloatRegister Rd, Register Rs, const int32_t offset) { \ - guarantee(is_simm12(offset), "offset is invalid."); \ - unsigned insn = 0; \ - uint32_t val = offset & 0xfff; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, funct3); \ - patch_reg((address)&insn, 15, Rs); \ - patch_reg((address)&insn, 7, Rd); \ - patch((address)&insn, 31, 20, val); \ - emit(insn); \ - } - - INSN(flw, 0b0000111, 0b010); - INSN(_fld, 0b0000111, 0b011); - -#undef INSN - #define INSN(NAME, op, funct3) \ void NAME(Register Rs1, Register Rs2, const int64_t offset) { \ guarantee(is_simm13(offset) && ((offset % 2) == 0), "offset is invalid."); \ @@ -813,26 +795,6 @@ enum operand_size { int8, int16, int32, uint32, int64 }; INSN(sc_d, 0b0101111, 0b011, 0b00011); #undef INSN -#define INSN(NAME, op, funct5, funct7) \ - void NAME(FloatRegister Rd, FloatRegister Rs1, RoundingMode rm = rne) { \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, rm); \ - patch((address)&insn, 24, 20, funct5); \ - patch((address)&insn, 31, 25, funct7); \ - patch_reg((address)&insn, 7, Rd); \ - patch_reg((address)&insn, 15, Rs1); \ - emit(insn); \ - } - - INSN(fsqrt_s, 0b1010011, 0b00000, 0b0101100); - INSN(fsqrt_d, 0b1010011, 0b00000, 0b0101101); - INSN(fcvt_s_h, 0b1010011, 0b00010, 0b0100000); - INSN(fcvt_h_s, 0b1010011, 0b00000, 0b0100010); - INSN(fcvt_s_d, 0b1010011, 0b00001, 0b0100000); - INSN(fcvt_d_s, 0b1010011, 0b00000, 0b0100001); -#undef INSN - // Immediate Instruction #define INSN(NAME, op, funct3) \ void NAME(Register Rd, Register Rs1, int64_t imm) { \ @@ -928,209 +890,408 @@ enum operand_size { int8, int16, int32, uint32, int64 }; #undef INSN -// Float and Double Rigster Instruction -#define INSN(NAME, op, funct2) \ - void NAME(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, rm); \ - patch((address)&insn, 26, 25, funct2); \ - patch_reg((address)&insn, 7, Rd); \ - patch_reg((address)&insn, 15, Rs1); \ - patch_reg((address)&insn, 20, Rs2); \ - patch_reg((address)&insn, 27, Rs3); \ - emit(insn); \ - } - - INSN(fmadd_s, 0b1000011, 0b00); - INSN(fmsub_s, 0b1000111, 0b00); - INSN(fnmsub_s, 0b1001011, 0b00); - INSN(fnmadd_s, 0b1001111, 0b00); - INSN(fmadd_d, 0b1000011, 0b01); - INSN(fmsub_d, 0b1000111, 0b01); - INSN(fnmsub_d, 0b1001011, 0b01); - INSN(fnmadd_d, 0b1001111, 0b01); - -#undef INSN - -// Float and Double Rigster Instruction -#define INSN(NAME, op, funct3, funct7) \ - void NAME(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, funct3); \ - patch((address)&insn, 31, 25, funct7); \ - patch_reg((address)&insn, 7, Rd); \ - patch_reg((address)&insn, 15, Rs1); \ - patch_reg((address)&insn, 20, Rs2); \ - emit(insn); \ - } - - INSN(fsgnj_s, 0b1010011, 0b000, 0b0010000); - INSN(fsgnjn_s, 0b1010011, 0b001, 0b0010000); - INSN(fsgnjx_s, 0b1010011, 0b010, 0b0010000); - INSN(fmin_s, 0b1010011, 0b000, 0b0010100); - INSN(fmax_s, 0b1010011, 0b001, 0b0010100); - INSN(fsgnj_d, 0b1010011, 0b000, 0b0010001); - INSN(fsgnjn_d, 0b1010011, 0b001, 0b0010001); - INSN(fsgnjx_d, 0b1010011, 0b010, 0b0010001); - INSN(fmin_d, 0b1010011, 0b000, 0b0010101); - INSN(fmax_d, 0b1010011, 0b001, 0b0010101); - -#undef INSN - -// Float and Double Rigster Arith Instruction -#define INSN(NAME, op, funct3, funct7) \ - void NAME(Register Rd, FloatRegister Rs1, FloatRegister Rs2) { \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, funct3); \ - patch((address)&insn, 31, 25, funct7); \ - patch_reg((address)&insn, 7, Rd); \ - patch_reg((address)&insn, 15, Rs1); \ - patch_reg((address)&insn, 20, Rs2); \ - emit(insn); \ +// ========================== +// Floating Point Instructions +// ========================== + static constexpr uint32_t OP_FP_MAJOR = 0b1010011; + + enum FmtPrecision : uint8_t { + S_32_sp = 0b00, + D_64_dp = 0b01, + H_16_hp = 0b10, + Q_128_qp = 0b11 + }; + + private: + + template + void fp_base(uint8_t Rd, uint8_t Rs1, uint8_t Rs2, RoundingMode rm) { + assert(Fmt != H_16_hp || UseZfh || UseZfhmin, "No half precision enabled"); + assert_cond(Fmt != Q_128_qp); + guarantee(is_uimm3(rm), "Rounding mode is out of validity"); + guarantee(is_uimm2(Fmt), "FMT is out of validity"); + guarantee(is_uimm5(funct5), "Funct5 is out of validity"); + uint32_t insn = 0; + patch((address)&insn, 6, 0, OP_FP_MAJOR); + patch((address)&insn, 11, 7, Rd); + patch((address)&insn, 14, 12, rm); + patch((address)&insn, 19, 15, Rs1); + patch((address)&insn, 24, 20, Rs2); + patch((address)&insn, 26, 25, Fmt); + patch((address)&insn, 31, 27, funct5); + emit(insn); } - INSN(feq_s, 0b1010011, 0b010, 0b1010000); - INSN(flt_s, 0b1010011, 0b001, 0b1010000); - INSN(fle_s, 0b1010011, 0b000, 0b1010000); - INSN(feq_d, 0b1010011, 0b010, 0b1010001); - INSN(fle_d, 0b1010011, 0b000, 0b1010001); - INSN(flt_d, 0b1010011, 0b001, 0b1010001); -#undef INSN + template + void fp_base(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm) { + fp_base(Rd->raw_encoding(), Rs1->raw_encoding(), Rs2->raw_encoding(), (RoundingMode)rm); + } -// Float and Double Arith Instruction -#define INSN(NAME, op, funct7) \ - void NAME(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, rm); \ - patch((address)&insn, 31, 25, funct7); \ - patch_reg((address)&insn, 7, Rd); \ - patch_reg((address)&insn, 15, Rs1); \ - patch_reg((address)&insn, 20, Rs2); \ - emit(insn); \ + template + void fp_base(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, int8_t rm) { + fp_base(Rd->raw_encoding(), Rs1->raw_encoding(), Rs2->raw_encoding(), (RoundingMode)rm); } - INSN(fadd_s, 0b1010011, 0b0000000); - INSN(fsub_s, 0b1010011, 0b0000100); - INSN(fmul_s, 0b1010011, 0b0001000); - INSN(fdiv_s, 0b1010011, 0b0001100); - INSN(fadd_d, 0b1010011, 0b0000001); - INSN(fsub_d, 0b1010011, 0b0000101); - INSN(fmul_d, 0b1010011, 0b0001001); - INSN(fdiv_d, 0b1010011, 0b0001101); + template + void fp_base(Register Rd, FloatRegister Rs1, FloatRegister Rs2, int8_t rm) { + fp_base(Rd->raw_encoding(), Rs1->raw_encoding(), Rs2->raw_encoding(), (RoundingMode)rm); + } -#undef INSN + template + void fp_base(FloatRegister Rd, FloatRegister Rs1, int Rs2, int8_t rm) { + guarantee(is_uimm5(Rs2), "Rs2 is out of validity"); + fp_base(Rd->raw_encoding(), Rs1->raw_encoding(), Rs2, (RoundingMode)rm); + } -// Whole Float and Double Conversion Instruction -#define INSN(NAME, op, funct5, funct7) \ - void NAME(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, rm); \ - patch((address)&insn, 24, 20, funct5); \ - patch((address)&insn, 31, 25, funct7); \ - patch_reg((address)&insn, 7, Rd); \ - patch_reg((address)&insn, 15, Rs1); \ - emit(insn); \ + template + void fp_base(FloatRegister Rd, Register Rs1, FloatRegister Rs2, RoundingMode rm) { + fp_base(Rd->raw_encoding(), Rs1->raw_encoding(), Rs2->raw_encoding(), rm); } - INSN(fcvt_s_w, 0b1010011, 0b00000, 0b1101000); - INSN(fcvt_s_wu, 0b1010011, 0b00001, 0b1101000); - INSN(fcvt_s_l, 0b1010011, 0b00010, 0b1101000); - INSN(fcvt_s_lu, 0b1010011, 0b00011, 0b1101000); - INSN(fcvt_d_w, 0b1010011, 0b00000, 0b1101001); - INSN(fcvt_d_wu, 0b1010011, 0b00001, 0b1101001); - INSN(fcvt_d_l, 0b1010011, 0b00010, 0b1101001); - INSN(fcvt_d_lu, 0b1010011, 0b00011, 0b1101001); + template + void fp_base(Register Rd, FloatRegister Rs1, uint8_t Rs2, RoundingMode rm) { + guarantee(is_uimm5(Rs2), "Rs2 is out of validity"); + fp_base(Rd->raw_encoding(), Rs1->raw_encoding(), Rs2, rm); + } -#undef INSN + template + void fp_base(Register Rd, FloatRegister Rs1, uint8_t Rs2, uint8_t rm) { + guarantee(is_uimm5(Rs2), "Rs2 is out of validity"); + fp_base(Rd->raw_encoding(), Rs1->raw_encoding(), Rs2, (RoundingMode)rm); + } -// Float and Double Conversion Instruction -#define INSN(NAME, op, funct5, funct7) \ - void NAME(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, rm); \ - patch((address)&insn, 24, 20, funct5); \ - patch((address)&insn, 31, 25, funct7); \ - patch_reg((address)&insn, 7, Rd); \ - patch_reg((address)&insn, 15, Rs1); \ - emit(insn); \ + template + void fp_base(FloatRegister Rd, Register Rs1, uint8_t Rs2, RoundingMode rm) { + guarantee(is_uimm5(Rs2), "Rs2 is out of validity"); + fp_base(Rd->raw_encoding(), Rs1->raw_encoding(), Rs2, rm); } - INSN(fcvt_w_s, 0b1010011, 0b00000, 0b1100000); - INSN(fcvt_l_s, 0b1010011, 0b00010, 0b1100000); - INSN(fcvt_wu_s, 0b1010011, 0b00001, 0b1100000); - INSN(fcvt_lu_s, 0b1010011, 0b00011, 0b1100000); - INSN(fcvt_w_d, 0b1010011, 0b00000, 0b1100001); - INSN(fcvt_wu_d, 0b1010011, 0b00001, 0b1100001); - INSN(fcvt_l_d, 0b1010011, 0b00010, 0b1100001); - INSN(fcvt_lu_d, 0b1010011, 0b00011, 0b1100001); - -#undef INSN - -// Float and Double Move Instruction -#define INSN(NAME, op, funct3, funct5, funct7) \ - void NAME(FloatRegister Rd, Register Rs1) { \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, funct3); \ - patch((address)&insn, 20, funct5); \ - patch((address)&insn, 31, 25, funct7); \ - patch_reg((address)&insn, 7, Rd); \ - patch_reg((address)&insn, 15, Rs1); \ - emit(insn); \ - } - - INSN(fmv_h_x, 0b1010011, 0b000, 0b00000, 0b1111010); - INSN(fmv_w_x, 0b1010011, 0b000, 0b00000, 0b1111000); - INSN(fmv_d_x, 0b1010011, 0b000, 0b00000, 0b1111001); - -#undef INSN - -enum fclass_mask { - minf = 1 << 0, // negative infinite - mnorm = 1 << 1, // negative normal number - msubnorm = 1 << 2, // negative subnormal number - mzero = 1 << 3, // negative zero - pzero = 1 << 4, // positive zero - psubnorm = 1 << 5, // positive subnormal number - pnorm = 1 << 6, // positive normal number - pinf = 1 << 7, // positive infinite - snan = 1 << 8, // signaling NaN - qnan = 1 << 9, // quiet NaN - zero = mzero | pzero, - subnorm = msubnorm | psubnorm, - norm = mnorm | pnorm, - inf = minf | pinf, - nan = snan | qnan, - finite = zero | subnorm | norm, -}; + template + void fp_base(FloatRegister Rd, Register Rs1, uint8_t Rs2, int8_t rm) { + guarantee(is_uimm5(Rs2), "Rs2 is out of validity"); + fp_base(Rd->raw_encoding(), Rs1->raw_encoding(), Rs2, (RoundingMode)rm); + } + + public: + + enum FClassBit { + minf = 1 << 0, // negative infinite + mnorm = 1 << 1, // negative normal number + msubnorm = 1 << 2, // negative subnormal number + mzero = 1 << 3, // negative zero + pzero = 1 << 4, // positive zero + psubnorm = 1 << 5, // positive subnormal number + pnorm = 1 << 6, // positive normal number + pinf = 1 << 7, // positive infinite + snan = 1 << 8, // signaling NaN + qnan = 1 << 9, // quiet NaN + zero = mzero | pzero, + subnorm = msubnorm | psubnorm, + norm = mnorm | pnorm, + inf = minf | pinf, + nan = snan | qnan, + finite = zero | subnorm | norm, + }; + + void fsqrt_s(FloatRegister Rd, FloatRegister Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00000, rm); + } -// Float and Double Conversion/Classify Instruction -#define INSN(NAME, op, funct3, funct5, funct7) \ - void NAME(Register Rd, FloatRegister Rs1) { \ - unsigned insn = 0; \ - patch((address)&insn, 6, 0, op); \ - patch((address)&insn, 14, 12, funct3); \ - patch((address)&insn, 20, funct5); \ - patch((address)&insn, 31, 25, funct7); \ - patch_reg((address)&insn, 7, Rd); \ - patch_reg((address)&insn, 15, Rs1); \ - emit(insn); \ + void fsqrt_d(FloatRegister Rd, FloatRegister Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00000, rm); } - INSN(fclass_h, 0b1010011, 0b001, 0b00000, 0b1110010); - INSN(fclass_s, 0b1010011, 0b001, 0b00000, 0b1110000); - INSN(fclass_d, 0b1010011, 0b001, 0b00000, 0b1110001); - INSN(fmv_x_h, 0b1010011, 0b000, 0b00000, 0b1110010); - INSN(fmv_x_w, 0b1010011, 0b000, 0b00000, 0b1110000); - INSN(fmv_x_d, 0b1010011, 0b000, 0b00000, 0b1110001); + void fcvt_s_d(FloatRegister Rd, FloatRegister Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00001, rm); + } -#undef INSN + void fcvt_d_s(FloatRegister Rd, FloatRegister Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00000, rm); + } + + void fsgnj_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b000); + } + + void fsgnjn_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b001); + } + + void fsgnjx_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b010); + } + + void fmin_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b000); + } + + void fmax_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b001); + } + + void fsgnj_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b000); + } + + void fsgnjn_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b001); + } + + void fsgnjx_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b010); + } + + void fmin_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b000); + } + + void fmax_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b001); + } + + void feq_s(Register Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b010); + } + + void flt_s(Register Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b001); + } + + void fle_s(Register Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b000); + } + + void feq_d(Register Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b010); + } + + void fle_d(Register Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b000); + } + + void flt_d(Register Rd, FloatRegister Rs1, FloatRegister Rs2) { + fp_base(Rd, Rs1, Rs2, 0b001); + } + + void fadd_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { + fp_base(Rd, Rs1, Rs2, rm); + } + + void fsub_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { + fp_base(Rd, Rs1, Rs2, rm); + } + + void fmul_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { + fp_base(Rd, Rs1, Rs2, rm); + } + + void fdiv_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { + fp_base(Rd, Rs1, Rs2, rm); + } + + void fadd_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { + fp_base(Rd, Rs1, Rs2, rm); + } + + void fsub_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { + fp_base(Rd, Rs1, Rs2, rm); + } + + void fmul_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { + fp_base(Rd, Rs1, Rs2, rm); + } + + void fdiv_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, RoundingMode rm = rne) { + fp_base(Rd, Rs1, Rs2, rm); + } + + void fcvt_s_w(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00000, rm); + } + + void fcvt_s_wu(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00001, rm); + } + + void fcvt_s_l(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00010, rm); + } + + void fcvt_s_lu(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00011, rm); + } + + void fcvt_d_w(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00000, rm); + } + + void fcvt_d_wu(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00001, rm); + } + + void fcvt_d_l(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00010, rm); + } + + void fcvt_d_lu(FloatRegister Rd, Register Rs1, RoundingMode rm = rne) { + fp_base(Rd, Rs1, 0b00011, rm); + } + + void fcvt_w_s(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { + fp_base(Rd, Rs1, 0b00000, rm); + } + + void fcvt_l_s(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { + fp_base(Rd, Rs1, 0b00010, rm); + } + + void fcvt_wu_s(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { + fp_base(Rd, Rs1, 0b00001, rm); + } + + void fcvt_lu_s(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { + fp_base(Rd, Rs1, 0b00011, rm); + } + + void fcvt_w_d(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { + fp_base(Rd, Rs1, 0b00000, rm); + } + + void fcvt_wu_d(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { + fp_base(Rd, Rs1, 0b00001, rm); + } + + void fcvt_l_d(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { + fp_base(Rd, Rs1, 0b00010, rm); + } + + void fcvt_lu_d(Register Rd, FloatRegister Rs1, RoundingMode rm = rtz) { + fp_base(Rd, Rs1, 0b00011, rm); + } + + void fmv_w_x(FloatRegister Rd, Register Rs1) { + fp_base(Rd, Rs1, 0b00000, 0b000); + } + + void fmv_d_x(FloatRegister Rd, Register Rs1) { + fp_base(Rd, Rs1, 0b00000, 0b000); + } + + void fclass_s(Register Rd, FloatRegister Rs1) { + fp_base(Rd, Rs1, 0b00000, 0b001); + } + + void fclass_d(Register Rd, FloatRegister Rs1) { + fp_base(Rd, Rs1, 0b00000, 0b001); + } + + void fmv_x_w(Register Rd, FloatRegister Rs1) { + fp_base(Rd, Rs1, 0b00000, 0b000); + } + + void fmv_x_d(Register Rd, FloatRegister Rs1) { + fp_base(Rd, Rs1, 0b00000, 0b000); + } + + private: + static constexpr unsigned int OP_LOAD_FP = 0b0000111; + + template + void fp_load(FloatRegister Rd, Register Rs, const int32_t offset) { + guarantee(is_uimm3(FpWidth), "Rounding mode is out of validity"); + guarantee(is_simm12(offset), "offset is invalid."); + unsigned insn = 0; + uint32_t val = offset & 0xfff; + patch((address)&insn, 6, 0, OP_LOAD_FP); + patch_reg((address)&insn, 7, Rd); + patch((address)&insn, 14, 12, FpWidth); + patch_reg((address)&insn, 15, Rs); + patch((address)&insn, 31, 20, val); + emit(insn); + } + + public: + + void flw(FloatRegister Rd, Register Rs, const int32_t offset) { fp_load<0b010>(Rd, Rs, offset); } + void _fld(FloatRegister Rd, Register Rs, const int32_t offset) { fp_load<0b011>(Rd, Rs, offset); } + + private: + template + void fp_fm(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm) { + assert_cond(Fmt != Q_128_qp); + guarantee(is_uimm3(rm), "Rounding mode is out of validity"); + guarantee(is_uimm2(Fmt), "FMT is out of validity"); + unsigned insn = 0; + patch((address)&insn, 6, 0, OpVal); + patch_reg((address)&insn, 7, Rd); + patch((address)&insn, 14, 12, rm); + patch_reg((address)&insn, 15, Rs1); + patch_reg((address)&insn, 20, Rs2); + patch((address)&insn, 26, 25, Fmt); + patch_reg((address)&insn, 27, Rs3); + emit(insn); + } + + public: + void fmadd_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { + fp_fm(Rd, Rs1, Rs2, Rs3, rm); + } + + void fmsub_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { + fp_fm(Rd, Rs1, Rs2, Rs3, rm); + } + + void fnmsub_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { + fp_fm(Rd, Rs1, Rs2, Rs3, rm); + } + + void fnmadd_s(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { + fp_fm(Rd, Rs1, Rs2, Rs3, rm); + } + + void fmadd_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { + fp_fm(Rd, Rs1, Rs2, Rs3, rm); + } + + void fmsub_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { + fp_fm(Rd, Rs1, Rs2, Rs3, rm); + } + + void fnmsub_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { + fp_fm(Rd, Rs1, Rs2, Rs3, rm); + } + + void fnmadd_d(FloatRegister Rd, FloatRegister Rs1, FloatRegister Rs2, FloatRegister Rs3, RoundingMode rm = rne) { + fp_fm(Rd, Rs1, Rs2, Rs3, rm); + } + +// -------------- ZFH Instruction Definitions -------------- +// Zfh Standard Extensions for Half-Precision Floating-Point + void fclass_h(Register Rd, FloatRegister Rs1) { + assert_cond(UseZfh); + fp_base(Rd, Rs1, 0b00000, 0b001); + } + +// Zfh and Zfhmin Half-Precision Floating-Point + void fcvt_s_h(FloatRegister Rd, FloatRegister Rs1, RoundingMode rm = rne) { + assert_cond(UseZfh || UseZfhmin); + fp_base(Rd, Rs1, 0b00010, rm); + } + + void fcvt_h_s(FloatRegister Rd, FloatRegister Rs1, RoundingMode rm = rne) { + assert_cond(UseZfh || UseZfhmin); + fp_base(Rd, Rs1, 0b00000, rm); + } + + void fmv_h_x(FloatRegister Rd, Register Rs1) { + assert_cond(UseZfh || UseZfhmin); + fp_base(Rd, Rs1, 0b00000, 0b000); + } + + void fmv_x_h(Register Rd, FloatRegister Rs1) { + assert_cond(UseZfh || UseZfhmin); + fp_base(Rd, Rs1, 0b00000, 0b000); + } // ========================== // RISC-V Vector Extension @@ -3381,6 +3542,7 @@ enum Nf { static bool is_simm18(int64_t x); static bool is_simm21(int64_t x); + static bool is_uimm2(uint64_t x); static bool is_uimm3(uint64_t x); static bool is_uimm5(uint64_t x); static bool is_uimm6(uint64_t x); diff --git a/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp b/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp index c51650881fc73..1f9e6df217206 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp @@ -38,6 +38,7 @@ inline bool Assembler::is_simm13(int64_t x) { return is_simm(x, 13); } inline bool Assembler::is_simm18(int64_t x) { return is_simm(x, 18); } inline bool Assembler::is_simm21(int64_t x) { return is_simm(x, 21); } +inline bool Assembler::is_uimm2(uint64_t x) { return is_uimm(x, 2); } inline bool Assembler::is_uimm3(uint64_t x) { return is_uimm(x, 3); } inline bool Assembler::is_uimm5(uint64_t x) { return is_uimm(x, 5); } inline bool Assembler::is_uimm6(uint64_t x) { return is_uimm(x, 6); } diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index d04f48713eda7..034ab5ca5d55b 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -2059,7 +2059,7 @@ void C2_MacroAssembler::minmax_fp(FloatRegister dst, FloatRegister src1, FloatRe is_double ? fclass_d(t1, src2) : fclass_s(t1, src2); orr(t0, t0, t1); - andi(t0, t0, fclass_mask::nan); // if src1 or src2 is quiet or signaling NaN then return NaN + andi(t0, t0, FClassBit::nan); // if src1 or src2 is quiet or signaling NaN then return NaN beqz(t0, Compare); is_double ? fadd_d(dst, src1, src2) : fadd_s(dst, src1, src2); @@ -2153,7 +2153,7 @@ void C2_MacroAssembler::signum_fp(FloatRegister dst, FloatRegister one, bool is_ : fclass_s(t0, dst); // check if input is -0, +0, signaling NaN or quiet NaN - andi(t0, t0, fclass_mask::zero | fclass_mask::nan); + andi(t0, t0, FClassBit::zero | FClassBit::nan); bnez(t0, done); @@ -2369,7 +2369,7 @@ void C2_MacroAssembler::signum_fp_v(VectorRegister dst, VectorRegister one, Basi // check if input is -0, +0, signaling NaN or quiet NaN vfclass_v(v0, dst); - mv(t0, fclass_mask::zero | fclass_mask::nan); + mv(t0, FClassBit::zero | FClassBit::nan); vand_vx(v0, v0, t0); vmseq_vi(v0, v0, 0); diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index 806cca16269ea..a70dedd1ef79b 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -104,6 +104,7 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseZbb, false, DIAGNOSTIC, "Use Zbb instructions") \ product(bool, UseZbs, false, DIAGNOSTIC, "Use Zbs instructions") \ product(bool, UseZfh, false, DIAGNOSTIC, "Use Zfh instructions") \ + product(bool, UseZfhmin, false, DIAGNOSTIC, "Use Zfhmin instructions") \ product(bool, UseZacas, false, EXPERIMENTAL, "Use Zacas instructions") \ product(bool, UseZcb, false, EXPERIMENTAL, "Use Zcb instructions") \ product(bool, UseZic64b, false, EXPERIMENTAL, "Use Zic64b instructions") \ diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 24504472509d1..eec46e56ac496 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -5689,7 +5689,7 @@ void MacroAssembler::FLOATCVT##_safe(Register dst, FloatRegister src, Register t fclass_##FLOATSIG(tmp, src); \ mv(dst, zr); \ /* check if src is NaN */ \ - andi(tmp, tmp, fclass_mask::nan); \ + andi(tmp, tmp, FClassBit::nan); \ bnez(tmp, done); \ FLOATCVT(dst, src); \ bind(done); \ diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index a9b48fd18c406..deb3f8f0fcff0 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1918,7 +1918,7 @@ bool Matcher::match_rule_supported(int opcode) { case Op_ConvHF2F: case Op_ConvF2HF: - return UseZfh; + return UseZfh || UseZfhmin; } return true; // Per default match rules are supported. @@ -7348,7 +7348,7 @@ instruct isInfiniteF_reg_reg(iRegINoSp dst, fRegF src) format %{ "isInfinite $dst, $src" %} ins_encode %{ __ fclass_s(as_Register($dst$$reg), as_FloatRegister($src$$reg)); - __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::fclass_mask::inf); + __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::FClassBit::inf); __ slt(as_Register($dst$$reg), zr, as_Register($dst$$reg)); %} @@ -7363,7 +7363,7 @@ instruct isInfiniteD_reg_reg(iRegINoSp dst, fRegD src) format %{ "isInfinite $dst, $src" %} ins_encode %{ __ fclass_d(as_Register($dst$$reg), as_FloatRegister($src$$reg)); - __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::fclass_mask::inf); + __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::FClassBit::inf); __ slt(as_Register($dst$$reg), zr, as_Register($dst$$reg)); %} @@ -7378,7 +7378,7 @@ instruct isFiniteF_reg_reg(iRegINoSp dst, fRegF src) format %{ "isFinite $dst, $src" %} ins_encode %{ __ fclass_s(as_Register($dst$$reg), as_FloatRegister($src$$reg)); - __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::fclass_mask::finite); + __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::FClassBit::finite); __ slt(as_Register($dst$$reg), zr, as_Register($dst$$reg)); %} @@ -7393,7 +7393,7 @@ instruct isFiniteD_reg_reg(iRegINoSp dst, fRegD src) format %{ "isFinite $dst, $src" %} ins_encode %{ __ fclass_d(as_Register($dst$$reg), as_FloatRegister($src$$reg)); - __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::fclass_mask::finite); + __ andi(as_Register($dst$$reg), as_Register($dst$$reg), Assembler::FClassBit::finite); __ slt(as_Register($dst$$reg), zr, as_Register($dst$$reg)); %} diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index 59b41892fef0c..da594eee9069d 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -115,6 +115,7 @@ class VM_Version : public Abstract_VM_Version { // Zbs Single-bit instructions // // Zfh Half-Precision Floating-Point instructions + // Zfhmin Minimal Half-Precision Floating-Point instructions // // Zicond Conditional operations // @@ -157,6 +158,7 @@ class VM_Version : public Abstract_VM_Version { decl(ext_Zbs , "Zbs" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \ decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \ decl(ext_Zfh , "Zfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \ + decl(ext_Zfhmin , "Zfhmin" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \ decl(ext_Zicsr , "Zicsr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ decl(ext_Zifencei , "Zifencei" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ decl(ext_Zic64b , "Zic64b" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \ @@ -223,6 +225,7 @@ class VM_Version : public Abstract_VM_Version { RV_ENABLE_EXTENSION(UseZbb) \ RV_ENABLE_EXTENSION(UseZbs) \ RV_ENABLE_EXTENSION(UseZcb) \ + RV_ENABLE_EXTENSION(UseZfhmin) \ RV_ENABLE_EXTENSION(UseZic64b) \ RV_ENABLE_EXTENSION(UseZicbom) \ RV_ENABLE_EXTENSION(UseZicbop) \ diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index e65254fc5718f..f0b435aa07637 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -178,6 +178,9 @@ void RiscvHwprobe::add_features_from_query_result() { if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFH)) { VM_Version::ext_Zfh.enable_feature(); } + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFHMIN)) { + VM_Version::ext_Zfhmin.enable_feature(); + } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVBC)) { VM_Version::ext_Zvbc.enable_feature(); }