1/* ----------------------------------------------------------------------- 2 hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc. 3 (c) 2008 Red Hat, Inc. 4 (c) 2016 John David Anglin 5 based on src/pa/linux.S 6 7 HP-UX PA Foreign Function Interface 8 9 Permission is hereby granted, free of charge, to any person obtaining 10 a copy of this software and associated documentation files (the 11 ``Software''), to deal in the Software without restriction, including 12 without limitation the rights to use, copy, modify, merge, publish, 13 distribute, sublicense, and/or sell copies of the Software, and to 14 permit persons to whom the Software is furnished to do so, subject to 15 the following conditions: 16 17 The above copyright notice and this permission notice shall be included 18 in all copies or substantial portions of the Software. 19 20 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 OTHER DEALINGS IN THE SOFTWARE. 27 ----------------------------------------------------------------------- */ 28 29#define LIBFFI_ASM 30#include <fficonfig.h> 31#include <ffi.h> 32 33 .LEVEL 1.1 34 .SPACE $PRIVATE$ 35 .IMPORT $global$,DATA 36 .IMPORT $$dyncall,MILLICODE 37 .SUBSPA $DATA$ 38 .align 4 39 40 /* void ffi_call_pa32(void (*)(char *, extended_cif *), 41 extended_cif *ecif, 42 unsigned bytes, 43 unsigned flags, 44 unsigned *rvalue, 45 void (*fn)(void), 46 ffi_go_closure *closure); 47 */ 48 49 .export ffi_call_pa32,ENTRY,PRIV_LEV=3 50 .import ffi_prep_args_pa32,CODE 51 52 .SPACE $TEXT$ 53 .SUBSPA $CODE$ 54 .align 4 55 56L$FB1 57ffi_call_pa32 58 .proc 59 .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4 60 .entry 61 stw %rp, -20(%sp) 62 copy %r3, %r1 63L$CFI11 64 copy %sp, %r3 65L$CFI12 66 67 /* Setup the stack for calling prep_args... 68 We want the stack to look like this: 69 70 [ Previous stack ] <- %r3 71 72 [ 64-bytes register save area ] <- %r4 73 74 [ Stack space for actual call, passed as ] <- %arg0 75 [ arg0 to ffi_prep_args_pa32 ] 76 77 [ Stack for calling prep_args ] <- %sp 78 */ 79 80 stwm %r1, 64(%sp) 81 stw %r4, 12(%r3) 82L$CFI13 83 copy %sp, %r4 84 85 addl %arg2, %r4, %arg0 ; arg stack 86 stw %arg3, -48(%r3) ; save flags we need it later 87 88 /* Call prep_args: 89 %arg0(stack) -- set up above 90 %arg1(ecif) -- same as incoming param 91 %arg2(bytes) -- same as incoming param */ 92 bl ffi_prep_args_pa32,%r2 93 ldo 64(%arg0), %sp 94 ldo -64(%sp), %sp 95 96 /* now %sp should point where %arg0 was pointing. */ 97 98 /* Load the arguments that should be passed in registers 99 The fp args are loaded by the prep_args function. */ 100 ldw -36(%sp), %arg0 101 ldw -40(%sp), %arg1 102 ldw -44(%sp), %arg2 103 ldw -48(%sp), %arg3 104 105 /* in case the function is going to return a structure 106 we need to give it a place to put the result. */ 107 ldw -52(%r3), %ret0 ; %ret0 <- rvalue 108 ldw -56(%r3), %r22 ; %r22 <- function to call 109 ldw -60(%r3), %ret1 ; %ret1 <- closure 110 bl $$dyncall, %r31 ; Call the user function 111 copy %r31, %rp 112 113 /* Prepare to store the result; we need to recover flags and rvalue. */ 114 ldw -48(%r3), %r21 ; r21 <- flags 115 ldw -52(%r3), %r20 ; r20 <- rvalue 116 117 /* Store the result according to the return type. The most 118 likely types should come first. */ 119 120L$checkint 121 comib,<>,n FFI_TYPE_INT, %r21, L$checkint8 122 b L$done 123 stw %ret0, 0(%r20) 124 125L$checkint8 126 comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16 127 b L$done 128 stb %ret0, 0(%r20) 129 130L$checkint16 131 comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl 132 b L$done 133 sth %ret0, 0(%r20) 134 135L$checkdbl 136 comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat 137 b L$done 138 fstd %fr4,0(%r20) 139 140L$checkfloat 141 comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll 142 b L$done 143 fstw %fr4L,0(%r20) 144 145L$checkll 146 comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2 147 stw %ret0, 0(%r20) 148 b L$done 149 stw %ret1, 4(%r20) 150 151L$checksmst2 152 comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3 153 /* 2-byte structs are returned in ret0 as ????xxyy. */ 154 extru %ret0, 23, 8, %r22 155 stbs,ma %r22, 1(%r20) 156 b L$done 157 stb %ret0, 0(%r20) 158 159L$checksmst3 160 comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4 161 /* 3-byte structs are returned in ret0 as ??xxyyzz. */ 162 extru %ret0, 15, 8, %r22 163 stbs,ma %r22, 1(%r20) 164 extru %ret0, 23, 8, %r22 165 stbs,ma %r22, 1(%r20) 166 b L$done 167 stb %ret0, 0(%r20) 168 169L$checksmst4 170 comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5 171 /* 4-byte structs are returned in ret0 as wwxxyyzz. */ 172 extru %ret0, 7, 8, %r22 173 stbs,ma %r22, 1(%r20) 174 extru %ret0, 15, 8, %r22 175 stbs,ma %r22, 1(%r20) 176 extru %ret0, 23, 8, %r22 177 stbs,ma %r22, 1(%r20) 178 b L$done 179 stb %ret0, 0(%r20) 180 181L$checksmst5 182 comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6 183 /* 5 byte values are returned right justified: 184 ret0 ret1 185 5: ??????aa bbccddee */ 186 stbs,ma %ret0, 1(%r20) 187 extru %ret1, 7, 8, %r22 188 stbs,ma %r22, 1(%r20) 189 extru %ret1, 15, 8, %r22 190 stbs,ma %r22, 1(%r20) 191 extru %ret1, 23, 8, %r22 192 stbs,ma %r22, 1(%r20) 193 b L$done 194 stb %ret1, 0(%r20) 195 196L$checksmst6 197 comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7 198 /* 6 byte values are returned right justified: 199 ret0 ret1 200 6: ????aabb ccddeeff */ 201 extru %ret0, 23, 8, %r22 202 stbs,ma %r22, 1(%r20) 203 stbs,ma %ret0, 1(%r20) 204 extru %ret1, 7, 8, %r22 205 stbs,ma %r22, 1(%r20) 206 extru %ret1, 15, 8, %r22 207 stbs,ma %r22, 1(%r20) 208 extru %ret1, 23, 8, %r22 209 stbs,ma %r22, 1(%r20) 210 b L$done 211 stb %ret1, 0(%r20) 212 213L$checksmst7 214 comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8 215 /* 7 byte values are returned right justified: 216 ret0 ret1 217 7: ??aabbcc ddeeffgg */ 218 extru %ret0, 15, 8, %r22 219 stbs,ma %r22, 1(%r20) 220 extru %ret0, 23, 8, %r22 221 stbs,ma %r22, 1(%r20) 222 stbs,ma %ret0, 1(%r20) 223 extru %ret1, 7, 8, %r22 224 stbs,ma %r22, 1(%r20) 225 extru %ret1, 15, 8, %r22 226 stbs,ma %r22, 1(%r20) 227 extru %ret1, 23, 8, %r22 228 stbs,ma %r22, 1(%r20) 229 b L$done 230 stb %ret1, 0(%r20) 231 232L$checksmst8 233 comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done 234 /* 8 byte values are returned right justified: 235 ret0 ret1 236 8: aabbccdd eeffgghh */ 237 extru %ret0, 7, 8, %r22 238 stbs,ma %r22, 1(%r20) 239 extru %ret0, 15, 8, %r22 240 stbs,ma %r22, 1(%r20) 241 extru %ret0, 23, 8, %r22 242 stbs,ma %r22, 1(%r20) 243 stbs,ma %ret0, 1(%r20) 244 extru %ret1, 7, 8, %r22 245 stbs,ma %r22, 1(%r20) 246 extru %ret1, 15, 8, %r22 247 stbs,ma %r22, 1(%r20) 248 extru %ret1, 23, 8, %r22 249 stbs,ma %r22, 1(%r20) 250 stb %ret1, 0(%r20) 251 252L$done 253 /* all done, return */ 254 copy %r4, %sp ; pop arg stack 255 ldw 12(%r3), %r4 256 ldwm -64(%sp), %r3 ; .. and pop stack 257 ldw -20(%sp), %rp 258 bv %r0(%rp) 259 nop 260 .exit 261 .procend 262L$FE1 263 264 /* void ffi_closure_pa32(void); 265 Called with closure argument in %r21 */ 266 267 .SPACE $TEXT$ 268 .SUBSPA $CODE$ 269 .export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR 270 .import ffi_closure_inner_pa32,CODE 271 .align 4 272L$FB2 273ffi_closure_pa32 274 .proc 275 .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3 276 .entry 277 278 stw %rp, -20(%sp) 279 copy %r3, %r1 280L$CFI21 281 copy %sp, %r3 282L$CFI22 283 stwm %r1, 64(%sp) 284 285 /* Put arguments onto the stack and call ffi_closure_inner. */ 286 stw %arg0, -36(%r3) 287 stw %arg1, -40(%r3) 288 stw %arg2, -44(%r3) 289 stw %arg3, -48(%r3) 290 291 /* Closure type 0. */ 292 copy %r21, %arg0 293 copy %r0, %arg2 294 bl ffi_closure_inner_pa32, %r2 295 copy %r3, %arg1 296 ldwm -64(%sp), %r3 297 ldw -20(%sp), %rp 298 ldw -36(%sp), %ret0 299 bv %r0(%rp) 300 ldw -40(%sp), %ret1 301 .exit 302 .procend 303L$FE2: 304 305 /* void ffi_go_closure_pa32(void); 306 Called with closure argument in %ret1 */ 307 308 .SPACE $TEXT$ 309 .SUBSPA $CODE$ 310 .export ffi_go_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR 311 .import ffi_closure_inner_pa32,CODE 312 .align 4 313L$FB3 314ffi_go_closure_pa32 315 .proc 316 .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3 317 .entry 318 319 stw %rp, -20(%sp) 320 copy %r3, %r1 321L$CFI31 322 copy %sp, %r3 323L$CFI32 324 stwm %r1, 64(%sp) 325 326 /* Put arguments onto the stack and call ffi_closure_inner. */ 327 stw %arg0, -36(%r3) 328 stw %arg1, -40(%r3) 329 stw %arg2, -44(%r3) 330 stw %arg3, -48(%r3) 331 332 /* Closure type 1. */ 333 copy %ret1, %arg0 334 ldi 1, %arg2 335 bl ffi_closure_inner_pa32, %r2 336 copy %r3, %arg1 337 ldwm -64(%sp), %r3 338 ldw -20(%sp), %rp 339 ldw -36(%sp), %ret0 340 bv %r0(%rp) 341 ldw -40(%sp), %ret1 342 .exit 343 .procend 344L$FE3: 345 346 .SPACE $PRIVATE$ 347 .SUBSPA $DATA$ 348 349 .align 4 350 .EXPORT _GLOBAL__F_ffi_call_pa32,DATA 351_GLOBAL__F_ffi_call_pa32 352L$frame1: 353 .word L$ECIE1-L$SCIE1 ;# Length of Common Information Entry 354L$SCIE1: 355 .word 0x0 ;# CIE Identifier Tag 356 .byte 0x1 ;# CIE Version 357 .ascii "\0" ;# CIE Augmentation 358 .uleb128 0x1 ;# CIE Code Alignment Factor 359 .sleb128 4 ;# CIE Data Alignment Factor 360 .byte 0x2 ;# CIE RA Column 361 .byte 0xc ;# DW_CFA_def_cfa 362 .uleb128 0x1e 363 .uleb128 0x0 364 .align 4 365L$ECIE1: 366L$SFDE1: 367 .word L$EFDE1-L$ASFDE1 ;# FDE Length 368L$ASFDE1: 369 .word L$ASFDE1-L$frame1 ;# FDE CIE offset 370 .word L$FB1 ;# FDE initial location 371 .word L$FE1-L$FB1 ;# FDE address range 372 373 .byte 0x4 ;# DW_CFA_advance_loc4 374 .word L$CFI11-L$FB1 375 .byte 0x83 ;# DW_CFA_offset, column 0x3 376 .uleb128 0x0 377 .byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20] 378 .uleb128 0x2 379 .sleb128 -5 380 381 .byte 0x4 ;# DW_CFA_advance_loc4 382 .word L$CFI12-L$CFI11 383 .byte 0xd ;# DW_CFA_def_cfa_register = r3 384 .uleb128 0x3 385 386 .byte 0x4 ;# DW_CFA_advance_loc4 387 .word L$CFI13-L$CFI12 388 .byte 0x84 ;# DW_CFA_offset, column 0x4 389 .uleb128 0x3 390 391 .align 4 392L$EFDE1: 393 394L$SFDE2: 395 .word L$EFDE2-L$ASFDE2 ;# FDE Length 396L$ASFDE2: 397 .word L$ASFDE2-L$frame1 ;# FDE CIE offset 398 .word L$FB2 ;# FDE initial location 399 .word L$FE2-L$FB2 ;# FDE address range 400 .byte 0x4 ;# DW_CFA_advance_loc4 401 .word L$CFI21-L$FB2 402 .byte 0x83 ;# DW_CFA_offset, column 0x3 403 .uleb128 0x0 404 .byte 0x11 ;# DW_CFA_offset_extended_sf 405 .uleb128 0x2 406 .sleb128 -5 407 408 .byte 0x4 ;# DW_CFA_advance_loc4 409 .word L$CFI22-L$CFI21 410 .byte 0xd ;# DW_CFA_def_cfa_register = r3 411 .uleb128 0x3 412 413 .align 4 414L$EFDE2: 415 416L$SFDE3: 417 .word L$EFDE3-L$ASFDE3 ;# FDE Length 418L$ASFDE3: 419 .word L$ASFDE3-L$frame1 ;# FDE CIE offset 420 .word L$FB3 ;# FDE initial location 421 .word L$FE3-L$FB3 ;# FDE address range 422 .byte 0x4 ;# DW_CFA_advance_loc4 423 .word L$CFI31-L$FB3 424 .byte 0x83 ;# DW_CFA_offset, column 0x3 425 .uleb128 0x0 426 .byte 0x11 ;# DW_CFA_offset_extended_sf 427 .uleb128 0x2 428 .sleb128 -5 429 430 .byte 0x4 ;# DW_CFA_advance_loc4 431 .word L$CFI32-L$CFI31 432 .byte 0xd ;# DW_CFA_def_cfa_register = r3 433 .uleb128 0x3 434 435 .align 4 436L$EFDE3: 437