Hi!

On Thu, Sep 27, 2018 at 04:17:57PM -0700, Carl Love wrote:
> +  if (icode == CODE_FOR_rs6000_mffsl
> +      && rs6000_isa_flags_explicit & OPTION_MASK_SOFT_FLOAT)
> +    fatal_error (input_location,
> +              "__builtin_mffsl() not supported with -msoft-float");

Please use plain "error ()" instead.  To keep whatever else here from
wreaking havoc, also immediately after the error() do "return const0_rtx"?

(Same for all other fatal_error, of course.  fatal_error is for when the
compiler needs to go down ungracefully, _now_.  It is nicer to still try
to continue for a little while).

> +  /* If the argument is a constant, check the range. Argument can only be a
> +     2-bit value.  Unfortunately, can't check the range of the value at
> +     compile time if the argument is a variable.  The least significant two
> +     bits of the argument, regardless of type, are used to set the rounding
> +     mode.  All other bits are ignored.  */
> +  if (GET_CODE (op0) == CONST_INT && !const_0_to_3_operand(op0, VOIDmode))
> +    {
> +       error ("Argument must be a value between 0 and 3.");
> +       return const0_rtx;
> +    }

These are indented a char too many.

> +  if (TARGET_P9_MISC)
> +    {
> +       rtx src_df = gen_reg_rtx (DImode);
> +
> +       src_df = simplify_gen_subreg (DFmode, operands[0], DImode, 0);
> +       emit_insn (gen_rs6000_mffscrn (tmp_df, src_df));
> +    }
> +  else

This is easier if you write it like:

  if (...)
    {
      emit this;
      emit that;
      DONE;
    }

  if (...)
    {
      emit this;
      emit that;
      DONE;
    }

etc.
With that style, code that is semantically at the same level has the same
indent, instead of wandering further and further to the right.

> +     {
> +       rtx tmp_rn = gen_reg_rtx (DImode);
> +       rtx tmp_di = gen_reg_rtx (DImode);
> +
> +       /* Extract new RN mode from operand.  */
> +       emit_insn (gen_anddi3 (tmp_rn, operands[0], GEN_INT (0x3)));
> +
> +       /* Insert new RN mode into FSCPR.  */
> +       emit_insn (gen_rs6000_mffs (tmp_df));
> +       tmp_di = simplify_gen_subreg (DImode, tmp_df, DFmode, 0);
> +       emit_insn (gen_anddi3 (tmp_di, tmp_di, GEN_INT (0xFFFFFFFC)));

This loses bits 0..31 (the top half of the register).  Maybe use
GEN_INT (-4) ?

> +       emit_insn (gen_iordi3 (tmp_di, tmp_di, tmp_rn));
> +
> +       /* Need to write to field k=15.  The fields are [0:15].  Hence with
> +          L=0, W=0, FLM_i must be equal to 8, 16 = i + 8*(1-W).  FLM is an
> +          8-bit field[0:7]. Need to set the bit that corresponds to the
> +          value of i that you want [0:7].  */
> +       tmp_df = simplify_gen_subreg (DFmode, tmp_di, DImode, 0);
> +       emit_insn (gen_rs6000_mtfsf (GEN_INT (0x01), tmp_df));
> +    }

:-)

> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/test_fpscr_drn_builtin.c
> @@ -0,0 +1,116 @@
> +/* { dg-do run { target { powerpc*-*-* &&  lp64 } } } */
> +/* { dg-options "-std=c99" } */

You need to require a system that implements the DRN bits...  I think
you'll need the "dfp_hw" selector.  (That's power6 and later, may not
be so easy to test this ;-) )

> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/test_mffsl.c
> @@ -0,0 +1,34 @@
> +/* { dg-do run { target { powerpc*-*-* } } } */
> +/* { dg-options "-std=c99" } */

Maybe you should do the run tests with -O2?  Maybe compile tests, too,
come to think of it.


With those details fixed, okay for trunk.  Thanks!


Segher

Reply via email to