asm_zos_s390x.s 11 KB

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