1 | /* -----------------------------------------------------------------------
|
---|
2 | o32.S - Copyright (c) 1996, 1998 Cygnus Solutions
|
---|
3 |
|
---|
4 | MIPS 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 |
|
---|
29 | /* Only build this code if we are compiling for o32 */
|
---|
30 |
|
---|
31 | #if defined(FFI_MIPS_O32)
|
---|
32 |
|
---|
33 | #define callback a0
|
---|
34 | #define bytes a2
|
---|
35 | #define flags a3
|
---|
36 |
|
---|
37 | #define SIZEOF_FRAME ( 4 * SIZEOF_ARG + 2 * SIZEOF_ARG )
|
---|
38 |
|
---|
39 | .text
|
---|
40 | .align 2
|
---|
41 | .globl ffi_call_O32
|
---|
42 | .ent ffi_call_O32
|
---|
43 | ffi_call_O32:
|
---|
44 |
|
---|
45 | # Prologue
|
---|
46 | SUBU $sp, SIZEOF_FRAME # Frame size
|
---|
47 | REG_S $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Save frame pointer
|
---|
48 | REG_S ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Save return address
|
---|
49 | move $fp, $sp
|
---|
50 |
|
---|
51 | move t9, callback # callback function pointer
|
---|
52 | REG_S flags, SIZEOF_FRAME + 3*SIZEOF_ARG($fp) # flags
|
---|
53 |
|
---|
54 | # Allocate at least 4 words in the argstack
|
---|
55 | move v0, bytes
|
---|
56 | bge bytes, 4 * SIZEOF_ARG, bigger
|
---|
57 | LI v0, 4 * SIZEOF_ARG
|
---|
58 | b sixteen
|
---|
59 |
|
---|
60 | bigger:
|
---|
61 | ADDU t0, v0, 2 * SIZEOF_ARG -1 # make sure it is aligned
|
---|
62 | and v0, t0, -2 * SIZEOF_ARG # to an 8 byte boundry
|
---|
63 |
|
---|
64 | sixteen:
|
---|
65 | SUBU $sp, $sp, v0 # move the stack pointer to reflect the
|
---|
66 | # arg space
|
---|
67 |
|
---|
68 | ADDU a0, $sp, 4 * SIZEOF_ARG
|
---|
69 | ADDU a3, $fp, SIZEOF_FRAME + 3*SIZEOF_ARG
|
---|
70 |
|
---|
71 | jal t9
|
---|
72 |
|
---|
73 | REG_L t0, SIZEOF_FRAME + 3*SIZEOF_ARG($fp) # load the flags word
|
---|
74 | add t2, t0, 0 # and copy it into t2
|
---|
75 |
|
---|
76 | and t0, ((1<<4)-1) # mask out the return type
|
---|
77 | SRL t2, 4 # shift our arg info
|
---|
78 |
|
---|
79 | ADDU $sp, $sp, 4 * SIZEOF_ARG # adjust $sp to new args
|
---|
80 |
|
---|
81 | bnez t0, pass_d # make it quick for int
|
---|
82 | REG_L a0, 0*SIZEOF_ARG($sp) # just go ahead and load the
|
---|
83 | REG_L a1, 1*SIZEOF_ARG($sp) # four regs.
|
---|
84 | REG_L a2, 2*SIZEOF_ARG($sp)
|
---|
85 | REG_L a3, 3*SIZEOF_ARG($sp)
|
---|
86 | b call_it
|
---|
87 |
|
---|
88 | pass_d:
|
---|
89 | bne t0, FFI_ARGS_D, pass_f
|
---|
90 | l.d $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
---|
91 | REG_L a2, 2*SIZEOF_ARG($sp) # passing a double
|
---|
92 | REG_L a3, 3*SIZEOF_ARG($sp)
|
---|
93 | b call_it
|
---|
94 |
|
---|
95 | pass_f:
|
---|
96 | bne t0, FFI_ARGS_F, pass_d_d
|
---|
97 | l.s $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
---|
98 | REG_L a1, 1*SIZEOF_ARG($sp) # passing a float
|
---|
99 | REG_L a2, 2*SIZEOF_ARG($sp)
|
---|
100 | REG_L a3, 3*SIZEOF_ARG($sp)
|
---|
101 | b call_it
|
---|
102 |
|
---|
103 | pass_d_d:
|
---|
104 | bne t0, FFI_ARGS_DD, pass_f_f
|
---|
105 | l.d $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
---|
106 | l.d $f14, 2*SIZEOF_ARG($sp) # passing two doubles
|
---|
107 | b call_it
|
---|
108 |
|
---|
109 | pass_f_f:
|
---|
110 | bne t0, FFI_ARGS_FF, pass_d_f
|
---|
111 | l.s $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
---|
112 | l.s $f14, 1*SIZEOF_ARG($sp) # passing two floats
|
---|
113 | REG_L a2, 2*SIZEOF_ARG($sp)
|
---|
114 | REG_L a3, 3*SIZEOF_ARG($sp)
|
---|
115 | b call_it
|
---|
116 |
|
---|
117 | pass_d_f:
|
---|
118 | bne t0, FFI_ARGS_DF, pass_f_d
|
---|
119 | l.d $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
---|
120 | l.s $f14, 2*SIZEOF_ARG($sp) # passing double and float
|
---|
121 | REG_L a3, 3*SIZEOF_ARG($sp)
|
---|
122 | b call_it
|
---|
123 |
|
---|
124 | pass_f_d:
|
---|
125 | # assume that the only other combination must be float then double
|
---|
126 | # bne t0, FFI_ARGS_F_D, call_it
|
---|
127 | l.s $f12, 0*SIZEOF_ARG($sp) # load $fp regs from args
|
---|
128 | l.d $f14, 2*SIZEOF_ARG($sp) # passing double and float
|
---|
129 |
|
---|
130 | call_it:
|
---|
131 | # Load the function pointer
|
---|
132 | REG_L t9, SIZEOF_FRAME + 5*SIZEOF_ARG($fp)
|
---|
133 |
|
---|
134 | # If the return value pointer is NULL, assume no return value.
|
---|
135 | REG_L t1, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
|
---|
136 | beqz t1, noretval
|
---|
137 |
|
---|
138 | bne t2, FFI_TYPE_INT, retfloat
|
---|
139 | jal t9
|
---|
140 | REG_L t0, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
|
---|
141 | REG_S v0, 0(t0)
|
---|
142 | b epilogue
|
---|
143 |
|
---|
144 | retfloat:
|
---|
145 | bne t2, FFI_TYPE_FLOAT, retdouble
|
---|
146 | jal t9
|
---|
147 | REG_L t0, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
|
---|
148 | s.s $f0, 0(t0)
|
---|
149 | b epilogue
|
---|
150 |
|
---|
151 | retdouble:
|
---|
152 | bne t2, FFI_TYPE_DOUBLE, noretval
|
---|
153 | jal t9
|
---|
154 | REG_L t0, SIZEOF_FRAME + 4*SIZEOF_ARG($fp)
|
---|
155 | s.d $f0, 0(t0)
|
---|
156 | b epilogue
|
---|
157 |
|
---|
158 | noretval:
|
---|
159 | jal t9
|
---|
160 |
|
---|
161 | # Epilogue
|
---|
162 | epilogue:
|
---|
163 | move $sp, $fp
|
---|
164 | REG_L $fp, SIZEOF_FRAME - 2*SIZEOF_ARG($sp) # Restore frame pointer
|
---|
165 | REG_L ra, SIZEOF_FRAME - 1*SIZEOF_ARG($sp) # Restore return address
|
---|
166 | ADDU $sp, SIZEOF_FRAME # Fix stack pointer
|
---|
167 | j ra
|
---|
168 |
|
---|
169 | .end ffi_call_O32
|
---|
170 |
|
---|
171 | #endif
|
---|