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;
261 for (t = TYPE_INT; t <= TYPE_ADR; t++) {
262 v = &interfaces[s][t];
265 if (IS_FLT_DBL_TYPE(t)) {
267 v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
268 v->regoff = interfaces[s][fltalloc].regoff;
270 else if (iftmpfltregcnt > 0) {
272 v->regoff = tmpfltregs[iftmpfltregcnt];
274 else if (ifsavfltregcnt > 0) {
276 v->regoff = savfltregs[ifsavfltregcnt];
279 v->flags |= INMEMORY;
280 v->regoff = ifmemuse++;
286 v->flags |= interfaces[s][intalloc].flags & INMEMORY;
287 v->regoff = interfaces[s][intalloc].regoff;
289 else if (iftmpintregcnt > 0) {
291 v->regoff = tmpintregs[iftmpintregcnt];
293 else if (ifsavintregcnt > 0) {
295 v->regoff = savintregs[ifsavintregcnt];
298 v->flags |= INMEMORY;
299 v->regoff = ifmemuse++;
305 if (IS_FLT_DBL_TYPE(t)) {
307 v->flags |= interfaces[s][fltalloc].flags & INMEMORY;
308 v->regoff = interfaces[s][fltalloc].regoff;
310 else if (ifsavfltregcnt > 0) {
312 v->regoff = savfltregs[ifsavfltregcnt];
315 v->flags |= INMEMORY;
316 v->regoff = ifmemuse++;
322 v->flags |= interfaces[s][intalloc].flags & INMEMORY;
323 v->regoff = interfaces[s][intalloc].regoff;
325 else if (ifsavintregcnt > 0) {
327 v->regoff = savintregs[ifsavintregcnt];
330 v->flags |= INMEMORY;
331 v->regoff = ifmemuse++;
336 } /* if (type >= 0) */
340 maxmemuse = ifmemuse;
341 maxtmpintreguse = iftmpintregcnt;
342 maxsavintreguse = ifsavintregcnt;
343 maxtmpfltreguse = iftmpfltregcnt;
344 maxsavfltreguse = ifsavfltregcnt;
349 /* function local_regalloc *****************************************************
351 allocates registers for all local variables
353 *******************************************************************************/
355 static void local_regalloc ()
358 int intalloc, fltalloc;
362 int arg, doublewordarg;
365 for (s = 0; s < maxlocals; s++) {
366 intalloc = -1; fltalloc = -1;
367 for (t = TYPE_INT; t <= TYPE_ADR; t++) {
370 if (IS_FLT_DBL_TYPE(t)) {
372 v->flags = locals[s][fltalloc].flags;
373 v->regoff = locals[s][fltalloc].regoff;
375 else if (!doublewordarg && (arg < mparamcount)
376 && (arg < fltreg_argnum)) {
378 v->regoff = argfltregs[arg];
380 else if (maxtmpfltreguse > 0) {
383 v->regoff = tmpfltregs[maxtmpfltreguse];
385 else if (maxsavfltreguse > 0) {
388 v->regoff = savfltregs[maxsavfltreguse];
392 v->regoff = maxmemuse++;
398 v->flags = locals[s][intalloc].flags;
399 v->regoff = locals[s][intalloc].regoff;
401 else if (!doublewordarg && (arg < mparamcount)
402 && (arg < intreg_argnum)) {
404 v->regoff = argintregs[arg];
406 else if (maxtmpintreguse > 0) {
409 v->regoff = tmpintregs[maxtmpintreguse];
411 else if (maxsavintreguse > 0) {
414 v->regoff = savintregs[maxsavintreguse];
418 v->regoff = maxmemuse++;
424 if (arg < mparamcount) {
429 else if (IS_2_WORD_TYPE(mparamtypes[arg]))
437 for (s = 0; s < maxlocals; s++) {
438 intalloc = -1; fltalloc = -1;
439 for (t=TYPE_INT; t<=TYPE_ADR; t++) {
442 if (IS_FLT_DBL_TYPE(t)) {
444 v->flags = locals[s][fltalloc].flags;
445 v->regoff = locals[s][fltalloc].regoff;
447 else if (maxsavfltreguse > 0) {
450 v->regoff = savfltregs[maxsavfltreguse];
454 v->regoff = maxmemuse++;
460 v->flags = locals[s][intalloc].flags;
461 v->regoff = locals[s][intalloc].regoff;
463 else if (maxsavintreguse > 0) {
466 v->regoff = savintregs[maxsavintreguse];
470 v->regoff = maxmemuse++;
480 static void reg_init_temp()
489 tmpintreguse = iftmpintregcnt;
490 savintreguse = ifsavintregcnt;
491 tmpfltreguse = iftmpfltregcnt;
492 savfltreguse = ifsavfltregcnt;
496 #define reg_new_temp(s) if(s->varkind==TEMPVAR)reg_new_temp_func(s)
498 static void reg_new_temp_func(stackptr s)
500 if (s->flags & SAVEDVAR) {
501 if (IS_FLT_DBL_TYPE(s->type)) {
502 if (freesavflttop > 0) {
504 s->regoff = freesavfltregs[freesavflttop];
507 else if (savfltreguse > 0) {
509 if (savfltreguse < maxsavfltreguse)
510 maxsavfltreguse = savfltreguse;
511 s->regoff = savfltregs[savfltreguse];
516 if (freesavinttop > 0) {
518 s->regoff = freesavintregs[freesavinttop];
521 else if (savintreguse > 0) {
523 if (savintreguse < maxsavintreguse)
524 maxsavintreguse = savintreguse;
525 s->regoff = savintregs[savintreguse];
531 if (IS_FLT_DBL_TYPE(s->type)) {
532 if (freetmpflttop > 0) {
534 s->regoff = freetmpfltregs[freetmpflttop];
537 else if (tmpfltreguse > 0) {
539 if (tmpfltreguse < maxtmpfltreguse)
540 maxtmpfltreguse = tmpfltreguse;
541 s->regoff = tmpfltregs[tmpfltreguse];
546 if (freetmpinttop > 0) {
548 s->regoff = freetmpintregs[freetmpinttop];
551 else if (tmpintreguse > 0) {
553 if (tmpintreguse < maxtmpintreguse)
554 maxtmpintreguse = tmpintreguse;
555 s->regoff = tmpintregs[tmpintreguse];
560 if (freememtop > 0) {
562 s->regoff = freemem[freememtop];
565 s->regoff = memuse++;
566 if (memuse > maxmemuse)
569 s->flags |= INMEMORY;
573 #define reg_free_temp(s) if(s->varkind==TEMPVAR)reg_free_temp_func(s)
575 static void reg_free_temp_func(stackptr s)
577 if (s->flags & INMEMORY)
578 freemem[freememtop++] = s->regoff;
579 else if (IS_FLT_DBL_TYPE(s->type)) {
580 if (s->flags & SAVEDVAR)
581 freesavfltregs[freesavflttop++] = s->regoff;
583 freetmpfltregs[freetmpflttop++] = s->regoff;
586 if (s->flags & SAVEDVAR)
587 freesavintregs[freesavinttop++] = s->regoff;
589 freetmpintregs[freetmpinttop++] = s->regoff;
593 static void allocate_scratch_registers()
598 instruction *iptr = instr;
601 /* b_count = block_count; */
604 while (bptr != NULL) {
606 if (bptr->flags >= BBREACHED) {
622 case ICMD_ELSE_ICONST:
623 case ICMD_CHECKASIZE:
631 /* pop 0 push 1 const */
639 /* pop 0 push 1 load */
662 reg_free_temp(src->prev);
679 reg_free_temp(src->prev);
680 reg_free_temp(src->prev->prev);
683 /* pop 1 push 0 store */
705 /* pop 1 push 0 branch */
724 /* pop 1 push 0 table branch */
726 case ICMD_TABLESWITCH:
727 case ICMD_LOOKUPSWITCH:
729 case ICMD_NULLCHECKPOP:
730 case ICMD_MONITORENTER:
731 case ICMD_MONITOREXIT:
735 /* pop 2 push 0 branch */
760 reg_free_temp(src->prev);
763 /* pop 0 push 1 dup */
769 /* pop 0 push 2 dup */
772 reg_new_temp(dst->prev);
776 /* pop 2 push 3 dup */
779 reg_new_temp(dst->prev->prev);
780 reg_new_temp(dst->prev);
783 reg_free_temp(src->prev);
786 /* pop 3 push 4 dup */
789 reg_new_temp(dst->prev->prev->prev);
790 reg_new_temp(dst->prev->prev);
791 reg_new_temp(dst->prev);
794 reg_free_temp(src->prev);
795 reg_free_temp(src->prev->prev);
798 /* pop 3 push 5 dup */
801 reg_new_temp(dst->prev->prev->prev->prev);
802 reg_new_temp(dst->prev->prev->prev);
803 reg_new_temp(dst->prev->prev);
804 reg_new_temp(dst->prev);
807 reg_free_temp(src->prev);
808 reg_free_temp(src->prev->prev);
811 /* pop 4 push 6 dup */
814 reg_new_temp(dst->prev->prev->prev->prev->prev);
815 reg_new_temp(dst->prev->prev->prev->prev);
816 reg_new_temp(dst->prev->prev->prev);
817 reg_new_temp(dst->prev->prev);
818 reg_new_temp(dst->prev);
821 reg_free_temp(src->prev);
822 reg_free_temp(src->prev->prev);
823 reg_free_temp(src->prev->prev->prev);
826 /* pop 2 push 2 swap */
829 reg_new_temp(dst->prev);
832 reg_free_temp(src->prev);
882 reg_free_temp(src->prev);
893 case ICMD_IREM0X10001:
899 case ICMD_IUSHRCONST:
906 case ICMD_LREM0X10001:
912 case ICMD_LUSHRCONST:
914 case ICMD_IFEQ_ICONST:
915 case ICMD_IFNE_ICONST:
916 case ICMD_IFLT_ICONST:
917 case ICMD_IFGE_ICONST:
918 case ICMD_IFGT_ICONST:
919 case ICMD_IFLE_ICONST:
944 case ICMD_ARRAYLENGTH:
945 case ICMD_INSTANCEOF:
964 /* pop many push any */
966 case ICMD_INVOKEVIRTUAL:
967 case ICMD_INVOKESPECIAL:
968 case ICMD_INVOKESTATIC:
969 case ICMD_INVOKEINTERFACE:
976 if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID)
990 if (iptr->op1 != TYPE_VOID)
994 case ICMD_MULTIANEWARRAY:
1004 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1005 panic("Missing ICMD code during register allocation");
1008 } /* while instructions */
1011 } /* while blocks */
1016 * These are local overrides for various environment variables in Emacs.
1017 * Please do not remove this and leave it at the end of the file, where
1018 * Emacs will automagically detect them.
1019 * ---------------------------------------------------------------------
1022 * indent-tabs-mode: t