> 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

Thanks for bringing this back, I almost forgot this still has not merged yet.

> 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")])

indention

>
>  ;; 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")])

indention

>
>  ;; 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")])

Should be fsq?

also it should add flq to "define_mode_attr load"?

> 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;
> +

BYTES_BIG_ENDIAN handling is gone after this change?


>    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";

indention seems not right here

>           }
>
>        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";

indention seems not right here

>               }
>         }
>        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";

indention seems not right here

>           }
>
>        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";

indention seems not right here

>           }
>      }
>    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";

indention seems not right here

> 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" } */

Could you also add some tests for rv32gcq? IIRC q on RV32 has some
issues and I don't remember if I fixed them all at that moment.

> +
> +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 } } */

Reply via email to