1/*******************************************************
2 *  -------------------------------------------------  *
3 *  |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  *
4 *  -------------------------------------------------  *
5 *  |     0     |     8     |    16     |    24     |  *
6 *  -------------------------------------------------  *
7 *  |   t.fctx  |   t.data  |    r2     |    r6     |  *
8 *  -------------------------------------------------  *
9 *  -------------------------------------------------  *
10 *  |  8  |  9  |  10 |  11 |  12 |  13 |  14 |  15 |  *
11 *  -------------------------------------------------  *
12 *  |     32    |    40     |     48    |     56    |  *
13 *  -------------------------------------------------  *
14 *  |     r7    |     r8    |     r9    |    r10    |  *
15 *  -------------------------------------------------  *
16 *  -------------------------------------------------  *
17 *  |  16 |  17 |  18 |  19 |  20 |  21 |  22 |  23 |  *
18 *  -------------------------------------------------  *
19 *  |     64    |     72    |     80    |     88    |  *
20 *  -------------------------------------------------  *
21 *  |    r11    |    r12    |    r13    |    r14    |  *
22 *  -------------------------------------------------  *
23 *  -------------------------------------------------  *
24 *  |  24 |  25 |  26 |  27 |  28 | 29  |  30 |  31 |  *
25 *  -------------------------------------------------  *
26 *  |     96    |    104    |    112    |    120    |  *
27 *  -------------------------------------------------  *
28 *  |     f8    |     f9    |    f10    |    f11    |  *
29 *  -------------------------------------------------  *
30 *  -------------------------------------------------  *
31 *  |  32 |  33 |  34 |  35 |  36 |  37 |  38 |  39 |  *
32 *  -------------------------------------------------  *
33 *  |    128    |    136    |    144    |    152    |  *
34 *  -------------------------------------------------  *
35 *  |    f12    |    f13    |    f14    |    f15    |  *
36 *  -------------------------------------------------  *
37 *  -------------------------------------------------  *
38 *  |  40 |  41 |  42 |  43 |  44 |  45 |  46 |  47 |  *
39 *  -------------------------------------------------  *
40 *  |    160    |    168    |    176    |           |  *
41 *  -------------------------------------------------  *
42 *  |    fpc    |     pc    |           |           |  *
43 *  -------------------------------------------------  *
44 *******************************************************/
45
46.text
47.align	8
48.global	jump_fcontext
49.type	jump_fcontext, @function
50
51#define ARG_OFFSET         0
52#define GR_OFFSET	   16
53#define FP_OFFSET	   96
54#define FPC_OFFSET	   160
55#define PC_OFFSET	   168
56#define CONTEXT_SIZE	   176
57
58#define REG_SAVE_AREA_SIZE 160
59
60/*
61
62typedef void*   fcontext_t;
63
64struct transfer_t {
65   fcontext_t  fctx;
66   void    *   data;
67};
68
69transfer_t jump_fcontext( fcontext_t const to,
70			  void * data);
71
72Incoming args
73r2 - Hidden argument to the location where the return transfer_t needs to be returned
74r3 - Context we want to switch to
75r4 - Data pointer
76
77*/
78
79jump_fcontext:
80	.machine "z10"
81	/* Reserve stack space to store the current context.  */
82	aghi	%r15,-CONTEXT_SIZE
83
84	/* Save the argument register holding the location of the return value.  */
85	stg	%r2,GR_OFFSET(%r15)
86
87	/* Save the call-saved general purpose registers.  */
88	stmg	%r6,%r14,GR_OFFSET+8(%r15)
89
90	/* Save call-saved floating point registers.  */
91	std	%f8,FP_OFFSET(%r15)
92	std	%f9,FP_OFFSET+8(%r15)
93	std	%f10,FP_OFFSET+16(%r15)
94	std	%f11,FP_OFFSET+24(%r15)
95	std	%f12,FP_OFFSET+32(%r15)
96	std	%f13,FP_OFFSET+40(%r15)
97	std	%f14,FP_OFFSET+48(%r15)
98	std	%f15,FP_OFFSET+56(%r15)
99
100	/* Save the return address as current pc.  */
101	stg	%r14,PC_OFFSET(%r15)
102
103	/* Save the floating point control register.  */
104	stfpc	FPC_OFFSET(%r15)
105
106	/* Backup the stack pointer pointing to the old context-data into r1.  */
107	lgr	 %r1,%r15
108
109	/* Load the new context pointer as stack pointer.  */
110	lgr	%r15,%r3
111
112	/* Restore the call-saved GPRs from the new context.  */
113	lmg	%r6,%r14,GR_OFFSET+8(%r15)
114
115	/* Restore call-saved floating point registers.  */
116	ld	%f8,FP_OFFSET(%r15)
117	ld	%f9,FP_OFFSET+8(%r15)
118	ld	%f10,FP_OFFSET+16(%r15)
119	ld	%f11,FP_OFFSET+24(%r15)
120	ld	%f12,FP_OFFSET+32(%r15)
121	ld	%f13,FP_OFFSET+40(%r15)
122	ld	%f14,FP_OFFSET+48(%r15)
123	ld	%f15,FP_OFFSET+56(%r15)
124
125	/* Load the floating point control register.  */
126	lfpc	FPC_OFFSET(%r15)
127
128	/* Restore PC - the location where we will jump to at the end.  */
129	lg	%r5,PC_OFFSET(%r15)
130
131	ltg	%r2,GR_OFFSET(%r15)
132	jnz	use_return_slot
133
134	/* We restore a make_fcontext context.  Use the function
135	   argument slot in the context we just saved and allocate the
136	   register save area for the target function.  */
137	la	%r2,ARG_OFFSET(%r1)
138	aghi	%r15,-REG_SAVE_AREA_SIZE
139
140use_return_slot:
141	/* Save the two fields in transfer_t.  When calling a
142	   make_fcontext function this becomes the function argument of
143	   the target function, otherwise it will be the return value of
144	   jump_fcontext.  */
145	stg	%r1,0(%r2)
146	stg	%r4,8(%r2)
147
148	/* Free the restored context.  */
149	aghi	%r15,CONTEXT_SIZE
150
151	/* Jump to the PC loaded from the new context.  */
152	br	%r5
153
154
155.size   jump_fcontext,.-jump_fcontext
156.section .note.GNU-stack,"",%progbits
157