summaryrefslogtreecommitdiff
path: root/lib/libpthread/arch/sparc/uthread_machdep_asm.S
blob: 03baf530bef3819d3edac340b62d7316d1b419a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*	$OpenBSD: uthread_machdep_asm.S,v 1.9 2004/02/02 20:43:37 brad Exp $	*/
/* David Leonard <d@csee.uq.edu.au>. Public domain. */

#include <machine/asm.h>
#include <machine/trap.h>

/*
 * Switch stacks.
 * On sparc this also means we switch register windows.
 */

#define SA(x)	(((x)+7)&(~0x7))
#define MINFRAME ((16+1+6)*4)	

/*
 * void _thread_machdep_switch(newstate, oldstate);
 *	struct _machdep_state *newstate, *oldstate;
 */
ENTRY(_thread_machdep_switch)

	/* new window */
	save	%sp, -SA(MINFRAME), %sp

	/* flush all windows (except current one) into memory frames */
	t ST_FLUSHWIN

	/* switch the stack pointer and return address */
	st 	%fp, [%i1 + 0]
	st	%i7, [%i1 + 4]
	ld	[%i0 + 0], %fp
	ld	[%i0 + 4], %i7

	/* return to saved window at new %fp */
	ret
	restore

/*
 * void _thread_machdep_fpsave(csr, regs)
 *	u_int32_t *csr;
 *	u_int64_t *regs;
 */
ENTRY(_thread_machdep_fpsave)
	/*
	 * If %psr were readable, exitting could be faster.  The EF
	 * bit is only set if the FPU is enabled, and we only need
	 * to save fpu state if it is enabled.  But, RDPSR is a
	 * privileged instruction.
	 */

	/* save registers */
	st	%fsr, [%o0]
	std	%f0, [%o1 + 0 * 8]
	std	%f2, [%o1 + 1 * 8]
	std	%f4, [%o1 + 2 * 8]
	std	%f6, [%o1 + 3 * 8]
	std	%f8, [%o1 + 4 * 8]
	std	%f10, [%o1 + 5 * 8]
	std	%f12, [%o1 + 6 * 8]
	std	%f14, [%o1 + 7 * 8]
	std	%f16, [%o1 + 8 * 8]
	std	%f18, [%o1 + 9 * 8]
	std	%f20, [%o1 + 10 * 8]
	std	%f22, [%o1 + 11 * 8]
	std	%f24, [%o1 + 12 * 8]
	std	%f26, [%o1 + 13 * 8]
	std	%f28, [%o1 + 14 * 8]
	std	%f30, [%o1 + 15 * 8]
	retl
	 nop

/*
 * void _thread_machdep_fprestore(csr, regs)
 *	u_int32_t *csr;
 *	u_int64_t *regs;
 */
ENTRY(_thread_machdep_fprestore)
	ldd	[%o1 + 0 * 8], %f0
	ldd	[%o1 + 1 * 8], %f2
	ldd	[%o1 + 2 * 8], %f4
	ldd	[%o1 + 3 * 8], %f6
	ldd	[%o1 + 4 * 8], %f8
	ldd	[%o1 + 5 * 8], %f10
	ldd	[%o1 + 6 * 8], %f12
	ldd	[%o1 + 7 * 8], %f14
	ldd	[%o1 + 8 * 8], %f16
	ldd	[%o1 + 9 * 8], %f18
	ldd	[%o1 + 10 * 8], %f20
	ldd	[%o1 + 11 * 8], %f22
	ldd	[%o1 + 12 * 8], %f24
	ldd	[%o1 + 13 * 8], %f26
	ldd	[%o1 + 14 * 8], %f28
	ldd	[%o1 + 15 * 8], %f30
	ld	[%o0], %fsr
	/* ldfsr needs three instructions to be stable, ensure that here */
	nop
	retl
	 nop