aarch64: warn on unpredictable results for new rcpc3 instructions

Message ID 2435c8da-08ae-4ba4-a3db-1e25a91e2c0c@arm.com
State Committed
Headers
Series aarch64: warn on unpredictable results for new rcpc3 instructions |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Testing passed

Commit Message

Matthieu Longo June 7, 2024, 9:29 a.m. UTC
  The previous patch for the feature rcpc3 introduced 4 new operations 
(ldiapp, stilp, ldapr, stlr).
The specification mentions some cases of inputs causing unpredictable 
results. gas currently fails
to diagnose them, and does not emit warnings. Even if the instruction 
encoding is valid, the
developer probably wants to know for those cases that the instruction 
won't have the expected
effect.
- ldiapp & stilp:
   * unpredictable load pair transfer with register overlap
   * unpredictable transfer with writeback
- ldapr & stlr:
   * unpredictable transfer with writeback

This patch also completes the existing relevant tests.

Regression tested on aarch64-none-elf, and no regression found.

Ok for binutils-master? I don't have commit access so I need someone
to commit on my behalf.

Regards,
Matthieu.
From dbd3e4a9d535704a0d11f9584e05c039ccf8fc1f Mon Sep 17 00:00:00 2001
From: Matthieu Longo <matthieu.longo@arm.com>
Date: Tue, 21 May 2024 17:37:07 +0100
Subject: [PATCH] aarch64: warn on unpredictable results for new rcpc3
 instructions

The previous patch for the feature rcpc3 introduced 4 new operations
(ldiapp, stilp, ldapr, stlr).
The specification mentions some cases of inputs causing unpredictable
results. gas currently fails to diagnose them, and does not emit
warnings. Even if the instruction encoding is valid, the developer
probably wants to know for those cases that the instruction won't have
the expected effect.
- ldiapp & stilp:
  * unpredictable load pair transfer with register overlap
  * unpredictable transfer with writeback
- ldapr & stlr:
  * unpredictable transfer with writeback

This patch also completes the existing relevant tests.
---
 gas/config/tc-aarch64.c                |  40 +++++++++-
 gas/testsuite/gas/aarch64/rcpc3-fail.d |   1 +
 gas/testsuite/gas/aarch64/rcpc3-fail.l |  86 +++++++++++++++++---
 gas/testsuite/gas/aarch64/rcpc3-fail.s | 104 ++++++++++++++++++++++++-
 gas/testsuite/gas/aarch64/rcpc3.d      |  59 +++++++++++---
 gas/testsuite/gas/aarch64/rcpc3.s      |  42 ++++++++++
 6 files changed, 306 insertions(+), 26 deletions(-)
  

Comments

Richard Earnshaw (lists) June 10, 2024, 3:26 p.m. UTC | #1
On 07/06/2024 10:29, Matthieu Longo wrote:
> The previous patch for the feature rcpc3 introduced 4 new operations (ldiapp, stilp, ldapr, stlr).
> The specification mentions some cases of inputs causing unpredictable results. gas currently fails
> to diagnose them, and does not emit warnings. Even if the instruction encoding is valid, the
> developer probably wants to know for those cases that the instruction won't have the expected
> effect.
> - ldiapp & stilp:
>   * unpredictable load pair transfer with register overlap
>   * unpredictable transfer with writeback
> - ldapr & stlr:
>   * unpredictable transfer with writeback
> 
> This patch also completes the existing relevant tests.
> 
> Regression tested on aarch64-none-elf, and no regression found.
> 
> Ok for binutils-master? I don't have commit access so I need someone
> to commit on my behalf.
> 
> Regards,
> Matthieu.

Pushed, thanks.

R.
  

Patch

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index fec17c40a43..73b733ff727 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -3875,7 +3875,7 @@  parse_shifter_operand_reloc (char **str, aarch64_opnd_info *operand,
       if (! aarch64_get_expression (&inst.reloc.exp, str, GE_NO_PREFIX,
 				    REJECT_ABSENT))
 	return false;
-      
+
       /* Record the relocation type (use the ADD variant here).  */
       inst.reloc.type = entry->add_type;
       inst.reloc.pc_rel = entry->pc_rel;
@@ -8330,6 +8330,44 @@  warn_unpredictable_ldst (aarch64_instruction *instr, char *str)
 	as_warn (_("unpredictable transfer with writeback -- `%s'"), str);
       break;
 
+    case rcpc3:
+      {
+	const int nb_operands = aarch64_num_of_operands (opcode);
+	if (aarch64_get_operand_class (opnds[0].type)
+	    == AARCH64_OPND_CLASS_INT_REG)
+	  {
+	    /* Load Pair transfer with register overlap. */
+	    if (nb_operands == 3 && opnds[0].reg.regno == opnds[1].reg.regno)
+	      { // ldiapp, stilp
+		as_warn (_("unpredictable load pair transfer with register "
+			   "overlap -- `%s'"),
+			 str);
+	      }
+	    /* Loading/storing the base register is unpredictable if writeback. */
+	    else if ((nb_operands == 2
+		      && opnds[0].reg.regno == opnds[1].addr.base_regno
+		      && opnds[1].addr.base_regno != REG_SP
+		      && opnds[1].addr.writeback)
+		     || (nb_operands == 3
+			 && (opnds[0].reg.regno == opnds[2].addr.base_regno
+			     || opnds[1].reg.regno == opnds[2].addr.base_regno)
+			 && opnds[2].addr.base_regno != REG_SP
+			 && opnds[2].addr.writeback))
+	      {
+		if (strcmp (opcode->name, "ldapr") == 0
+		    || strcmp (opcode->name, "ldiapp") == 0)
+		  as_warn (
+		    _("unpredictable transfer with writeback (load) -- `%s'"),
+		    str);
+		else // stlr, stilp
+		  as_warn (
+		    _("unpredictable transfer with writeback (store) -- `%s'"),
+		    str);
+	      }
+	  }
+      }
+      break;
+
     case ldstpair_off:
     case ldstnapair_offs:
     case ldstpair_indexed:
diff --git a/gas/testsuite/gas/aarch64/rcpc3-fail.d b/gas/testsuite/gas/aarch64/rcpc3-fail.d
index 508a27f5a39..e9a63a295e1 100644
--- a/gas/testsuite/gas/aarch64/rcpc3-fail.d
+++ b/gas/testsuite/gas/aarch64/rcpc3-fail.d
@@ -1,3 +1,4 @@ 
 #name: RCPC3 GPR load/store illegal
+#source: rcpc3-fail.s
 #as: -march=armv8.3-a+rcpc3 -mno-verbose-error
 #error_output: rcpc3-fail.l
diff --git a/gas/testsuite/gas/aarch64/rcpc3-fail.l b/gas/testsuite/gas/aarch64/rcpc3-fail.l
index 4b33c8524e5..96c2f0aee6c 100644
--- a/gas/testsuite/gas/aarch64/rcpc3-fail.l
+++ b/gas/testsuite/gas/aarch64/rcpc3-fail.l
@@ -1,9 +1,77 @@ 
-[^:]+: Assembler messages:
-[^:]+:3: Error: operand 3 must be an address with post-incrementing by ammount of loaded bytes -- `ldiapp w0,w1,\[x3,#8\]'
-[^:]+:4: Error: operand 3 must be an address with post-incrementing by ammount of loaded bytes -- `ldiapp x0,x1,\[x3,#16\]'
-[^:]+:6: Error: operand 3 must be an address with pre-incrementing with write-back by ammount of stored bytes -- `stilp w0,w1,\[x3,#8\]'
-[^:]+:7: Error: operand 3 must be an address with pre-incrementing with write-back by ammount of stored bytes -- `stilp x0,x1,\[x3,#16\]'
-[^:]+:9: Error: invalid addressing mode at operand 3 -- `stilp w0,w1,\[x3\],#8'
-[^:]+:10: Error: invalid addressing mode at operand 3 -- `stilp x0,x1,\[x3\],#16'
-[^:]+:12: Error: invalid addressing mode at operand 3 -- `ldiapp w0,w1,\[x3,#-8\]!'
-[^:]+:13: Error: invalid addressing mode at operand 3 -- `ldiapp x0,x1,\[x3,#-16\]!'
+.*: Assembler messages:
+.*: Error: operand 3 must be an address with post-incrementing by ammount of loaded bytes -- `ldiapp w0,w1,\[x3,#8\]'
+.*: Error: operand 3 must be an address with post-incrementing by ammount of loaded bytes -- `ldiapp x0,x1,\[x3,#16\]'
+.*: Error: invalid addressing mode at operand 3 -- `ldiapp w0,w1,\[x3,#-8\]!'
+.*: Error: invalid addressing mode at operand 3 -- `ldiapp x0,x1,\[x3,#-16\]!'
+.*: Error: expected an integer or zero register at operand 1 -- `ldiapp sp,x1,\[x3\],#16'
+.*: Error: expected an integer or zero register at operand 1 -- `ldiapp wsp,w1,\[x3\],#8'
+.*: Error: expected an integer or zero register at operand 2 -- `ldiapp x0,sp,\[x3\],#16'
+.*: Error: expected an integer or zero register at operand 2 -- `ldiapp w0,wsp,\[x3\],#8'
+.*: Error: invalid base register at operand 3 -- `ldiapp x0,x1,\[xzr\],#16'
+.*: Error: invalid base register at operand 3 -- `ldiapp x0,x1,\[wzr\],#16'
+.*: Error: expected a 64-bit base register at operand 3 -- `ldiapp w0,w1,\[w3\],#8'
+.*: Error: invalid increment amount at operand 3 -- `ldiapp x0,x1,\[x3\],#8'
+.*: Error: invalid increment amount at operand 3 -- `ldiapp w0,w1,\[x3\],#16'
+.*: Error: operand 3 must be an address with pre-incrementing with write-back by ammount of stored bytes -- `stilp w0,w1,\[x3,#8\]'
+.*: Error: operand 3 must be an address with pre-incrementing with write-back by ammount of stored bytes -- `stilp x0,x1,\[x3,#16\]'
+.*: Error: invalid addressing mode at operand 3 -- `stilp w0,w1,\[x3\],#8'
+.*: Error: invalid addressing mode at operand 3 -- `stilp x0,x1,\[x3\],#16'
+.*: Error: expected an integer or zero register at operand 1 -- `stilp sp,x1,\[x3,#-16\]!'
+.*: Error: expected an integer or zero register at operand 1 -- `stilp wsp,w1,\[x3,#-8\]!'
+.*: Error: expected an integer or zero register at operand 2 -- `stilp x0,sp,\[x3,#-16\]!'
+.*: Error: expected an integer or zero register at operand 2 -- `stilp w0,wsp,\[x3,#-8\]!'
+.*: Error: invalid base register at operand 3 -- `stilp x0,x1,\[xzr,#-16\]!'
+.*: Error: invalid base register at operand 3 -- `stilp x0,x1,\[wzr,#-16\]!'
+.*: Error: expected a 64-bit base register at operand 3 -- `stilp w0,w1,\[w3,#-8\]!'
+.*: Error: invalid increment amount at operand 3 -- `stilp w0,w1,\[x3,#-16\]!'
+.*: Error: invalid increment amount at operand 3 -- `stilp x0,x1,\[x3,#-8\]!'
+.*: Error: invalid increment amount at operand 3 -- `stilp w0,w1,\[x3,#16\]!'
+.*: Error: invalid increment amount at operand 3 -- `stilp x0,x1,\[x3,#8\]!'
+.*: Error: the optional immediate offset can only be 0 at operand 2 -- `ldapr w0,\[x1,#4\]'
+.*: Error: the optional immediate offset can only be 0 at operand 2 -- `ldapr x0,\[x1,#8\]'
+.*: Error: unexpected address writeback at operand 2 -- `ldapr w0,\[x1,#-4\]!'
+.*: Error: unexpected address writeback at operand 2 -- `ldapr x0,\[x1,#-8\]!'
+.*: Error: expected an integer or zero register at operand 1 -- `ldapr wsp,\[x0\],#4'
+.*: Error: expected an integer or zero register at operand 1 -- `ldapr sp,\[x0\],#8'
+.*: Error: invalid base register at operand 2 -- `ldapr x0,\[wzr\],#8'
+.*: Error: invalid base register at operand 2 -- `ldapr x0,\[xzr\],#8'
+.*: Error: expected a 64-bit base register at operand 2 -- `ldapr x0,\[w1\],#8'
+.*: Error: invalid increment amount at operand 2 -- `ldapr w0,\[x1\],#8'
+.*: Error: invalid increment amount at operand 2 -- `ldapr x0,\[x1\],#4'
+.*: Error: unexpected address writeback at operand 2 -- `stlr w0,\[x1\],#4'
+.*: Error: unexpected address writeback at operand 2 -- `stlr x0,\[x1\],#8'
+.*: Error: expected an integer or zero register at operand 1 -- `stlr wsp,\[x0,#-4\]!'
+.*: Error: expected an integer or zero register at operand 1 -- `stlr sp,\[x0,#-8\]!'
+.*: Error: invalid base register at operand 2 -- `stlr x0,\[xzr,#-8\]!'
+.*: Error: invalid base register at operand 2 -- `stlr x0,\[wzr,#-8\]!'
+.*: Error: expected a 64-bit base register at operand 2 -- `stlr x0,\[w1,#-8\]!'
+.*: Error: the optional immediate offset can only be 0 at operand 2 -- `stlr w0,\[x1,#4\]'
+.*: Error: the optional immediate offset can only be 0 at operand 2 -- `stlr x0,\[x1,#8\]'
+.*: Error: invalid increment amount at operand 2 -- `stlr w0,\[x1,#-8\]!'
+.*: Error: invalid increment amount at operand 2 -- `stlr x0,\[x1,#-4\]!'
+.*: Error: invalid increment amount at operand 2 -- `stlr w0,\[x1,#4\]!'
+.*: Error: invalid increment amount at operand 2 -- `stlr x0,\[x1,#8\]!'
+.*: Warning: unpredictable load pair transfer with register overlap -- `ldiapp w0,w0,\[x1\]'
+.*: Warning: unpredictable load pair transfer with register overlap -- `ldiapp x0,x0,\[x1\]'
+.*: Warning: unpredictable load pair transfer with register overlap -- `ldiapp w0,w0,\[x1\],#8'
+.*: Warning: unpredictable load pair transfer with register overlap -- `ldiapp x0,x0,\[x1\],#16'
+.*: Warning: unpredictable load pair transfer with register overlap -- `stilp w0,w0,\[x1\]'
+.*: Warning: unpredictable load pair transfer with register overlap -- `stilp x0,x0,\[x1\]'
+.*: Warning: unpredictable load pair transfer with register overlap -- `stilp w0,w0,\[x1,#-8\]!'
+.*: Warning: unpredictable load pair transfer with register overlap -- `stilp x0,x0,\[x1,#-16\]!'
+.*: Warning: unpredictable transfer with writeback \(load\) -- `ldiapp x0,x1,\[x0\],#16'
+.*: Warning: unpredictable transfer with writeback \(load\) -- `ldiapp x0,x1,\[x1\],#16'
+.*: Warning: unpredictable transfer with writeback \(load\) -- `ldiapp w0,w1,\[x0\],#8'
+.*: Warning: unpredictable transfer with writeback \(load\) -- `ldiapp w0,w1,\[x1\],#8'
+.*: Warning: unpredictable transfer with writeback \(load\) -- `ldapr x0,\[x0\],#8'
+.*: Warning: unpredictable transfer with writeback \(load\) -- `ldapr w0,\[x0\],#4'
+.*: Warning: unpredictable transfer with writeback \(load\) -- `ldapr x1,\[x1\],#8'
+.*: Warning: unpredictable transfer with writeback \(load\) -- `ldapr x30,\[x30\],#8'
+.*: Warning: unpredictable transfer with writeback \(store\) -- `stilp x0,x1,\[x1,#-16\]!'
+.*: Warning: unpredictable transfer with writeback \(store\) -- `stilp w0,w1,\[x1,#-8\]!'
+.*: Warning: unpredictable transfer with writeback \(store\) -- `stilp x0,x1,\[x0,#-16\]!'
+.*: Warning: unpredictable transfer with writeback \(store\) -- `stilp w0,w1,\[x0,#-8\]!'
+.*: Warning: unpredictable transfer with writeback \(store\) -- `stlr x0,\[x0,#-8\]!'
+.*: Warning: unpredictable transfer with writeback \(store\) -- `stlr w0,\[x0,#-4\]!'
+.*: Warning: unpredictable transfer with writeback \(store\) -- `stlr x1,\[x1,#-8\]!'
+.*: Warning: unpredictable transfer with writeback \(store\) -- `stlr x30,\[x30,#-8\]!'
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/rcpc3-fail.s b/gas/testsuite/gas/aarch64/rcpc3-fail.s
index 23b9eaaf19a..687bdd7c700 100644
--- a/gas/testsuite/gas/aarch64/rcpc3-fail.s
+++ b/gas/testsuite/gas/aarch64/rcpc3-fail.s
@@ -1,13 +1,109 @@ 
 .text
-
+	/* Check invalid operands */
+	// wrong addressing mode
 	ldiapp w0, w1, [x3, #8]
 	ldiapp x0, x1, [x3, #16]
+	ldiapp w0, w1, [x3, #-8]!
+	ldiapp x0, x1, [x3, #-16]!
+	// wrong operand 1
+	ldiapp sp, x1, [x3], #16
+	ldiapp wsp, w1, [x3], #8
+	// wrong operand 2
+	ldiapp x0, sp, [x3], #16
+	ldiapp w0, wsp, [x3], #8
+	// wrong base register
+	ldiapp x0, x1, [xzr], #16
+	ldiapp x0, x1, [wzr], #16
+	ldiapp w0, w1, [w3], #8
+	// wrong increment amount
+	ldiapp x0, x1, [x3], #8
+	ldiapp w0, w1, [x3], #16
 
+	// wrong addressing mode
 	stilp w0, w1, [x3, #8]
 	stilp x0, x1, [x3, #16]
-
 	stilp w0, w1, [x3], #8
 	stilp x0, x1, [x3], #16
+	// wrong operand 1
+	stilp sp, x1, [x3, #-16]!
+	stilp wsp, w1, [x3, #-8]!
+	// wrong operand 2
+	stilp x0, sp, [x3, #-16]!
+	stilp w0, wsp, [x3, #-8]!
+	// wrong base register
+	stilp x0, x1, [xzr, #-16]!
+	stilp x0, x1, [wzr, #-16]!
+	stilp w0, w1, [w3, #-8]!
+	// wrong increment amount
+	stilp w0, w1, [x3, #-16]!
+	stilp x0, x1, [x3, #-8]!
+	stilp w0, w1, [x3, #16]!
+	stilp x0, x1, [x3, #8]!
 
-	ldiapp w0, w1, [x3, #-8]!
-	ldiapp x0, x1, [x3, #-16]!
+	// wrong addressing mode
+	ldapr w0, [x1, #4]
+	ldapr x0, [x1, #8]
+	ldapr w0, [x1, #-4]!
+	ldapr x0, [x1, #-8]!
+	// wrong operand 1
+	ldapr wsp, [x0], #4
+	ldapr sp, [x0], #8
+	// wrong base register
+	ldapr x0, [wzr], #8
+	ldapr x0, [xzr], #8
+	ldapr x0, [w1], #8
+	// wrong increment amount
+	ldapr w0, [x1], #8
+	ldapr x0, [x1], #4
+
+	// wrong addressing mode
+	stlr w0, [x1], #4
+	stlr x0, [x1], #8
+	// wrong operand 1
+	stlr wsp, [x0, #-4]!
+	stlr sp, [x0, #-8]!
+	// wrong base register
+	stlr x0, [xzr, #-8]!
+	stlr x0, [wzr, #-8]!
+	stlr x0, [w1, #-8]!
+	// wrong immediate offset
+	stlr w0, [x1, #4]
+	stlr x0, [x1, #8]
+	// wrong increment amount
+	stlr w0, [x1, #-8]!
+	stlr x0, [x1, #-4]!
+	stlr w0, [x1, #4]!
+	stlr x0, [x1, #8]!
+
+	/* Invalid load pair transfer with register overlap */
+	ldiapp w0, w0, [x1]
+	ldiapp x0, x0, [x1]
+	ldiapp w0, w0, [x1], #8
+	ldiapp x0, x0, [x1], #16
+
+	stilp w0, w0, [x1]
+	stilp x0, x0, [x1]
+	stilp w0, w0, [x1, #-8]!
+	stilp x0, x0, [x1, #-16]!
+
+	/* Invalid write back overlap (load)*/
+	ldiapp x0, x1, [x0], #16
+	ldiapp x0, x1, [x1], #16
+	ldiapp w0, w1, [x0], #8
+	ldiapp w0, w1, [x1], #8
+
+	ldapr x0, [x0], #8
+	ldapr w0, [x0], #4
+	ldapr x1, [x1], #8
+	ldapr x30, [x30], #8
+
+	/* Invalid write back overlap (store)*/
+	stilp x0, x1, [x1, #-16]!
+	stilp w0, w1, [x1, #-8]!
+	stilp x0, x1, [x0, #-16]!
+	stilp w0, w1, [x0, #-8]!
+
+	stlr x0, [x0, #-8]!
+	stlr w0, [x0, #-4]!
+	stlr x1, [x1, #-8]!
+	stlr x30, [x30, #-8]!
diff --git a/gas/testsuite/gas/aarch64/rcpc3.d b/gas/testsuite/gas/aarch64/rcpc3.d
index 4560ed09e5d..575e46e56ba 100644
--- a/gas/testsuite/gas/aarch64/rcpc3.d
+++ b/gas/testsuite/gas/aarch64/rcpc3.d
@@ -1,4 +1,5 @@ 
 #name: RCPC3 GPR load/store
+#source: rcpc3.s
 #as: -march=armv8.2-a+rcpc3
 #objdump: -dr
 
@@ -7,15 +8,49 @@ 
 Disassembly of section \.text:
 
 0+ <.*>:
-   0:	d9411860 	ldiapp	x0, x1, \[x3\]
-   4:	99411860 	ldiapp	w0, w1, \[x3\]
-   8:	d9410860 	ldiapp	x0, x1, \[x3\], #16
-   c:	99410860 	ldiapp	w0, w1, \[x3\], #8
-  10:	d9011860 	stilp	x0, x1, \[x3\]
-  14:	99011860 	stilp	w0, w1, \[x3\]
-  18:	d9010860 	stilp	x0, x1, \[x3, #-16\]!
-  1c:	99010860 	stilp	w0, w1, \[x3, #-8\]!
-  20:	99c00841 	ldapr	w1, \[x2\], #4
-  24:	d9c00841 	ldapr	x1, \[x2\], #8
-  28:	99800841 	stlr	w1, \[x2, #-4\]!
-  2c:	d9800841 	stlr	x1, \[x2, #-8\]!
+[^:]+:	d9411860 	ldiapp	x0, x1, \[x3\]
+[^:]+:	99411860 	ldiapp	w0, w1, \[x3\]
+[^:]+:	d9410860 	ldiapp	x0, x1, \[x3\], #16
+[^:]+:	99410860 	ldiapp	w0, w1, \[x3\], #8
+[^:]+:	d9410bc0 	ldiapp	x0, x1, \[x30\], #16
+[^:]+:	d95e081d 	ldiapp	x29, x30, \[x0\], #16
+[^:]+:	d941087f 	ldiapp	xzr, x1, \[x3\], #16
+[^:]+:	9941087f 	ldiapp	wzr, w1, \[x3\], #8
+[^:]+:	d9410be0 	ldiapp	x0, x1, \[sp\], #16
+[^:]+:	99410be0 	ldiapp	w0, w1, \[sp\], #8
+[^:]+:	d9411800 	ldiapp	x0, x1, \[x0\]
+[^:]+:	d9411820 	ldiapp	x0, x1, \[x1\]
+[^:]+:	99411800 	ldiapp	w0, w1, \[x0\]
+[^:]+:	99411820 	ldiapp	w0, w1, \[x1\]
+[^:]+:	d9011860 	stilp	x0, x1, \[x3\]
+[^:]+:	99011860 	stilp	w0, w1, \[x3\]
+[^:]+:	d9010860 	stilp	x0, x1, \[x3, #-16\]!
+[^:]+:	99010860 	stilp	w0, w1, \[x3, #-8\]!
+[^:]+:	d9011820 	stilp	x0, x1, \[x1\]
+[^:]+:	d9011800 	stilp	x0, x1, \[x0\]
+[^:]+:	99011820 	stilp	w0, w1, \[x1\]
+[^:]+:	99011800 	stilp	w0, w1, \[x0\]
+[^:]+:	b8bfc020 	ldapr	w0, \[x1\]
+[^:]+:	b8bfc020 	ldapr	w0, \[x1\]
+[^:]+:	f8bfc020 	ldapr	x0, \[x1\]
+[^:]+:	f8bfc020 	ldapr	x0, \[x1\]
+[^:]+:	99c00841 	ldapr	w1, \[x2\], #4
+[^:]+:	d9c00841 	ldapr	x1, \[x2\], #8
+[^:]+:	d9c0081e 	ldapr	x30, \[x0\], #8
+[^:]+:	d9c00bc0 	ldapr	x0, \[x30\], #8
+[^:]+:	99c0083f 	ldapr	wzr, \[x1\], #4
+[^:]+:	d9c0083f 	ldapr	xzr, \[x1\], #8
+[^:]+:	99c00be0 	ldapr	w0, \[sp\], #4
+[^:]+:	d9c00be0 	ldapr	x0, \[sp\], #8
+[^:]+:	889ffc20 	stlr	w0, \[x1\]
+[^:]+:	889ffc20 	stlr	w0, \[x1\]
+[^:]+:	c89ffc20 	stlr	x0, \[x1\]
+[^:]+:	c89ffc20 	stlr	x0, \[x1\]
+[^:]+:	99800841 	stlr	w1, \[x2, #-4\]!
+[^:]+:	d9800841 	stlr	x1, \[x2, #-8\]!
+[^:]+:	d980081e 	stlr	x30, \[x0, #-8\]!
+[^:]+:	d9800bc0 	stlr	x0, \[x30, #-8\]!
+[^:]+:	9980083f 	stlr	wzr, \[x1, #-4\]!
+[^:]+:	d980083f 	stlr	xzr, \[x1, #-8\]!
+[^:]+:	99800be0 	stlr	w0, \[sp, #-4\]!
+[^:]+:	d9800be0 	stlr	x0, \[sp, #-8\]!
diff --git a/gas/testsuite/gas/aarch64/rcpc3.s b/gas/testsuite/gas/aarch64/rcpc3.s
index 2a877341e41..41026d4ca04 100644
--- a/gas/testsuite/gas/aarch64/rcpc3.s
+++ b/gas/testsuite/gas/aarch64/rcpc3.s
@@ -4,14 +4,56 @@ 
 	ldiapp w0, w1, [x3]
 	ldiapp x0, x1, [x3], #16
 	ldiapp w0, w1, [x3], #8
+	ldiapp x0, x1, [x30], #16
+	ldiapp x29, x30, [x0], #16
+	ldiapp xzr, x1, [x3], #16
+	ldiapp wzr, w1, [x3], #8
+	ldiapp x0, x1, [sp], #16
+	ldiapp w0, w1, [sp], #8
+	// Note: the following examples have a register overlap between source and
+	// destination registers, but the doc mentions that, in the case where no
+	// offset is specified, writeback is disabled, and so the writeback overlap
+	// for load is fine.
+	ldiapp x0, x1, [x0]
+	ldiapp x0, x1, [x1]
+	ldiapp w0, w1, [x0]
+	ldiapp w0, w1, [x1]
 
 	stilp x0, x1, [x3]
 	stilp w0, w1, [x3]
 	stilp x0, x1, [x3, #-16]!
 	stilp w0, w1, [x3, #-8]!
+	// Note: the following examples have a register overlap between source and
+	// destination registers, but the doc mentions that, in the case where no
+	// offset is specified, writeback is disabled, and so the writeback overlap
+	// for store is fine.
+	stilp x0, x1, [x1]
+	stilp x0, x1, [x0]
+	stilp w0, w1, [x1]
+	stilp w0, w1, [x0]
 
+	ldapr w0, [x1]
+	ldapr w0, [x1, #0]
+	ldapr x0, [x1]
+	ldapr x0, [x1, #0]
 	ldapr w1, [x2], #4
 	ldapr x1, [x2], #8
+	ldapr x30, [x0], #8
+	ldapr x0, [x30], #8
+	ldapr wzr, [x1], #4
+	ldapr xzr, [x1], #8
+	ldapr w0, [sp], #4
+	ldapr x0, [sp], #8
 
+	stlr w0, [x1]
+	stlr w0, [x1, #0]
+	stlr x0, [x1]
+	stlr x0, [x1, #0]
 	stlr w1, [x2, #-4]!
 	stlr x1, [x2, #-8]!
+	stlr x30, [x0, #-8]!
+	stlr x0, [x30, #-8]!
+	stlr wzr, [x1, #-4]!
+	stlr xzr, [x1, #-8]!
+	stlr w0, [sp, #-4]!
+	stlr x0, [sp, #-8]!