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
9FUNC_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!!!
671:	blr
68
69
70// int check_all_fprs(double darray[32])
71FUNC_START(check_all_fprs)
72	PUSH_BASIC_STACK(8)
73	mr	r4, r3	// r4 = darray
74	li	r3, 1	// prepare for failure
75
76	stfd	f31, STACK_FRAME_LOCAL(0, 0)(sp) // backup f31
77
78	// Check regs f0-f30, using f31 as scratch
79	.set i, 0
80	.rept 31
81	lfd	f31, (8 * i)(r4)	// load expected value
82	fcmpu	cr0, i, f31		// compare
83	bne	cr0, 1f			// bail if mismatch
84	.set i, i + 1
85	.endr
86
87	lfd	f31, STACK_FRAME_LOCAL(0, 0)(sp) // reload f31
88	stfd	f30, STACK_FRAME_LOCAL(0, 0)(sp) // backup f30
89
90	lfd	f30, (8 * 31)(r4)	// load expected value of f31
91	fcmpu	cr0, f30, f31		// compare
92	bne	cr0, 1f			// bail if mismatch
93
94	lfd	f30, STACK_FRAME_LOCAL(0, 0)(sp) // reload f30
95
96	// Success
97	li	r3, 0
98
991:	POP_BASIC_STACK(8)
100	blr
101FUNC_END(check_all_fprs)
102
103FUNC_START(test_fpu)
104	# r3 holds pointer to where to put the result of fork
105	# r4 holds pointer to the pid
106	# f14-f31 are non volatiles
107	PUSH_BASIC_STACK(256)
108	PUSH_FPU(256)
109	std	r3,STACK_FRAME_PARAM(0)(sp) # Address of darray
110	std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid
111
112	// Load FPRs with expected values
113	OP_REGS lfd, 8, 0, 31, r3
114
115	li	r0,__NR_fork
116	sc
117
118	# pass the result of the fork to the caller
119	ld	r9,STACK_FRAME_PARAM(1)(sp)
120	std	r3,0(r9)
121
122	ld r3,STACK_FRAME_PARAM(0)(sp)
123	bl check_all_fprs
124	nop
125
126	POP_FPU(256)
127	POP_BASIC_STACK(256)
128	blr
129FUNC_END(test_fpu)
130
131# int preempt_fpu(double *darray, int *threads_running, int *running)
132# On starting will (atomically) decrement not_ready as a signal that the FPU
133# has been loaded with darray. Will proceed to check the validity of the FPU
134# registers while running is not zero.
135FUNC_START(preempt_fpu)
136	PUSH_BASIC_STACK(256)
137	PUSH_FPU(256)
138	std r3,STACK_FRAME_PARAM(0)(sp) # double *darray
139	std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
140	std r5,STACK_FRAME_PARAM(2)(sp) # int *running
141
142	// Load FPRs with expected values
143	OP_REGS lfd, 8, 0, 31, r3
144
145	sync
146	# Atomic DEC
147	ld r3,STACK_FRAME_PARAM(1)(sp)
1481:	lwarx r4,0,r3
149	addi r4,r4,-1
150	stwcx. r4,0,r3
151	bne- 1b
152
1532:	ld r3,STACK_FRAME_PARAM(0)(sp)
154	bl check_all_fprs
155	cmpdi r3,0
156	bne 3f
157	ld r4,STACK_FRAME_PARAM(2)(sp)
158	ld r5,0(r4)
159	cmpwi r5,0
160	bne 2b
161
1623:	POP_FPU(256)
163	POP_BASIC_STACK(256)
164	blr
165FUNC_END(preempt_fpu)
166