Imported Upstream version 4.8.1
[platform/upstream/gcc48.git] / libffi / src / bfin / sysv.S
1 /* -----------------------------------------------------------------------
2    sysv.S - Copyright (c) 2012  Alexandre K. I. de Mendonca <alexandre.keunecke@gmail.com>
3
4    Blackfin 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,
18    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24    DEALINGS IN THE SOFTWARE.
25    ----------------------------------------------------------------------- */
26
27 #define LIBFFI_ASM
28 #include <fficonfig.h>
29 #include <ffi.h>
30
31 .text
32 .align 4
33
34         /*
35          There is a "feature" in the bfin toolchain that it puts a _ before funcion names
36          that's why the function here it's called _ffi_call_SYSV and not ffi_call_SYSV
37          */
38         .global _ffi_call_SYSV;
39         .type _ffi_call_SYSV, STT_FUNC;
40         .func ffi_call_SYSV
41
42         /*
43         cif->bytes      = R0    (fp+8)
44         &ecif                   = R1    (fp+12)
45         ffi_prep_args   = R2    (fp+16)
46         ret_type                = stack (fp+20)
47         ecif.rvalue             = stack (fp+24)
48         fn                              = stack (fp+28)
49                                           got   (fp+32)
50     There is room for improvement here (we can use temporary registers
51         instead of saving the values in the memory)
52         REGS:
53                 P5 => Stack pointer (function arguments)
54                 R5 => cif->bytes
55                 R4 => ret->type
56
57                 FP-20 = P3
58                 FP-16 = SP (parameters area)
59                 FP-12 = SP (temp)
60                 FP-08 = function return part 1 [R0]
61                 FP-04 = function return part 2 [R1]
62         */
63
64 _ffi_call_SYSV:
65 .prologue:
66         LINK 20;
67         [FP-20] = P3;
68         [FP+8] = R0;
69         [FP+12] = R1;
70         [FP+16] = R2;
71
72 .allocate_stack:
73         //alocate cif->bytes into the stack
74         R1 = [FP+8];
75         R0 = SP;
76         R0 = R0 - R1;
77         R1 = 4;
78         R0 = R0 - R1;
79         [FP-12] = SP;
80         SP = R0;
81         [FP-16] = SP;
82
83 .call_prep_args:
84         //get the addr of prep_args
85         P0 = [P3 + _ffi_prep_args@FUNCDESC_GOT17M4];
86         P1 = [P0];
87         P3 = [P0+4];
88         R0 = [FP-16];//SP (parameter area)
89         R1 = [FP+12];//ecif
90         call (P1);
91
92 .call_user_function:
93         //ajust SP so as to allow the user function access the parameters on the stack
94         SP = [FP-16]; //point to function parameters
95         R0 = [SP];
96         R1 = [SP+4];
97         R2 = [SP+8];
98         //load user function address
99         P0 = FP;
100         P0 +=28;
101         P1 = [P0];
102         P1 = [P1];
103         P3 = [P0+4];
104         /*
105                 For functions returning aggregate values (struct) occupying more than 8 bytes,
106                 the caller allocates the return value object on the stack and the address
107                 of this object is passed to the callee as a hidden argument in register P0.
108         */
109         P0 = [FP+24];
110
111         call (P1);
112         SP = [FP-12];
113 .compute_return:
114         P2 = [FP-20];
115         [FP-8] = R0;
116         [FP-4] = R1;
117
118         R0 = [FP+20];
119         R1 = R0 << 2;
120
121         R0 = [P2+.rettable@GOT17M4];
122         R0 = R1 + R0;
123         P2 = R0;
124         R1 = [P2];
125
126         P2 = [FP+-20];
127         R0 = [P2+.rettable@GOT17M4];
128         R0 = R1 + R0;
129         P2 = R0;
130         R0 = [FP-8];
131         R1 = [FP-4];
132         jump (P2);
133
134 /*
135 #define FFIBFIN_RET_VOID 0
136 #define FFIBFIN_RET_BYTE 1
137 #define FFIBFIN_RET_HALFWORD 2
138 #define FFIBFIN_RET_INT64 3
139 #define FFIBFIN_RET_INT32 4
140 */
141 .align 4
142 .align 4
143 .rettable:
144         .dd .epilogue - .rettable
145         .dd     .rbyte - .rettable;
146         .dd     .rhalfword - .rettable;
147         .dd     .rint64 - .rettable;
148         .dd     .rint32 - .rettable;
149
150 .rbyte:
151         P0 = [FP+24];
152         R0 = R0.B (Z);
153         [P0] = R0;
154         JUMP .epilogue
155 .rhalfword:
156         P0 = [FP+24];
157         R0 = R0.L;
158         [P0] = R0;
159         JUMP .epilogue
160 .rint64:
161         P0 = [FP+24];// &rvalue
162         [P0] = R0;
163         [P0+4] = R1;
164         JUMP .epilogue
165 .rint32:
166         P0 = [FP+24];
167         [P0] = R0;
168 .epilogue:
169         R0 = [FP+8];
170         R1 = [FP+12];
171         R2 = [FP+16];
172         P3 = [FP-20];
173         UNLINK;
174         RTS;
175
176 .size _ffi_call_SYSV,.-_ffi_call_SYSV;
177 .endfunc