2006-04-05 23:26:34 +02:00
|
|
|
/* -----------------------------------------------------------------------
|
|
|
|
hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc.
|
2009-06-04 17:43:03 +02:00
|
|
|
(c) 2008 Red Hat, Inc.
|
2016-09-04 19:39:05 +02:00
|
|
|
(c) 2016 John David Anglin
|
2006-04-05 23:26:34 +02:00
|
|
|
based on src/pa/linux.S
|
|
|
|
|
|
|
|
HP-UX PA Foreign Function Interface
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
a copy of this software and associated documentation files (the
|
|
|
|
``Software''), to deal in the Software without restriction, including
|
|
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
|
|
in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
|
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
|
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
|
|
OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
----------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
#define LIBFFI_ASM
|
|
|
|
#include <fficonfig.h>
|
|
|
|
#include <ffi.h>
|
|
|
|
|
|
|
|
.LEVEL 1.1
|
|
|
|
.SPACE $PRIVATE$
|
|
|
|
.IMPORT $global$,DATA
|
|
|
|
.IMPORT $$dyncall,MILLICODE
|
|
|
|
.SUBSPA $DATA$
|
|
|
|
.align 4
|
|
|
|
|
|
|
|
/* void ffi_call_pa32(void (*)(char *, extended_cif *),
|
|
|
|
extended_cif *ecif,
|
|
|
|
unsigned bytes,
|
|
|
|
unsigned flags,
|
|
|
|
unsigned *rvalue,
|
2016-09-04 19:39:05 +02:00
|
|
|
void (*fn)(void),
|
|
|
|
ffi_go_closure *closure);
|
2006-04-05 23:26:34 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
.export ffi_call_pa32,ENTRY,PRIV_LEV=3
|
|
|
|
.import ffi_prep_args_pa32,CODE
|
|
|
|
|
|
|
|
.SPACE $TEXT$
|
|
|
|
.SUBSPA $CODE$
|
|
|
|
.align 4
|
|
|
|
|
|
|
|
L$FB1
|
|
|
|
ffi_call_pa32
|
|
|
|
.proc
|
|
|
|
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
|
|
|
|
.entry
|
|
|
|
stw %rp, -20(%sp)
|
|
|
|
copy %r3, %r1
|
|
|
|
L$CFI11
|
|
|
|
copy %sp, %r3
|
|
|
|
L$CFI12
|
|
|
|
|
|
|
|
/* Setup the stack for calling prep_args...
|
|
|
|
We want the stack to look like this:
|
|
|
|
|
|
|
|
[ Previous stack ] <- %r3
|
|
|
|
|
|
|
|
[ 64-bytes register save area ] <- %r4
|
|
|
|
|
|
|
|
[ Stack space for actual call, passed as ] <- %arg0
|
|
|
|
[ arg0 to ffi_prep_args_pa32 ]
|
|
|
|
|
|
|
|
[ Stack for calling prep_args ] <- %sp
|
|
|
|
*/
|
|
|
|
|
|
|
|
stwm %r1, 64(%sp)
|
|
|
|
stw %r4, 12(%r3)
|
|
|
|
L$CFI13
|
|
|
|
copy %sp, %r4
|
|
|
|
|
|
|
|
addl %arg2, %r4, %arg0 ; arg stack
|
|
|
|
stw %arg3, -48(%r3) ; save flags we need it later
|
|
|
|
|
|
|
|
/* Call prep_args:
|
|
|
|
%arg0(stack) -- set up above
|
|
|
|
%arg1(ecif) -- same as incoming param
|
|
|
|
%arg2(bytes) -- same as incoming param */
|
|
|
|
bl ffi_prep_args_pa32,%r2
|
|
|
|
ldo 64(%arg0), %sp
|
|
|
|
ldo -64(%sp), %sp
|
|
|
|
|
|
|
|
/* now %sp should point where %arg0 was pointing. */
|
|
|
|
|
|
|
|
/* Load the arguments that should be passed in registers
|
|
|
|
The fp args are loaded by the prep_args function. */
|
|
|
|
ldw -36(%sp), %arg0
|
|
|
|
ldw -40(%sp), %arg1
|
|
|
|
ldw -44(%sp), %arg2
|
|
|
|
ldw -48(%sp), %arg3
|
|
|
|
|
|
|
|
/* in case the function is going to return a structure
|
|
|
|
we need to give it a place to put the result. */
|
|
|
|
ldw -52(%r3), %ret0 ; %ret0 <- rvalue
|
|
|
|
ldw -56(%r3), %r22 ; %r22 <- function to call
|
2016-09-04 19:39:05 +02:00
|
|
|
ldw -60(%r3), %ret1 ; %ret1 <- closure
|
2006-04-05 23:26:34 +02:00
|
|
|
bl $$dyncall, %r31 ; Call the user function
|
|
|
|
copy %r31, %rp
|
|
|
|
|
|
|
|
/* Prepare to store the result; we need to recover flags and rvalue. */
|
|
|
|
ldw -48(%r3), %r21 ; r21 <- flags
|
|
|
|
ldw -52(%r3), %r20 ; r20 <- rvalue
|
|
|
|
|
|
|
|
/* Store the result according to the return type. The most
|
|
|
|
likely types should come first. */
|
|
|
|
|
|
|
|
L$checkint
|
|
|
|
comib,<>,n FFI_TYPE_INT, %r21, L$checkint8
|
|
|
|
b L$done
|
|
|
|
stw %ret0, 0(%r20)
|
|
|
|
|
|
|
|
L$checkint8
|
|
|
|
comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16
|
|
|
|
b L$done
|
|
|
|
stb %ret0, 0(%r20)
|
|
|
|
|
|
|
|
L$checkint16
|
|
|
|
comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl
|
|
|
|
b L$done
|
|
|
|
sth %ret0, 0(%r20)
|
|
|
|
|
|
|
|
L$checkdbl
|
|
|
|
comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat
|
|
|
|
b L$done
|
|
|
|
fstd %fr4,0(%r20)
|
|
|
|
|
|
|
|
L$checkfloat
|
|
|
|
comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll
|
|
|
|
b L$done
|
|
|
|
fstw %fr4L,0(%r20)
|
|
|
|
|
|
|
|
L$checkll
|
|
|
|
comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2
|
|
|
|
stw %ret0, 0(%r20)
|
|
|
|
b L$done
|
|
|
|
stw %ret1, 4(%r20)
|
|
|
|
|
|
|
|
L$checksmst2
|
|
|
|
comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3
|
|
|
|
/* 2-byte structs are returned in ret0 as ????xxyy. */
|
|
|
|
extru %ret0, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
b L$done
|
|
|
|
stb %ret0, 0(%r20)
|
|
|
|
|
|
|
|
L$checksmst3
|
|
|
|
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4
|
|
|
|
/* 3-byte structs are returned in ret0 as ??xxyyzz. */
|
|
|
|
extru %ret0, 15, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret0, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
b L$done
|
|
|
|
stb %ret0, 0(%r20)
|
|
|
|
|
|
|
|
L$checksmst4
|
|
|
|
comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5
|
|
|
|
/* 4-byte structs are returned in ret0 as wwxxyyzz. */
|
|
|
|
extru %ret0, 7, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret0, 15, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret0, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
b L$done
|
|
|
|
stb %ret0, 0(%r20)
|
|
|
|
|
|
|
|
L$checksmst5
|
|
|
|
comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6
|
|
|
|
/* 5 byte values are returned right justified:
|
|
|
|
ret0 ret1
|
|
|
|
5: ??????aa bbccddee */
|
|
|
|
stbs,ma %ret0, 1(%r20)
|
|
|
|
extru %ret1, 7, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret1, 15, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret1, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
b L$done
|
|
|
|
stb %ret1, 0(%r20)
|
|
|
|
|
|
|
|
L$checksmst6
|
|
|
|
comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7
|
|
|
|
/* 6 byte values are returned right justified:
|
|
|
|
ret0 ret1
|
|
|
|
6: ????aabb ccddeeff */
|
|
|
|
extru %ret0, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
stbs,ma %ret0, 1(%r20)
|
|
|
|
extru %ret1, 7, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret1, 15, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret1, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
b L$done
|
|
|
|
stb %ret1, 0(%r20)
|
|
|
|
|
|
|
|
L$checksmst7
|
|
|
|
comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8
|
|
|
|
/* 7 byte values are returned right justified:
|
|
|
|
ret0 ret1
|
|
|
|
7: ??aabbcc ddeeffgg */
|
|
|
|
extru %ret0, 15, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret0, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
stbs,ma %ret0, 1(%r20)
|
|
|
|
extru %ret1, 7, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret1, 15, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret1, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
b L$done
|
|
|
|
stb %ret1, 0(%r20)
|
|
|
|
|
|
|
|
L$checksmst8
|
|
|
|
comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done
|
|
|
|
/* 8 byte values are returned right justified:
|
|
|
|
ret0 ret1
|
|
|
|
8: aabbccdd eeffgghh */
|
|
|
|
extru %ret0, 7, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret0, 15, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret0, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
stbs,ma %ret0, 1(%r20)
|
|
|
|
extru %ret1, 7, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret1, 15, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
extru %ret1, 23, 8, %r22
|
|
|
|
stbs,ma %r22, 1(%r20)
|
|
|
|
stb %ret1, 0(%r20)
|
|
|
|
|
|
|
|
L$done
|
|
|
|
/* all done, return */
|
|
|
|
copy %r4, %sp ; pop arg stack
|
|
|
|
ldw 12(%r3), %r4
|
|
|
|
ldwm -64(%sp), %r3 ; .. and pop stack
|
|
|
|
ldw -20(%sp), %rp
|
|
|
|
bv %r0(%rp)
|
|
|
|
nop
|
|
|
|
.exit
|
|
|
|
.procend
|
|
|
|
L$FE1
|
|
|
|
|
|
|
|
/* void ffi_closure_pa32(void);
|
|
|
|
Called with closure argument in %r21 */
|
|
|
|
|
|
|
|
.SPACE $TEXT$
|
|
|
|
.SUBSPA $CODE$
|
|
|
|
.export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
|
|
|
|
.import ffi_closure_inner_pa32,CODE
|
|
|
|
.align 4
|
|
|
|
L$FB2
|
|
|
|
ffi_closure_pa32
|
|
|
|
.proc
|
|
|
|
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
|
|
|
.entry
|
|
|
|
|
|
|
|
stw %rp, -20(%sp)
|
|
|
|
copy %r3, %r1
|
|
|
|
L$CFI21
|
|
|
|
copy %sp, %r3
|
|
|
|
L$CFI22
|
|
|
|
stwm %r1, 64(%sp)
|
|
|
|
|
|
|
|
/* Put arguments onto the stack and call ffi_closure_inner. */
|
|
|
|
stw %arg0, -36(%r3)
|
|
|
|
stw %arg1, -40(%r3)
|
|
|
|
stw %arg2, -44(%r3)
|
|
|
|
stw %arg3, -48(%r3)
|
|
|
|
|
2016-09-04 19:39:05 +02:00
|
|
|
/* Closure type 0. */
|
2006-04-05 23:26:34 +02:00
|
|
|
copy %r21, %arg0
|
2016-09-04 19:39:05 +02:00
|
|
|
copy %r0, %arg2
|
2006-04-05 23:26:34 +02:00
|
|
|
bl ffi_closure_inner_pa32, %r2
|
|
|
|
copy %r3, %arg1
|
|
|
|
ldwm -64(%sp), %r3
|
|
|
|
ldw -20(%sp), %rp
|
|
|
|
ldw -36(%sp), %ret0
|
|
|
|
bv %r0(%rp)
|
|
|
|
ldw -40(%sp), %ret1
|
|
|
|
.exit
|
|
|
|
.procend
|
|
|
|
L$FE2:
|
|
|
|
|
2016-09-04 19:39:05 +02:00
|
|
|
/* void ffi_go_closure_pa32(void);
|
|
|
|
Called with closure argument in %ret1 */
|
|
|
|
|
|
|
|
.SPACE $TEXT$
|
|
|
|
.SUBSPA $CODE$
|
|
|
|
.export ffi_go_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
|
|
|
|
.import ffi_closure_inner_pa32,CODE
|
|
|
|
.align 4
|
|
|
|
L$FB3
|
|
|
|
ffi_go_closure_pa32
|
|
|
|
.proc
|
|
|
|
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
|
|
|
|
.entry
|
|
|
|
|
|
|
|
stw %rp, -20(%sp)
|
|
|
|
copy %r3, %r1
|
|
|
|
L$CFI31
|
|
|
|
copy %sp, %r3
|
|
|
|
L$CFI32
|
|
|
|
stwm %r1, 64(%sp)
|
|
|
|
|
|
|
|
/* Put arguments onto the stack and call ffi_closure_inner. */
|
|
|
|
stw %arg0, -36(%r3)
|
|
|
|
stw %arg1, -40(%r3)
|
|
|
|
stw %arg2, -44(%r3)
|
|
|
|
stw %arg3, -48(%r3)
|
|
|
|
|
|
|
|
/* Closure type 1. */
|
|
|
|
copy %ret1, %arg0
|
|
|
|
ldi 1, %arg2
|
|
|
|
bl ffi_closure_inner_pa32, %r2
|
|
|
|
copy %r3, %arg1
|
|
|
|
ldwm -64(%sp), %r3
|
|
|
|
ldw -20(%sp), %rp
|
|
|
|
ldw -36(%sp), %ret0
|
|
|
|
bv %r0(%rp)
|
|
|
|
ldw -40(%sp), %ret1
|
|
|
|
.exit
|
|
|
|
.procend
|
|
|
|
L$FE3:
|
|
|
|
|
2006-04-05 23:26:34 +02:00
|
|
|
.SPACE $PRIVATE$
|
|
|
|
.SUBSPA $DATA$
|
|
|
|
|
|
|
|
.align 4
|
|
|
|
.EXPORT _GLOBAL__F_ffi_call_pa32,DATA
|
|
|
|
_GLOBAL__F_ffi_call_pa32
|
|
|
|
L$frame1:
|
|
|
|
.word L$ECIE1-L$SCIE1 ;# Length of Common Information Entry
|
|
|
|
L$SCIE1:
|
|
|
|
.word 0x0 ;# CIE Identifier Tag
|
|
|
|
.byte 0x1 ;# CIE Version
|
|
|
|
.ascii "\0" ;# CIE Augmentation
|
|
|
|
.uleb128 0x1 ;# CIE Code Alignment Factor
|
|
|
|
.sleb128 4 ;# CIE Data Alignment Factor
|
|
|
|
.byte 0x2 ;# CIE RA Column
|
|
|
|
.byte 0xc ;# DW_CFA_def_cfa
|
|
|
|
.uleb128 0x1e
|
|
|
|
.uleb128 0x0
|
|
|
|
.align 4
|
|
|
|
L$ECIE1:
|
|
|
|
L$SFDE1:
|
|
|
|
.word L$EFDE1-L$ASFDE1 ;# FDE Length
|
|
|
|
L$ASFDE1:
|
|
|
|
.word L$ASFDE1-L$frame1 ;# FDE CIE offset
|
|
|
|
.word L$FB1 ;# FDE initial location
|
|
|
|
.word L$FE1-L$FB1 ;# FDE address range
|
|
|
|
|
|
|
|
.byte 0x4 ;# DW_CFA_advance_loc4
|
|
|
|
.word L$CFI11-L$FB1
|
|
|
|
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
|
|
|
.uleb128 0x0
|
|
|
|
.byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
|
|
|
|
.uleb128 0x2
|
|
|
|
.sleb128 -5
|
|
|
|
|
|
|
|
.byte 0x4 ;# DW_CFA_advance_loc4
|
|
|
|
.word L$CFI12-L$CFI11
|
|
|
|
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
|
|
|
.uleb128 0x3
|
|
|
|
|
|
|
|
.byte 0x4 ;# DW_CFA_advance_loc4
|
|
|
|
.word L$CFI13-L$CFI12
|
|
|
|
.byte 0x84 ;# DW_CFA_offset, column 0x4
|
|
|
|
.uleb128 0x3
|
|
|
|
|
|
|
|
.align 4
|
|
|
|
L$EFDE1:
|
|
|
|
|
|
|
|
L$SFDE2:
|
|
|
|
.word L$EFDE2-L$ASFDE2 ;# FDE Length
|
|
|
|
L$ASFDE2:
|
|
|
|
.word L$ASFDE2-L$frame1 ;# FDE CIE offset
|
|
|
|
.word L$FB2 ;# FDE initial location
|
|
|
|
.word L$FE2-L$FB2 ;# FDE address range
|
|
|
|
.byte 0x4 ;# DW_CFA_advance_loc4
|
|
|
|
.word L$CFI21-L$FB2
|
|
|
|
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
|
|
|
.uleb128 0x0
|
|
|
|
.byte 0x11 ;# DW_CFA_offset_extended_sf
|
|
|
|
.uleb128 0x2
|
|
|
|
.sleb128 -5
|
|
|
|
|
|
|
|
.byte 0x4 ;# DW_CFA_advance_loc4
|
2006-04-13 00:56:19 +02:00
|
|
|
.word L$CFI22-L$CFI21
|
2006-04-05 23:26:34 +02:00
|
|
|
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
|
|
|
.uleb128 0x3
|
|
|
|
|
|
|
|
.align 4
|
|
|
|
L$EFDE2:
|
2016-09-04 19:39:05 +02:00
|
|
|
|
|
|
|
L$SFDE3:
|
|
|
|
.word L$EFDE3-L$ASFDE3 ;# FDE Length
|
|
|
|
L$ASFDE3:
|
|
|
|
.word L$ASFDE3-L$frame1 ;# FDE CIE offset
|
|
|
|
.word L$FB3 ;# FDE initial location
|
|
|
|
.word L$FE3-L$FB3 ;# FDE address range
|
|
|
|
.byte 0x4 ;# DW_CFA_advance_loc4
|
|
|
|
.word L$CFI31-L$FB3
|
|
|
|
.byte 0x83 ;# DW_CFA_offset, column 0x3
|
|
|
|
.uleb128 0x0
|
|
|
|
.byte 0x11 ;# DW_CFA_offset_extended_sf
|
|
|
|
.uleb128 0x2
|
|
|
|
.sleb128 -5
|
|
|
|
|
|
|
|
.byte 0x4 ;# DW_CFA_advance_loc4
|
|
|
|
.word L$CFI32-L$CFI31
|
|
|
|
.byte 0xd ;# DW_CFA_def_cfa_register = r3
|
|
|
|
.uleb128 0x3
|
|
|
|
|
|
|
|
.align 4
|
|
|
|
L$EFDE3:
|