123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- // Copyright 2020 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- //go:build zos && s390x && gc
- #include "textflag.h"
- #define PSALAA 1208(R0)
- #define GTAB64(x) 80(x)
- #define LCA64(x) 88(x)
- #define SAVSTACK_ASYNC(x) 336(x) // in the LCA
- #define CAA(x) 8(x)
- #define CEECAATHDID(x) 976(x) // in the CAA
- #define EDCHPXV(x) 1016(x) // in the CAA
- #define GOCB(x) 1104(x) // in the CAA
- // SS_*, where x=SAVSTACK_ASYNC
- #define SS_LE(x) 0(x)
- #define SS_GO(x) 8(x)
- #define SS_ERRNO(x) 16(x)
- #define SS_ERRNOJR(x) 20(x)
- // Function Descriptor Offsets
- #define __errno 0x156*16
- #define __err2ad 0x16C*16
- // Call Instructions
- #define LE_CALL BYTE $0x0D; BYTE $0x76 // BL R7, R6
- #define SVC_LOAD BYTE $0x0A; BYTE $0x08 // SVC 08 LOAD
- #define SVC_DELETE BYTE $0x0A; BYTE $0x09 // SVC 09 DELETE
- DATA zosLibVec<>(SB)/8, $0
- GLOBL zosLibVec<>(SB), NOPTR, $8
- TEXT ·initZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
- MOVD CAA(R8), R8
- MOVD EDCHPXV(R8), R8
- MOVD R8, zosLibVec<>(SB)
- RET
- TEXT ·GetZosLibVec(SB), NOSPLIT|NOFRAME, $0-0
- MOVD zosLibVec<>(SB), R8
- MOVD R8, ret+0(FP)
- RET
- TEXT ·clearErrno(SB), NOSPLIT, $0-0
- BL addrerrno<>(SB)
- MOVD $0, 0(R3)
- RET
- // Returns the address of errno in R3.
- TEXT addrerrno<>(SB), NOSPLIT|NOFRAME, $0-0
- // Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
- // Get __errno FuncDesc.
- MOVD CAA(R8), R9
- MOVD EDCHPXV(R9), R9
- ADD $(__errno), R9
- LMG 0(R9), R5, R6
- // Switch to saved LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R4
- MOVD $0, 0(R9)
- // Call __errno function.
- LE_CALL
- NOPH
- // Switch back to Go stack.
- XOR R0, R0 // Restore R0 to $0.
- MOVD R4, 0(R9) // Save stack pointer.
- RET
- // func svcCall(fnptr unsafe.Pointer, argv *unsafe.Pointer, dsa *uint64)
- TEXT ·svcCall(SB), NOSPLIT, $0
- BL runtime·save_g(SB) // Save g and stack pointer
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD R15, 0(R9)
- MOVD argv+8(FP), R1 // Move function arguments into registers
- MOVD dsa+16(FP), g
- MOVD fnptr+0(FP), R15
- BYTE $0x0D // Branch to function
- BYTE $0xEF
- BL runtime·load_g(SB) // Restore g and stack pointer
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
- MOVD SAVSTACK_ASYNC(R8), R9
- MOVD 0(R9), R15
- RET
- // func svcLoad(name *byte) unsafe.Pointer
- TEXT ·svcLoad(SB), NOSPLIT, $0
- MOVD R15, R2 // Save go stack pointer
- MOVD name+0(FP), R0 // Move SVC args into registers
- MOVD $0x80000000, R1
- MOVD $0, R15
- SVC_LOAD
- MOVW R15, R3 // Save return code from SVC
- MOVD R2, R15 // Restore go stack pointer
- CMP R3, $0 // Check SVC return code
- BNE error
- MOVD $-2, R3 // Reset last bit of entry point to zero
- AND R0, R3
- MOVD R3, ret+8(FP) // Return entry point returned by SVC
- CMP R0, R3 // Check if last bit of entry point was set
- BNE done
- MOVD R15, R2 // Save go stack pointer
- MOVD $0, R15 // Move SVC args into registers (entry point still in r0 from SVC 08)
- SVC_DELETE
- MOVD R2, R15 // Restore go stack pointer
- error:
- MOVD $0, ret+8(FP) // Return 0 on failure
- done:
- XOR R0, R0 // Reset r0 to 0
- RET
- // func svcUnload(name *byte, fnptr unsafe.Pointer) int64
- TEXT ·svcUnload(SB), NOSPLIT, $0
- MOVD R15, R2 // Save go stack pointer
- MOVD name+0(FP), R0 // Move SVC args into registers
- MOVD fnptr+8(FP), R15
- SVC_DELETE
- XOR R0, R0 // Reset r0 to 0
- MOVD R15, R1 // Save SVC return code
- MOVD R2, R15 // Restore go stack pointer
- MOVD R1, ret+16(FP) // Return SVC return code
- RET
- // func gettid() uint64
- TEXT ·gettid(SB), NOSPLIT, $0
- // Get library control area (LCA).
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
- // Get CEECAATHDID
- MOVD CAA(R8), R9
- MOVD CEECAATHDID(R9), R9
- MOVD R9, ret+0(FP)
- RET
- //
- // Call LE function, if the return is -1
- // errno and errno2 is retrieved
- //
- TEXT ·CallLeFuncWithErr(SB), NOSPLIT, $0
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
- MOVD CAA(R8), R9
- MOVD g, GOCB(R9)
- // Restore LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
- MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
- MOVD parms_base+8(FP), R7 // R7 -> argument array
- MOVD parms_len+16(FP), R8 // R8 number of arguments
- // arg 1 ---> R1
- CMP R8, $0
- BEQ docall
- SUB $1, R8
- MOVD 0(R7), R1
- // arg 2 ---> R2
- CMP R8, $0
- BEQ docall
- SUB $1, R8
- ADD $8, R7
- MOVD 0(R7), R2
- // arg 3 --> R3
- CMP R8, $0
- BEQ docall
- SUB $1, R8
- ADD $8, R7
- MOVD 0(R7), R3
- CMP R8, $0
- BEQ docall
- MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
- repeat:
- ADD $8, R7
- MOVD 0(R7), R0 // advance arg pointer by 8 byte
- ADD $8, R6 // advance LE argument address by 8 byte
- MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
- SUB $1, R8
- CMP R8, $0
- BNE repeat
- docall:
- MOVD funcdesc+0(FP), R8 // R8-> function descriptor
- LMG 0(R8), R5, R6
- MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
- LE_CALL // balr R7, R6 (return #1)
- NOPH
- MOVD R3, ret+32(FP)
- CMP R3, $-1 // compare result to -1
- BNE done
- // retrieve errno and errno2
- MOVD zosLibVec<>(SB), R8
- ADD $(__errno), R8
- LMG 0(R8), R5, R6
- LE_CALL // balr R7, R6 __errno (return #3)
- NOPH
- MOVWZ 0(R3), R3
- MOVD R3, err+48(FP)
- MOVD zosLibVec<>(SB), R8
- ADD $(__err2ad), R8
- LMG 0(R8), R5, R6
- LE_CALL // balr R7, R6 __err2ad (return #2)
- NOPH
- MOVW (R3), R2 // retrieve errno2
- MOVD R2, errno2+40(FP) // store in return area
- done:
- MOVD R4, 0(R9) // Save stack pointer.
- RET
- //
- // Call LE function, if the return is 0
- // errno and errno2 is retrieved
- //
- TEXT ·CallLeFuncWithPtrReturn(SB), NOSPLIT, $0
- MOVW PSALAA, R8
- MOVD LCA64(R8), R8
- MOVD CAA(R8), R9
- MOVD g, GOCB(R9)
- // Restore LE stack.
- MOVD SAVSTACK_ASYNC(R8), R9 // R9-> LE stack frame saving address
- MOVD 0(R9), R4 // R4-> restore previously saved stack frame pointer
- MOVD parms_base+8(FP), R7 // R7 -> argument array
- MOVD parms_len+16(FP), R8 // R8 number of arguments
- // arg 1 ---> R1
- CMP R8, $0
- BEQ docall
- SUB $1, R8
- MOVD 0(R7), R1
- // arg 2 ---> R2
- CMP R8, $0
- BEQ docall
- SUB $1, R8
- ADD $8, R7
- MOVD 0(R7), R2
- // arg 3 --> R3
- CMP R8, $0
- BEQ docall
- SUB $1, R8
- ADD $8, R7
- MOVD 0(R7), R3
- CMP R8, $0
- BEQ docall
- MOVD $2176+16, R6 // starting LE stack address-8 to store 4th argument
- repeat:
- ADD $8, R7
- MOVD 0(R7), R0 // advance arg pointer by 8 byte
- ADD $8, R6 // advance LE argument address by 8 byte
- MOVD R0, (R4)(R6*1) // copy argument from go-slice to le-frame
- SUB $1, R8
- CMP R8, $0
- BNE repeat
- docall:
- MOVD funcdesc+0(FP), R8 // R8-> function descriptor
- LMG 0(R8), R5, R6
- MOVD $0, 0(R9) // R9 address of SAVSTACK_ASYNC
- LE_CALL // balr R7, R6 (return #1)
- NOPH
- MOVD R3, ret+32(FP)
- CMP R3, $0 // compare result to 0
- BNE done
- // retrieve errno and errno2
- MOVD zosLibVec<>(SB), R8
- ADD $(__errno), R8
- LMG 0(R8), R5, R6
- LE_CALL // balr R7, R6 __errno (return #3)
- NOPH
- MOVWZ 0(R3), R3
- MOVD R3, err+48(FP)
- MOVD zosLibVec<>(SB), R8
- ADD $(__err2ad), R8
- LMG 0(R8), R5, R6
- LE_CALL // balr R7, R6 __err2ad (return #2)
- NOPH
- MOVW (R3), R2 // retrieve errno2
- MOVD R2, errno2+40(FP) // store in return area
- XOR R2, R2
- MOVWZ R2, (R3) // clear errno2
- done:
- MOVD R4, 0(R9) // Save stack pointer.
- RET
- //
- // function to test if a pointer can be safely dereferenced (content read)
- // return 0 for succces
- //
- TEXT ·ptrtest(SB), NOSPLIT, $0-16
- MOVD arg+0(FP), R10 // test pointer in R10
- // set up R2 to point to CEECAADMC
- BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
- BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
- BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
- BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
- BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
- BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
- // set up R5 to point to the "shunt" path which set 1 to R3 (failure)
- BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
- BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
- BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
- // if r3 is not zero (failed) then branch to finish
- BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
- BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
- // stomic store shunt address in R5 into CEECAADMC
- BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
- // now try reading from the test pointer in R10, if it fails it branches to the "lghi" instruction above
- BYTE $0xE3; BYTE $0x9A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 9,0(10)
- // finish here, restore 0 into CEECAADMC
- BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
- BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
- MOVD R3, ret+8(FP) // result in R3
- RET
- //
- // function to test if a untptr can be loaded from a pointer
- // return 1: the 8-byte content
- // 2: 0 for success, 1 for failure
- //
- // func safeload(ptr uintptr) ( value uintptr, error uintptr)
- TEXT ·safeload(SB), NOSPLIT, $0-24
- MOVD ptr+0(FP), R10 // test pointer in R10
- MOVD $0x0, R6
- BYTE $0xE3; BYTE $0x20; BYTE $0x04; BYTE $0xB8; BYTE $0x00; BYTE $0x17 // llgt 2,1208
- BYTE $0xB9; BYTE $0x17; BYTE $0x00; BYTE $0x22 // llgtr 2,2
- BYTE $0xA5; BYTE $0x26; BYTE $0x7F; BYTE $0xFF // nilh 2,32767
- BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x58; BYTE $0x00; BYTE $0x04 // lg 2,88(2)
- BYTE $0xE3; BYTE $0x22; BYTE $0x00; BYTE $0x08; BYTE $0x00; BYTE $0x04 // lg 2,8(2)
- BYTE $0x41; BYTE $0x22; BYTE $0x03; BYTE $0x68 // la 2,872(2)
- BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x33 // xgr 3,3
- BYTE $0xA7; BYTE $0x55; BYTE $0x00; BYTE $0x04 // bras 5,lbl1
- BYTE $0xA7; BYTE $0x39; BYTE $0x00; BYTE $0x01 // lghi 3,1
- BYTE $0xB9; BYTE $0x02; BYTE $0x00; BYTE $0x33 // lbl1 ltgr 3,3
- BYTE $0xA7; BYTE $0x74; BYTE $0x00; BYTE $0x08 // brc b'0111',lbl2
- BYTE $0xE3; BYTE $0x52; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 5,0(2)
- BYTE $0xE3; BYTE $0x6A; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x04 // lg 6,0(10)
- BYTE $0xB9; BYTE $0x82; BYTE $0x00; BYTE $0x99 // lbl2 xgr 9,9
- BYTE $0xE3; BYTE $0x92; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x24 // stg 9,0(2)
- MOVD R6, value+8(FP) // result in R6
- MOVD R3, error+16(FP) // error in R3
- RET
|