1 /* jit/reg.c *******************************************************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
9 Authors: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
11 Last Change: 1998/11/09
13 *******************************************************************************/
15 static varinfo5 *locals;
16 static varinfo5 *interfaces;
18 static int intregsnum; /* absolute number of integer registers */
19 static int floatregsnum; /* absolute number of float registers */
21 static int intreg_ret; /* register to return integer values */
22 static int intreg_argnum; /* number of integer argument registers */
24 static int floatreg_ret; /* register for return float values */
25 static int fltreg_argnum; /* number of float argument registers */
28 static int *argintregs; /* scratch integer registers */
29 static int *tmpintregs = NULL; /* scratch integer registers */
30 static int *savintregs; /* saved integer registers */
31 static int *argfltregs; /* scratch float registers */
32 static int *tmpfltregs; /* scratch float registers */
33 static int *savfltregs; /* saved float registers */
34 static int *freetmpintregs; /* free scratch integer registers */
35 static int *freesavintregs; /* free saved integer registers */
36 static int *freetmpfltregs; /* free scratch float registers */
37 static int *freesavfltregs; /* free saved float registers */
39 static int *freemem; /* free scratch memory */
40 static int memuse; /* used memory count */
41 static int ifmemuse; /* interface used memory count */
42 static int maxmemuse; /* maximal used memory count (spills) */
43 static int freememtop; /* free memory count */
45 static int tmpintregcnt; /* scratch integer register count */
46 static int savintregcnt; /* saved integer register count */
47 static int tmpfltregcnt; /* scratch float register count */
48 static int savfltregcnt; /* saved float register count */
50 static int iftmpintregcnt; /* iface scratch integer register count */
51 static int ifsavintregcnt; /* iface saved integer register count */
52 static int iftmpfltregcnt; /* iface scratch float register count */
53 static int ifsavfltregcnt; /* iface saved float register count */
55 static int tmpintreguse; /* used scratch integer register count */
56 static int savintreguse; /* used saved integer register count */
57 static int tmpfltreguse; /* used scratch float register count */
58 static int savfltreguse; /* used saved float register count */
60 static int maxtmpintreguse; /* max used scratch int register count */
61 static int maxsavintreguse; /* max used saved int register count */
62 static int maxtmpfltreguse; /* max used scratch float register count */
63 static int maxsavfltreguse; /* max used saved float register count */
65 static int freetmpinttop; /* free scratch integer register count */
66 static int freesavinttop; /* free saved integer register count */
67 static int freetmpflttop; /* free scratch float register count */
68 static int freesavflttop; /* free saved float register count */
70 static int savedregs_num; /* total number of registers to be saved */
71 static int arguments_num; /* size of parameter field in the stackframe */
75 /* function reg_init ***********************************************************
77 initialises the register-allocator
79 *******************************************************************************/
81 static void reg_init()
87 if (TYPE_INT != 0 || TYPE_ADR != 4)
88 panic ("JAVA-Basictypes have been changed");
94 for (intregsnum = 0; nregdescint[intregsnum] != REG_END; intregsnum++) {
95 switch (nregdescint[intregsnum]) {
96 case REG_SAV: savintregcnt++;
98 case REG_TMP: tmpintregcnt++;
100 case REG_ARG: intreg_argnum++;
104 argintregs = MNEW (int, intreg_argnum);
105 tmpintregs = MNEW (int, tmpintregcnt);
106 savintregs = MNEW (int, savintregcnt);
107 freetmpintregs = MNEW (int, tmpintregcnt);
108 freesavintregs = MNEW (int, savintregcnt);
114 for (n = 0; n < intregsnum; n++) {
115 switch (nregdescint[n]) {
116 case REG_RET: intreg_ret = n;
118 case REG_SAV: savintregs[savintreguse++] = n;
120 case REG_TMP: tmpintregs[tmpintreguse++] = n;
122 case REG_ARG: argintregs[intreg_argnum++] = n;
132 for (floatregsnum = 0; nregdescfloat[floatregsnum] != REG_END; floatregsnum++) {
133 switch (nregdescfloat[floatregsnum]) {
134 case REG_SAV: savfltregcnt++;
136 case REG_TMP: tmpfltregcnt++;
138 case REG_ARG: fltreg_argnum++;
143 argfltregs = MNEW (int, fltreg_argnum);
144 tmpfltregs = MNEW (int, tmpfltregcnt);
145 savfltregs = MNEW (int, savfltregcnt);
146 freetmpfltregs = MNEW (int, tmpfltregcnt);
147 freesavfltregs = MNEW (int, savfltregcnt);
153 for (n = 0; n < floatregsnum; n++) {
154 switch (nregdescfloat[n]) {
155 case REG_RET: floatreg_ret = n;
157 case REG_SAV: savfltregs[savfltreguse++] = n;
159 case REG_TMP: tmpfltregs[tmpfltreguse++] = n;
161 case REG_ARG: argfltregs[fltreg_argnum++] = n;
171 /* function reg_close **********************************************************
173 releases all allocated space for registers
175 *******************************************************************************/
177 static void reg_close ()
179 if (argintregs) MFREE (argintregs, int, intreg_argnum);
180 if (argfltregs) MFREE (argfltregs, int, fltreg_argnum);
181 if (tmpintregs) MFREE (tmpintregs, int, tmpintregcnt);
182 if (savintregs) MFREE (savintregs, int, savintregcnt);
183 if (tmpfltregs) MFREE (tmpfltregs, int, tmpfltregcnt);
184 if (savfltregs) MFREE (savfltregs, int, savfltregcnt);
186 if (freetmpintregs) MFREE (freetmpintregs, int, tmpintregcnt);
187 if (freesavintregs) MFREE (freesavintregs, int, savintregcnt);
188 if (freetmpfltregs) MFREE (freetmpfltregs, int, tmpfltregcnt);
189 if (freesavfltregs) MFREE (freesavfltregs, int, savfltregcnt);
193 /* function local_init *********************************************************
195 initialises the local variable and interfaces table
197 *******************************************************************************/
199 static void local_init()
204 freemem = DMNEW(int, maxstack);
205 locals = DMNEW(varinfo5, maxlocals);
206 interfaces = DMNEW(varinfo5, maxstack);
208 for (v = locals, i = maxlocals; i > 0; v++, i--) {
209 v[0][TYPE_INT].type = -1;
210 v[0][TYPE_LNG].type = -1;
211 v[0][TYPE_FLT].type = -1;
212 v[0][TYPE_DBL].type = -1;
213 v[0][TYPE_ADR].type = -1;
216 for (v = interfaces, i = maxstack; i > 0; v++, i--) {
217 v[0][TYPE_INT].type = -1;
218 v[0][TYPE_INT].flags = 0;
219 v[0][TYPE_LNG].type = -1;
220 v[0][TYPE_LNG].flags = 0;
221 v[0][TYPE_FLT].type = -1;
222 v[0][TYPE_FLT].flags = 0;
223 v[0][TYPE_DBL].type = -1;
224 v[0][TYPE_DBL].flags = 0;
225 v[0][TYPE_ADR].type = -1;
226 v[0][TYPE_ADR].flags = 0;
231 /* function interface_regalloc *************************************************
233 allocates registers for all interface variables
235 *******************************************************************************/
237 static void interface_regalloc ()
240 int intalloc, fltalloc;
243 /* allocate stack space for passing arguments to called methods */
245 if (arguments_num > intreg_argnum)
246 ifmemuse = arguments_num - intreg_argnum;
250 iftmpintregcnt = tmpintregcnt;
251 ifsavintregcnt = savintregcnt;
252 iftmpfltregcnt = tmpfltregcnt;
253 ifsavfltregcnt = savfltregcnt;
255 for (s = 0; s < maxstack; s++) {
256 intalloc = -1; fltalloc = -1;
257 saved = (interfaces[s][TYPE_INT].flags | interfaces[s][TYPE_LNG].flags |
258 interfaces[s][TYPE_FLT].flags | interfaces[s][TYPE_DBL].flags |
259 interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
260 for (t = TYPE_INT; t <= TYPE_ADR; t++) {
261 v = &interfaces[s][t];
264 if (IS_FLT_DBL_TYPE(t)) {
266 v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
267 v->regoff = interfaces[s][fltalloc].regoff;
269 else if (iftmpfltregcnt > 0) {
271 v->regoff = tmpfltregs[iftmpfltregcnt];
273 else if (ifsavfltregcnt > 0) {
275 v->regoff = savfltregs[ifsavfltregcnt];
278 v->flags |= INMEMORY;
279 v->regoff = ifmemuse++;
285 v->flags |= interfaces[s][intalloc].flags & INMEMORY;
286 v->regoff = interfaces[s][intalloc].regoff;
288 else if (iftmpintregcnt > 0) {
290 v->regoff = tmpintregs[iftmpintregcnt];
292 else if (ifsavintregcnt > 0) {
294 v->regoff = savintregs[ifsavintregcnt];
297 v->flags |= INMEMORY;
298 v->regoff = ifmemuse++;
304 if (IS_FLT_DBL_TYPE(t)) {
306 v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
307 v->regoff = interfaces[s][fltalloc].regoff;
309 else if (ifsavfltregcnt > 0) {
311 v->regoff = savfltregs[ifsavfltregcnt];
314 v->flags |= INMEMORY;
315 v->regoff = ifmemuse++;
321 v->flags |= interfaces[s][intalloc].flags & INMEMORY;
322 v->regoff = interfaces[s][intalloc].regoff;
324 else if (ifsavintregcnt > 0) {
326 v->regoff = savintregs[ifsavintregcnt];
329 v->flags |= INMEMORY;
330 v->regoff = ifmemuse++;
335 } /* if (type >= 0) */
338 maxmemuse = ifmemuse;
339 maxtmpintreguse = iftmpintregcnt;
340 maxsavintreguse = ifsavintregcnt;
341 maxtmpfltreguse = iftmpfltregcnt;
342 maxsavfltreguse = ifsavfltregcnt;
346 /* function local_regalloc *****************************************************
348 allocates registers for all local variables
350 *******************************************************************************/
352 static void local_regalloc ()
355 int intalloc, fltalloc;
359 int arg, doublewordarg;
362 for (s = 0; s < maxlocals; s++) {
363 intalloc = -1; fltalloc = -1;
364 for (t = TYPE_INT; t <= TYPE_ADR; t++) {
367 if (IS_FLT_DBL_TYPE(t)) {
369 v->flags = locals[s][fltalloc].flags;
370 v->regoff = locals[s][fltalloc].regoff;
372 else if (!doublewordarg && (arg < mparamcount)
373 && (arg < fltreg_argnum)) {
375 v->regoff = argfltregs[arg];
377 else if (maxtmpfltreguse > 0) {
380 v->regoff = tmpfltregs[maxtmpfltreguse];
382 else if (maxsavfltreguse > 0) {
385 v->regoff = savfltregs[maxsavfltreguse];
389 v->regoff = maxmemuse++;
395 v->flags = locals[s][intalloc].flags;
396 v->regoff = locals[s][intalloc].regoff;
398 else if (!doublewordarg && (arg < mparamcount)
399 && (arg < intreg_argnum)) {
401 v->regoff = argintregs[arg];
403 else if (maxtmpintreguse > 0) {
406 v->regoff = tmpintregs[maxtmpintreguse];
408 else if (maxsavintreguse > 0) {
411 v->regoff = savintregs[maxsavintreguse];
415 v->regoff = maxmemuse++;
421 if (arg < mparamcount) {
426 else if (IS_2_WORD_TYPE(mparamtypes[arg]))
434 for (s = 0; s < maxlocals; s++) {
435 intalloc = -1; fltalloc = -1;
436 for (t=TYPE_INT; t<=TYPE_ADR; t++) {
439 if (IS_FLT_DBL_TYPE(t)) {
441 v->flags = locals[s][fltalloc].flags;
442 v->regoff = locals[s][fltalloc].regoff;
444 else if (maxsavfltreguse > 0) {
447 v->regoff = savfltregs[maxsavfltreguse];
451 v->regoff = maxmemuse++;
457 v->flags = locals[s][intalloc].flags;
458 v->regoff = locals[s][intalloc].regoff;
460 else if (maxsavintreguse > 0) {
463 v->regoff = savintregs[maxsavintreguse];
467 v->regoff = maxmemuse++;
477 static void reg_init_temp()
486 tmpintreguse = iftmpintregcnt;
487 savintreguse = ifsavintregcnt;
488 tmpfltreguse = iftmpfltregcnt;
489 savfltreguse = ifsavfltregcnt;
493 #define reg_new_temp(s) if(s->varkind==TEMPVAR)reg_new_temp_func(s)
495 static void reg_new_temp_func(stackptr s)
497 if (s->flags & SAVEDVAR) {
498 if (IS_FLT_DBL_TYPE(s->type)) {
499 if (freesavflttop > 0) {
501 s->regoff = freesavfltregs[freesavflttop];
504 else if (savfltreguse > 0) {
506 if (savfltreguse < maxsavfltreguse)
507 maxsavfltreguse = savfltreguse;
508 s->regoff = savfltregs[savfltreguse];
513 if (freesavinttop > 0) {
515 s->regoff = freesavintregs[freesavinttop];
518 else if (savintreguse > 0) {
520 if (savintreguse < maxsavintreguse)
521 maxsavintreguse = savintreguse;
522 s->regoff = savintregs[savintreguse];
528 if (IS_FLT_DBL_TYPE(s->type)) {
529 if (freetmpflttop > 0) {
531 s->regoff = freetmpfltregs[freetmpflttop];
534 else if (tmpfltreguse > 0) {
536 if (tmpfltreguse < maxtmpfltreguse)
537 maxtmpfltreguse = tmpfltreguse;
538 s->regoff = tmpfltregs[tmpfltreguse];
543 if (freetmpinttop > 0) {
545 s->regoff = freetmpintregs[freetmpinttop];
548 else if (tmpintreguse > 0) {
550 if (tmpintreguse < maxtmpintreguse)
551 maxtmpintreguse = tmpintreguse;
552 s->regoff = tmpintregs[tmpintreguse];
557 if (freememtop > 0) {
559 s->regoff = freemem[freememtop];
562 s->regoff = memuse++;
563 if (memuse > maxmemuse)
566 s->flags |= INMEMORY;
570 #define reg_free_temp(s) if(s->varkind==TEMPVAR)reg_free_temp_func(s)
572 static void reg_free_temp_func(stackptr s)
574 if (s->flags & INMEMORY)
575 freemem[freememtop++] = s->regoff;
576 else if (IS_FLT_DBL_TYPE(s->type)) {
577 if (s->flags & SAVEDVAR)
578 freesavfltregs[freesavflttop++] = s->regoff;
580 freetmpfltregs[freetmpflttop++] = s->regoff;
583 if (s->flags & SAVEDVAR)
584 freesavintregs[freesavinttop++] = s->regoff;
586 freetmpintregs[freetmpinttop++] = s->regoff;
590 static void allocate_scratch_registers()
595 instruction *iptr = instr;
598 b_count = block_count;
600 while (--b_count >= 0) {
601 if (bptr->flags >= BBREACHED) {
615 case ICMD_ELSE_ICONST:
616 case ICMD_CHECKASIZE:
624 /* pop 0 push 1 const */
632 /* pop 0 push 1 load */
655 reg_free_temp(src->prev);
672 reg_free_temp(src->prev);
673 reg_free_temp(src->prev->prev);
676 /* pop 1 push 0 store */
698 /* pop 1 push 0 branch */
717 /* pop 1 push 0 table branch */
719 case ICMD_TABLESWITCH:
720 case ICMD_LOOKUPSWITCH:
722 case ICMD_NULLCHECKPOP:
723 case ICMD_MONITORENTER:
724 case ICMD_MONITOREXIT:
728 /* pop 2 push 0 branch */
753 reg_free_temp(src->prev);
756 /* pop 0 push 1 dup */
762 /* pop 0 push 2 dup */
765 reg_new_temp(dst->prev);
769 /* pop 2 push 3 dup */
772 reg_new_temp(dst->prev->prev);
773 reg_new_temp(dst->prev);
776 reg_free_temp(src->prev);
779 /* pop 3 push 4 dup */
782 reg_new_temp(dst->prev->prev->prev);
783 reg_new_temp(dst->prev->prev);
784 reg_new_temp(dst->prev);
787 reg_free_temp(src->prev);
788 reg_free_temp(src->prev->prev);
791 /* pop 3 push 5 dup */
794 reg_new_temp(dst->prev->prev->prev->prev);
795 reg_new_temp(dst->prev->prev->prev);
796 reg_new_temp(dst->prev->prev);
797 reg_new_temp(dst->prev);
800 reg_free_temp(src->prev);
801 reg_free_temp(src->prev->prev);
804 /* pop 4 push 6 dup */
807 reg_new_temp(dst->prev->prev->prev->prev->prev);
808 reg_new_temp(dst->prev->prev->prev->prev);
809 reg_new_temp(dst->prev->prev->prev);
810 reg_new_temp(dst->prev->prev);
811 reg_new_temp(dst->prev);
814 reg_free_temp(src->prev);
815 reg_free_temp(src->prev->prev);
816 reg_free_temp(src->prev->prev->prev);
819 /* pop 2 push 2 swap */
822 reg_new_temp(dst->prev);
825 reg_free_temp(src->prev);
875 reg_free_temp(src->prev);
886 case ICMD_IREM0X10001:
892 case ICMD_IUSHRCONST:
899 case ICMD_LREM0X10001:
905 case ICMD_LUSHRCONST:
907 case ICMD_IFEQ_ICONST:
908 case ICMD_IFNE_ICONST:
909 case ICMD_IFLT_ICONST:
910 case ICMD_IFGE_ICONST:
911 case ICMD_IFGT_ICONST:
912 case ICMD_IFLE_ICONST:
937 case ICMD_ARRAYLENGTH:
938 case ICMD_INSTANCEOF:
957 /* pop many push any */
959 case ICMD_INVOKEVIRTUAL:
960 case ICMD_INVOKESPECIAL:
961 case ICMD_INVOKESTATIC:
962 case ICMD_INVOKEINTERFACE:
969 if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID)
983 if (iptr->op1 != TYPE_VOID)
987 case ICMD_MULTIANEWARRAY:
997 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
998 panic("Missing ICMD code during register allocation");
1001 } /* while instructions */
1004 } /* while blocks */
1009 * These are local overrides for various environment variables in Emacs.
1010 * Please do not remove this and leave it at the end of the file, where
1011 * Emacs will automagically detect them.
1012 * ---------------------------------------------------------------------
1015 * indent-tabs-mode: t