Commit 6b35e114 authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle

MIPS: Introduce accessors for MSA vector registers

Introduce accessor functions allowing the kernel to access arbitrary
vector registers using an arbitrary data format. The accessors are
implemented in assembly, using macros to avoid massive duplication, in
order to make use of the existing support for MSA with & without
toolchain support. The accessors will be used in a later patch.
Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: Leonid Yegoshin <Leonid.Yegoshin@imgtec.com>
Cc: linux-kernel@vger.kernel.org
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Cc: Manuel Lauss <manuel.lauss@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/10572/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 6701ca2d
...@@ -232,6 +232,30 @@ ...@@ -232,6 +232,30 @@
.set pop .set pop
.endm .endm
.macro ld_b wd, off, base
.set push
.set mips32r2
.set msa
ld.b $w\wd, \off(\base)
.set pop
.endm
.macro ld_h wd, off, base
.set push
.set mips32r2
.set msa
ld.h $w\wd, \off(\base)
.set pop
.endm
.macro ld_w wd, off, base
.set push
.set mips32r2
.set msa
ld.w $w\wd, \off(\base)
.set pop
.endm
.macro ld_d wd, off, base .macro ld_d wd, off, base
.set push .set push
.set mips32r2 .set mips32r2
...@@ -241,6 +265,30 @@ ...@@ -241,6 +265,30 @@
.set pop .set pop
.endm .endm
.macro st_b wd, off, base
.set push
.set mips32r2
.set msa
st.b $w\wd, \off(\base)
.set pop
.endm
.macro st_h wd, off, base
.set push
.set mips32r2
.set msa
st.h $w\wd, \off(\base)
.set pop
.endm
.macro st_w wd, off, base
.set push
.set mips32r2
.set msa
st.w $w\wd, \off(\base)
.set pop
.endm
.macro st_d wd, off, base .macro st_d wd, off, base
.set push .set push
.set mips32r2 .set mips32r2
...@@ -290,7 +338,13 @@ ...@@ -290,7 +338,13 @@
#ifdef CONFIG_CPU_MICROMIPS #ifdef CONFIG_CPU_MICROMIPS
#define CFC_MSA_INSN 0x587e0056 #define CFC_MSA_INSN 0x587e0056
#define CTC_MSA_INSN 0x583e0816 #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 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 STD_MSA_INSN 0x5800083f
#define COPY_UW_MSA_INSN 0x58f00056 #define COPY_UW_MSA_INSN 0x58f00056
#define COPY_UD_MSA_INSN 0x58f80056 #define COPY_UD_MSA_INSN 0x58f80056
...@@ -299,7 +353,13 @@ ...@@ -299,7 +353,13 @@
#else #else
#define CFC_MSA_INSN 0x787e0059 #define CFC_MSA_INSN 0x787e0059
#define CTC_MSA_INSN 0x783e0819 #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 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 STD_MSA_INSN 0x78000827
#define COPY_UW_MSA_INSN 0x78f00059 #define COPY_UW_MSA_INSN 0x78f00059
#define COPY_UD_MSA_INSN 0x78f80059 #define COPY_UD_MSA_INSN 0x78f80059
...@@ -329,6 +389,33 @@ ...@@ -329,6 +389,33 @@
.set pop .set pop
.endm .endm
.macro ld_b wd, off, base
.set push
.set noat
SET_HARDFLOAT
addu $1, \base, \off
.word LDB_MSA_INSN | (\wd << 6)
.set pop
.endm
.macro ld_h wd, off, base
.set push
.set noat
SET_HARDFLOAT
addu $1, \base, \off
.word LDH_MSA_INSN | (\wd << 6)
.set pop
.endm
.macro ld_w wd, off, base
.set push
.set noat
SET_HARDFLOAT
addu $1, \base, \off
.word LDW_MSA_INSN | (\wd << 6)
.set pop
.endm
.macro ld_d wd, off, base .macro ld_d wd, off, base
.set push .set push
.set noat .set noat
...@@ -338,6 +425,33 @@ ...@@ -338,6 +425,33 @@
.set pop .set pop
.endm .endm
.macro st_b wd, off, base
.set push
.set noat
SET_HARDFLOAT
addu $1, \base, \off
.word STB_MSA_INSN | (\wd << 6)
.set pop
.endm
.macro st_h wd, off, base
.set push
.set noat
SET_HARDFLOAT
addu $1, \base, \off
.word STH_MSA_INSN | (\wd << 6)
.set pop
.endm
.macro st_w wd, off, base
.set push
.set noat
SET_HARDFLOAT
addu $1, \base, \off
.word STW_MSA_INSN | (\wd << 6)
.set pop
.endm
.macro st_d wd, off, base .macro st_d wd, off, base
.set push .set push
.set noat .set noat
......
...@@ -14,10 +14,90 @@ ...@@ -14,10 +14,90 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/inst.h>
extern void _save_msa(struct task_struct *); extern void _save_msa(struct task_struct *);
extern void _restore_msa(struct task_struct *); extern void _restore_msa(struct task_struct *);
extern void _init_msa_upper(void); extern void _init_msa_upper(void);
extern void read_msa_wr_b(unsigned idx, union fpureg *to);
extern void read_msa_wr_h(unsigned idx, union fpureg *to);
extern void read_msa_wr_w(unsigned idx, union fpureg *to);
extern void read_msa_wr_d(unsigned idx, union fpureg *to);
/**
* read_msa_wr() - Read a single MSA vector register
* @idx: The index of the vector register to read
* @to: The FPU register union to store the registers value in
* @fmt: The format of the data in the vector register
*
* Read the value of MSA vector register idx into the FPU register
* union to, using the format fmt.
*/
static inline void read_msa_wr(unsigned idx, union fpureg *to,
enum msa_2b_fmt fmt)
{
switch (fmt) {
case msa_fmt_b:
read_msa_wr_b(idx, to);
break;
case msa_fmt_h:
read_msa_wr_h(idx, to);
break;
case msa_fmt_w:
read_msa_wr_w(idx, to);
break;
case msa_fmt_d:
read_msa_wr_d(idx, to);
break;
default:
BUG();
}
}
extern void write_msa_wr_b(unsigned idx, union fpureg *from);
extern void write_msa_wr_h(unsigned idx, union fpureg *from);
extern void write_msa_wr_w(unsigned idx, union fpureg *from);
extern void write_msa_wr_d(unsigned idx, union fpureg *from);
/**
* write_msa_wr() - Write a single MSA vector register
* @idx: The index of the vector register to write
* @from: The FPU register union to take the registers value from
* @fmt: The format of the data in the vector register
*
* Write the value from the FPU register union from into MSA vector
* register idx, using the format fmt.
*/
static inline void write_msa_wr(unsigned idx, union fpureg *from,
enum msa_2b_fmt fmt)
{
switch (fmt) {
case msa_fmt_b:
write_msa_wr_b(idx, from);
break;
case msa_fmt_h:
write_msa_wr_h(idx, from);
break;
case msa_fmt_w:
write_msa_wr_w(idx, from);
break;
case msa_fmt_d:
write_msa_wr_d(idx, from);
break;
default:
BUG();
}
}
static inline void enable_msa(void) static inline void enable_msa(void)
{ {
if (cpu_has_msa) { if (cpu_has_msa) {
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* Copyright (C) 1999, 2001 Silicon Graphics, Inc. * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
*/ */
#include <asm/asm.h> #include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/fpregdef.h> #include <asm/fpregdef.h>
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
...@@ -274,6 +275,72 @@ LEAF(_restore_fp_context32) ...@@ -274,6 +275,72 @@ LEAF(_restore_fp_context32)
END(_restore_fp_context32) END(_restore_fp_context32)
#endif #endif
#ifdef CONFIG_CPU_HAS_MSA
.macro op_one_wr op, idx, base
.align 4
\idx: \op \idx, 0, \base
jr ra
nop
.endm
.macro op_msa_wr name, op
LEAF(\name)
.set push
.set noreorder
sll t0, a0, 4
PTR_LA t1, 0f
PTR_ADDU t0, t0, t1
jr t0
nop
op_one_wr \op, 0, a1
op_one_wr \op, 1, a1
op_one_wr \op, 2, a1
op_one_wr \op, 3, a1
op_one_wr \op, 4, a1
op_one_wr \op, 5, a1
op_one_wr \op, 6, a1
op_one_wr \op, 7, a1
op_one_wr \op, 8, a1
op_one_wr \op, 9, a1
op_one_wr \op, 10, a1
op_one_wr \op, 11, a1
op_one_wr \op, 12, a1
op_one_wr \op, 13, a1
op_one_wr \op, 14, a1
op_one_wr \op, 15, a1
op_one_wr \op, 16, a1
op_one_wr \op, 17, a1
op_one_wr \op, 18, a1
op_one_wr \op, 19, a1
op_one_wr \op, 20, a1
op_one_wr \op, 21, a1
op_one_wr \op, 22, a1
op_one_wr \op, 23, a1
op_one_wr \op, 24, a1
op_one_wr \op, 25, a1
op_one_wr \op, 26, a1
op_one_wr \op, 27, a1
op_one_wr \op, 28, a1
op_one_wr \op, 29, a1
op_one_wr \op, 30, a1
op_one_wr \op, 31, a1
.set pop
END(\name)
.endm
op_msa_wr read_msa_wr_b, st_b
op_msa_wr read_msa_wr_h, st_h
op_msa_wr read_msa_wr_w, st_w
op_msa_wr read_msa_wr_d, st_d
op_msa_wr write_msa_wr_b, ld_b
op_msa_wr write_msa_wr_h, ld_h
op_msa_wr write_msa_wr_w, ld_w
op_msa_wr write_msa_wr_d, ld_d
#endif /* CONFIG_CPU_HAS_MSA */
.set reorder .set reorder
.type fault@function .type fault@function
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment