[PATCH 1/2] ARC: io: work around GCC PR127718 in __raw_write{w,l}()

From: Vineet Gupta

Date: Tue Nov 03 2026 - 23:35:46 EST


The __raw_write{w,l}() accessors use inline asm with an "m" operand for
the store destination. GCC's ARC backend lets "m" match any legitimate
address, including the register-indexed [b,c] forms that only loads
support: stores only have [reg], [reg,s9] and [limm] addressing. With
newer GCC (late-combine in GCC 15, combine in GCC 16), a writew() with a
scaled, non-constant offset gets

stw.as r2,[r0,r1]

which the assembler rejects:

Error: inappropriate arguments for opcode 'stw'

With GCC 16 this breaks even hsdk_defconfig (drivers/net/pcs/
pcs-xpcs-plat.c) and axs101_defconfig. allyesconfig additionally trips
in drivers/pinctrl/renesas/pinctrl-rza2.c and drivers/video/fbdev/
s3c-fb.c.

Work around it by passing the address in a register and using a fixed
[%1] address in the asm template, so the compiler can't pick an
addressing mode that stores don't support. This is the minimal fix.
The next patch drops the inline asm altogether.

Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127718
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Vineet Gupta <vgupta@xxxxxxxxxx>
---
arch/arc/include/asm/io.h | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index 00171a212b3c..b4a3393d1bdc 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -133,10 +133,14 @@ static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
#define __raw_writew __raw_writew
static inline void __raw_writew(u16 s, volatile void __iomem *addr)
{
+ /*
+ * Not an "m" operand: GCC can pick a register-indexed address for it,
+ * which ST doesn't support (GCC PR target/127718).
+ */
__asm__ __volatile__(
- " stw%U1 %0, %1 \n"
+ " stw %0, [%1] \n"
:
- : "r" (s), "m" (*(volatile u16 __force *)addr)
+ : "r" (s), "r" (addr)
: "memory");

}
@@ -144,10 +148,11 @@ static inline void __raw_writew(u16 s, volatile void __iomem *addr)
#define __raw_writel __raw_writel
static inline void __raw_writel(u32 w, volatile void __iomem *addr)
{
+ /* See __raw_writew() above for why this doesn't use an "m" operand. */
__asm__ __volatile__(
- " st%U1 %0, %1 \n"
+ " st %0, [%1] \n"
:
- : "r" (w), "m" (*(volatile u32 __force *)addr)
+ : "r" (w), "r" (addr)
: "memory");

}
--
2.53.0