Merged revisions 7940-8026 via svnmerge from
[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 8013 2007-06-05 10:19:09Z 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 (reguse < 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
297                 case TYPE_FLT:
298                 case TYPE_DBL:
299                         if (reguse < FLT_ARG_CNT) {
300                                 pd->inmemory = false;
301                                 pd->regoff   = abi_registers_float_argument[reguse];
302                                 reguse++;
303                                 md->argfltreguse = reguse;
304                         }
305                         else {
306                                 pd->inmemory = true;
307                                 pd->regoff   = stacksize;
308                                 stacksize++;
309                         }
310                         break;
311                 }
312
313                 /* register type is the same as java type */
314
315                 pd->type = md->paramtypes[i].type;
316         }
317
318 #else /* SIZEOF_VOID_P == 8 */
319
320 # if !defined(ENABLE_SOFT_FLOAT)
321
322         /* Set stacksize to 2, as 4 32-bit argument registers can be
323            stored. */
324         /* XXX maybe this should be done in stack.c? */
325
326         stacksize = 2;
327
328         for (i = 0; i < md->paramcount; i++, pd++) {
329                 switch (md->paramtypes[i].type) {
330                 case TYPE_INT:
331                 case TYPE_ADR:
332                         if (reguse < INT_ARG_CNT) {
333                                 pd->inmemory = false;
334                                 pd->regoff   = abi_registers_integer_argument[reguse];
335                                 reguse++;
336                                 md->argintreguse = reguse;
337                         }
338                         else {
339                                 pd->inmemory = true;
340                                 pd->regoff   = stacksize;
341                                 stacksize++;
342                         }
343                         break;
344
345                 case TYPE_LNG:
346                         ALIGN_2(reguse);
347
348                         if (reguse < INT_ARG_CNT) {
349                                 pd->inmemory = false;
350 #  if WORDS_BIGENDIAN == 1
351                                 pd->regoff   =
352                                         PACK_REGS(abi_registers_integer_argument[reguse + 1],
353                                                           abi_registers_integer_argument[reguse]);
354 #  else
355                                 pd->regoff   =
356                                         PACK_REGS(abi_registers_integer_argument[reguse],
357                                                           abi_registers_integer_argument[reguse + 1]);
358 #  endif
359                                 reguse += 2;
360                                 md->argintreguse = reguse;
361                         }
362                         else {
363                                 pd->inmemory = true;
364                                 pd->regoff   = stacksize;
365                                 stacksize++;
366                         }
367                         break;
368
369                 case TYPE_FLT:
370                 case TYPE_DBL:
371                         if (reguse < FLT_ARG_CNT) {
372                                 pd->inmemory = false;
373                                 pd->regoff   = abi_registers_float_argument[reguse];
374                                 reguse++;
375                                 md->argfltreguse = reguse;
376                         }
377                         else {
378                                 pd->inmemory = true;
379                                 pd->regoff   = stacksize;
380                                 stacksize++;
381                         }
382                         break;
383                 }
384
385                 /* register type is the same as java type */
386
387                 pd->type = md->paramtypes[i].type;
388         }
389
390 # else /* !defined(ENABLE_SOFT_FLOAT) */
391 #  error never actually tested!
392
393         for (i = 0; i < md->paramcount; i++, pd++) {
394                 switch (md->paramtypes[i].type) {
395                 case TYPE_INT:
396                 case TYPE_ADR:
397                 case TYPE_FLT:
398                         pd->type = TYPE_INT;
399
400                         if (reguse < INT_ARG_CNT) {
401                                 pd->inmemory = false;
402                                 pd->regoff   = abi_registers_integer_argument[reguse];
403                                 reguse++;
404                                 md->argintreguse = reguse;
405                         }
406                         else {
407                                 pd->inmemory = true;
408                                 pd->regoff   = stacksize;
409                         }
410                         stacksize++;
411                         break;
412
413                 case TYPE_LNG:
414                 case TYPE_DBL:
415                         pd->type = TYPE_LNG;
416
417                         if (reguse < INT_ARG_CNT) {
418                                 pd->inmemory = false;
419 #  if WORDS_BIGENDIAN == 1
420                                 pd->regoff   =
421                                         PACK_REGS(abi_registers_integer_argument[reguse + 1],
422                                                           abi_registers_integer_argument[reguse]);
423 #  else
424                                 pd->regoff   =
425                                         PACK_REGS(abi_registers_integer_argument[reguse],
426                                                           abi_registers_integer_argument[reguse + 1]);
427 #  endif
428                                 reguse += 2;
429                                 md->argintreguse = reguse;
430                         }
431                         else {
432                                 pd->inmemory = true;
433                                 pd->regoff   = stacksize;
434                         }
435                         stacksize += 2;
436                         break;
437                 }
438         }
439
440 # endif /* !defined(ENABLE_SOFT_FLOAT) */
441 #endif /* SIZEOF_VOID_P == 8 */
442
443         /* fill register and stack usage */
444
445         md->memuse = stacksize;
446 }
447
448
449 /* md_param_alloc_native *******************************************************
450
451    Pre-allocate arguments according the native ABI.
452
453 *******************************************************************************/
454
455 void md_param_alloc_native(methoddesc *md)
456 {
457 #if SIZEOF_VOID_P == 8
458
459         /* On MIPS n64 we use the same ABI for JIT method calls as for
460            native method calls. */
461
462         md_param_alloc(md);
463
464 #else /* SIZEOF_VOID_P == 8 */
465
466         paramdesc *pd;
467         s4         i;
468         s4         reguse;
469         s4         stacksize;
470 # if !defined(ENABLE_SOFT_FLOAT)
471         s4         t;
472         bool       a0_is_float;
473 # endif
474
475         /* set default values */
476
477         reguse      = 0;
478         stacksize   = 0;
479 # if !defined(ENABLE_SOFT_FLOAT)
480         a0_is_float = false;
481 # endif
482
483         /* get params field of methoddesc */
484
485         pd = md->params;
486
487 # if !defined(ENABLE_SOFT_FLOAT)
488
489         for (i = 0; i < md->paramcount; i++, pd++) {
490                 t = md->paramtypes[i].type;
491
492                 if (IS_FLT_DBL_TYPE(t) &&
493                         ((i == 0) ||
494                          ((i == 1) && IS_FLT_DBL_TYPE(md->paramtypes[0].type)))) {
495                         if (IS_2_WORD_TYPE(t)) {
496                                 pd->type   = TYPE_DBL;
497                                 pd->regoff = abi_registers_float_argument[reguse];
498                                 reguse++;
499                                 stacksize += 2;
500                         }
501                         else {
502                                 pd->type   = TYPE_FLT;
503                                 pd->regoff = abi_registers_float_argument[reguse];
504                                 reguse++;
505                                 stacksize++;
506                         }
507                         md->argfltreguse = reguse;
508                         a0_is_float = true;
509                 }
510                 else {
511                         if (IS_2_WORD_TYPE(t)) {
512                                 ALIGN_2(reguse);
513                                 pd->type = TYPE_LNG;
514
515                                 if (reguse < INT_ARG_CNT) {
516                                         pd->inmemory = false;
517 #  if WORDS_BIGENDIAN == 1
518                                         pd->regoff   =
519                                                 PACK_REGS(abi_registers_integer_argument[reguse + 1],
520                                                                   abi_registers_integer_argument[reguse]);
521 #  else
522                                         pd->regoff   =
523                                                 PACK_REGS(abi_registers_integer_argument[reguse],
524                                                                   abi_registers_integer_argument[reguse + 1]);
525 #  endif
526                                         reguse += 2;
527                                         md->argintreguse = reguse;
528                                 }
529                                 else {
530                                         ALIGN_2(stacksize);
531
532                                         pd->inmemory = true;
533                                         pd->regoff   = stacksize;
534                                 }
535                                 stacksize += 2;
536                         }
537                         else {
538                                 pd->type = TYPE_INT;
539
540                                 if (reguse < INT_ARG_CNT) {
541                                         pd->inmemory = false;
542                                         pd->regoff   = abi_registers_integer_argument[reguse];
543                                         reguse++;
544                                         md->argintreguse = reguse;
545                                 }
546                                 else {
547                                         pd->inmemory = true;
548                                         pd->regoff   = stacksize;
549                                 }
550                                 stacksize++;
551                         }
552                 }
553         }
554
555 # else /* !defined(ENABLE_SOFT_FLOAT) */
556 #  error never actually tested!
557
558         for (i = 0; i < md->paramcount; i++, pd++) {
559                 switch (md->paramtypes[i].type) {
560                 case TYPE_INT:
561                 case TYPE_ADR:
562                 case TYPE_FLT:
563                         pd->type = TYPE_INT;
564
565                         if (i < INT_ARG_CNT) {
566                                 pd->inmemory = false;
567                                 pd->regoff   = abi_registers_integer_argument[reguse];
568                                 reguse++;
569                                 md->argintreguse = reguse;
570                         }
571                         else {
572                                 pd->inmemory = true;
573                                 pd->regoff   = stacksize;
574                         }
575                         stacksize++;
576                         break;
577                 case TYPE_LNG:
578                 case TYPE_DBL:
579                         pd->type = TYPE_LNG;
580
581                         if (i < INT_ARG_CNT) {
582                                 pd->inmemory = false;
583 #  if WORDS_BIGENDIAN == 1
584                                 pd->regoff   =
585                                         PACK_REGS(abi_registers_integer_argument[reguse + 1],
586                                                           abi_registers_integer_argument[reguse]);
587 #  else
588                                 pd->regoff   =
589                                         PACK_REGS(abi_registers_integer_argument[reguse],
590                                                           abi_registers_integer_argument[reguse + 1]);
591 #  endif
592                                 reguse += 2;
593                                 md->argintreguse = reguse;
594                         }
595                         else {
596                                 pd->inmemory = true;
597                                 pd->regoff   = stacksize;
598                         }
599                         stacksize += 2;
600                         break;
601                 }
602         }
603
604 # endif /* !defined(ENABLE_SOFT_FLOAT) */
605
606         /* fill register and stack usage */
607
608         md->memuse = stacksize;
609
610 #endif /* SIZEOF_VOID_P == 8 */
611 }
612
613
614 /* md_return_alloc *************************************************************
615
616    Precolor the Java Stackelement containing the Return Value. Since
617    mips has a dedicated return register (not an reused arg or reserved
618    reg), this is striaghtforward possible, as long, as this
619    stackelement does not have to survive a method invokation
620    (SAVEDVAR)
621
622    --- in
623    jd:                      jitdata of the current method
624    stackslot:               Java Stackslot to contain the Return Value
625    
626    --- out
627    if precoloring was possible:
628    VAR(stackslot->varnum)->flags       = PREALLOC
629                                      ->regoff      = [REG_RESULT|REG_FRESULT]
630
631 *******************************************************************************/
632
633 void md_return_alloc(jitdata *jd, stackptr stackslot)
634 {
635         methodinfo *m;
636         methoddesc *md;
637
638         /* get required compiler data */
639
640         m = jd->m;
641
642         md = m->parseddesc;
643
644         /* Only precolor the stackslot, if it is not a SAVEDVAR <-> has
645            not to survive method invokations. */
646
647         if (!(stackslot->flags & SAVEDVAR)) {
648                 VAR(stackslot->varnum)->flags = PREALLOC;
649
650                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
651 #if SIZEOF_VOID_P == 4
652                         if (IS_2_WORD_TYPE(md->returntype.type))
653                                 VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
654                         else
655 #endif
656                                 VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
657                 }
658                 else
659                         VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
660         }
661 }
662
663
664 /*
665  * These are local overrides for various environment variables in Emacs.
666  * Please do not remove this and leave it at the end of the file, where
667  * Emacs will automagically detect them.
668  * ---------------------------------------------------------------------
669  * Local variables:
670  * mode: c
671  * indent-tabs-mode: t
672  * c-basic-offset: 4
673  * tab-width: 4
674  * End:
675  */