/Modules/_ctypes/libffi/src/ia64/unix.S

http://unladen-swallow.googlecode.com/ · Assembly · 560 lines · 393 code · 30 blank · 137 comment · 1 complexity · 8e5389d0a78a91c44ad3532ef97779da MD5 · raw file

  1. /* -----------------------------------------------------------------------
  2. unix.S - Copyright (c) 1998, 2008 Red Hat, Inc.
  3. Copyright (c) 2000 Hewlett Packard Company
  4. IA64/unix Foreign Function Interface
  5. Primary author: Hans Boehm, HP Labs
  6. Loosely modeled on Cygnus code for other platforms.
  7. Permission is hereby granted, free of charge, to any person obtaining
  8. a copy of this software and associated documentation files (the
  9. ``Software''), to deal in the Software without restriction, including
  10. without limitation the rights to use, copy, modify, merge, publish,
  11. distribute, sublicense, and/or sell copies of the Software, and to
  12. permit persons to whom the Software is furnished to do so, subject to
  13. the following conditions:
  14. The above copyright notice and this permission notice shall be included
  15. in all copies or substantial portions of the Software.
  16. THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
  17. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. DEALINGS IN THE SOFTWARE.
  24. ----------------------------------------------------------------------- */
  25. #define LIBFFI_ASM
  26. #include <fficonfig.h>
  27. #include <ffi.h>
  28. #include "ia64_flags.h"
  29. .pred.safe_across_calls p1-p5,p16-p63
  30. .text
  31. /* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
  32. void (*fn)(void), int flags);
  33. */
  34. .align 16
  35. .global ffi_call_unix
  36. .proc ffi_call_unix
  37. ffi_call_unix:
  38. .prologue
  39. /* Bit o trickiness. We actually share a stack frame with ffi_call.
  40. Rely on the fact that ffi_call uses a vframe and don't bother
  41. tracking one here at all. */
  42. .fframe 0
  43. .save ar.pfs, r36 // loc0
  44. alloc loc0 = ar.pfs, 4, 3, 8, 0
  45. .save rp, loc1
  46. mov loc1 = b0
  47. .body
  48. add r16 = 16, in0
  49. mov loc2 = gp
  50. mov r8 = in1
  51. ;;
  52. /* Load up all of the argument registers. */
  53. ldf.fill f8 = [in0], 32
  54. ldf.fill f9 = [r16], 32
  55. ;;
  56. ldf.fill f10 = [in0], 32
  57. ldf.fill f11 = [r16], 32
  58. ;;
  59. ldf.fill f12 = [in0], 32
  60. ldf.fill f13 = [r16], 32
  61. ;;
  62. ldf.fill f14 = [in0], 32
  63. ldf.fill f15 = [r16], 24
  64. ;;
  65. ld8 out0 = [in0], 16
  66. ld8 out1 = [r16], 16
  67. ;;
  68. ld8 out2 = [in0], 16
  69. ld8 out3 = [r16], 16
  70. ;;
  71. ld8 out4 = [in0], 16
  72. ld8 out5 = [r16], 16
  73. ;;
  74. ld8 out6 = [in0]
  75. ld8 out7 = [r16]
  76. ;;
  77. /* Deallocate the register save area from the stack frame. */
  78. mov sp = in0
  79. /* Call the target function. */
  80. ld8 r16 = [in2], 8
  81. ;;
  82. ld8 gp = [in2]
  83. mov b6 = r16
  84. br.call.sptk.many b0 = b6
  85. ;;
  86. /* Dispatch to handle return value. */
  87. mov gp = loc2
  88. zxt1 r16 = in3
  89. ;;
  90. mov ar.pfs = loc0
  91. addl r18 = @ltoffx(.Lst_table), gp
  92. ;;
  93. ld8.mov r18 = [r18], .Lst_table
  94. mov b0 = loc1
  95. ;;
  96. shladd r18 = r16, 3, r18
  97. ;;
  98. ld8 r17 = [r18]
  99. shr in3 = in3, 8
  100. ;;
  101. add r17 = r17, r18
  102. ;;
  103. mov b6 = r17
  104. br b6
  105. ;;
  106. .Lst_void:
  107. br.ret.sptk.many b0
  108. ;;
  109. .Lst_uint8:
  110. zxt1 r8 = r8
  111. ;;
  112. st8 [in1] = r8
  113. br.ret.sptk.many b0
  114. ;;
  115. .Lst_sint8:
  116. sxt1 r8 = r8
  117. ;;
  118. st8 [in1] = r8
  119. br.ret.sptk.many b0
  120. ;;
  121. .Lst_uint16:
  122. zxt2 r8 = r8
  123. ;;
  124. st8 [in1] = r8
  125. br.ret.sptk.many b0
  126. ;;
  127. .Lst_sint16:
  128. sxt2 r8 = r8
  129. ;;
  130. st8 [in1] = r8
  131. br.ret.sptk.many b0
  132. ;;
  133. .Lst_uint32:
  134. zxt4 r8 = r8
  135. ;;
  136. st8 [in1] = r8
  137. br.ret.sptk.many b0
  138. ;;
  139. .Lst_sint32:
  140. sxt4 r8 = r8
  141. ;;
  142. st8 [in1] = r8
  143. br.ret.sptk.many b0
  144. ;;
  145. .Lst_int64:
  146. st8 [in1] = r8
  147. br.ret.sptk.many b0
  148. ;;
  149. .Lst_float:
  150. stfs [in1] = f8
  151. br.ret.sptk.many b0
  152. ;;
  153. .Lst_double:
  154. stfd [in1] = f8
  155. br.ret.sptk.many b0
  156. ;;
  157. .Lst_ldouble:
  158. stfe [in1] = f8
  159. br.ret.sptk.many b0
  160. ;;
  161. .Lst_small_struct:
  162. add sp = -16, sp
  163. cmp.lt p6, p0 = 8, in3
  164. cmp.lt p7, p0 = 16, in3
  165. cmp.lt p8, p0 = 24, in3
  166. ;;
  167. add r16 = 8, sp
  168. add r17 = 16, sp
  169. add r18 = 24, sp
  170. ;;
  171. st8 [sp] = r8
  172. (p6) st8 [r16] = r9
  173. mov out0 = in1
  174. (p7) st8 [r17] = r10
  175. (p8) st8 [r18] = r11
  176. mov out1 = sp
  177. mov out2 = in3
  178. br.call.sptk.many b0 = memcpy#
  179. ;;
  180. mov ar.pfs = loc0
  181. mov b0 = loc1
  182. mov gp = loc2
  183. br.ret.sptk.many b0
  184. .Lst_hfa_float:
  185. add r16 = 4, in1
  186. cmp.lt p6, p0 = 4, in3
  187. ;;
  188. stfs [in1] = f8, 8
  189. (p6) stfs [r16] = f9, 8
  190. cmp.lt p7, p0 = 8, in3
  191. cmp.lt p8, p0 = 12, in3
  192. ;;
  193. (p7) stfs [in1] = f10, 8
  194. (p8) stfs [r16] = f11, 8
  195. cmp.lt p9, p0 = 16, in3
  196. cmp.lt p10, p0 = 20, in3
  197. ;;
  198. (p9) stfs [in1] = f12, 8
  199. (p10) stfs [r16] = f13, 8
  200. cmp.lt p6, p0 = 24, in3
  201. cmp.lt p7, p0 = 28, in3
  202. ;;
  203. (p6) stfs [in1] = f14
  204. (p7) stfs [r16] = f15
  205. br.ret.sptk.many b0
  206. ;;
  207. .Lst_hfa_double:
  208. add r16 = 8, in1
  209. cmp.lt p6, p0 = 8, in3
  210. ;;
  211. stfd [in1] = f8, 16
  212. (p6) stfd [r16] = f9, 16
  213. cmp.lt p7, p0 = 16, in3
  214. cmp.lt p8, p0 = 24, in3
  215. ;;
  216. (p7) stfd [in1] = f10, 16
  217. (p8) stfd [r16] = f11, 16
  218. cmp.lt p9, p0 = 32, in3
  219. cmp.lt p10, p0 = 40, in3
  220. ;;
  221. (p9) stfd [in1] = f12, 16
  222. (p10) stfd [r16] = f13, 16
  223. cmp.lt p6, p0 = 48, in3
  224. cmp.lt p7, p0 = 56, in3
  225. ;;
  226. (p6) stfd [in1] = f14
  227. (p7) stfd [r16] = f15
  228. br.ret.sptk.many b0
  229. ;;
  230. .Lst_hfa_ldouble:
  231. add r16 = 16, in1
  232. cmp.lt p6, p0 = 16, in3
  233. ;;
  234. stfe [in1] = f8, 32
  235. (p6) stfe [r16] = f9, 32
  236. cmp.lt p7, p0 = 32, in3
  237. cmp.lt p8, p0 = 48, in3
  238. ;;
  239. (p7) stfe [in1] = f10, 32
  240. (p8) stfe [r16] = f11, 32
  241. cmp.lt p9, p0 = 64, in3
  242. cmp.lt p10, p0 = 80, in3
  243. ;;
  244. (p9) stfe [in1] = f12, 32
  245. (p10) stfe [r16] = f13, 32
  246. cmp.lt p6, p0 = 96, in3
  247. cmp.lt p7, p0 = 112, in3
  248. ;;
  249. (p6) stfe [in1] = f14
  250. (p7) stfe [r16] = f15
  251. br.ret.sptk.many b0
  252. ;;
  253. .endp ffi_call_unix
  254. .align 16
  255. .global ffi_closure_unix
  256. .proc ffi_closure_unix
  257. #define FRAME_SIZE (8*16 + 8*8 + 8*16)
  258. ffi_closure_unix:
  259. .prologue
  260. .save ar.pfs, r40 // loc0
  261. alloc loc0 = ar.pfs, 8, 4, 4, 0
  262. .fframe FRAME_SIZE
  263. add r12 = -FRAME_SIZE, r12
  264. .save rp, loc1
  265. mov loc1 = b0
  266. .save ar.unat, loc2
  267. mov loc2 = ar.unat
  268. .body
  269. /* Retrieve closure pointer and real gp. */
  270. #ifdef _ILP32
  271. addp4 out0 = 0, gp
  272. addp4 gp = 16, gp
  273. #else
  274. mov out0 = gp
  275. add gp = 16, gp
  276. #endif
  277. ;;
  278. ld8 gp = [gp]
  279. /* Spill all of the possible argument registers. */
  280. add r16 = 16 + 8*16, sp
  281. add r17 = 16 + 8*16 + 16, sp
  282. ;;
  283. stf.spill [r16] = f8, 32
  284. stf.spill [r17] = f9, 32
  285. mov loc3 = gp
  286. ;;
  287. stf.spill [r16] = f10, 32
  288. stf.spill [r17] = f11, 32
  289. ;;
  290. stf.spill [r16] = f12, 32
  291. stf.spill [r17] = f13, 32
  292. ;;
  293. stf.spill [r16] = f14, 32
  294. stf.spill [r17] = f15, 24
  295. ;;
  296. .mem.offset 0, 0
  297. st8.spill [r16] = in0, 16
  298. .mem.offset 8, 0
  299. st8.spill [r17] = in1, 16
  300. add out1 = 16 + 8*16, sp
  301. ;;
  302. .mem.offset 0, 0
  303. st8.spill [r16] = in2, 16
  304. .mem.offset 8, 0
  305. st8.spill [r17] = in3, 16
  306. add out2 = 16, sp
  307. ;;
  308. .mem.offset 0, 0
  309. st8.spill [r16] = in4, 16
  310. .mem.offset 8, 0
  311. st8.spill [r17] = in5, 16
  312. mov out3 = r8
  313. ;;
  314. .mem.offset 0, 0
  315. st8.spill [r16] = in6
  316. .mem.offset 8, 0
  317. st8.spill [r17] = in7
  318. /* Invoke ffi_closure_unix_inner for the hard work. */
  319. br.call.sptk.many b0 = ffi_closure_unix_inner
  320. ;;
  321. /* Dispatch to handle return value. */
  322. mov gp = loc3
  323. zxt1 r16 = r8
  324. ;;
  325. addl r18 = @ltoffx(.Lld_table), gp
  326. mov ar.pfs = loc0
  327. ;;
  328. ld8.mov r18 = [r18], .Lld_table
  329. mov b0 = loc1
  330. ;;
  331. shladd r18 = r16, 3, r18
  332. mov ar.unat = loc2
  333. ;;
  334. ld8 r17 = [r18]
  335. shr r8 = r8, 8
  336. ;;
  337. add r17 = r17, r18
  338. add r16 = 16, sp
  339. ;;
  340. mov b6 = r17
  341. br b6
  342. ;;
  343. .label_state 1
  344. .Lld_void:
  345. .restore sp
  346. add sp = FRAME_SIZE, sp
  347. br.ret.sptk.many b0
  348. ;;
  349. .Lld_int:
  350. .body
  351. .copy_state 1
  352. ld8 r8 = [r16]
  353. .restore sp
  354. add sp = FRAME_SIZE, sp
  355. br.ret.sptk.many b0
  356. ;;
  357. .Lld_float:
  358. .body
  359. .copy_state 1
  360. ldfs f8 = [r16]
  361. .restore sp
  362. add sp = FRAME_SIZE, sp
  363. br.ret.sptk.many b0
  364. ;;
  365. .Lld_double:
  366. .body
  367. .copy_state 1
  368. ldfd f8 = [r16]
  369. .restore sp
  370. add sp = FRAME_SIZE, sp
  371. br.ret.sptk.many b0
  372. ;;
  373. .Lld_ldouble:
  374. .body
  375. .copy_state 1
  376. ldfe f8 = [r16]
  377. .restore sp
  378. add sp = FRAME_SIZE, sp
  379. br.ret.sptk.many b0
  380. ;;
  381. .Lld_small_struct:
  382. .body
  383. .copy_state 1
  384. add r17 = 8, r16
  385. cmp.lt p6, p0 = 8, r8
  386. cmp.lt p7, p0 = 16, r8
  387. cmp.lt p8, p0 = 24, r8
  388. ;;
  389. ld8 r8 = [r16], 16
  390. (p6) ld8 r9 = [r17], 16
  391. ;;
  392. (p7) ld8 r10 = [r16]
  393. (p8) ld8 r11 = [r17]
  394. .restore sp
  395. add sp = FRAME_SIZE, sp
  396. br.ret.sptk.many b0
  397. ;;
  398. .Lld_hfa_float:
  399. .body
  400. .copy_state 1
  401. add r17 = 4, r16
  402. cmp.lt p6, p0 = 4, r8
  403. ;;
  404. ldfs f8 = [r16], 8
  405. (p6) ldfs f9 = [r17], 8
  406. cmp.lt p7, p0 = 8, r8
  407. cmp.lt p8, p0 = 12, r8
  408. ;;
  409. (p7) ldfs f10 = [r16], 8
  410. (p8) ldfs f11 = [r17], 8
  411. cmp.lt p9, p0 = 16, r8
  412. cmp.lt p10, p0 = 20, r8
  413. ;;
  414. (p9) ldfs f12 = [r16], 8
  415. (p10) ldfs f13 = [r17], 8
  416. cmp.lt p6, p0 = 24, r8
  417. cmp.lt p7, p0 = 28, r8
  418. ;;
  419. (p6) ldfs f14 = [r16]
  420. (p7) ldfs f15 = [r17]
  421. .restore sp
  422. add sp = FRAME_SIZE, sp
  423. br.ret.sptk.many b0
  424. ;;
  425. .Lld_hfa_double:
  426. .body
  427. .copy_state 1
  428. add r17 = 8, r16
  429. cmp.lt p6, p0 = 8, r8
  430. ;;
  431. ldfd f8 = [r16], 16
  432. (p6) ldfd f9 = [r17], 16
  433. cmp.lt p7, p0 = 16, r8
  434. cmp.lt p8, p0 = 24, r8
  435. ;;
  436. (p7) ldfd f10 = [r16], 16
  437. (p8) ldfd f11 = [r17], 16
  438. cmp.lt p9, p0 = 32, r8
  439. cmp.lt p10, p0 = 40, r8
  440. ;;
  441. (p9) ldfd f12 = [r16], 16
  442. (p10) ldfd f13 = [r17], 16
  443. cmp.lt p6, p0 = 48, r8
  444. cmp.lt p7, p0 = 56, r8
  445. ;;
  446. (p6) ldfd f14 = [r16]
  447. (p7) ldfd f15 = [r17]
  448. .restore sp
  449. add sp = FRAME_SIZE, sp
  450. br.ret.sptk.many b0
  451. ;;
  452. .Lld_hfa_ldouble:
  453. .body
  454. .copy_state 1
  455. add r17 = 16, r16
  456. cmp.lt p6, p0 = 16, r8
  457. ;;
  458. ldfe f8 = [r16], 32
  459. (p6) ldfe f9 = [r17], 32
  460. cmp.lt p7, p0 = 32, r8
  461. cmp.lt p8, p0 = 48, r8
  462. ;;
  463. (p7) ldfe f10 = [r16], 32
  464. (p8) ldfe f11 = [r17], 32
  465. cmp.lt p9, p0 = 64, r8
  466. cmp.lt p10, p0 = 80, r8
  467. ;;
  468. (p9) ldfe f12 = [r16], 32
  469. (p10) ldfe f13 = [r17], 32
  470. cmp.lt p6, p0 = 96, r8
  471. cmp.lt p7, p0 = 112, r8
  472. ;;
  473. (p6) ldfe f14 = [r16]
  474. (p7) ldfe f15 = [r17]
  475. .restore sp
  476. add sp = FRAME_SIZE, sp
  477. br.ret.sptk.many b0
  478. ;;
  479. .endp ffi_closure_unix
  480. .section .rodata
  481. .align 8
  482. .Lst_table:
  483. data8 @pcrel(.Lst_void) // FFI_TYPE_VOID
  484. data8 @pcrel(.Lst_sint32) // FFI_TYPE_INT
  485. data8 @pcrel(.Lst_float) // FFI_TYPE_FLOAT
  486. data8 @pcrel(.Lst_double) // FFI_TYPE_DOUBLE
  487. data8 @pcrel(.Lst_ldouble) // FFI_TYPE_LONGDOUBLE
  488. data8 @pcrel(.Lst_uint8) // FFI_TYPE_UINT8
  489. data8 @pcrel(.Lst_sint8) // FFI_TYPE_SINT8
  490. data8 @pcrel(.Lst_uint16) // FFI_TYPE_UINT16
  491. data8 @pcrel(.Lst_sint16) // FFI_TYPE_SINT16
  492. data8 @pcrel(.Lst_uint32) // FFI_TYPE_UINT32
  493. data8 @pcrel(.Lst_sint32) // FFI_TYPE_SINT32
  494. data8 @pcrel(.Lst_int64) // FFI_TYPE_UINT64
  495. data8 @pcrel(.Lst_int64) // FFI_TYPE_SINT64
  496. data8 @pcrel(.Lst_void) // FFI_TYPE_STRUCT
  497. data8 @pcrel(.Lst_int64) // FFI_TYPE_POINTER
  498. data8 @pcrel(.Lst_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
  499. data8 @pcrel(.Lst_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
  500. data8 @pcrel(.Lst_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
  501. data8 @pcrel(.Lst_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
  502. .Lld_table:
  503. data8 @pcrel(.Lld_void) // FFI_TYPE_VOID
  504. data8 @pcrel(.Lld_int) // FFI_TYPE_INT
  505. data8 @pcrel(.Lld_float) // FFI_TYPE_FLOAT
  506. data8 @pcrel(.Lld_double) // FFI_TYPE_DOUBLE
  507. data8 @pcrel(.Lld_ldouble) // FFI_TYPE_LONGDOUBLE
  508. data8 @pcrel(.Lld_int) // FFI_TYPE_UINT8
  509. data8 @pcrel(.Lld_int) // FFI_TYPE_SINT8
  510. data8 @pcrel(.Lld_int) // FFI_TYPE_UINT16
  511. data8 @pcrel(.Lld_int) // FFI_TYPE_SINT16
  512. data8 @pcrel(.Lld_int) // FFI_TYPE_UINT32
  513. data8 @pcrel(.Lld_int) // FFI_TYPE_SINT32
  514. data8 @pcrel(.Lld_int) // FFI_TYPE_UINT64
  515. data8 @pcrel(.Lld_int) // FFI_TYPE_SINT64
  516. data8 @pcrel(.Lld_void) // FFI_TYPE_STRUCT
  517. data8 @pcrel(.Lld_int) // FFI_TYPE_POINTER
  518. data8 @pcrel(.Lld_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
  519. data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
  520. data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
  521. data8 @pcrel(.Lld_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
  522. #if defined __ELF__ && defined __linux__
  523. .section .note.GNU-stack,"",@progbits
  524. #endif