asm_zos_s390x.s

  1// Copyright 2020 The Go Authors. All rights reserved.
  2// Use of this source code is governed by a BSD-style
  3// license that can be found in the LICENSE file.
  4
  5//go:build zos && s390x && gc
  6
  7#include "textflag.h"
  8
  9#define PSALAA            1208(R0)
 10#define GTAB64(x)           80(x)
 11#define LCA64(x)            88(x)
 12#define SAVSTACK_ASYNC(x)  336(x) // in the LCA
 13#define CAA(x)               8(x)
 14#define CEECAATHDID(x)     976(x) // in the CAA
 15#define EDCHPXV(x)        1016(x) // in the CAA
 16#define GOCB(x)           1104(x) // in the CAA
 17
 18// SS_*, where x=SAVSTACK_ASYNC
 19#define SS_LE(x)             0(x)
 20#define SS_GO(x)             8(x)
 21#define SS_ERRNO(x)         16(x)
 22#define SS_ERRNOJR(x)       20(x)
 23
 24// Function Descriptor Offsets
 25#define __errno  0x156*16
 26#define __err2ad 0x16C*16
 27
 28// Call Instructions
 29#define LE_CALL    BYTE $0x0D; BYTE $0x76 // BL R7, R6
 30#define SVC_LOAD   BYTE $0x0A; BYTE $0x08 // SVC 08 LOAD
 31#define SVC_DELETE BYTE $0x0A; BYTE $0x09 // SVC 09 DELETE
 32
 33DATA zosLibVec<>(SB)/8, $0
 34GLOBL zosLibVec<>(SB), NOPTR, $8
 35
 36TEXT initZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
 37	MOVW PSALAA, R8
 38	MOVD LCA64(R8), R8
 39	MOVD CAA(R8), R8
 40	MOVD EDCHPXV(R8), R8
 41	MOVD R8, zosLibVec<>(SB)
 42	RET
 43
 44TEXT GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
 45	MOVD zosLibVec<>(SB), R8
 46	MOVD R8, ret+0(FP)
 47	RET
 48
 49TEXT clearErrno(SB), NOSPLIT, $0-0
 50	BL   addrerrno<>(SB)
 51	MOVD $0, 0(R3)
 52	RET
 53
 54// Returns the address of errno in R3.
 55TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0
 56	// Get library control area (LCA).
 57	MOVW PSALAA, R8
 58	MOVD LCA64(R8), R8
 59
 60	// Get __errno FuncDesc.
 61	MOVD CAA(R8), R9
 62	MOVD EDCHPXV(R9), R9
 63	ADD  $(__errno), R9
 64	LMG  0(R9), R5, R6
 65
 66	// Switch to saved LE stack.
 67	MOVD SAVSTACK_ASYNC(R8), R9
 68	MOVD 0(R9), R4
 69	MOVD $0, 0(R9)
 70
 71	// Call __errno function.
 72	LE_CALL
 73	NOPH
 74
 75	// Switch back to Go stack.
 76	XOR  R0, R0    // Restore R0 to $0.
 77	MOVD R4, 0(R9) // Save stack pointer.
 78	RET
 79
 80// func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
 81TEXT svcCall(SB), NOSPLIT, $0
 82	BL   runtimesave_g(SB)     // Save g and stack pointer
 83	MOVW PSALAA, R8
 84	MOVD LCA64(R8), R8
 85	MOVD SAVSTACK_ASYNC(R8), R9
 86	MOVD R15, 0(R9)
 87
 88	MOVD argv+8(FP), R1   // Move function arguments into registers
 89	MOVD dsa+16(FP), g
 90	MOVD fnptr+0(FP), R15
 91
 92	BYTE $0x0D // Branch to function
 93	BYTE $0xEF
 94
 95	BL   runtimeload_g(SB)     // Restore g and stack pointer
 96	MOVW PSALAA, R8
 97	MOVD LCA64(R8), R8
 98	MOVD SAVSTACK_ASYNC(R8), R9
 99	MOVD 0(R9), R15
100
101	RET
102
103// func svcLoad(name *byte) unsafe.Pointer
104TEXT svcLoad(SB), NOSPLIT, $0
105	MOVD R15, R2         // Save go stack pointer
106	MOVD name+0(FP), R0  // Move SVC args into registers
107	MOVD $0x80000000, R1
108	MOVD $0, R15
109	SVC_LOAD
110	MOVW R15, R3         // Save return code from SVC
111	MOVD R2, R15         // Restore go stack pointer
112	CMP  R3, $0          // Check SVC return code
113	BNE  error
114
115	MOVD $-2, R3       // Reset last bit of entry point to zero
116	AND  R0, R3
117	MOVD R3, ret+8(FP) // Return entry point returned by SVC
118	CMP  R0, R3        // Check if last bit of entry point was set
119	BNE  done
120
121	MOVD R15, R2 // Save go stack pointer
122	MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
123	SVC_DELETE
124	MOVD R2, R15 // Restore go stack pointer
125
126error:
127	MOVD $0, ret+8(FP) // Return 0 on failure
128
129done:
130	XOR R0, R0 // Reset r0 to 0
131	RET
132
133// func svcUnload(name *byte, fnptr unsafe.Pointer) int64
134TEXT svcUnload(SB), NOSPLIT, $0
135	MOVD R15, R2          // Save go stack pointer
136	MOVD name+0(FP), R0   // Move SVC args into registers
137	MOVD fnptr+8(FP), R15
138	SVC_DELETE
139	XOR  R0, R0           // Reset r0 to 0
140	MOVD R15, R1          // Save SVC return code
141	MOVD R2, R15          // Restore go stack pointer
142	MOVD R1, ret+16(FP)   // Return SVC return code
143	RET
144
145// func gettid() uint64
146TEXT gettid(SB), NOSPLIT, $0
147	// Get library control area (LCA).
148	MOVW PSALAA, R8
149	MOVD LCA64(R8), R8
150
151	// Get CEECAATHDID
152	MOVD CAA(R8), R9
153	MOVD CEECAATHDID(R9), R9
154	MOVD R9, ret+0(FP)
155
156	RET
157
158//
159// Call LE function, if the return is -1
160// errno and errno2 is retrieved
161//
162TEXT CallLeFuncWithErr(SB), NOSPLIT, $0
163	MOVW PSALAA, R8
164	MOVD LCA64(R8), R8
165	MOVD CAA(R8), R9
166	MOVD g, GOCB(R9)
167
168	// Restore LE stack.
169	MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
170	MOVD 0(R9), R4              // R4-> restore previously saved stack frame pointer
171
172	MOVD parms_base+8(FP), R7 // R7 -> argument array
173	MOVD parms_len+16(FP), R8 // R8 number of arguments
174
175	//  arg 1 ---> R1
176	CMP  R8, $0
177	BEQ  docall
178	SUB  $1, R8
179	MOVD 0(R7), R1
180
181	//  arg 2 ---> R2
182	CMP  R8, $0
183	BEQ  docall
184	SUB  $1, R8
185	ADD  $8, R7
186	MOVD 0(R7), R2
187
188	//  arg 3 --> R3
189	CMP  R8, $0
190	BEQ  docall
191	SUB  $1, R8
192	ADD  $8, R7
193	MOVD 0(R7), R3
194
195	CMP  R8, $0
196	BEQ  docall
197	MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
198
199repeat:
200	ADD  $8, R7
201	MOVD 0(R7), R0      // advance arg pointer by 8 byte
202	ADD  $8, R6         // advance LE argument address by 8 byte
203	MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
204	SUB  $1, R8
205	CMP  R8, $0
206	BNE  repeat
207
208docall:
209	MOVD funcdesc+0(FP), R8 // R8-> function descriptor
210	LMG  0(R8), R5, R6
211	MOVD $0, 0(R9)          // R9 address of SAVSTACK_ASYNC
212	LE_CALL                 // balr R7, R6 (return #1)
213	NOPH
214	MOVD R3, ret+32(FP)
215	CMP  R3, $-1            // compare result to -1
216	BNE  done
217
218	// retrieve errno and errno2
219	MOVD  zosLibVec<>(SB), R8
220	ADD   $(__errno), R8
221	LMG   0(R8), R5, R6
222	LE_CALL                   // balr R7, R6 __errno (return #3)
223	NOPH
224	MOVWZ 0(R3), R3
225	MOVD  R3, err+48(FP)
226	MOVD  zosLibVec<>(SB), R8
227	ADD   $(__err2ad), R8
228	LMG   0(R8), R5, R6
229	LE_CALL                   // balr R7, R6 __err2ad (return #2)
230	NOPH
231	MOVW  (R3), R2            // retrieve errno2
232	MOVD  R2, errno2+40(FP)   // store in return area
233
234done:
235	MOVD R4, 0(R9)            // Save stack pointer.
236	RET
237
238//
239// Call LE function, if the return is 0
240// errno and errno2 is retrieved
241//
242TEXT CallLeFuncWithPtrReturn(SB), NOSPLIT, $0
243	MOVW PSALAA, R8
244	MOVD LCA64(R8), R8
245	MOVD CAA(R8), R9
246	MOVD g, GOCB(R9)
247
248	// Restore LE stack.
249	MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
250	MOVD 0(R9), R4              // R4-> restore previously saved stack frame pointer
251
252	MOVD parms_base+8(FP), R7 // R7 -> argument array
253	MOVD parms_len+16(FP), R8 // R8 number of arguments
254
255	//  arg 1 ---> R1
256	CMP  R8, $0
257	BEQ  docall
258	SUB  $1, R8
259	MOVD 0(R7), R1
260
261	//  arg 2 ---> R2
262	CMP  R8, $0
263	BEQ  docall
264	SUB  $1, R8
265	ADD  $8, R7
266	MOVD 0(R7), R2
267
268	//  arg 3 --> R3
269	CMP  R8, $0
270	BEQ  docall
271	SUB  $1, R8
272	ADD  $8, R7
273	MOVD 0(R7), R3
274
275	CMP  R8, $0
276	BEQ  docall
277	MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
278
279repeat:
280	ADD  $8, R7
281	MOVD 0(R7), R0      // advance arg pointer by 8 byte
282	ADD  $8, R6         // advance LE argument address by 8 byte
283	MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
284	SUB  $1, R8
285	CMP  R8, $0
286	BNE  repeat
287
288docall:
289	MOVD funcdesc+0(FP), R8 // R8-> function descriptor
290	LMG  0(R8), R5, R6
291	MOVD $0, 0(R9)          // R9 address of SAVSTACK_ASYNC
292	LE_CALL                 // balr R7, R6 (return #1)
293	NOPH
294	MOVD R3, ret+32(FP)
295	CMP  R3, $0             // compare result to 0
296	BNE  done
297
298	// retrieve errno and errno2
299	MOVD  zosLibVec<>(SB), R8
300	ADD   $(__errno), R8
301	LMG   0(R8), R5, R6
302	LE_CALL                   // balr R7, R6 __errno (return #3)
303	NOPH
304	MOVWZ 0(R3), R3
305	MOVD  R3, err+48(FP)
306	MOVD  zosLibVec<>(SB), R8
307	ADD   $(__err2ad), R8
308	LMG   0(R8), R5, R6
309	LE_CALL                   // balr R7, R6 __err2ad (return #2)
310	NOPH
311	MOVW  (R3), R2            // retrieve errno2
312	MOVD  R2, errno2+40(FP)   // store in return area
313	XOR   R2, R2
314	MOVWZ R2, (R3)            // clear errno2
315
316done:
317	MOVD R4, 0(R9)            // Save stack pointer.
318	RET
319
320//
321// function to test if a pointer can be safely dereferenced (content read)
322// return 0 for succces
323//
324TEXT ptrtest(SB), NOSPLIT, $0-16
325	MOVD arg+0(FP), R10 // test pointer in R10
326
327	// set up R2 to point to CEECAADMC
328	BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt  2,1208
329	BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22                         // llgtr 2,2
330	BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF                         // nilh  2,32767
331	BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg    2,88(2)
332	BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg    2,8(2)
333	BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68                         // la    2,872(2)
334
335	// set up R5 to point to the "shunt" path which set 1 to R3 (failure)
336	BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr   3,3
337	BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras  5,lbl1
338	BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi  3,1
339
340	// if r3 is not zero (failed) then branch to finish
341	BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1     ltgr  3,3
342	BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc   b'0111',lbl2
343
344	// stomic store shunt address in R5 into CEECAADMC
345	BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg   5,0(2)
346
347	// now try reading from the test pointer in R10, if it fails it branches to the "lghi" instruction above
348	BYTE $0xE3; BYTE $0x9A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg    9,0(10)
349
350	// finish here, restore 0 into CEECAADMC
351	BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99                         // lbl2     xgr   9,9
352	BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg   9,0(2)
353	MOVD R3, ret+8(FP)                                                     // result in R3
354	RET
355
356//
357// function to test if a untptr can be loaded from a pointer
358// return 1: the 8-byte content
359//        2: 0 for success, 1 for failure
360//
361// func safeload(ptr uintptr) ( value uintptr, error uintptr)
362TEXT safeload(SB), NOSPLIT, $0-24
363	MOVD ptr+0(FP), R10                                                    // test pointer in R10
364	MOVD $0x0, R6
365	BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt  2,1208
366	BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22                         // llgtr 2,2
367	BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF                         // nilh  2,32767
368	BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg    2,88(2)
369	BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg    2,8(2)
370	BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68                         // la    2,872(2)
371	BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33                         // xgr   3,3
372	BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04                         // bras  5,lbl1
373	BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01                         // lghi  3,1
374	BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33                         // lbl1     ltgr  3,3
375	BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08                         // brc   b'0111',lbl2
376	BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
377	BYTE $0xE3; BYTE $0x6A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg    6,0(10)
378	BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99                         // lbl2     xgr   9,9
379	BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg   9,0(2)
380	MOVD R6, value+8(FP)                                                   // result in R6
381	MOVD R3, error+16(FP)                                                  // error in R3
382	RET