Changed x86_64 abi back to 8 float argument registers.
[cacao.git] / src / vm / jit / reg.inc
1 /* vm/jit/reg.inc - register allocator
2
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
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Andreas Krall
28
29    Changes: Stefan Ring
30             Christian Thalinger
31
32    $Id: reg.inc 1753 2004-12-13 08:40:16Z twisti $
33
34 */
35
36
37 #include "mm/memory.h"
38 #include "vm/jit/reg.h"
39
40
41 /* function prototypes for this file */
42
43 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
44 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
45 static void allocate_scratch_registers(methodinfo *m, registerdata *rd);
46
47
48 /* reg_init ********************************************************************
49
50    TODO
51         
52 *******************************************************************************/
53
54 void reg_init()
55 {
56         /* void */
57 }
58
59
60 /* reg_setup *******************************************************************
61
62    TODO
63
64 *******************************************************************************/
65
66 void reg_setup(methodinfo *m, registerdata *rd, t_inlining_globals *id)
67 {
68         s4 i;
69         varinfo5 *v;
70
71         /* setup the integer register table */
72         rd->intreg_argnum = 0;
73         rd->tmpintregcnt = 0;
74         rd->savintregcnt = 0;
75
76         for (rd->intregsnum = 0; nregdescint[rd->intregsnum] != REG_END; rd->intregsnum++) {
77                 switch (nregdescint[rd->intregsnum]) {
78                 case REG_SAV:
79                         rd->savintregcnt++;
80                         break;
81                 case REG_TMP:
82                         rd->tmpintregcnt++;
83                         break;
84                 case REG_ARG:
85                         rd->intreg_argnum++;
86                         break;
87                 }
88         }
89
90         rd->argintregs = DMNEW(s4, rd->intreg_argnum);
91         rd->tmpintregs = DMNEW(s4, rd->tmpintregcnt);
92         rd->savintregs = DMNEW(s4, rd->savintregcnt);
93         rd->freeargintregs = DMNEW(s4, rd->intreg_argnum);
94         rd->freetmpintregs = DMNEW(s4, rd->tmpintregcnt);
95         rd->freesavintregs = DMNEW(s4, rd->savintregcnt);
96 #ifdef USETWOREGS
97         rd->secondregs = DMNEW(s4, rd->intregsnum);
98 #endif
99
100         rd->intreg_argnum = 0;
101         rd->argintreguse = 0;
102         rd->tmpintreguse = 0;
103         rd->savintreguse = 0;
104
105         for (i = 0; i < rd->intregsnum; i++) {
106                 switch (nregdescint[i]) {
107                 case REG_RET:
108                         rd->intreg_ret = i; 
109                         break;
110                 case REG_SAV:
111                         rd->savintregs[rd->savintreguse++] = i;
112                         break;
113                 case REG_TMP:
114                         rd->tmpintregs[rd->tmpintreguse++] = i;
115                         break;
116                 case REG_ARG:
117                         rd->argintregs[rd->intreg_argnum++] = i;
118                         rd->argintreguse++;
119                         break;
120                 }
121         }
122
123 #if defined(__X86_64__)
124         /* 
125          * on x86_64 the argument registers are not in ascending order 
126          * a00 (%rdi) <-> a03 (%rcx) and a01 (%rsi) <-> a02 (%rdx)
127          */
128         i = rd->argintregs[3];
129         rd->argintregs[3] = rd->argintregs[0];
130         rd->argintregs[0] = i;
131
132         i = rd->argintregs[2];
133         rd->argintregs[2] = rd->argintregs[1];
134         rd->argintregs[1] = i;
135 #endif
136                 
137 #ifdef USETWOREGS
138         for (i = 1; i < rd->intreg_argnum; i++)
139                 rd->secondregs[rd->argintregs[i - 1]] = rd->argintregs[i];
140         for (i = 1; i < rd->tmpintregcnt; i++)
141                 rd->secondregs[rd->tmpintregs[i - 1]] = rd->tmpintregs[i];
142         for (i = 1; i < rd->savintregcnt; i++)
143                 rd->secondregs[rd->savintregs[i - 1]] = rd->savintregs[i];
144
145         rd->secondregs[REG_ITMP1] = REG_ITMP2;
146         rd->secondregs[REG_ITMP3] = REG_ITMP2;
147         rd->secondregs[REG_RESULT] = REG_RESULT + 1;
148         rd->secondregs[rd->argintregs[rd->intreg_argnum - 1]] = REG_ITMP3;
149 #endif
150
151         /* setup the float register table */
152         rd->fltreg_argnum = 0;
153         rd->tmpfltregcnt = 0;
154         rd->savfltregcnt = 0;
155
156         for (rd->floatregsnum = 0; nregdescfloat[rd->floatregsnum] != REG_END; rd->floatregsnum++) {
157                 switch (nregdescfloat[rd->floatregsnum]) {
158                 case REG_SAV:
159                         rd->savfltregcnt++;
160                         break;
161                 case REG_TMP:
162                         rd->tmpfltregcnt++;
163                         break;
164                 case REG_ARG:
165                         rd->fltreg_argnum++;
166                         break;
167                 }
168         }
169
170         rd->argfltregs = DMNEW(s4, rd->fltreg_argnum);
171         rd->tmpfltregs = DMNEW(s4, rd->tmpfltregcnt);
172         rd->savfltregs = DMNEW(s4, rd->savfltregcnt);
173         rd->freeargfltregs = DMNEW(s4, rd->fltreg_argnum);
174         rd->freetmpfltregs = DMNEW(s4, rd->tmpfltregcnt);
175         rd->freesavfltregs = DMNEW(s4, rd->savfltregcnt);
176
177         rd->fltreg_argnum = 0;
178         rd->argfltreguse = 0;
179         rd->tmpfltreguse = 0;
180         rd->savfltreguse = 0;
181
182         for (i = 0; i < rd->floatregsnum; i++) {
183                 switch (nregdescfloat[i]) {
184                 case REG_RET:
185                         rd->floatreg_ret = i; 
186                         break;
187                 case REG_SAV:
188                         rd->savfltregs[rd->savfltreguse++] = i;
189                         break;
190                 case REG_TMP:
191                         rd->tmpfltregs[rd->tmpfltreguse++] = i;
192                         break;
193                 case REG_ARG:
194                         rd->argfltregs[rd->fltreg_argnum++] = i;
195                         rd->argfltreguse++;
196                         break;
197                 }
198         }
199
200
201         rd->freemem    = DMNEW(s4, id->cummaxstack);
202         rd->locals     = DMNEW(varinfo5, id->cumlocals);
203         rd->interfaces = DMNEW(varinfo5, id->cummaxstack);
204
205         for (v = rd->locals, i = id->cumlocals; i > 0; v++, i--) {
206                 v[0][TYPE_INT].type = -1;
207                 v[0][TYPE_LNG].type = -1;
208                 v[0][TYPE_FLT].type = -1;
209                 v[0][TYPE_DBL].type = -1;
210                 v[0][TYPE_ADR].type = -1;
211         }
212
213         for (v = rd->interfaces, i = id->cummaxstack; i > 0; v++, i--) {
214                 v[0][TYPE_INT].type = -1;
215                 v[0][TYPE_INT].flags = 0;
216                 v[0][TYPE_LNG].type = -1;
217                 v[0][TYPE_LNG].flags = 0;
218                 v[0][TYPE_FLT].type = -1;
219                 v[0][TYPE_FLT].flags = 0;
220                 v[0][TYPE_DBL].type = -1;
221                 v[0][TYPE_DBL].flags = 0;
222                 v[0][TYPE_ADR].type = -1;
223                 v[0][TYPE_ADR].flags = 0;
224         }
225 }
226
227
228 /* function reg_free ***********************************************************
229
230    releases all allocated space for registers
231
232 *******************************************************************************/
233
234 void reg_free(methodinfo *m, registerdata *rd)
235 {
236         /* void */
237 }
238
239
240 /* reg_close *******************************************************************
241
242    TODO
243
244 *******************************************************************************/
245
246 void reg_close()
247 {
248         /* void */
249 }
250
251
252 /* function interface_regalloc *************************************************
253
254         allocates registers for all interface variables
255         
256 *******************************************************************************/
257         
258 void regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
259 {
260         interface_regalloc(m, cd, rd);
261         allocate_scratch_registers(m, rd);
262         local_regalloc(m, cd, rd);
263 }
264
265
266 /* function interface_regalloc *************************************************
267
268         allocates registers for all interface variables
269         
270 *******************************************************************************/
271         
272 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
273 {
274         int     s, t, saved;
275         int     intalloc, fltalloc;
276         varinfo *v;
277         int             regsneeded = 0;
278
279         /* allocate stack space for passing arguments to called methods */
280
281 #if !defined(SPECIALMEMUSE)
282         /* For this to work properly the integer argument register count must be  */
283         /* less or equal the float argument register count (e.g. x86_64).         */
284         /* (arch.h: INT_ARG_CNT <= FLT_ARG_CNT)                                   */
285         if (rd->arguments_num > INT_ARG_CNT) {
286                 rd->ifmemuse = rd->arguments_num - INT_ARG_CNT;
287
288         } else {
289                 rd->ifmemuse = 0;
290         }
291 #endif
292
293         rd->iftmpintregcnt = rd->tmpintregcnt;
294         rd->ifsavintregcnt = rd->savintregcnt;
295         rd->iftmpfltregcnt = rd->tmpfltregcnt;
296         rd->ifsavfltregcnt = rd->savfltregcnt;
297
298         for (s = 0; s < cd->maxstack; s++) {
299                 intalloc = -1; fltalloc = -1;
300                 saved = (rd->interfaces[s][TYPE_INT].flags |
301                                  rd->interfaces[s][TYPE_LNG].flags |
302                          rd->interfaces[s][TYPE_FLT].flags |
303                                  rd->interfaces[s][TYPE_DBL].flags |
304                          rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
305  
306                 for (t = TYPE_INT; t <= TYPE_ADR; t++) {
307                         v = &rd->interfaces[s][t];
308                         if (v->type >= 0) {
309 #ifdef USETWOREGS
310                                 regsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
311 #endif
312                                 if (!saved) {
313                                         if (IS_FLT_DBL_TYPE(t)) {
314                                                 if (fltalloc >= 0) {
315                                                         v->flags |= rd->interfaces[s][fltalloc].flags & INMEMORY;
316                                                         v->regoff = rd->interfaces[s][fltalloc].regoff;
317                                                 }
318                                                 else if (rd->iftmpfltregcnt > 0) {
319                                                         rd->iftmpfltregcnt--;
320                                                         v->regoff = rd->tmpfltregs[rd->iftmpfltregcnt];
321                                                 }
322                                                 else if (rd->ifsavfltregcnt > 0) {
323                                                         rd->ifsavfltregcnt--;
324                                                         v->regoff = rd->savfltregs[rd->ifsavfltregcnt];
325                                                 }
326                                                 else {
327                                                         v->flags |= INMEMORY;
328                                                         v->regoff = rd->ifmemuse;
329                                                         rd->ifmemuse += regsneeded + 1;
330                                                 }
331                                                 fltalloc = t;
332                                         }
333                                         else {
334 #if defined(__I386__)
335                                                 /*
336                                                  * for i386 put all longs in memory
337                                                  */
338                                                 if (IS_2_WORD_TYPE(t)) {
339                                                         v->flags |= INMEMORY;
340                                                         v->regoff = rd->ifmemuse++;
341                                                 } else {
342 #endif
343                                                         if (intalloc >= 0) {
344                                                                 v->flags |= rd->interfaces[s][intalloc].flags & INMEMORY;
345                                                                 v->regoff = rd->interfaces[s][intalloc].regoff;
346                                                         }
347                                                         else if (rd->iftmpintregcnt > regsneeded) {
348                                                                 rd->iftmpintregcnt -= regsneeded + 1;
349                                                                 v->regoff = rd->tmpintregs[rd->iftmpintregcnt];
350                                                         }
351                                                         else if (rd->ifsavintregcnt > regsneeded) {
352                                                                 rd->ifsavintregcnt -= regsneeded + 1;
353                                                                 v->regoff = rd->savintregs[rd->ifsavintregcnt];
354                                                         }
355                                                         else {
356                                                                 v->flags |= INMEMORY;
357                                                                 v->regoff = rd->ifmemuse;
358                                                                 rd->ifmemuse += regsneeded + 1;
359                                                         }
360 #if defined(__I386__)
361                                                 }
362 #endif
363                                                 intalloc = t;
364                                         }
365                                 }
366                                 else {
367                                         if (IS_FLT_DBL_TYPE(t)) {
368                                                 if (fltalloc >= 0) {
369                                                         v->flags |= rd->interfaces[s][fltalloc].flags & INMEMORY;
370                                                         v->regoff = rd->interfaces[s][fltalloc].regoff;
371                                                 }
372                                                 else if (rd->ifsavfltregcnt > 0) {
373                                                         rd->ifsavfltregcnt--;
374                                                         v->regoff = rd->savfltregs[rd->ifsavfltregcnt];
375                                                 }
376                                                 else {
377                                                         v->flags |= INMEMORY;
378                                                         v->regoff = rd->ifmemuse;
379                                                         rd->ifmemuse += regsneeded + 1;
380                                                 }
381                                                 fltalloc = t;
382                                         }
383                                         else {
384 #if defined(__I386__)
385                                                 /*
386                                                  * for i386 put all longs in memory
387                                                  */
388                                                 if (IS_2_WORD_TYPE(t)) {
389                                                         v->flags |= INMEMORY;
390                                                         v->regoff = rd->ifmemuse++;
391                                                 } else {
392 #endif
393                                                         if (intalloc >= 0) {
394                                                                 v->flags |= rd->interfaces[s][intalloc].flags & INMEMORY;
395                                                                 v->regoff = rd->interfaces[s][intalloc].regoff;
396                                                         }
397                                                         else if (rd->ifsavintregcnt > regsneeded) {
398                                                                 rd->ifsavintregcnt -= regsneeded + 1;
399                                                                 v->regoff = rd->savintregs[rd->ifsavintregcnt];
400                                                         }
401                                                         else {
402                                                                 v->flags |= INMEMORY;
403                                                                 v->regoff = rd->ifmemuse;
404                                                                 rd->ifmemuse += regsneeded + 1;
405                                                         }
406 #if defined(__I386__)
407                                                 }
408 #endif
409                                                 intalloc = t;
410                                         }
411                                 }
412                         } /* if (type >= 0) */
413                 } /* for t */
414         } /* for s */
415
416         rd->maxmemuse = rd->ifmemuse;
417         rd->maxargintreguse = -1;
418         rd->maxtmpintreguse = rd->iftmpintregcnt;
419         rd->maxsavintreguse = rd->ifsavintregcnt;
420         rd->maxargfltreguse = -1;
421         rd->maxtmpfltreguse = rd->iftmpfltregcnt;
422         rd->maxsavfltreguse = rd->ifsavfltregcnt;
423 }
424
425
426
427 /* function local_regalloc *****************************************************
428
429         allocates registers for all local variables
430         
431 *******************************************************************************/
432         
433 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
434 {
435         int      s, t, tt;
436         int      intalloc, fltalloc;
437         varinfo *v;
438         int      regsneeded = 0;
439         int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
440
441         if (m->isleafmethod) {
442                 int arg, doublewordarg, iargcnt, fargcnt;
443
444                 arg = 0, iargcnt = 0, fargcnt = 0;
445                 doublewordarg = 0;
446                 for (s = 0; s < cd->maxlocals; s++) {
447                         intalloc = -1; fltalloc = -1;
448                         for (tt = 0; tt <= 4; tt++) {
449                                 t = typeloop[tt];
450                                 v = &rd->locals[s][t];
451
452                                 if (v->type >= 0) {
453 #ifdef USETWOREGS
454                                         regsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
455 #endif
456                                         if (IS_FLT_DBL_TYPE(t)) {
457 #if !defined(CONSECUTIVE_FLOATARGS)
458                                                 fargcnt = arg;
459 #endif
460                                                 if (fltalloc >= 0) {
461                                                         v->flags = rd->locals[s][fltalloc].flags;
462                                                         v->regoff = rd->locals[s][fltalloc].regoff;
463                                                 }
464                                                 else if (!doublewordarg && (arg < m->paramcount) &&
465                                                                  (fargcnt < rd->fltreg_argnum)) {
466                                                         v->flags = 0;
467                                                         v->regoff = rd->argfltregs[fargcnt];
468                                                 }
469                                                 else if (rd->maxtmpfltreguse > 0) {
470                                                         rd->maxtmpfltreguse--;
471                                                         v->flags = 0;
472                                                         v->regoff = rd->tmpfltregs[rd->maxtmpfltreguse];
473                                                 }
474                                                 else if (rd->maxsavfltreguse > 0) {
475                                                         rd->maxsavfltreguse--;
476                                                         v->flags = 0;
477                                                         v->regoff = rd->savfltregs[rd->maxsavfltreguse];
478                                                 }
479                                                 else {
480                                                         v->flags = INMEMORY;
481                                                         v->regoff = rd->maxmemuse;
482                                                         rd->maxmemuse += regsneeded + 1;
483                                                 }
484                                                 fltalloc = t;
485
486                                         } else {
487                                                 int regtouse;
488 #if defined(__I386__)
489                                                 /*
490                                                  * for i386 put all longs in memory
491                                                  */
492                                                 if (IS_2_WORD_TYPE(t)) {
493                                                         v->flags = INMEMORY;
494                                                         v->regoff = rd->maxmemuse++;
495                                                 } else {
496 #endif
497 #if !defined(CONSECUTIVE_INTARGS)
498                                                         iargcnt = arg;
499 #endif
500                                                         if (intalloc >= 0) {
501                                                                 v->flags = rd->locals[s][intalloc].flags;
502                                                                 v->regoff = rd->locals[s][intalloc].regoff;
503                                                         }
504                                                         else if (!doublewordarg && (arg < m->paramcount)
505 #ifndef USETWOREGS
506                                                                          && ((regtouse = iargcnt) < rd->intreg_argnum)
507 #else
508                                                                          && ((regtouse = s) < rd->intreg_argnum - regsneeded)
509 #endif
510                                                                          ) {
511                                                                 v->flags = 0;
512                                                                 v->regoff = rd->argintregs[regtouse];
513                                                         }
514                                                         else if (rd->maxtmpintreguse > regsneeded) {
515                                                                 rd->maxtmpintreguse -= regsneeded + 1;
516                                                                 v->flags = 0;
517                                                                 v->regoff = rd->tmpintregs[rd->maxtmpintreguse];
518                                                         }
519                                                         else if (rd->maxsavintreguse > regsneeded) {
520                                                                 rd->maxsavintreguse -= regsneeded + 1;
521                                                                 v->flags = 0;
522                                                                 v->regoff = rd->savintregs[rd->maxsavintreguse];
523                                                         }
524                                                         /*
525                                                          * use unused argument registers as local registers
526                                                          */
527                                                         else if (!doublewordarg && (arg >= m->paramcount) &&
528                                                                          (iargcnt < rd->intreg_argnum)) {
529                                                                 v->flags = 0;
530                                                                 v->regoff = rd->argintregs[iargcnt];
531                                                                 iargcnt++;
532                                                                 arg++;
533                                                         }
534                                                         else {
535                                                                 v->flags = INMEMORY;
536                                                                 v->regoff = rd->maxmemuse;
537                                                                 rd->maxmemuse += regsneeded + 1;
538                                                         }
539 #if defined(__I386__)
540                                                 }
541 #endif
542                                                 intalloc = t;
543                                         }
544                                 }
545                         }
546                         if (arg < m->paramcount) {
547                                 if (doublewordarg) {
548                                         doublewordarg = 0;
549                                         /* what type was the double arg? */
550                                         if (IS_FLT_DBL_TYPE(m->paramtypes[arg])) {
551                                                 fargcnt++;
552
553                                         } else {
554                                                 iargcnt++;
555                                         }
556                                         arg++;
557
558                                 } else if (IS_2_WORD_TYPE(m->paramtypes[arg])) {
559                                         doublewordarg = 1;
560
561                                 } else {
562                                         if (IS_FLT_DBL_TYPE(m->paramtypes[arg])) {
563                                                 fargcnt++;
564
565                                         } else {
566                                                 iargcnt++;
567                                         }
568                                         arg++;
569                                 }
570                         }
571                 }
572                 return;
573         }
574
575         for (s = 0; s < cd->maxlocals; s++) {
576                 intalloc = -1; fltalloc = -1;
577                 for (tt=0; tt<=4; tt++) {
578                         t = typeloop[tt];
579                         v = &rd->locals[s][t];
580                         if (v->type >= 0) {
581 #ifdef USETWOREGS
582                                 regsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
583 #endif
584                                 if (IS_FLT_DBL_TYPE(t)) {
585                                         if (fltalloc >= 0) {
586                                                 v->flags = rd->locals[s][fltalloc].flags;
587                                                 v->regoff = rd->locals[s][fltalloc].regoff;
588                                         }
589                                         else if (rd->maxsavfltreguse > 0) {
590                                                 rd->maxsavfltreguse--;
591                                                 v->flags = 0;
592                                                 v->regoff = rd->savfltregs[rd->maxsavfltreguse];
593                                         }
594                                         else {
595                                                 v->flags = INMEMORY;
596                                                 v->regoff = rd->maxmemuse;
597                                                 rd->maxmemuse += regsneeded + 1;
598                                         }
599                                         fltalloc = t;
600                                 }
601                                 else {
602 #if defined(__I386__)
603                                         /*
604                                          * for i386 put all longs in memory
605                                          */
606                                         if (IS_2_WORD_TYPE(t)) {
607                                                 v->flags = INMEMORY;
608                                                 v->regoff = rd->maxmemuse++;
609                                         } else {
610 #endif
611                                                 if (intalloc >= 0) {
612                                                         v->flags = rd->locals[s][intalloc].flags;
613                                                         v->regoff = rd->locals[s][intalloc].regoff;
614                                                 }
615                                                 else if (rd->maxsavintreguse > regsneeded) {
616                                                         rd->maxsavintreguse -= regsneeded+1;
617                                                         v->flags = 0;
618                                                         v->regoff = rd->savintregs[rd->maxsavintreguse];
619                                                 }
620                                                 else {
621                                                         v->flags = INMEMORY;
622                                                         v->regoff = rd->maxmemuse;
623                                                         rd->maxmemuse += regsneeded + 1;
624                                                 }
625 #if defined(__I386__)
626                                         }
627 #endif
628                                         intalloc = t;
629                                 }
630                         }
631                 }
632         }
633 }
634
635
636
637 static void reg_init_temp(registerdata *rd)
638 {
639         rd->freememtop = 0;
640         rd->memuse = rd->ifmemuse;
641
642         rd->freetmpinttop = 0;
643         rd->freesavinttop = 0;
644         rd->freetmpflttop = 0;
645         rd->freesavflttop = 0;
646
647         rd->tmpintreguse = rd->iftmpintregcnt;
648         rd->savintreguse = rd->ifsavintregcnt;
649         rd->tmpfltreguse = rd->iftmpfltregcnt;
650         rd->savfltreguse = rd->ifsavfltregcnt;
651
652         /* all argument registers are available */
653         rd->argintreguse = rd->intreg_argnum;
654         rd->argfltreguse = rd->fltreg_argnum;
655 }
656
657
658 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
659
660
661 static void reg_new_temp_func(registerdata *rd, stackptr s)
662 {
663         s4 regsneeded;
664         s4 tryagain;
665
666         /* Try to allocate a saved register if there is no temporary one          */
667         /* available. This is what happens during the second run.                 */
668         tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
669
670 #ifdef USETWOREGS
671         regsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
672 #else
673         regsneeded = 0;
674 #endif
675
676         for(; tryagain; --tryagain) {
677                 if (tryagain == 1) {
678                         if (!(s->flags & SAVEDVAR))
679                                 s->flags |= SAVEDTMP;
680                         if (IS_FLT_DBL_TYPE(s->type)) {
681                                 if (rd->freesavflttop > 0) {
682                                         rd->freesavflttop--;
683                                         s->regoff = rd->freesavfltregs[rd->freesavflttop];
684                                         return;
685
686                                 } else if (rd->savfltreguse > 0) {
687                                         rd->savfltreguse--;
688                                         if (rd->savfltreguse < rd->maxsavfltreguse)
689                                                 rd->maxsavfltreguse = rd->savfltreguse;
690                                         s->regoff = rd->savfltregs[rd->savfltreguse];
691                                         return;
692                                 }
693
694                         } else {
695 #if defined(__I386__)
696                                 /*
697                                  * for i386 put all longs in memory
698                                  */
699                                 if (!IS_2_WORD_TYPE(s->type)) {
700 #endif
701                                         if (rd->freesavinttop > regsneeded) {
702                                                 rd->freesavinttop -= regsneeded + 1;
703                                                 s->regoff = rd->freesavintregs[rd->freesavinttop];
704                                                 return;
705
706                                         } else if (rd->savintreguse > regsneeded) {
707                                                 rd->savintreguse -= regsneeded + 1;
708                                                 if (rd->savintreguse < rd->maxsavintreguse)
709                                                         rd->maxsavintreguse = rd->savintreguse;
710                                                 s->regoff = rd->savintregs[rd->savintreguse];
711                                                 return;
712                                         }
713 #if defined(__I386__)
714                                 }
715 #endif
716                         }
717
718                 } else {
719                         if (IS_FLT_DBL_TYPE(s->type)) {
720                                 if (rd->freetmpflttop > 0) {
721                                         rd->freetmpflttop--;
722                                         s->regoff = rd->freetmpfltregs[rd->freetmpflttop];
723                                         return;
724
725                                 } else if (rd->tmpfltreguse > 0) {
726                                         rd->tmpfltreguse--;
727                                         if (rd->tmpfltreguse < rd->maxtmpfltreguse)
728                                                 rd->maxtmpfltreguse = rd->tmpfltreguse;
729                                         s->regoff = rd->tmpfltregs[rd->tmpfltreguse];
730                                         return;
731                                 }
732
733                         } else {
734 #if defined(__I386__)
735                                 /*
736                                  * for i386 put all longs in memory
737                                  */
738                                 if (!IS_2_WORD_TYPE(s->type)) {
739 #endif
740                                         if (rd->freetmpinttop > regsneeded) {
741                                                 rd->freetmpinttop -= regsneeded + 1;
742                                                 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
743                                                 return;
744
745                                         } else if (rd->tmpintreguse > regsneeded) {
746                                                 rd->tmpintreguse -= regsneeded + 1;
747                                                 if (rd->tmpintreguse < rd->maxtmpintreguse)
748                                                         rd->maxtmpintreguse = rd->tmpintreguse;
749                                                 s->regoff = rd->tmpintregs[rd->tmpintreguse];
750                                                 return;
751                                         }
752 #if defined(__I386__)
753                                 }
754 #endif
755                         }
756                 }
757         }
758
759         if (rd->freememtop > regsneeded) {
760                 rd->freememtop -= regsneeded + 1;
761                 s->regoff = rd->freemem[rd->freememtop];
762
763         } else {
764                 s->regoff = rd->memuse;
765                 rd->memuse += regsneeded + 1;
766                 if (rd->memuse > rd->maxmemuse)
767                         rd->maxmemuse = rd->memuse;
768         }
769         s->flags |= INMEMORY;
770 }
771
772
773 #define reg_free_temp(rd,s) if (s->varkind == TEMPVAR) reg_free_temp_func(rd, s)
774
775
776 static void reg_free_temp_func(registerdata *rd, stackptr s)
777 {
778         s4 regsneeded;
779
780 #ifdef USETWOREGS
781         regsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
782 #else
783         regsneeded = 0;
784 #endif
785
786         if (s->flags & INMEMORY) {
787                 rd->freemem[rd->freememtop] = s->regoff;
788                 if (regsneeded)
789                         rd->freemem[rd->freememtop + 1] = s->regoff + 1;
790                 rd->freememtop += regsneeded + 1;
791
792         } else if (IS_FLT_DBL_TYPE(s->type)) {
793                 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
794                         s->flags &= ~SAVEDTMP;
795                         rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
796
797                 } else
798                         rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
799
800         } else {
801                 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
802                         s->flags &= ~SAVEDTMP;
803                         rd->freesavintregs[rd->freesavinttop] = s->regoff;
804 #ifdef USETWOREGS
805                         if (regsneeded)
806                                 rd->freesavintregs[rd->freesavinttop + 1] = rd->secondregs[s->regoff];
807 #endif
808                         rd->freesavinttop += regsneeded + 1;
809
810                 } else {
811                         rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
812 #ifdef USETWOREGS
813                         if (regsneeded)
814                                 rd->freetmpintregs[rd->freetmpinttop + 1] = rd->secondregs[s->regoff];
815 #endif
816                         rd->freetmpinttop += regsneeded + 1;
817                 }
818         }
819 }
820
821
822
823 static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
824 {
825         s4 opcode;
826         s4 i;
827         s4 len;
828         stackptr    src;
829         stackptr    dst;
830         instruction *iptr;
831         basicblock  *bptr;
832
833         bptr = m->basicblocks;
834
835         while (bptr != NULL) {
836                 if (bptr->flags >= BBREACHED) {
837                         dst = bptr->instack;
838
839                         /* initialize temp registers */
840                         reg_init_temp(rd);
841
842                         iptr = bptr->iinstr;
843                         len = bptr->icount;
844
845                         while (--len >= 0)  {
846                                 src = dst;
847                                 dst = iptr->dst;
848                                 opcode = iptr->opc;
849
850                                 switch (opcode) {
851
852                                         /* pop 0 push 0 */
853
854                                 case ICMD_NOP:
855                                 case ICMD_ELSE_ICONST:
856                                 case ICMD_CHECKASIZE:
857                                 case ICMD_CHECKEXCEPTION:
858                                 case ICMD_IINC:
859                                 case ICMD_JSR:
860                                 case ICMD_RET:
861                                 case ICMD_RETURN:
862                                 case ICMD_GOTO:
863                                 case ICMD_INLINE_START:
864                                 case ICMD_INLINE_END:
865                                         break;
866
867                                         /* pop 0 push 1 const */
868                                         
869                                 case ICMD_ICONST:
870                                 case ICMD_LCONST:
871                                 case ICMD_FCONST:
872                                 case ICMD_DCONST:
873                                 case ICMD_ACONST:
874
875                                         /* pop 0 push 1 load */
876                                         
877                                 case ICMD_ILOAD:
878                                 case ICMD_LLOAD:
879                                 case ICMD_FLOAD:
880                                 case ICMD_DLOAD:
881                                 case ICMD_ALOAD:
882                                         reg_new_temp(rd, dst);
883                                         break;
884
885                                         /* pop 2 push 1 */
886
887                                 case ICMD_IALOAD:
888                                 case ICMD_LALOAD:
889                                 case ICMD_FALOAD:
890                                 case ICMD_DALOAD:
891                                 case ICMD_AALOAD:
892
893                                 case ICMD_BALOAD:
894                                 case ICMD_CALOAD:
895                                 case ICMD_SALOAD:
896                                         reg_free_temp(rd, src);
897                                         reg_free_temp(rd, src->prev);
898                                         reg_new_temp(rd, dst);
899                                         break;
900
901                                         /* pop 3 push 0 */
902
903                                 case ICMD_IASTORE:
904                                 case ICMD_LASTORE:
905                                 case ICMD_FASTORE:
906                                 case ICMD_DASTORE:
907                                 case ICMD_AASTORE:
908
909                                 case ICMD_BASTORE:
910                                 case ICMD_CASTORE:
911                                 case ICMD_SASTORE:
912                                         reg_free_temp(rd, src);
913                                         reg_free_temp(rd, src->prev);
914                                         reg_free_temp(rd, src->prev->prev);
915                                         break;
916
917                                         /* pop 1 push 0 store */
918
919                                 case ICMD_ISTORE:
920                                 case ICMD_LSTORE:
921                                 case ICMD_FSTORE:
922                                 case ICMD_DSTORE:
923                                 case ICMD_ASTORE:
924
925                                         /* pop 1 push 0 */
926
927                                 case ICMD_POP:
928
929                                 case ICMD_IRETURN:
930                                 case ICMD_LRETURN:
931                                 case ICMD_FRETURN:
932                                 case ICMD_DRETURN:
933                                 case ICMD_ARETURN:
934
935                                 case ICMD_ATHROW:
936
937                                 case ICMD_PUTSTATIC:
938
939                                         /* pop 1 push 0 branch */
940
941                                 case ICMD_IFNULL:
942                                 case ICMD_IFNONNULL:
943
944                                 case ICMD_IFEQ:
945                                 case ICMD_IFNE:
946                                 case ICMD_IFLT:
947                                 case ICMD_IFGE:
948                                 case ICMD_IFGT:
949                                 case ICMD_IFLE:
950
951                                 case ICMD_IF_LEQ:
952                                 case ICMD_IF_LNE:
953                                 case ICMD_IF_LLT:
954                                 case ICMD_IF_LGE:
955                                 case ICMD_IF_LGT:
956                                 case ICMD_IF_LLE:
957
958                                         /* pop 1 push 0 table branch */
959
960                                 case ICMD_TABLESWITCH:
961                                 case ICMD_LOOKUPSWITCH:
962
963                                 case ICMD_NULLCHECKPOP:
964                                 case ICMD_MONITORENTER:
965                                 case ICMD_MONITOREXIT:
966                                         reg_free_temp(rd, src);
967                                         break;
968
969                                         /* pop 2 push 0 branch */
970
971                                 case ICMD_IF_ICMPEQ:
972                                 case ICMD_IF_ICMPNE:
973                                 case ICMD_IF_ICMPLT:
974                                 case ICMD_IF_ICMPGE:
975                                 case ICMD_IF_ICMPGT:
976                                 case ICMD_IF_ICMPLE:
977
978                                 case ICMD_IF_LCMPEQ:
979                                 case ICMD_IF_LCMPNE:
980                                 case ICMD_IF_LCMPLT:
981                                 case ICMD_IF_LCMPGE:
982                                 case ICMD_IF_LCMPGT:
983                                 case ICMD_IF_LCMPLE:
984
985                                 case ICMD_IF_ACMPEQ:
986                                 case ICMD_IF_ACMPNE:
987
988                                         /* pop 2 push 0 */
989
990                                 case ICMD_POP2:
991
992                                 case ICMD_PUTFIELD:
993
994                                 case ICMD_IASTORECONST:
995                                 case ICMD_LASTORECONST:
996                                 case ICMD_AASTORECONST:
997                                 case ICMD_BASTORECONST:
998                                 case ICMD_CASTORECONST:
999                                 case ICMD_SASTORECONST:
1000                                         reg_free_temp(rd, src);
1001                                         reg_free_temp(rd, src->prev);
1002                                         break;
1003
1004                                         /* pop 0 push 1 dup */
1005                                         
1006                                 case ICMD_DUP:
1007                                         reg_new_temp(rd, dst);
1008                                         break;
1009
1010                                         /* pop 0 push 2 dup */
1011                                         
1012                                 case ICMD_DUP2:
1013                                         reg_new_temp(rd, dst->prev);
1014                                         reg_new_temp(rd, dst);
1015                                         break;
1016
1017                                         /* pop 2 push 3 dup */
1018                                         
1019                                 case ICMD_DUP_X1:
1020                                         reg_free_temp(rd, src);
1021                                         reg_new_temp(rd, dst);
1022                                         reg_free_temp(rd, src->prev);
1023                                         reg_new_temp(rd, dst->prev);
1024                                         reg_new_temp(rd, dst->prev->prev);
1025                                         break;
1026
1027                                         /* pop 3 push 4 dup */
1028                                         
1029                                 case ICMD_DUP_X2:
1030                                         reg_free_temp(rd, src);
1031                                         reg_new_temp(rd, dst);
1032                                         reg_free_temp(rd, src->prev);
1033                                         reg_new_temp(rd, dst->prev);
1034                                         reg_free_temp(rd, src->prev->prev);
1035                                         reg_new_temp(rd, dst->prev->prev);
1036                                         reg_new_temp(rd, dst->prev->prev->prev);
1037                                         break;
1038
1039                                         /* pop 3 push 5 dup */
1040                                         
1041                                 case ICMD_DUP2_X1:
1042                                         reg_free_temp(rd, src);
1043                                         reg_new_temp(rd, dst);
1044                                         reg_free_temp(rd, src->prev);
1045                                         reg_new_temp(rd, dst->prev);
1046                                         reg_free_temp(rd, src->prev->prev);
1047                                         reg_new_temp(rd, dst->prev->prev);
1048                                         reg_new_temp(rd, dst->prev->prev->prev);
1049                                         reg_new_temp(rd, dst->prev->prev->prev->prev);
1050                                         break;
1051
1052                                         /* pop 4 push 6 dup */
1053                                         
1054                                 case ICMD_DUP2_X2:
1055                                         reg_free_temp(rd, src);
1056                                         reg_new_temp(rd, dst);
1057                                         reg_free_temp(rd, src->prev);
1058                                         reg_new_temp(rd, dst->prev);
1059                                         reg_free_temp(rd, src->prev->prev);
1060                                         reg_new_temp(rd, dst->prev->prev);
1061                                         reg_free_temp(rd, src->prev->prev->prev);
1062                                         reg_new_temp(rd, dst->prev->prev->prev);
1063                                         reg_new_temp(rd, dst->prev->prev->prev->prev);
1064                                         reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
1065                                         break;
1066
1067                                         /* pop 2 push 2 swap */
1068                                         
1069                                 case ICMD_SWAP:
1070                                         reg_free_temp(rd, src);
1071                                         reg_new_temp(rd, dst->prev);
1072                                         reg_free_temp(rd, src->prev);
1073                                         reg_new_temp(rd, dst);
1074                                         break;
1075
1076                                         /* pop 2 push 1 */
1077                                         
1078                                 case ICMD_IADD:
1079                                 case ICMD_ISUB:
1080                                 case ICMD_IMUL:
1081                                 case ICMD_IDIV:
1082                                 case ICMD_IREM:
1083
1084                                 case ICMD_ISHL:
1085                                 case ICMD_ISHR:
1086                                 case ICMD_IUSHR:
1087                                 case ICMD_IAND:
1088                                 case ICMD_IOR:
1089                                 case ICMD_IXOR:
1090
1091                                 case ICMD_LADD:
1092                                 case ICMD_LSUB:
1093                                 case ICMD_LMUL:
1094                                 case ICMD_LDIV:
1095                                 case ICMD_LREM:
1096
1097                                 case ICMD_LOR:
1098                                 case ICMD_LAND:
1099                                 case ICMD_LXOR:
1100
1101                                 case ICMD_LSHL:
1102                                 case ICMD_LSHR:
1103                                 case ICMD_LUSHR:
1104
1105                                 case ICMD_FADD:
1106                                 case ICMD_FSUB:
1107                                 case ICMD_FMUL:
1108                                 case ICMD_FDIV:
1109                                 case ICMD_FREM:
1110
1111                                 case ICMD_DADD:
1112                                 case ICMD_DSUB:
1113                                 case ICMD_DMUL:
1114                                 case ICMD_DDIV:
1115                                 case ICMD_DREM:
1116
1117                                 case ICMD_LCMP:
1118                                 case ICMD_FCMPL:
1119                                 case ICMD_FCMPG:
1120                                 case ICMD_DCMPL:
1121                                 case ICMD_DCMPG:
1122                                         reg_free_temp(rd, src);
1123                                         reg_free_temp(rd, src->prev);
1124                                         reg_new_temp(rd, dst);
1125                                         break;
1126
1127                                         /* pop 1 push 1 */
1128                                         
1129                                 case ICMD_IADDCONST:
1130                                 case ICMD_ISUBCONST:
1131                                 case ICMD_IMULCONST:
1132                                 case ICMD_IDIVPOW2:
1133                                 case ICMD_IREMPOW2:
1134                                 case ICMD_IANDCONST:
1135                                 case ICMD_IORCONST:
1136                                 case ICMD_IXORCONST:
1137                                 case ICMD_ISHLCONST:
1138                                 case ICMD_ISHRCONST:
1139                                 case ICMD_IUSHRCONST:
1140
1141                                 case ICMD_LADDCONST:
1142                                 case ICMD_LSUBCONST:
1143                                 case ICMD_LMULCONST:
1144                                 case ICMD_LDIVPOW2:
1145                                 case ICMD_LREMPOW2:
1146                                 case ICMD_LANDCONST:
1147                                 case ICMD_LORCONST:
1148                                 case ICMD_LXORCONST:
1149                                 case ICMD_LSHLCONST:
1150                                 case ICMD_LSHRCONST:
1151                                 case ICMD_LUSHRCONST:
1152
1153                                 case ICMD_IFEQ_ICONST:
1154                                 case ICMD_IFNE_ICONST:
1155                                 case ICMD_IFLT_ICONST:
1156                                 case ICMD_IFGE_ICONST:
1157                                 case ICMD_IFGT_ICONST:
1158                                 case ICMD_IFLE_ICONST:
1159
1160                                 case ICMD_INEG:
1161                                 case ICMD_INT2BYTE:
1162                                 case ICMD_INT2CHAR:
1163                                 case ICMD_INT2SHORT:
1164                                 case ICMD_LNEG:
1165                                 case ICMD_FNEG:
1166                                 case ICMD_DNEG:
1167
1168                                 case ICMD_I2L:
1169                                 case ICMD_I2F:
1170                                 case ICMD_I2D:
1171                                 case ICMD_L2I:
1172                                 case ICMD_L2F:
1173                                 case ICMD_L2D:
1174                                 case ICMD_F2I:
1175                                 case ICMD_F2L:
1176                                 case ICMD_F2D:
1177                                 case ICMD_D2I:
1178                                 case ICMD_D2L:
1179                                 case ICMD_D2F:
1180
1181                                 case ICMD_CHECKCAST:
1182
1183                                 case ICMD_ARRAYLENGTH:
1184                                 case ICMD_INSTANCEOF:
1185
1186                                 case ICMD_NEWARRAY:
1187                                 case ICMD_ANEWARRAY:
1188
1189                                 case ICMD_GETFIELD:
1190                                         reg_free_temp(rd, src);
1191                                         reg_new_temp(rd, dst);
1192                                         break;
1193
1194                                         /* pop 0 push 1 */
1195                                         
1196                                 case ICMD_GETSTATIC:
1197
1198                                 case ICMD_NEW:
1199                                         reg_new_temp(rd, dst);
1200                                         break;
1201
1202                                         /* pop many push any */
1203                                         
1204                                 case ICMD_INVOKEVIRTUAL:
1205                                 case ICMD_INVOKESPECIAL:
1206                                 case ICMD_INVOKESTATIC:
1207                                 case ICMD_INVOKEINTERFACE:
1208                                         i = iptr->op1;
1209                                         while (--i >= 0) {
1210                                                 reg_free_temp(rd, src);
1211                                                 src = src->prev;
1212                                         }
1213                                         if (((methodinfo *) iptr->val.a)->returntype != TYPE_VOID)
1214                                                 reg_new_temp(rd, dst);
1215                                         break;
1216
1217                                 case ICMD_BUILTIN3:
1218                                         reg_free_temp(rd, src);
1219                                         src = src->prev;
1220                                 case ICMD_BUILTIN2:
1221                                         reg_free_temp(rd, src);
1222                                         src = src->prev;
1223                                 case ICMD_BUILTIN1:
1224                                         reg_free_temp(rd, src);
1225                                         src = src->prev;
1226                                         if (iptr->op1 != TYPE_VOID)
1227                                                 reg_new_temp(rd, dst);
1228                                         break;
1229
1230                                 case ICMD_MULTIANEWARRAY:
1231                                         i = iptr->op1;
1232                                         while (--i >= 0) {
1233                                                 reg_free_temp(rd, src);
1234                                                 src = src->prev;
1235                                         }
1236                                         reg_new_temp(rd, dst);
1237                                         break;
1238
1239                                 default:
1240                                         printf("ICMD %d at %d\n", iptr->opc, (s4) (iptr - m->instructions));
1241                                         panic("Missing ICMD code during register allocation");
1242                                 } /* switch */
1243                                 iptr++;
1244                         } /* while instructions */
1245                 } /* if */
1246                 bptr = bptr->next;
1247         } /* while blocks */
1248 }
1249
1250
1251 /*
1252  * These are local overrides for various environment variables in Emacs.
1253  * Please do not remove this and leave it at the end of the file, where
1254  * Emacs will automagically detect them.
1255  * ---------------------------------------------------------------------
1256  * Local variables:
1257  * mode: c
1258  * indent-tabs-mode: t
1259  * c-basic-offset: 4
1260  * tab-width: 4
1261  * End:
1262  */