1 | /* -----------------------------------------------------------------------
|
---|
2 | sysv.S - Copyright (c) 1998 Cygnus Solutions
|
---|
3 |
|
---|
4 | ARM Foreign Function Interface
|
---|
5 |
|
---|
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:
|
---|
13 |
|
---|
14 | The above copyright notice and this permission notice shall be included
|
---|
15 | in all copies or substantial portions of the Software.
|
---|
16 |
|
---|
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 | ----------------------------------------------------------------------- */
|
---|
25 |
|
---|
26 | #define LIBFFI_ASM
|
---|
27 | #include <ffi.h>
|
---|
28 | #ifdef HAVE_MACHINE_ASM_H
|
---|
29 | #include <machine/asm.h>
|
---|
30 | #else
|
---|
31 | #ifdef __USER_LABEL_PREFIX__
|
---|
32 | #define CONCAT1(a, b) CONCAT2(a, b)
|
---|
33 | #define CONCAT2(a, b) a ## b
|
---|
34 |
|
---|
35 | /* Use the right prefix for global labels. */
|
---|
36 | #define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
---|
37 | #else
|
---|
38 | #define CNAME(x) x
|
---|
39 | #endif
|
---|
40 | #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
|
---|
41 | #endif
|
---|
42 |
|
---|
43 | .text
|
---|
44 |
|
---|
45 | # a1: ffi_prep_args
|
---|
46 | # a2: &ecif
|
---|
47 | # a3: cif->bytes
|
---|
48 | # a4: fig->flags
|
---|
49 | # sp+0: ecif.rvalue
|
---|
50 | # sp+4: fn
|
---|
51 |
|
---|
52 | # This assumes we are using gas.
|
---|
53 | ENTRY(ffi_call_SYSV)
|
---|
54 | # Save registers
|
---|
55 | stmfd sp!, {a1-a4, fp, lr}
|
---|
56 | mov fp, sp
|
---|
57 |
|
---|
58 | # Make room for all of the new args.
|
---|
59 | sub sp, fp, a3
|
---|
60 |
|
---|
61 | # Place all of the ffi_prep_args in position
|
---|
62 | mov ip, a1
|
---|
63 | mov a1, sp
|
---|
64 | # a2 already set
|
---|
65 |
|
---|
66 | # And call
|
---|
67 | mov lr, pc
|
---|
68 | mov pc, ip
|
---|
69 |
|
---|
70 | # move first 4 parameters in registers
|
---|
71 | ldr a1, [sp, #0]
|
---|
72 | ldr a2, [sp, #4]
|
---|
73 | ldr a3, [sp, #8]
|
---|
74 | ldr a4, [sp, #12]
|
---|
75 |
|
---|
76 | # and adjust stack
|
---|
77 | ldr ip, [fp, #8]
|
---|
78 | cmp ip, #16
|
---|
79 | movge ip, #16
|
---|
80 | add sp, sp, ip
|
---|
81 |
|
---|
82 | # call function
|
---|
83 | mov lr, pc
|
---|
84 | ldr pc, [fp, #28]
|
---|
85 |
|
---|
86 | # Remove the space we pushed for the args
|
---|
87 | mov sp, fp
|
---|
88 |
|
---|
89 | # Load a3 with the pointer to storage for the return value
|
---|
90 | ldr a3, [sp, #24]
|
---|
91 |
|
---|
92 | # Load a4 with the return type code
|
---|
93 | ldr a4, [sp, #12]
|
---|
94 |
|
---|
95 | # If the return value pointer is NULL, assume no return value.
|
---|
96 | cmp a3, #0
|
---|
97 | beq epilogue
|
---|
98 |
|
---|
99 | # return INT
|
---|
100 | cmp a4, #FFI_TYPE_INT
|
---|
101 | streq a1, [a3]
|
---|
102 | beq epilogue
|
---|
103 |
|
---|
104 | # return FLOAT
|
---|
105 | cmp a4, #FFI_TYPE_FLOAT
|
---|
106 | #ifdef __SOFTFP__
|
---|
107 | streq a1, [a3]
|
---|
108 | #else
|
---|
109 | stfeqs f0, [a3]
|
---|
110 | #endif
|
---|
111 | beq epilogue
|
---|
112 |
|
---|
113 | # return DOUBLE or LONGDOUBLE
|
---|
114 | cmp a4, #FFI_TYPE_DOUBLE
|
---|
115 | #ifdef __SOFTFP__
|
---|
116 | stmeqia a3, {a1, a2}
|
---|
117 | #else
|
---|
118 | stfeqd f0, [a3]
|
---|
119 | #endif
|
---|
120 |
|
---|
121 | epilogue:
|
---|
122 | ldmfd sp!, {a1-a4, fp, pc}
|
---|
123 |
|
---|
124 | .ffi_call_SYSV_end:
|
---|
125 | .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
|
---|
126 |
|
---|