source: trunk/gcc/libffi/src/mips/o32.S

Last change on this file was 2, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 4.8 KB
Line 
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
43ffi_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
60bigger:
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
64sixteen:
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
88pass_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
95pass_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
103pass_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
109pass_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
117pass_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
124pass_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
130call_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
144retfloat:
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
151retdouble:
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
158noretval:
159 jal t9
160
161 # Epilogue
162epilogue:
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
Note: See TracBrowser for help on using the repository browser.