Hi Carl, Sorry for the late review.
On Mon, Sep 17, 2018 at 03:03:28PM -0700, Carl Love wrote: > * config/rs6000.c (rs6000_expand_mtfsb0_mtfsb1_builtin): Add. config/rs6000/rs6000.c > +RS6000_BUILTIN_X (RS6000_BUILTIN_MTFSB0, "__builtin_mtfsb0", > + RS6000_BTM_ALWAYS, > + RS6000_BTC_MISC | RS6000_BTC_UNARY, > + CODE_FOR_rs6000_mtfsb0) I think you need RS6000_BTC_VOID on most of these calls? > static rtx > +rs6000_expand_mtfsb_builtin (enum insn_code icode, tree exp) The changelog has the function name wrong? > + pat = GEN_FCN (icode) (op0); > + if (! pat) No space after ! (or any other prefix operator that doesn't have letters in its name, i.e. casts, sizeof, etc.) > +static rtx > +rs6000_expand_set_fpscr_rn_builtin (enum insn_code icode, tree exp) > + /* 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. */ So what do we do for variable args? Mask off the bits? > +static rtx > +rs6000_expand_set_fpscr_drn_builtin (enum insn_code icode, tree exp) > + /* If the argument is a constant, check the range. Agrument can only be a > + 3-bit value. Unfortunately, can't check the range of the value at > + compile time if the argument is a variable. > + */ Don't put */ on a separate line please. > + if (GET_CODE (op0) == CONST_INT && !const_0_to_7_operand(op0, VOIDmode )) Stray space after VOIDmode. > +(define_insn "rs6000_mtfsb0" > + [(unspec_volatile [(match_operand:SI 0 "u5bit_cint_operand" "n")] > + UNSPECV_MTFSB0)] > + "TARGET_HARD_FLOAT" > + "mtfsb0 %0" > + [(set_attr "type" "fp")]) Hrm... Does all of this work with -msoft-float? Does it not ICE at least? > +(define_expand "rs6000_set_fpscr_rn" > + [(match_operand:DI 0 "gpc_reg_operand")] (Two spaces.) You could handle immediate operands separately: you need only two mtfsbN instructions for that, which is smaller and faster than the "variable" sequence. Well, for non-P9 anyway. > +(define_expand "rs6000_mffsl" > + [(set (match_operand:DF 0 "gpc_reg_operand") > + (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFSL))] > + "TARGET_HARD_FLOAT" > +{ > + /* If the low latency mffsl instruction (ISA 3.0) is available use it, > + otherwise fall back to the older mffs instruction to emulate the mffsl > + instruction. */ > + > + if (TARGET_P9_MISC) > + emit_insn (gen_rs6000_mffsl_hw (operands[0])); The indent is incorrect. But you could just not do anything if TARGET_P9_MISC: the RTL pattern above already is exactly what you need. So "if (!TARGET_P9_MISC)" and then that block with the DONE moved in there, and the TARGET_P9_MISC case can just fall through. > + emit_insn (gen_anddi3 (tmp_di, tmp_di, GEN_INT (0x70007F0FFLL))); Write numbers in lower case please (for readability). 0x70007f0ffLL > +(define_insn "rs6000_mtfsf_hi" > + [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i") const_int_operand is "n": an actual number, not e.g. a constant address (like "i" allows). It doesn't make a real difference in some cases, but it's best to get it right. > +the most significant word on 32-bit environments. The @code{__builtin_mffs} > +return the value of the FPSCR register. Note, ISA 3.0 supports the > +@code{__builtin_mffsl()} which is a lower latency version of this builtin. > The mffsl does not return the whole fpscr, just the more useful (and cheaper to access!) fields: rn and drn, the exception enables, the non-sticky exception flags. > +++ b/gcc/testsuite/gcc.target/powerpc/test_fpscr_drn_builtin.c > @@ -0,0 +1,116 @@ > +/* { dg-do run { target { powerpc*-*-linux* && lp64 } } } */ Why only linux? Okay for trunk with the nits fixed; the things that are more like extensions can happen later (if at all). Thanks! Segher