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