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 for (s = 0; s < maxlocals; s++) {
360 intalloc = -1; fltalloc = -1;
361 for (t = TYPE_INT; t <= TYPE_ADR; t++) {
364 if (IS_FLT_DBL_TYPE(t)) {
366 v->flags = locals[s][fltalloc].flags;
367 v->regoff = locals[s][fltalloc].regoff;
369 else if (s < fltreg_argnum) {
371 v->regoff = argfltregs[s];
373 else if (maxtmpfltreguse > 0) {
376 v->regoff = tmpfltregs[maxtmpfltreguse];
378 else if (maxsavfltreguse > 0) {
381 v->regoff = savfltregs[maxsavfltreguse];
385 v->regoff = maxmemuse++;
391 v->flags = locals[s][intalloc].flags;
392 v->regoff = locals[s][intalloc].regoff;
394 else if (s < intreg_argnum) {
396 v->regoff = argintregs[s];
398 else if (maxtmpintreguse > 0) {
401 v->regoff = tmpintregs[maxtmpintreguse];
403 else if (maxsavintreguse > 0) {
406 v->regoff = savintregs[maxsavintreguse];
410 v->regoff = maxmemuse++;
419 for (s = 0; s < maxlocals; s++) {
420 intalloc = -1; fltalloc = -1;
421 for (t=TYPE_INT; t<=TYPE_ADR; t++) {
424 if (IS_FLT_DBL_TYPE(t)) {
426 v->flags = locals[s][fltalloc].flags;
427 v->regoff = locals[s][fltalloc].regoff;
429 else if (maxsavfltreguse > 0) {
432 v->regoff = savfltregs[maxsavfltreguse];
436 v->regoff = maxmemuse++;
442 v->flags = locals[s][intalloc].flags;
443 v->regoff = locals[s][intalloc].regoff;
445 else if (maxsavintreguse > 0) {
448 v->regoff = savintregs[maxsavintreguse];
452 v->regoff = maxmemuse++;
462 static void reg_init_temp()
471 tmpintreguse = iftmpintregcnt;
472 savintreguse = ifsavintregcnt;
473 tmpfltreguse = iftmpfltregcnt;
474 savfltreguse = ifsavfltregcnt;
478 #define reg_new_temp(s) if(s->varkind==TEMPVAR)reg_new_temp_func(s)
480 static void reg_new_temp_func(stackptr s)
482 if (s->flags & SAVEDVAR) {
483 if (IS_FLT_DBL_TYPE(s->type)) {
484 if (freesavflttop > 0) {
486 s->regoff = freesavfltregs[freesavflttop];
489 else if (savfltreguse > 0) {
491 if (savfltreguse < maxsavfltreguse)
492 maxsavfltreguse = savfltreguse;
493 s->regoff = savfltregs[savfltreguse];
498 if (freesavinttop > 0) {
500 s->regoff = freesavintregs[freesavinttop];
503 else if (savintreguse > 0) {
505 if (savintreguse < maxsavintreguse)
506 maxsavintreguse = savintreguse;
507 s->regoff = savintregs[savintreguse];
513 if (IS_FLT_DBL_TYPE(s->type)) {
514 if (freetmpflttop > 0) {
516 s->regoff = freetmpfltregs[freetmpflttop];
519 else if (tmpfltreguse > 0) {
521 if (tmpfltreguse < maxtmpfltreguse)
522 maxtmpfltreguse = tmpfltreguse;
523 s->regoff = tmpfltregs[tmpfltreguse];
528 if (freetmpinttop > 0) {
530 s->regoff = freetmpintregs[freetmpinttop];
533 else if (tmpintreguse > 0) {
535 if (tmpintreguse < maxtmpintreguse)
536 maxtmpintreguse = tmpintreguse;
537 s->regoff = tmpintregs[tmpintreguse];
542 if (freememtop > 0) {
544 s->regoff = freemem[freememtop];
547 s->regoff = memuse++;
548 if (memuse > maxmemuse)
551 s->flags |= INMEMORY;
555 #define reg_free_temp(s) if(s->varkind==TEMPVAR)reg_free_temp_func(s)
557 static void reg_free_temp_func(stackptr s)
559 if (s->flags & INMEMORY)
560 freemem[freememtop++] = s->regoff;
561 else if (IS_FLT_DBL_TYPE(s->type)) {
562 if (s->flags & SAVEDVAR)
563 freesavfltregs[freesavflttop++] = s->regoff;
565 freetmpfltregs[freetmpflttop++] = s->regoff;
568 if (s->flags & SAVEDVAR)
569 freesavintregs[freesavinttop++] = s->regoff;
571 freetmpintregs[freetmpinttop++] = s->regoff;
575 static void allocate_scratch_registers()
580 instruction *iptr = instr;
583 b_count = block_count;
585 while (--b_count >= 0) {
586 if (bptr->flags >= BBREACHED) {
600 case ICMD_ELSE_ICONST:
601 case ICMD_CHECKASIZE:
609 /* pop 0 push 1 const */
617 /* pop 0 push 1 load */
639 case ICMD_OPT_IALOAD:
640 case ICMD_OPT_LALOAD:
641 case ICMD_OPT_FALOAD:
642 case ICMD_OPT_DALOAD:
643 case ICMD_OPT_AALOAD:
645 case ICMD_OPT_BALOAD:
646 case ICMD_OPT_CALOAD:
647 case ICMD_OPT_SALOAD:
649 reg_free_temp(src->prev);
665 case ICMD_OPT_IASTORE:
666 case ICMD_OPT_LASTORE:
667 case ICMD_OPT_FASTORE:
668 case ICMD_OPT_DASTORE:
669 case ICMD_OPT_AASTORE:
671 case ICMD_OPT_BASTORE:
672 case ICMD_OPT_CASTORE:
673 case ICMD_OPT_SASTORE:
675 reg_free_temp(src->prev);
676 reg_free_temp(src->prev->prev);
679 /* pop 1 push 0 store */
701 /* pop 1 push 0 branch */
720 /* pop 1 push 0 table branch */
722 case ICMD_TABLESWITCH:
723 case ICMD_LOOKUPSWITCH:
725 case ICMD_NULLCHECKPOP:
726 case ICMD_MONITORENTER:
727 case ICMD_MONITOREXIT:
731 /* pop 2 push 0 branch */
756 reg_free_temp(src->prev);
759 /* pop 0 push 1 dup */
765 /* pop 0 push 2 dup */
768 reg_new_temp(dst->prev);
772 /* pop 2 push 3 dup */
775 reg_new_temp(dst->prev->prev);
776 reg_new_temp(dst->prev);
779 reg_free_temp(src->prev);
782 /* pop 3 push 4 dup */
785 reg_new_temp(dst->prev->prev->prev);
786 reg_new_temp(dst->prev->prev);
787 reg_new_temp(dst->prev);
790 reg_free_temp(src->prev);
791 reg_free_temp(src->prev->prev);
794 /* pop 3 push 5 dup */
797 reg_new_temp(dst->prev->prev->prev->prev);
798 reg_new_temp(dst->prev->prev->prev);
799 reg_new_temp(dst->prev->prev);
800 reg_new_temp(dst->prev);
803 reg_free_temp(src->prev);
804 reg_free_temp(src->prev->prev);
807 /* pop 4 push 6 dup */
810 reg_new_temp(dst->prev->prev->prev->prev->prev);
811 reg_new_temp(dst->prev->prev->prev->prev);
812 reg_new_temp(dst->prev->prev->prev);
813 reg_new_temp(dst->prev->prev);
814 reg_new_temp(dst->prev);
817 reg_free_temp(src->prev);
818 reg_free_temp(src->prev->prev);
819 reg_free_temp(src->prev->prev->prev);
822 /* pop 2 push 2 swap */
825 reg_new_temp(dst->prev);
828 reg_free_temp(src->prev);
878 reg_free_temp(src->prev);
889 case ICMD_IREM0X10001:
895 case ICMD_IUSHRCONST:
902 case ICMD_LREM0X10001:
908 case ICMD_LUSHRCONST:
910 case ICMD_IFEQ_ICONST:
911 case ICMD_IFNE_ICONST:
912 case ICMD_IFLT_ICONST:
913 case ICMD_IFGE_ICONST:
914 case ICMD_IFGT_ICONST:
915 case ICMD_IFLE_ICONST:
940 case ICMD_ARRAYLENGTH:
941 case ICMD_INSTANCEOF:
960 /* pop many push any */
962 case ICMD_INVOKEVIRTUAL:
963 case ICMD_INVOKESPECIAL:
964 case ICMD_INVOKESTATIC:
965 case ICMD_INVOKEINTERFACE:
972 if (((methodinfo*)iptr->val.a)->returntype != TYPE_VOID)
986 if (iptr->op1 != TYPE_VOID)
990 case ICMD_MULTIANEWARRAY:
1000 printf("ICMD %d at %d\n", iptr->opc, (int)(iptr-instr));
1001 panic("Missing ICMD code during register allocation");
1004 } /* while instructions */
1007 } /* while blocks */
1012 * These are local overrides for various environment variables in Emacs.
1013 * Please do not remove this and leave it at the end of the file, where
1014 * Emacs will automagically detect them.
1015 * ---------------------------------------------------------------------
1018 * indent-tabs-mode: t