* Removed all Id tags.
[cacao.git] / src / vm / jit / powerpc / netbsd / md-abi.c
1 /* src/vm/jit/powerpc/netbsd/md-abi.c - functions for PowerPC NetBSD ABI
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28
29    Changes: Christian Ullrich
30
31 */
32
33
34 #include "config.h"
35 #include "vm/types.h"
36
37 #include "vm/jit/powerpc/netbsd/md-abi.h"
38
39 #include "vm/descriptor.h"
40 #include "vm/global.h"
41 #include "vm/jit/abi.h"
42
43
44 #define _ALIGN(a)    do { if ((a) & 1) (a)++; } while (0)
45
46
47 /* register descripton array **************************************************/
48
49 s4 nregdescint[] = {
50         /* zero,      sp, NO(sys),   a0/v0,   a0/v1,      a2,      a3,      a4,   */
51         REG_RES, REG_RES, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
52
53         /*   a5,      a6,      a7,   itmp1,   itmp2,      pv,      s0,      s1,   */
54         REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
55
56         /*itmp3,      t0,      t1,      t2,      t3,      t4,      t5,      t6,   */
57         REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
58
59         /*   s2,      s3,      s4,      s5,      s6,      s7,      s8,      s9,   */
60         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
61
62         REG_END
63 };
64
65
66 s4 nregdescfloat[] = {
67         /*ftmp3,  fa0/v0,     fa1,     fa2,     fa3,     fa4,     fa5,     fa6,   */
68         REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
69
70         /*  fa7,     ft0,     ft1,     ft2,     ft3,     ft4,     fs0,     fs1,   */
71         REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_SAV, REG_SAV,
72
73         /*ftmp1,   ftmp2,     ft5,     ft6,     ft7,     ft8,     ft9,    ft10,   */
74         REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
75
76         /*  fs2,     fs3,     fs4,     fs5,     fs6,     fs7,     fs8,     fs9    */
77         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
78
79         REG_END
80 };
81
82
83 /* md_param_alloc **************************************************************
84
85    Allocate Arguments to Stackslots according the Calling Conventions
86
87    --- in
88    md->paramcount:           Number of arguments for this method
89    md->paramtypes[].type:    Argument types
90
91    --- out
92    md->params[].inmemory:    Argument spilled on stack
93    md->params[].regoff:      Stack offset or rd->arg[int|flt]regs index
94    md->memuse:               Stackslots needed for argument spilling
95    md->argintreguse:         max number of integer arguments used
96    md->argfltreguse:         max number of float arguments used
97
98 *******************************************************************************/
99
100 void md_param_alloc(methoddesc *md)
101 {
102         paramdesc *pd;
103         s4         i;
104         s4         iarg;
105         s4         farg;
106         s4         stacksize;
107
108         /* set default values */
109
110         iarg = 0;
111         farg = 0;
112         stacksize = LA_WORD_SIZE;
113
114         /* get params field of methoddesc */
115
116         pd = md->params;
117
118         for (i = 0; i < md->paramcount; i++, pd++) {
119                 switch (md->paramtypes[i].type) {
120                 case TYPE_INT:
121                 case TYPE_ADR:
122                         if (iarg < INT_ARG_CNT) {
123                                 pd->inmemory = false;
124                                 pd->regoff = iarg;
125                                 iarg++;
126                         } else {
127                                 pd->inmemory = true;
128                                 pd->regoff = stacksize * 4;
129                                 stacksize++;
130                         }
131                         break;
132                 case TYPE_LNG:
133                         if (iarg < INT_ARG_CNT - 1) {
134                                 _ALIGN(iarg);
135                                 pd->inmemory = false;
136                                                              /* rd->arg[int|flt]regs index !! */
137                                 pd->regoff = PACK_REGS(iarg + 1, iarg); 
138                                 iarg += 2;
139                         } else {
140                                 _ALIGN(stacksize);
141                                 pd->inmemory = true;
142                                 pd->regoff = stacksize * 4;
143                                 iarg = INT_ARG_CNT;
144                                 stacksize += 2;
145                         }
146                         break;
147                 case TYPE_FLT:
148                         if (farg < FLT_ARG_CNT) {
149                                 pd->inmemory = false;
150                                 pd->regoff = farg;
151                                 farg++;
152                         } else {
153                                 pd->inmemory = true;
154                                 pd->regoff = stacksize * 4;
155                                 stacksize++;
156                         }
157                         break;
158                 case TYPE_DBL:
159                         if (farg < FLT_ARG_CNT) {
160                                 pd->inmemory = false;
161                                 pd->regoff = farg;
162                                 farg++;
163                         } else {
164                                 _ALIGN(stacksize);
165                                 pd->inmemory = true;
166                                 pd->regoff = stacksize * 4;
167                                 stacksize += 2;
168                         }
169                         break;
170                 }
171         }
172
173         /* Since R3/R4, F1 (==A0/A1, A0) are used for passing return values, this */
174         /* argument register usage has to be regarded, too                        */
175         if (IS_INT_LNG_TYPE(md->returntype.type)) {
176                 if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1))
177                         iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1;
178         } else {
179                 if (IS_FLT_DBL_TYPE(md->returntype.type))
180                         if (farg < 1)
181                                 farg = 1;
182         }
183
184         /* fill register and stack usage */
185
186         md->argintreguse = iarg;
187         md->argfltreguse = farg;
188         md->memuse = stacksize;
189 }
190
191
192 /* md_return_alloc *************************************************************
193
194    Precolor the Java Stackelement containing the Return Value, if
195    possible.  (R3==a00 for int/adr, R4/R3 == a01/a00 for long, F1==a00
196    for float/double)
197
198    --- in
199    jd:                      jitdata of current method
200    stackslot:               Java Stackslot to contain the Return Value
201
202    --- out
203    if precoloring was possible:
204    VAR(stackslot->varnum)->flags  = PREALLOC
205    VAR(stackslot->varnum)->vv.regoff = [REG_RESULT, (REG_RESULT2/REG_RESULT), REG_FRESULT]
206    rd->arg[flt|int]reguse   set to a value according the register usage
207
208 *******************************************************************************/
209
210 void md_return_alloc(jitdata *jd, stackptr stackslot)
211 {
212         methodinfo   *m;
213         registerdata *rd;
214         methoddesc   *md;
215
216         /* get required compiler data */
217
218         m  = jd->m;
219         rd = jd->rd;
220
221         md = m->parseddesc;
222
223         /* In Leafmethods Local Vars holding parameters are precolored to
224            their argument register -> so leafmethods with paramcount > 0
225            could already use R3 == a00! */
226
227         if (!m->isleafmethod || (md->paramcount == 0)) {
228                 /* Only precolor the stackslot, if it is not a SAVEDVAR <->
229                    has not to survive method invokations. */
230
231                 if (!(stackslot->flags & SAVEDVAR)) {
232
233                         VAR(stackslot->varnum)->flags = PREALLOC;
234
235                         if (IS_INT_LNG_TYPE(md->returntype.type)) {
236                                 if (!IS_2_WORD_TYPE(md->returntype.type)) {
237                                         if (rd->argintreguse < 1)
238                                                 rd->argintreguse = 1;
239
240                                         VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
241
242                                 } else {
243                                         if (rd->argintreguse < 2)
244                                                 rd->argintreguse = 2;
245
246                                         VAR(stackslot->varnum)->vv.regoff = PACK_REGS(REG_RESULT2, REG_RESULT);
247                                 }
248
249                         } else { /* float/double */
250                                 if (rd->argfltreguse < 1)
251                                         rd->argfltreguse = 1;
252
253                                 VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
254                         }
255                 }
256         }
257 }
258
259
260 /*
261  * These are local overrides for various environment variables in Emacs.
262  * Please do not remove this and leave it at the end of the file, where
263  * Emacs will automagically detect them.
264  * ---------------------------------------------------------------------
265  * Local variables:
266  * mode: c
267  * indent-tabs-mode: t
268  * c-basic-offset: 4
269  * tab-width: 4
270  * End:
271  */