MIPS: Fix little endian microMIPS MSA encodings
authorJames Hogan <james.hogan@imgtec.com>
Fri, 20 May 2016 22:28:39 +0000 (23:28 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Sat, 28 May 2016 10:35:10 +0000 (12:35 +0200)
When the toolchain doesn't support MSA we encode MSA instructions
explicitly in assembly. Unfortunately we use .word for both MIPS and
microMIPS encodings which is wrong, since 32-bit microMIPS instructions
are made up from a pair of halfwords.

- The most significant halfword always comes first, so for little endian
  builds the halves will be emitted in the wrong order.

- 32-bit alignment isn't guaranteed, so the assembler may insert a
  16-bit nop instruction to pad the instruction stream to a 32-bit
  boundary.

Use the new instruction encoding macros to encode microMIPS MSA
instructions correctly.

Fixes: d96cc3d1ec5d ("MIPS: Add microMIPS MSA support.")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <Paul.Burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13312/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/include/asm/asmmacro.h
arch/mips/include/asm/msa.h

index 6741673..56584a6 100644 (file)
 #include <asm/asmmacro-64.h>
 #endif
 
+/*
+ * Helper macros for generating raw instruction encodings.
+ */
+#ifdef CONFIG_CPU_MICROMIPS
+       .macro  insn32_if_mm enc
+       .insn
+       .hword ((\enc) >> 16)
+       .hword ((\enc) & 0xffff)
+       .endm
+
+       .macro  insn_if_mips enc
+       .endm
+#else
+       .macro  insn32_if_mm enc
+       .endm
+
+       .macro  insn_if_mips enc
+       .insn
+       .word (\enc)
+       .endm
+#endif
+
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
        .macro  local_irq_enable reg=t0
        ei
        .endm
 #else
 
-#ifdef CONFIG_CPU_MICROMIPS
-#define CFC_MSA_INSN           0x587e0056
-#define CTC_MSA_INSN           0x583e0816
-#define LDB_MSA_INSN           0x58000807
-#define LDH_MSA_INSN           0x58000817
-#define LDW_MSA_INSN           0x58000827
-#define LDD_MSA_INSN           0x58000837
-#define STB_MSA_INSN           0x5800080f
-#define STH_MSA_INSN           0x5800081f
-#define STW_MSA_INSN           0x5800082f
-#define STD_MSA_INSN           0x5800083f
-#define COPY_SW_MSA_INSN       0x58b00056
-#define COPY_SD_MSA_INSN       0x58b80056
-#define INSERT_W_MSA_INSN      0x59300816
-#define INSERT_D_MSA_INSN      0x59380816
-#else
-#define CFC_MSA_INSN           0x787e0059
-#define CTC_MSA_INSN           0x783e0819
-#define LDB_MSA_INSN           0x78000820
-#define LDH_MSA_INSN           0x78000821
-#define LDW_MSA_INSN           0x78000822
-#define LDD_MSA_INSN           0x78000823
-#define STB_MSA_INSN           0x78000824
-#define STH_MSA_INSN           0x78000825
-#define STW_MSA_INSN           0x78000826
-#define STD_MSA_INSN           0x78000827
-#define COPY_SW_MSA_INSN       0x78b00059
-#define COPY_SD_MSA_INSN       0x78b80059
-#define INSERT_W_MSA_INSN      0x79300819
-#define INSERT_D_MSA_INSN      0x79380819
-#endif
-
        /*
         * Temporary until all toolchains in use include MSA support.
         */
        .set    push
        .set    noat
        SET_HARDFLOAT
-       .insn
-       .word   CFC_MSA_INSN | (\cs << 11)
+       insn_if_mips 0x787e0059 | (\cs << 11)
+       insn32_if_mm 0x587e0056 | (\cs << 11)
        move    \rd, $1
        .set    pop
        .endm
        .set    noat
        SET_HARDFLOAT
        move    $1, \rs
-       .word   CTC_MSA_INSN | (\cd << 6)
+       insn_if_mips 0x783e0819 | (\cd << 6)
+       insn32_if_mm 0x583e0816 | (\cd << 6)
        .set    pop
        .endm
 
        .set    noat
        SET_HARDFLOAT
        PTR_ADDU $1, \base, \off
-       .word   LDB_MSA_INSN | (\wd << 6)
+       insn_if_mips 0x78000820 | (\wd << 6)
+       insn32_if_mm 0x58000807 | (\wd << 6)
        .set    pop
        .endm
 
        .set    noat
        SET_HARDFLOAT
        PTR_ADDU $1, \base, \off
-       .word   LDH_MSA_INSN | (\wd << 6)
+       insn_if_mips 0x78000821 | (\wd << 6)
+       insn32_if_mm 0x58000817 | (\wd << 6)
        .set    pop
        .endm
 
        .set    noat
        SET_HARDFLOAT
        PTR_ADDU $1, \base, \off
-       .word   LDW_MSA_INSN | (\wd << 6)
+       insn_if_mips 0x78000822 | (\wd << 6)
+       insn32_if_mm 0x58000827 | (\wd << 6)
        .set    pop
        .endm
 
        .set    noat
        SET_HARDFLOAT
        PTR_ADDU $1, \base, \off
-       .word   LDD_MSA_INSN | (\wd << 6)
+       insn_if_mips 0x78000823 | (\wd << 6)
+       insn32_if_mm 0x58000837 | (\wd << 6)
        .set    pop
        .endm
 
        .set    noat
        SET_HARDFLOAT
        PTR_ADDU $1, \base, \off
-       .word   STB_MSA_INSN | (\wd << 6)
+       insn_if_mips 0x78000824 | (\wd << 6)
+       insn32_if_mm 0x5800080f | (\wd << 6)
        .set    pop
        .endm
 
        .set    noat
        SET_HARDFLOAT
        PTR_ADDU $1, \base, \off
-       .word   STH_MSA_INSN | (\wd << 6)
+       insn_if_mips 0x78000825 | (\wd << 6)
+       insn32_if_mm 0x5800081f | (\wd << 6)
        .set    pop
        .endm
 
        .set    noat
        SET_HARDFLOAT
        PTR_ADDU $1, \base, \off
-       .word   STW_MSA_INSN | (\wd << 6)
+       insn_if_mips 0x78000826 | (\wd << 6)
+       insn32_if_mm 0x5800082f | (\wd << 6)
        .set    pop
        .endm
 
        .set    noat
        SET_HARDFLOAT
        PTR_ADDU $1, \base, \off
-       .word   STD_MSA_INSN | (\wd << 6)
+       insn_if_mips 0x78000827 | (\wd << 6)
+       insn32_if_mm 0x5800083f | (\wd << 6)
        .set    pop
        .endm
 
        .set    push
        .set    noat
        SET_HARDFLOAT
-       .insn
-       .word   COPY_SW_MSA_INSN | (\n << 16) | (\ws << 11)
+       insn_if_mips 0x78b00059 | (\n << 16) | (\ws << 11)
+       insn32_if_mm 0x58b00056 | (\n << 16) | (\ws << 11)
        .set    pop
        .endm
 
        .set    push
        .set    noat
        SET_HARDFLOAT
-       .insn
-       .word   COPY_SD_MSA_INSN | (\n << 16) | (\ws << 11)
+       insn_if_mips 0x78b80059 | (\n << 16) | (\ws << 11)
+       insn32_if_mm 0x58b80056 | (\n << 16) | (\ws << 11)
        .set    pop
        .endm
 
        .set    push
        .set    noat
        SET_HARDFLOAT
-       .word   INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6)
+       insn_if_mips 0x79300819 | (\n << 16) | (\wd << 6)
+       insn32_if_mm 0x59300816 | (\n << 16) | (\wd << 6)
        .set    pop
        .endm
 
        .set    push
        .set    noat
        SET_HARDFLOAT
-       .word   INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6)
+       insn_if_mips 0x79380819 | (\n << 16) | (\wd << 6)
+       insn32_if_mm 0x59380816 | (\n << 16) | (\wd << 6)
        .set    pop
        .endm
 #endif
index 6e4effa..ddf496c 100644 (file)
@@ -192,13 +192,6 @@ static inline void write_msa_##name(unsigned int val)              \
  * allow compilation with toolchains that do not support MSA. Once all
  * toolchains in use support MSA these can be removed.
  */
-#ifdef CONFIG_CPU_MICROMIPS
-#define CFC_MSA_INSN   0x587e0056
-#define CTC_MSA_INSN   0x583e0816
-#else
-#define CFC_MSA_INSN   0x787e0059
-#define CTC_MSA_INSN   0x783e0819
-#endif
 
 #define __BUILD_MSA_CTL_REG(name, cs)                          \
 static inline unsigned int read_msa_##name(void)               \
@@ -207,11 +200,12 @@ static inline unsigned int read_msa_##name(void)          \
        __asm__ __volatile__(                                   \
        "       .set    push\n"                                 \
        "       .set    noat\n"                                 \
-       "       .insn\n"                                        \
-       "       .word   %1 | (" #cs " << 11)\n"                 \
+       "       # cfcmsa $1, $%1\n"                             \
+       _ASM_INSN_IF_MIPS(0x787e0059 | %1 << 11)                \
+       _ASM_INSN32_IF_MM(0x587e0056 | %1 << 11)                \
        "       move    %0, $1\n"                               \
        "       .set    pop\n"                                  \
-       : "=r"(reg) : "i"(CFC_MSA_INSN));                       \
+       : "=r"(reg) : "i"(cs));                                 \
        return reg;                                             \
 }                                                              \
                                                                \
@@ -221,10 +215,11 @@ static inline void write_msa_##name(unsigned int val)             \
        "       .set    push\n"                                 \
        "       .set    noat\n"                                 \
        "       move    $1, %0\n"                               \
-       "       .insn\n"                                        \
-       "       .word   %1 | (" #cs " << 6)\n"                  \
+       "       # ctcmsa $%1, $1\n"                             \
+       _ASM_INSN_IF_MIPS(0x783e0819 | %1 << 6)                 \
+       _ASM_INSN32_IF_MM(0x583e0816 | %1 << 6)                 \
        "       .set    pop\n"                                  \
-       : : "r"(val), "i"(CTC_MSA_INSN));                       \
+       : : "r"(val), "i"(cs));                                 \
 }
 
 #endif /* !TOOLCHAIN_SUPPORTS_MSA */