src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

asm_zos_s390x.s (11433B)


      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