Merged.
[cacao.git] / src / vm / jit / sparc64 / md-abi.c
1 /* src/vm/jit/sparc64/md-abi.c - functions for Sparc ABI
2
3    Copyright (C) 1996-2005, 2006, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27 #include "vm/types.h"
28
29 #include "vm/jit/sparc64/md-abi.h"
30
31 #include "vm/descriptor.hpp"
32 #include "vm/global.h"
33
34 #include "vm/jit/abi.h"
35 #include "vm/jit/stack.h"
36
37 /* temp */
38 #include "mm/memory.h"
39 #include <assert.h>
40
41
42 /* helper macros for allocation methods ***************************************/
43 #define MIN(a,b) (((a) <= (b)) ? (a) : (b))
44
45 /* register descripton array **************************************************/
46
47 /* callee point-of-view, after SAVE has been called. */
48 s4 nregdescint[] = {
49         /* zero  itmp1/g1 itmp2/g2 itmp3/g3 temp/g4  temp/g5  sys/g6   sys/g7 */  
50         REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
51         
52         /* o0    o1       o2       o3       o4       pv/o5    sp/o6    ra/o7  */
53         REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES,
54         
55         /* l0    l1       l2       l3       l4       l5       l6       l7     */
56         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
57         
58         /* i0    i1       i2       i3       i4       pv/i5    fp/i6    ra/i7  */
59         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_RES, REG_RES, REG_RES,
60         REG_END
61 };
62
63 const char *abi_registers_integer_name[] = {
64                 "zero",  "g1",  "g2",  "g3",  "g4",  "g5",  "g6",  "g7",
65                 "o0",    "o1",  "o2",  "o3",  "o4",  "o5",  "sp",  "o7",
66                 "l0",    "l1",  "l2",  "l3",  "l4",  "l5",  "l6",  "l7",
67                 "i0",    "i1",  "i2",  "i3",  "i4",  "i5",  "fp",  "i7"
68 };
69
70 const s4 abi_registers_integer_argument[] = {
71         8,  /* o0  */
72         9,  /* o1  */
73         10, /* o2  */
74         11, /* o3  */
75         12, /* o4  */
76 };
77
78 const s4 abi_registers_integer_saved[] = {
79         16, /* l0  */
80         17, /* l1  */
81         18, /* l2  */
82         19, /* l3  */
83         20, /* l4  */
84         21, /* l5  */
85         22, /* l6  */
86         23, /* l7  */
87         24, /* i0  */
88         25, /* i1  */
89         26, /* i2  */
90         27, /* i3  */
91         28, /* i4  */
92 };
93
94
95
96 s4 nregdescfloat[] = {
97         REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
98         REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP,
99         REG_END
100 };
101
102
103 const s4 abi_registers_float_argument[] = {
104         8,  /* f16  */
105         9,  /* f18  */
106         10, /* f20  */
107         11, /* f22  */
108         12, /* f24  */
109 };
110
111 const s4 abi_registers_float_temporary[] = {
112         4,  /* f8   */
113         5,  /* f10  */
114         6,  /* f12  */
115         7,  /* f14  */
116         13, /* f26  */
117         14, /* f28  */
118         15, /* f30  */
119 };
120
121 s4 nat_argintregs[] = {
122         REG_OUT0, REG_OUT1, REG_OUT2, REG_OUT3, REG_OUT4, REG_OUT5
123 };
124
125
126 /* md_param_alloc **************************************************************
127
128    Allocate Arguments to Stackslots according the Calling Conventions
129
130    --- in
131    md->paramcount:           Number of arguments for this method
132    md->paramtypes[].type:    Argument types
133
134    --- out
135    md->params[].inmemory:    Argument spilled on stack
136    md->params[].regoff:      Stack offset or rd->arg[int|flt]regs index
137    md->memuse:               Stackslots needed for argument spilling
138    md->argintreguse:         max number of integer arguments used
139    md->argfltreguse:         max number of float arguments used
140
141 *******************************************************************************/
142
143 void md_param_alloc(methoddesc *md)
144 {
145         paramdesc *pd;
146         s4         i;
147         s4         reguse;
148         s4         stacksize;
149
150         /* set default values */
151
152         reguse = 0;
153         stacksize = 0;
154
155         /* get params field of methoddesc */
156
157         pd = md->params;
158
159         for (i = 0; i < md->paramcount; i++, pd++) {
160                 switch (md->paramtypes[i].type) {
161                 case TYPE_INT:
162                 case TYPE_ADR:
163                 case TYPE_LNG:
164                         if (i < INT_ARG_CNT) {
165                                 pd->inmemory = false;
166                                 pd->index = reguse;
167                                 pd->regoff   = abi_registers_integer_argument[reguse];
168                                 reguse++;
169                                 md->argintreguse = reguse;
170                         }
171                         else {
172                                 pd->inmemory = true;
173                                 pd->index = stacksize;
174                                 pd->regoff = stacksize * 8;
175                                 stacksize++;
176                         }
177                         break;
178
179                 case TYPE_FLT:
180                 case TYPE_DBL:
181                         if (i < FLT_ARG_CNT) {
182                                 pd->inmemory = false;
183                                 pd->index = reguse;
184                                 pd->regoff   = abi_registers_float_argument[reguse];
185                                 reguse++;
186                                 md->argfltreguse = reguse;
187                         }
188                         else {
189                                 pd->inmemory = true;
190                                 pd->index = stacksize;
191                                 pd->regoff = stacksize * 8;
192                                 stacksize++;
193                         }
194                         break;
195                 }
196                 assert(pd->regoff != 26);
197         }
198         
199         /* Since O0 is used for passing return values, this */
200         /* argument register usage has to be regarded, too                        */
201         if (IS_INT_LNG_TYPE(md->returntype.type)) {
202                 if (reguse < 1)
203                         md->argintreguse = 1;
204         }
205
206         /* fill register and stack usage */
207
208         md->memuse = stacksize;
209 }
210
211
212 /* md_param_alloc_native *******************************************************
213  *
214  *    Pre-allocate arguments according to the native ABI.
215  *
216  *    *******************************************************************************/
217
218 void md_param_alloc_native(methoddesc *md)
219 {
220         paramdesc *pd;
221         s4         i;
222         s4         reguse;
223         s4         stacksize;
224         s4         min_nat_regs;
225
226         /* Note: regoff will be set relative to a stack base of $sp+16 */
227          
228         /* set default values */
229         reguse = 0;
230         stacksize = 6; /* abi params: allocated, but not used */
231
232         /* when we are above this, we have to increase the stacksize with every */
233         /* single argument to create the proper argument array                  */
234         min_nat_regs = MIN(INT_NATARG_CNT, FLT_NATARG_CNT);
235
236         /* get params field of methoddesc */
237
238         pd = md->params;
239
240         for (i = 0; i < md->paramcount; i++, pd++) {
241                 switch (md->paramtypes[i].type) {
242                 case TYPE_INT:
243                 case TYPE_ADR:
244                 case TYPE_LNG:
245                         if (i < INT_NATARG_CNT) {
246                                 pd->inmemory = false;
247                                 pd->regoff = nat_argintregs[reguse];
248                                 reguse++;
249                                 md->argintreguse = reguse;
250
251                         } else {
252                                 pd->inmemory = true;
253                                 pd->regoff = reguse * 8;
254                                 reguse++;
255                         }
256                         break;
257                 case TYPE_FLT:
258                 case TYPE_DBL:
259                         if (i < FLT_NATARG_CNT) {
260                                 pd->inmemory = false;
261                                 pd->regoff = reguse;
262                                 reguse++;
263                                 md->argfltreguse = reguse;
264                         } else {
265                                 pd->inmemory = true;
266                                 pd->regoff = reguse * 8;
267                                 reguse++;
268                         }
269
270                         break;
271                 }
272
273                 if (i >= min_nat_regs)
274                         stacksize++;
275         }
276         
277         /* Since O0 is used for passing return values, this */
278         /* argument register usage has to be regarded, too                        */
279         if (IS_INT_LNG_TYPE(md->returntype.type)) {
280                 if (reguse < 1)
281                         md->argintreguse = 1;
282         }
283
284         /* fill register and stack usage */
285
286         md->memuse = stacksize;
287 }
288
289 /* md_return_alloc *************************************************************
290
291   XXX
292
293 *******************************************************************************/
294
295 void md_return_alloc(jitdata *jd, stackelement_t* stackslot)
296 {
297         /* XXX */
298 }
299
300
301 /*
302  * These are local overrides for various environment variables in Emacs.
303  * Please do not remove this and leave it at the end of the file, where
304  * Emacs will automagically detect them.
305  * ---------------------------------------------------------------------
306  * Local variables:
307  * mode: c
308  * indent-tabs-mode: t
309  * c-basic-offset: 4
310  * tab-width: 4
311  * End:
312  */