* lib/target-supports.exp
[official-gcc.git] / libffi / src / riscv / sysv.S
blob2d098651d0da14ff81866fb5a1dd1247f518ad24
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 2015 Michael Knyszek <mknyszek@berkeley.edu>
3                          2015 Andrew Waterman <waterman@cs.berkeley.edu>
4                          2018 Stef O'Rear <sorear2@gmail.com>
6    RISC-V Foreign Function Interface
8    Permission is hereby granted, free of charge, to any person obtaining
9    a copy of this software and associated documentation files (the
10    ``Software''), to deal in the Software without restriction, including
11    without limitation the rights to use, copy, modify, merge, publish,
12    distribute, sublicense, and/or sell copies of the Software, and to
13    permit persons to whom the Software is furnished to do so, subject to
14    the following conditions:
16    The above copyright notice and this permission notice shall be included
17    in all copies or substantial portions of the Software.
19    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
20    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26    DEALINGS IN THE SOFTWARE.
27    ----------------------------------------------------------------------- */
29 #define LIBFFI_ASM
30 #include <fficonfig.h>
31 #include <ffi.h>
33 /* Define aliases so that we can handle all ABIs uniformly */
35 #if __SIZEOF_POINTER__ == 8
36 #define PTRS 8
37 #define LARG ld
38 #define SARG sd
39 #else
40 #define PTRS 4
41 #define LARG lw
42 #define SARG sw
43 #endif
45 #if __riscv_float_abi_double
46 #define FLTS 8
47 #define FLARG fld
48 #define FSARG fsd
49 #elif __riscv_float_abi_single
50 #define FLTS 4
51 #define FLARG flw
52 #define FSARG fsw
53 #else
54 #define FLTS 0
55 #endif
57 #define fp s0
59     .text
60     .globl  ffi_call_asm
61     .type   ffi_call_asm, @function
62     .hidden ffi_call_asm
64   struct call_context {
65       floatreg fa[8];
66       intreg a[8];
67       intreg pad[rv32 ? 2 : 0];
68       intreg save_fp, save_ra;
69   }
70   void ffi_call_asm(size_t *stackargs, struct call_context *regargs,
71       void (*fn)(void));
74 #define FRAME_LEN (8 * FLTS + 8 * PTRS + 16)
76 ffi_call_asm:
77     .cfi_startproc
79     /*
80       We are NOT going to set up an ordinary stack frame.  In order to pass
81       the stacked args to the called function, we adjust our stack pointer to
82       a0, which is in the _caller's_ alloca area.  We establish our own stack
83       frame at the end of the call_context.
85       Anything below the arguments will be freed at this point, although we
86       preserve the call_context so that it can be read back in the caller.
87     */
89     .cfi_def_cfa 11, FRAME_LEN # interim CFA based on a1
90     SARG    fp, FRAME_LEN - 2*PTRS(a1)
91     .cfi_offset 8, -2*PTRS
92     SARG    ra, FRAME_LEN - 1*PTRS(a1)
93     .cfi_offset 1, -1*PTRS
95     addi    fp, a1, FRAME_LEN
96     mv      sp, a0
97     .cfi_def_cfa 8, 0 # our frame is fully set up
99     # Load arguments
100     mv      t1, a2
102 #if FLTS
103     FLARG   fa0, -FRAME_LEN+0*FLTS(fp)
104     FLARG   fa1, -FRAME_LEN+1*FLTS(fp)
105     FLARG   fa2, -FRAME_LEN+2*FLTS(fp)
106     FLARG   fa3, -FRAME_LEN+3*FLTS(fp)
107     FLARG   fa4, -FRAME_LEN+4*FLTS(fp)
108     FLARG   fa5, -FRAME_LEN+5*FLTS(fp)
109     FLARG   fa6, -FRAME_LEN+6*FLTS(fp)
110     FLARG   fa7, -FRAME_LEN+7*FLTS(fp)
111 #endif
113     LARG    a0, -FRAME_LEN+8*FLTS+0*PTRS(fp)
114     LARG    a1, -FRAME_LEN+8*FLTS+1*PTRS(fp)
115     LARG    a2, -FRAME_LEN+8*FLTS+2*PTRS(fp)
116     LARG    a3, -FRAME_LEN+8*FLTS+3*PTRS(fp)
117     LARG    a4, -FRAME_LEN+8*FLTS+4*PTRS(fp)
118     LARG    a5, -FRAME_LEN+8*FLTS+5*PTRS(fp)
119     LARG    a6, -FRAME_LEN+8*FLTS+6*PTRS(fp)
120     LARG    a7, -FRAME_LEN+8*FLTS+7*PTRS(fp)
122     /* Call */
123     jalr    t1
125     /* Save return values - only a0/a1 (fa0/fa1) are used */
126 #if FLTS
127     FSARG   fa0, -FRAME_LEN+0*FLTS(fp)
128     FSARG   fa1, -FRAME_LEN+1*FLTS(fp)
129 #endif
131     SARG    a0, -FRAME_LEN+8*FLTS+0*PTRS(fp)
132     SARG    a1, -FRAME_LEN+8*FLTS+1*PTRS(fp)
134     /* Restore and return */
135     addi    sp, fp, -FRAME_LEN
136     .cfi_def_cfa 2, FRAME_LEN
137     LARG    ra, -1*PTRS(fp)
138     .cfi_restore 1
139     LARG    fp, -2*PTRS(fp)
140     .cfi_restore 8
141     ret
142     .cfi_endproc
143     .size   ffi_call_asm, .-ffi_call_asm
147   ffi_closure_asm. Expects address of the passed-in ffi_closure in t1.
148   void ffi_closure_inner(size_t *stackargs, struct call_context *regargs,
149       ffi_closure *closure);
152     .globl ffi_closure_asm
153     .hidden ffi_closure_asm
154     .type ffi_closure_asm, @function
155 ffi_closure_asm:
156     .cfi_startproc
158     addi    sp,  sp, -FRAME_LEN
159     .cfi_def_cfa_offset FRAME_LEN
161     /* make a frame */
162     SARG    fp, FRAME_LEN - 2*PTRS(sp)
163     .cfi_offset 8, -2*PTRS
164     SARG    ra, FRAME_LEN - 1*PTRS(sp)
165     .cfi_offset 1, -1*PTRS
166     addi    fp, sp, FRAME_LEN
168     /* save arguments */
169 #if FLTS
170     FSARG   fa0, 0*FLTS(sp)
171     FSARG   fa1, 1*FLTS(sp)
172     FSARG   fa2, 2*FLTS(sp)
173     FSARG   fa3, 3*FLTS(sp)
174     FSARG   fa4, 4*FLTS(sp)
175     FSARG   fa5, 5*FLTS(sp)
176     FSARG   fa6, 6*FLTS(sp)
177     FSARG   fa7, 7*FLTS(sp)
178 #endif
180     SARG    a0, 8*FLTS+0*PTRS(sp)
181     SARG    a1, 8*FLTS+1*PTRS(sp)
182     SARG    a2, 8*FLTS+2*PTRS(sp)
183     SARG    a3, 8*FLTS+3*PTRS(sp)
184     SARG    a4, 8*FLTS+4*PTRS(sp)
185     SARG    a5, 8*FLTS+5*PTRS(sp)
186     SARG    a6, 8*FLTS+6*PTRS(sp)
187     SARG    a7, 8*FLTS+7*PTRS(sp)
189     /* enter C */
190     addi    a0, sp, FRAME_LEN
191     mv      a1, sp
192     mv      a2, t1
194     call    ffi_closure_inner
196     /* return values */
197 #if FLTS
198     FLARG   fa0, 0*FLTS(sp)
199     FLARG   fa1, 1*FLTS(sp)
200 #endif
202     LARG    a0, 8*FLTS+0*PTRS(sp)
203     LARG    a1, 8*FLTS+1*PTRS(sp)
205     /* restore and return */
206     LARG    ra, FRAME_LEN-1*PTRS(sp)
207     .cfi_restore 1
208     LARG    fp, FRAME_LEN-2*PTRS(sp)
209     .cfi_restore 8
210     addi    sp, sp, FRAME_LEN
211     .cfi_def_cfa_offset 0
212     ret
213     .cfi_endproc
214     .size ffi_closure_asm, .-ffi_closure_asm