1 /* src/vm/jit/reg.inc - register allocator
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
34 $Id: reg.inc 3617 2005-11-07 18:39:10Z twisti $
40 #include "mm/memory.h"
41 #include "vm/method.h"
42 #include "vm/resolve.h"
43 #include "vm/jit/reg.h"
46 /* function prototypes for this file */
48 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
49 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
50 static void allocate_scratch_registers(methodinfo *m, registerdata *rd);
53 /* reg_init ********************************************************************
57 *******************************************************************************/
65 /* reg_setup *******************************************************************
69 *******************************************************************************/
71 void reg_setup(methodinfo *m, registerdata *rd, t_inlining_globals *id)
76 /* setup the integer register table */
79 /* On ARM longs can be split across argument regs and stack. This is
80 * signed by setting the HIGH_REG to INT_ARG_CNT in md_param_alloc().
81 * Here we make sure it resolves to a special dummy reg (REG_SPLIT). */
82 rd->argintregs = DMNEW(s4, INT_ARG_CNT + 1);
83 rd->argintregs[INT_ARG_CNT] = REG_SPLIT;
85 rd->argintregs = DMNEW(s4, INT_ARG_CNT);
87 rd->tmpintregs = DMNEW(s4, INT_TMP_CNT);
88 rd->savintregs = DMNEW(s4, INT_SAV_CNT);
89 rd->freeargintregs = DMNEW(s4, INT_ARG_CNT);
90 rd->freetmpintregs = DMNEW(s4, INT_TMP_CNT);
91 rd->freesavintregs = DMNEW(s4, INT_SAV_CNT);
97 for (i = 0; i < INT_REG_CNT; i++) {
98 switch (nregdescint[i]) {
103 rd->savintregs[rd->savintreguse++] = i;
106 rd->tmpintregs[rd->tmpintreguse++] = i;
109 rd->argintregs[rd->argintreguse++] = i;
113 assert(rd->savintreguse == INT_SAV_CNT);
114 assert(rd->tmpintreguse == INT_TMP_CNT);
115 assert(rd->argintreguse == INT_ARG_CNT);
117 #if defined(__X86_64__)
119 * on x86_64 the argument registers are not in ascending order
120 * a00 (%rdi) <-> a03 (%rcx) and a01 (%rsi) <-> a02 (%rdx)
122 i = rd->argintregs[3];
123 rd->argintregs[3] = rd->argintregs[0];
124 rd->argintregs[0] = i;
126 i = rd->argintregs[2];
127 rd->argintregs[2] = rd->argintregs[1];
128 rd->argintregs[1] = i;
131 #ifdef HAS_ADDRESS_REGISTER_FILE
132 /* setup the address register table */
134 rd->argadrregs = DMNEW(s4, ADR_ARG_CNT);
135 rd->tmpadrregs = DMNEW(s4, ADR_TMP_CNT);
136 rd->savadrregs = DMNEW(s4, ADR_SAV_CNT);
137 rd->freeargadrregs = DMNEW(s4, ADR_ARG_CNT);
138 rd->freetmpadrregs = DMNEW(s4, ADR_TMP_CNT);
139 rd->freesavadrregs = DMNEW(s4, ADR_SAV_CNT);
141 rd->adrreg_argnum = 0;
142 rd->argadrreguse = 0;
143 rd->tmpadrreguse = 0;
144 rd->savadrreguse = 0;
146 for (i = 0; i < ADR_REG_CNT; i++) {
147 switch (nregdescadr[i]) {
152 rd->savadrregs[rd->savadrreguse++] = i;
155 rd->tmpadrregs[rd->tmpadrreguse++] = i;
158 rd->argadrregs[rd->argadrreguse++] = i;
162 assert(rd->savadrreguse == ADR_SAV_CNT);
163 assert(rd->tmpadrreguse == ADR_TMP_CNT);
164 assert(rd->argadrreguse == ADR_ARG_CNT);
167 /* setup the float register table */
169 rd->argfltregs = DMNEW(s4, FLT_ARG_CNT);
170 rd->tmpfltregs = DMNEW(s4, FLT_TMP_CNT);
171 rd->savfltregs = DMNEW(s4, FLT_SAV_CNT);
172 rd->freeargfltregs = DMNEW(s4, FLT_ARG_CNT);
173 rd->freetmpfltregs = DMNEW(s4, FLT_TMP_CNT);
174 rd->freesavfltregs = DMNEW(s4, FLT_SAV_CNT);
176 rd->argfltreguse = 0;
177 rd->tmpfltreguse = 0;
178 rd->savfltreguse = 0;
180 for (i = 0; i < FLT_REG_CNT; i++) {
181 switch (nregdescfloat[i]) {
186 rd->savfltregs[rd->savfltreguse++] = i;
189 rd->tmpfltregs[rd->tmpfltreguse++] = i;
192 rd->argfltregs[rd->argfltreguse++] = i;
196 assert(rd->savfltreguse == FLT_SAV_CNT);
197 assert(rd->tmpfltreguse == FLT_TMP_CNT);
198 assert(rd->argfltreguse == FLT_ARG_CNT);
201 rd->freemem = DMNEW(s4, id->cummaxstack);
202 #if defined(HAS_4BYTE_STACKSLOT)
203 rd->freemem_2 = DMNEW(s4, id->cummaxstack);
205 rd->locals = DMNEW(varinfo5, id->cumlocals);
206 rd->interfaces = DMNEW(varinfo5, id->cummaxstack);
207 for (v = rd->locals, i = id->cumlocals; i > 0; v++, i--) {
208 v[0][TYPE_INT].type = -1;
209 v[0][TYPE_LNG].type = -1;
210 v[0][TYPE_FLT].type = -1;
211 v[0][TYPE_DBL].type = -1;
212 v[0][TYPE_ADR].type = -1;
215 for (v = rd->interfaces, i = id->cummaxstack; i > 0; v++, i--) {
216 v[0][TYPE_INT].type = -1;
217 v[0][TYPE_INT].flags = 0;
218 v[0][TYPE_LNG].type = -1;
219 v[0][TYPE_LNG].flags = 0;
220 v[0][TYPE_FLT].type = -1;
221 v[0][TYPE_FLT].flags = 0;
222 v[0][TYPE_DBL].type = -1;
223 v[0][TYPE_DBL].flags = 0;
224 v[0][TYPE_ADR].type = -1;
225 v[0][TYPE_ADR].flags = 0;
228 #if defined(SPECIALMEMUSE)
229 # if defined(__DARWIN__)
230 /* 6*4=24 byte linkage area + 8*4=32 byte minimum parameter Area */
231 rd->memuse = LA_WORD_SIZE + INT_ARG_CNT;
233 rd->memuse = LA_WORD_SIZE;
236 rd->memuse = 0; /* init to zero -> analyse_stack will set it to a higher */
237 /* value, if appropriate */
240 /* Set rd->argxxxreguse to XXX_ARG_CNBT to not use unused argument */
241 /* registers as temp registers */
242 #if defined(HAS_ADDRESS_REGISTER_FILE)
243 rd->argadrreguse = 0;
244 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
245 rd->argintreguse = 0;
246 rd->argfltreguse = 0;
250 /* function reg_free ***********************************************************
252 releases all allocated space for registers
254 *******************************************************************************/
256 void reg_free(methodinfo *m, registerdata *rd)
262 /* reg_close *******************************************************************
266 *******************************************************************************/
274 /* function interface_regalloc *************************************************
276 allocates registers for all interface variables
278 *******************************************************************************/
280 void regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
282 interface_regalloc(m, cd, rd);
283 allocate_scratch_registers(m, rd);
284 local_regalloc(m, cd, rd);
285 #ifdef INVOKE_NEW_DEBUG
286 if (compileverbose) {
287 printf("memuse after reg.inc: %3i\n",rd->memuse);
293 /* function interface_regalloc *************************************************
295 allocates registers for all interface variables
297 *******************************************************************************/
299 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
302 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
303 /* in case a more vars are packed into this interface slot */
305 int intregsneeded = 0;
307 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
308 /* on HAS_4BYTE_STACKSLOT architectures */
309 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
311 /* rd->memuse was already set in stack.c to allocate stack space for */
312 /* passing arguments to called methods */
313 #if defined(__I386__)
314 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
315 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
320 #ifdef INVOKE_NEW_DEBUG
321 if (compileverbose) {
322 if (checksync && (m->flags & ACC_SYNCHRONIZED))
323 printf("ACC_SYNCHRONIZED\n");
324 printf("analyse: argintru %3i argfltru %3i memuse %3i\n",
325 rd->argintreguse, rd->argfltreguse, rd->memuse);
330 for (s = 0; s < cd->maxstack; s++) {
331 intalloc = -1; fltalloc = -1;
332 saved = (rd->interfaces[s][TYPE_INT].flags |
333 rd->interfaces[s][TYPE_LNG].flags |
334 rd->interfaces[s][TYPE_FLT].flags |
335 rd->interfaces[s][TYPE_DBL].flags |
336 rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
338 for (tt = 0; tt <= 4; tt++) {
340 v = &rd->interfaces[s][t];
342 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
343 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
345 #if defined(HAS_4BYTE_STACKSLOT)
346 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
349 #if defined(HAS_ADDRESS_REGISTER_FILE)
350 if (IS_ADR_TYPE(t)) {
352 &&(rd->argadrreguse < ADR_ARG_CNT)) {
353 v->regoff = rd->argadrregs[rd->argadrreguset++];
354 } else if (rd->tmpadrreguse > 0) {
355 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
356 } else if (rd->savadrreguse > 0) {
357 v->regoff = rd->savadrregs[--rd->savadrreguse];
359 v->flags |= INMEMORY;
360 v->regoff = rd->memuse++;
362 } else /* !IS_ADR_TYPE */
363 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
365 if (IS_FLT_DBL_TYPE(t)) {
367 /* Reuse memory slot(s)/register(s) for shared interface slots */
368 v->flags |= rd->interfaces[s][fltalloc].flags
370 v->regoff = rd->interfaces[s][fltalloc].regoff;
371 } else if (!m->isleafmethod
372 && (rd->argfltreguse < FLT_ARG_CNT)) {
373 v->regoff = rd->argfltregs[rd->argfltreguse++];
374 } else if (rd->tmpfltreguse > 0) {
375 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
376 } else if (rd->savfltreguse > 0) {
377 v->regoff = rd->savfltregs[--rd->savfltreguse];
379 v->flags |= INMEMORY;
380 v->regoff = rd->memuse;
381 rd->memuse += memneeded + 1;
384 } else { /* !IS_FLT_DBL_TYPE(t) */
385 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
387 * for i386 put all longs in memory
389 if (IS_2_WORD_TYPE(t)) {
390 v->flags |= INMEMORY;
391 v->regoff = rd->memuse;
392 rd->memuse += memneeded + 1;
394 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
395 /* #if !defined(HAS_4BYTE_STACKSLOT) */
397 /* Reuse memory slot(s)/register(s) for shared interface slots */
399 rd->interfaces[s][intalloc].flags
401 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
402 if (!(v->flags & INMEMORY)
403 && IS_2_WORD_TYPE(intalloc))
404 v->regoff = GET_LOW_REG(
405 rd->interfaces[s][intalloc].regoff);
409 rd->interfaces[s][intalloc].regoff;
411 /* #endif *//* !defined(HAS_4BYTE_STACKSLOT) */
412 if (!m->isleafmethod &&
414 + intregsneeded < INT_ARG_CNT)) {
415 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
418 rd->argintregs[rd->argintreguse],
419 rd->argintregs[rd->argintreguse + 1]);
423 rd->argintregs[rd->argintreguse];
424 rd->argintreguse += intregsneeded + 1;
426 else if (rd->tmpintreguse > intregsneeded) {
427 rd->tmpintreguse -= intregsneeded + 1;
428 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
431 rd->tmpintregs[rd->tmpintreguse],
432 rd->tmpintregs[rd->tmpintreguse + 1]);
436 rd->tmpintregs[rd->tmpintreguse];
438 else if (rd->savintreguse > intregsneeded) {
439 rd->savintreguse -= intregsneeded + 1;
441 rd->savintregs[rd->savintreguse];
442 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
445 rd->savintregs[rd->savintreguse],
446 rd->savintregs[rd->savintreguse + 1]);
450 rd->savintregs[rd->savintreguse];
453 v->flags |= INMEMORY;
454 v->regoff = rd->memuse;
455 rd->memuse += memneeded + 1;
459 } /* if (IS_FLT_DBL_TYPE(t)) */
461 } else { /* (saved) */
462 /* now the same like above, but without a chance to take a temporary register */
463 #ifdef HAS_ADDRESS_REGISTER_FILE
464 if (IS_ADR_TYPE(t)) {
465 if (rd->savadrreguse > 0) {
466 v->regoff = rd->savadrregs[--rd->savadrreguse];
469 v->flags |= INMEMORY;
470 v->regoff = rd->memuse++;
475 if (IS_FLT_DBL_TYPE(t)) {
477 v->flags |= rd->interfaces[s][fltalloc].flags
479 v->regoff = rd->interfaces[s][fltalloc].regoff;
481 if (rd->savfltreguse > 0) {
482 v->regoff = rd->savfltregs[--rd->savfltreguse];
485 v->flags |= INMEMORY;
486 v->regoff = rd->memuse;
487 rd->memuse += memneeded + 1;
491 else { /* IS_INT_LNG */
492 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
494 * for i386 put all longs in memory
496 if (IS_2_WORD_TYPE(t)) {
497 v->flags |= INMEMORY;
498 v->regoff = rd->memuse;
499 rd->memuse += memneeded + 1;
503 /* #if !defined(HAS_4BYTE_STACKSLOT) */
506 rd->interfaces[s][intalloc].flags & INMEMORY;
507 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
508 if (!(v->flags & INMEMORY)
509 && IS_2_WORD_TYPE(intalloc))
512 rd->interfaces[s][intalloc].regoff);
516 rd->interfaces[s][intalloc].regoff;
520 if (rd->savintreguse > intregsneeded) {
521 rd->savintreguse -= intregsneeded + 1;
522 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
524 v->regoff = PACK_REGS(
525 rd->savintregs[rd->savintreguse],
526 rd->savintregs[rd->savintreguse + 1]);
530 rd->savintregs[rd->savintreguse];
532 v->flags |= INMEMORY;
533 v->regoff = rd->memuse;
534 rd->memuse += memneeded + 1;
539 } /* if (IS_FLT_DBL_TYPE(t) else */
540 } /* if (IS_ADR_TYPE(t)) else */
541 } /* if (saved) else */
542 } /* if (type >= 0) */
549 /* function local_regalloc *****************************************************
551 allocates registers for all local variables
553 *******************************************************************************/
555 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
558 int intalloc, fltalloc;
560 int intregsneeded = 0;
562 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
563 int fargcnt, iargcnt;
564 #ifdef HAS_ADDRESS_REGISTER_FILE
568 if (m->isleafmethod) {
569 methoddesc *md = m->parseddesc;
571 iargcnt = md->argintreguse;
572 fargcnt = md->argfltreguse;
573 #ifdef HAS_ADDRESS_REGISTER_FILE
574 aargcnt = md->argadrreguse;
576 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
577 intalloc = -1; fltalloc = -1;
578 for (tt = 0; tt <= 4; tt++) {
580 v = &rd->locals[s][t];
585 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
586 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
588 #if defined(HAS_4BYTE_STACKSLOT)
589 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
595 * #ifdef HAS_ADDRESS_REGISTER_FILE
602 * } else { / int & lng
606 * must not to be changed!
609 #ifdef HAS_ADDRESS_REGISTER_FILE
610 if (IS_ADR_TYPE(t)) {
611 if ((p < md->paramcount) && !md->params[p].inmemory) {
613 v->regoff = rd->argadrregs[md->params[p].regoff];
615 if (rd->tmpadrreguse > 0) {
617 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
619 else if (rd->savadrreguse > 0) {
621 v->regoff = rd->savadrregs[--rd->savadrreguse];
623 /* use unused argument registers as local registers */
624 else if ((p >= md->paramcount) &&
625 (aargcnt < ADR_ARG_CNT)) {
627 v->regoff = rd->argadrregs[aargcnt++];
630 v->flags |= INMEMORY;
631 v->regoff = rd->memuse++;
635 if (IS_FLT_DBL_TYPE(t)) {
637 v->flags = rd->locals[s][fltalloc].flags;
638 v->regoff = rd->locals[s][fltalloc].regoff;
640 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
641 /* We can only use float arguments as local variables,
642 * if we do not pass them in integer registers. */
643 else if ((p < md->paramcount) &&
644 !md->params[p].inmemory) {
646 v->regoff = rd->argfltregs[md->params[p].regoff];
649 else if (rd->tmpfltreguse > 0) {
651 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
653 else if (rd->savfltreguse > 0) {
655 v->regoff = rd->savfltregs[--rd->savfltreguse];
657 /* use unused argument registers as local registers */
658 else if ((p >= m->paramcount) &&
659 (fargcnt < FLT_ARG_CNT)) {
661 v->regoff = rd->argfltregs[fargcnt];
666 v->regoff = rd->memuse;
667 rd->memuse += memneeded + 1;
672 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
674 * for i386 put all longs in memory
676 if (IS_2_WORD_TYPE(t)) {
678 v->regoff = rd->memuse;
679 rd->memuse += memneeded + 1;
684 v->flags = rd->locals[s][intalloc].flags;
685 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
686 if (!(v->flags & INMEMORY)
687 && IS_2_WORD_TYPE(intalloc))
688 v->regoff = GET_LOW_REG(
689 rd->locals[s][intalloc].regoff);
692 v->regoff = rd->locals[s][intalloc].regoff;
694 else if ((p < md->paramcount) &&
695 !md->params[p].inmemory) {
697 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
698 if (IS_2_WORD_TYPE(t))
699 /* For ARM: - if GET_LOW_REG(md->params[p].regoff) == R4, prevent here that */
700 /* rd->argintregs[GET_HIGH_REG(md->...)) is used! */
701 v->regoff = PACK_REGS(
702 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
703 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
707 rd->argintregs[md->params[p].regoff];
709 else if (rd->tmpintreguse > intregsneeded) {
710 rd->tmpintreguse -= intregsneeded + 1;
712 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
714 v->regoff = PACK_REGS(
715 rd->tmpintregs[rd->tmpintreguse],
716 rd->tmpintregs[rd->tmpintreguse + 1]);
720 rd->tmpintregs[rd->tmpintreguse];
722 else if (rd->savintreguse > intregsneeded) {
723 rd->savintreguse -= intregsneeded + 1;
725 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
727 v->regoff = PACK_REGS(
728 rd->savintregs[rd->savintreguse],
729 rd->savintregs[rd->savintreguse + 1]);
732 v->regoff =rd->savintregs[rd->savintreguse];
735 * use unused argument registers as local registers
737 else if ((p >= m->paramcount) &&
738 (iargcnt < INT_ARG_CNT)) {
740 v->regoff = rd->argintregs[iargcnt];
745 v->regoff = rd->memuse;
746 rd->memuse += memneeded + 1;
751 #ifdef HAS_ADDRESS_REGISTER_FILE
754 } /* for (tt=0;...) */
756 /* If the current parameter is a 2-word type, the next local slot */
759 if (p < md->paramcount)
760 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
766 for (s = 0; s < cd->maxlocals; s++) {
767 intalloc = -1; fltalloc = -1;
768 for (tt=0; tt<=4; tt++) {
770 v = &rd->locals[s][t];
773 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
774 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
776 #if defined(HAS_4BYTE_STACKSLOT)
777 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
779 #ifdef HAS_ADDRESS_REGISTER_FILE
780 if ( IS_ADR_TYPE(t) ) {
781 if (rd->savadrreguse > 0) {
783 v->regoff = rd->savadrregs[--rd->savadrreguse];
787 v->regoff = rd->memuse++;
791 if (IS_FLT_DBL_TYPE(t)) {
793 v->flags = rd->locals[s][fltalloc].flags;
794 v->regoff = rd->locals[s][fltalloc].regoff;
796 else if (rd->savfltreguse > 0) {
798 v->regoff = rd->savfltregs[--rd->savfltreguse];
802 /* Align doubles in Memory */
803 if ( (memneeded) && (rd->memuse & 1))
805 v->regoff = rd->memuse;
806 rd->memuse += memneeded + 1;
811 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
813 * for i386 put all longs in memory
815 if (IS_2_WORD_TYPE(t)) {
817 v->regoff = rd->memuse;
818 rd->memuse += memneeded + 1;
822 v->flags = rd->locals[s][intalloc].flags;
823 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
824 if (!(v->flags & INMEMORY)
825 && IS_2_WORD_TYPE(intalloc))
826 v->regoff = GET_LOW_REG(
827 rd->locals[s][intalloc].regoff);
830 v->regoff = rd->locals[s][intalloc].regoff;
832 else if (rd->savintreguse > intregsneeded) {
833 rd->savintreguse -= intregsneeded+1;
835 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
837 v->regoff = PACK_REGS(
838 rd->savintregs[rd->savintreguse],
839 rd->savintregs[rd->savintreguse + 1]);
842 v->regoff =rd->savintregs[rd->savintreguse];
846 v->regoff = rd->memuse;
847 rd->memuse += memneeded + 1;
849 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
854 #ifdef HAS_ADDRESS_REGISTER_FILE
863 static void reg_init_temp(methodinfo *m, registerdata *rd)
866 #if defined(HAS_4BYTE_STACKSLOT)
867 rd->freememtop_2 = 0;
870 rd->freetmpinttop = 0;
871 rd->freesavinttop = 0;
872 rd->freetmpflttop = 0;
873 rd->freesavflttop = 0;
874 #ifdef HAS_ADDRESS_REGISTER_FILE
875 rd->freetmpadrtop = 0;
876 rd->freesavadrtop = 0;
879 rd->freearginttop = 0;
880 rd->freeargflttop = 0;
881 #ifdef HAS_ADDRESS_REGISTER_FILE
882 rd->freeargadrtop = 0;
885 if (m->isleafmethod) {
886 /* Don't use not used Argument Registers in Leafmethods -> they could */
887 /* already be in use for Locals passed as parameter to this Method */
888 rd->argintreguse = INT_ARG_CNT;
889 rd->argfltreguse = FLT_ARG_CNT;
890 #ifdef HAS_ADDRESS_REGISTER_FILE
891 rd->argadrreguse = ADR_ARG_CNT;
897 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
899 static void reg_new_temp_func(registerdata *rd, stackptr s)
905 /* Try to allocate a saved register if there is no temporary one */
906 /* available. This is what happens during the second run. */
907 tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
909 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
910 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
914 #if defined(HAS_4BYTE_STACKSLOT)
915 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
920 for(; tryagain; --tryagain) {
922 if (!(s->flags & SAVEDVAR))
923 s->flags |= SAVEDTMP;
924 #ifdef HAS_ADDRESS_REGISTER_FILE
925 if (IS_ADR_TYPE(s->type)) {
926 if (rd->freesavadrtop > 0) {
927 s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
929 } else if (rd->savadrreguse > 0) {
930 s->regoff = rd->savadrregs[--rd->savadrreguse];
936 if (IS_FLT_DBL_TYPE(s->type)) {
937 if (rd->freesavflttop > 0) {
938 s->regoff = rd->freesavfltregs[--rd->freesavflttop];
940 } else if (rd->savfltreguse > 0) {
941 s->regoff = rd->savfltregs[--rd->savfltreguse];
945 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
947 * for i386 put all longs in memory
949 if (!IS_2_WORD_TYPE(s->type))
952 if (rd->freesavinttop > intregsneeded) {
953 rd->freesavinttop -= intregsneeded + 1;
954 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
956 s->regoff = PACK_REGS(
957 rd->freesavintregs[rd->freesavinttop],
958 rd->freesavintregs[rd->freesavinttop + 1]);
962 rd->freesavintregs[rd->freesavinttop];
964 } else if (rd->savintreguse > intregsneeded) {
965 rd->savintreguse -= intregsneeded + 1;
966 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
968 s->regoff = PACK_REGS(
969 rd->savintregs[rd->savintreguse],
970 rd->savintregs[rd->savintreguse + 1]);
973 s->regoff = rd->savintregs[rd->savintreguse];
979 } else { /* tryagain == 2 */
980 #ifdef HAS_ADDRESS_REGISTER_FILE
981 if (IS_ADR_TYPE(s->type)) {
982 if (rd->freetmpadrtop > 0) {
983 s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
985 } else if (rd->tmpadrreguse > 0) {
986 s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
992 if (IS_FLT_DBL_TYPE(s->type)) {
993 if (rd->freeargflttop > 0) {
994 s->regoff = rd->freeargfltregs[--rd->freeargflttop];
997 } else if (rd->argfltreguse < FLT_ARG_CNT) {
998 s->regoff = rd->argfltregs[rd->argfltreguse++];
1001 } else if (rd->freetmpflttop > 0) {
1002 s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
1004 } else if (rd->tmpfltreguse > 0) {
1005 s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
1010 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1012 * for i386 put all longs in memory
1014 if (!IS_2_WORD_TYPE(s->type))
1017 if (rd->freearginttop > intregsneeded) {
1018 rd->freearginttop -= intregsneeded + 1;
1020 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1022 s->regoff = PACK_REGS(
1023 rd->freeargintregs[rd->freearginttop],
1024 rd->freeargintregs[rd->freearginttop + 1]);
1028 rd->freeargintregs[rd->freearginttop];
1030 } else if (rd->argintreguse
1031 < INT_ARG_CNT - intregsneeded) {
1032 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1034 s->regoff = PACK_REGS(
1035 rd->argintregs[rd->argintreguse],
1036 rd->argintregs[rd->argintreguse + 1]);
1039 s->regoff = rd->argintregs[rd->argintreguse];
1041 rd->argintreguse += intregsneeded + 1;
1043 } else if (rd->freetmpinttop > intregsneeded) {
1044 rd->freetmpinttop -= intregsneeded + 1;
1045 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1047 s->regoff = PACK_REGS(
1048 rd->freetmpintregs[rd->freetmpinttop],
1049 rd->freetmpintregs[rd->freetmpinttop + 1]);
1052 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
1054 } else if (rd->tmpintreguse > intregsneeded) {
1055 rd->tmpintreguse -= intregsneeded + 1;
1056 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1058 s->regoff = PACK_REGS(
1059 rd->tmpintregs[rd->tmpintreguse],
1060 rd->tmpintregs[rd->tmpintreguse + 1]);
1063 s->regoff = rd->tmpintregs[rd->tmpintreguse];
1066 } /* if (!IS_2_WORD_TYPE(s->type)) */
1067 } /* if (IS_FLT_DBL_TYPE(s->type)) */
1068 } /* if (IS_ADR_TYPE(s->type)) */
1069 } /* if (tryagain == 1) else */
1070 } /* for(; tryagain; --tryagain) */
1072 #if defined(HAS_4BYTE_STACKSLOT)
1073 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
1075 s->regoff = rd->freemem_2[rd->freememtop_2];
1077 #endif /*defined(HAS_4BYTE_STACKSLOT) */
1078 if ((memneeded == 0) && (rd->freememtop > 0)) {
1080 s->regoff = rd->freemem[rd->freememtop];
1082 #if defined(HAS_4BYTE_STACKSLOT)
1083 /* align 2 Word Types */
1084 if ((memneeded) && ((rd->memuse & 1) == 1)) {
1085 /* Put patched memory slot on freemem */
1086 rd->freemem[rd->freememtop++] = rd->memuse;
1089 #endif /*defined(HAS_4BYTE_STACKSLOT) */
1090 s->regoff = rd->memuse;
1091 rd->memuse += memneeded + 1;
1093 s->flags |= INMEMORY;
1097 #define reg_free_temp(rd,s) if (s->varkind == TEMPVAR) reg_free_temp_func(rd, s)
1099 static void reg_free_temp_func(registerdata *rd, stackptr s)
1104 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1105 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
1110 #if defined(HAS_4BYTE_STACKSLOT)
1111 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
1116 if (s->flags & INMEMORY) {
1117 #if defined(HAS_4BYTE_STACKSLOT)
1118 if (memneeded > 0) {
1119 rd->freemem_2[rd->freememtop_2] = s->regoff;
1124 rd->freemem[rd->freememtop] = s->regoff;
1128 #ifdef HAS_ADDRESS_REGISTER_FILE
1129 } else if (IS_ADR_TYPE(s->type)) {
1130 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1131 s->flags &= ~SAVEDTMP;
1132 rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
1134 rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
1136 } else if (IS_FLT_DBL_TYPE(s->type)) {
1137 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1138 s->flags &= ~SAVEDTMP;
1139 rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
1140 } else if (s->flags & TMPARG) {
1141 s->flags &= ~TMPARG;
1142 rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
1144 rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
1145 } else { /* IS_INT_LNG_TYPE */
1146 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1147 s->flags &= ~SAVEDTMP;
1148 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1149 if (intregsneeded) {
1150 rd->freesavintregs[rd->freesavinttop] =
1151 GET_LOW_REG(s->regoff);
1152 rd->freesavintregs[rd->freesavinttop + 1] =
1153 GET_HIGH_REG(s->regoff);
1156 rd->freesavintregs[rd->freesavinttop] = s->regoff;
1157 rd->freesavinttop += intregsneeded + 1;
1159 } else if (s->flags & TMPARG) {
1160 s->flags &= ~TMPARG;
1161 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1162 if (intregsneeded) {
1163 rd->freeargintregs[rd->freearginttop] =
1164 GET_LOW_REG(s->regoff);
1165 rd->freeargintregs[rd->freearginttop + 1] =
1166 GET_HIGH_REG(s->regoff);
1169 rd->freeargintregs[rd->freearginttop] = s->regoff;
1170 rd->freearginttop += intregsneeded + 1;
1172 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1173 if (intregsneeded) {
1174 rd->freetmpintregs[rd->freetmpinttop] =
1175 GET_LOW_REG(s->regoff);
1176 rd->freetmpintregs[rd->freetmpinttop + 1] =
1177 GET_HIGH_REG(s->regoff);
1180 rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
1181 rd->freetmpinttop += intregsneeded + 1;
1188 static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
1198 builtintable_entry *bte;
1201 /* initialize temp registers */
1202 reg_init_temp(m, rd);
1204 bptr = m->basicblocks;
1206 while (bptr != NULL) {
1207 if (bptr->flags >= BBREACHED) {
1208 dst = bptr->instack;
1211 iptr = bptr->iinstr;
1214 while (--len >= 0) {
1224 case ICMD_ELSE_ICONST:
1225 case ICMD_CHECKNULL:
1231 case ICMD_PUTSTATICCONST:
1232 case ICMD_INLINE_START:
1233 case ICMD_INLINE_END:
1236 /* pop 0 push 1 const */
1244 /* pop 0 push 1 load */
1251 reg_new_temp(rd, dst);
1265 reg_free_temp(rd, src);
1266 reg_free_temp(rd, src->prev);
1267 reg_new_temp(rd, dst);
1281 reg_free_temp(rd, src);
1282 reg_free_temp(rd, src->prev);
1283 reg_free_temp(rd, src->prev->prev);
1286 /* pop 1 push 0 store */
1306 case ICMD_PUTSTATIC:
1307 case ICMD_PUTFIELDCONST:
1309 /* pop 1 push 0 branch */
1312 case ICMD_IFNONNULL:
1328 /* pop 1 push 0 table branch */
1330 case ICMD_TABLESWITCH:
1331 case ICMD_LOOKUPSWITCH:
1333 case ICMD_MONITORENTER:
1334 case ICMD_MONITOREXIT:
1335 reg_free_temp(rd, src);
1338 /* pop 2 push 0 branch */
1340 case ICMD_IF_ICMPEQ:
1341 case ICMD_IF_ICMPNE:
1342 case ICMD_IF_ICMPLT:
1343 case ICMD_IF_ICMPGE:
1344 case ICMD_IF_ICMPGT:
1345 case ICMD_IF_ICMPLE:
1347 case ICMD_IF_LCMPEQ:
1348 case ICMD_IF_LCMPNE:
1349 case ICMD_IF_LCMPLT:
1350 case ICMD_IF_LCMPGE:
1351 case ICMD_IF_LCMPGT:
1352 case ICMD_IF_LCMPLE:
1354 case ICMD_IF_ACMPEQ:
1355 case ICMD_IF_ACMPNE:
1363 case ICMD_IASTORECONST:
1364 case ICMD_LASTORECONST:
1365 case ICMD_AASTORECONST:
1366 case ICMD_BASTORECONST:
1367 case ICMD_CASTORECONST:
1368 case ICMD_SASTORECONST:
1369 reg_free_temp(rd, src);
1370 reg_free_temp(rd, src->prev);
1373 /* pop 0 push 1 dup */
1376 reg_new_temp(rd, dst);
1379 /* pop 0 push 2 dup */
1382 reg_new_temp(rd, dst->prev);
1383 reg_new_temp(rd, dst);
1386 /* pop 2 push 3 dup */
1389 reg_free_temp(rd, src);
1390 reg_new_temp(rd, dst);
1391 reg_free_temp(rd, src->prev);
1392 reg_new_temp(rd, dst->prev);
1393 reg_new_temp(rd, dst->prev->prev);
1396 /* pop 3 push 4 dup */
1399 reg_free_temp(rd, src);
1400 reg_new_temp(rd, dst);
1401 reg_free_temp(rd, src->prev);
1402 reg_new_temp(rd, dst->prev);
1403 reg_free_temp(rd, src->prev->prev);
1404 reg_new_temp(rd, dst->prev->prev);
1405 reg_new_temp(rd, dst->prev->prev->prev);
1408 /* pop 3 push 5 dup */
1411 reg_free_temp(rd, src);
1412 reg_new_temp(rd, dst);
1413 reg_free_temp(rd, src->prev);
1414 reg_new_temp(rd, dst->prev);
1415 reg_free_temp(rd, src->prev->prev);
1416 reg_new_temp(rd, dst->prev->prev);
1417 reg_new_temp(rd, dst->prev->prev->prev);
1418 reg_new_temp(rd, dst->prev->prev->prev->prev);
1421 /* pop 4 push 6 dup */
1424 reg_free_temp(rd, src);
1425 reg_new_temp(rd, dst);
1426 reg_free_temp(rd, src->prev);
1427 reg_new_temp(rd, dst->prev);
1428 reg_free_temp(rd, src->prev->prev);
1429 reg_new_temp(rd, dst->prev->prev);
1430 reg_free_temp(rd, src->prev->prev->prev);
1431 reg_new_temp(rd, dst->prev->prev->prev);
1432 reg_new_temp(rd, dst->prev->prev->prev->prev);
1433 reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
1436 /* pop 2 push 2 swap */
1439 reg_free_temp(rd, src);
1440 reg_new_temp(rd, dst->prev);
1441 reg_free_temp(rd, src->prev);
1442 reg_new_temp(rd, dst);
1491 reg_free_temp(rd, src);
1492 reg_free_temp(rd, src->prev);
1493 reg_new_temp(rd, dst);
1498 case ICMD_IADDCONST:
1499 case ICMD_ISUBCONST:
1500 case ICMD_IMULCONST:
1504 case ICMD_IANDCONST:
1506 case ICMD_IXORCONST:
1507 case ICMD_ISHLCONST:
1508 case ICMD_ISHRCONST:
1509 case ICMD_IUSHRCONST:
1511 case ICMD_LADDCONST:
1512 case ICMD_LSUBCONST:
1513 case ICMD_LMULCONST:
1517 case ICMD_LANDCONST:
1519 case ICMD_LXORCONST:
1520 case ICMD_LSHLCONST:
1521 case ICMD_LSHRCONST:
1522 case ICMD_LUSHRCONST:
1524 case ICMD_IFEQ_ICONST:
1525 case ICMD_IFNE_ICONST:
1526 case ICMD_IFLT_ICONST:
1527 case ICMD_IFGE_ICONST:
1528 case ICMD_IFGT_ICONST:
1529 case ICMD_IFLE_ICONST:
1534 case ICMD_INT2SHORT:
1552 case ICMD_CHECKCAST:
1554 case ICMD_ARRAYLENGTH:
1555 case ICMD_INSTANCEOF:
1558 case ICMD_ANEWARRAY:
1561 reg_free_temp(rd, src);
1562 reg_new_temp(rd, dst);
1567 case ICMD_GETSTATIC:
1570 reg_new_temp(rd, dst);
1573 /* pop many push any */
1575 case ICMD_INVOKESTATIC:
1576 case ICMD_INVOKESPECIAL:
1577 case ICMD_INVOKEVIRTUAL:
1578 case ICMD_INVOKEINTERFACE:
1582 md = lm->parseddesc;
1584 unresolved_method *um = iptr->target;
1585 md = um->methodref->parseddesc.md;
1589 reg_free_temp(rd, src);
1592 if (md->returntype.type != TYPE_VOID)
1593 reg_new_temp(rd, dst);
1601 reg_free_temp(rd, src);
1604 if (md->returntype.type != TYPE_VOID)
1605 reg_new_temp(rd, dst);
1608 case ICMD_MULTIANEWARRAY:
1611 reg_free_temp(rd, src);
1614 reg_new_temp(rd, dst);
1618 throw_cacao_exception_exit(string_java_lang_InternalError,
1619 "Unknown ICMD %d during register allocation",
1623 } /* while instructions */
1626 } /* while blocks */
1631 void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
1634 stackptr src, src_old;
1638 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1645 /* count how many local variables are held in memory or register */
1646 for(i=0; i < cd->maxlocals; i++)
1647 for (type=0; type <=4; type++)
1648 if (rd->locals[i][type].type != -1) { /* valid local */
1649 if (rd->locals[i][type].flags & INMEMORY) {
1650 count_locals_spilled++;
1654 count_locals_register++;
1656 /* count how many stack slots are held in memory or register */
1658 bptr = m->basicblocks;
1659 while (bptr != NULL) {
1660 if (bptr->flags >= BBREACHED) {
1665 /* check for memory moves from interface to BB instack */
1666 dst = bptr->instack;
1667 len = bptr->indepth;
1669 if (len > size_interface) size_interface = len;
1671 while (dst != NULL) {
1673 if (dst->varkind != STACKVAR) {
1674 if ( (dst->flags & INMEMORY) ||
1675 (rd->interfaces[len][dst->type].flags & INMEMORY) ||
1676 ( (dst->flags & INMEMORY) &&
1677 (rd->interfaces[len][dst->type].flags & INMEMORY) &&
1678 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1680 /* one in memory or both inmemory at different offsets */
1681 count_mem_move_bb++;
1689 /* check for memory moves from BB outstack to interface */
1690 dst = bptr->outstack;
1691 len = bptr->outdepth;
1692 if (len > size_interface) size_interface = len;
1696 if (dst->varkind != STACKVAR) {
1697 if ( (dst->flags & INMEMORY) || \
1698 (rd->interfaces[len][dst->type].flags & INMEMORY) || \
1699 ( (dst->flags & INMEMORY) && \
1700 (rd->interfaces[len][dst->type].flags & INMEMORY) && \
1701 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1703 /* one in memory or both inmemory at different offsets */
1704 count_mem_move_bb++;
1716 dst = bptr->instack;
1717 iptr = bptr->iinstr;
1721 while (--len >= 0) {
1725 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1726 switch (src->varkind) {
1729 if (!(src->flags & INMEMORY))
1730 count_ss_register++;
1736 /* case LOCALVAR: */
1737 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1738 /* count_ss_register++; */
1740 /* count_ss_spilled++; */
1743 if (!(src->flags & INMEMORY))
1744 count_argument_mem_ss++;
1746 count_argument_reg_ss++;
1750 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1751 /* if (src->varnum < FLT_ARG_CNT) { */
1752 /* count_ss_register++; */
1756 /* #if defined(__POWERPC__) */
1757 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1759 /* if (src->varnum < INT_ARG_CNT) { */
1761 /* count_ss_register++; */
1765 /* count_ss_spilled++; */
1772 } /* while instructions */
1775 } /* while blocks */
1776 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1777 if (in_register) count_method_in_register++;
1781 * These are local overrides for various environment variables in Emacs.
1782 * Please do not remove this and leave it at the end of the file, where
1783 * Emacs will automagically detect them.
1784 * ---------------------------------------------------------------------
1787 * indent-tabs-mode: t