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