162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2015, Cyril Bur, IBM Corp.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include "basic_asm.h"
762306a36Sopenharmony_ci#include "fpu_asm.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciFUNC_START(check_fpu)
1062306a36Sopenharmony_ci	mr r4,r3
1162306a36Sopenharmony_ci	li	r3,1 # assume a bad result
1262306a36Sopenharmony_ci	lfd	f0,0(r4)
1362306a36Sopenharmony_ci	fcmpu	cr1,f0,f14
1462306a36Sopenharmony_ci	bne	cr1,1f
1562306a36Sopenharmony_ci	lfd	f0,8(r4)
1662306a36Sopenharmony_ci	fcmpu	cr1,f0,f15
1762306a36Sopenharmony_ci	bne	cr1,1f
1862306a36Sopenharmony_ci	lfd	f0,16(r4)
1962306a36Sopenharmony_ci	fcmpu	cr1,f0,f16
2062306a36Sopenharmony_ci	bne	cr1,1f
2162306a36Sopenharmony_ci	lfd	f0,24(r4)
2262306a36Sopenharmony_ci	fcmpu	cr1,f0,f17
2362306a36Sopenharmony_ci	bne	cr1,1f
2462306a36Sopenharmony_ci	lfd	f0,32(r4)
2562306a36Sopenharmony_ci	fcmpu	cr1,f0,f18
2662306a36Sopenharmony_ci	bne	cr1,1f
2762306a36Sopenharmony_ci	lfd	f0,40(r4)
2862306a36Sopenharmony_ci	fcmpu	cr1,f0,f19
2962306a36Sopenharmony_ci	bne	cr1,1f
3062306a36Sopenharmony_ci	lfd	f0,48(r4)
3162306a36Sopenharmony_ci	fcmpu	cr1,f0,f20
3262306a36Sopenharmony_ci	bne	cr1,1f
3362306a36Sopenharmony_ci	lfd	f0,56(r4)
3462306a36Sopenharmony_ci	fcmpu	cr1,f0,f21
3562306a36Sopenharmony_ci	bne	cr1,1f
3662306a36Sopenharmony_ci	lfd	f0,64(r4)
3762306a36Sopenharmony_ci	fcmpu	cr1,f0,f22
3862306a36Sopenharmony_ci	bne	cr1,1f
3962306a36Sopenharmony_ci	lfd	f0,72(r4)
4062306a36Sopenharmony_ci	fcmpu	cr1,f0,f23
4162306a36Sopenharmony_ci	bne	cr1,1f
4262306a36Sopenharmony_ci	lfd	f0,80(r4)
4362306a36Sopenharmony_ci	fcmpu	cr1,f0,f24
4462306a36Sopenharmony_ci	bne	cr1,1f
4562306a36Sopenharmony_ci	lfd	f0,88(r4)
4662306a36Sopenharmony_ci	fcmpu	cr1,f0,f25
4762306a36Sopenharmony_ci	bne	cr1,1f
4862306a36Sopenharmony_ci	lfd	f0,96(r4)
4962306a36Sopenharmony_ci	fcmpu	cr1,f0,f26
5062306a36Sopenharmony_ci	bne	cr1,1f
5162306a36Sopenharmony_ci	lfd	f0,104(r4)
5262306a36Sopenharmony_ci	fcmpu	cr1,f0,f27
5362306a36Sopenharmony_ci	bne	cr1,1f
5462306a36Sopenharmony_ci	lfd	f0,112(r4)
5562306a36Sopenharmony_ci	fcmpu	cr1,f0,f28
5662306a36Sopenharmony_ci	bne	cr1,1f
5762306a36Sopenharmony_ci	lfd	f0,120(r4)
5862306a36Sopenharmony_ci	fcmpu	cr1,f0,f29
5962306a36Sopenharmony_ci	bne	cr1,1f
6062306a36Sopenharmony_ci	lfd	f0,128(r4)
6162306a36Sopenharmony_ci	fcmpu	cr1,f0,f30
6262306a36Sopenharmony_ci	bne	cr1,1f
6362306a36Sopenharmony_ci	lfd	f0,136(r4)
6462306a36Sopenharmony_ci	fcmpu	cr1,f0,f31
6562306a36Sopenharmony_ci	bne	cr1,1f
6662306a36Sopenharmony_ci	li	r3,0 # Success!!!
6762306a36Sopenharmony_ci1:	blr
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ciFUNC_START(test_fpu)
7062306a36Sopenharmony_ci	# r3 holds pointer to where to put the result of fork
7162306a36Sopenharmony_ci	# r4 holds pointer to the pid
7262306a36Sopenharmony_ci	# f14-f31 are non volatiles
7362306a36Sopenharmony_ci	PUSH_BASIC_STACK(256)
7462306a36Sopenharmony_ci	PUSH_FPU(256)
7562306a36Sopenharmony_ci	std	r3,STACK_FRAME_PARAM(0)(sp) # Address of darray
7662306a36Sopenharmony_ci	std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	bl load_fpu
7962306a36Sopenharmony_ci	nop
8062306a36Sopenharmony_ci	li	r0,__NR_fork
8162306a36Sopenharmony_ci	sc
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	# pass the result of the fork to the caller
8462306a36Sopenharmony_ci	ld	r9,STACK_FRAME_PARAM(1)(sp)
8562306a36Sopenharmony_ci	std	r3,0(r9)
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	ld r3,STACK_FRAME_PARAM(0)(sp)
8862306a36Sopenharmony_ci	bl check_fpu
8962306a36Sopenharmony_ci	nop
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	POP_FPU(256)
9262306a36Sopenharmony_ci	POP_BASIC_STACK(256)
9362306a36Sopenharmony_ci	blr
9462306a36Sopenharmony_ciFUNC_END(test_fpu)
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci# int preempt_fpu(double *darray, int *threads_running, int *running)
9762306a36Sopenharmony_ci# On starting will (atomically) decrement not_ready as a signal that the FPU
9862306a36Sopenharmony_ci# has been loaded with darray. Will proceed to check the validity of the FPU
9962306a36Sopenharmony_ci# registers while running is not zero.
10062306a36Sopenharmony_ciFUNC_START(preempt_fpu)
10162306a36Sopenharmony_ci	PUSH_BASIC_STACK(256)
10262306a36Sopenharmony_ci	PUSH_FPU(256)
10362306a36Sopenharmony_ci	std r3,STACK_FRAME_PARAM(0)(sp) # double *darray
10462306a36Sopenharmony_ci	std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
10562306a36Sopenharmony_ci	std r5,STACK_FRAME_PARAM(2)(sp) # int *running
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	bl load_fpu
10862306a36Sopenharmony_ci	nop
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	sync
11162306a36Sopenharmony_ci	# Atomic DEC
11262306a36Sopenharmony_ci	ld r3,STACK_FRAME_PARAM(1)(sp)
11362306a36Sopenharmony_ci1:	lwarx r4,0,r3
11462306a36Sopenharmony_ci	addi r4,r4,-1
11562306a36Sopenharmony_ci	stwcx. r4,0,r3
11662306a36Sopenharmony_ci	bne- 1b
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci2:	ld r3,STACK_FRAME_PARAM(0)(sp)
11962306a36Sopenharmony_ci	bl check_fpu
12062306a36Sopenharmony_ci	nop
12162306a36Sopenharmony_ci	cmpdi r3,0
12262306a36Sopenharmony_ci	bne 3f
12362306a36Sopenharmony_ci	ld r4,STACK_FRAME_PARAM(2)(sp)
12462306a36Sopenharmony_ci	ld r5,0(r4)
12562306a36Sopenharmony_ci	cmpwi r5,0
12662306a36Sopenharmony_ci	bne 2b
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci3:	POP_FPU(256)
12962306a36Sopenharmony_ci	POP_BASIC_STACK(256)
13062306a36Sopenharmony_ci	blr
13162306a36Sopenharmony_ciFUNC_END(preempt_fpu)
132