mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
3.7 KiB
237 lines
3.7 KiB
/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|
/* |
|
* Floating-point, VMX/Altivec and VSX loads and stores |
|
* for use in instruction emulation. |
|
* |
|
* Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> |
|
*/ |
|
|
|
#include <asm/processor.h> |
|
#include <asm/ppc_asm.h> |
|
#include <asm/ppc-opcode.h> |
|
#include <asm/reg.h> |
|
#include <asm/asm-offsets.h> |
|
#include <asm/asm-compat.h> |
|
#include <linux/errno.h> |
|
|
|
#define STKFRM (PPC_MIN_STKFRM + 16) |
|
|
|
/* Get the contents of frN into *p; N is in r3 and p is in r4. */ |
|
_GLOBAL(get_fpr) |
|
mflr r0 |
|
mfmsr r6 |
|
ori r7, r6, MSR_FP |
|
MTMSRD(r7) |
|
isync |
|
rlwinm r3,r3,3,0xf8 |
|
bcl 20,31,1f |
|
reg = 0 |
|
.rept 32 |
|
stfd reg, 0(r4) |
|
b 2f |
|
reg = reg + 1 |
|
.endr |
|
1: mflr r5 |
|
add r5,r3,r5 |
|
mtctr r5 |
|
mtlr r0 |
|
bctr |
|
2: MTMSRD(r6) |
|
isync |
|
blr |
|
|
|
/* Put the contents of *p into frN; N is in r3 and p is in r4. */ |
|
_GLOBAL(put_fpr) |
|
mflr r0 |
|
mfmsr r6 |
|
ori r7, r6, MSR_FP |
|
MTMSRD(r7) |
|
isync |
|
rlwinm r3,r3,3,0xf8 |
|
bcl 20,31,1f |
|
reg = 0 |
|
.rept 32 |
|
lfd reg, 0(r4) |
|
b 2f |
|
reg = reg + 1 |
|
.endr |
|
1: mflr r5 |
|
add r5,r3,r5 |
|
mtctr r5 |
|
mtlr r0 |
|
bctr |
|
2: MTMSRD(r6) |
|
isync |
|
blr |
|
|
|
#ifdef CONFIG_ALTIVEC |
|
/* Get the contents of vrN into *p; N is in r3 and p is in r4. */ |
|
_GLOBAL(get_vr) |
|
mflr r0 |
|
mfmsr r6 |
|
oris r7, r6, MSR_VEC@h |
|
MTMSRD(r7) |
|
isync |
|
rlwinm r3,r3,3,0xf8 |
|
bcl 20,31,1f |
|
reg = 0 |
|
.rept 32 |
|
stvx reg, 0, r4 |
|
b 2f |
|
reg = reg + 1 |
|
.endr |
|
1: mflr r5 |
|
add r5,r3,r5 |
|
mtctr r5 |
|
mtlr r0 |
|
bctr |
|
2: MTMSRD(r6) |
|
isync |
|
blr |
|
|
|
/* Put the contents of *p into vrN; N is in r3 and p is in r4. */ |
|
_GLOBAL(put_vr) |
|
mflr r0 |
|
mfmsr r6 |
|
oris r7, r6, MSR_VEC@h |
|
MTMSRD(r7) |
|
isync |
|
rlwinm r3,r3,3,0xf8 |
|
bcl 20,31,1f |
|
reg = 0 |
|
.rept 32 |
|
lvx reg, 0, r4 |
|
b 2f |
|
reg = reg + 1 |
|
.endr |
|
1: mflr r5 |
|
add r5,r3,r5 |
|
mtctr r5 |
|
mtlr r0 |
|
bctr |
|
2: MTMSRD(r6) |
|
isync |
|
blr |
|
#endif /* CONFIG_ALTIVEC */ |
|
|
|
#ifdef CONFIG_VSX |
|
/* Get the contents of vsN into vs0; N is in r3. */ |
|
_GLOBAL(get_vsr) |
|
mflr r0 |
|
rlwinm r3,r3,3,0x1f8 |
|
bcl 20,31,1f |
|
blr /* vs0 is already in vs0 */ |
|
nop |
|
reg = 1 |
|
.rept 63 |
|
XXLOR(0,reg,reg) |
|
blr |
|
reg = reg + 1 |
|
.endr |
|
1: mflr r5 |
|
add r5,r3,r5 |
|
mtctr r5 |
|
mtlr r0 |
|
bctr |
|
|
|
/* Put the contents of vs0 into vsN; N is in r3. */ |
|
_GLOBAL(put_vsr) |
|
mflr r0 |
|
rlwinm r3,r3,3,0x1f8 |
|
bcl 20,31,1f |
|
blr /* v0 is already in v0 */ |
|
nop |
|
reg = 1 |
|
.rept 63 |
|
XXLOR(reg,0,0) |
|
blr |
|
reg = reg + 1 |
|
.endr |
|
1: mflr r5 |
|
add r5,r3,r5 |
|
mtctr r5 |
|
mtlr r0 |
|
bctr |
|
|
|
/* Load VSX reg N from vector doubleword *p. N is in r3, p in r4. */ |
|
_GLOBAL(load_vsrn) |
|
PPC_STLU r1,-STKFRM(r1) |
|
mflr r0 |
|
PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) |
|
mfmsr r6 |
|
oris r7,r6,MSR_VSX@h |
|
cmpwi cr7,r3,0 |
|
li r8,STKFRM-16 |
|
MTMSRD(r7) |
|
isync |
|
beq cr7,1f |
|
STXVD2X(0,R1,R8) |
|
1: LXVD2X(0,R0,R4) |
|
#ifdef __LITTLE_ENDIAN__ |
|
XXSWAPD(0,0) |
|
#endif |
|
beq cr7,4f |
|
bl put_vsr |
|
LXVD2X(0,R1,R8) |
|
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
|
mtlr r0 |
|
MTMSRD(r6) |
|
isync |
|
addi r1,r1,STKFRM |
|
blr |
|
|
|
/* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */ |
|
_GLOBAL(store_vsrn) |
|
PPC_STLU r1,-STKFRM(r1) |
|
mflr r0 |
|
PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1) |
|
mfmsr r6 |
|
oris r7,r6,MSR_VSX@h |
|
li r8,STKFRM-16 |
|
MTMSRD(r7) |
|
isync |
|
STXVD2X(0,R1,R8) |
|
bl get_vsr |
|
#ifdef __LITTLE_ENDIAN__ |
|
XXSWAPD(0,0) |
|
#endif |
|
STXVD2X(0,R0,R4) |
|
LXVD2X(0,R1,R8) |
|
PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
|
mtlr r0 |
|
MTMSRD(r6) |
|
isync |
|
mr r3,r9 |
|
addi r1,r1,STKFRM |
|
blr |
|
#endif /* CONFIG_VSX */ |
|
|
|
/* Convert single-precision to double, without disturbing FPRs. */ |
|
/* conv_sp_to_dp(float *sp, double *dp) */ |
|
_GLOBAL(conv_sp_to_dp) |
|
mfmsr r6 |
|
ori r7, r6, MSR_FP |
|
MTMSRD(r7) |
|
isync |
|
stfd fr0, -16(r1) |
|
lfs fr0, 0(r3) |
|
stfd fr0, 0(r4) |
|
lfd fr0, -16(r1) |
|
MTMSRD(r6) |
|
isync |
|
blr |
|
|
|
/* Convert single-precision to double, without disturbing FPRs. */ |
|
/* conv_sp_to_dp(double *dp, float *sp) */ |
|
_GLOBAL(conv_dp_to_sp) |
|
mfmsr r6 |
|
ori r7, r6, MSR_FP |
|
MTMSRD(r7) |
|
isync |
|
stfd fr0, -16(r1) |
|
lfd fr0, 0(r3) |
|
stfs fr0, 0(r4) |
|
lfd fr0, -16(r1) |
|
MTMSRD(r6) |
|
isync |
|
blr
|
|
|