diff options
author | chaoyingfu <chaoyingfu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-05 00:26:14 +0000 |
---|---|---|
committer | chaoyingfu <chaoyingfu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-05 00:26:14 +0000 |
commit | 3e60fdb785b6b04cbb9ecabbe85fb022bb541c0a (patch) | |
tree | 6b8bba7d8f858fae48851ba021aa3c36731bd2e8 | |
parent | 1cdf62f185ac98275fc58ff2ee6d8c3c8ffafad3 (diff) | |
download | gcc-3e60fdb785b6b04cbb9ecabbe85fb022bb541c0a.tar.gz |
2010-11-04 Chao-ying Fu <fu@mips.com>
* configure.ac: Test assembler support for DSP Rev1 mult.
* configure: Regenerate.
* config.in: Regenerate.
* config/mips/mips.h (ISA_HAS_DSP_MULT): New define.
* config/mips/mips.c (CODE_FOR_mips_mult): New define.
(CODE_FOR_mips_multu): New define.
(mips_builtins): Move madd, maddu, msub, msubu, mult, multu from
dspr2_32 to dsp_32.
(mips_mulsidi3_gen_fn): Test (TARGET_FIX_R4000 && !ISA_HAS_DSP).
Delete returns when ISA_HAS_DSPR2, because the old patterns are deleted.
* config/mips/mips-dsp.md (mips_madd<u>, mips_msub<u>):
New define_expand patterns.
* config/mips/constraints.md (ka): Update the constraint to test
ISA_HAS_DSP_MULT instead of ISA_HAS_DSPR2.
* config/mips/mips-dspr2.md (mips_madd<u>, mips_msub<u>, mips_mult,
mips_multu): Delete.
* config/mips/mips.md (<u>mulsidi3_32bit): Add comments.
Change target constraint to "ka".
Use (!TARGET_FIX_R4000 || ISA_HAS_DSP), instead of
(!TARGET_FIX_R4000 && !ISA_HAS_DSPR2).
Emit the accumulator destination when ISA_HAS_DSP_MULT.
(<u>msubsidi4): Add comments.
Test ISA_HAS_DSP.
Emit the accumulator destination when ISA_HAS_DSP_MULT.
(<u>maddsidi4): Likewise.
* doc/extend.texi (MIPS DSP Built-in Functions): Move madd, maddu,
msub, msubu, mult, multu built-in functions from DSP r2 to DSP r1.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166344 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 30 | ||||
-rw-r--r-- | gcc/config.in | 6 | ||||
-rw-r--r-- | gcc/config/mips/constraints.md | 4 | ||||
-rw-r--r-- | gcc/config/mips/mips-dsp.md | 15 | ||||
-rw-r--r-- | gcc/config/mips/mips-dspr2.md | 36 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 18 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 7 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 31 | ||||
-rwxr-xr-x | gcc/configure | 39 | ||||
-rw-r--r-- | gcc/configure.ac | 14 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 12 |
11 files changed, 152 insertions, 60 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f0fbbf41c95..d9227714f83 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2010-11-04 Chao-ying Fu <fu@mips.com> + + * configure.ac: Test assembler support for DSP Rev1 mult. + * configure: Regenerate. + * config.in: Regenerate. + * config/mips/mips.h (ISA_HAS_DSP_MULT): New define. + * config/mips/mips.c (CODE_FOR_mips_mult): New define. + (CODE_FOR_mips_multu): New define. + (mips_builtins): Move madd, maddu, msub, msubu, mult, multu from + dspr2_32 to dsp_32. + (mips_mulsidi3_gen_fn): Test (TARGET_FIX_R4000 && !ISA_HAS_DSP). + Delete returns when ISA_HAS_DSPR2, because the old patterns are deleted. + * config/mips/mips-dsp.md (mips_madd<u>, mips_msub<u>): + New define_expand patterns. + * config/mips/constraints.md (ka): Update the constraint to test + ISA_HAS_DSP_MULT instead of ISA_HAS_DSPR2. + * config/mips/mips-dspr2.md (mips_madd<u>, mips_msub<u>, mips_mult, + mips_multu): Delete. + * config/mips/mips.md (<u>mulsidi3_32bit): Add comments. + Change target constraint to "ka". + Use (!TARGET_FIX_R4000 || ISA_HAS_DSP), instead of + (!TARGET_FIX_R4000 && !ISA_HAS_DSPR2). + Emit the accumulator destination when ISA_HAS_DSP_MULT. + (<u>msubsidi4): Add comments. + Test ISA_HAS_DSP. + Emit the accumulator destination when ISA_HAS_DSP_MULT. + (<u>maddsidi4): Likewise. + * doc/extend.texi (MIPS DSP Built-in Functions): Move madd, maddu, + msub, msubu, mult, multu built-in functions from DSP r2 to DSP r1. + 2010-11-04 Paul Koning <ni1d@arrl.net> * doc/md.texi (Machine Constraints): Add PDP-11 constraints. diff --git a/gcc/config.in b/gcc/config.in index bb8df2bd7a0..b6a95b53e19 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -229,6 +229,12 @@ #endif +/* Define if your assembler supports DSPR1 mult. */ +#ifndef USED_FOR_TARGET +#undef HAVE_AS_DSPR1_MULT +#endif + + /* Define if your assembler supports .dtprelword. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_DTPRELWORD diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md index a29d2c97696..dcffdb5aed9 100644 --- a/gcc/config/mips/constraints.md +++ b/gcc/config/mips/constraints.md @@ -86,8 +86,8 @@ ;; Registers that can be used as the target of multiply-accumulate ;; instructions. The core MIPS32 ISA provides a hi/lo madd, -;; but the DSPr2 version allows any accumulator target. -(define_register_constraint "ka" "ISA_HAS_DSPR2 ? ACC_REGS : MD_REGS") +;; but the DSP version allows any accumulator target. +(define_register_constraint "ka" "ISA_HAS_DSP_MULT ? ACC_REGS : MD_REGS") (define_constraint "kf" "@internal" diff --git a/gcc/config/mips/mips-dsp.md b/gcc/config/mips/mips-dsp.md index faa22bdd364..4f518cbc6dd 100644 --- a/gcc/config/mips/mips-dsp.md +++ b/gcc/config/mips/mips-dsp.md @@ -1181,3 +1181,18 @@ "%*bposge%1\t%0%/" [(set_attr "type" "branch")]) +(define_expand "mips_madd<u>" + [(set (match_operand:DI 0 "register_operand") + (plus:DI + (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand")) + (any_extend:DI (match_operand:SI 3 "register_operand"))) + (match_operand:DI 1 "register_operand")))] + "ISA_HAS_DSP && !TARGET_64BIT") + +(define_expand "mips_msub<u>" + [(set (match_operand:DI 0 "register_operand") + (minus:DI + (match_operand:DI 1 "register_operand") + (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand")) + (any_extend:DI (match_operand:SI 3 "register_operand")))))] + "ISA_HAS_DSP && !TARGET_64BIT") diff --git a/gcc/config/mips/mips-dspr2.md b/gcc/config/mips/mips-dspr2.md index 9c3cbd58435..3a5c7d2ce34 100644 --- a/gcc/config/mips/mips-dspr2.md +++ b/gcc/config/mips/mips-dspr2.md @@ -224,22 +224,6 @@ [(set_attr "type" "imadd") (set_attr "mode" "SI")]) -(define_expand "mips_madd<u>" - [(set (match_operand:DI 0 "register_operand") - (plus:DI - (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand")) - (any_extend:DI (match_operand:SI 3 "register_operand"))) - (match_operand:DI 1 "register_operand")))] - "ISA_HAS_DSPR2 && !TARGET_64BIT") - -(define_expand "mips_msub<u>" - [(set (match_operand:DI 0 "register_operand") - (minus:DI - (match_operand:DI 1 "register_operand") - (mult:DI (any_extend:DI (match_operand:SI 2 "register_operand")) - (any_extend:DI (match_operand:SI 3 "register_operand")))))] - "ISA_HAS_DSPR2 && !TARGET_64BIT") - (define_insn "mulv2hi3" [(parallel [(set (match_operand:V2HI 0 "register_operand" "=d") @@ -320,26 +304,6 @@ [(set_attr "type" "imadd") (set_attr "mode" "SI")]) -(define_insn "mips_mult" - [(set (match_operand:DI 0 "register_operand" "=a") - (mult:DI - (sign_extend:DI (match_operand:SI 1 "register_operand" "d")) - (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "mult\t%q0,%1,%2" - [(set_attr "type" "imul") - (set_attr "mode" "SI")]) - -(define_insn "mips_multu" - [(set (match_operand:DI 0 "register_operand" "=a") - (mult:DI - (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) - (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))] - "ISA_HAS_DSPR2 && !TARGET_64BIT" - "multu\t%q0,%1,%2" - [(set_attr "type" "imul") - (set_attr "mode" "SI")]) - (define_insn "mips_precr_qb_ph" [(set (match_operand:V4QI 0 "register_operand" "=d") (unspec:V4QI [(match_operand:V2HI 1 "reg_or_0_operand" "dYG") diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 3dfc59ed4cc..76c0786713e 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -12730,6 +12730,8 @@ AVAIL_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN) #define CODE_FOR_mips_subq_ph CODE_FOR_subv2hi3 #define CODE_FOR_mips_subu_qb CODE_FOR_subv4qi3 #define CODE_FOR_mips_mul_ph CODE_FOR_mulv2hi3 +#define CODE_FOR_mips_mult CODE_FOR_mulsidi3_32bit +#define CODE_FOR_mips_multu CODE_FOR_umulsidi3_32bit #define CODE_FOR_loongson_packsswh CODE_FOR_vec_pack_ssat_v2si #define CODE_FOR_loongson_packsshb CODE_FOR_vec_pack_ssat_v4hi @@ -12928,17 +12930,17 @@ static const struct mips_builtin_description mips_builtins[] = { DIRECT_BUILTIN (extpdp, MIPS_SI_FTYPE_DI_SI, dsp_32), DIRECT_BUILTIN (shilo, MIPS_DI_FTYPE_DI_SI, dsp_32), DIRECT_BUILTIN (mthlip, MIPS_DI_FTYPE_DI_SI, dsp_32), + DIRECT_BUILTIN (madd, MIPS_DI_FTYPE_DI_SI_SI, dsp_32), + DIRECT_BUILTIN (maddu, MIPS_DI_FTYPE_DI_USI_USI, dsp_32), + DIRECT_BUILTIN (msub, MIPS_DI_FTYPE_DI_SI_SI, dsp_32), + DIRECT_BUILTIN (msubu, MIPS_DI_FTYPE_DI_USI_USI, dsp_32), + DIRECT_BUILTIN (mult, MIPS_DI_FTYPE_SI_SI, dsp_32), + DIRECT_BUILTIN (multu, MIPS_DI_FTYPE_USI_USI, dsp_32), /* The following are for the MIPS DSP ASE REV 2 (32-bit only). */ DIRECT_BUILTIN (dpa_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32), DIRECT_BUILTIN (dps_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32), - DIRECT_BUILTIN (madd, MIPS_DI_FTYPE_DI_SI_SI, dspr2_32), - DIRECT_BUILTIN (maddu, MIPS_DI_FTYPE_DI_USI_USI, dspr2_32), - DIRECT_BUILTIN (msub, MIPS_DI_FTYPE_DI_SI_SI, dspr2_32), - DIRECT_BUILTIN (msubu, MIPS_DI_FTYPE_DI_USI_USI, dspr2_32), DIRECT_BUILTIN (mulsa_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32), - DIRECT_BUILTIN (mult, MIPS_DI_FTYPE_SI_SI, dspr2_32), - DIRECT_BUILTIN (multu, MIPS_DI_FTYPE_USI_USI, dspr2_32), DIRECT_BUILTIN (dpax_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32), DIRECT_BUILTIN (dpsx_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32), DIRECT_BUILTIN (dpaqx_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, dspr2_32), @@ -16173,10 +16175,8 @@ mips_mulsidi3_gen_fn (enum rtx_code ext_code) } else { - if (TARGET_FIX_R4000) + if (TARGET_FIX_R4000 && !ISA_HAS_DSP) return signed_p ? gen_mulsidi3_32bit_r4000 : gen_umulsidi3_32bit_r4000; - if (ISA_HAS_DSPR2) - return signed_p ? gen_mips_mult : gen_mips_multu; return signed_p ? gen_mulsidi3_32bit : gen_umulsidi3_32bit; } } diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index a3675039462..7b5e140f9a8 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -180,6 +180,13 @@ enum mips_code_readable_setting { #define TARGET_WRITABLE_EH_FRAME (flag_pic && TARGET_SHARED) #endif +/* Test the assembler to set ISA_HAS_DSP_MULT to DSP Rev 1 or 2. */ +#ifdef HAVE_AS_DSPR1_MULT +#define ISA_HAS_DSP_MULT ISA_HAS_DSP +#else +#define ISA_HAS_DSP_MULT ISA_HAS_DSPR2 +#endif + /* Generate mips16 code */ #define TARGET_MIPS16 ((target_flags & MASK_MIPS16) != 0) /* Generate mips16e code. Default 16bit ASE for mips32* and mips64* */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 9b09344d9c9..b7893941408 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -1731,12 +1731,20 @@ DONE; }) +;; As well as being named patterns, these instructions are used by the +;; __builtin_mips_mult<u>() functions. We must always make those functions +;; available if !TARGET_64BIT && ISA_HAS_DSP. (define_insn "<u>mulsidi3_32bit" - [(set (match_operand:DI 0 "register_operand" "=x") + [(set (match_operand:DI 0 "register_operand" "=ka") (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))] - "!TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DSPR2" - "mult<u>\t%1,%2" + "!TARGET_64BIT && (!TARGET_FIX_R4000 || ISA_HAS_DSP)" +{ + if (ISA_HAS_DSP_MULT) + return "mult<u>\t%q0,%1,%2"; + else + return "mult<u>\t%1,%2"; +} [(set_attr "type" "imul") (set_attr "mode" "SI")]) @@ -1856,6 +1864,13 @@ [(set_attr "type" "imul") (set_attr "mode" "SI")]) +;; As well as being named patterns, these instructions are used by the +;; __builtin_mips_msub<u>() functions. We must always make those functions +;; available if !TARGET_64BIT && ISA_HAS_DSP. +;; +;; This leads to a slight inconsistency. We honor any tuning overrides +;; in GENERATE_MADD_MSUB for -mno-dsp, but always ignore them for -mdsp, +;; even if !ISA_HAS_DSP_MULT. (define_insn "<u>msubsidi4" [(set (match_operand:DI 0 "register_operand" "=ka") (minus:DI @@ -1863,9 +1878,9 @@ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))] - "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || ISA_HAS_DSPR2)" + "!TARGET_64BIT && (ISA_HAS_MSAC || GENERATE_MADD_MSUB || ISA_HAS_DSP)" { - if (ISA_HAS_DSPR2) + if (ISA_HAS_DSP_MULT) return "msub<u>\t%q0,%1,%2"; else if (TARGET_MIPS5500 || GENERATE_MADD_MSUB) return "msub<u>\t%1,%2"; @@ -2036,18 +2051,20 @@ [(set_attr "type" "imadd") (set_attr "mode" "SI")]) +;; See the comment above <u>msubsidi4 for the relationship between +;; ISA_HAS_DSP and ISA_HAS_DSP_MULT. (define_insn "<u>maddsidi4" [(set (match_operand:DI 0 "register_operand" "=ka") (plus:DI (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (any_extend:DI (match_operand:SI 2 "register_operand" "d"))) (match_operand:DI 3 "register_operand" "0")))] - "(TARGET_MAD || ISA_HAS_MACC || GENERATE_MADD_MSUB || ISA_HAS_DSPR2) + "(TARGET_MAD || ISA_HAS_MACC || GENERATE_MADD_MSUB || ISA_HAS_DSP) && !TARGET_64BIT" { if (TARGET_MAD) return "mad<u>\t%1,%2"; - else if (ISA_HAS_DSPR2) + else if (ISA_HAS_DSP_MULT) return "madd<u>\t%q0,%1,%2"; else if (GENERATE_MADD_MSUB || TARGET_MIPS5500) return "madd<u>\t%1,%2"; diff --git a/gcc/configure b/gcc/configure index e39b946811d..c8d81d4ba50 100755 --- a/gcc/configure +++ b/gcc/configure @@ -24541,6 +24541,45 @@ $as_echo "#define HAVE_AS_DTPRELWORD 1" >>confdefs.h fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for DSPR1 mult with four accumulators support" >&5 +$as_echo_n "checking assembler for DSPR1 mult with four accumulators support... " >&6; } +if test "${gcc_cv_as_mips_dspr1_mult+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + gcc_cv_as_mips_dspr1_mult=no + if test x$gcc_cv_as != x; then + echo ' .set mips32r2 + .set nodspr2 + .set dsp + madd $ac3,$4,$5 + maddu $ac3,$4,$5 + msub $ac3,$4,$5 + msubu $ac3,$4,$5 + mult $ac3,$4,$5 + multu $ac3,$4,$5' > conftest.s + if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + gcc_cv_as_mips_dspr1_mult=yes + else + echo "configure: failed program was" >&5 + cat conftest.s >&5 + fi + rm -f conftest.o conftest.s + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_mips_dspr1_mult" >&5 +$as_echo "$gcc_cv_as_mips_dspr1_mult" >&6; } +if test $gcc_cv_as_mips_dspr1_mult = yes; then + +$as_echo "#define HAVE_AS_DSPR1_MULT 1" >>confdefs.h + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler and linker for explicit JALR relocation" >&5 $as_echo_n "checking assembler and linker for explicit JALR relocation... " >&6; } gcc_cv_as_ld_jalr_reloc=no diff --git a/gcc/configure.ac b/gcc/configure.ac index cc400425c27..a61e5f1fca1 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -3654,6 +3654,20 @@ x: [AC_DEFINE(HAVE_AS_DTPRELWORD, 1, [Define if your assembler supports .dtprelword.])]) + gcc_GAS_CHECK_FEATURE([DSPR1 mult with four accumulators support], + gcc_cv_as_mips_dspr1_mult,,, +[ .set mips32r2 + .set nodspr2 + .set dsp + madd $ac3,$4,$5 + maddu $ac3,$4,$5 + msub $ac3,$4,$5 + msubu $ac3,$4,$5 + mult $ac3,$4,$5 + multu $ac3,$4,$5],, + [AC_DEFINE(HAVE_AS_DSPR1_MULT, 1, + [Define if your assembler supports DSPR1 mult.])]) + AC_MSG_CHECKING(assembler and linker for explicit JALR relocation) gcc_cv_as_ld_jalr_reloc=no if test $gcc_cv_as_mips_explicit_relocs = yes; then diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index de2be889bdc..95e9d8808f8 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -9646,6 +9646,12 @@ i32 __builtin_mips_lbux (void *, i32) i32 __builtin_mips_lhx (void *, i32) i32 __builtin_mips_lwx (void *, i32) i32 __builtin_mips_bposge32 (void) +a64 __builtin_mips_madd (a64, i32, i32); +a64 __builtin_mips_maddu (a64, ui32, ui32); +a64 __builtin_mips_msub (a64, i32, i32); +a64 __builtin_mips_msubu (a64, ui32, ui32); +a64 __builtin_mips_mult (i32, i32); +a64 __builtin_mips_multu (ui32, ui32); @end smallexample The following built-in functions map directly to a particular MIPS DSP REV 2 @@ -9665,18 +9671,12 @@ i32 __builtin_mips_cmpgdu_lt_qb (v4i8, v4i8); i32 __builtin_mips_cmpgdu_le_qb (v4i8, v4i8); a64 __builtin_mips_dpa_w_ph (a64, v2i16, v2i16); a64 __builtin_mips_dps_w_ph (a64, v2i16, v2i16); -a64 __builtin_mips_madd (a64, i32, i32); -a64 __builtin_mips_maddu (a64, ui32, ui32); -a64 __builtin_mips_msub (a64, i32, i32); -a64 __builtin_mips_msubu (a64, ui32, ui32); v2i16 __builtin_mips_mul_ph (v2i16, v2i16); v2i16 __builtin_mips_mul_s_ph (v2i16, v2i16); q31 __builtin_mips_mulq_rs_w (q31, q31); v2q15 __builtin_mips_mulq_s_ph (v2q15, v2q15); q31 __builtin_mips_mulq_s_w (q31, q31); a64 __builtin_mips_mulsa_w_ph (a64, v2i16, v2i16); -a64 __builtin_mips_mult (i32, i32); -a64 __builtin_mips_multu (ui32, ui32); v4i8 __builtin_mips_precr_qb_ph (v2i16, v2i16); v2i16 __builtin_mips_precr_sra_ph_w (i32, i32, imm0_31); v2i16 __builtin_mips_precr_sra_r_ph_w (i32, i32, imm0_31); |