[09/21] MIPS: Add CRYPTO ASE support

Message ID 20250402121759.1962001-10-jovan.dmitrovic@htecgroup.com
State New
Headers
Series Integrate MIPS-Specific Support |

Commit Message

Jovan Dmitrovic April 2, 2025, 12:18 p.m. UTC
  From: Scott Egerton <scott.egerton@imgtec.com>

Integrates support for the CRYPTO Application Specific Extension (ASE)
in the MIPS architecture, enabling the MIPS assembler and disassembler
to handle cryptographic instructions. New options (-mcrypto and
-mno-crypto), directives (.set crypto and .set nocrypto), and various
parts of the MIPS tools have been updated to support CRYPTO ASE,
including documentation, tests, and flag handling.Additionally,
relevant code files have been modified, and new tests have been added
to ensure the proper functioning of the CRYPTO extension.

Cherry-picked 2f66b2a
from https://github.com/MIPS/binutils-gdb

Signed-off-by: Scott Egerton <scott.egerton@imgtec.com>
Signed-off-by: Faraz Shahbazker <fshahbazker@wavecomp.com>
Signed-off-by: Milica Matic <milica.matic@htecgroup.com>

ChangeLog:

bfd/
    * elfxx-mips.c (print_mips_ases): Add CRYPTO.

binutils/
    * readelf.c (print_mips_ases): Add CRYPTO.

gas/
    * config/tc-mips.c (options): Add OPTION_CRYPTO and
    OPTION_NO_CRYPTO.
    (md_longopts): Likewise.
    (md_show_usage): Add help for -mcrypto and -mno-crypto.
    (mips_ases): Define availability for CRYPTO.
    (mips_convert_ase_flags): Map ASE_CRYPTO to AFL_ASE_CRYPTO.
    * doc/as.texinfo: Document -mcrypto, -mno-crypto.
    * doc/c-mips.texi: Document -mcrypto, -mno-crypto, .set crypto and
    .set no-crypto.
    * testsuite/gas/mips/ase-errors-1.l: Add error checks for CRYPTO
    ASE.
    * testsuite/gas/mips/ase-errors-1.s: Likewise.
    * testsuite/gas/mips/ase-errors-2.l: Likewise.
    * testsuite/gas/mips/ase-errors-2.s: Likewise.
    * testsuite/gas/mips/crypto.d: New test.
    * testsuite/gas/mips/crypto.s: New test source.
    * testsuite/gas/mips/loongson-2f-mmi.d: Update.
    * testsuite/gas/mips/loongson-3a-2.d: Likewise.
    * testsuite/gas/mips/loongson-3a-3.d: Likewise.
    * testsuite/gas/mips/loongson-3a-mmi.d: Likewise.
    * testsuite/gas/mips/loongson-3a.d: Likewise.
    * testsuite/gas/mips/loongson.l: Add warning checks for crypto
    extension.
    * testsuite/gas/mips/mips.exp: Run the new tests.

include/
    * elf/mips.h (AFL_ASE_CRYPTO): New macro.
    (AFL_ASE_MASK): Update to include AFL_ASE_CRYPTO.
    * opcode/mips.h (ASE_CRYPTO): New macro.
ld/
    * testsuite/ld-mips-elf/mips-elf-flags.exp: Add CRYPTO ASE and
    disable warning for crypto extension.

opcodes/
    * mips-dis.c (mips_arch_choices): Add ASE_CRYPTO to mips32r6 and
    mips64r6.
    * mips-opc.c (CRYPTO): New macro.
    (mips_builtin_opcodes): Define new cryptography instructions.
---
 bfd/elfxx-mips.c                            |  2 +
 binutils/readelf.c                          |  2 +
 gas/NEWS                                    |  2 +
 gas/config/tc-mips.c                        | 17 ++++++++
 gas/doc/as.texi                             |  7 ++++
 gas/doc/c-mips.texi                         | 14 +++++++
 gas/testsuite/gas/mips/ase-errors-1.l       | 12 ++++--
 gas/testsuite/gas/mips/ase-errors-1.s       |  9 +++++
 gas/testsuite/gas/mips/ase-errors-2.l       |  4 ++
 gas/testsuite/gas/mips/ase-errors-2.s       |  9 +++++
 gas/testsuite/gas/mips/crypto.d             | 45 +++++++++++++++++++++
 gas/testsuite/gas/mips/crypto.s             | 38 +++++++++++++++++
 gas/testsuite/gas/mips/loongson-2f-mmi.d    |  1 +
 gas/testsuite/gas/mips/loongson-3a-2.d      |  1 +
 gas/testsuite/gas/mips/loongson-3a-3.d      |  1 +
 gas/testsuite/gas/mips/loongson-3a-mmi.d    |  3 ++
 gas/testsuite/gas/mips/loongson-3a.d        |  1 +
 gas/testsuite/gas/mips/loongson.l           |  2 +
 gas/testsuite/gas/mips/mips.exp             |  4 ++
 include/elf/mips.h                          |  4 +-
 include/opcode/mips.h                       | 40 +++++++++---------
 ld/testsuite/ld-mips-elf/mips-elf-flags.exp |  6 +--
 opcodes/mips-dis.c                          |  4 +-
 opcodes/mips-opc.c                          | 34 ++++++++++++++++
 24 files changed, 232 insertions(+), 30 deletions(-)
 create mode 100644 gas/testsuite/gas/mips/crypto.d
 create mode 100644 gas/testsuite/gas/mips/crypto.s
 create mode 100644 gas/testsuite/gas/mips/loongson.l
  

Patch

diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index a895d08e009..68b439c456a 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -16605,6 +16605,8 @@  print_mips_ases (FILE *file, unsigned int mask)
     fputs ("\n\tCRC ASE", file);
   if (mask & AFL_ASE_GINV)
     fputs ("\n\tGINV ASE", file);
+  if (mask & AFL_ASE_CRYPTO)
+    fputs ("\n\tCRYPTO ASE", file);
   if (mask & AFL_ASE_LOONGSON_MMI)
     fputs ("\n\tLoongson MMI ASE", file);
   if (mask & AFL_ASE_LOONGSON_CAM)
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 64e461daf86..72f5c4cb62e 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -19519,6 +19519,8 @@  print_mips_ases (unsigned int mask)
     fputs ("\n\tCRC ASE", stdout);
   if (mask & AFL_ASE_GINV)
     fputs ("\n\tGINV ASE", stdout);
+  if (mask & AFL_ASE_CRYPTO)
+    fputs ("\n\tCRYPTO ASE", stdout);
   if (mask & AFL_ASE_LOONGSON_MMI)
     fputs ("\n\tLoongson MMI ASE", stdout);
   if (mask & AFL_ASE_LOONGSON_CAM)
diff --git a/gas/NEWS b/gas/NEWS
index 269b63e2056..b0a560fc171 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -482,6 +482,8 @@  Changes in 2.32:
 * Add support for the MIPS Loongson MultiMedia extensions Instructions (MMI)
   ASE.
 
+* Add support for the MIPS CRYPTO ASE.
+
 Changes in 2.31:
 
 * The ADR and ADRL pseudo-instructions supported by the ARM assembler
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 4eba79b7146..ce58bae8a7f 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -1503,6 +1503,8 @@  enum options
     OPTION_NO_MIPS16E2,
     OPTION_CRC,
     OPTION_NO_CRC,
+    OPTION_CRYPTO,
+    OPTION_NO_CRYPTO,
     OPTION_M4650,
     OPTION_NO_M4650,
     OPTION_M4010,
@@ -1642,6 +1644,8 @@  const struct option md_longopts[] =
   {"mno-crc", no_argument, NULL, OPTION_NO_CRC},
   {"mginv", no_argument, NULL, OPTION_GINV},
   {"mno-ginv", no_argument, NULL, OPTION_NO_GINV},
+  {"mcrypto", no_argument, NULL, OPTION_CRYPTO},
+  {"mno-crypto", no_argument, NULL, OPTION_NO_CRYPTO},
   {"mloongson-mmi", no_argument, NULL, OPTION_LOONGSON_MMI},
   {"mno-loongson-mmi", no_argument, NULL, OPTION_NO_LOONGSON_MMI},
   {"mloongson-cam", no_argument, NULL, OPTION_LOONGSON_CAM},
@@ -1871,6 +1875,11 @@  static const struct mips_ase mips_ases[] = {
     OPTION_LOONGSON_EXT2, OPTION_NO_LOONGSON_EXT2,
     0, 0, -1, -1,
     -1 },
+
+  { "crypto", ASE_CRYPTO, 0,
+    OPTION_CRYPTO, OPTION_NO_CRYPTO,
+    6,  6, -1, -1,
+    -1 },
 };
 
 /* The set of ASEs that require -mfp64.  */
@@ -6070,6 +6079,9 @@  match_tied_reg_operand (struct mips_arg_info *arg, unsigned int other_regno)
 {
   unsigned int regno;
 
+  if (match_reg (arg, OP_REG_MSA, &regno) && regno == other_regno)
+    return TRUE;
+
   return match_reg (arg, OP_REG_GP, &regno) && regno == other_regno;
 }
 
@@ -19667,6 +19679,8 @@  mips_convert_ase_flags (int ase)
     ext_ases |= AFL_ASE_CRC;
   if (ase & ASE_GINV)
     ext_ases |= AFL_ASE_GINV;
+  if (ase & ASE_CRYPTO)
+    ext_ases |= AFL_ASE_CRYPTO;
   if (ase & ASE_LOONGSON_MMI)
     ext_ases |= AFL_ASE_LOONGSON_MMI;
   if (ase & ASE_LOONGSON_CAM)
@@ -20718,6 +20732,9 @@  MIPS options:\n\
 -mloongson-ext2		generate Loongson EXTensions R2 (EXT2) instructions\n\
 -mno-loongson-ext2	do not generate Loongson EXTensions R2 Instructions\n"));
   fprintf (stream, _("\
+-mcrypto			generate crypto instructions\n\
+-mno-crypto		do not generate crypto instructions\n"));
+  fprintf (stream, _("\
 -minsn32		only generate 32-bit microMIPS instructions\n\
 -mno-insn32		generate all microMIPS instructions\n"));
 #if DEFAULT_MIPS_FIX_LOONGSON3_LLSC
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index 725029c867d..d59de97b239 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -475,6 +475,7 @@  gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
    [@b{-mmcu}] [@b{-mno-mcu}]
    [@b{-mcrc}] [@b{-mno-crc}]
    [@b{-mginv}] [@b{-mno-ginv}]
+   [@b{-mcrypto}] [@b{-mno-crypto}]
    [@b{-mloongson-mmi}] [@b{-mno-loongson-mmi}]
    [@b{-mloongson-cam}] [@b{-mno-loongson-cam}]
    [@b{-mloongson-ext}] [@b{-mno-loongson-ext}]
@@ -1708,6 +1709,12 @@  This option implies @samp{-mloongson-ext}.
 This tells the assembler to accept Loongson EXT2 instructions.
 @samp{-mno-loongson-ext2} turns off this option.
 
+@item -mcrypto
+@itemx -mno-crypto
+Generate code for the MIPS Crypto Application Specific Extension.
+This tells the assembler to accept crypto instructions.
+@samp{-mno-crypto} turns off this option.
+
 @item -minsn32
 @itemx -mno-insn32
 Only use 32-bit instruction encodings when generating code for the
diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi
index 4181aa305a0..8ed41e1d2f4 100644
--- a/gas/doc/c-mips.texi
+++ b/gas/doc/c-mips.texi
@@ -274,6 +274,13 @@  Application Specific Extension.  This tells the assembler to accept EXT2
 instructions.
 @samp{-mno-loongson-ext2} turns off this option.
 
+@item -mcrypto
+@itemx -mno-crypto
+Generate code for the Crypto Application Specific
+Extension.
+This tells the assembler to accept crypto instructions.
+@samp{-mno-crypto} turns off this option.
+
 @item -minsn32
 @itemx -mno-insn32
 Only use 32-bit instruction encodings when generating code for the
@@ -1223,6 +1230,13 @@  This directive implies @code{.set loognson-ext}.
 The @code{.set noloongson-ext2} directive prevents Loongson EXT2 instructions
 from being accepted.
 
+@cindex MIPS crypto instruction generation override
+@kindex @code{.set crypto}
+@kindex @code{.set nocrypto}
+The directive @code{.set crypto} makes the assembler accept instructions
+from the crypto extension from that point on in the assembly.  The
+@code{.set nocrypto} directive prevents crypto instructions from being accepted.
+
 Traditional MIPS assemblers do not support these directives.
 
 @node MIPS Floating-Point
diff --git a/gas/testsuite/gas/mips/ase-errors-1.l b/gas/testsuite/gas/mips/ase-errors-1.l
index b51db4fa545..c3142e64392 100644
--- a/gas/testsuite/gas/mips/ase-errors-1.l
+++ b/gas/testsuite/gas/mips/ase-errors-1.l
@@ -48,7 +48,11 @@ 
 .*:117: Warning: the `ginv' extension requires MIPS32 revision 6 or greater
 .*:120: Error: opcode not supported.* `ginvi \$a0'
 # ----------------------------------------------------------------------------
-.*:127: Error: opcode not supported .* `llwpe \$2,\$3,\$4'
-.*:128: Error: opcode not supported .* `scwpe \$2,\$3,\$4'
-.*:131: Error: opcode not supported .* `llwpe \$2,\$3,\$4'
-.*:132: Error: opcode not supported .* `scwpe \$2,\$3,\$4'
+.*:127: Error: opcode not supported on this processor: mips32r6 \(mips32r6\) `llwpe \$2,\$3,\$4'
+.*:128: Error: opcode not supported on this processor: mips32r6 \(mips32r6\) `scwpe \$2,\$3,\$4'
+.*:131: Error: opcode not supported on this processor: mips32r5 \(mips32r5\) `llwpe \$2,\$3,\$4'
+# ----------------------------------------------------------------------------
+.*:132: Error: opcode not supported on this processor: mips32r5 \(mips32r5\) `scwpe \$2,\$3,\$4'
+.*:137: Error: invalid operands `sha1\.ms\.2 \$w4,\$w7,\$w6'
+.*:138: Warning: the `crypto' extension requires MIPS32 revision 6 or greater
+.*:141: Error: opcode not supported on this processor: mips32r5 \(mips32r5\) `sha1\.ms\.1 \$w4,\$w7,\$w6'
diff --git a/gas/testsuite/gas/mips/ase-errors-1.s b/gas/testsuite/gas/mips/ase-errors-1.s
index 7deeea1df26..9bdc15b80e8 100644
--- a/gas/testsuite/gas/mips/ase-errors-1.s
+++ b/gas/testsuite/gas/mips/ase-errors-1.s
@@ -131,6 +131,15 @@ 
 	llwpe	$2, $3, $4	# ERROR: only avaialable on R6
 	scwpe	$2, $3, $4	# ERROR: only avaialable on R6
 
+	.set mips32r6
+	.set crypto		# OK
+	aes128.enc	$w4,$w7	# OK
+	sha1.ms.2 	$w4,$w7,$w6	#ERROR: Invalid operands
+	.set mips32r5		# ERROR: too low
+	aes256.enc	$w4,$w7,$w6	# OK
+	.set nocrypto
+	sha1.ms.1	$w4,$w7,$w6	# ERROR: crypto not enabled
+
 	# There should be no errors after this.
 	.set fp=32
 	.set mips1
diff --git a/gas/testsuite/gas/mips/ase-errors-2.l b/gas/testsuite/gas/mips/ase-errors-2.l
index 6ac51630d44..7c5a3e2b000 100644
--- a/gas/testsuite/gas/mips/ase-errors-2.l
+++ b/gas/testsuite/gas/mips/ase-errors-2.l
@@ -40,3 +40,7 @@ 
 .*:103: Warning: the `ginv' extension requires MIPS64 revision 6 or greater
 .*:106: Error: opcode not supported.* `ginvi \$a0'
 # ----------------------------------------------------------------------------
+.*:111: Error: invalid operands `sha1.ms.2 \$w4,\$w7,\$w6'
+.*:112: Warning: the `crypto' extension requires MIPS64 revision 6 or greater
+.*:115: Error: opcode not supported.* `sha1.ms.1 \$w4,\$w7,\$w6'
+# ----------------------------------------------------------------------------
diff --git a/gas/testsuite/gas/mips/ase-errors-2.s b/gas/testsuite/gas/mips/ase-errors-2.s
index 2b31517e6e1..0b1684b87a1 100644
--- a/gas/testsuite/gas/mips/ase-errors-2.s
+++ b/gas/testsuite/gas/mips/ase-errors-2.s
@@ -105,6 +105,15 @@ 
 	.set noginv
 	ginvi $a0		# ERROR: ginv not enabled
 
+	.set mips64r6
+	.set crypto		# OK
+	aes128.enc	$w4,$w7	# OK
+	sha1.ms.2	$w4,$w7,$w6	# ERROR: Invalid operands
+	.set mips64r5		# ERROR: too low
+	aes256.enc	$w4,$w7,$w6	# OK
+	.set nocrypto
+	sha1.ms.1	$w4,$w7,$w6	# ERROR: crypto not enabled
+
 	# There should be no errors after this.
 	.set fp=32
 	.set mips4
diff --git a/gas/testsuite/gas/mips/crypto.d b/gas/testsuite/gas/mips/crypto.d
new file mode 100644
index 00000000000..30bb26ec06e
--- /dev/null
+++ b/gas/testsuite/gas/mips/crypto.d
@@ -0,0 +1,45 @@ 
+#objdump: -pdr --prefix-addresses --show-raw-insn
+#name: MIPS CRYPTO
+#as: -mcrypto -32
+
+# Test the CRYPTO instructions
+
+.*: +file format .*mips.*
+#...
+ASEs:
+#...
+	CRYPTO ASE
+#...
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 78003917 	aes128.enc	\$w4,\$w7
+[0-9a-f]+ <[^>]*> 78013917 	aes128.dec	\$w4,\$w7
+[0-9a-f]+ <[^>]*> 78463917 	aes192.enc	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 78663917 	aes192.dec	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 78863917 	aes256.enc	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 78a63917 	aes256.dec	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 781a3917 	aes.kg	\$w4,\$w7
+[0-9a-f]+ <[^>]*> 78103917 	aes.fr.enc	\$w4,\$w7
+[0-9a-f]+ <[^>]*> 78113917 	aes.fr.dec	\$w4,\$w7
+[0-9a-f]+ <[^>]*> 78123917 	aes.lr.enc	\$w4,\$w7
+[0-9a-f]+ <[^>]*> 78133917 	aes.lr.dec	\$w4,\$w7
+[0-9a-f]+ <[^>]*> 78160117 	aes.mc.enc	\$w4
+[0-9a-f]+ <[^>]*> 78170117 	aes.mc.dec	\$w4
+[0-9a-f]+ <[^>]*> 78140117 	aes.sb.enc	\$w4
+[0-9a-f]+ <[^>]*> 78150117 	aes.sb.dec	\$w4
+[0-9a-f]+ <[^>]*> 78180117 	aes.sr.enc	\$w4
+[0-9a-f]+ <[^>]*> 78190117 	aes.sr.dec	\$w4
+[0-9a-f]+ <[^>]*> 7be63917 	md5.ms	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7ae63917 	md5.4r	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7b063917 	sha1.ms.1	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7b203917 	sha1.ms.2	\$w4,\$w7,\$w4
+[0-9a-f]+ <[^>]*> 7a063917 	sha1.hash.4r	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7b463917 	sha256.ms.1	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7b663917 	sha256.ms.2	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7a463917 	sha256.hash.2r	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7b863917 	sha512.ms.1	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7ba63917 	sha512.ms.2	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7a863917 	sha512.hash.r.1	\$w4,\$w7,\$w6
+[0-9a-f]+ <[^>]*> 7aa63917 	sha512.hash.r.2	\$w4,\$w7,\$w6
+
+	\.\.\.
diff --git a/gas/testsuite/gas/mips/crypto.s b/gas/testsuite/gas/mips/crypto.s
new file mode 100644
index 00000000000..d7e2db0e79e
--- /dev/null
+++ b/gas/testsuite/gas/mips/crypto.s
@@ -0,0 +1,38 @@ 
+	.set	noreorder
+	.set	noat
+
+	.text
+test_crypto:
+	aes128.enc	$w4, $w7
+	aes128.dec	$w4, $w7
+	aes192.enc	$w4, $w7, $w6
+	aes192.dec	$w4, $w7, $w6
+	aes256.enc	$w4, $w7, $w6
+	aes256.dec	$w4, $w7, $w6
+	aes.kg		$w4, $w7
+	aes.fr.enc	$w4, $w7
+	aes.fr.dec	$w4, $w7
+	aes.lr.enc	$w4, $w7
+	aes.lr.dec	$w4, $w7
+	aes.mc.enc	$w4
+	aes.mc.dec	$w4
+	aes.sb.enc	$w4
+	aes.sb.dec	$w4
+	aes.sr.enc	$w4
+	aes.sr.dec	$w4
+	md5.ms		$w4, $w7, $w6
+	md5.4r		$w4, $w7, $w6
+	sha1.ms.1	$w4, $w7, $w6
+	sha1.ms.2	$w4, $w7, $w4
+	sha1.hash.4r	$w4, $w7, $w6
+	sha256.ms.1	$w4, $w7, $w6
+	sha256.ms.2	$w4, $w7, $w6
+	sha256.hash.2r	$w4, $w7, $w6
+	sha512.ms.1	$w4, $w7, $w6
+	sha512.ms.2	$w4, $w7, $w6
+	sha512.hash.r.1	$w4, $w7, $w6
+	sha512.hash.r.2	$w4, $w7, $w6
+
+# Force at least 8 (non-delay-slot) zero bytes, to make 'objdump' print ...
+	.align	2
+	.space	8
diff --git a/gas/testsuite/gas/mips/loongson-2f-mmi.d b/gas/testsuite/gas/mips/loongson-2f-mmi.d
index 84224f93672..04fe0a81e29 100644
--- a/gas/testsuite/gas/mips/loongson-2f-mmi.d
+++ b/gas/testsuite/gas/mips/loongson-2f-mmi.d
@@ -15,6 +15,7 @@  FP ABI: .*
 ISA Extension: ST Microelectronics Loongson 2F
 ASEs:
 	Loongson MMI ASE
+.*
 FLAGS 1: .*
 FLAGS 2: .*
 
diff --git a/gas/testsuite/gas/mips/loongson-3a-2.d b/gas/testsuite/gas/mips/loongson-3a-2.d
index ff2f553c82a..68b7a828413 100644
--- a/gas/testsuite/gas/mips/loongson-3a-2.d
+++ b/gas/testsuite/gas/mips/loongson-3a-2.d
@@ -1,6 +1,7 @@ 
 #as: -march=loongson3a -mabi=o64
 #objdump: -M reg-names=numeric -dr
 #name: Loongson-3A tests 2
+#warning_output: loongson.l
 
 .*:     file format .*
 
diff --git a/gas/testsuite/gas/mips/loongson-3a-3.d b/gas/testsuite/gas/mips/loongson-3a-3.d
index e242c5dc972..5316039592a 100644
--- a/gas/testsuite/gas/mips/loongson-3a-3.d
+++ b/gas/testsuite/gas/mips/loongson-3a-3.d
@@ -1,6 +1,7 @@ 
 #as: -march=loongson3a -mabi=o64
 #objdump: -M reg-names=numeric -dr
 #name: Loongson delay slot tests
+#warning_output: loongson.l
 
 .*:     file format .*
 
diff --git a/gas/testsuite/gas/mips/loongson-3a-mmi.d b/gas/testsuite/gas/mips/loongson-3a-mmi.d
index 3a52c5a59f4..b15acbd811b 100644
--- a/gas/testsuite/gas/mips/loongson-3a-mmi.d
+++ b/gas/testsuite/gas/mips/loongson-3a-mmi.d
@@ -1,6 +1,7 @@ 
 #as: -march=loongson3a -mabi=o64
 #objdump: -M reg-names=numeric -dp
 #name: Loongson-3A MMI tests
+#warning_output: loongson.l
 
 .*:     file format .*
 
@@ -14,9 +15,11 @@  CPR2 size: .*
 FP ABI: .*
 ISA Extension: None
 ASEs:
+	CRYPTO ASE
 	Loongson MMI ASE
 	Loongson CAM ASE
 	Loongson EXT ASE
+	Unknown \([a-z0-9]+\)
 FLAGS 1: .*
 FLAGS 2: .*
 
diff --git a/gas/testsuite/gas/mips/loongson-3a.d b/gas/testsuite/gas/mips/loongson-3a.d
index 108c82d4a1c..1eca137985f 100644
--- a/gas/testsuite/gas/mips/loongson-3a.d
+++ b/gas/testsuite/gas/mips/loongson-3a.d
@@ -1,6 +1,7 @@ 
 #as: -march=loongson3a -mabi=o64
 #objdump: -M reg-names=numeric -dr
 #name: Loongson-3A tests
+#warning_output: loongson.l
 
 .*:     file format .*
 
diff --git a/gas/testsuite/gas/mips/loongson.l b/gas/testsuite/gas/mips/loongson.l
new file mode 100644
index 00000000000..ed12a593db5
--- /dev/null
+++ b/gas/testsuite/gas/mips/loongson.l
@@ -0,0 +1,2 @@ 
+.*: Assembler messages:
+.*:[0-9]+: Warning: the `crypto' extension requires MIPS64 revision 6 or greater
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 0003dc91ff1..5c34e69add1 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -568,6 +568,7 @@  if { [istarget mips*-*-vxworks*] } {
     run_dump_test "vxworks1-el"
     run_dump_test "vxworks1-xgot-el"
 
+
     run_list_test "option-pic-vxworks-1" "-mvxworks-pic" \
 	"MIPS invalid PIC option in VxWorks PIC"
     run_list_test "option-pic-vxworks-2" "-mvxworks-pic" \
@@ -2215,6 +2216,9 @@  if { [istarget mips*-*-vxworks*] } {
     run_dump_test_arch "llpscp-64" "" mips64r6
     run_dump_test "llpscp-64-micromips"
 
+    run_dump_test_arches "crypto"	[mips_arch_list_matching mips32r6 \
+					     !micromipsr6]
+
     run_dump_test "pr14798${imips}"
     run_dump_test "insn-isa-mode"
     run_dump_test "insn-isa-mode"
diff --git a/include/elf/mips.h b/include/elf/mips.h
index 2d390056374..6b52c953e75 100644
--- a/include/elf/mips.h
+++ b/include/elf/mips.h
@@ -1299,13 +1299,13 @@  extern void bfd_mips_elf_swap_abiflags_v0_out
 #define AFL_ASE_DSPR3        0x00002000 /* DSP R3 ASE.  */
 #define AFL_ASE_MIPS16E2     0x00004000 /* MIPS16e2 ASE.  */
 #define AFL_ASE_CRC          0x00008000 /* CRC ASE.  */
-#define AFL_ASE_RESERVED1    0x00010000 /* Reserved by MIPS Tech for WIP.  */
+#define AFL_ASE_CRYPTO       0x00010000 /* CRYPTO ASE.  */
 #define AFL_ASE_GINV         0x00020000 /* GINV ASE.  */
 #define AFL_ASE_LOONGSON_MMI 0x00040000 /* Loongson MMI ASE.  */
 #define AFL_ASE_LOONGSON_CAM 0x00080000 /* Loongson CAM ASE.  */
 #define AFL_ASE_LOONGSON_EXT 0x00100000 /* Loongson EXT instructions.  */
 #define AFL_ASE_LOONGSON_EXT2 0x00200000 /* Loongson EXT2 instructions.  */
-#define AFL_ASE_MASK         0x003effff /* All ASEs.  */
+#define AFL_ASE_MASK         0x0003ffff /* All ASEs.  */
 
 /* Values for the isa_ext word of an ABI flags structure.  */
 
diff --git a/include/opcode/mips.h b/include/opcode/mips.h
index dc625334bf3..27476f3fdc1 100644
--- a/include/opcode/mips.h
+++ b/include/opcode/mips.h
@@ -739,25 +739,25 @@  mips_opcode_32bit_p (const struct mips_opcode *mo)
    "+|" 8-bit mask at bit 16.
 
    MIPS R6:
-   "+:" 11-bit mask at bit 0.
-   "+'" 26-bit PC relative branch target address at bit 0.
-   "+"" 21-bit PC relative branch target address at bit 0.
-   "+;" 5-bit same register at both bit 16 and 21 (both RT and RS).
-   "+I" 2-bit unsigned bit position at bit 6.
-   "+O" 3-bit unsigned bit position at bit 6.
-   "+R" Must be program counter.
-   "-a" (-262144 .. 262143) << 2 at bit 0.
-   "-b" (-131072 .. 131071) << 3 at bit 0.
-   "-d" Same as destination register GP.
-   "-s" 5-bit source register at bit 21 (RS) not $0.
-   "-t" 5-bit target register at bit 16 (RT) not $0
-   "-u" 5-bit target register at bit 16 (RT) greater than RS.
-   "-v" 5-bit target register at bit 16 (RT) not $0 not RS.
-   "-w" 5-bit target register at bit 16 (RT) less than or equal to RS.
-   "-x" 5-bit source register at bit 21 (RS) greater than RT.
-   "-y" 5-bit source register at bit 21 (RS) not $0 less than RT.
-   "-A" Symbolic offset (-262144 .. 262143) << 2 at bit 0.
-   "-B" Symbolic offset (-131072 .. 131071) << 3 at bit 0.
+   "+:" 11-bit mask at bit 0
+   "+'" 26 bit PC relative branch target address
+   "+"" 21 bit PC relative branch target address
+   "+;" 5 bit same register in both OP_*_RS and OP_*_RT
+   "+I" 2bit unsigned bit position at bit 6
+   "+O" 3bit unsigned bit position at bit 6
+   "+R" must be program counter
+   "-a" (-262144 .. 262143) << 2 at bit 0
+   "-b" (-131072 .. 131071) << 3 at bit 0
+   "-d" Same as destination register (GP or MSA)
+   "-s" 5 bit source register specifier (OP_*_RS) not $0
+   "-t" 5 bit target register specifier (OP_*_RT) not $0
+   "-u" 5 bit target register specifier (OP_*_RT) greater than OP_*_RS
+   "-v" 5 bit target register specifier (OP_*_RT) not $0 not OP_*_RS
+   "-w" 5 bit target register specifier (OP_*_RT) less than or equal to OP_*_RS
+   "-x" 5 bit source register specifier (OP_*_RS) greater than OP_*_RT
+   "-y" 5 bit source register specifier (OP_*_RS) not $0 less than OP_*_RT
+   "-A" symbolic offset (-262144 .. 262143) << 2 at bit 0
+   "-B" symbolic offset (-131072 .. 131071) << 3 at bit 0
 
    GINV ASE usage:
    "+\" 2-bit Global TLB invalidate type at bit 8.
@@ -1083,6 +1083,8 @@  static const unsigned int mips_isa_table[] = {
 /* The Enhanced VA Scheme (EVA) extension has instructions which are
    only valid for the R6 ISA.  */
 #define ASE_EVA_R6		0x02000000
+/* Crypto ASE */
+#define ASE_CRYPTO		0x00400000
 
 /* MIPS ISA defines, use instead of hardcoding ISA level.  */
 
diff --git a/ld/testsuite/ld-mips-elf/mips-elf-flags.exp b/ld/testsuite/ld-mips-elf/mips-elf-flags.exp
index d7eed978e12..bc5222080a7 100644
--- a/ld/testsuite/ld-mips-elf/mips-elf-flags.exp
+++ b/ld/testsuite/ld-mips-elf/mips-elf-flags.exp
@@ -71,7 +71,7 @@  proc assemble_for_flags {arglist} {
 
     foreach args $arglist {
 	set obj "tmpdir/mips-flags-${index}.o"
-	if {![ld_assemble $as "$args $srcdir/$subdir/jr.s" $obj]} {
+	if {![ld_assemble $as "$args  --no-warn $srcdir/$subdir/jr.s" $obj]} {
 	    return ""
 	}
 	lappend objs $obj
@@ -319,8 +319,8 @@  good_combination { "-march=interaptiv-mr2 -32" "-march=m5100 -32" } \
 good_combination { "-march=gs464 -32" "-march=gs464e -32" }	\
 		 { gs464e o32 }					\
 		 MIPS64r2 "None"				\
-		 { "Loongson MMI ASE" "Loongson CAM ASE" "Loongson EXT ASE" "Loongson EXT2 ASE" }
+		 { "CRYPTO ASE" "Loongson MMI ASE" "Loongson CAM ASE" "Loongson EXT ASE" "Loongson EXT2 ASE" "Unknown (3c0000)" }
 good_combination { "-march=gs264e -32" "-march=gs464e -32" }	\
 		 { gs264e o32 }					\
 		 MIPS64r2 "None"				\
-		 { "Loongson MMI ASE" "Loongson CAM ASE" "Loongson EXT ASE" "Loongson EXT2 ASE" }
+		 { "CRYPTO ASE" "Loongson MMI ASE" "Loongson CAM ASE" "Loongson EXT ASE" "Loongson EXT2 ASE" "Unknown (3c0000)" }
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index 80c447e854d..35caa1e945c 100644
--- a/opcodes/mips-dis.c
+++ b/opcodes/mips-dis.c
@@ -591,7 +591,7 @@  const struct mips_arch_choice mips_arch_choices[] =
   { "mips32r6",	1, bfd_mach_mipsisa32r6, CPU_MIPS32R6,
     ISA_MIPS32R6,
     (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_XPA | ASE_MCU | ASE_MT | ASE_DSP
-     | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC | ASE_GINV),
+     | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC | ASE_GINV | ASE_CRYPTO),
     mips_cp0_names_mips3264r2,
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
@@ -631,7 +631,7 @@  const struct mips_arch_choice mips_arch_choices[] =
     ISA_MIPS64R6,
     (ASE_EVA | ASE_MSA | ASE_MSA64 | ASE_XPA | ASE_VIRT | ASE_VIRT64
      | ASE_MCU | ASE_MT | ASE_DSP | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC
-     | ASE_CRC64 | ASE_GINV),
+     | ASE_CRC64 | ASE_GINV | ASE_CRYPTO),
     mips_cp0_names_mips3264r2,
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
diff --git a/opcodes/mips-opc.c b/opcodes/mips-opc.c
index 97441a4e01e..ede01e176c9 100644
--- a/opcodes/mips-opc.c
+++ b/opcodes/mips-opc.c
@@ -406,6 +406,9 @@  decode_mips_operand (const char *p)
 #define MSA	ASE_MSA
 #define MSA64	ASE_MSA64
 
+/* Crypto support.  */
+#define CRYPTO	ASE_CRYPTO
+
 /* eXtended Physical Address (XPA) support.  */
 #define XPA     ASE_XPA
 #define XPAVZ	ASE_XPA_VIRT
@@ -3150,6 +3153,37 @@  const struct mips_opcode mips_builtin_opcodes[] =
 {"restore",		"-m",		0x7000001f, 0xfc00603f, WR_31|NODS,		MOD_SP,		IAMR2,		0,	0 },
 {"save",		"-m",		0x7000201f, 0xfc00603f, NODS,			RD_31|MOD_SP,	IAMR2,		0,	0 },
 
+/* MIPS Crypto ASE.  */
+{"aes128.enc",		"+d,+e",	0x78000017, 0xffff003f,	MOD_1|RD_2,		0,		0,		CRYPTO,	0 },
+{"aes128.dec",		"+d,+e",	0x78010017, 0xffff003f,	MOD_1|RD_2,		0,		0,		CRYPTO,	0 },
+{"aes192.enc",		"+d,+e,+h",	0x78400017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"aes192.dec",		"+d,+e,+h",	0x78600017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"aes256.enc",		"+d,+e,+h",	0x78800017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"aes256.dec",		"+d,+e,+h",	0x78a00017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"aes.kg",		"+d,+e",	0x781a0017, 0xffff003f,	MOD_1|RD_2,		0,		0,		CRYPTO,	0 },
+{"aes.fr.enc",		"+d,+e",	0x78100017, 0xffff003f,	MOD_1|RD_2,		0,		0,		CRYPTO,	0 },
+{"aes.fr.dec",		"+d,+e",	0x78110017, 0xffff003f,	MOD_1|RD_2,		0,		0,		CRYPTO,	0 },
+{"aes.lr.enc",		"+d,+e",	0x78120017, 0xffff003f,	MOD_1|RD_2,		0,		0,		CRYPTO,	0 },
+{"aes.lr.dec",		"+d,+e",	0x78130017, 0xffff003f,	MOD_1|RD_2,		0,		0,		CRYPTO,	0 },
+{"aes.mc.enc",		"+d",		0x78160017, 0xfffff83f,	MOD_1,			0,		0,		CRYPTO,	0 },
+{"aes.mc.dec",		"+d",		0x78170017, 0xfffff83f,	MOD_1,			0,		0,		CRYPTO,	0 },
+{"aes.sb.enc",		"+d",		0x78140017, 0xfffff83f,	MOD_1,			0,		0,		CRYPTO,	0 },
+{"aes.sb.dec",		"+d",		0x78150017, 0xfffff83f,	MOD_1,			0,		0,		CRYPTO,	0 },
+{"aes.sr.enc",		"+d",		0x78180017, 0xfffff83f,	MOD_1,			0,		0,		CRYPTO,	0 },
+{"aes.sr.dec",		"+d",		0x78190017, 0xfffff83f,	MOD_1,			0,		0,		CRYPTO,	0 },
+{"md5.ms",		"+d,+e,+h",	0x7be00017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"md5.4r",		"+d,+e,+h",	0x7ae00017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"sha1.ms.1",		"+d,+e,+h",	0x7b000017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"sha1.ms.2",		"+d,+e,-d",	0x7b200017, 0xffff003f,	MOD_1|RD_2,		0,		0,		CRYPTO,	0 },
+{"sha1.hash.4r",	"+d,+e,+h",	0x7a000017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"sha256.ms.1",		"+d,+e,+h",	0x7b400017, 0xffe0003f,	WR_1|RD_2|RD_3,		0,		0,		CRYPTO,	0 },
+{"sha256.ms.2",		"+d,+e,+h",	0x7b600017, 0xffe0003f,	WR_1|RD_2|RD_3,		0,		0,		CRYPTO,	0 },
+{"sha256.hash.2r",	"+d,+e,+h",	0x7a400017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"sha512.ms.1",		"+d,+e,+h",	0x7b800017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"sha512.ms.2",		"+d,+e,+h",	0x7ba00017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"sha512.hash.r.1",	"+d,+e,+h",	0x7a800017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+{"sha512.hash.r.2",	"+d,+e,+h",	0x7aa00017, 0xffe0003f,	MOD_1|RD_2|RD_3,	0,		0,		CRYPTO,	0 },
+
 /* User Defined Instruction.  */
 {"udi0",		"s,t,d,+1",	0x70000010, 0xfc00003f,	UDI,			0,		I33,		0,	0 },
 {"udi0",		"s,t,+2",	0x70000010, 0xfc00003f,	UDI,			0,		I33,		0,	0 },