74a3ea914c21231ec928b4c35723f19fe5915f3e
[cacao.git] / src / vm / jit / powerpc / darwin / md-abi.c
1 /* src/vm/jit/powerpc/darwin/md-abi.c - functions for PowerPC Darwin ABI
2
3    Copyright (C) 1996-2005, 2006, 2007 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    $Id: md-abi.c 8270 2007-08-08 13:57:12Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <stdint.h>
33
34 #include "vm/jit/powerpc/darwin/md-abi.h"
35
36 #include "vm/global.h"
37
38 #include "vm/jit/abi.h"
39
40 #include "vmcore/descriptor.h"
41
42
43 /* register descripton arrays *************************************************/
44
45 int nregdescint[] = {
46         /* zero,      sp,      t0,   a0/v0,   a0/v1,      a2,      a3,      a4,   */
47         REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
48
49         /*   a5,      a6,      a7,   itmp1,   itmp2,      pv,      s0,      s1,   */
50         REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
51
52         /*itmp3,      t1,      t2,      t3,      t4,      t5,      t6,      t7,   */
53         REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
54
55         /*   s2,      s3,      s4,      s5,      s6,      s7,      s8,      s9,   */
56         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
57
58         REG_END
59 };
60
61 const char *abi_registers_integer_name[] = {
62         "r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
63         "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
64         "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
65         "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
66 };
67
68 const int abi_registers_integer_argument[] = {
69         3,  /* a0 */
70         4,  /* a1 */
71         5,  /* a2 */
72         6,  /* a3 */
73         7,  /* a4 */
74         8,  /* a5 */
75         9,  /* a6 */
76         10, /* a7 */
77 };
78
79 const int abi_registers_integer_saved[] = {
80         14, /* s0 */
81         15, /* s1 */
82         24, /* s2 */
83         25, /* s3 */
84         26, /* s4 */
85         27, /* s5 */
86         28, /* s6 */
87         29, /* s7 */
88         30, /* s8 */
89         31, /* s9 */
90 };
91
92 const int abi_registers_integer_temporary[] = {
93         2,  /* t0 */
94         17, /* t1 */
95         18, /* t2 */
96         19, /* t3 */
97         20, /* t4 */
98         21, /* t5 */
99         22, /* t6 */
100         23, /* t7 */
101 };
102
103
104 int nregdescfloat[] = {
105         /*ftmp3,  fa0/v0,     fa1,     fa2,     fa3,     fa4,     fa5,     fa6,   */
106         REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
107
108         /*  fa7,     fa8,     fa9,    fa10,    fa11,    fa12,     fs0,     fs1,   */
109         REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV,
110
111         /*ftmp1,   ftmp2,     ft0,     ft1,     ft2,     ft3,     ft4,     ft5,   */
112         REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
113
114         /*  fs2,     fs3,     fs4,     fs5,     fs6,     fs7,     fs8,     fs9    */
115         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
116
117         REG_END
118 };
119
120 const int abi_registers_float_argument[] = {
121         1,  /* fa0  */
122         2,  /* fa1  */
123         3,  /* fa2  */
124         4,  /* fa3  */
125         5,  /* fa4  */
126         6,  /* fa5  */
127         7,  /* fa6  */
128         8,  /* fa7  */
129         9,  /* fa8  */
130         10, /* fa9  */
131         11, /* fa10 */
132         12, /* fa11 */
133         13, /* fa12 */
134 };
135
136 const int abi_registers_float_saved[] = {
137         14, /* fs0  */
138         15, /* fs1  */
139         24, /* fs2  */
140         25, /* fs3  */
141         26, /* fs4  */
142         27, /* fs5  */
143         28, /* fs6  */
144         29, /* fs7  */
145         30, /* fs8  */
146         31, /* fs9  */
147 };
148
149 const int abi_registers_float_temporary[] = {
150         17, /* ft5  */
151         18, /* ft6  */
152         19, /* ft7  */
153         20, /* ft8  */
154         21, /* ft9  */
155         22, /* ft10 */
156         23, /* ft11 */
157 };
158
159
160 /* md_param_alloc **************************************************************
161
162    Allocate Arguments to Stackslots according the Calling Conventions
163
164    --- in
165    md->paramcount:           Number of arguments for this method
166    md->paramtypes[].type:    Argument types
167    
168    --- out
169    md->params[].inmemory:    Argument spilled on stack
170    md->params[].regoff:      Stack offset or rd->arg[int|flt]regs index
171    md->memuse:               Stackslots needed for argument spilling
172    md->argintreguse:         max number of integer arguments used
173    md->argfltreguse:         max number of float arguments used
174
175 *******************************************************************************/
176
177 void md_param_alloc(methoddesc *md)
178 {
179         paramdesc *pd;
180         int        i;
181         int        iarg;
182         int        farg;
183         int        stacksize;
184
185         /* set default values */
186
187         iarg      = 0;
188         farg      = 0;
189         stacksize = LA_SIZE_IN_POINTERS;
190
191         /* get params field of methoddesc */
192
193         pd = md->params;
194
195         for (i = 0; i < md->paramcount; i++, pd++) {
196                 switch (md->paramtypes[i].type) {
197                 case TYPE_INT:
198                 case TYPE_ADR:
199                         if (iarg < INT_ARG_CNT) {
200                                 pd->inmemory = false;
201                                 pd->index    = iarg;
202                                 pd->regoff   = abi_registers_integer_argument[iarg];
203                                 iarg++;
204                         }
205                         else {
206                                 pd->inmemory = true;
207                                 pd->index    = stacksize;
208                                 pd->regoff   = stacksize * 8;
209                                 stacksize++;
210                         }
211                         break;
212
213                 case TYPE_LNG:
214                         if (iarg < INT_ARG_CNT - 1) {
215                                 pd->inmemory = false;
216                                 pd->index    = PACK_REGS(iarg + 1, iarg);
217                                 pd->regoff   =
218                                         PACK_REGS(abi_registers_integer_argument[iarg + 1],
219                                                           abi_registers_integer_argument[iarg]);
220                                 iarg += 2;
221                         }
222                         else {
223                                 pd->inmemory = true;
224                                 pd->index    = stacksize;
225                                 pd->regoff   = stacksize * 8;
226                                 iarg         = INT_ARG_CNT;
227                                 stacksize++;
228                         }
229                         break;
230
231                 case TYPE_FLT:
232                 case TYPE_DBL:
233                         if (farg < FLT_ARG_CNT) {
234                                 pd->inmemory = false;
235                                 pd->index    = farg;
236                                 pd->regoff   = abi_registers_float_argument[farg];
237                                 farg++;
238                         }
239                         else {
240                                 pd->inmemory = true;
241                                 pd->index    = stacksize;
242                                 pd->regoff   = stacksize * 8;
243                                 stacksize++;
244                         }
245                         break;
246                 }
247         }
248
249
250         /* Since R3/R4, F1 (==A0/A1, A0) are used for passing return values, this */
251         /* argument register usage has to be regarded, too                        */
252
253         if (IS_INT_LNG_TYPE(md->returntype.type)) {
254                 if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1))
255                         iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1;
256         }
257         else {
258                 if (IS_FLT_DBL_TYPE(md->returntype.type))
259                         if (farg < 1)
260                                 farg = 1;
261         }
262
263         /* fill register and stack usage */
264
265         md->argintreguse = iarg;
266         md->argfltreguse = farg;
267         md->memuse       = stacksize;
268 }
269
270
271 /* md_param_alloc_native *******************************************************
272
273    Pre-allocate arguments according the native ABI.
274
275 *******************************************************************************/
276
277 void md_param_alloc_native(methoddesc *md)
278 {
279         paramdesc *pd;
280         int        i;
281         int        iarg;
282         int        farg;
283         int        stacksize;
284
285         /* set default values */
286
287         iarg      = 0;
288         farg      = 0;
289         stacksize = LA_SIZE_IN_POINTERS;
290
291         /* get params field of methoddesc */
292
293         pd = md->params;
294
295         for (i = 0; i < md->paramcount; i++, pd++) {
296                 switch (md->paramtypes[i].type) {
297                 case TYPE_INT:
298                 case TYPE_ADR:
299                         if (iarg < INT_ARG_CNT) {
300                                 pd->inmemory = false;
301                                 pd->regoff   = abi_registers_integer_argument[iarg];
302                                 iarg++;
303                         }
304                         else {
305                                 pd->inmemory = true;
306                                 pd->regoff   = stacksize * 4;
307                         }
308                         stacksize++;
309                         break;
310
311                 case TYPE_LNG:
312                         if (iarg < INT_ARG_CNT - 1) {
313                                 pd->inmemory = false;
314                                 pd->regoff   =
315                                         PACK_REGS(abi_registers_integer_argument[iarg + 1],
316                                                           abi_registers_integer_argument[iarg]);
317                                 iarg += 2;
318                         }
319                         else {
320                                 pd->inmemory = true;
321                                 pd->regoff   = stacksize * 4;
322                                 iarg         = INT_ARG_CNT;
323                         }
324                         stacksize += 2;
325                         break;
326
327                 case TYPE_FLT:
328                         if (farg < FLT_ARG_CNT) {
329                                 pd->inmemory = false;
330                                 pd->regoff   = abi_registers_float_argument[farg];
331                                 iarg++;                   /* skip 1 integer argument register */
332                                 farg++;
333                         }
334                         else {
335                                 pd->inmemory = true;
336                                 pd->regoff   = stacksize * 4;
337                         }
338                         stacksize++;
339                         break;
340
341                 case TYPE_DBL:
342                         if (farg < FLT_ARG_CNT) {
343                                 pd->inmemory = false;
344                                 pd->regoff   = abi_registers_float_argument[farg];
345                                 iarg += 2;               /* skip 2 integer argument registers */
346                                 farg++;
347                         }
348                         else {
349                                 pd->inmemory = true;
350                                 pd->regoff   = stacksize * 4;
351                         }
352                         stacksize += 2;
353                         break;
354                 }
355         }
356
357
358         /* Since R3/R4, F1 (==A0/A1, A0) are used for passing return values, this */
359         /* argument register usage has to be regarded, too                        */
360
361         if (IS_INT_LNG_TYPE(md->returntype.type)) {
362                 if (iarg < (IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1))
363                         iarg = IS_2_WORD_TYPE(md->returntype.type) ? 2 : 1;
364         }
365         else {
366                 if (IS_FLT_DBL_TYPE(md->returntype.type))
367                         if (farg < 1)
368                                 farg = 1;
369         }
370
371         /* fill register and stack usage */
372
373         md->argintreguse = iarg;
374         md->argfltreguse = farg;
375         md->memuse       = stacksize;
376 }
377
378
379 /* md_return_alloc *************************************************************
380
381    Precolor the Java Stackelement containing the Return Value, if
382    possible. (R3==a00 for int/adr, R4/R3 == a01/a00 for long, F1==a00
383    for float/double)
384
385    --- in
386    jd:                      jitdata of the current method
387    stackslot:               Java Stackslot to contain the Return Value
388    
389    --- out
390    if precoloring was possible:
391    VAR(stackslot->varnum)->flags  = PREALLOC
392                                      ->regoff = [REG_RESULT|REG_FRESULT]
393    rd->arg[flt|int]reguse   set to a value according the register usage
394
395    NOTE: Do not pass a LOCALVAR in stackslot->varnum.
396
397 *******************************************************************************/
398
399 void md_return_alloc(jitdata *jd, stackptr stackslot)
400 {
401         methodinfo   *m;
402         registerdata *rd;
403         methoddesc   *md;
404
405         /* get required compiler data */
406
407         m  = jd->m;
408         rd = jd->rd;
409
410         md = m->parseddesc;
411
412         /* In Leafmethods Local Vars holding parameters are precolored to
413            their argument register -> so leafmethods with paramcount > 0
414            could already use R3 == a00! */
415
416         if (!jd->isleafmethod || (md->paramcount == 0)) {
417                 /* Only precolor the stackslot, if it is not a SAVEDVAR <->
418                    has not to survive method invokations. */
419
420                 if (!(stackslot->flags & SAVEDVAR)) {
421
422                         VAR(stackslot->varnum)->flags = PREALLOC;
423
424                         if (IS_INT_LNG_TYPE(md->returntype.type)) {
425                                 if (!IS_2_WORD_TYPE(md->returntype.type)) {
426                                         if (rd->argintreguse < 1)
427                                                 rd->argintreguse = 1;
428
429                                         VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
430                                 }
431                                 else {
432                                         if (rd->argintreguse < 2)
433                                                 rd->argintreguse = 2;
434
435                                         VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
436                                 }
437                         }
438                         else {
439                                 if (rd->argfltreguse < 1)
440                                         rd->argfltreguse = 1;
441
442                                 VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
443                         }
444                 }
445         }
446 }
447
448
449 /*
450  * These are local overrides for various environment variables in Emacs.
451  * Please do not remove this and leave it at the end of the file, where
452  * Emacs will automagically detect them.
453  * ---------------------------------------------------------------------
454  * Local variables:
455  * mode: c
456  * indent-tabs-mode: t
457  * c-basic-offset: 4
458  * tab-width: 4
459  * End:
460  */