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