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>
33 /* void ffi_call_LINUX(void (*)(char *, extended_cif *),
41 .export ffi_call_LINUX,code
42 .import ffi_prep_args_LINUX,code
44 .type ffi_call_LINUX, @function
48 .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
57 /* Setup the stack for calling prep_args...
58 We want the stack to look like this:
60 [ Previous stack ] <- %r3
62 [ 64-bytes register save area ] <- %r4
64 [ Stack space for actual call, passed as ] <- %arg0
65 [ arg0 to ffi_prep_args_LINUX ]
67 [ Stack for calling prep_args ] <- %sp
75 addl %arg2, %r4, %arg0 /* arg stack */
76 stw %arg3, -48(%r3) /* save flags; we need it later */
79 %arg0(stack) -- set up above
80 %arg1(ecif) -- same as incoming param
81 %arg2(bytes) -- same as incoming param */
82 bl ffi_prep_args_LINUX,%r2
86 /* now %sp should point where %arg0 was pointing. */
88 /* Load the arguments that should be passed in registers
89 The fp args were loaded by the prep_args function. */
95 /* in case the function is going to return a structure
96 we need to give it a place to put the result. */
97 ldw -52(%r3), %ret0 /* %ret0 <- rvalue */
98 ldw -56(%r3), %r22 /* %r22 <- function to call */
99 bl $$dyncall, %r31 /* Call the user function */
102 /* Prepare to store the result; we need to recover flags and rvalue. */
103 ldw -48(%r3), %r21 /* r21 <- flags */
104 ldw -52(%r3), %r20 /* r20 <- rvalue */
106 /* Store the result according to the return type. */
109 comib,<>,n FFI_TYPE_SMALL_STRUCT1, %r21, checksmst2
110 /* There is maybe a better way to handle 3 byte structs. */
119 comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, checkint8
120 /* Up to now I don't have a way to handle 6/7 byte structs.
121 The values are left bounded in the registers. In the struct
122 itself they are left bounded. */
128 comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
133 comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
138 comib,<>,n FFI_TYPE_UINT32, %r21, checkint
143 comib,<>,n FFI_TYPE_INT, %r21, checkll
148 comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
154 comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
159 comib,<>,n FFI_TYPE_FLOAT, %r21, done
162 /* structure returns are either handled by one of the
163 INT/UINT64 cases above, or, if passed by pointer,
164 is handled by the callee. */
167 /* all done, return */
168 copy %r4, %sp /* pop arg stack */
170 ldwm -64(%sp), %r3 /* .. and pop stack */
178 /* void ffi_closure_LINUX(void);
179 Called with closure argument in %r21 */
180 .export ffi_closure_LINUX,code
181 .import ffi_closure_inner_LINUX,code
183 .type ffi_closure_LINUX, @function
187 .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
198 /* Put arguments onto the stack and call ffi_closure_inner. */
205 bl ffi_closure_inner_LINUX, %r2
218 .section ".eh_frame",EH_FRAME_FLAGS,@progbits
220 .word .LECIE1-.LSCIE1 ;# Length of Common Information Entry
222 .word 0x0 ;# CIE Identifier Tag
223 .byte 0x1 ;# CIE Version
224 .ascii "\0" ;# CIE Augmentation
225 .uleb128 0x1 ;# CIE Code Alignment Factor
226 .sleb128 4 ;# CIE Data Alignment Factor
227 .byte 0x2 ;# CIE RA Column
228 .byte 0xc ;# DW_CFA_def_cfa
234 .word .LEFDE1-.LASFDE1 ;# FDE Length
236 .word .LASFDE1-.Lframe1 ;# FDE CIE offset
237 .word .LFB1 ;# FDE initial location
238 .word .LFE1-.LFB1 ;# FDE address range
240 .byte 0x4 ;# DW_CFA_advance_loc4
242 .byte 0x83 ;# DW_CFA_offset, column 0x3
244 .byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
248 .byte 0x4 ;# DW_CFA_advance_loc4
249 .word .LCFI12-.LCFI11
250 .byte 0xd ;# DW_CFA_def_cfa_register = r3
253 .byte 0x4 ;# DW_CFA_advance_loc4
254 .word .LCFI13-.LCFI12
255 .byte 0x84 ;# DW_CFA_offset, column 0x4
262 .word .LEFDE2-.LASFDE2 ;# FDE Length
264 .word .LASFDE2-.Lframe1 ;# FDE CIE offset
265 .word .LFB2 ;# FDE initial location
266 .word .LFE2-.LFB2 ;# FDE address range
267 .byte 0x4 ;# DW_CFA_advance_loc4
269 .byte 0x83 ;# DW_CFA_offset, column 0x3
271 .byte 0x11 ;# DW_CFA_offset_extended_sf
275 .byte 0x4 ;# DW_CFA_advance_loc4
276 .word .LCFI12-.LCFI11
277 .byte 0xd ;# DW_CFA_def_cfa_register = r3