Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+114 −0
Original line number Diff line number Diff line
@@ -232,6 +232,30 @@
	.set	pop
	.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
	.set	push
	.set	mips32r2
@@ -241,6 +265,30 @@
	.set	pop
	.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
	.set	push
	.set	mips32r2
@@ -290,7 +338,13 @@
#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_UW_MSA_INSN	0x58f00056
#define COPY_UD_MSA_INSN	0x58f80056
@@ -299,7 +353,13 @@
#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_UW_MSA_INSN	0x78f00059
#define COPY_UD_MSA_INSN	0x78f80059
@@ -329,6 +389,33 @@
	.set	pop
	.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
	.set	push
	.set	noat
@@ -338,6 +425,33 @@
	.set	pop
	.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
	.set	push
	.set	noat
+80 −0
Original line number Diff line number Diff line
@@ -14,10 +14,90 @@

#ifndef __ASSEMBLY__

#include <asm/inst.h>

extern void _save_msa(struct task_struct *);
extern void _restore_msa(struct task_struct *);
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)
{
	if (cpu_has_msa) {
+67 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
 * Copyright (C) 1999, 2001 Silicon Graphics, Inc.
 */
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/errno.h>
#include <asm/fpregdef.h>
#include <asm/mipsregs.h>
@@ -274,6 +275,72 @@ LEAF(_restore_fp_context32)
	END(_restore_fp_context32)
#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

	.type	fault@function