forked from Minki/linux
e55174e911
These macros are using integers where they could be using logical names since they take registers. We are going to enforce this soon, so fix these up now. Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
380 lines
6.1 KiB
ArmAsm
380 lines
6.1 KiB
ArmAsm
/*
|
|
* Floating-point, VMX/Altivec and VSX loads and stores
|
|
* for use in instruction emulation.
|
|
*
|
|
* Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.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.
|
|
*/
|
|
|
|
#include <asm/processor.h>
|
|
#include <asm/ppc_asm.h>
|
|
#include <asm/ppc-opcode.h>
|
|
#include <asm/reg.h>
|
|
#include <asm/asm-offsets.h>
|
|
#include <linux/errno.h>
|
|
|
|
#ifdef CONFIG_PPC_FPU
|
|
|
|
#define STKFRM (PPC_MIN_STKFRM + 16)
|
|
|
|
.macro extab instr,handler
|
|
.section __ex_table,"a"
|
|
PPC_LONG \instr,\handler
|
|
.previous
|
|
.endm
|
|
|
|
.macro inst32 op
|
|
reg = 0
|
|
.rept 32
|
|
20: \op reg,0,r4
|
|
b 3f
|
|
extab 20b,99f
|
|
reg = reg + 1
|
|
.endr
|
|
.endm
|
|
|
|
/* Get the contents of frN into fr0; N is in r3. */
|
|
_GLOBAL(get_fpr)
|
|
mflr r0
|
|
rlwinm r3,r3,3,0xf8
|
|
bcl 20,31,1f
|
|
blr /* fr0 is already in fr0 */
|
|
nop
|
|
reg = 1
|
|
.rept 31
|
|
fmr fr0,reg
|
|
blr
|
|
reg = reg + 1
|
|
.endr
|
|
1: mflr r5
|
|
add r5,r3,r5
|
|
mtctr r5
|
|
mtlr r0
|
|
bctr
|
|
|
|
/* Put the contents of fr0 into frN; N is in r3. */
|
|
_GLOBAL(put_fpr)
|
|
mflr r0
|
|
rlwinm r3,r3,3,0xf8
|
|
bcl 20,31,1f
|
|
blr /* fr0 is already in fr0 */
|
|
nop
|
|
reg = 1
|
|
.rept 31
|
|
fmr reg,fr0
|
|
blr
|
|
reg = reg + 1
|
|
.endr
|
|
1: mflr r5
|
|
add r5,r3,r5
|
|
mtctr r5
|
|
mtlr r0
|
|
bctr
|
|
|
|
/* Load FP reg N from float at *p. N is in r3, p in r4. */
|
|
_GLOBAL(do_lfs)
|
|
PPC_STLU r1,-STKFRM(r1)
|
|
mflr r0
|
|
PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mfmsr r6
|
|
ori r7,r6,MSR_FP
|
|
cmpwi cr7,r3,0
|
|
MTMSRD(r7)
|
|
isync
|
|
beq cr7,1f
|
|
stfd fr0,STKFRM-16(r1)
|
|
1: li r9,-EFAULT
|
|
2: lfs fr0,0(r4)
|
|
li r9,0
|
|
3: bl put_fpr
|
|
beq cr7,4f
|
|
lfd fr0,STKFRM-16(r1)
|
|
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mtlr r0
|
|
MTMSRD(r6)
|
|
isync
|
|
mr r3,r9
|
|
addi r1,r1,STKFRM
|
|
blr
|
|
extab 2b,3b
|
|
|
|
/* Load FP reg N from double at *p. N is in r3, p in r4. */
|
|
_GLOBAL(do_lfd)
|
|
PPC_STLU r1,-STKFRM(r1)
|
|
mflr r0
|
|
PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mfmsr r6
|
|
ori r7,r6,MSR_FP
|
|
cmpwi cr7,r3,0
|
|
MTMSRD(r7)
|
|
isync
|
|
beq cr7,1f
|
|
stfd fr0,STKFRM-16(r1)
|
|
1: li r9,-EFAULT
|
|
2: lfd fr0,0(r4)
|
|
li r9,0
|
|
3: beq cr7,4f
|
|
bl put_fpr
|
|
lfd fr0,STKFRM-16(r1)
|
|
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mtlr r0
|
|
MTMSRD(r6)
|
|
isync
|
|
mr r3,r9
|
|
addi r1,r1,STKFRM
|
|
blr
|
|
extab 2b,3b
|
|
|
|
/* Store FP reg N to float at *p. N is in r3, p in r4. */
|
|
_GLOBAL(do_stfs)
|
|
PPC_STLU r1,-STKFRM(r1)
|
|
mflr r0
|
|
PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mfmsr r6
|
|
ori r7,r6,MSR_FP
|
|
cmpwi cr7,r3,0
|
|
MTMSRD(r7)
|
|
isync
|
|
beq cr7,1f
|
|
stfd fr0,STKFRM-16(r1)
|
|
bl get_fpr
|
|
1: li r9,-EFAULT
|
|
2: stfs fr0,0(r4)
|
|
li r9,0
|
|
3: beq cr7,4f
|
|
lfd fr0,STKFRM-16(r1)
|
|
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mtlr r0
|
|
MTMSRD(r6)
|
|
isync
|
|
mr r3,r9
|
|
addi r1,r1,STKFRM
|
|
blr
|
|
extab 2b,3b
|
|
|
|
/* Store FP reg N to double at *p. N is in r3, p in r4. */
|
|
_GLOBAL(do_stfd)
|
|
PPC_STLU r1,-STKFRM(r1)
|
|
mflr r0
|
|
PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mfmsr r6
|
|
ori r7,r6,MSR_FP
|
|
cmpwi cr7,r3,0
|
|
MTMSRD(r7)
|
|
isync
|
|
beq cr7,1f
|
|
stfd fr0,STKFRM-16(r1)
|
|
bl get_fpr
|
|
1: li r9,-EFAULT
|
|
2: stfd fr0,0(r4)
|
|
li r9,0
|
|
3: beq cr7,4f
|
|
lfd fr0,STKFRM-16(r1)
|
|
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mtlr r0
|
|
MTMSRD(r6)
|
|
isync
|
|
mr r3,r9
|
|
addi r1,r1,STKFRM
|
|
blr
|
|
extab 2b,3b
|
|
|
|
#ifdef CONFIG_ALTIVEC
|
|
/* Get the contents of vrN into vr0; N is in r3. */
|
|
_GLOBAL(get_vr)
|
|
mflr r0
|
|
rlwinm r3,r3,3,0xf8
|
|
bcl 20,31,1f
|
|
blr /* vr0 is already in vr0 */
|
|
nop
|
|
reg = 1
|
|
.rept 31
|
|
vor vr0,reg,reg /* assembler doesn't know vmr? */
|
|
blr
|
|
reg = reg + 1
|
|
.endr
|
|
1: mflr r5
|
|
add r5,r3,r5
|
|
mtctr r5
|
|
mtlr r0
|
|
bctr
|
|
|
|
/* Put the contents of vr0 into vrN; N is in r3. */
|
|
_GLOBAL(put_vr)
|
|
mflr r0
|
|
rlwinm r3,r3,3,0xf8
|
|
bcl 20,31,1f
|
|
blr /* vr0 is already in vr0 */
|
|
nop
|
|
reg = 1
|
|
.rept 31
|
|
vor reg,vr0,vr0
|
|
blr
|
|
reg = reg + 1
|
|
.endr
|
|
1: mflr r5
|
|
add r5,r3,r5
|
|
mtctr r5
|
|
mtlr r0
|
|
bctr
|
|
|
|
/* Load vector reg N from *p. N is in r3, p in r4. */
|
|
_GLOBAL(do_lvx)
|
|
PPC_STLU r1,-STKFRM(r1)
|
|
mflr r0
|
|
PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mfmsr r6
|
|
oris r7,r6,MSR_VEC@h
|
|
cmpwi cr7,r3,0
|
|
li r8,STKFRM-16
|
|
MTMSRD(r7)
|
|
isync
|
|
beq cr7,1f
|
|
stvx vr0,r1,r8
|
|
1: li r9,-EFAULT
|
|
2: lvx vr0,0,r4
|
|
li r9,0
|
|
3: beq cr7,4f
|
|
bl put_vr
|
|
lvx vr0,r1,r8
|
|
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mtlr r0
|
|
MTMSRD(r6)
|
|
isync
|
|
mr r3,r9
|
|
addi r1,r1,STKFRM
|
|
blr
|
|
extab 2b,3b
|
|
|
|
/* Store vector reg N to *p. N is in r3, p in r4. */
|
|
_GLOBAL(do_stvx)
|
|
PPC_STLU r1,-STKFRM(r1)
|
|
mflr r0
|
|
PPC_STL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mfmsr r6
|
|
oris r7,r6,MSR_VEC@h
|
|
cmpwi cr7,r3,0
|
|
li r8,STKFRM-16
|
|
MTMSRD(r7)
|
|
isync
|
|
beq cr7,1f
|
|
stvx vr0,r1,r8
|
|
bl get_vr
|
|
1: li r9,-EFAULT
|
|
2: stvx vr0,0,r4
|
|
li r9,0
|
|
3: beq cr7,4f
|
|
lvx vr0,r1,r8
|
|
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mtlr r0
|
|
MTMSRD(r6)
|
|
isync
|
|
mr r3,r9
|
|
addi r1,r1,STKFRM
|
|
blr
|
|
extab 2b,3b
|
|
#endif /* CONFIG_ALTIVEC */
|
|
|
|
#ifdef CONFIG_VSX
|
|
/* Get the contents of vsrN into vsr0; N is in r3. */
|
|
_GLOBAL(get_vsr)
|
|
mflr r0
|
|
rlwinm r3,r3,3,0x1f8
|
|
bcl 20,31,1f
|
|
blr /* vsr0 is already in vsr0 */
|
|
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 vsr0 into vsrN; N is in r3. */
|
|
_GLOBAL(put_vsr)
|
|
mflr r0
|
|
rlwinm r3,r3,3,0x1f8
|
|
bcl 20,31,1f
|
|
blr /* vr0 is already in vr0 */
|
|
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(do_lxvd2x)
|
|
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: li r9,-EFAULT
|
|
2: LXVD2X(0,R0,R4)
|
|
li r9,0
|
|
3: beq cr7,4f
|
|
bl put_vsr
|
|
LXVD2X(0,R1,R8)
|
|
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mtlr r0
|
|
MTMSRD(r6)
|
|
isync
|
|
mr r3,r9
|
|
addi r1,r1,STKFRM
|
|
blr
|
|
extab 2b,3b
|
|
|
|
/* Store VSX reg N to vector doubleword *p. N is in r3, p in r4. */
|
|
_GLOBAL(do_stxvd2x)
|
|
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)
|
|
bl get_vsr
|
|
1: li r9,-EFAULT
|
|
2: STXVD2X(0,R0,R4)
|
|
li r9,0
|
|
3: beq cr7,4f
|
|
LXVD2X(0,R1,R8)
|
|
4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1)
|
|
mtlr r0
|
|
MTMSRD(r6)
|
|
isync
|
|
mr r3,r9
|
|
addi r1,r1,STKFRM
|
|
blr
|
|
extab 2b,3b
|
|
|
|
#endif /* CONFIG_VSX */
|
|
|
|
#endif /* CONFIG_PPC_FPU */
|