@@ -219,16 +219,16 @@
(eq_attr "type" "fabs,fneg,fmove"))
"i6400_fpu_short, i6400_fpu_apu")
-;; min, max
+;; min, max, fclass
(define_insn_reservation "i6400_fpu_minmax" 2
(and (eq_attr "cpu" "i6400")
- (eq_attr "type" "fminmax"))
+ (eq_attr "type" "fminmax,fclass"))
"i6400_fpu_short+i6400_fpu_logic")
-;; fadd, fsub, fcvt
+;; fadd, fsub, fcvt, frint
(define_insn_reservation "i6400_fpu_fadd" 4
(and (eq_attr "cpu" "i6400")
- (eq_attr "type" "fadd,fcvt"))
+ (eq_attr "type" "fadd,fcvt,frint"))
"i6400_fpu_long, i6400_fpu_apu")
;; fmul
@@ -15775,6 +15775,7 @@ AVAIL_NON_MIPS16 (dspr2_32, !TARGET_64BIT && TARGET_DSPR2)
AVAIL_NON_MIPS16 (loongson, TARGET_LOONGSON_MMI)
AVAIL_MIPS16E2_OR_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN)
AVAIL_NON_MIPS16 (msa, TARGET_MSA)
+AVAIL_NON_MIPS16 (r6, mips_isa_rev >= 6)
/* Construct a mips_builtin_description from the given arguments.
@@ -15940,6 +15941,14 @@ AVAIL_NON_MIPS16 (msa, TARGET_MSA)
"__builtin_msa_" #INSN, MIPS_BUILTIN_DIRECT_NO_TARGET, \
FUNCTION_TYPE, mips_builtin_avail_msa, false }
+/* Define a MIPSr6 MIPS_BUILTIN_DIRECT pure function __builtin_mipsr6_<INSN>
+ for instruction CODE_FOR_mipsr6_<INSN>. FUNCTION_TYPE is a builtin_description
+ field. */
+#define MIPSR6_BUILTIN_PURE(INSN, FUNCTION_TYPE) \
+ { CODE_FOR_mipsr6_ ## INSN, MIPS_FP_COND_f, \
+ "__builtin_mipsr6_" #INSN, MIPS_BUILTIN_DIRECT, \
+ FUNCTION_TYPE, mips_builtin_avail_r6, true }
+
#define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2
#define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3
#define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3
@@ -16177,6 +16186,13 @@ AVAIL_NON_MIPS16 (msa, TARGET_MSA)
#define CODE_FOR_msa_ldi_w CODE_FOR_msa_ldiv4si
#define CODE_FOR_msa_ldi_d CODE_FOR_msa_ldiv2di
+#define CODE_FOR_mipsr6_min_a_s CODE_FOR_fmin_a_sf
+#define CODE_FOR_mipsr6_min_a_d CODE_FOR_fmin_a_df
+#define CODE_FOR_mipsr6_max_a_s CODE_FOR_fmax_a_sf
+#define CODE_FOR_mipsr6_max_a_d CODE_FOR_fmax_a_df
+#define CODE_FOR_mipsr6_class_s CODE_FOR_fclass_sf
+#define CODE_FOR_mipsr6_class_d CODE_FOR_fclass_df
+
static const struct mips_builtin_description mips_builtins[] = {
#define MIPS_GET_FCSR 0
DIRECT_BUILTIN (get_fcsr, MIPS_USI_FTYPE_VOID, hard_float),
@@ -16998,6 +17014,14 @@ static const struct mips_builtin_description mips_builtins[] = {
MSA_NO_TARGET_BUILTIN (ctcmsa, MIPS_VOID_FTYPE_UQI_SI),
MSA_BUILTIN_PURE (cfcmsa, MIPS_SI_FTYPE_UQI),
MSA_BUILTIN_PURE (move_v, MIPS_V16QI_FTYPE_V16QI),
+
+ /* Built-in functions for MIPSr6. */
+ MIPSR6_BUILTIN_PURE (min_a_s, MIPS_SF_FTYPE_SF_SF),
+ MIPSR6_BUILTIN_PURE (min_a_d, MIPS_DF_FTYPE_DF_DF),
+ MIPSR6_BUILTIN_PURE (max_a_s, MIPS_SF_FTYPE_SF_SF),
+ MIPSR6_BUILTIN_PURE (max_a_d, MIPS_DF_FTYPE_DF_DF),
+ MIPSR6_BUILTIN_PURE (class_s, MIPS_SF_FTYPE_SF),
+ MIPSR6_BUILTIN_PURE (class_d, MIPS_DF_FTYPE_DF),
};
/* Index I is the function declaration for mips_builtins[I], or null if the
@@ -1264,6 +1264,10 @@ struct mips_cpu_info {
#define ISA_HAS_FMIN_FMAX (mips_isa_rev >= 6)
+#define ISA_HAS_FRINT (mips_isa_rev >= 6)
+
+#define ISA_HAS_FCLASS (mips_isa_rev >= 6)
+
/* ISA has data indexed prefetch instructions. This controls use of
'prefx', along with TARGET_HARD_FLOAT and TARGET_DOUBLE_FLOAT.
(prefx is a cop1x instruction, so can only be used if FP is
@@ -100,6 +100,8 @@
;; Floating-point unspecs.
UNSPEC_FMIN
UNSPEC_FMAX
+ UNSPEC_FRINT
+ UNSPEC_FCLASS
;; HI/LO moves.
UNSPEC_MFHI
@@ -375,6 +377,8 @@
;; frsqrt1 floating point reciprocal square root step1
;; frsqrt2 floating point reciprocal square root step2
;; fminmax floating point min/max
+;; frint floating point round to integral
+;; fclass floating point class mask
;; dspmac DSP MAC instructions not saturating the accumulator
;; dspmacsat DSP MAC instructions that saturate the accumulator
;; accext DSP accumulator extract instructions
@@ -392,8 +396,8 @@
prefetch,prefetchx,condmove,mtc,mfc,mthi,mtlo,mfhi,mflo,const,arith,logical,
shift,slt,signext,clz,pop,trap,imul,imul3,imul3nc,imadd,idiv,idiv3,move,
fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,
- frsqrt,frsqrt1,frsqrt2,fminmax,dspmac,dspmacsat,accext,accmod,dspalu,
- dspalusat,multi,atomic,syncloop,nop,ghost,multimem,
+ frsqrt,frsqrt1,frsqrt2,fminmax,frint,fclass,dspmac,dspmacsat,accext,
+ accmod,dspalu,dspalusat,multi,atomic,syncloop,nop,ghost,multimem,
simd_div,simd_fclass,simd_flog2,simd_fadd,simd_fcvt,simd_fmul,simd_fmadd,
simd_fdiv,simd_bitins,simd_bitmov,simd_insert,simd_sld,simd_mul,simd_fcmp,
simd_fexp2,simd_int_arith,simd_bit,simd_shift,simd_splat,simd_fill,
@@ -8011,6 +8015,50 @@
[(set_attr "type" "fminmax")
(set_attr "mode" "<UNITMODE>")])
+(define_insn "fmin_a_<mode>"
+ [(set (match_operand:SCALARF 0 "register_operand" "=f")
+ (if_then_else
+ (lt (abs:SCALARF (match_operand:SCALARF 1 "register_operand" "f"))
+ (abs:SCALARF (match_operand:SCALARF 2 "register_operand" "f")))
+ (match_dup 1)
+ (match_dup 2)))]
+ "ISA_HAS_FMIN_FMAX"
+ "mina.<fmt>\t%0,%1,%2"
+ [(set_attr "type" "fminmax")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "fmax_a_<mode>"
+ [(set (match_operand:SCALARF 0 "register_operand" "=f")
+ (if_then_else
+ (gt (abs:SCALARF (match_operand:SCALARF 1 "register_operand" "f"))
+ (abs:SCALARF (match_operand:SCALARF 2 "register_operand" "f")))
+ (match_dup 1)
+ (match_dup 2)))]
+ "ISA_HAS_FMIN_FMAX"
+ "maxa.<fmt>\t%0,%1,%2"
+ [(set_attr "type" "fminmax")
+ (set_attr "mode" "<UNITMODE>")])
+
+;;Float point round to integral
+(define_insn "rint<mode>2"
+ [(set (match_operand:SCALARF 0 "register_operand" "=f")
+ (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" "f")]
+ UNSPEC_FRINT))]
+ "ISA_HAS_FRINT"
+ "rint.<fmt>\t%0,%1"
+ [(set_attr "type" "frint")
+ (set_attr "mode" "<UNITMODE>")])
+
+;;Float point class mask
+(define_insn "fclass_<mode>"
+ [(set (match_operand:SCALARF 0 "register_operand" "=f")
+ (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" "f")]
+ UNSPEC_FCLASS))]
+ "ISA_HAS_FCLASS"
+ "class.<fmt>\t%0,%1"
+ [(set_attr "type" "fclass")
+ (set_attr "mode" "<UNITMODE>")])
+
;; 2 HI loads are joined.
(define_peephole2
[(set (match_operand:SI 0 "register_operand")
@@ -161,16 +161,16 @@
;; FPU pipe
;;
-;; fadd, fsub
+;; fadd, fsub, frint
(define_insn_reservation "p6600_fpu_fadd" 4
(and (eq_attr "cpu" "p6600")
- (eq_attr "type" "fadd"))
+ (eq_attr "type" "fadd,frint"))
"p6600_fpu_long, p6600_fpu_apu")
-;; fabs, fneg, fcmp, fminmax
+;; fabs, fneg, fcmp, fminmax, fclass
(define_insn_reservation "p6600_fpu_fabs" 2
(and (eq_attr "cpu" "p6600")
- (ior (eq_attr "type" "fabs,fneg,fcmp,fmove,fminmax")
+ (ior (eq_attr "type" "fabs,fneg,fcmp,fmove,fminmax,fclass")
(and (eq_attr "type" "condmove")
(eq_attr "mode" "SF,DF"))))
"p6600_fpu_short, p6600_fpu_apu")
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-mhard-float -march=mips32r6" } */
+
+NOMIPS16 float
+test01 (float a)
+{
+ return __builtin_mipsr6_class_s (a);
+}
+
+NOMIPS16 double
+test02 (double a)
+{
+ return __builtin_mipsr6_class_d (a);
+}
+
+/* { dg-final { scan-assembler "class\\.s" } } */
+/* { dg-final { scan-assembler "class\\.d" } } */
new file mode 100644
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-mhard-float -march=mips32r6" } */
+
+NOMIPS16 float
+test01 (float a, float b)
+{
+ return __builtin_mipsr6_min_a_s (a, b);
+}
+
+NOMIPS16 double
+test02 (double a, double b)
+{
+ return __builtin_mipsr6_min_a_d (a, b);
+}
+
+NOMIPS16 float
+test03 (float a, float b)
+{
+ return __builtin_mipsr6_max_a_s (a, b);
+}
+
+NOMIPS16 double
+test04 (double a, double b)
+{
+ return __builtin_mipsr6_max_a_d (a, b);
+}
+
+/* { dg-final { scan-assembler "mina\\.s" } } */
+/* { dg-final { scan-assembler "mina\\.d" } } */
+/* { dg-final { scan-assembler "maxa\\.s" } } */
+/* { dg-final { scan-assembler "maxa\\.d" } } */
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-mhard-float -march=mips32r6" } */
+
+NOMIPS16 float
+test01 (float a)
+{
+ return __builtin_rintf (a);
+}
+
+NOMIPS16 double
+test02 (double a)
+{
+ return __builtin_rint (a);
+}
+
+/* { dg-final { scan-assembler "rint\\.s" } } */
+/* { dg-final { scan-assembler "rint\\.d" } } */