MIPS: XPA: Use XPA instructions in assembly
authorJames Hogan <jhogan@kernel.org>
Wed, 22 Nov 2017 11:30:30 +0000 (11:30 +0000)
committerJames Hogan <jhogan@kernel.org>
Mon, 22 Jan 2018 20:51:55 +0000 (20:51 +0000)
Utilise XPA instructions MFHC0 & MTHC0 in inline assembly instead of
directly encoding them with the _ASM_INSN* macros, and transparently
implement these instructions as assembler macros if the toolchain
doesn't support them natively, using the recently introduced assembler
macro helpers.

The old direct encodings were restricted to using the register $at, so
this allows the extra register moves to go away (saving a grand total of
24 bytes).

Signed-off-by: James Hogan <jhogan@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/17775/

arch/mips/Makefile
arch/mips/include/asm/mipsregs.h

index 0f20f84de53b81941a6525f113adf66723e7645a..d1ca839c3981e5c7db6d42affe939f2fc0d8dbb0 100644 (file)
@@ -216,6 +216,12 @@ cflags-$(toolchain-msa)                    += -DTOOLCHAIN_SUPPORTS_MSA
 endif
 toolchain-virt                         := $(call cc-option-yn,$(mips-cflags) -mvirt)
 cflags-$(toolchain-virt)               += -DTOOLCHAIN_SUPPORTS_VIRT
+# For -mmicromips, use -Wa,-fatal-warnings to catch unsupported -mxpa which
+# only warns
+xpa-cflags-y                           := $(mips-cflags)
+xpa-cflags-$(micromips-ase)            += -mmicromips -Wa$(comma)-fatal-warnings
+toolchain-xpa                          := $(call cc-option-yn,$(xpa-cflags-y) -mxpa)
+cflags-$(toolchain-xpa)                        += -DTOOLCHAIN_SUPPORTS_XPA
 
 #
 # Firmware support
index 509879f6a1e3097cb49511c400635af94dd3fb55..f336846fb4158943f6370ad212e2ee06c15fa098 100644 (file)
@@ -1504,18 +1504,27 @@ do {                                                                    \
        local_irq_restore(__flags);                                     \
 } while (0)
 
+#ifndef TOOLCHAIN_SUPPORTS_XPA
+_ASM_MACRO_2R_1S(mfhc0, rt, rs, sel,
+       _ASM_INSN_IF_MIPS(0x40400000 | __rt << 16 | __rs << 11 | \\sel)
+       _ASM_INSN32_IF_MM(0x000000f4 | __rt << 21 | __rs << 16 | \\sel << 11));
+_ASM_MACRO_2R_1S(mthc0, rt, rd, sel,
+       _ASM_INSN_IF_MIPS(0x40c00000 | __rt << 16 | __rd << 11 | \\sel)
+       _ASM_INSN32_IF_MM(0x000002f4 | __rt << 21 | __rd << 16 | \\sel << 11));
+#define _ASM_SET_XPA ""
+#else  /* !TOOLCHAIN_SUPPORTS_XPA */
+#define _ASM_SET_XPA ".set\txpa\n\t"
+#endif
+
 #define __readx_32bit_c0_register(source)                              \
 ({                                                                     \
        unsigned int __res;                                             \
                                                                        \
        __asm__ __volatile__(                                           \
        "       .set    push                                    \n"     \
-       "       .set    noat                                    \n"     \
        "       .set    mips32r2                                \n"     \
-       "       # mfhc0 $1, %1                                  \n"     \
-       _ASM_INSN_IF_MIPS(0x40410000 | ((%1 & 0x1f) << 11))             \
-       _ASM_INSN32_IF_MM(0x002000f4 | ((%1 & 0x1f) << 16))             \
-       "       move    %0, $1                                  \n"     \
+       _ASM_SET_XPA                                                    \
+       "       mfhc0   %0, $%1                                 \n"     \
        "       .set    pop                                     \n"     \
        : "=r" (__res)                                                  \
        : "i" (source));                                                \
@@ -1526,12 +1535,9 @@ do {                                                                     \
 do {                                                                   \
        __asm__ __volatile__(                                           \
        "       .set    push                                    \n"     \
-       "       .set    noat                                    \n"     \
        "       .set    mips32r2                                \n"     \
-       "       move    $1, %0                                  \n"     \
-       "       # mthc0 $1, %1                                  \n"     \
-       _ASM_INSN_IF_MIPS(0x40c10000 | ((%1 & 0x1f) << 11))             \
-       _ASM_INSN32_IF_MM(0x002002f4 | ((%1 & 0x1f) << 16))             \
+       _ASM_SET_XPA                                                    \
+       "       mthc0   %0, $%1                                 \n"     \
        "       .set    pop                                     \n"     \
        :                                                               \
        : "r" (value), "i" (register));                                 \