Added some missing vim modelines.
[cacao.git] / src / vm / jit / s390 / md-abi.c
1 /* src/vm/jit/s390/md-abi.c - s390 Linux 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
28 #include "vm/descriptor.hpp"
29 #include "vm/global.h"
30 #include "vm/types.h"
31
32 #include "vm/jit/jit.hpp"
33 #include "vm/jit/stack.h"
34
35 #include "vm/jit/s390/md-abi.h"
36
37 #include <assert.h>
38
39
40 /* register descripton array **************************************************/
41
42 s4 nregdescint[] = {
43         /*itmp3,   itmp1,      a0,      a1,      a2,      a3,      a4,      s0, */
44         REG_RES, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV,
45         /*   s1,      s2,      s3,      s4,      s5,    pv,  ra/itmp2,      sp */
46         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_RES, REG_RES, REG_RES,
47     REG_END
48 };
49
50 const char *abi_registers_integer_name[] = {
51         "r0", "r1", "r2", "r3",
52         "r4", "r5", "r6", "r7",
53         "r8", "r9", "r10", "r11",
54         "r12", "r13", "r14", "r15"
55 };
56
57 const s4 abi_registers_integer_argument[] = {
58         2, /* r2/a0 */
59         3, /* r3/a1 */
60         4, /* r4/a2 */
61         5, /* r5/a3 */
62         6  /* r6/a4 */
63 };
64
65 const s4 abi_registers_integer_saved[] = {
66         7,  /* r7/s0 */
67         8,  /* r8/s1 */
68         9,  /* r9/s2 */
69         10, /* r10/s3 */
70         11, /* r11/s4 */
71         12  /* r12/s5 */
72 };
73
74 const s4 abi_registers_integer_temporary[] = {
75         -1 /* none */
76 };
77
78 s4 nregdescfloat[] = {
79         REG_ARG, REG_TMP, REG_ARG, REG_TMP, REG_RES, REG_TMP, REG_RES, REG_TMP,
80         REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
81     REG_END
82 };
83
84 const s4 abi_registers_float_argument[] = {
85         0, /* f0/fa0 */
86         2  /* f2/fa2 */
87 };
88
89 const s4 abi_registers_float_saved[] = {
90         -1 /* none */
91 };
92
93 const s4 abi_registers_float_temporary[] = {
94         1,  /* f1/ft0 */
95         3,  /* f3/ft1 */
96         5,  /* f5/ft2 */
97         7,  /* f7/ft3 */
98         8,  /* f8/ft4 */
99         9,  /* f9/ft5 */
100         10, /* f10/ft6 */
101         11, /* f11/ft7 */
102         12, /* f12/ft8 */
103         13, /* f13/ft9 */
104         14, /* f14/ft10 */
105         15  /* f15/ft11 */
106 };
107
108 /* md_param_alloc_intern *******************************************************
109
110    Allocates parameters to registers or stackslots for both native and java
111    methods.
112
113    --- in:
114    slot: size in bytes of a stack slot
115    slots1w: number of stack slots used by a 1 word type parameter
116    slots2w: number of stack slots used by a 2 word type parameter
117    stackoff: offset on stack frame where to start placing arguments
118
119 *******************************************************************************/
120
121 static void md_param_alloc_intern(methoddesc *md, s4 slot, s4 slots1w, s4 slots2w, s4 stackoff)
122 {
123         paramdesc *pd;
124         s4         i;
125         s4         iarg;
126         s4         farg;
127         s4         stacksize;
128
129         /* set default values */
130
131         iarg = 0;
132         farg = 0;
133         stacksize = 0;
134
135         /* get params field of methoddesc */
136
137         pd = md->params;
138
139         for (i = 0; i < md->paramcount; i++, pd++) {
140                 switch (md->paramtypes[i].type) {
141                 case TYPE_INT:
142                 case TYPE_ADR:
143                         if (iarg < INT_ARG_CNT) {
144                                 pd->inmemory  = false;
145                                 pd->regoff    = abi_registers_integer_argument[iarg]; 
146                                 pd->index     = iarg;
147                                 iarg++;
148                         }
149                         else {
150                                 pd->inmemory  = true;
151                                 pd->regoff    = (stacksize * slot) + stackoff;
152                                 pd->index     = stacksize;
153                                 stacksize += slots1w;
154                         }
155                         break;
156
157                 case TYPE_LNG:
158                         if (iarg < INT_ARG_CNT - 1) {
159                                 /* _ALIGN(iarg); */
160                                 pd->inmemory  = false;
161                                 pd->regoff    = 
162                                         PACK_REGS(abi_registers_integer_argument[iarg + 1], 
163                                                           abi_registers_integer_argument[iarg]); 
164                                 pd->index     = PACK_REGS(iarg + 1, iarg);
165                                 iarg += 2;
166                         }
167                         else {
168                                 /* _ALIGN(stacksize); */
169                                 pd->inmemory  = true;
170                                 pd->regoff    = (stacksize * slot) + stackoff;
171                                 pd->index     = stacksize;
172                                 iarg          = INT_ARG_CNT;
173                                 stacksize    += slots2w;
174                         }
175                         break;
176
177                 case TYPE_FLT:
178                         if (farg < FLT_ARG_CNT) {
179                                 pd->inmemory  = false;
180                                 pd->regoff    = abi_registers_float_argument[farg]; 
181                                 pd->index     = farg;
182                                 farg++;
183                         }
184                         else {
185                                 pd->inmemory  = true;
186                                 pd->regoff    = (stacksize * slot) + stackoff;
187                                 pd->index     = stacksize;
188                                 stacksize += slots1w;
189                         }
190                         break;
191
192                 case TYPE_DBL:
193                         if (farg < FLT_ARG_CNT) {
194                                 pd->inmemory  = false;
195                                 pd->regoff    = abi_registers_float_argument[farg]; 
196                                 pd->index     = farg;
197                                 farg++;
198                         }
199                         else {
200                                 /* _ALIGN(stacksize); */
201                                 pd->inmemory  = true;
202                                 pd->regoff    = (stacksize * slot) + stackoff;
203                                 pd->index     = stacksize;
204                                 stacksize    += slots2w;
205                         }
206                         break;
207
208                 default:
209                         assert(0);
210                 }
211         }
212
213         /* Since A0+A1/FA0 are used for passing return
214            values, this argument register usage has to be regarded,
215            too. */
216
217         if (IS_INT_LNG_TYPE(md->returntype.type)) {
218                 if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1))
219                         iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1;
220         }
221         else {
222                 if (IS_FLT_DBL_TYPE(md->returntype.type))
223                         if (farg < 1)
224                                 farg = 1;
225         }
226
227         /* fill register and stack usage */
228
229         md->argintreguse = iarg;
230         md->argfltreguse = farg;
231         md->memuse = stacksize;
232 }
233
234 void md_param_alloc(methoddesc *md)
235 {
236         md_param_alloc_intern(md, 8, 1, 1, 0);
237 }
238
239 void md_param_alloc_native(methoddesc *md)
240 {
241         md_param_alloc_intern(md, 4, 1, 2, 96);
242 }
243
244
245 /* md_return_alloc *************************************************************
246
247    Precolor the Java Stackelement containing the Return Value. Only
248    for float/ double types straight forward possible, since INT_LNG
249    types use "reserved" registers Float/Double values use a00 as
250    return register.
251
252    --- in
253    jd:                      jitdata of the current method
254    stackslot:               Java Stackslot to contain the Return Value
255
256    --- out
257    if precoloring was possible:
258    VAR(stackslot->varnum)->flags     = PREALLOC
259                                      ->vv.regoff = [REG_RESULT|REG_FRESULT]
260    rd->arg[flt|int]reguse   set to a value according the register usage
261
262    NOTE: Do not pass a LOCALVAR in stackslot->varnum.
263
264 *******************************************************************************/
265
266 void md_return_alloc(jitdata *jd, stackelement_t* stackslot)
267 {
268         methodinfo   *m;
269         codeinfo     *code;
270         registerdata *rd;
271         methoddesc   *md;
272
273         /* get required compiler data */
274
275         m    = jd->m;
276         code = jd->code;
277         rd   = jd->rd;
278
279         md = m->parseddesc;
280
281         /* In Leafmethods Local Vars holding parameters are precolored to
282            their argument register -> so leafmethods with paramcount > 0
283            could already use R3 == a00! */
284
285         if (!code_is_leafmethod(code) || (md->paramcount == 0)) {
286                 /* Only precolor the stackslot, if it is not a SAVEDVAR <->
287                    has not to survive method invokations. */
288
289                 if (!(stackslot->flags & SAVEDVAR)) {
290                         VAR(stackslot->varnum)->flags = PREALLOC;
291
292                         if (IS_INT_LNG_TYPE(md->returntype.type)) {
293                                 if (!IS_2_WORD_TYPE(md->returntype.type)) {
294                                         if (rd->argintreguse < 1)
295                                                 rd->argintreguse = 1;
296
297                                         VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
298                                 }
299                                 else {
300                                         if (rd->argintreguse < 2)
301                                                 rd->argintreguse = 2;
302
303                                         VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
304                                 }
305                         }
306                         else { /* float/double */
307                                 if (rd->argfltreguse < 1)
308                                         rd->argfltreguse = 1;
309
310                                 VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
311                         }
312                 }
313         }
314 }
315
316
317 /*
318  * These are local overrides for various environment variables in Emacs.
319  * Please do not remove this and leave it at the end of the file, where
320  * Emacs will automagically detect them.
321  * ---------------------------------------------------------------------
322  * Local variables:
323  * mode: c
324  * indent-tabs-mode: t
325  * c-basic-offset: 4
326  * tab-width: 4
327  * End:
328  * vim:noexpandtab:sw=4:ts=4:
329  */