7e203809262a69176872479ee63d1d0a13d14ba2
[cacao.git] / src / vm / jit / powerpc / linux / md-abi.c
1 /* src/vm/jit/powerpc/linux/md-abi.c - functions for PowerPC Linux ABI
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Christian Thalinger
28
29    Changes: Christian Ullrich
30
31    $Id: md-abi.c 2928 2005-07-07 16:35:34Z christian $
32
33 */
34
35
36 #include "vm/jit/powerpc/types.h"
37 #include "vm/jit/powerpc/linux/md-abi.h"
38
39 #include "vm/descriptor.h"
40 #include "vm/global.h"
41
42
43 #define _ALIGN(a)    do { if ((a) & 1) (a)++; } while (0)
44
45
46 /* md_param_alloc **************************************************************
47
48  Allocate Arguments to Stackslots according the Calling Conventions
49
50 --- in
51 md->paramcount:           Number of arguments for this method
52 md->paramtypes[].type:    Argument types
53
54 --- out
55 md->params[].inmemory:    Argument spilled on stack
56 md->params[].regoff:      Stack offset or rd->arg[int|flt]regs index
57 md->memuse:               Stackslots needed for argument spilling
58 md->argintreguse:         max number of integer arguments used
59 md->argfltreguse:         max number of float arguments used
60
61 *******************************************************************************/
62
63 void md_param_alloc(methoddesc *md)
64 {
65         paramdesc *pd;
66         s4         i;
67         s4         iarg;
68         s4         farg;
69         s4         stacksize;
70
71         /* set default values */
72
73         iarg = 0;
74         farg = 0;
75         stacksize = LA_WORD_SIZE;
76
77         /* get params field of methoddesc */
78
79         pd = md->params;
80
81         for (i = 0; i < md->paramcount; i++, pd++) {
82                 switch (md->paramtypes[i].type) {
83                 case TYPE_INT:
84                 case TYPE_ADR:
85                         if (iarg < INT_ARG_CNT) {
86                                 pd->inmemory = false;
87                                 pd->regoff = iarg;
88                                 iarg++;
89                         } else {
90                                 pd->inmemory = true;
91                                 pd->regoff = stacksize;
92                                 stacksize++;
93                         }
94                         break;
95                 case TYPE_LNG:
96                         if (iarg < INT_ARG_CNT - 1) {
97                                 _ALIGN(iarg);
98                                 pd->inmemory = false;
99                                                              /* rd->arg[int|flt]regs index !! */
100                                 pd->regoff = PACK_REGS(iarg + 1, iarg); 
101                                 iarg += 2;
102                         } else {
103                                 _ALIGN(stacksize);
104                                 pd->inmemory = true;
105                                 pd->regoff = stacksize;
106                                 iarg = INT_ARG_CNT;
107                                 stacksize += 2;
108                         }
109                         break;
110                 case TYPE_FLT:
111                         if (farg < FLT_ARG_CNT) {
112                                 pd->inmemory = false;
113                                 pd->regoff = farg;
114                                 farg++;
115                         } else {
116                                 pd->inmemory = true;
117                                 pd->regoff = stacksize;
118                                 stacksize++;
119                         }
120                         break;
121                 case TYPE_DBL:
122                         if (farg < FLT_ARG_CNT) {
123                                 pd->inmemory = false;
124                                 pd->regoff = farg;
125                                 farg++;
126                         } else {
127                                 _ALIGN(stacksize);
128                                 pd->inmemory = true;
129                                 pd->regoff = stacksize;
130                                 stacksize += 2;
131                         }
132                         break;
133                 }
134         }
135
136         /* Since R3/R4, F1 (==A0/A1, A0) are used for passing return values, this */
137         /* argument register usage has to be regarded, too                        */
138         if (IS_INT_LNG_TYPE(md->returntype.type)) {
139                 if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1))
140                         iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1;
141         } else {
142                 if (IS_FLT_DBL_TYPE(md->returntype.type))
143                         if (farg < 1)
144                                 farg = 1;
145         }
146
147         /* fill register and stack usage */
148
149         md->argintreguse = iarg;
150         md->argfltreguse = farg;
151         md->memuse = stacksize;
152 }
153
154 /* md_return_alloc *************************************************************
155
156  Precolor the Java Stackelement containing the Return Value, if possible.
157  (R3==a00 for int/adr, R4/R3 == a01/a00 for long, F1==a00 for float/double)
158
159 --- in
160 m:                       Methodinfo of current method
161 return_type:             Return Type of the Method (TYPE_INT.. TYPE_ADR)
162                          TYPE_VOID is not allowed!
163 stackslot:               Java Stackslot to contain the Return Value
164
165 --- out
166 if precoloring was possible:
167 stackslot->varkind       =ARGVAR
168          ->varnum        =-1
169                  ->flags         =0
170                  ->regoff        =[REG_RESULT, (REG_RESULT2/REG_RESULT), REG_FRESULT]
171 rd->arg[flt|int]reguse   set to a value according the register usage
172                                  
173
174 *******************************************************************************/
175 void md_return_alloc(methodinfo *m, registerdata *rd, s4 return_type,
176                                          stackptr stackslot) {
177         /* In Leafmethods Local Vars holding parameters are precolored to their   */
178         /* argument register -> so leafmethods with paramcount > 0 could already  */
179         /* use  R3 == a00! */
180         if (!m->isleafmethod || (m->paramcount == 0)) {
181                 /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has not   */
182                 /* to survive method invokations */
183                 if (!(stackslot->flags & SAVEDVAR)) {
184                         stackslot->varkind = ARGVAR;
185                         stackslot->varnum = -1;
186                         stackslot->flags = 0;
187                         if ( IS_INT_LNG_TYPE(return_type) ) {
188                                 if (!IS_2_WORD_TYPE(return_type)) {
189                                         if (rd->argintreguse < 1) rd->argintreguse = 1;
190                                         stackslot->regoff = REG_RESULT;
191                                 } else {
192                                         if (rd->argintreguse < 2) rd->argintreguse = 2;
193                                         stackslot->regoff = PACK_REGS(REG_RESULT2, REG_RESULT);
194                                 }
195                         } else { /* float/double */
196                                 if (rd->argfltreguse < 1) rd->argfltreguse = 1;
197                                 stackslot->regoff = REG_FRESULT;
198                         }
199                 }
200         }
201 }
202
203 /*
204  * These are local overrides for various environment variables in Emacs.
205  * Please do not remove this and leave it at the end of the file, where
206  * Emacs will automagically detect them.
207  * ---------------------------------------------------------------------
208  * Local variables:
209  * mode: c
210  * indent-tabs-mode: t
211  * c-basic-offset: 4
212  * tab-width: 4
213  * End:
214  */