aarch64: Add support for Check Feature Status Extension.

Message ID 77dc20a4-900d-4cd0-d612-8809ad4d9f18@arm.com
State Committed
Headers
Series aarch64: Add support for Check Feature Status Extension. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_check--master-arm fail Patch failed to apply

Commit Message

Srinath Parvathaneni Oct. 31, 2023, 5:46 p.m. UTC
  Hi,

This patch adds support for Check Feature Status Extension (CHK) which
is mandatory from Armv8.0-A. Also this patch supports "chkfeat" instruction
(hint #40).

Regression tested for aarch64-none-elf target and found no regressions.

Ok for binutils-master?

Regards,
Srinath.
  

Comments

Srinath Parvathaneni Nov. 2, 2023, 9:51 a.m. UTC | #1
Hi,

This patch adds support for Check Feature Status Extension (CHK) which
is mandatory from Armv8.0-A. Also this patch supports "chkfeat" instruction
(hint #40).

Regression tested for aarch64-none-elf target and found no regressions.

Ok for binutils-master?

Regards,
Srinath

On 10/31/2023 5:46 PM, Srinath Parvathaneni wrote:
>
> Hi,
>
> This patch adds support for Check Feature Status Extension (CHK) which
> is mandatory from Armv8.0-A. Also this patch supports "chkfeat" 
> instruction
> (hint #40).
>
> Regression tested for aarch64-none-elf target and found no regressions.
>
> Ok for binutils-master?
>
> Regards,
> Srinath.
>
diff --git a/gas/NEWS b/gas/NEWS
index 5b6bffcbdf58e3a3bcb34ba7875601cb67ca0db0..896ea2d7eb24cd7295f953ce0c619b0a778024f0 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@
 -*- text -*-
 
+* Add support for AArch64 Check Feature Status Extension (CHK).
+
 * Add support for 'armv8.9-a' and 'armv9.4-a' for -march in AArch64 GAS.
 
 * Add support for Intel AVX10.1.
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 7d7e54965f12e074a5cc0437accd770e1f1776e1..f5b7b427dd6b5a0bc899cc3c79f05c02005b6c5b 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -6570,6 +6570,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	case AARCH64_OPND_Rm:
 	case AARCH64_OPND_Rt:
 	case AARCH64_OPND_Rt2:
+	case AARCH64_OPND_X16:
 	case AARCH64_OPND_Rs:
 	case AARCH64_OPND_Ra:
 	case AARCH64_OPND_Rt_LS64:
@@ -6581,17 +6582,26 @@ parse_operands (char *str, const aarch64_opcode *opcode)
 	  /* In LS64 load/store instructions Rt register number must be even
 	     and <=22.  */
 	  if (operands[i] == AARCH64_OPND_Rt_LS64)
-	  {
-	    /* We've already checked if this is valid register.
-	       This will check if register number (Rt) is not undefined for LS64
-	       instructions:
-	       if Rt<4:3> == '11' || Rt<0> == '1' then UNDEFINED.  */
-	    if ((info->reg.regno & 0x18) == 0x18 || (info->reg.regno & 0x01) == 0x01)
 	    {
-	      set_syntax_error (_("invalid Rt register number in 64-byte load/store"));
-	      goto failure;
+	      /* We've already checked if this is valid register.
+		This will check if register number (Rt) is not undefined for
+		LS64 instructions:
+		if Rt<4:3> == '11' || Rt<0> == '1' then UNDEFINED.  */
+	      if ((info->reg.regno & 0x18) == 0x18
+		  || (info->reg.regno & 0x01) == 0x01)
+		{
+		  set_syntax_error
+		    (_("invalid Rt register number in 64-byte load/store"));
+		  goto failure;
+		}
+	    }
+	  else if (operands[i] == AARCH64_OPND_X16)
+	    {
+	      if (info->reg.regno != 16)
+		{
+		  goto failure;
+		}
 	    }
-	  }
 	  break;
 
 	case AARCH64_OPND_Rd_SP:
@@ -10314,6 +10324,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
   {"mops",		AARCH64_FEATURE (MOPS), AARCH64_NO_FEATURES},
   {"hbc",		AARCH64_FEATURE (HBC), AARCH64_NO_FEATURES},
   {"cssc",		AARCH64_FEATURE (CSSC), AARCH64_NO_FEATURES},
+  {"chk",		AARCH64_FEATURE (CHK), AARCH64_NO_FEATURES},
   {NULL,		AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
 };
 
diff --git a/gas/doc/c-aarch64.texi b/gas/doc/c-aarch64.texi
index 9b73fbf70b2af243c6583439eff8bd1338daa751..0cabf72e8e206d8208f4a6e22e8bb462ba705e74 100644
--- a/gas/doc/c-aarch64.texi
+++ b/gas/doc/c-aarch64.texi
@@ -259,6 +259,8 @@ automatically cause those extensions to be disabled.
  @tab Enable SVE2 SM4 Extension.  This implies @code{sm4} and @code{sve2}.
 @item @code{tme} @tab ARMv8-A @tab No
  @tab Enable Transactional Memory Extensions.
+@item @code{chk} @tab ARMv8-A @tab ARMv8-A
+ @tab Enable Check Feature Status Extension.
 @end multitable
 
 @node AArch64 Syntax
diff --git a/gas/testsuite/gas/aarch64/chk-bad-1.d b/gas/testsuite/gas/aarch64/chk-bad-1.d
new file mode 100644
index 0000000000000000000000000000000000000000..6389d05f9511c72904a58e58d228652728547194
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk-bad-1.d
@@ -0,0 +1,4 @@
+#name: Test of chkfeat extension operand
+#source: chk-bad-1.s
+#as: -march=armv8-a
+#error_output: chk-bad-1.l
diff --git a/gas/testsuite/gas/aarch64/chk-bad-1.l b/gas/testsuite/gas/aarch64/chk-bad-1.l
new file mode 100644
index 0000000000000000000000000000000000000000..b7403c21f4563cd772d32a0025c47b40a242a9f7
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk-bad-1.l
@@ -0,0 +1,13 @@
+[^ :]+: Assembler messages:
+[^ :]+:[0-9]+: Error: expected an integer or zero register at operand 1 -- `chkfeat'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat x0'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat x10'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat x17'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat x30'
+[^ :]+:[0-9]+: Error: expected an integer or zero register at operand 1 -- `chkfeat x31'
+[^ :]+:[0-9]+: Error: operand mismatch -- `chkfeat w16'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	chkfeat x16
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat xzr'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat wzr'
+[^ :]+:[0-9]+: Error: expected an integer or zero register at operand 1 -- `chkfeat sp'
diff --git a/gas/testsuite/gas/aarch64/chk-bad-1.s b/gas/testsuite/gas/aarch64/chk-bad-1.s
new file mode 100644
index 0000000000000000000000000000000000000000..5e75d58ffa8db382eb4d4d67b5f0661e6e523016
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk-bad-1.s
@@ -0,0 +1,12 @@
+	.text
+	chkfeat
+	chkfeat x0
+	chkfeat x10
+	chkfeat x17
+	chkfeat x30
+	chkfeat x31
+	chkfeat x16
+	chkfeat w16
+	chkfeat xzr
+	chkfeat wzr
+	chkfeat sp
diff --git a/gas/testsuite/gas/aarch64/chk.d b/gas/testsuite/gas/aarch64/chk.d
new file mode 100644
index 0000000000000000000000000000000000000000..6222eca4ddf1efe380bc8b5f3c91b7879f0f939b
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk.d
@@ -0,0 +1,11 @@
+#name: Test of Check Feature Status Instruction.
+#as: -march=armv8-a
+#objdump: -dr
+
+[^:]+:     file format .*
+
+
+[^:]+:
+
+[^:]+:
+.*:	d503251f 	chkfeat	x16
diff --git a/gas/testsuite/gas/aarch64/chk.s b/gas/testsuite/gas/aarch64/chk.s
new file mode 100644
index 0000000000000000000000000000000000000000..3d6dc53e0468ea9c33cbf09f2ed10232e12404e0
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk.s
@@ -0,0 +1,2 @@
+	.text
+	chkfeat x16
diff --git a/gas/testsuite/gas/aarch64/system.d b/gas/testsuite/gas/aarch64/system.d
index 6de9aeb00d1d57c81827b29f61dadc88edf8aed8..8ad274655049dd8b7ab5253f2d8b45537e50528f 100644
--- a/gas/testsuite/gas/aarch64/system.d
+++ b/gas/testsuite/gas/aarch64/system.d
@@ -55,7 +55,7 @@ Disassembly of section \.text:
 .*:	d50324bf 	hint	#0x25
 .*:	d50324df 	(hint	#0x26|bti	jc)
 .*:	d50324ff 	hint	#0x27
-.*:	d503251f 	hint	#0x28
+.*:	d503251f 	(hint	#0x28|chkfeat	x16)
 .*:	d503253f 	hint	#0x29
 .*:	d503255f 	hint	#0x2a
 .*:	d503257f 	hint	#0x2b
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index dbfbb0a4ad7957eb4cc9b44378fc6a0058af08c3..004df9ec1eb59bb60c821a96ce8f2960b76a9a7c 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -159,6 +159,8 @@ enum aarch64_feature_bit {
   AARCH64_FEATURE_CSSC,
   /* Armv8.9-A processors.  */
   AARCH64_FEATURE_V8_9A,
+  /* Check Feature Status Extension.  */
+  AARCH64_FEATURE_CHK,
   /* SME2.  */
   AARCH64_FEATURE_SME2,
   DUMMY1,
@@ -184,7 +186,8 @@ enum aarch64_feature_bit {
 #define AARCH64_ARCH_V8A_FEATURES(X)	(AARCH64_FEATBIT (X, V8A)	\
 					 | AARCH64_FEATBIT (X, FP)	\
 					 | AARCH64_FEATBIT (X, RAS)	\
-					 | AARCH64_FEATBIT (X, SIMD))
+					 | AARCH64_FEATBIT (X, SIMD)	\
+					 | AARCH64_FEATBIT (X, CHK))
 #define AARCH64_ARCH_V8_1A_FEATURES(X)	(AARCH64_FEATBIT (X, V8_1A)	\
 					 | AARCH64_FEATBIT (X, CRC)	\
 					 | AARCH64_FEATBIT (X, LSE)	\
@@ -387,6 +390,7 @@ enum aarch64_opnd
   AARCH64_OPND_Rm,	/* Integer register as source.  */
   AARCH64_OPND_Rt,	/* Integer register used in ld/st instructions.  */
   AARCH64_OPND_Rt2,	/* Integer register used in ld/st pair instructions.  */
+  AARCH64_OPND_X16,	/* Integer register x16 in chkfeat instruction.  */
   AARCH64_OPND_Rt_LS64,	/* Integer register used in LS64 instructions.  */
   AARCH64_OPND_Rt_SP,	/* Integer Rt or SP used in STG instructions.  */
   AARCH64_OPND_Rs,	/* Integer register used in ld/st exclusive.  */
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 295638d6d8c21b84ec89564199825e90d9f071e5..599bb6365374257189c3247ae0dbf0881ab6c079 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -4612,6 +4612,10 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       snprintf (buf, size, "%s", style_sub_mnem (styler, "csync"));
       break;
 
+    case AARCH64_OPND_X16:
+      snprintf (buf, size, "%s", style_reg (styler, "x16"));
+      break;
+
     case AARCH64_OPND_SME_ZT0:
       snprintf (buf, size, "%s", style_reg (styler, "zt0"));
       break;
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index dc72b13f5f7049bae18a63a5a3950013970c1d5a..8f4bfc3f2d8a2cc64a72320cb4882d35c66b208e 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -2572,6 +2572,8 @@ static const aarch64_feature_set aarch64_feature_hbc =
   AARCH64_FEATURE (HBC);
 static const aarch64_feature_set aarch64_feature_cssc =
   AARCH64_FEATURE (CSSC);
+static const aarch64_feature_set aarch64_feature_chk =
+  AARCH64_FEATURE (CHK);
 
 #define CORE		&aarch64_feature_v8
 #define FP		&aarch64_feature_fp
@@ -2630,6 +2632,7 @@ static const aarch64_feature_set aarch64_feature_cssc =
 #define MOPS_MEMTAG &aarch64_feature_mops_memtag
 #define HBC	  &aarch64_feature_hbc
 #define CSSC	  &aarch64_feature_cssc
+#define CHK	  &aarch64_feature_chk
 
 #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
@@ -2777,6 +2780,8 @@ static const aarch64_feature_set aarch64_feature_cssc =
   { NAME, OPCODE, MASK, CLASS, 0, HBC, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define CSSC_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, cssc, 0, CSSC, OPS, QUALS, FLAGS, 0, 0, NULL }
+#define CHK_INSN(NAME, OPCODE, MASK, OPS, QUALS, FLAGS) \
+  { NAME, OPCODE, MASK, ic_system, 0, CHK, OPS, QUALS, FLAGS, 0, 0, NULL }
 
 #define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \
   MOPS_INSN (NAME, OPCODE, MASK, 0, \
@@ -4106,6 +4111,7 @@ const struct aarch64_opcode aarch64_opcode_table[] =
   SME_INSN ("smstart", 0xd503417f, 0xfffff1ff, sme_start, 0, OP1 (SME_SM_ZA), {}, F_SYS_WRITE, 0),
   SME_INSN ("smstop",  0xd503407f, 0xfffff1ff, sme_stop,  0, OP1 (SME_SM_ZA), {}, F_SYS_WRITE, 0),
   /* System.  */
+  CHK_INSN ("chkfeat", 0xd503251f, 0xffffffff, OP1 (X16), QL_I1X, 0),
   CORE_INSN ("msr", 0xd500401f, 0xfff8f01f, ic_system, 0, OP2 (PSTATEFIELD, UIMM4), {}, F_SYS_WRITE),
   CORE_INSN ("hint",0xd503201f, 0xfffff01f, ic_system, 0, OP1 (UIMM7), {}, F_HAS_ALIAS),
   CORE_INSN ("nop", 0xd503201f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
@@ -6092,6 +6098,7 @@ const struct aarch64_opcode aarch64_opcode_table[] =
     Y(INT_REG, regno, "Rm", 0, F(FLD_Rm), "an integer register")	\
     Y(INT_REG, regno, "Rt", 0, F(FLD_Rt), "an integer register")	\
     Y(INT_REG, regno, "Rt2", 0, F(FLD_Rt2), "an integer register")	\
+    Y(INT_REG, none, "X16", 0, F(), "X16")	\
     Y(INT_REG, regno, "Rt_LS64", 0, F(FLD_Rt), "an integer register")	\
     Y(INT_REG, regno, "Rt_SP", OPD_F_MAYBE_SP, F(FLD_Rt),		\
       "an integer or stack pointer register")				\
  
Nick Clifton Nov. 2, 2023, 11:42 a.m. UTC | #2
Hi Srinath,

> This patch adds support for Check Feature Status Extension (CHK) which
> is mandatory from Armv8.0-A. Also this patch supports "chkfeat" instruction
> (hint #40).
> 
> Regression tested for aarch64-none-elf target and found no regressions.
> 
> Ok for binutils-master?

Approved - please apply.

Cheers
   Nick
  

Patch

diff --git a/gas/NEWS b/gas/NEWS
index 5b6bffcbdf58e3a3bcb34ba7875601cb67ca0db0..896ea2d7eb24cd7295f953ce0c619b0a778024f0 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,7 @@ 
 -*- text -*-
 
+* Add support for AArch64 Check Feature Status Extension (CHK).
+
 * Add support for 'armv8.9-a' and 'armv9.4-a' for -march in AArch64 GAS.
 
 * Add support for Intel AVX10.1.
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 7d7e54965f12e074a5cc0437accd770e1f1776e1..f5b7b427dd6b5a0bc899cc3c79f05c02005b6c5b 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -6570,6 +6570,7 @@  parse_operands (char *str, const aarch64_opcode *opcode)
 	case AARCH64_OPND_Rm:
 	case AARCH64_OPND_Rt:
 	case AARCH64_OPND_Rt2:
+	case AARCH64_OPND_X16:
 	case AARCH64_OPND_Rs:
 	case AARCH64_OPND_Ra:
 	case AARCH64_OPND_Rt_LS64:
@@ -6581,17 +6582,26 @@  parse_operands (char *str, const aarch64_opcode *opcode)
 	  /* In LS64 load/store instructions Rt register number must be even
 	     and <=22.  */
 	  if (operands[i] == AARCH64_OPND_Rt_LS64)
-	  {
-	    /* We've already checked if this is valid register.
-	       This will check if register number (Rt) is not undefined for LS64
-	       instructions:
-	       if Rt<4:3> == '11' || Rt<0> == '1' then UNDEFINED.  */
-	    if ((info->reg.regno & 0x18) == 0x18 || (info->reg.regno & 0x01) == 0x01)
 	    {
-	      set_syntax_error (_("invalid Rt register number in 64-byte load/store"));
-	      goto failure;
+	      /* We've already checked if this is valid register.
+		This will check if register number (Rt) is not undefined for
+		LS64 instructions:
+		if Rt<4:3> == '11' || Rt<0> == '1' then UNDEFINED.  */
+	      if ((info->reg.regno & 0x18) == 0x18
+		  || (info->reg.regno & 0x01) == 0x01)
+		{
+		  set_syntax_error
+		    (_("invalid Rt register number in 64-byte load/store"));
+		  goto failure;
+		}
+	    }
+	  else if (operands[i] == AARCH64_OPND_X16)
+	    {
+	      if (info->reg.regno != 16)
+		{
+		  goto failure;
+		}
 	    }
-	  }
 	  break;
 
 	case AARCH64_OPND_Rd_SP:
@@ -10314,6 +10324,7 @@  static const struct aarch64_option_cpu_value_table aarch64_features[] = {
   {"mops",		AARCH64_FEATURE (MOPS), AARCH64_NO_FEATURES},
   {"hbc",		AARCH64_FEATURE (HBC), AARCH64_NO_FEATURES},
   {"cssc",		AARCH64_FEATURE (CSSC), AARCH64_NO_FEATURES},
+  {"chk",		AARCH64_FEATURE (CHK), AARCH64_NO_FEATURES},
   {NULL,		AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
 };
 
diff --git a/gas/doc/c-aarch64.texi b/gas/doc/c-aarch64.texi
index 9b73fbf70b2af243c6583439eff8bd1338daa751..0cabf72e8e206d8208f4a6e22e8bb462ba705e74 100644
--- a/gas/doc/c-aarch64.texi
+++ b/gas/doc/c-aarch64.texi
@@ -259,6 +259,8 @@  automatically cause those extensions to be disabled.
  @tab Enable SVE2 SM4 Extension.  This implies @code{sm4} and @code{sve2}.
 @item @code{tme} @tab ARMv8-A @tab No
  @tab Enable Transactional Memory Extensions.
+@item @code{chk} @tab ARMv8-A @tab ARMv8-A
+ @tab Enable Check Feature Status Extension.
 @end multitable
 
 @node AArch64 Syntax
diff --git a/gas/testsuite/gas/aarch64/chk-bad-1.d b/gas/testsuite/gas/aarch64/chk-bad-1.d
new file mode 100644
index 0000000000000000000000000000000000000000..6389d05f9511c72904a58e58d228652728547194
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk-bad-1.d
@@ -0,0 +1,4 @@ 
+#name: Test of chkfeat extension operand
+#source: chk-bad-1.s
+#as: -march=armv8-a
+#error_output: chk-bad-1.l
diff --git a/gas/testsuite/gas/aarch64/chk-bad-1.l b/gas/testsuite/gas/aarch64/chk-bad-1.l
new file mode 100644
index 0000000000000000000000000000000000000000..b7403c21f4563cd772d32a0025c47b40a242a9f7
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk-bad-1.l
@@ -0,0 +1,13 @@ 
+[^ :]+: Assembler messages:
+[^ :]+:[0-9]+: Error: expected an integer or zero register at operand 1 -- `chkfeat'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat x0'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat x10'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat x17'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat x30'
+[^ :]+:[0-9]+: Error: expected an integer or zero register at operand 1 -- `chkfeat x31'
+[^ :]+:[0-9]+: Error: operand mismatch -- `chkfeat w16'
+[^ :]+:[0-9]+: Info:    did you mean this\?
+[^ :]+:[0-9]+: Info:    	chkfeat x16
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat xzr'
+[^ :]+:[0-9]+: Error: operand 1 must be X16 -- `chkfeat wzr'
+[^ :]+:[0-9]+: Error: expected an integer or zero register at operand 1 -- `chkfeat sp'
diff --git a/gas/testsuite/gas/aarch64/chk-bad-1.s b/gas/testsuite/gas/aarch64/chk-bad-1.s
new file mode 100644
index 0000000000000000000000000000000000000000..5e75d58ffa8db382eb4d4d67b5f0661e6e523016
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk-bad-1.s
@@ -0,0 +1,12 @@ 
+	.text
+	chkfeat
+	chkfeat x0
+	chkfeat x10
+	chkfeat x17
+	chkfeat x30
+	chkfeat x31
+	chkfeat x16
+	chkfeat w16
+	chkfeat xzr
+	chkfeat wzr
+	chkfeat sp
diff --git a/gas/testsuite/gas/aarch64/chk.d b/gas/testsuite/gas/aarch64/chk.d
new file mode 100644
index 0000000000000000000000000000000000000000..6222eca4ddf1efe380bc8b5f3c91b7879f0f939b
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk.d
@@ -0,0 +1,11 @@ 
+#name: Test of Check Feature Status Instruction.
+#as: -march=armv8-a
+#objdump: -dr
+
+[^:]+:     file format .*
+
+
+[^:]+:
+
+[^:]+:
+.*:	d503251f 	chkfeat	x16
diff --git a/gas/testsuite/gas/aarch64/chk.s b/gas/testsuite/gas/aarch64/chk.s
new file mode 100644
index 0000000000000000000000000000000000000000..3d6dc53e0468ea9c33cbf09f2ed10232e12404e0
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/chk.s
@@ -0,0 +1,2 @@ 
+	.text
+	chkfeat x16
diff --git a/gas/testsuite/gas/aarch64/system.d b/gas/testsuite/gas/aarch64/system.d
index 6de9aeb00d1d57c81827b29f61dadc88edf8aed8..8ad274655049dd8b7ab5253f2d8b45537e50528f 100644
--- a/gas/testsuite/gas/aarch64/system.d
+++ b/gas/testsuite/gas/aarch64/system.d
@@ -55,7 +55,7 @@  Disassembly of section \.text:
 .*:	d50324bf 	hint	#0x25
 .*:	d50324df 	(hint	#0x26|bti	jc)
 .*:	d50324ff 	hint	#0x27
-.*:	d503251f 	hint	#0x28
+.*:	d503251f 	(hint	#0x28|chkfeat	x16)
 .*:	d503253f 	hint	#0x29
 .*:	d503255f 	hint	#0x2a
 .*:	d503257f 	hint	#0x2b
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index dbfbb0a4ad7957eb4cc9b44378fc6a0058af08c3..004df9ec1eb59bb60c821a96ce8f2960b76a9a7c 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -159,6 +159,8 @@  enum aarch64_feature_bit {
   AARCH64_FEATURE_CSSC,
   /* Armv8.9-A processors.  */
   AARCH64_FEATURE_V8_9A,
+  /* Check Feature Status Extension.  */
+  AARCH64_FEATURE_CHK,
   /* SME2.  */
   AARCH64_FEATURE_SME2,
   DUMMY1,
@@ -184,7 +186,8 @@  enum aarch64_feature_bit {
 #define AARCH64_ARCH_V8A_FEATURES(X)	(AARCH64_FEATBIT (X, V8A)	\
 					 | AARCH64_FEATBIT (X, FP)	\
 					 | AARCH64_FEATBIT (X, RAS)	\
-					 | AARCH64_FEATBIT (X, SIMD))
+					 | AARCH64_FEATBIT (X, SIMD)	\
+					 | AARCH64_FEATBIT (X, CHK))
 #define AARCH64_ARCH_V8_1A_FEATURES(X)	(AARCH64_FEATBIT (X, V8_1A)	\
 					 | AARCH64_FEATBIT (X, CRC)	\
 					 | AARCH64_FEATBIT (X, LSE)	\
@@ -387,6 +390,7 @@  enum aarch64_opnd
   AARCH64_OPND_Rm,	/* Integer register as source.  */
   AARCH64_OPND_Rt,	/* Integer register used in ld/st instructions.  */
   AARCH64_OPND_Rt2,	/* Integer register used in ld/st pair instructions.  */
+  AARCH64_OPND_X16,	/* Integer register x16 in chkfeat instruction.  */
   AARCH64_OPND_Rt_LS64,	/* Integer register used in LS64 instructions.  */
   AARCH64_OPND_Rt_SP,	/* Integer Rt or SP used in STG instructions.  */
   AARCH64_OPND_Rs,	/* Integer register used in ld/st exclusive.  */
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 295638d6d8c21b84ec89564199825e90d9f071e5..599bb6365374257189c3247ae0dbf0881ab6c079 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -4612,6 +4612,10 @@  aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
       snprintf (buf, size, "%s", style_sub_mnem (styler, "csync"));
       break;
 
+    case AARCH64_OPND_X16:
+      snprintf (buf, size, "%s", style_reg (styler, "x16"));
+      break;
+
     case AARCH64_OPND_SME_ZT0:
       snprintf (buf, size, "%s", style_reg (styler, "zt0"));
       break;
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index dc72b13f5f7049bae18a63a5a3950013970c1d5a..8f4bfc3f2d8a2cc64a72320cb4882d35c66b208e 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -2572,6 +2572,8 @@  static const aarch64_feature_set aarch64_feature_hbc =
   AARCH64_FEATURE (HBC);
 static const aarch64_feature_set aarch64_feature_cssc =
   AARCH64_FEATURE (CSSC);
+static const aarch64_feature_set aarch64_feature_chk =
+  AARCH64_FEATURE (CHK);
 
 #define CORE		&aarch64_feature_v8
 #define FP		&aarch64_feature_fp
@@ -2630,6 +2632,7 @@  static const aarch64_feature_set aarch64_feature_cssc =
 #define MOPS_MEMTAG &aarch64_feature_mops_memtag
 #define HBC	  &aarch64_feature_hbc
 #define CSSC	  &aarch64_feature_cssc
+#define CHK	  &aarch64_feature_chk
 
 #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, 0, NULL }
@@ -2777,6 +2780,8 @@  static const aarch64_feature_set aarch64_feature_cssc =
   { NAME, OPCODE, MASK, CLASS, 0, HBC, OPS, QUALS, FLAGS, 0, 0, NULL }
 #define CSSC_INSN(NAME,OPCODE,MASK,OPS,QUALS,FLAGS) \
   { NAME, OPCODE, MASK, cssc, 0, CSSC, OPS, QUALS, FLAGS, 0, 0, NULL }
+#define CHK_INSN(NAME, OPCODE, MASK, OPS, QUALS, FLAGS) \
+  { NAME, OPCODE, MASK, ic_system, 0, CHK, OPS, QUALS, FLAGS, 0, 0, NULL }
 
 #define MOPS_CPY_OP1_OP2_PME_INSN(NAME, OPCODE, MASK, FLAGS, CONSTRAINTS) \
   MOPS_INSN (NAME, OPCODE, MASK, 0, \
@@ -4106,6 +4111,7 @@  const struct aarch64_opcode aarch64_opcode_table[] =
   SME_INSN ("smstart", 0xd503417f, 0xfffff1ff, sme_start, 0, OP1 (SME_SM_ZA), {}, F_SYS_WRITE, 0),
   SME_INSN ("smstop",  0xd503407f, 0xfffff1ff, sme_stop,  0, OP1 (SME_SM_ZA), {}, F_SYS_WRITE, 0),
   /* System.  */
+  CHK_INSN ("chkfeat", 0xd503251f, 0xffffffff, OP1 (X16), QL_I1X, 0),
   CORE_INSN ("msr", 0xd500401f, 0xfff8f01f, ic_system, 0, OP2 (PSTATEFIELD, UIMM4), {}, F_SYS_WRITE),
   CORE_INSN ("hint",0xd503201f, 0xfffff01f, ic_system, 0, OP1 (UIMM7), {}, F_HAS_ALIAS),
   CORE_INSN ("nop", 0xd503201f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS),
@@ -6092,6 +6098,7 @@  const struct aarch64_opcode aarch64_opcode_table[] =
     Y(INT_REG, regno, "Rm", 0, F(FLD_Rm), "an integer register")	\
     Y(INT_REG, regno, "Rt", 0, F(FLD_Rt), "an integer register")	\
     Y(INT_REG, regno, "Rt2", 0, F(FLD_Rt2), "an integer register")	\
+    Y(INT_REG, none, "X16", 0, F(), "X16")	\
     Y(INT_REG, regno, "Rt_LS64", 0, F(FLD_Rt), "an integer register")	\
     Y(INT_REG, regno, "Rt_SP", OPD_F_MAYBE_SP, F(FLD_Rt),		\
       "an integer or stack pointer register")				\