MIPS: Add MSA register definitions & access
authorPaul Burton <paul.burton@imgtec.com>
Mon, 27 Jan 2014 15:23:09 +0000 (15:23 +0000)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 26 Mar 2014 22:09:10 +0000 (23:09 +0100)
This patch introduces definitions for the MSA control registers and
functions which allow access to both the control & vector registers. If
the toolchain being used to build the kernel includes support for MSA
then this patch will make use of that support & use MSA instructions
directly. However toolchain support for MSA is very new & far from a
point where it can be reasonably expected that everyone building the
kernel uses a toolchain with support. Thus fallbacks using .word
assembler directives are also provided for now as a temporary measure.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6429/
Patchwork: https://patchwork.linux-mips.org/patch/6607/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/Makefile
arch/mips/include/asm/asmmacro.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/msa.h [new file with mode: 0644]

index 9b8556d..1a5b403 100644 (file)
@@ -119,6 +119,11 @@ cflags-$(CONFIG_CPU_MICROMIPS) += $(call cc-option,-mmicromips)
 cflags-$(CONFIG_SB1XXX_CORELIS)        += $(call cc-option,-mno-sched-prolog) \
                                   -fno-omit-frame-pointer
 
+ifeq ($(CONFIG_CPU_HAS_MSA),y)
+toolchain-msa                  := $(call cc-option-yn,-mhard-float -mfp64 -mmsa)
+cflags-$(toolchain-msa)                += -DTOOLCHAIN_SUPPORTS_MSA
+endif
+
 #
 # CPU-dependent compiler/assembler options for optimization.
 #
index 63cf434..f571db3 100644 (file)
         .word  0x41800000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel)
        .endm
 
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+       .macro  ld_d    wd, off, base
+       .set    push
+       .set    mips32r2
+       .set    msa
+       ld.d    $w\wd, \off(\base)
+       .set    pop
+       .endm
+
+       .macro  st_d    wd, off, base
+       .set    push
+       .set    mips32r2
+       .set    msa
+       st.d    $w\wd, \off(\base)
+       .set    pop
+       .endm
+
+       .macro  copy_u_w        rd, ws, n
+       .set    push
+       .set    mips32r2
+       .set    msa
+       copy_u.w \rd, $w\ws[\n]
+       .set    pop
+       .endm
+
+       .macro  copy_u_d        rd, ws, n
+       .set    push
+       .set    mips64r2
+       .set    msa
+       copy_u.d \rd, $w\ws[\n]
+       .set    pop
+       .endm
+
+       .macro  insert_w        wd, n, rs
+       .set    push
+       .set    mips32r2
+       .set    msa
+       insert.w $w\wd[\n], \rs
+       .set    pop
+       .endm
+
+       .macro  insert_d        wd, n, rs
+       .set    push
+       .set    mips64r2
+       .set    msa
+       insert.d $w\wd[\n], \rs
+       .set    pop
+       .endm
+#else
+       /*
+        * Temporary until all toolchains in use include MSA support.
+        */
+       .macro  cfcmsa  rd, cs
+       .set    push
+       .set    noat
+       .word   0x787e0059 | (\cs << 11)
+       move    \rd, $1
+       .set    pop
+       .endm
+
+       .macro  ctcmsa  cd, rs
+       .set    push
+       .set    noat
+       move    $1, \rs
+       .word   0x783e0819 | (\cd << 6)
+       .set    pop
+       .endm
+
+       .macro  ld_d    wd, off, base
+       .set    push
+       .set    noat
+       add     $1, \base, \off
+       .word   0x78000823 | (\wd << 6)
+       .set    pop
+       .endm
+
+       .macro  st_d    wd, off, base
+       .set    push
+       .set    noat
+       add     $1, \base, \off
+       .word   0x78000827 | (\wd << 6)
+       .set    pop
+       .endm
+
+       .macro  copy_u_w        rd, ws, n
+       .set    push
+       .set    noat
+       .word   0x78f00059 | (\n << 16) | (\ws << 11)
+       /* move triggers an assembler bug... */
+       or      \rd, $1, zero
+       .set    pop
+       .endm
+
+       .macro  copy_u_d        rd, ws, n
+       .set    push
+       .set    noat
+       .word   0x78f80059 | (\n << 16) | (\ws << 11)
+       /* move triggers an assembler bug... */
+       or      \rd, $1, zero
+       .set    pop
+       .endm
+
+       .macro  insert_w        wd, n, rs
+       .set    push
+       .set    noat
+       /* move triggers an assembler bug... */
+       or      $1, \rs, zero
+       .word   0x79300819 | (\n << 16) | (\wd << 6)
+       .set    pop
+       .endm
+
+       .macro  insert_d        wd, n, rs
+       .set    push
+       .set    noat
+       /* move triggers an assembler bug... */
+       or      $1, \rs, zero
+       .word   0x79380819 | (\n << 16) | (\wd << 6)
+       .set    pop
+       .endm
+#endif
+
 #endif /* _ASM_ASMMACRO_H */
index dde6a78..3e025b5 100644 (file)
@@ -1904,6 +1904,7 @@ change_c0_##name(unsigned int change, unsigned int newbits)       \
 __BUILD_SET_C0(status)
 __BUILD_SET_C0(cause)
 __BUILD_SET_C0(config)
+__BUILD_SET_C0(config5)
 __BUILD_SET_C0(intcontrol)
 __BUILD_SET_C0(intctl)
 __BUILD_SET_C0(srsmap)
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
new file mode 100644 (file)
index 0000000..0a614fb
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2013 Imagination Technologies
+ * Author: Paul Burton <paul.burton@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef _ASM_MSA_H
+#define _ASM_MSA_H
+
+#include <asm/mipsregs.h>
+
+static inline void enable_msa(void)
+{
+       if (cpu_has_msa) {
+               set_c0_config5(MIPS_CONF5_MSAEN);
+               enable_fpu_hazard();
+       }
+}
+
+static inline void disable_msa(void)
+{
+       if (cpu_has_msa) {
+               clear_c0_config5(MIPS_CONF5_MSAEN);
+               disable_fpu_hazard();
+       }
+}
+
+static inline int is_msa_enabled(void)
+{
+       if (!cpu_has_msa)
+               return 0;
+
+       return read_c0_config5() & MIPS_CONF5_MSAEN;
+}
+
+#ifdef TOOLCHAIN_SUPPORTS_MSA
+
+#define __BUILD_MSA_CTL_REG(name, cs)                          \
+static inline unsigned int read_msa_##name(void)               \
+{                                                              \
+       unsigned int reg;                                       \
+       __asm__ __volatile__(                                   \
+       "       .set    push\n"                                 \
+       "       .set    msa\n"                                  \
+       "       cfcmsa  %0, $" #cs "\n"                         \
+       "       .set    pop\n"                                  \
+       : "=r"(reg));                                           \
+       return reg;                                             \
+}                                                              \
+                                                               \
+static inline void write_msa_##name(unsigned int val)          \
+{                                                              \
+       __asm__ __volatile__(                                   \
+       "       .set    push\n"                                 \
+       "       .set    msa\n"                                  \
+       "       cfcmsa  $" #cs ", %0\n"                         \
+       "       .set    pop\n"                                  \
+       : : "r"(val));                                          \
+}
+
+#else /* !TOOLCHAIN_SUPPORTS_MSA */
+
+/*
+ * Define functions using .word for the c[ft]cmsa instructions in order to
+ * allow compilation with toolchains that do not support MSA. Once all
+ * toolchains in use support MSA these can be removed.
+ */
+
+#define __BUILD_MSA_CTL_REG(name, cs)                          \
+static inline unsigned int read_msa_##name(void)               \
+{                                                              \
+       unsigned int reg;                                       \
+       __asm__ __volatile__(                                   \
+       "       .set    push\n"                                 \
+       "       .set    noat\n"                                 \
+       "       .word   0x787e0059 | (" #cs " << 11)\n"         \
+       "       move    %0, $1\n"                               \
+       "       .set    pop\n"                                  \
+       : "=r"(reg));                                           \
+       return reg;                                             \
+}                                                              \
+                                                               \
+static inline void write_msa_##name(unsigned int val)          \
+{                                                              \
+       __asm__ __volatile__(                                   \
+       "       .set    push\n"                                 \
+       "       .set    noat\n"                                 \
+       "       move    $1, %0\n"                               \
+       "       .word   0x783e0819 | (" #cs " << 6)\n"          \
+       "       .set    pop\n"                                  \
+       : : "r"(val));                                          \
+}
+
+#endif /* !TOOLCHAIN_SUPPORTS_MSA */
+
+#define MSA_IR         0
+#define MSA_CSR                1
+#define MSA_ACCESS     2
+#define MSA_SAVE       3
+#define MSA_MODIFY     4
+#define MSA_REQUEST    5
+#define MSA_MAP                6
+#define MSA_UNMAP      7
+
+__BUILD_MSA_CTL_REG(ir, 0)
+__BUILD_MSA_CTL_REG(csr, 1)
+__BUILD_MSA_CTL_REG(access, 2)
+__BUILD_MSA_CTL_REG(save, 3)
+__BUILD_MSA_CTL_REG(modify, 4)
+__BUILD_MSA_CTL_REG(request, 5)
+__BUILD_MSA_CTL_REG(map, 6)
+__BUILD_MSA_CTL_REG(unmap, 7)
+
+/* MSA Implementation Register (MSAIR) */
+#define MSA_IR_REVB            0
+#define MSA_IR_REVF            (_ULCAST_(0xff) << MSA_IR_REVB)
+#define MSA_IR_PROCB           8
+#define MSA_IR_PROCF           (_ULCAST_(0xff) << MSA_IR_PROCB)
+#define MSA_IR_WRPB            16
+#define MSA_IR_WRPF            (_ULCAST_(0x1) << MSA_IR_WRPB)
+
+/* MSA Control & Status Register (MSACSR) */
+#define MSA_CSR_RMB            0
+#define MSA_CSR_RMF            (_ULCAST_(0x3) << MSA_CSR_RMB)
+#define MSA_CSR_RM_NEAREST     0
+#define MSA_CSR_RM_TO_ZERO     1
+#define MSA_CSR_RM_TO_POS      2
+#define MSA_CSR_RM_TO_NEG      3
+#define MSA_CSR_FLAGSB         2
+#define MSA_CSR_FLAGSF         (_ULCAST_(0x1f) << MSA_CSR_FLAGSB)
+#define MSA_CSR_FLAGS_IB       2
+#define MSA_CSR_FLAGS_IF       (_ULCAST_(0x1) << MSA_CSR_FLAGS_IB)
+#define MSA_CSR_FLAGS_UB       3
+#define MSA_CSR_FLAGS_UF       (_ULCAST_(0x1) << MSA_CSR_FLAGS_UB)
+#define MSA_CSR_FLAGS_OB       4
+#define MSA_CSR_FLAGS_OF       (_ULCAST_(0x1) << MSA_CSR_FLAGS_OB)
+#define MSA_CSR_FLAGS_ZB       5
+#define MSA_CSR_FLAGS_ZF       (_ULCAST_(0x1) << MSA_CSR_FLAGS_ZB)
+#define MSA_CSR_FLAGS_VB       6
+#define MSA_CSR_FLAGS_VF       (_ULCAST_(0x1) << MSA_CSR_FLAGS_VB)
+#define MSA_CSR_ENABLESB       7
+#define MSA_CSR_ENABLESF       (_ULCAST_(0x1f) << MSA_CSR_ENABLESB)
+#define MSA_CSR_ENABLES_IB     7
+#define MSA_CSR_ENABLES_IF     (_ULCAST_(0x1) << MSA_CSR_ENABLES_IB)
+#define MSA_CSR_ENABLES_UB     8
+#define MSA_CSR_ENABLES_UF     (_ULCAST_(0x1) << MSA_CSR_ENABLES_UB)
+#define MSA_CSR_ENABLES_OB     9
+#define MSA_CSR_ENABLES_OF     (_ULCAST_(0x1) << MSA_CSR_ENABLES_OB)
+#define MSA_CSR_ENABLES_ZB     10
+#define MSA_CSR_ENABLES_ZF     (_ULCAST_(0x1) << MSA_CSR_ENABLES_ZB)
+#define MSA_CSR_ENABLES_VB     11
+#define MSA_CSR_ENABLES_VF     (_ULCAST_(0x1) << MSA_CSR_ENABLES_VB)
+#define MSA_CSR_CAUSEB         12
+#define MSA_CSR_CAUSEF         (_ULCAST_(0x3f) << MSA_CSR_CAUSEB)
+#define MSA_CSR_CAUSE_IB       12
+#define MSA_CSR_CAUSE_IF       (_ULCAST_(0x1) << MSA_CSR_CAUSE_IB)
+#define MSA_CSR_CAUSE_UB       13
+#define MSA_CSR_CAUSE_UF       (_ULCAST_(0x1) << MSA_CSR_CAUSE_UB)
+#define MSA_CSR_CAUSE_OB       14
+#define MSA_CSR_CAUSE_OF       (_ULCAST_(0x1) << MSA_CSR_CAUSE_OB)
+#define MSA_CSR_CAUSE_ZB       15
+#define MSA_CSR_CAUSE_ZF       (_ULCAST_(0x1) << MSA_CSR_CAUSE_ZB)
+#define MSA_CSR_CAUSE_VB       16
+#define MSA_CSR_CAUSE_VF       (_ULCAST_(0x1) << MSA_CSR_CAUSE_VB)
+#define MSA_CSR_CAUSE_EB       17
+#define MSA_CSR_CAUSE_EF       (_ULCAST_(0x1) << MSA_CSR_CAUSE_EB)
+#define MSA_CSR_NXB            18
+#define MSA_CSR_NXF            (_ULCAST_(0x1) << MSA_CSR_NXB)
+#define MSA_CSR_FSB            24
+#define MSA_CSR_FSF            (_ULCAST_(0x1) << MSA_CSR_FSB)
+
+#endif /* _ASM_MSA_H */