asm_zos_s390x.s raw

   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  
  33  DATA zosLibVec<>(SB)/8, $0
  34  GLOBL zosLibVec<>(SB), NOPTR, $8
  35  
  36  TEXT ·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  
  44  TEXT ·GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
  45  	MOVD zosLibVec<>(SB), R8
  46  	MOVD R8, ret+0(FP)
  47  	RET
  48  
  49  TEXT ·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.
  55  TEXT 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)
  81  TEXT ·svcCall(SB), NOSPLIT, $0
  82  	BL   runtime·save_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   runtime·load_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
 104  TEXT ·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  
 126  error:
 127  	MOVD $0, ret+8(FP) // Return 0 on failure
 128  
 129  done:
 130  	XOR R0, R0 // Reset r0 to 0
 131  	RET
 132  
 133  // func svcUnload(name *byte, fnptr unsafe.Pointer) int64
 134  TEXT ·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
 146  TEXT ·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  //
 162  TEXT ·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  
 199  repeat:
 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  
 208  docall:
 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  
 234  done:
 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  //
 242  TEXT ·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  
 279  repeat:
 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  
 288  docall:
 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  
 316  done:
 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  //
 324  TEXT ·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)
 362  TEXT ·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
 383