* src/vm/jit/mips/md-abi.c (md_param_alloc_native)
[cacao.git] / src / vm / jit / mips / md-abi.c
1 /* src/vm/jit/mips/md-abi.c - functions for MIPS 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 8012 2007-06-05 10:14:29Z twisti $
26
27 */
28
29
30 #include "config.h"
31 #include "vm/types.h"
32
33 #include "vm/jit/mips/md-abi.h"
34
35 #include "vm/global.h"
36
37 #include "vm/jit/abi.h"
38
39 #include "vmcore/descriptor.h"
40
41
42 /* register descripton array **************************************************/
43
44 #if SIZEOF_VOID_P == 8
45
46 /* MIPS64 */
47
48 s4 nregdescint[] = {
49         REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
50         REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
51         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
52         REG_TMP, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
53         REG_END
54 };
55
56 const char *abi_registers_integer_name[] = {
57         "zero",  "at",    "v0",    "v1",    "a0",    "a1",    "a2",    "a3",
58         "a4",    "a5",    "a6",    "a7",    "t0",    "t1",    "t2",    "t3",
59         "s0",    "s1",    "s2",    "s3",    "s4",    "s5",    "s6",    "s7",
60         "t8",    "t9",    "k0",    "k1",    "gp",    "sp",    "s8",    "ra"
61 };
62
63 const s4 abi_registers_integer_argument[] = {
64         4,  /* a0  */
65         5,  /* a1  */
66         6,  /* a2  */
67         7,  /* a3  */
68         8,  /* a4  */
69         9,  /* a5  */
70         10, /* a6  */
71         11, /* a7  */
72 };
73
74 const s4 abi_registers_integer_saved[] = {
75         16, /* s0  */
76         17, /* s1  */
77         18, /* s2  */
78         19, /* s3  */
79         20, /* s4  */
80         21, /* s5  */
81         22, /* s6  */
82         23, /* s7  */
83 };
84
85 const s4 abi_registers_integer_temporary[] = {
86         12, /* t0  */
87         13, /* t1  */
88         14, /* t2  */
89         15, /* t3  */
90         24, /* t4  */
91 };
92
93
94 s4 nregdescfloat[] = {
95         /*  fv0,   ftmp1,   ftmp2,   ftmp3,     ft0,     ft1,     ft2,     ft3,   */
96         REG_RET, REG_RES, REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
97
98         /*  ft4,     ft5,     ft6,     ft7,     fa0,     fa1,     fa2,     fa3,   */
99         REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
100
101         /*  fa4,     fa5,     fa6,     fa7,     ft8,     ft9,    ft10,    ft11,   */
102         REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
103
104         /*  fs0,    ft12,     fs1,    ft13,     fs2,    ft14,     fs3     ft15    */
105         REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP, REG_SAV, REG_TMP,
106
107         REG_END
108 };
109
110 const s4 abi_registers_float_argument[] = {
111         12, /* fa0  */
112         13, /* fa1  */
113         14, /* fa2  */
114         15, /* fa3  */
115         16, /* fa4  */
116         17, /* fa5  */
117         18, /* fa6  */
118         19, /* fa7  */
119 };
120
121 const s4 abi_registers_float_saved[] = {
122         24, /* fs0  */
123         26, /* fs1  */
124         28, /* fs2  */
125         30, /* fs3  */
126 };
127
128 const s4 abi_registers_float_temporary[] = {
129         4,  /* ft0  */
130         5,  /* ft1  */
131         6,  /* ft2  */
132         7,  /* ft3  */
133         8,  /* ft4  */
134         9,  /* ft5  */
135         10, /* ft6  */
136         11, /* ft7  */
137         20, /* ft8  */
138         21, /* ft9  */
139         22, /* ft10 */
140         23, /* ft11 */
141         25, /* ft12 */
142         27, /* ft13 */
143         29, /* ft14 */
144         31, /* ft15 */
145 };
146
147 #else /* SIZEOF_VOID_P == 8 */
148
149 /* MIPS32 */
150
151 s4 nregdescint[] = {
152         /* zero,   itmp1,      v0,      v1,      a0,      a1,      a2,      a3,   */
153         REG_RES, REG_RES, REG_RET, REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
154
155         /*   t0,      t1,      t2,      t3,      t4,      t5,      t6,      t7,   */
156         REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
157
158         /*   s0,      s1,      s2,      s3,      s4,      s5,      s6,      s7,   */
159         REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
160
161         /*itmp2,   itmp3, k0(sys), k1(sys),      gp,      sp,      pv,      ra    */
162         REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
163
164         REG_END
165 };
166
167 const char *abi_registers_integer_name[] = {
168         "zero",  "at",    "v0",    "v1",    "a0",    "a1",    "a2",    "a3",
169         "a4",    "a5",    "a6",    "a7",    "t0",    "t1",    "t2",    "t3",
170         "s0",    "s1",    "s2",    "s3",    "s4",    "s5",    "s6",    "s7",
171         "t8",    "t9",    "k0",    "k1",    "gp",    "sp",    "s8",    "ra"
172 };
173
174 const s4 abi_registers_integer_argument[] = {
175         4,  /* a0  */
176         5,  /* a1  */
177         6,  /* a2  */
178         7,  /* a3  */
179 };
180
181 const s4 abi_registers_integer_saved[] = {
182         16, /* s0  */
183         17, /* s1  */
184         18, /* s2  */
185         19, /* s3  */
186         20, /* s4  */
187         21, /* s5  */
188         22, /* s6  */
189         23, /* s7  */
190 };
191
192 const s4 abi_registers_integer_temporary[] = {
193         8,  /* t0  */
194         9,  /* t1  */
195         10, /* t2  */
196         11, /* t3  */
197         12, /* t4  */
198         13, /* t5  */
199         14, /* t6  */
200         15, /* t7  */
201 };
202
203
204 #if !defined(ENABLE_SOFT_FLOAT)
205
206 s4 nregdescfloat[] = {
207         /*  fv0,            ftmp1,            ftmp2,            ftmp3,            */
208         REG_RET, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES, REG_RES,
209
210         /*  ft0,              ft1,              fa0,              fa1,            */
211         REG_TMP, REG_RES, REG_TMP, REG_RES, REG_ARG, REG_RES, REG_ARG, REG_RES,
212
213         /*  ft2,              ft3,              fs0,              fs1,            */
214         REG_TMP, REG_RES, REG_TMP, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
215
216         /*  fs2,              fs3,              fs4,              fs5             */
217         REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES, REG_SAV, REG_RES,
218
219         REG_END
220 };
221
222 const s4 abi_registers_float_argument[] = {
223         12, /* fa0  */
224         14, /* fa1  */
225 };
226
227 const s4 abi_registers_float_saved[] = {
228         20, /* fs0  */
229         22, /* fs1  */
230         24, /* fs2  */
231         26, /* fs3  */
232         28, /* fs4  */
233         30, /* fs5  */
234 };
235
236 const s4 abi_registers_float_temporary[] = {
237         8,  /* ft0  */
238         10, /* ft1  */
239         16, /* ft2  */
240         18, /* ft3  */
241 };
242
243
244 #else /* !defined(ENABLE_SOFT_FLOAT) */
245
246 s4 nregdescfloat[] = {
247         REG_END
248 };
249
250 #endif /* !defined(ENABLE_SOFT_FLOAT) */
251
252 #endif /* SIZEOF_VOID_P == 8 */
253
254
255 /* md_param_alloc **************************************************************
256
257    Pre-allocate arguments according to the internal JIT ABI.
258
259 *******************************************************************************/
260
261 void md_param_alloc(methoddesc *md)
262 {
263         paramdesc *pd;
264         s4         i;
265         s4         reguse;
266         s4         stacksize;
267
268         /* set default values */
269
270         reguse      = 0;
271         stacksize   = 0;
272
273         /* get params field of methoddesc */
274
275         pd = md->params;
276
277 #if SIZEOF_VOID_P == 8
278
279         for (i = 0; i < md->paramcount; i++, pd++) {
280                 switch (md->paramtypes[i].type) {
281                 case TYPE_INT:
282                 case TYPE_ADR:
283                 case TYPE_LNG:
284                         if (i < INT_ARG_CNT) {
285                                 pd->inmemory = false;
286                                 pd->regoff   = abi_registers_integer_argument[reguse];
287                                 reguse++;
288                                 md->argintreguse = reguse;
289                         }
290                         else {
291                                 pd->inmemory = true;
292                                 pd->regoff   = stacksize;
293                                 stacksize++;
294                         }
295                         break;
296                 case TYPE_FLT:
297                 case TYPE_DBL:
298                         if (i < FLT_ARG_CNT) {
299                                 pd->inmemory = false;
300                                 pd->regoff   = abi_registers_float_argument[reguse];
301                                 reguse++;
302                                 md->argfltreguse = reguse;
303                         }
304                         else {
305                                 pd->inmemory = true;
306                                 pd->regoff   = stacksize;
307                                 stacksize++;
308                         }
309                         break;
310                 }
311
312                 /* register type is the same as java type */
313
314                 pd->type = md->paramtypes[i].type;
315         }
316
317 #else /* SIZEOF_VOID_P == 8 */
318
319 # if !defined(ENABLE_SOFT_FLOAT)
320
321         /* Set stacksize to 2, as 4 32-bit argument registers can be
322            stored. */
323         /* XXX maybe this should be done in stack.c? */
324
325         stacksize = 2;
326
327         for (i = 0; i < md->paramcount; i++, pd++) {
328                 switch (md->paramtypes[i].type) {
329                 case TYPE_INT:
330                 case TYPE_ADR:
331                         if (reguse < INT_ARG_CNT) {
332                                 pd->inmemory = false;
333                                 pd->regoff   = abi_registers_integer_argument[reguse];
334                                 reguse++;
335                                 md->argintreguse = reguse;
336                         }
337                         else {
338                                 pd->inmemory = true;
339                                 pd->regoff   = stacksize;
340                                 stacksize++;
341                         }
342                         break;
343
344                 case TYPE_LNG:
345                         ALIGN_2(reguse);
346
347                         if (reguse < INT_ARG_CNT) {
348                                 pd->inmemory = false;
349 #  if WORDS_BIGENDIAN == 1
350                                 pd->regoff   =
351                                         PACK_REGS(abi_registers_integer_argument[reguse + 1],
352                                                           abi_registers_integer_argument[reguse]);
353 #  else
354                                 pd->regoff   =
355                                         PACK_REGS(abi_registers_integer_argument[reguse],
356                                                           abi_registers_integer_argument[reguse + 1]);
357 #  endif
358                                 reguse += 2;
359                                 md->argintreguse = reguse;
360                         }
361                         else {
362                                 pd->inmemory = true;
363                                 pd->regoff   = stacksize;
364                                 stacksize++;
365                         }
366                         break;
367
368                 case TYPE_FLT:
369                 case TYPE_DBL:
370                         if (reguse < FLT_ARG_CNT) {
371                                 pd->inmemory = false;
372                                 pd->regoff   = abi_registers_float_argument[reguse];
373                                 reguse++;
374                                 md->argfltreguse = reguse;
375                         }
376                         else {
377                                 pd->inmemory = true;
378                                 pd->regoff   = stacksize;
379                                 stacksize++;
380                         }
381                         break;
382                 }
383
384                 /* register type is the same as java type */
385
386                 pd->type = md->paramtypes[i].type;
387         }
388
389 # else /* !defined(ENABLE_SOFT_FLOAT) */
390 #  error never actually tested!
391
392         for (i = 0; i < md->paramcount; i++, pd++) {
393                 switch (md->paramtypes[i].type) {
394                 case TYPE_INT:
395                 case TYPE_ADR:
396                 case TYPE_FLT:
397                         pd->type = TYPE_INT;
398
399                         if (reguse < INT_ARG_CNT) {
400                                 pd->inmemory = false;
401                                 pd->regoff   = abi_registers_integer_argument[reguse];
402                                 reguse++;
403                                 md->argintreguse = reguse;
404                         }
405                         else {
406                                 pd->inmemory = true;
407                                 pd->regoff   = stacksize;
408                         }
409                         stacksize++;
410                         break;
411
412                 case TYPE_LNG:
413                 case TYPE_DBL:
414                         pd->type = TYPE_LNG;
415
416                         if (reguse < INT_ARG_CNT) {
417                                 pd->inmemory = false;
418 #  if WORDS_BIGENDIAN == 1
419                                 pd->regoff   =
420                                         PACK_REGS(abi_registers_integer_argument[reguse + 1],
421                                                           abi_registers_integer_argument[reguse]);
422 #  else
423                                 pd->regoff   =
424                                         PACK_REGS(abi_registers_integer_argument[reguse],
425                                                           abi_registers_integer_argument[reguse + 1]);
426 #  endif
427                                 reguse += 2;
428                                 md->argintreguse = reguse;
429                         }
430                         else {
431                                 pd->inmemory = true;
432                                 pd->regoff   = stacksize;
433                         }
434                         stacksize += 2;
435                         break;
436                 }
437         }
438
439 # endif /* !defined(ENABLE_SOFT_FLOAT) */
440 #endif /* SIZEOF_VOID_P == 8 */
441
442         /* fill register and stack usage */
443
444         md->memuse = stacksize;
445 }
446
447
448 /* md_param_alloc_native *******************************************************
449
450    Pre-allocate arguments according the native ABI.
451
452 *******************************************************************************/
453
454 void md_param_alloc_native(methoddesc *md)
455 {
456 #if SIZEOF_VOID_P == 8
457
458         /* On MIPS n64 we use the same ABI for JIT method calls as for
459            native method calls. */
460
461         md_param_alloc(md);
462
463 #else /* SIZEOF_VOID_P == 8 */
464
465         paramdesc *pd;
466         s4         i;
467         s4         reguse;
468         s4         stacksize;
469 # if !defined(ENABLE_SOFT_FLOAT)
470         s4         t;
471         bool       a0_is_float;
472 # endif
473
474         /* set default values */
475
476         reguse      = 0;
477         stacksize   = 0;
478 # if !defined(ENABLE_SOFT_FLOAT)
479         a0_is_float = false;
480 # endif
481
482         /* get params field of methoddesc */
483
484         pd = md->params;
485
486 # if !defined(ENABLE_SOFT_FLOAT)
487
488         for (i = 0; i < md->paramcount; i++, pd++) {
489                 t = md->paramtypes[i].type;
490
491                 if (IS_FLT_DBL_TYPE(t) &&
492                         ((i == 0) ||
493                          ((i == 1) && IS_FLT_DBL_TYPE(md->paramtypes[0].type)))) {
494                         if (IS_2_WORD_TYPE(t)) {
495                                 pd->type   = TYPE_DBL;
496                                 pd->regoff = abi_registers_float_argument[reguse];
497                                 reguse++;
498                                 stacksize += 2;
499                         }
500                         else {
501                                 pd->type   = TYPE_FLT;
502                                 pd->regoff = abi_registers_float_argument[reguse];
503                                 reguse++;
504                                 stacksize++;
505                         }
506                         md->argfltreguse = reguse;
507                         a0_is_float = true;
508                 }
509                 else {
510                         if (IS_2_WORD_TYPE(t)) {
511                                 ALIGN_2(reguse);
512                                 pd->type = TYPE_LNG;
513
514                                 if (reguse < INT_ARG_CNT) {
515                                         pd->inmemory = false;
516 #  if WORDS_BIGENDIAN == 1
517                                         pd->regoff   =
518                                                 PACK_REGS(abi_registers_integer_argument[reguse + 1],
519                                                                   abi_registers_integer_argument[reguse]);
520 #  else
521                                         pd->regoff   =
522                                                 PACK_REGS(abi_registers_integer_argument[reguse],
523                                                                   abi_registers_integer_argument[reguse + 1]);
524 #  endif
525                                         reguse += 2;
526                                         md->argintreguse = reguse;
527                                 }
528                                 else {
529                                         ALIGN_2(stacksize);
530
531                                         pd->inmemory = true;
532                                         pd->regoff   = stacksize;
533                                 }
534                                 stacksize += 2;
535                         }
536                         else {
537                                 pd->type = TYPE_INT;
538
539                                 if (reguse < INT_ARG_CNT) {
540                                         pd->inmemory = false;
541                                         pd->regoff   = abi_registers_integer_argument[reguse];
542                                         reguse++;
543                                         md->argintreguse = reguse;
544                                 }
545                                 else {
546                                         pd->inmemory = true;
547                                         pd->regoff   = stacksize;
548                                 }
549                                 stacksize++;
550                         }
551                 }
552         }
553
554 # else /* !defined(ENABLE_SOFT_FLOAT) */
555 #  error never actually tested!
556
557         for (i = 0; i < md->paramcount; i++, pd++) {
558                 switch (md->paramtypes[i].type) {
559                 case TYPE_INT:
560                 case TYPE_ADR:
561                 case TYPE_FLT:
562                         pd->type = TYPE_INT;
563
564                         if (i < INT_ARG_CNT) {
565                                 pd->inmemory = false;
566                                 pd->regoff   = abi_registers_integer_argument[reguse];
567                                 reguse++;
568                                 md->argintreguse = reguse;
569                         }
570                         else {
571                                 pd->inmemory = true;
572                                 pd->regoff   = stacksize;
573                         }
574                         stacksize++;
575                         break;
576                 case TYPE_LNG:
577                 case TYPE_DBL:
578                         pd->type = TYPE_LNG;
579
580                         if (i < INT_ARG_CNT) {
581                                 pd->inmemory = false;
582 #  if WORDS_BIGENDIAN == 1
583                                 pd->regoff   =
584                                         PACK_REGS(abi_registers_integer_argument[reguse + 1],
585                                                           abi_registers_integer_argument[reguse]);
586 #  else
587                                 pd->regoff   =
588                                         PACK_REGS(abi_registers_integer_argument[reguse],
589                                                           abi_registers_integer_argument[reguse + 1]);
590 #  endif
591                                 reguse += 2;
592                                 md->argintreguse = reguse;
593                         }
594                         else {
595                                 pd->inmemory = true;
596                                 pd->regoff   = stacksize;
597                         }
598                         stacksize += 2;
599                         break;
600                 }
601         }
602
603 # endif /* !defined(ENABLE_SOFT_FLOAT) */
604
605         /* fill register and stack usage */
606
607         md->memuse = stacksize;
608
609 #endif /* SIZEOF_VOID_P == 8 */
610 }
611
612
613 /* md_return_alloc *************************************************************
614
615    Precolor the Java Stackelement containing the Return Value. Since
616    mips has a dedicated return register (not an reused arg or reserved
617    reg), this is striaghtforward possible, as long, as this
618    stackelement does not have to survive a method invokation
619    (SAVEDVAR)
620
621    --- in
622    jd:                      jitdata of the current method
623    stackslot:               Java Stackslot to contain the Return Value
624    
625    --- out
626    if precoloring was possible:
627    VAR(stackslot->varnum)->flags       = PREALLOC
628                                      ->regoff      = [REG_RESULT|REG_FRESULT]
629
630 *******************************************************************************/
631
632 void md_return_alloc(jitdata *jd, stackptr stackslot)
633 {
634         methodinfo *m;
635         methoddesc *md;
636
637         /* get required compiler data */
638
639         m = jd->m;
640
641         md = m->parseddesc;
642
643         /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
644            not to survive method invokations. */
645
646         if (!(stackslot->flags & SAVEDVAR)) {
647                 VAR(stackslot->varnum)->flags = PREALLOC;
648
649                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
650 #if SIZEOF_VOID_P == 4
651                         if (IS_2_WORD_TYPE(md->returntype.type))
652                                 VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
653                         else
654 #endif
655                                 VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
656                 }
657                 else
658                         VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
659         }
660 }
661
662
663 /*
664  * These are local overrides for various environment variables in Emacs.
665  * Please do not remove this and leave it at the end of the file, where
666  * Emacs will automagically detect them.
667  * ---------------------------------------------------------------------
668  * Local variables:
669  * mode: c
670  * indent-tabs-mode: t
671  * c-basic-offset: 4
672  * tab-width: 4
673  * End:
674  */