1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Copyright 2015, Cyril Bur, IBM Corp.
4  */
5 
6 #include "basic_asm.h"
7 #include "fpu_asm.h"
8 
9 FUNC_START(check_fpu)
10 	mr r4,r3
11 	li	r3,1 # assume a bad result
12 	lfd	f0,0(r4)
13 	fcmpu	cr1,f0,f14
14 	bne	cr1,1f
15 	lfd	f0,8(r4)
16 	fcmpu	cr1,f0,f15
17 	bne	cr1,1f
18 	lfd	f0,16(r4)
19 	fcmpu	cr1,f0,f16
20 	bne	cr1,1f
21 	lfd	f0,24(r4)
22 	fcmpu	cr1,f0,f17
23 	bne	cr1,1f
24 	lfd	f0,32(r4)
25 	fcmpu	cr1,f0,f18
26 	bne	cr1,1f
27 	lfd	f0,40(r4)
28 	fcmpu	cr1,f0,f19
29 	bne	cr1,1f
30 	lfd	f0,48(r4)
31 	fcmpu	cr1,f0,f20
32 	bne	cr1,1f
33 	lfd	f0,56(r4)
34 	fcmpu	cr1,f0,f21
35 	bne	cr1,1f
36 	lfd	f0,64(r4)
37 	fcmpu	cr1,f0,f22
38 	bne	cr1,1f
39 	lfd	f0,72(r4)
40 	fcmpu	cr1,f0,f23
41 	bne	cr1,1f
42 	lfd	f0,80(r4)
43 	fcmpu	cr1,f0,f24
44 	bne	cr1,1f
45 	lfd	f0,88(r4)
46 	fcmpu	cr1,f0,f25
47 	bne	cr1,1f
48 	lfd	f0,96(r4)
49 	fcmpu	cr1,f0,f26
50 	bne	cr1,1f
51 	lfd	f0,104(r4)
52 	fcmpu	cr1,f0,f27
53 	bne	cr1,1f
54 	lfd	f0,112(r4)
55 	fcmpu	cr1,f0,f28
56 	bne	cr1,1f
57 	lfd	f0,120(r4)
58 	fcmpu	cr1,f0,f29
59 	bne	cr1,1f
60 	lfd	f0,128(r4)
61 	fcmpu	cr1,f0,f30
62 	bne	cr1,1f
63 	lfd	f0,136(r4)
64 	fcmpu	cr1,f0,f31
65 	bne	cr1,1f
66 	li	r3,0 # Success!!!
67 1:	blr
68 
69 FUNC_START(test_fpu)
70 	# r3 holds pointer to where to put the result of fork
71 	# r4 holds pointer to the pid
72 	# f14-f31 are non volatiles
73 	PUSH_BASIC_STACK(256)
74 	PUSH_FPU(256)
75 	std	r3,STACK_FRAME_PARAM(0)(sp) # Address of darray
76 	std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid
77 
78 	bl load_fpu
79 	nop
80 	li	r0,__NR_fork
81 	sc
82 
83 	# pass the result of the fork to the caller
84 	ld	r9,STACK_FRAME_PARAM(1)(sp)
85 	std	r3,0(r9)
86 
87 	ld r3,STACK_FRAME_PARAM(0)(sp)
88 	bl check_fpu
89 	nop
90 
91 	POP_FPU(256)
92 	POP_BASIC_STACK(256)
93 	blr
94 FUNC_END(test_fpu)
95 
96 # int preempt_fpu(double *darray, int *threads_running, int *running)
97 # On starting will (atomically) decrement not_ready as a signal that the FPU
98 # has been loaded with darray. Will proceed to check the validity of the FPU
99 # registers while running is not zero.
100 FUNC_START(preempt_fpu)
101 	PUSH_BASIC_STACK(256)
102 	PUSH_FPU(256)
103 	std r3,STACK_FRAME_PARAM(0)(sp) # double *darray
104 	std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
105 	std r5,STACK_FRAME_PARAM(2)(sp) # int *running
106 
107 	bl load_fpu
108 	nop
109 
110 	sync
111 	# Atomic DEC
112 	ld r3,STACK_FRAME_PARAM(1)(sp)
113 1:	lwarx r4,0,r3
114 	addi r4,r4,-1
115 	stwcx. r4,0,r3
116 	bne- 1b
117 
118 2:	ld r3,STACK_FRAME_PARAM(0)(sp)
119 	bl check_fpu
120 	nop
121 	cmpdi r3,0
122 	bne 3f
123 	ld r4,STACK_FRAME_PARAM(2)(sp)
124 	ld r5,0(r4)
125 	cmpwi r5,0
126 	bne 2b
127 
128 3:	POP_FPU(256)
129 	POP_BASIC_STACK(256)
130 	blr
131 FUNC_END(preempt_fpu)
132