1 /* src/vm/jit/allocator/simplereg.c - 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: simplereg.c 4386 2006-01-30 11:26:34Z christian $
47 #include "vm/builtin.h"
48 #include "vm/exceptions.h"
49 #include "mm/memory.h"
50 #include "vm/method.h"
51 #include "vm/options.h"
52 #include "vm/resolve.h"
53 #include "vm/stringlocal.h"
54 #include "vm/jit/reg.h"
55 #include "vm/jit/allocator/simplereg.h"
57 /* function prototypes for this file */
59 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
60 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
61 static void allocate_scratch_registers(methodinfo *m, registerdata *rd);
64 /* function interface_regalloc *************************************************
66 allocates registers for all interface variables
68 *******************************************************************************/
70 void regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
72 interface_regalloc(m, cd, rd);
73 allocate_scratch_registers(m, rd);
74 local_regalloc(m, cd, rd);
78 /* function interface_regalloc *************************************************
80 allocates registers for all interface variables
82 *******************************************************************************/
84 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
87 int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
88 /* in case a more vars are packed into this interface slot */
90 int intregsneeded = 0;
92 /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
93 /* on HAS_4BYTE_STACKSLOT architectures */
94 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
96 /* rd->memuse was already set in stack.c to allocate stack space for */
97 /* passing arguments to called methods */
99 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
100 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
106 for (s = 0; s < cd->maxstack; s++) {
107 intalloc = -1; fltalloc = -1;
108 saved = (rd->interfaces[s][TYPE_INT].flags |
109 rd->interfaces[s][TYPE_LNG].flags |
110 rd->interfaces[s][TYPE_FLT].flags |
111 rd->interfaces[s][TYPE_DBL].flags |
112 rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
114 for (tt = 0; tt <= 4; tt++) {
116 v = &rd->interfaces[s][t];
118 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
119 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
121 #if defined(HAS_4BYTE_STACKSLOT)
122 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
125 #if defined(HAS_ADDRESS_REGISTER_FILE)
126 if (IS_ADR_TYPE(t)) {
128 &&(rd->argadrreguse < ADR_ARG_CNT)) {
129 v->regoff = rd->argadrregs[rd->argadrreguse++];
130 } else if (rd->tmpadrreguse > 0) {
131 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
132 } else if (rd->savadrreguse > 0) {
133 v->regoff = rd->savadrregs[--rd->savadrreguse];
135 v->flags |= INMEMORY;
136 v->regoff = rd->memuse++;
138 } else /* !IS_ADR_TYPE */
139 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
141 if (IS_FLT_DBL_TYPE(t)) {
143 /* Reuse memory slot(s)/register(s) for shared interface slots */
144 v->flags |= rd->interfaces[s][fltalloc].flags
146 v->regoff = rd->interfaces[s][fltalloc].regoff;
147 } else if (!m->isleafmethod
148 && (rd->argfltreguse < FLT_ARG_CNT)) {
149 v->regoff = rd->argfltregs[rd->argfltreguse++];
150 } else if (rd->tmpfltreguse > 0) {
151 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
152 } else if (rd->savfltreguse > 0) {
153 v->regoff = rd->savfltregs[--rd->savfltreguse];
155 v->flags |= INMEMORY;
156 #if defined(ALIGN_DOUBLES_IN_MEMORY)
157 /* Align doubles in Memory */
158 if ( (memneeded) && (rd->memuse & 1))
161 v->regoff = rd->memuse;
162 rd->memuse += memneeded + 1;
165 } else { /* !IS_FLT_DBL_TYPE(t) */
166 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
168 * for i386 put all longs in memory
170 if (IS_2_WORD_TYPE(t)) {
171 v->flags |= INMEMORY;
172 #if defined(ALIGN_LONGS_IN_MEMORY)
173 /* Align longs in Memory */
177 v->regoff = rd->memuse;
178 rd->memuse += memneeded + 1;
180 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
182 /* Reuse memory slot(s)/register(s) for shared interface slots */
184 rd->interfaces[s][intalloc].flags
186 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
187 if (!(v->flags & INMEMORY)
188 && IS_2_WORD_TYPE(intalloc))
189 v->regoff = GET_LOW_REG(
190 rd->interfaces[s][intalloc].regoff);
194 rd->interfaces[s][intalloc].regoff;
196 if (!m->isleafmethod &&
198 + intregsneeded < INT_ARG_CNT)) {
199 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
202 rd->argintregs[rd->argintreguse],
203 rd->argintregs[rd->argintreguse + 1]);
207 rd->argintregs[rd->argintreguse];
208 rd->argintreguse += intregsneeded + 1;
210 else if (rd->tmpintreguse > intregsneeded) {
211 rd->tmpintreguse -= intregsneeded + 1;
212 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
215 rd->tmpintregs[rd->tmpintreguse],
216 rd->tmpintregs[rd->tmpintreguse + 1]);
220 rd->tmpintregs[rd->tmpintreguse];
222 else if (rd->savintreguse > intregsneeded) {
223 rd->savintreguse -= intregsneeded + 1;
225 rd->savintregs[rd->savintreguse];
226 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
229 rd->savintregs[rd->savintreguse],
230 rd->savintregs[rd->savintreguse + 1]);
234 rd->savintregs[rd->savintreguse];
237 v->flags |= INMEMORY;
238 #if defined(ALIGN_LONGS_IN_MEMORY)
239 /* Align longs in Memory */
240 if ( (memneeded) && (rd->memuse & 1))
243 v->regoff = rd->memuse;
244 rd->memuse += memneeded + 1;
248 } /* if (IS_FLT_DBL_TYPE(t)) */
250 } else { /* (saved) */
251 /* now the same like above, but without a chance to take a temporary register */
252 #ifdef HAS_ADDRESS_REGISTER_FILE
253 if (IS_ADR_TYPE(t)) {
254 if (rd->savadrreguse > 0) {
255 v->regoff = rd->savadrregs[--rd->savadrreguse];
258 v->flags |= INMEMORY;
259 v->regoff = rd->memuse++;
264 if (IS_FLT_DBL_TYPE(t)) {
266 v->flags |= rd->interfaces[s][fltalloc].flags
268 v->regoff = rd->interfaces[s][fltalloc].regoff;
270 if (rd->savfltreguse > 0) {
271 v->regoff = rd->savfltregs[--rd->savfltreguse];
274 v->flags |= INMEMORY;
275 #if defined(ALIGN_DOUBLES_IN_MEMORY)
276 /* Align doubles in Memory */
277 if ( (memneeded) && (rd->memuse & 1))
280 v->regoff = rd->memuse;
281 rd->memuse += memneeded + 1;
285 else { /* IS_INT_LNG */
286 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
288 * for i386 put all longs in memory
290 if (IS_2_WORD_TYPE(t)) {
291 v->flags |= INMEMORY;
292 #if defined(ALIGN_LONGS_IN_MEMORY)
293 /* Align longs in Memory */
297 v->regoff = rd->memuse;
298 rd->memuse += memneeded + 1;
304 rd->interfaces[s][intalloc].flags & INMEMORY;
305 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
306 if (!(v->flags & INMEMORY)
307 && IS_2_WORD_TYPE(intalloc))
310 rd->interfaces[s][intalloc].regoff);
314 rd->interfaces[s][intalloc].regoff;
316 if (rd->savintreguse > intregsneeded) {
317 rd->savintreguse -= intregsneeded + 1;
318 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
320 v->regoff = PACK_REGS(
321 rd->savintregs[rd->savintreguse],
322 rd->savintregs[rd->savintreguse + 1]);
326 rd->savintregs[rd->savintreguse];
328 v->flags |= INMEMORY;
329 #if defined(ALIGN_LONGS_IN_MEMORY)
330 /* Align longs in Memory */
331 if ( (memneeded) && (rd->memuse & 1))
334 v->regoff = rd->memuse;
335 rd->memuse += memneeded + 1;
340 } /* if (IS_FLT_DBL_TYPE(t) else */
341 } /* if (IS_ADR_TYPE(t)) else */
342 } /* if (saved) else */
343 } /* if (type >= 0) */
350 /* function local_regalloc *****************************************************
352 allocates registers for all local variables
354 *******************************************************************************/
356 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
359 int intalloc, fltalloc;
361 int intregsneeded = 0;
363 int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
364 int fargcnt, iargcnt;
365 #ifdef HAS_ADDRESS_REGISTER_FILE
369 if (m->isleafmethod) {
370 methoddesc *md = m->parseddesc;
372 iargcnt = md->argintreguse;
373 fargcnt = md->argfltreguse;
374 #ifdef HAS_ADDRESS_REGISTER_FILE
375 aargcnt = md->argadrreguse;
377 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
378 intalloc = -1; fltalloc = -1;
379 for (tt = 0; tt <= 4; tt++) {
381 v = &rd->locals[s][t];
386 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
387 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
389 #if defined(HAS_4BYTE_STACKSLOT)
390 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
396 * #ifdef HAS_ADDRESS_REGISTER_FILE
403 * } else { / int & lng
407 * must not to be changed!
410 #ifdef HAS_ADDRESS_REGISTER_FILE
411 if (IS_ADR_TYPE(t)) {
412 if ((p < md->paramcount) && !md->params[p].inmemory) {
414 v->regoff = rd->argadrregs[md->params[p].regoff];
416 else if (rd->tmpadrreguse > 0) {
418 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
420 /* use unused argument registers as local registers */
421 else if ((p >= md->paramcount) &&
422 (aargcnt < ADR_ARG_CNT)) {
424 v->regoff = rd->argadrregs[aargcnt++];
426 else if (rd->savadrreguse > 0) {
428 v->regoff = rd->savadrregs[--rd->savadrreguse];
431 v->flags |= INMEMORY;
432 v->regoff = rd->memuse++;
436 if (IS_FLT_DBL_TYPE(t)) {
438 v->flags = rd->locals[s][fltalloc].flags;
439 v->regoff = rd->locals[s][fltalloc].regoff;
441 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
442 /* We can only use float arguments as local variables,
443 * if we do not pass them in integer registers. */
444 else if ((p < md->paramcount) &&
445 !md->params[p].inmemory) {
447 v->regoff = rd->argfltregs[md->params[p].regoff];
450 else if (rd->tmpfltreguse > 0) {
452 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
454 /* use unused argument registers as local registers */
455 else if ((p >= md->paramcount) &&
456 (fargcnt < FLT_ARG_CNT)) {
458 v->regoff = rd->argfltregs[fargcnt];
461 else if (rd->savfltreguse > 0) {
463 v->regoff = rd->savfltregs[--rd->savfltreguse];
467 #if defined(ALIGN_DOUBLES_IN_MEMORY)
468 /* Align doubles in Memory */
469 if ( (memneeded) && (rd->memuse & 1))
472 v->regoff = rd->memuse;
473 rd->memuse += memneeded + 1;
478 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
480 * for i386 put all longs in memory
482 if (IS_2_WORD_TYPE(t)) {
484 #if defined(ALIGN_LONGS_IN_MEMORY)
485 /* Align longs in Memory */
489 v->regoff = rd->memuse;
490 rd->memuse += memneeded + 1;
495 v->flags = rd->locals[s][intalloc].flags;
496 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
497 if (!(v->flags & INMEMORY)
498 && IS_2_WORD_TYPE(intalloc))
499 v->regoff = GET_LOW_REG(
500 rd->locals[s][intalloc].regoff);
503 v->regoff = rd->locals[s][intalloc].regoff;
505 else if ((p < md->paramcount) &&
506 !md->params[p].inmemory) {
508 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
509 if (IS_2_WORD_TYPE(t))
510 v->regoff = PACK_REGS(
511 rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
512 rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
516 rd->argintregs[md->params[p].regoff];
518 else if (rd->tmpintreguse > intregsneeded) {
519 rd->tmpintreguse -= intregsneeded + 1;
521 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
523 v->regoff = PACK_REGS(
524 rd->tmpintregs[rd->tmpintreguse],
525 rd->tmpintregs[rd->tmpintreguse + 1]);
529 rd->tmpintregs[rd->tmpintreguse];
532 * use unused argument registers as local registers
534 else if ((p >= m->parseddesc->paramcount) &&
535 (iargcnt + intregsneeded < INT_ARG_CNT)) {
537 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
540 rd->argintregs[iargcnt],
541 rd->argintregs[iargcnt + 1]);
544 v->regoff = rd->argintregs[iargcnt];
545 iargcnt += intregsneeded + 1;
547 else if (rd->savintreguse > intregsneeded) {
548 rd->savintreguse -= intregsneeded + 1;
550 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
552 v->regoff = PACK_REGS(
553 rd->savintregs[rd->savintreguse],
554 rd->savintregs[rd->savintreguse + 1]);
557 v->regoff =rd->savintregs[rd->savintreguse];
561 #if defined(ALIGN_LONGS_IN_MEMORY)
562 /* Align longs in Memory */
563 if ( (memneeded) && (rd->memuse & 1))
566 v->regoff = rd->memuse;
567 rd->memuse += memneeded + 1;
572 #ifdef HAS_ADDRESS_REGISTER_FILE
575 } /* for (tt=0;...) */
577 /* If the current parameter is a 2-word type, the next local slot */
580 if (p < md->paramcount)
581 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
587 for (s = 0; s < cd->maxlocals; s++) {
588 intalloc = -1; fltalloc = -1;
589 for (tt=0; tt<=4; tt++) {
591 v = &rd->locals[s][t];
594 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
595 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
597 #if defined(HAS_4BYTE_STACKSLOT)
598 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
600 #ifdef HAS_ADDRESS_REGISTER_FILE
601 if ( IS_ADR_TYPE(t) ) {
602 if (rd->savadrreguse > 0) {
604 v->regoff = rd->savadrregs[--rd->savadrreguse];
608 v->regoff = rd->memuse++;
612 if (IS_FLT_DBL_TYPE(t)) {
614 v->flags = rd->locals[s][fltalloc].flags;
615 v->regoff = rd->locals[s][fltalloc].regoff;
617 else if (rd->savfltreguse > 0) {
619 v->regoff = rd->savfltregs[--rd->savfltreguse];
623 #if defined(ALIGN_DOUBLES_IN_MEMORY)
624 /* Align doubles in Memory */
625 if ( (memneeded) && (rd->memuse & 1))
628 v->regoff = rd->memuse;
629 rd->memuse += memneeded + 1;
634 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
636 * for i386 put all longs in memory
638 if (IS_2_WORD_TYPE(t)) {
640 #if defined(ALIGN_LONGS_IN_MEMORY)
641 /* Align longs in Memory */
645 v->regoff = rd->memuse;
646 rd->memuse += memneeded + 1;
650 v->flags = rd->locals[s][intalloc].flags;
651 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
652 if (!(v->flags & INMEMORY)
653 && IS_2_WORD_TYPE(intalloc))
654 v->regoff = GET_LOW_REG(
655 rd->locals[s][intalloc].regoff);
658 v->regoff = rd->locals[s][intalloc].regoff;
660 else if (rd->savintreguse > intregsneeded) {
661 rd->savintreguse -= intregsneeded+1;
663 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
665 v->regoff = PACK_REGS(
666 rd->savintregs[rd->savintreguse],
667 rd->savintregs[rd->savintreguse + 1]);
670 v->regoff =rd->savintregs[rd->savintreguse];
674 #if defined(ALIGN_LONGS_IN_MEMORY)
675 /* Align longs in Memory */
676 if ( (memneeded) && (rd->memuse & 1))
679 v->regoff = rd->memuse;
680 rd->memuse += memneeded + 1;
682 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
687 #ifdef HAS_ADDRESS_REGISTER_FILE
696 static void reg_init_temp(methodinfo *m, registerdata *rd)
699 #if defined(HAS_4BYTE_STACKSLOT)
700 rd->freememtop_2 = 0;
703 rd->freetmpinttop = 0;
704 rd->freesavinttop = 0;
705 rd->freetmpflttop = 0;
706 rd->freesavflttop = 0;
707 #ifdef HAS_ADDRESS_REGISTER_FILE
708 rd->freetmpadrtop = 0;
709 rd->freesavadrtop = 0;
712 rd->freearginttop = 0;
713 rd->freeargflttop = 0;
714 #ifdef HAS_ADDRESS_REGISTER_FILE
715 rd->freeargadrtop = 0;
718 if (m->isleafmethod) {
719 /* Don't use not used Argument Registers in Leafmethods -> they could */
720 /* already be in use for Locals passed as parameter to this Method */
721 rd->argintreguse = INT_ARG_CNT;
722 rd->argfltreguse = FLT_ARG_CNT;
723 #ifdef HAS_ADDRESS_REGISTER_FILE
724 rd->argadrreguse = ADR_ARG_CNT;
730 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
732 static void reg_new_temp_func(registerdata *rd, stackptr s)
738 /* Try to allocate a saved register if there is no temporary one */
739 /* available. This is what happens during the second run. */
740 tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
742 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
743 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
747 #if defined(HAS_4BYTE_STACKSLOT)
748 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
753 for(; tryagain; --tryagain) {
755 if (!(s->flags & SAVEDVAR))
756 s->flags |= SAVEDTMP;
757 #ifdef HAS_ADDRESS_REGISTER_FILE
758 if (IS_ADR_TYPE(s->type)) {
759 if (rd->freesavadrtop > 0) {
760 s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
762 } else if (rd->savadrreguse > 0) {
763 s->regoff = rd->savadrregs[--rd->savadrreguse];
769 if (IS_FLT_DBL_TYPE(s->type)) {
770 if (rd->freesavflttop > 0) {
771 s->regoff = rd->freesavfltregs[--rd->freesavflttop];
773 } else if (rd->savfltreguse > 0) {
774 s->regoff = rd->savfltregs[--rd->savfltreguse];
778 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
780 * for i386 put all longs in memory
782 if (!IS_2_WORD_TYPE(s->type))
785 if (rd->freesavinttop > intregsneeded) {
786 rd->freesavinttop -= intregsneeded + 1;
787 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
789 s->regoff = PACK_REGS(
790 rd->freesavintregs[rd->freesavinttop],
791 rd->freesavintregs[rd->freesavinttop + 1]);
795 rd->freesavintregs[rd->freesavinttop];
797 } else if (rd->savintreguse > intregsneeded) {
798 rd->savintreguse -= intregsneeded + 1;
799 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
801 s->regoff = PACK_REGS(
802 rd->savintregs[rd->savintreguse],
803 rd->savintregs[rd->savintreguse + 1]);
806 s->regoff = rd->savintregs[rd->savintreguse];
812 } else { /* tryagain == 2 */
813 #ifdef HAS_ADDRESS_REGISTER_FILE
814 if (IS_ADR_TYPE(s->type)) {
815 if (rd->freetmpadrtop > 0) {
816 s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
818 } else if (rd->tmpadrreguse > 0) {
819 s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
825 if (IS_FLT_DBL_TYPE(s->type)) {
826 if (rd->freeargflttop > 0) {
827 s->regoff = rd->freeargfltregs[--rd->freeargflttop];
830 } else if (rd->argfltreguse < FLT_ARG_CNT) {
831 s->regoff = rd->argfltregs[rd->argfltreguse++];
834 } else if (rd->freetmpflttop > 0) {
835 s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
837 } else if (rd->tmpfltreguse > 0) {
838 s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
843 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
845 * for i386 put all longs in memory
847 if (!IS_2_WORD_TYPE(s->type))
850 if (rd->freearginttop > intregsneeded) {
851 rd->freearginttop -= intregsneeded + 1;
853 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
855 s->regoff = PACK_REGS(
856 rd->freeargintregs[rd->freearginttop],
857 rd->freeargintregs[rd->freearginttop + 1]);
861 rd->freeargintregs[rd->freearginttop];
863 } else if (rd->argintreguse
864 < INT_ARG_CNT - intregsneeded) {
865 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
867 s->regoff = PACK_REGS(
868 rd->argintregs[rd->argintreguse],
869 rd->argintregs[rd->argintreguse + 1]);
872 s->regoff = rd->argintregs[rd->argintreguse];
874 rd->argintreguse += intregsneeded + 1;
876 } else if (rd->freetmpinttop > intregsneeded) {
877 rd->freetmpinttop -= intregsneeded + 1;
878 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
880 s->regoff = PACK_REGS(
881 rd->freetmpintregs[rd->freetmpinttop],
882 rd->freetmpintregs[rd->freetmpinttop + 1]);
885 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
887 } else if (rd->tmpintreguse > intregsneeded) {
888 rd->tmpintreguse -= intregsneeded + 1;
889 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
891 s->regoff = PACK_REGS(
892 rd->tmpintregs[rd->tmpintreguse],
893 rd->tmpintregs[rd->tmpintreguse + 1]);
896 s->regoff = rd->tmpintregs[rd->tmpintreguse];
899 } /* if (!IS_2_WORD_TYPE(s->type)) */
900 } /* if (IS_FLT_DBL_TYPE(s->type)) */
901 } /* if (IS_ADR_TYPE(s->type)) */
902 } /* if (tryagain == 1) else */
903 } /* for(; tryagain; --tryagain) */
905 #if defined(HAS_4BYTE_STACKSLOT)
906 if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
908 s->regoff = rd->freemem_2[rd->freememtop_2];
910 #endif /*defined(HAS_4BYTE_STACKSLOT) */
911 if ((memneeded == 0) && (rd->freememtop > 0)) {
913 s->regoff = rd->freemem[rd->freememtop];
915 #if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
916 /* align 2 Word Types */
917 if ((memneeded) && ((rd->memuse & 1) == 1)) {
918 /* Put patched memory slot on freemem */
919 rd->freemem[rd->freememtop++] = rd->memuse;
922 #endif /* defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY) */
923 s->regoff = rd->memuse;
924 rd->memuse += memneeded + 1;
926 s->flags |= INMEMORY;
930 #define reg_free_temp(rd,s) if (s->varkind == TEMPVAR) reg_free_temp_func(rd, s)
932 static void reg_free_temp_func(registerdata *rd, stackptr s)
937 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
938 intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
943 #if defined(HAS_4BYTE_STACKSLOT)
944 memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
949 if (s->flags & INMEMORY) {
950 #if defined(HAS_4BYTE_STACKSLOT)
952 rd->freemem_2[rd->freememtop_2] = s->regoff;
957 rd->freemem[rd->freememtop] = s->regoff;
961 #ifdef HAS_ADDRESS_REGISTER_FILE
962 } else if (IS_ADR_TYPE(s->type)) {
963 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
964 s->flags &= ~SAVEDTMP;
965 rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
967 rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
969 } else if (IS_FLT_DBL_TYPE(s->type)) {
970 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
971 s->flags &= ~SAVEDTMP;
972 rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
973 } else if (s->flags & TMPARG) {
975 rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
977 rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
978 } else { /* IS_INT_LNG_TYPE */
979 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
980 s->flags &= ~SAVEDTMP;
981 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
983 rd->freesavintregs[rd->freesavinttop] =
984 GET_LOW_REG(s->regoff);
985 rd->freesavintregs[rd->freesavinttop + 1] =
986 GET_HIGH_REG(s->regoff);
989 rd->freesavintregs[rd->freesavinttop] = s->regoff;
990 rd->freesavinttop += intregsneeded + 1;
992 } else if (s->flags & TMPARG) {
994 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
996 rd->freeargintregs[rd->freearginttop] =
997 GET_LOW_REG(s->regoff);
998 rd->freeargintregs[rd->freearginttop + 1] =
999 GET_HIGH_REG(s->regoff);
1002 rd->freeargintregs[rd->freearginttop] = s->regoff;
1003 rd->freearginttop += intregsneeded + 1;
1005 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1006 if (intregsneeded) {
1007 rd->freetmpintregs[rd->freetmpinttop] =
1008 GET_LOW_REG(s->regoff);
1009 rd->freetmpintregs[rd->freetmpinttop + 1] =
1010 GET_HIGH_REG(s->regoff);
1013 rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
1014 rd->freetmpinttop += intregsneeded + 1;
1021 static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
1031 builtintable_entry *bte;
1034 /* initialize temp registers */
1035 reg_init_temp(m, rd);
1037 bptr = m->basicblocks;
1039 while (bptr != NULL) {
1040 if (bptr->flags >= BBREACHED) {
1041 dst = bptr->instack;
1044 iptr = bptr->iinstr;
1047 while (--len >= 0) {
1057 case ICMD_ELSE_ICONST:
1058 case ICMD_CHECKNULL:
1064 case ICMD_PUTSTATICCONST:
1065 case ICMD_INLINE_START:
1066 case ICMD_INLINE_END:
1069 /* pop 0 push 1 const */
1077 /* pop 0 push 1 load */
1084 reg_new_temp(rd, dst);
1098 reg_free_temp(rd, src);
1099 reg_free_temp(rd, src->prev);
1100 reg_new_temp(rd, dst);
1114 reg_free_temp(rd, src);
1115 reg_free_temp(rd, src->prev);
1116 reg_free_temp(rd, src->prev->prev);
1119 /* pop 1 push 0 store */
1139 case ICMD_PUTSTATIC:
1140 case ICMD_PUTFIELDCONST:
1142 /* pop 1 push 0 branch */
1145 case ICMD_IFNONNULL:
1161 /* pop 1 push 0 table branch */
1163 case ICMD_TABLESWITCH:
1164 case ICMD_LOOKUPSWITCH:
1166 case ICMD_MONITORENTER:
1167 case ICMD_MONITOREXIT:
1168 reg_free_temp(rd, src);
1171 /* pop 2 push 0 branch */
1173 case ICMD_IF_ICMPEQ:
1174 case ICMD_IF_ICMPNE:
1175 case ICMD_IF_ICMPLT:
1176 case ICMD_IF_ICMPGE:
1177 case ICMD_IF_ICMPGT:
1178 case ICMD_IF_ICMPLE:
1180 case ICMD_IF_LCMPEQ:
1181 case ICMD_IF_LCMPNE:
1182 case ICMD_IF_LCMPLT:
1183 case ICMD_IF_LCMPGE:
1184 case ICMD_IF_LCMPGT:
1185 case ICMD_IF_LCMPLE:
1187 case ICMD_IF_ACMPEQ:
1188 case ICMD_IF_ACMPNE:
1196 case ICMD_IASTORECONST:
1197 case ICMD_LASTORECONST:
1198 case ICMD_AASTORECONST:
1199 case ICMD_BASTORECONST:
1200 case ICMD_CASTORECONST:
1201 case ICMD_SASTORECONST:
1202 reg_free_temp(rd, src);
1203 reg_free_temp(rd, src->prev);
1206 /* pop 0 push 1 dup */
1209 reg_new_temp(rd, dst);
1212 /* pop 0 push 2 dup */
1215 reg_new_temp(rd, dst->prev);
1216 reg_new_temp(rd, dst);
1219 /* pop 2 push 3 dup */
1222 reg_free_temp(rd, src);
1223 reg_new_temp(rd, dst);
1224 reg_free_temp(rd, src->prev);
1225 reg_new_temp(rd, dst->prev);
1226 reg_new_temp(rd, dst->prev->prev);
1229 /* pop 3 push 4 dup */
1232 reg_free_temp(rd, src);
1233 reg_new_temp(rd, dst);
1234 reg_free_temp(rd, src->prev);
1235 reg_new_temp(rd, dst->prev);
1236 reg_free_temp(rd, src->prev->prev);
1237 reg_new_temp(rd, dst->prev->prev);
1238 reg_new_temp(rd, dst->prev->prev->prev);
1241 /* pop 3 push 5 dup */
1244 reg_free_temp(rd, src);
1245 reg_new_temp(rd, dst);
1246 reg_free_temp(rd, src->prev);
1247 reg_new_temp(rd, dst->prev);
1248 reg_free_temp(rd, src->prev->prev);
1249 reg_new_temp(rd, dst->prev->prev);
1250 reg_new_temp(rd, dst->prev->prev->prev);
1251 reg_new_temp(rd, dst->prev->prev->prev->prev);
1254 /* pop 4 push 6 dup */
1257 reg_free_temp(rd, src);
1258 reg_new_temp(rd, dst);
1259 reg_free_temp(rd, src->prev);
1260 reg_new_temp(rd, dst->prev);
1261 reg_free_temp(rd, src->prev->prev);
1262 reg_new_temp(rd, dst->prev->prev);
1263 reg_free_temp(rd, src->prev->prev->prev);
1264 reg_new_temp(rd, dst->prev->prev->prev);
1265 reg_new_temp(rd, dst->prev->prev->prev->prev);
1266 reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
1269 /* pop 2 push 2 swap */
1272 reg_free_temp(rd, src);
1273 reg_new_temp(rd, dst->prev);
1274 reg_free_temp(rd, src->prev);
1275 reg_new_temp(rd, dst);
1324 reg_free_temp(rd, src);
1325 reg_free_temp(rd, src->prev);
1326 reg_new_temp(rd, dst);
1331 case ICMD_IADDCONST:
1332 case ICMD_ISUBCONST:
1333 case ICMD_IMULCONST:
1337 case ICMD_IANDCONST:
1339 case ICMD_IXORCONST:
1340 case ICMD_ISHLCONST:
1341 case ICMD_ISHRCONST:
1342 case ICMD_IUSHRCONST:
1344 case ICMD_LADDCONST:
1345 case ICMD_LSUBCONST:
1346 case ICMD_LMULCONST:
1350 case ICMD_LANDCONST:
1352 case ICMD_LXORCONST:
1353 case ICMD_LSHLCONST:
1354 case ICMD_LSHRCONST:
1355 case ICMD_LUSHRCONST:
1357 case ICMD_IFEQ_ICONST:
1358 case ICMD_IFNE_ICONST:
1359 case ICMD_IFLT_ICONST:
1360 case ICMD_IFGE_ICONST:
1361 case ICMD_IFGT_ICONST:
1362 case ICMD_IFLE_ICONST:
1367 case ICMD_INT2SHORT:
1385 case ICMD_CHECKCAST:
1387 case ICMD_ARRAYLENGTH:
1388 case ICMD_INSTANCEOF:
1391 case ICMD_ANEWARRAY:
1394 reg_free_temp(rd, src);
1395 reg_new_temp(rd, dst);
1400 case ICMD_GETSTATIC:
1403 reg_new_temp(rd, dst);
1406 /* pop many push any */
1408 case ICMD_INVOKESTATIC:
1409 case ICMD_INVOKESPECIAL:
1410 case ICMD_INVOKEVIRTUAL:
1411 case ICMD_INVOKEINTERFACE:
1415 md = lm->parseddesc;
1417 unresolved_method *um = iptr->target;
1418 md = um->methodref->parseddesc.md;
1422 reg_free_temp(rd, src);
1425 if (md->returntype.type != TYPE_VOID)
1426 reg_new_temp(rd, dst);
1434 reg_free_temp(rd, src);
1437 if (md->returntype.type != TYPE_VOID)
1438 reg_new_temp(rd, dst);
1441 case ICMD_MULTIANEWARRAY:
1444 reg_free_temp(rd, src);
1447 reg_new_temp(rd, dst);
1451 throw_cacao_exception_exit(string_java_lang_InternalError,
1452 "Unknown ICMD %d during register allocation",
1456 } /* while instructions */
1459 } /* while blocks */
1463 #if defined(ENABLE_STATISTICS)
1464 void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
1467 stackptr src, src_old;
1471 int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1478 /* count how many local variables are held in memory or register */
1479 for(i=0; i < cd->maxlocals; i++)
1480 for (type=0; type <=4; type++)
1481 if (rd->locals[i][type].type != -1) { /* valid local */
1482 if (rd->locals[i][type].flags & INMEMORY) {
1483 count_locals_spilled++;
1487 count_locals_register++;
1489 /* count how many stack slots are held in memory or register */
1491 bptr = m->basicblocks;
1492 while (bptr != NULL) {
1493 if (bptr->flags >= BBREACHED) {
1495 #if defined(ENABLE_LSRA)
1498 /* check for memory moves from interface to BB instack */
1499 dst = bptr->instack;
1500 len = bptr->indepth;
1502 if (len > size_interface) size_interface = len;
1504 while (dst != NULL) {
1506 if (dst->varkind != STACKVAR) {
1507 if ( (dst->flags & INMEMORY) ||
1508 (rd->interfaces[len][dst->type].flags & INMEMORY) ||
1509 ( (dst->flags & INMEMORY) &&
1510 (rd->interfaces[len][dst->type].flags & INMEMORY) &&
1511 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1513 /* one in memory or both inmemory at different offsets */
1514 count_mem_move_bb++;
1522 /* check for memory moves from BB outstack to interface */
1523 dst = bptr->outstack;
1524 len = bptr->outdepth;
1525 if (len > size_interface) size_interface = len;
1529 if (dst->varkind != STACKVAR) {
1530 if ( (dst->flags & INMEMORY) || \
1531 (rd->interfaces[len][dst->type].flags & INMEMORY) || \
1532 ( (dst->flags & INMEMORY) && \
1533 (rd->interfaces[len][dst->type].flags & INMEMORY) && \
1534 (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1536 /* one in memory or both inmemory at different offsets */
1537 count_mem_move_bb++;
1544 #if defined(ENABLE_LSRA)
1549 dst = bptr->instack;
1550 iptr = bptr->iinstr;
1554 while (--len >= 0) {
1558 if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1559 switch (src->varkind) {
1562 if (!(src->flags & INMEMORY))
1563 count_ss_register++;
1569 /* case LOCALVAR: */
1570 /* if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1571 /* count_ss_register++; */
1573 /* count_ss_spilled++; */
1576 if (!(src->flags & INMEMORY))
1577 count_argument_mem_ss++;
1579 count_argument_reg_ss++;
1583 /* if (IS_FLT_DBL_TYPE(src->type)) { */
1584 /* if (src->varnum < FLT_ARG_CNT) { */
1585 /* count_ss_register++; */
1589 /* #if defined(__POWERPC__) */
1590 /* if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1592 /* if (src->varnum < INT_ARG_CNT) { */
1594 /* count_ss_register++; */
1598 /* count_ss_spilled++; */
1605 } /* while instructions */
1608 } /* while blocks */
1609 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1610 if (in_register) count_method_in_register++;
1612 #endif /* defined(ENABLE_STATISTICS) */
1616 * These are local overrides for various environment variables in Emacs.
1617 * Please do not remove this and leave it at the end of the file, where
1618 * Emacs will automagically detect them.
1619 * ---------------------------------------------------------------------
1622 * indent-tabs-mode: t