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