1
/* -----------------------------------------------------------------------
2
linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
4
HPPA Foreign Function Interface
6
Permission is hereby granted, free of charge, to any person obtaining
7
a copy of this software and associated documentation files (the
8
``Software''), to deal in the Software without restriction, including
9
without limitation the rights to use, copy, modify, merge, publish,
10
distribute, sublicense, and/or sell copies of the Software, and to
11
permit persons to whom the Software is furnished to do so, subject to
12
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.
17
THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
OTHER DEALINGS IN THE SOFTWARE.
24
----------------------------------------------------------------------- */
27
#include <fficonfig.h>
34
/* void ffi_call_LINUX(void (*)(char *, extended_cif *),
42
.export ffi_call_LINUX,code
43
.import ffi_prep_args_LINUX,code
45
.type ffi_call_LINUX, @function
49
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
58
/* Setup the stack for calling prep_args...
59
We want the stack to look like this:
61
[ Previous stack ] <- %r3
63
[ 64-bytes register save area ] <- %r4
65
[ Stack space for actual call, passed as ] <- %arg0
66
[ arg0 to ffi_prep_args_LINUX ]
68
[ Stack for calling prep_args ] <- %sp
76
addl %arg2, %r4, %arg0 /* arg stack */
77
stw %arg3, -48(%r3) /* save flags; we need it later */
80
%arg0(stack) -- set up above
81
%arg1(ecif) -- same as incoming param
82
%arg2(bytes) -- same as incoming param */
83
bl ffi_prep_args_LINUX,%r2
87
/* now %sp should point where %arg0 was pointing. */
89
/* Load the arguments that should be passed in registers
90
The fp args were loaded by the prep_args function. */
96
/* in case the function is going to return a structure
97
we need to give it a place to put the result. */
98
ldw -52(%r3), %ret0 /* %ret0 <- rvalue */
99
ldw -56(%r3), %r22 /* %r22 <- function to call */
100
bl $$dyncall, %r31 /* Call the user function */
103
/* Prepare to store the result; we need to recover flags and rvalue. */
104
ldw -48(%r3), %r21 /* r21 <- flags */
105
ldw -52(%r3), %r20 /* r20 <- rvalue */
107
/* Store the result according to the return type. */
110
comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, checksmst567
111
/* 3-byte structs are returned in ret0 as ??xxyyzz. Shift
112
left 8 bits to write to the result structure. */
113
zdep %ret0, 23, 24, %r22
118
/* 5-7 byte values are returned right justified:
124
To store this in the result, write the first 4 bytes into a temp
125
register using shrpw (t1 = aabbccdd), followed by a rotation of
129
5: ??????aa bbccddee -> eebbccdd (rotate 8)
130
6: ????aabb ccddeeff -> eeffccdd (rotate 16)
131
7: ??aabbcc ddeeffgg -> eeffggdd (rotate 24)
133
then we write (t1, ret1) into the result. */
135
addi,<> -FFI_TYPE_SMALL_STRUCT5,%r21,%r0
137
addi,<> -FFI_TYPE_SMALL_STRUCT6,%r21,%r0
139
addi,<> -FFI_TYPE_SMALL_STRUCT7,%r21,%r0
142
/* This relies on all the FFI_TYPE_*_STRUCT* defines being <0 */
143
cmpib,<=,n 0, %r21, checkint8
146
shrpw %ret0, %ret1, %sar, %ret0 /* ret0 = aabbccdd */
147
shrpw %ret1, %ret1, %sar, %ret1 /* rotate ret1 */
154
comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
159
comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
164
comib,<>,n FFI_TYPE_UINT32, %r21, checkint
169
comib,<>,n FFI_TYPE_INT, %r21, checkll
174
comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
180
comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
185
comib,<>,n FFI_TYPE_FLOAT, %r21, done
188
/* structure returns are either handled by one of the
189
INT/UINT64 cases above, or, if passed by pointer,
190
is handled by the callee. */
193
/* all done, return */
194
copy %r4, %sp /* pop arg stack */
196
ldwm -64(%sp), %r3 /* .. and pop stack */
204
/* void ffi_closure_LINUX(void);
205
Called with closure argument in %r21 */
206
.export ffi_closure_LINUX,code
207
.import ffi_closure_inner_LINUX,code
209
.type ffi_closure_LINUX, @function
213
.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
224
/* Put arguments onto the stack and call ffi_closure_inner. */
231
bl ffi_closure_inner_LINUX, %r2
244
.section ".eh_frame",EH_FRAME_FLAGS,@progbits
246
.word .LECIE1-.LSCIE1 ;# Length of Common Information Entry
248
.word 0x0 ;# CIE Identifier Tag
249
.byte 0x1 ;# CIE Version
250
.ascii "\0" ;# CIE Augmentation
251
.uleb128 0x1 ;# CIE Code Alignment Factor
252
.sleb128 4 ;# CIE Data Alignment Factor
253
.byte 0x2 ;# CIE RA Column
254
.byte 0xc ;# DW_CFA_def_cfa
260
.word .LEFDE1-.LASFDE1 ;# FDE Length
262
.word .LASFDE1-.Lframe1 ;# FDE CIE offset
263
.word .LFB1 ;# FDE initial location
264
.word .LFE1-.LFB1 ;# FDE address range
266
.byte 0x4 ;# DW_CFA_advance_loc4
268
.byte 0x83 ;# DW_CFA_offset, column 0x3
270
.byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
274
.byte 0x4 ;# DW_CFA_advance_loc4
275
.word .LCFI12-.LCFI11
276
.byte 0xd ;# DW_CFA_def_cfa_register = r3
279
.byte 0x4 ;# DW_CFA_advance_loc4
280
.word .LCFI13-.LCFI12
281
.byte 0x84 ;# DW_CFA_offset, column 0x4
288
.word .LEFDE2-.LASFDE2 ;# FDE Length
290
.word .LASFDE2-.Lframe1 ;# FDE CIE offset
291
.word .LFB2 ;# FDE initial location
292
.word .LFE2-.LFB2 ;# FDE address range
293
.byte 0x4 ;# DW_CFA_advance_loc4
295
.byte 0x83 ;# DW_CFA_offset, column 0x3
297
.byte 0x11 ;# DW_CFA_offset_extended_sf
301
.byte 0x4 ;# DW_CFA_advance_loc4
302
.word .LCFI12-.LCFI11
303
.byte 0xd ;# DW_CFA_def_cfa_register = r3