From: Liao Shihua <shi...@iscas.ac.cn> This Patch implements the Quad-precision Float extension for RISC-V, based on Kito's work five years ago in https://github.com/riscvarchive/riscv-gcc/tree/q-ext
Co-authored-by: Kito Chen <kito.ch...@gmail.com> gcc/ChangeLog: * config/riscv/iterators.md (fsd): Add TF mode to ANYF and ANYLSF iterators. * config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): Handle __riscv_float_abi_quad. * config/riscv/riscv-d.cc (riscv_d_handle_target_float_abi): Handle "quad" float abi. * config/riscv/riscv-ext.def: Define 'q' extension. * config/riscv/riscv-ext.opt: * config/riscv/riscv-opts.h (enum riscv_abi_type): Add ABI_ILP32Q and ABI_LP64Q. * config/riscv/riscv-protos.h (riscv_split_64bit_move_p): Rename to riscv_split_move_p. * config/riscv/riscv.cc (riscv_load_store_insns): Use riscv_split_move_p. (riscv_subword): Fix the calculation of BYTE. (riscv_split_64bit_move_p): Rename to riscv_split_move_p, and handle TF mode. (riscv_split_move_p): (riscv_output_move): Handle TF mode in move instructions. (riscv_emit_float_compare): Handle TF mode in float compare. (riscv_for_each_saved_reg): Handle TF mode in saved FPRs. * config/riscv/riscv.h (UNITS_PER_FP_REG): Add support for TF mode. (UNITS_PER_FP_ARG): Add support for TF mode. * config/riscv/riscv.md (trunctfsf2): New pattern for truncating TF to SF. (trunctfdf2): New pattern for truncating TF to DF. (extendsftf2): New pattern for extending SF to TF. (extenddftf2): New pattern for extending DF to TF. (movtf): New expand for TF move. (*movtf_hardfloat_rv64): New insn for TF move in RV64. * config/riscv/riscv.opt: Add ABI_ILP32Q and ABI_LP64Q. * doc/riscv-ext.texi: gcc/testsuite/ChangeLog: * gcc.target/riscv/arch-rvq.c: New test. * gcc.target/riscv/attribute-rvq.c: New test. * gcc.target/riscv/long-double-1.c: New test. * gcc.target/riscv/predef-rvq.c: New test. --- gcc/config/riscv/iterators.md | 12 ++-- gcc/config/riscv/riscv-c.cc | 5 ++ gcc/config/riscv/riscv-d.cc | 5 ++ gcc/config/riscv/riscv-ext.def | 15 +++++ gcc/config/riscv/riscv-ext.opt | 2 + gcc/config/riscv/riscv-opts.h | 4 +- gcc/config/riscv/riscv-protos.h | 2 +- gcc/config/riscv/riscv.cc | 42 +++++++++--- gcc/config/riscv/riscv.h | 13 ++-- gcc/config/riscv/riscv.md | 67 ++++++++++++++++++- gcc/config/riscv/riscv.opt | 6 ++ gcc/doc/riscv-ext.texi | 4 ++ gcc/testsuite/gcc.target/riscv/arch-rvq.c | 6 ++ .../gcc.target/riscv/attribute-rvq.c | 8 +++ .../gcc.target/riscv/long-double-1.c | 16 +++++ gcc/testsuite/gcc.target/riscv/predef-rvq.c | 34 ++++++++++ 16 files changed, 217 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/arch-rvq.c create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-rvq.c create mode 100644 gcc/testsuite/gcc.target/riscv/long-double-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/predef-rvq.c diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index d300224150..8abfe96785 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -107,12 +107,14 @@ ;; Iterator for hardware-supported floating-point modes. (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT || TARGET_ZFINX") (DF "TARGET_DOUBLE_FLOAT || TARGET_ZDINX") - (HF "TARGET_ZFH || TARGET_ZHINX")]) + (HF "TARGET_ZFH || TARGET_ZHINX") + (TF "TARGET_QUAD_FLOAT")]) ;; Iterator for hardware-supported load/store floating-point modes. (define_mode_iterator ANYLSF [(SF "TARGET_HARD_FLOAT || TARGET_ZFINX") (DF "TARGET_DOUBLE_FLOAT || TARGET_ZDINX") - (HF "TARGET_ZFHMIN || TARGET_ZHINXMIN")]) + (HF "TARGET_ZFHMIN || TARGET_ZHINXMIN") + (TF "TARGET_QUAD_FLOAT")]) ;; Iterator for floating-point modes that can be loaded into X registers. (define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")]) @@ -143,7 +145,7 @@ (define_mode_attr softload [(HF "lh") (SF "lw") (DF "ld")]) ;; Instruction names for stores. -(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (HF "fsh") (SF "fsw") (DF "fsd")]) +(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (HF "fsh") (SF "fsw") (DF "fsd") (TF "flq")]) ;; Instruction names for FP stores from integer registers. (define_mode_attr softstore [(HF "sh") (SF "sw") (DF "sd")]) @@ -153,7 +155,7 @@ (define_mode_attr reg [(SI "d") (DI "d") (CC "d")]) ;; This attribute gives the format suffix for floating-point operations. -(define_mode_attr fmt [(HF "h") (SF "s") (DF "d")]) +(define_mode_attr fmt [(HF "h") (SF "s") (DF "d") (TF "q")]) ;; This attribute gives the integer suffix for floating-point conversions. (define_mode_attr ifmt [(SI "w") (DI "l")]) @@ -166,7 +168,7 @@ ;; This attribute gives the upper-case mode name for one unit of a ;; floating-point mode. -(define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF")]) +(define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF") (TF "TF")]) ;; This attribute gives the integer mode that has half the size of ;; the controlling mode. diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc index 4fc0528178..28c8e8622d 100644 --- a/gcc/config/riscv/riscv-c.cc +++ b/gcc/config/riscv/riscv-c.cc @@ -95,6 +95,11 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) case ABI_LP64D: builtin_define ("__riscv_float_abi_double"); break; + + case ABI_ILP32Q: + case ABI_LP64Q: + builtin_define ("__riscv_float_abi_quad"); + break; } switch (riscv_cmodel) diff --git a/gcc/config/riscv/riscv-d.cc b/gcc/config/riscv/riscv-d.cc index 9cce48d8ff..0fd7f47589 100644 --- a/gcc/config/riscv/riscv-d.cc +++ b/gcc/config/riscv/riscv-d.cc @@ -66,6 +66,11 @@ riscv_d_handle_target_float_abi (void) case ABI_LP64D: abi = "double"; break; + + case ABI_ILP32Q: + case ABI_LP64Q: + abi = "quad"; + break; default: abi = ""; diff --git a/gcc/config/riscv/riscv-ext.def b/gcc/config/riscv/riscv-ext.def index d162fa47ef..dde30709b3 100644 --- a/gcc/config/riscv/riscv-ext.def +++ b/gcc/config/riscv/riscv-ext.def @@ -157,6 +157,21 @@ DEFINE_RISCV_EXT( /* BITMASK_BIT_POSITION*/ 3, /* EXTRA_EXTENSION_FLAGS */ 0) +DEFINE_RISCV_EXT( + /* NAME */ q, + /* UPPERCASE_NAME */ QUAD_FLOAT, + /* FULL_NAME */ "Quad-precision floating-point extension", + /* DESC */ "", + /* URL */ , + /* DEP_EXTS */ ({"d", "zicsr"}), + /* SUPPORTED_VERSIONS */ ({{2, 2, ISA_SPEC_CLASS_20191213}, + {2, 2, ISA_SPEC_CLASS_20190608}, + {2, 0, ISA_SPEC_CLASS_2P2}}), + /* FLAG_GROUP */ base, + /* BITMASK_GROUP_ID */ 0, + /* BITMASK_BIT_POSITION*/ 16, + /* EXTRA_EXTENSION_FLAGS */ 0) + DEFINE_RISCV_EXT( /* NAME */ c, /* UPPERCASE_NAME */ RVC, diff --git a/gcc/config/riscv/riscv-ext.opt b/gcc/config/riscv/riscv-ext.opt index 2036c16498..4627ce202f 100644 --- a/gcc/config/riscv/riscv-ext.opt +++ b/gcc/config/riscv/riscv-ext.opt @@ -115,6 +115,8 @@ Mask(HARD_FLOAT) Var(riscv_base_subext) Mask(DOUBLE_FLOAT) Var(riscv_base_subext) +Mask(QUAD_FLOAT) Var(riscv_base_subext) + Mask(RVC) Var(riscv_base_subext) Mask(RVB) Var(riscv_base_subext) diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h index 4e4e9d8930..372a513c3e 100644 --- a/gcc/config/riscv/riscv-opts.h +++ b/gcc/config/riscv/riscv-opts.h @@ -26,10 +26,12 @@ enum riscv_abi_type { ABI_ILP32E, ABI_ILP32F, ABI_ILP32D, + ABI_ILP32Q, ABI_LP64, ABI_LP64E, ABI_LP64F, - ABI_LP64D + ABI_LP64D, + ABI_LP64Q }; extern enum riscv_abi_type riscv_abi; diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 46b256d635..5bb1d81006 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -122,7 +122,7 @@ extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type); extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT, machine_mode); extern bool riscv_legitimize_move (machine_mode, rtx, rtx); extern rtx riscv_subword (rtx, bool); -extern bool riscv_split_64bit_move_p (rtx, rtx); +extern bool riscv_split_move_p (rtx, rtx); extern void riscv_split_doubleword_move (rtx, rtx); extern const char *riscv_output_move (rtx, rtx); extern const char *riscv_output_return (); diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 07d40f459e..82cc6ad8d9 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -2661,7 +2661,7 @@ riscv_load_store_insns (rtx mem, rtx_insn *insn) else if (GET_MODE_BITSIZE (mode).to_constant () == 64) { set = single_set (insn); - if (set && !riscv_split_64bit_move_p (SET_DEST (set), SET_SRC (set))) + if (set && !riscv_split_move_p (SET_DEST (set), SET_SRC (set))) might_split_p = false; } @@ -4721,12 +4721,14 @@ riscv_noce_conversion_profitable_p (rtx_insn *seq, rtx riscv_subword (rtx op, bool high_p) { - unsigned int byte = (high_p != BYTES_BIG_ENDIAN) ? UNITS_PER_WORD : 0; + unsigned int byte; machine_mode mode = GET_MODE (op); if (mode == VOIDmode) mode = TARGET_64BIT ? TImode : DImode; + byte = high_p ? (GET_MODE_SIZE (mode).to_constant () / 2 ) : 0; + if (MEM_P (op)) return adjust_address (op, word_mode, byte); @@ -4736,12 +4738,14 @@ riscv_subword (rtx op, bool high_p) return simplify_gen_subreg (word_mode, op, mode, byte); } -/* Return true if a 64-bit move from SRC to DEST should be split into two. */ +/* Return true if move from SRC to DEST should be split into two. */ bool -riscv_split_64bit_move_p (rtx dest, rtx src) +riscv_split_move_p (rtx dest, rtx src) { - if (TARGET_64BIT) + machine_mode mode = GET_MODE (dest); + + if (GET_MODE_SIZE (mode).to_constant () <= UNITS_PER_WORD) return false; /* Zilsd provides load/store with even-odd register pair. */ @@ -4763,7 +4767,7 @@ riscv_split_64bit_move_p (rtx dest, rtx src) /* Allow FPR <-> FPR and FPR <-> MEM moves, and permit the special case of zeroing an FPR with FCVT.D.W. */ - if (TARGET_DOUBLE_FLOAT + if (GET_MODE_SIZE (mode).to_constant () <= UNITS_PER_FP_REG && ((FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) || (FP_REG_RTX_P (dest) && MEM_P (src)) || (FP_REG_RTX_P (src) && MEM_P (dest)) @@ -4774,7 +4778,7 @@ riscv_split_64bit_move_p (rtx dest, rtx src) } /* Split a doubleword move from SRC to DEST. On 32-bit targets, - this function handles 64-bit moves for which riscv_split_64bit_move_p + this function handles 64-bit moves for which riscv_split_move_p holds. For 64-bit targets, this function handles 128-bit moves. */ void @@ -4876,7 +4880,7 @@ riscv_output_move (rtx dest, rtx src) dbl_p = (GET_MODE_SIZE (mode).to_constant () == 8); width = GET_MODE_SIZE (mode).to_constant (); - if (dbl_p && riscv_split_64bit_move_p (dest, src)) + if (dbl_p && riscv_split_move_p (dest, src)) return "#"; if (dest_code == REG && GP_REG_P (REGNO (dest))) @@ -4893,6 +4897,8 @@ riscv_output_move (rtx dest, rtx src) return "fmv.x.s\t%0,%1"; case 8: return "fmv.x.d\t%0,%1"; + case 16: + return "fmv.x.q\t%0,%1"; } if (src_code == MEM) @@ -4954,6 +4960,13 @@ riscv_output_move (rtx dest, rtx src) /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */ gcc_assert (src == CONST0_RTX (mode)); return "fcvt.d.w\t%0,x0"; + case 16: + gcc_assert (src == CONST0_RTX (mode)); + /* In RV64, we can emulate fmv.q.x %0, x0 using fcvt.d.x. */ + if(TARGET_64BIT) + return "fmv.d.x\t%0,x0"; + /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */ + return "fcvt.d.w\t%0,x0"; } } if (dest_code == MEM) @@ -4978,6 +4991,8 @@ riscv_output_move (rtx dest, rtx src) return "fmv.s\t%0,%1"; case 8: return "fmv.d\t%0,%1"; + case 16: + return "fmv.q\t%0,%1"; } if (dest_code == MEM) @@ -4989,6 +5004,8 @@ riscv_output_move (rtx dest, rtx src) return "fsw\t%1,%0"; case 8: return "fsd\t%1,%0"; + case 16: + return "fsq\t%1,%0"; } } if (dest_code == REG && FP_REG_P (REGNO (dest))) @@ -5002,6 +5019,8 @@ riscv_output_move (rtx dest, rtx src) return "flw\t%0,%1"; case 8: return "fld\t%0,%1"; + case 16: + return "flq\t%0,%1"; } if (src_code == CONST_DOUBLE && satisfies_constraint_zfli (src)) @@ -5339,6 +5358,10 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1, emit_insn (gen_f##CMP##_quiethfdi4 (*op0, cmp_op0, cmp_op1)); \ else if (GET_MODE (cmp_op0) == HFmode) \ emit_insn (gen_f##CMP##_quiethfsi4 (*op0, cmp_op0, cmp_op1)); \ + else if (GET_MODE (cmp_op0) == TFmode && TARGET_64BIT) \ + emit_insn (gen_f##CMP##_quiettfdi4 (*op0, cmp_op0, cmp_op1)); \ + else if (GET_MODE (cmp_op0) == TFmode) \ + emit_insn (gen_f##CMP##_quiettfsi4 (*op0, cmp_op0, cmp_op1)); \ else \ gcc_unreachable (); \ *op1 = const0_rtx; \ @@ -8526,7 +8549,8 @@ riscv_for_each_saved_reg (poly_int64 sp_offset, riscv_save_restore_fn fn, if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) { bool handle_reg = !cfun->machine->reg_is_wrapped_separately[regno]; - machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode; + machine_mode mode = TARGET_QUAD_FLOAT ? TFmode : + TARGET_DOUBLE_FLOAT ? DFmode : SFmode; unsigned int slot = (riscv_use_multi_push (&cfun->machine->frame)) ? CALLEE_SAVED_FREG_NUMBER (regno) : num_masked_fp; diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 9146571908..c46315a62e 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -173,17 +173,16 @@ ARCH_UNSET_CLEANUP_SPECS \ #undef TARGET_MIN_ARITHMETIC_PRECISION #define TARGET_MIN_ARITHMETIC_PRECISION riscv_min_arithmetic_precision -/* The `Q' extension is not yet supported. */ -#define UNITS_PER_FP_REG (TARGET_DOUBLE_FLOAT ? 8 : 4) +#define UNITS_PER_FP_REG (TARGET_QUAD_FLOAT ? 16 : TARGET_DOUBLE_FLOAT ? 8 : 4) /* Size per vector register. For VLEN = 32, size = poly (4, 4). Otherwise, size = poly (8, 8). */ #define UNITS_PER_V_REG (riscv_vector_chunks * riscv_bytes_per_vector_chunk) /* The largest type that can be passed in floating-point registers. */ -#define UNITS_PER_FP_ARG \ - ((riscv_abi == ABI_ILP32 || riscv_abi == ABI_ILP32E \ - || riscv_abi == ABI_LP64 || riscv_abi == ABI_LP64E) \ - ? 0 \ - : ((riscv_abi == ABI_ILP32F || riscv_abi == ABI_LP64F) ? 4 : 8)) +#define UNITS_PER_FP_ARG \ + (riscv_abi == ABI_ILP32 || riscv_abi == ABI_LP64 ? 0 : \ + riscv_abi == ABI_ILP32E || riscv_abi == ABI_LP64E ? 0 : \ + riscv_abi == ABI_ILP32F || riscv_abi == ABI_LP64F ? 4 : \ + riscv_abi == ABI_ILP32D || riscv_abi == ABI_LP64D ? 8 : 16) /* Set the sizes of the core types. */ #define SHORT_TYPE_SIZE 16 diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 2a3a20e122..c1b4dd7be6 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1874,6 +1874,22 @@ [(set_attr "type" "fcvt") (set_attr "mode" "BF")]) +(define_insn "trunctfsf2" + [(set (match_operand:SF 0 "register_operand" "=f") + (float_truncate:SF (match_operand:TF 1 "register_operand" "f")))] + "TARGET_QUAD_FLOAT" + "fcvt.s.q\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "SF")]) + +(define_insn "trunctfdf2" + [(set (match_operand:DF 0 "register_operand" "=f") + (float_truncate:DF (match_operand:TF 1 "register_operand" "f")))] + "TARGET_QUAD_FLOAT" + "fcvt.d.q\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "DF")]) + ;; The conversion of HF/DF/TF to BF needs to be done with SF if there is a ;; chance to generate at least one instruction, otherwise just using ;; libfunc __trunc[h|d|t]fbf2. @@ -2086,6 +2102,22 @@ [(set_attr "type" "fcvt") (set_attr "mode" "DF")]) +(define_insn "extendsftf2" + [(set (match_operand:TF 0 "register_operand" "=f") + (float_extend:TF (match_operand:SF 1 "register_operand" "f")))] + "TARGET_QUAD_FLOAT" + "fcvt.q.s\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "TF")]) + +(define_insn "extenddftf2" + [(set (match_operand:TF 0 "register_operand" "=f") + (float_extend:TF (match_operand:DF 1 "register_operand" "f")))] + "TARGET_QUAD_FLOAT" + "fcvt.q.d\t%0,%1" + [(set_attr "type" "fcvt") + (set_attr "mode" "TF")]) + ;; 16-bit floating point moves (define_expand "mov<mode>" [(set (match_operand:HFBF 0 "") @@ -2792,7 +2824,40 @@ [(set (match_operand:MOVE64 0 "nonimmediate_operand") (match_operand:MOVE64 1 "move_operand"))] "reload_completed - && riscv_split_64bit_move_p (operands[0], operands[1])" + && riscv_split_move_p (operands[0], operands[1])" + [(const_int 0)] +{ + riscv_split_doubleword_move (operands[0], operands[1]); + DONE; +}) + +;; 128-bit floating point moves +(define_expand "movtf" + [(set (match_operand:TF 0 "") + (match_operand:TF 1 ""))] + "TARGET_QUAD_FLOAT" +{ + if (riscv_legitimize_move (TFmode, operands[0], operands[1])) + DONE; +}) + +;; In RV64, we lack fmv.x.q and fmv.q.x. Go through memory instead. +;; (However, we can still use fcvt.q.w to zero a floating-point register.) +(define_insn "*movtf_hardfloat_rv64" + [(set (match_operand:TF 0 "nonimmediate_operand" "=f,f,f,m,m, *r,*r,*m") + (match_operand:TF 1 "move_operand" " f,G,m,f,G,*r*G,*m,*r"))] + "TARGET_64BIT && TARGET_QUAD_FLOAT + && (register_operand (operands[0], TFmode) + || reg_or_0_operand (operands[1], TFmode))" + { return riscv_output_move (operands[0], operands[1]); } + [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,move,load,store") + (set_attr "mode" "TF")]) + +(define_split + [(set (match_operand:TF 0 "nonimmediate_operand") + (match_operand:TF 1 "move_operand"))] + "reload_completed + && riscv_split_move_p (operands[0], operands[1])" [(const_int 0)] { riscv_split_doubleword_move (operands[0], operands[1]); diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt index 6543fd1c4a..a6c97589a1 100644 --- a/gcc/config/riscv/riscv.opt +++ b/gcc/config/riscv/riscv.opt @@ -61,6 +61,9 @@ Enum(abi_type) String(ilp32f) Value(ABI_ILP32F) EnumValue Enum(abi_type) String(ilp32d) Value(ABI_ILP32D) +EnumValue +Enum(abi_type) String(ilp32q) Value(ABI_ILP32Q) + EnumValue Enum(abi_type) String(lp64) Value(ABI_LP64) @@ -73,6 +76,9 @@ Enum(abi_type) String(lp64f) Value(ABI_LP64F) EnumValue Enum(abi_type) String(lp64d) Value(ABI_LP64D) +EnumValue +Enum(abi_type) String(lp64q) Value(ABI_LP64Q) + mfdiv Target Mask(FDIV) Use hardware floating-point divide and square root instructions. diff --git a/gcc/doc/riscv-ext.texi b/gcc/doc/riscv-ext.texi index 13056e73ba..29daa89f40 100644 --- a/gcc/doc/riscv-ext.texi +++ b/gcc/doc/riscv-ext.texi @@ -42,6 +42,10 @@ @tab 2.0 2.2 @tab Double-precision floating-point extension +@item q +@tab 2.0 2.2 +@tab Quad-precision floating-point extension + @item c @tab 2.0 @tab Compressed extension diff --git a/gcc/testsuite/gcc.target/riscv/arch-rvq.c b/gcc/testsuite/gcc.target/riscv/arch-rvq.c new file mode 100644 index 0000000000..3fd9cf04d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/arch-rvq.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64i_q -mabi=lp64q" } */ +int foo() +{ +} + diff --git a/gcc/testsuite/gcc.target/riscv/attribute-rvq.c b/gcc/testsuite/gcc.target/riscv/attribute-rvq.c new file mode 100644 index 0000000000..f2a2d681eb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/attribute-rvq.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-mriscv-attribute -march=rv64iq -mabi=lp64q" } */ + +void foo(){} + +/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_f2p2_d2p2_q2p2_zicsr2p0\"" } } */ + + diff --git a/gcc/testsuite/gcc.target/riscv/long-double-1.c b/gcc/testsuite/gcc.target/riscv/long-double-1.c new file mode 100644 index 0000000000..1ee990eb44 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/long-double-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcq -mabi=lp64q -O0" } */ + +long double foo(long double a, long double b) +{ + return a + b; +} + +long double foo2(long double a, long double b) +{ + return a - b; +} + +/* { dg-final { scan-assembler-times {\mfadd\.q\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mfsub\.q\M} 1 } } */ + diff --git a/gcc/testsuite/gcc.target/riscv/predef-rvq.c b/gcc/testsuite/gcc.target/riscv/predef-rvq.c new file mode 100644 index 0000000000..24bf03045c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/predef-rvq.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64iq -mabi=lp64q" } */ + + +int main () { +#if !defined(__riscv) +#error "__riscv" +#endif + +#if __riscv_xlen != 64 +#error "__riscv_xlen" +#endif + +#if !defined(__riscv_fdiv) +#error "__riscv_fdiv" +#endif +#if !defined(__riscv_fsqrt) +#error "__riscv_fsqrt" +#endif + +#if defined(__riscv_float_abi_soft) +#error "__riscv_float_abi_soft" +#endif +#if defined(__riscv_float_abi_single) +#error "__riscv_float_abi_single" +#endif +#if defined(__riscv_float_abi_double) +#error "__riscv_float_abi_double" +#endif +#if !defined(__riscv_float_abi_quad) +#error "__riscv_float_abi_double" +#endif + return 0; +} -- 2.51.0