CACAO
md-abi.cpp
Go to the documentation of this file.
1 /* src/vm/jit/arm/md-abi.cpp - functions for arm 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 #include "vm/types.hpp"
28 
29 #include "vm/jit/arm/md-abi.hpp"
30 
31 #include "vm/descriptor.hpp"
32 #include "vm/method.hpp"
33 #include "vm/global.hpp"
34 
35 #include "vm/jit/abi.hpp"
36 #include "vm/jit/code.hpp"
37 #include "vm/jit/codegen-common.hpp" // for PACK_REGS
38 
39 /* register descripton array **************************************************/
40 
44  REG_END
45 };
46 
47 const char *abi_registers_integer_name[] = {
48  "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4",
49  "v5", "t3", "t1", "t2", "ip", "sp", "lr", "pc",
50 };
51 
53  0, /* a0 */
54  1, /* a1 */
55  2, /* a2 */
56  3, /* a3 */
57  REG_SPLIT,
58 };
59 
61  4, /* s0 */
62  5, /* s1 */
63  6, /* s2 */
64  7, /* s3 */
65  8, /* s4 */
66 };
67 
69  -1,
70 };
71 
72 
73 #if defined(ENABLE_SOFTFLOAT)
74 s4 nregdescfloat[] = {
77  REG_END
78 };
79 #else
80 #if !defined(__ARMHF__)
84  REG_END
85 };
86 #else
87 s4 nregdescfloat[] = {
90  REG_END
91 };
92 #endif
93 #endif /* defined(ENABLE_SOFTFLOAT) */
94 
96 #if defined(__ARMHF__)
97  0, 1, 2, 3, 4, 5, 6, 7,
98 #endif
99  -1,
100 };
101 
103 #if defined(__ARMHF__)
104  8, 9, 10, 11, 12, 13, 14, 15,
105 #endif
106  -1,
107 };
108 
110 #if defined(__ARMHF__) || defined(ENABLE_SOFTFLOAT)
111  -1,
112 #else
113  0, /* ft0 */
114  1, /* ft1 */
115  2, /* ft2 */
116  3, /* ft3 */
117  4, /* ft4 */
118  5, /* ft5 */
119 #endif
120 };
121 
122 
123 /* md_param_alloc **************************************************************
124 
125  Allocate Arguments to Stackslots according the Calling Conventions
126 
127  --- in:
128  md->paramcount: Number of arguments for this method
129  md->paramtypes[].type: Argument types
130 
131  --- out:
132  md->params[].inmemory: Argument spilled on stack
133  md->params[].regoff: Stack offset or rd->arg[int|flt]regs index
134  md->memuse: Stackslots needed for argument spilling
135  md->argintreguse: max number of integer arguments used
136  md->argfltreguse: max number of float arguments used
137 
138 *******************************************************************************/
139 
141 {
142  paramdesc *pd;
143  s4 i;
144  s4 reguse, freguse;
145  s4 stacksize;
146 
147  /* set default values */
148 
149  reguse = 0;
150  freguse = 0;
151  stacksize = 0;
152 
153  /* get params field of methoddesc */
154 
155  pd = md->params;
156 
157  for (i = 0; i < md->paramcount; i++, pd++) {
158  switch (md->paramtypes[i].type) {
159  case TYPE_INT:
160  case TYPE_ADR:
161 #if !defined(__ARMHF__)
162  case TYPE_FLT:
163 #endif
164  if (reguse < INT_ARG_CNT) {
165  pd->inmemory = false;
166  pd->index = reguse;
168  reguse++;
169  }
170  else {
171  pd->inmemory = true;
172  pd->index = stacksize;
173  pd->regoff = stacksize * 8;
174  stacksize++;
175  }
176  break;
177 
178  case TYPE_LNG:
179 #if !defined(__ARMHF__)
180  case TYPE_DBL:
181 #endif
182  /* interally we use the EABI */
183 
184  ALIGN_2(reguse);
185 
186  if (reguse < INT_ARG_CNT) {
187  pd->inmemory = false;
188 #if defined(__ARMEL__)
189  pd->index = PACK_REGS(reguse, reguse + 1);
190  pd->regoff =
192  abi_registers_integer_argument[reguse + 1]);
193 #else
194  pd->index = PACK_REGS(reguse + 1, reguse);
195  pd->regoff =
198 #endif
199  reguse += 2;
200  }
201  else {
202 
203  /*ALIGN_2(stacksize);*/
204 
205  pd->inmemory = true;
206  pd->index = stacksize;
207  pd->regoff = stacksize * 8;
208  /*stacksize += 2;*/
209  stacksize++;
210  }
211  break;
212 
213 #if defined(__ARMHF__)
214  case TYPE_FLT:
215  case TYPE_DBL:
216  if (freguse < FLT_ARG_CNT) {
217  pd->inmemory = false;
218  pd->index = freguse;
219  pd->regoff = abi_registers_float_argument[freguse];
220  freguse++;
221  }
222  else {
223  pd->inmemory = true;
224  pd->index = stacksize;
225  pd->regoff = stacksize * 8;
226  stacksize++;
227  }
228  break;
229 #endif
230  }
231  }
232 
233  /* Since R0/R1 (==A0/A1) are used for passing return values, this
234  argument register usage has to be regarded, too. */
235 
236  if (md->returntype.type != TYPE_VOID
237 #if defined(__ARMHF__)
239 #endif
240  )
241  {
242  if (!IS_2_WORD_TYPE(md->returntype.type)) {
243  if (reguse < 1)
244  reguse = 1;
245  }
246  else {
247  if (reguse < 2)
248  reguse = 2;
249  }
250  }
251 #if defined(__ARMHF__)
252  else if (IS_FLT_DBL_TYPE(md->returntype.type))
253  if (freguse < 1)
254  freguse = 1;
255 #endif
256 
257  /* fill register and stack usage */
258 
259  md->argintreguse = reguse;
260  md->argfltreguse = freguse;
261  md->memuse = stacksize;
262 }
263 
264 
265 /* md_param_alloc_native *******************************************************
266 
267  Pre-allocate arguments according the native ABI.
268 
269 *******************************************************************************/
270 
272 {
273  paramdesc *pd;
274  s4 i;
275  s4 reguse, freguse;
276  s4 stacksize;
277  s1 sregused[8]; /* 1 = full, 0 = half free */
278  bool backfill;
279 
280  /* set default values */
281 
282  reguse = 0;
283  freguse = 0;
284  stacksize = 0;
285  backfill = true;
286 
287  /* get params field of methoddesc */
288 
289  pd = md->params;
290 
291  for (i = 0; i < md->paramcount; i++, pd++) {
292 #if defined(__ARMHF__)
293  if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
294  bool found = false;
295  do {
296  /* Try to find free VFP register first. */
297  /* If it fails, use the normal path below. */
298  if (IS_2_WORD_TYPE(md->paramtypes[i].type)) {
299  if (freguse >= 8)
300  break;
301  pd->inmemory = false;
302  pd->index = -1;
303  pd->regoff = abi_registers_float_argument[freguse];
304  sregused[freguse] = 1;
305  freguse++;
306  }
307  else {
308  int i;
309  if (backfill) {
310  for (i=0; i<freguse; i++)
311  if (!sregused[i])
312  break;
313  }
314  else
315  i = freguse;
316  if (i<freguse) {
318  sregused[i] = 1;
319  }
320  else {
321  if (freguse >= 8)
322  break;
323  /* no backfill space found */
324  pd->regoff = abi_registers_float_argument[freguse];
325  sregused[freguse] = 0;
326  freguse++;
327  }
328  pd->inmemory = false;
329  pd->index = -1;
330  }
331  found = true;
332  } while (0);
333  if (found)
334  continue;
335  backfill = false;
336  }
337 #endif
338 
339  switch (md->paramtypes[i].type) {
340  case TYPE_INT:
341  case TYPE_ADR:
342  case TYPE_FLT:
343  if (reguse < INT_ARG_CNT
344 #if defined(__ARMHF__)
345  && md->paramtypes[i].type != TYPE_FLT
346 #endif
347  ) {
348  pd->inmemory = false;
349  pd->index = -1;
351  reguse++;
352  }
353  else {
354  pd->inmemory = true;
355  pd->index = -1;
356  pd->regoff = stacksize * 4;
357  stacksize++;
358  }
359  break;
360 
361  case TYPE_LNG:
362  case TYPE_DBL:
363  if (reguse < (INT_ARG_CNT - 1)
364 #if defined(__ARMHF__)
365  && md->paramtypes[i].type != TYPE_DBL
366 #endif
367  ) {
368 #if defined(__ARM_EABI__)
369  ALIGN_2(reguse);
370 #endif
371  pd->inmemory = false;
372 #if defined(__ARMEL__)
373  pd->index = -1;
374  pd->regoff =
376  abi_registers_integer_argument[reguse + 1]);
377 #else
378  pd->index = -1;
379  pd->regoff =
382 #endif
383  reguse += 2;
384  }
385 #if !defined(__ARM_EABI__)
386  else if (reguse < INT_ARG_CNT) {
387  pd->inmemory = false;
388 # if defined(__ARMEL__)
389  pd->index = -1;
390  pd->regoff =
393 # else
394  pd->index = -1;
395  pd->regoff =
398 # endif
399  reguse++;
400  stacksize++;
401  }
402 #endif
403  else {
404 #if defined(__ARM_EABI__)
405  ALIGN_2(stacksize);
406 #endif
407  pd->inmemory = true;
408  pd->index = -1;
409  pd->regoff = stacksize * 4;
410 #if defined(__ARMHF__)
411  if (md->paramtypes[i].type != TYPE_DBL)
412 #endif
413  reguse = INT_ARG_CNT;
414  stacksize += 2;
415  }
416  break;
417  }
418  }
419 
420  /* Since R0/R1 (==A0/A1) are used for passing return values, this
421  argument register usage has to be regarded, too. */
422 
423  if (md->returntype.type != TYPE_VOID
424 #if defined(__ARMHF__)
426 #endif
427  )
428  {
429  if (!IS_2_WORD_TYPE(md->returntype.type)) {
430  if (reguse < 1)
431  reguse = 1;
432  }
433  else {
434  if (reguse < 2)
435  reguse = 2;
436  }
437  }
438 #if defined(__ARMHF__)
439  else if (IS_FLT_DBL_TYPE(md->returntype.type))
440  if (freguse < 1)
441  freguse = 1;
442 #endif
443 
444  /* fill register and stack usage */
445 
446  md->argintreguse = reguse;
447  md->argfltreguse = freguse;
448  md->memuse = stacksize;
449 }
450 
451 
452 /* md_return_alloc *************************************************************
453 
454  Precolor the Java Stackelement containing the Return Value, if possible.
455 
456  --- in
457  m: Methodinfo of current method
458  return_type: Return Type of the Method (TYPE_INT.. TYPE_ADR)
459  TYPE_VOID is not allowed!
460  stackslot: Java Stackslot to contain the Return Value
461 
462  --- out
463  if precoloring was possible:
464  VAR(stackslot->varnum)->flags = PREALLOC
465  VAR(stackslot->varnum)->vv.regoff = [REG_RESULT, (REG_RESULT2/REG_RESULT), REG_FRESULT]
466  rd->arg[flt|int]reguse set to a value according the register usage
467 
468 *******************************************************************************/
469 
471 {
472  methodinfo *m;
473  codeinfo *code;
474  registerdata *rd;
475  methoddesc *md;
476 
477  /* get required compiler data */
478 
479  m = jd->m;
480  code = jd->code;
481  rd = jd->rd;
482 
483  md = m->parseddesc;
484 
485  /* In Leafmethods Local Vars holding parameters are precolored to
486  their argument register -> so leafmethods with paramcount > 0
487  could already use R0 == a00! */
488 
489  if (!code_is_leafmethod(code) || (md->paramcount == 0)) {
490  /* Only precolor the stackslot, if it is not a SAVEDVAR <->
491  has not to survive method invokations. */
492 
493  if (!(stackslot->flags & SAVEDVAR)) {
494 #if !defined(ENABLE_SOFTFLOAT)
495  /* Stackelements containing float or double values
496  (TYPE_FLT | TYPE_DBL) cannot be precolored, because we
497  use integer register to pass return values. (floats:
498  R0, doubles: R0/R1) */
499 
500  if (!IS_FLT_DBL_TYPE(md->returntype.type)) {
501 #endif
502 
503  VAR(stackslot->varnum)->flags = PREALLOC;
504 
505  if (!IS_2_WORD_TYPE(md->returntype.type)) {
506  if (rd->argintreguse < 1)
507  rd->argintreguse = 1;
508 
509  VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
510  }
511  else {
512  if (rd->argintreguse < 2)
513  rd->argintreguse = 2;
514 
515  VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
516  }
517 
518 #if !defined(ENABLE_SOFTFLOAT)
519  }
520 #if defined(__ARMHF__)
521  else {
522  VAR(stackslot->varnum)->flags = PREALLOC;
523 
524  if (rd->argfltreguse < 1)
525  rd->argfltreguse = 1;
526 
527  VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
528  }
529 #endif
530 #endif
531  }
532  }
533 }
534 
535 
536 /*
537  * These are local overrides for various environment variables in Emacs.
538  * Please do not remove this and leave it at the end of the file, where
539  * Emacs will automagically detect them.
540  * ---------------------------------------------------------------------
541  * Local variables:
542  * mode: c++
543  * indent-tabs-mode: t
544  * c-basic-offset: 4
545  * tab-width: 4
546  * End:
547  * vim:noexpandtab:sw=4:ts=4:
548  */
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
int argintreguse
Definition: reg.hpp:86
#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
const s4 abi_registers_integer_argument[]
Definition: md-abi.cpp:64
codeinfo * code
Definition: jit.hpp:128
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
static int code_is_leafmethod(codeinfo *code)
Definition: code.hpp:151
typedesc paramtypes[1]
Definition: descriptor.hpp:167
#define IS_2_WORD_TYPE(a)
Definition: global.hpp:132
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
int argfltreguse
Definition: reg.hpp:89
registerdata * rd
Definition: jit.hpp:130
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
int8_t s1
Definition: types.hpp:39
#define BACKFILL_OFFSET
Definition: md-abi.hpp:83
#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
#define REG_SPLIT
Definition: md-abi.hpp:58
uint32_t regoff
Definition: descriptor.hpp:153
#define REG_RESULT
Definition: md-abi.hpp:33
#define REG_RESULT_PACKED
Definition: md-abi.hpp:133