1d946b345e8e467fb48f97fcaa3204dcf4fdb4b5
[cacao.git] / src / vm / jit / reg.inc
1 /* src/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                         Christian Ullrich
32             Michael Starzinger
33
34    $Id: reg.inc 3969 2005-12-21 00:07:23Z twisti $
35
36 */
37
38
39 #include "arch.h"
40 #include "mm/memory.h"
41 #include "vm/method.h"   
42 #include "vm/resolve.h"
43 #include "vm/jit/reg.h"
44
45
46 /* function prototypes for this file */
47
48 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
49 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd);
50 static void allocate_scratch_registers(methodinfo *m, registerdata *rd);
51
52
53 /* reg_init ********************************************************************
54
55    TODO
56         
57 *******************************************************************************/
58
59 void reg_init()
60 {
61         /* void */
62 }
63
64
65 /* reg_setup *******************************************************************
66
67    TODO
68
69 *******************************************************************************/
70
71 void reg_setup(methodinfo *m, registerdata *rd, t_inlining_globals *id)
72 {
73         s4 i;
74         varinfo5 *v;
75         
76         /* setup the integer register table */
77
78 #if defined(__ARM__)
79         /* On ARM longs can be split across argument regs and stack. This is
80          * signed by setting the HIGH_REG to INT_ARG_CNT in md_param_alloc().
81          * Here we make sure it resolves to a special dummy reg (REG_SPLIT). */
82         rd->argintregs = DMNEW(s4, INT_ARG_CNT + 1);
83         rd->argintregs[INT_ARG_CNT] = REG_SPLIT;
84 #else
85         rd->argintregs = DMNEW(s4, INT_ARG_CNT);
86 #endif
87         rd->tmpintregs = DMNEW(s4, INT_TMP_CNT);
88         rd->savintregs = DMNEW(s4, INT_SAV_CNT);
89         rd->freeargintregs = DMNEW(s4, INT_ARG_CNT);
90         rd->freetmpintregs = DMNEW(s4, INT_TMP_CNT);
91         rd->freesavintregs = DMNEW(s4, INT_SAV_CNT);
92
93         rd->argintreguse = 0;
94         rd->tmpintreguse = 0;
95         rd->savintreguse = 0;
96
97         for (i = 0; i < INT_REG_CNT; i++) {
98                 switch (nregdescint[i]) {
99                 case REG_RET:
100                         rd->intreg_ret = i; 
101                         break;
102                 case REG_SAV:
103                         rd->savintregs[rd->savintreguse++] = i;
104                         break;
105                 case REG_TMP:
106                         rd->tmpintregs[rd->tmpintreguse++] = i; 
107                         break;
108                 case REG_ARG:
109                         rd->argintregs[rd->argintreguse++] = i;
110                         break;
111                 }
112         }
113         assert(rd->savintreguse == INT_SAV_CNT);
114         assert(rd->tmpintreguse == INT_TMP_CNT);
115         assert(rd->argintreguse == INT_ARG_CNT);
116
117 #if defined(__X86_64__)
118         /* 
119          * on x86_64 the argument registers are not in ascending order 
120          * a00 (%rdi) <-> a03 (%rcx) and a01 (%rsi) <-> a02 (%rdx)
121          */
122         i = rd->argintregs[3];
123         rd->argintregs[3] = rd->argintregs[0];
124         rd->argintregs[0] = i;
125
126         i = rd->argintregs[2];
127         rd->argintregs[2] = rd->argintregs[1];
128         rd->argintregs[1] = i;
129 #endif
130                 
131 #ifdef HAS_ADDRESS_REGISTER_FILE
132         /* setup the address register table */
133
134         rd->argadrregs = DMNEW(s4, ADR_ARG_CNT);
135         rd->tmpadrregs = DMNEW(s4, ADR_TMP_CNT);
136         rd->savadrregs = DMNEW(s4, ADR_SAV_CNT);
137         rd->freeargadrregs = DMNEW(s4, ADR_ARG_CNT);
138         rd->freetmpadrregs = DMNEW(s4, ADR_TMP_CNT);
139         rd->freesavadrregs = DMNEW(s4, ADR_SAV_CNT);
140
141         rd->adrreg_argnum = 0;
142         rd->argadrreguse = 0;
143         rd->tmpadrreguse = 0;
144         rd->savadrreguse = 0;
145
146         for (i = 0; i < ADR_REG_CNT; i++) {
147                 switch (nregdescadr[i]) {
148                 case REG_RET:
149                         rd->adrreg_ret = i; 
150                         break;
151                 case REG_SAV:
152                         rd->savadrregs[rd->savadrreguse++] = i;
153                         break;
154                 case REG_TMP:
155                         rd->tmpadrregs[rd->tmpadrreguse++] = i; 
156                         break;
157                 case REG_ARG:
158                         rd->argadrregs[rd->argadrreguse++] = i;
159                         break;
160                 }
161         }
162         assert(rd->savadrreguse == ADR_SAV_CNT);
163         assert(rd->tmpadrreguse == ADR_TMP_CNT);
164         assert(rd->argadrreguse == ADR_ARG_CNT);
165 #endif
166                 
167         /* setup the float register table */
168
169         rd->argfltregs = DMNEW(s4, FLT_ARG_CNT);
170         rd->tmpfltregs = DMNEW(s4, FLT_TMP_CNT);
171         rd->savfltregs = DMNEW(s4, FLT_SAV_CNT);
172         rd->freeargfltregs = DMNEW(s4, FLT_ARG_CNT);
173         rd->freetmpfltregs = DMNEW(s4, FLT_TMP_CNT);
174         rd->freesavfltregs = DMNEW(s4, FLT_SAV_CNT);
175
176         rd->argfltreguse = 0;
177         rd->tmpfltreguse = 0;
178         rd->savfltreguse = 0;
179
180         for (i = 0; i < FLT_REG_CNT; i++) {
181                 switch (nregdescfloat[i]) {
182                 case REG_RET:
183                         rd->fltreg_ret = i;
184                         break;
185                 case REG_SAV:
186                         rd->savfltregs[rd->savfltreguse++] = i;
187                         break;
188                 case REG_TMP:
189                         rd->tmpfltregs[rd->tmpfltreguse++] = i;
190                         break;
191                 case REG_ARG:
192                         rd->argfltregs[rd->argfltreguse++] = i;
193                         break;
194                 }
195         }
196         assert(rd->savfltreguse == FLT_SAV_CNT);
197         assert(rd->tmpfltreguse == FLT_TMP_CNT);
198         assert(rd->argfltreguse == FLT_ARG_CNT);
199
200
201         rd->freemem    = DMNEW(s4, id->cummaxstack);
202 #if defined(HAS_4BYTE_STACKSLOT)
203         rd->freemem_2  = DMNEW(s4, id->cummaxstack);
204 #endif
205         rd->locals     = DMNEW(varinfo5, id->cumlocals);
206         rd->interfaces = DMNEW(varinfo5, id->cummaxstack);
207         for (v = rd->locals, i = id->cumlocals; i > 0; v++, i--) {
208                 v[0][TYPE_INT].type = -1;
209                 v[0][TYPE_LNG].type = -1;
210                 v[0][TYPE_FLT].type = -1;
211                 v[0][TYPE_DBL].type = -1;
212                 v[0][TYPE_ADR].type = -1;
213         }
214
215         for (v = rd->interfaces, i = id->cummaxstack; i > 0; v++, i--) {
216                 v[0][TYPE_INT].type = -1;
217                 v[0][TYPE_INT].flags = 0;
218                 v[0][TYPE_LNG].type = -1;
219                 v[0][TYPE_LNG].flags = 0;
220                 v[0][TYPE_FLT].type = -1;
221                 v[0][TYPE_FLT].flags = 0;
222                 v[0][TYPE_DBL].type = -1;
223                 v[0][TYPE_DBL].flags = 0;
224                 v[0][TYPE_ADR].type = -1;
225                 v[0][TYPE_ADR].flags = 0;
226         }
227
228 #if defined(SPECIALMEMUSE)
229 # if defined(__DARWIN__)
230         /* 6*4=24 byte linkage area + 8*4=32 byte minimum parameter Area */
231         rd->memuse = LA_WORD_SIZE + INT_ARG_CNT; 
232 # else
233         rd->memuse = LA_WORD_SIZE;
234 # endif
235 #else
236         rd->memuse = 0; /* init to zero -> analyse_stack will set it to a higher  */
237                         /* value, if appropriate */
238 #endif
239
240         /* Set rd->argxxxreguse to XXX_ARG_CNBT to not use unused argument        */
241         /* registers as temp registers  */
242 #if defined(HAS_ADDRESS_REGISTER_FILE)
243         rd->argadrreguse = 0;
244 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
245         rd->argintreguse = 0;
246         rd->argfltreguse = 0;
247 }
248
249
250 /* function reg_free ***********************************************************
251
252    releases all allocated space for registers
253
254 *******************************************************************************/
255
256 void reg_free(methodinfo *m, registerdata *rd)
257 {
258         /* void */
259 }
260
261
262 /* reg_close *******************************************************************
263
264    TODO
265
266 *******************************************************************************/
267
268 void reg_close()
269 {
270         /* void */
271 }
272
273
274 /* function interface_regalloc *************************************************
275
276         allocates registers for all interface variables
277         
278 *******************************************************************************/
279         
280 void regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
281 {
282         interface_regalloc(m, cd, rd);
283         allocate_scratch_registers(m, rd);
284         local_regalloc(m, cd, rd);
285 #ifdef INVOKE_NEW_DEBUG
286                 if (compileverbose) {
287                         printf("memuse after reg.inc: %3i\n",rd->memuse);
288                 }
289 #endif
290 }
291
292
293 /* function interface_regalloc *************************************************
294
295         allocates registers for all interface variables
296         
297 *******************************************************************************/
298         
299 static void interface_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
300 {
301         int     s, t, tt, saved;
302         int     intalloc, fltalloc; /* Remember allocated Register/Memory offset */
303                       /* in case a more vars are packed into this interface slot */
304         varinfo *v;
305         int             intregsneeded = 0;
306         int             memneeded = 0;
307     /* allocate LNG and DBL Types first to ensure 2 memory slots or registers */
308         /* on HAS_4BYTE_STACKSLOT architectures */
309         int     typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
310
311         /* rd->memuse was already set in stack.c to allocate stack space for */
312         /* passing arguments to called methods                               */
313 #if defined(__I386__)
314         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
315                 /* reserve 0(%esp) for Monitorenter/exit Argument on i386 */
316                 if (rd->memuse < 1)
317                         rd->memuse = 1;
318         }
319 #endif
320 #ifdef INVOKE_NEW_DEBUG
321         if (compileverbose) {
322                 if (checksync && (m->flags & ACC_SYNCHRONIZED))
323                         printf("ACC_SYNCHRONIZED\n");
324                 printf("analyse: argintru %3i argfltru %3i memuse %3i\n",
325                            rd->argintreguse, rd->argfltreguse, rd->memuse);
326         }
327 #endif
328
329
330         for (s = 0; s < cd->maxstack; s++) {
331                 intalloc = -1; fltalloc = -1;
332                 saved = (rd->interfaces[s][TYPE_INT].flags |
333                                  rd->interfaces[s][TYPE_LNG].flags |
334                          rd->interfaces[s][TYPE_FLT].flags |
335                                  rd->interfaces[s][TYPE_DBL].flags |
336                          rd->interfaces[s][TYPE_ADR].flags) & SAVEDVAR;
337  
338                 for (tt = 0; tt <= 4; tt++) {
339                         t = typeloop[tt];
340                         v = &rd->interfaces[s][t];
341                         if (v->type >= 0) {
342 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
343                                 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
344 #endif
345 #if defined(HAS_4BYTE_STACKSLOT)
346                                 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
347 #endif
348                                 if (!saved) {
349 #if defined(HAS_ADDRESS_REGISTER_FILE)
350                                         if (IS_ADR_TYPE(t)) {
351                                                 if (!m->isleafmethod 
352                                                         &&(rd->argadrreguse < ADR_ARG_CNT)) {
353                                                         v->regoff = rd->argadrregs[rd->argadrreguset++];
354                                                 } else if (rd->tmpadrreguse > 0) {
355                                                                 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
356                                                 } else if (rd->savadrreguse > 0) {
357                                                                 v->regoff = rd->savadrregs[--rd->savadrreguse];
358                                                 } else {
359                                                         v->flags |= INMEMORY;
360                                                         v->regoff = rd->memuse++;
361                                                 }                                               
362                                         } else /* !IS_ADR_TYPE */
363 #endif /* defined(HAS_ADDRESS_REGISTER_FILE) */
364                                         {
365                                                 if (IS_FLT_DBL_TYPE(t)) {
366                                                         if (fltalloc >= 0) {
367                        /* Reuse memory slot(s)/register(s) for shared interface slots */
368                                                                 v->flags |= rd->interfaces[s][fltalloc].flags
369                                                                         & INMEMORY;
370                                                                 v->regoff = rd->interfaces[s][fltalloc].regoff;
371                                                         } else if (!m->isleafmethod 
372                                                                            && (rd->argfltreguse < FLT_ARG_CNT)) {
373                                                                 v->regoff = rd->argfltregs[rd->argfltreguse++];
374                                                         } else if (rd->tmpfltreguse > 0) {
375                                                                 v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
376                                                         } else if (rd->savfltreguse > 0) {
377                                                                 v->regoff = rd->savfltregs[--rd->savfltreguse];
378                                                         } else {
379                                                                 v->flags |= INMEMORY;
380                                                                 v->regoff = rd->memuse;
381                                                                 rd->memuse += memneeded + 1;
382                                                         }
383                                                         fltalloc = t;
384                                                 } else { /* !IS_FLT_DBL_TYPE(t) */
385 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
386                                                         /*
387                                                          * for i386 put all longs in memory
388                                                          */
389                                                         if (IS_2_WORD_TYPE(t)) {
390                                                                 v->flags |= INMEMORY;
391                                                                 v->regoff = rd->memuse;
392                                                                 rd->memuse += memneeded + 1;
393                                                         } else
394 #endif /* defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE...GISTERS) */
395 /* #if !defined(HAS_4BYTE_STACKSLOT) */
396                                                                 if (intalloc >= 0) {
397                        /* Reuse memory slot(s)/register(s) for shared interface slots */
398                                                                         v->flags |= 
399                                                                                 rd->interfaces[s][intalloc].flags 
400                                                                                 & INMEMORY;
401 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
402                                                                         if (!(v->flags & INMEMORY) 
403                                                                                 && IS_2_WORD_TYPE(intalloc))
404                                                                                 v->regoff = GET_LOW_REG(
405                                                                                         rd->interfaces[s][intalloc].regoff);
406                                                                         else
407 #endif
408                                                                                 v->regoff = 
409                                                                                     rd->interfaces[s][intalloc].regoff;
410                                                                 } else 
411 /* #endif *//* !defined(HAS_4BYTE_STACKSLOT) */
412                                                                         if (!m->isleafmethod && 
413                                                                                 (rd->argintreguse 
414                                                                                  + intregsneeded < INT_ARG_CNT)) {
415 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
416                                                                                 if (intregsneeded) 
417                                                                                         v->regoff=PACK_REGS( 
418                                                                                   rd->argintregs[rd->argintreguse],
419                                                                                   rd->argintregs[rd->argintreguse + 1]);
420                                                                                 else
421 #endif
422                                                                                         v->regoff = 
423                                                                                            rd->argintregs[rd->argintreguse];
424                                                                                 rd->argintreguse += intregsneeded + 1;
425                                                                         }
426                                                                         else if (rd->tmpintreguse > intregsneeded) {
427                                                                                 rd->tmpintreguse -= intregsneeded + 1;
428 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
429                                                                                 if (intregsneeded) 
430                                                                                         v->regoff=PACK_REGS( 
431                                                                                   rd->tmpintregs[rd->tmpintreguse],
432                                                                                   rd->tmpintregs[rd->tmpintreguse + 1]);
433                                                                                 else
434 #endif
435                                                                                         v->regoff = 
436                                                                                            rd->tmpintregs[rd->tmpintreguse];
437                                                                         }
438                                                                         else if (rd->savintreguse > intregsneeded) {
439                                                                                 rd->savintreguse -= intregsneeded + 1;
440                                                                                 v->regoff = 
441                                                                                         rd->savintregs[rd->savintreguse];
442 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
443                                                                                 if (intregsneeded) 
444                                                                                         v->regoff=PACK_REGS( 
445                                                                                   rd->savintregs[rd->savintreguse],
446                                                                                   rd->savintregs[rd->savintreguse + 1]);
447                                                                                 else
448 #endif
449                                                                                         v->regoff = 
450                                                                                            rd->savintregs[rd->savintreguse];
451                                                                         }
452                                                                         else {
453                                                                                 v->flags |= INMEMORY;
454                                                                                 v->regoff = rd->memuse;
455                                                                                 rd->memuse += memneeded + 1;
456                                                                         }
457
458                                                         intalloc = t;
459                                                 } /* if (IS_FLT_DBL_TYPE(t)) */
460                                         } 
461                                 } else { /* (saved) */
462 /* now the same like above, but without a chance to take a temporary register */
463 #ifdef HAS_ADDRESS_REGISTER_FILE
464                                         if (IS_ADR_TYPE(t)) {
465                                                 if (rd->savadrreguse > 0) {
466                                                         v->regoff = rd->savadrregs[--rd->savadrreguse];
467                                                 }
468                                                 else {
469                                                         v->flags |= INMEMORY;
470                                                         v->regoff = rd->memuse++;
471                                                 }                                               
472                                         } else
473 #endif
474                                         {
475                                                 if (IS_FLT_DBL_TYPE(t)) {
476                                                         if (fltalloc >= 0) {
477                                                                 v->flags |= rd->interfaces[s][fltalloc].flags
478                                                                         & INMEMORY;
479                                                                 v->regoff = rd->interfaces[s][fltalloc].regoff;
480                                                         } else
481                                                                 if (rd->savfltreguse > 0) {
482                                                                         v->regoff = rd->savfltregs[--rd->savfltreguse];
483                                                                 }
484                                                                 else {
485                                                                         v->flags |= INMEMORY;
486                                                                         v->regoff = rd->memuse;
487                                                                         rd->memuse += memneeded + 1;
488                                                                 }
489                                                         fltalloc = t;
490                                                 }
491                                                 else { /* IS_INT_LNG */
492 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
493                                                         /*
494                                                          * for i386 put all longs in memory
495                                                          */
496                                                         if (IS_2_WORD_TYPE(t)) {
497                                                                 v->flags |= INMEMORY;
498                                                                 v->regoff = rd->memuse;
499                                                                 rd->memuse += memneeded + 1;
500                                                         } else
501 #endif
502                                                         {
503 /* #if !defined(HAS_4BYTE_STACKSLOT) */
504                                                                 if (intalloc >= 0) {
505                                                                         v->flags |= 
506                                                                    rd->interfaces[s][intalloc].flags & INMEMORY;
507 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
508                                                                         if (!(v->flags & INMEMORY)
509                                                                                 && IS_2_WORD_TYPE(intalloc))
510                                                                                 v->regoff =
511                                                                                         GET_LOW_REG(
512                                                                                         rd->interfaces[s][intalloc].regoff);
513                                                                         else
514 #endif
515                                                                                 v->regoff =
516                                                                                         rd->interfaces[s][intalloc].regoff;
517                                                                 } else
518 /* #endif */
519                                                                 {
520                                                                         if (rd->savintreguse > intregsneeded) {
521                                                                                 rd->savintreguse -= intregsneeded + 1;
522 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
523                                                                                 if (intregsneeded) 
524                                                                                         v->regoff = PACK_REGS( 
525                                                                                   rd->savintregs[rd->savintreguse],
526                                                                                   rd->savintregs[rd->savintreguse + 1]);
527                                                                                 else
528 #endif
529                                                                                         v->regoff =
530                                                                                            rd->savintregs[rd->savintreguse];
531                                                                         } else {
532                                                                                 v->flags |= INMEMORY;
533                                                                                 v->regoff = rd->memuse;
534                                                                                 rd->memuse += memneeded + 1;
535                                                                         }
536                                                                 }
537                                                                 intalloc = t;
538                                                         }
539                                                 } /* if (IS_FLT_DBL_TYPE(t) else */
540                                         } /* if (IS_ADR_TYPE(t)) else */
541                                 } /* if (saved) else */
542                         } /* if (type >= 0) */
543                 } /* for t */
544         } /* for s */
545 }
546
547
548
549 /* function local_regalloc *****************************************************
550
551         allocates registers for all local variables
552         
553 *******************************************************************************/
554         
555 static void local_regalloc(methodinfo *m, codegendata *cd, registerdata *rd)
556 {
557         int     p, s, t, tt;
558         int     intalloc, fltalloc;
559         varinfo *v;
560         int     intregsneeded = 0;
561         int     memneeded = 0;
562         int     typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
563         int     fargcnt, iargcnt;
564 #ifdef HAS_ADDRESS_REGISTER_FILE
565         int     aargcnt;
566 #endif
567
568         if (m->isleafmethod) {
569                 methoddesc *md = m->parseddesc;
570
571                 iargcnt = md->argintreguse;
572                 fargcnt = md->argfltreguse;
573 #ifdef HAS_ADDRESS_REGISTER_FILE
574                 aargcnt = md->argadrreguse;
575 #endif
576                 for (p = 0, s = 0; s < cd->maxlocals; s++, p++) {
577                         intalloc = -1; fltalloc = -1;
578                         for (tt = 0; tt <= 4; tt++) {
579                                 t = typeloop[tt];
580                                 v = &rd->locals[s][t];
581
582                                 if (v->type < 0)
583                                         continue;
584
585 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
586                                 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
587 #endif
588 #if defined(HAS_4BYTE_STACKSLOT)
589                                 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
590 #endif
591
592                                 /*
593                                  *  The order of
594                                  *
595                                  *  #ifdef HAS_ADDRESS_REGISTER_FILE
596                                  *  if (IS_ADR_TYPE) { 
597                                  *  ...
598                                  *  } else 
599                                  *  #endif
600                                  *  if (IS_FLT_DBL) {
601                                  *  ...
602                                  *  } else { / int & lng
603                                  *  ...
604                                  *  }
605                                  *
606                                  *  must not to be changed!
607                                  */
608
609 #ifdef HAS_ADDRESS_REGISTER_FILE
610                                 if (IS_ADR_TYPE(t)) {
611                                         if ((p < md->paramcount) && !md->params[p].inmemory) {
612                                                 v->flags = 0;
613                                                 v->regoff = rd->argadrregs[md->params[p].regoff];
614                                         }
615                                         if (rd->tmpadrreguse > 0) {
616                                                 v->flags = 0;
617                                                 v->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
618                                         }
619                                         else if (rd->savadrreguse > 0) {
620                                                 v->flags = 0;
621                                                 v->regoff = rd->savadrregs[--rd->savadrreguse];
622                                         }
623                                         /* use unused argument registers as local registers */
624                                         else if ((p >= md->paramcount) &&
625                                                          (aargcnt < ADR_ARG_CNT)) {
626                                                 v->flags = 0;
627                                                 v->regoff = rd->argadrregs[aargcnt++];
628                                         }
629                                         else {
630                                                 v->flags |= INMEMORY;
631                                                 v->regoff = rd->memuse++;
632                                         }                                               
633                                 } else {
634 #endif
635                                         if (IS_FLT_DBL_TYPE(t)) {
636                                                 if (fltalloc >= 0) {
637                                                         v->flags = rd->locals[s][fltalloc].flags;
638                                                         v->regoff = rd->locals[s][fltalloc].regoff;
639                                                 }
640 #if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
641                                                 /* We can only use float arguments as local variables,
642                                                  * if we do not pass them in integer registers. */
643                                                 else if ((p < md->paramcount) &&
644                                                                  !md->params[p].inmemory) {
645                                                         v->flags = 0;
646                                                         v->regoff = rd->argfltregs[md->params[p].regoff];
647                                                 }
648 #endif
649                                                 else if (rd->tmpfltreguse > 0) {
650                                                         v->flags = 0;
651                                                         v->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
652                                                 }
653                                                 else if (rd->savfltreguse > 0) {
654                                                         v->flags = 0;
655                                                         v->regoff = rd->savfltregs[--rd->savfltreguse];
656                                                 }
657                                                 /* use unused argument registers as local registers */
658                                                 else if ((p >= m->paramcount) &&
659                                                                  (fargcnt < FLT_ARG_CNT)) {
660                                                         v->flags = 0;
661                                                         v->regoff = rd->argfltregs[fargcnt];
662                                                         fargcnt++;
663                                                 }
664                                                 else {
665                                                         v->flags = INMEMORY;
666                                                         v->regoff = rd->memuse;
667                                                         rd->memuse += memneeded + 1;
668                                                 }
669                                                 fltalloc = t;
670
671                                         } else {
672 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
673                                                 /*
674                                                  * for i386 put all longs in memory
675                                                  */
676                                                 if (IS_2_WORD_TYPE(t)) {
677                                                         v->flags = INMEMORY;
678                                                         v->regoff = rd->memuse;
679                                                         rd->memuse += memneeded + 1;
680                                                 } else 
681 #endif
682                                                 {
683                                                         if (intalloc >= 0) {
684                                                                 v->flags = rd->locals[s][intalloc].flags;
685 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
686                                                                 if (!(v->flags & INMEMORY)
687                                                                         && IS_2_WORD_TYPE(intalloc))
688                                                                         v->regoff = GET_LOW_REG(
689                                                                                     rd->locals[s][intalloc].regoff);
690                                                                 else
691 #endif
692                                                                         v->regoff = rd->locals[s][intalloc].regoff;
693                                                         }
694                                                         else if ((p < md->paramcount) && 
695                                                                          !md->params[p].inmemory) {
696                                                                 v->flags = 0;
697 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
698                                                                 if (IS_2_WORD_TYPE(t))
699 /* For ARM: - if GET_LOW_REG(md->params[p].regoff) == R4, prevent here that   */
700 /* rd->argintregs[GET_HIGH_REG(md->...)) is used!                             */
701                                                                         v->regoff = PACK_REGS(
702                                                         rd->argintregs[GET_LOW_REG(md->params[p].regoff)],
703                                                         rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]);
704                                                                         else
705 #endif
706                                                                                 v->regoff =
707                                                                                rd->argintregs[md->params[p].regoff];
708                                                         }
709                                                         else if (rd->tmpintreguse > intregsneeded) {
710                                                                 rd->tmpintreguse -= intregsneeded + 1;
711                                                                 v->flags = 0;
712 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
713                                                                 if (intregsneeded) 
714                                                                         v->regoff = PACK_REGS(
715                                                                             rd->tmpintregs[rd->tmpintreguse],
716                                                                                 rd->tmpintregs[rd->tmpintreguse + 1]);
717                                                                 else
718 #endif
719                                                                         v->regoff = 
720                                                                                 rd->tmpintregs[rd->tmpintreguse];
721                                                         }
722                                                         else if (rd->savintreguse > intregsneeded) {
723                                                                 rd->savintreguse -= intregsneeded + 1;
724                                                                 v->flags = 0;
725 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
726                                                                 if (intregsneeded) 
727                                                                         v->regoff = PACK_REGS(
728                                                                             rd->savintregs[rd->savintreguse],
729                                                                                 rd->savintregs[rd->savintreguse + 1]);
730                                                                 else
731 #endif
732                                                                         v->regoff =rd->savintregs[rd->savintreguse];
733                                                         }
734                                                         /*
735                                                          * use unused argument registers as local registers
736                                                          */
737                                                         else if ((p >= m->paramcount) &&
738                                                                          (iargcnt < INT_ARG_CNT)) {
739                                                                 v->flags = 0;
740                                                                 v->regoff = rd->argintregs[iargcnt];
741                                                                 iargcnt++;
742                                                         }
743                                                         else {
744                                                                 v->flags = INMEMORY;
745                                                                 v->regoff = rd->memuse;
746                                                                 rd->memuse += memneeded + 1;
747                                                         }
748                                                 }
749                                                 intalloc = t;
750                                         }
751 #ifdef HAS_ADDRESS_REGISTER_FILE
752                                 }
753 #endif
754                         } /* for (tt=0;...) */
755
756                         /* If the current parameter is a 2-word type, the next local slot */
757                         /* is skipped.                                                    */
758
759                         if (p < md->paramcount)
760                                 if (IS_2_WORD_TYPE(md->paramtypes[p].type))
761                                         s++;
762                 }
763                 return;
764         }
765
766         for (s = 0; s < cd->maxlocals; s++) {
767                 intalloc = -1; fltalloc = -1;
768                 for (tt=0; tt<=4; tt++) {
769                         t = typeloop[tt];
770                         v = &rd->locals[s][t];
771
772                         if (v->type >= 0) {
773 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
774                                 intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
775 #endif
776 #if defined(HAS_4BYTE_STACKSLOT)
777                                 memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
778 #endif
779 #ifdef HAS_ADDRESS_REGISTER_FILE
780                                 if ( IS_ADR_TYPE(t) ) {
781                                         if (rd->savadrreguse > 0) {
782                                                 v->flags = 0;
783                                                 v->regoff = rd->savadrregs[--rd->savadrreguse];
784                                         }
785                                         else {
786                                                 v->flags = INMEMORY;
787                                                 v->regoff = rd->memuse++;
788                                         }
789                                 } else {
790 #endif
791                                 if (IS_FLT_DBL_TYPE(t)) {
792                                         if (fltalloc >= 0) {
793                                                 v->flags = rd->locals[s][fltalloc].flags;
794                                                 v->regoff = rd->locals[s][fltalloc].regoff;
795                                         }
796                                         else if (rd->savfltreguse > 0) {
797                                                 v->flags = 0;
798                                                 v->regoff = rd->savfltregs[--rd->savfltreguse];
799                                         }
800                                         else {
801                                                 v->flags = INMEMORY;
802                                                 /* Align doubles in Memory */
803                                                 if ( (memneeded) && (rd->memuse & 1))
804                                                         rd->memuse++;
805                                                 v->regoff = rd->memuse;
806                                                 rd->memuse += memneeded + 1;
807                                         }
808                                         fltalloc = t;
809                                 }
810                                 else {
811 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
812                                         /*
813                                          * for i386 put all longs in memory
814                                          */
815                                         if (IS_2_WORD_TYPE(t)) {
816                                                 v->flags = INMEMORY;
817                                                 v->regoff = rd->memuse;
818                                                 rd->memuse += memneeded + 1;
819                                         } else {
820 #endif
821                                                 if (intalloc >= 0) {
822                                                         v->flags = rd->locals[s][intalloc].flags;
823 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
824                                                         if (!(v->flags & INMEMORY)
825                                                                 && IS_2_WORD_TYPE(intalloc))
826                                                                 v->regoff = GET_LOW_REG(
827                                                                             rd->locals[s][intalloc].regoff);
828                                                         else
829 #endif
830                                                                 v->regoff = rd->locals[s][intalloc].regoff;
831                                                 }
832                                                 else if (rd->savintreguse > intregsneeded) {
833                                                         rd->savintreguse -= intregsneeded+1;
834                                                         v->flags = 0;
835 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
836                                                                 if (intregsneeded) 
837                                                                         v->regoff = PACK_REGS(
838                                                                                 rd->savintregs[rd->savintreguse],
839                                                                             rd->savintregs[rd->savintreguse + 1]);
840                                                                 else
841 #endif
842                                                                         v->regoff =rd->savintregs[rd->savintreguse];
843                                                 }
844                                                 else {
845                                                         v->flags = INMEMORY;
846                                                         v->regoff = rd->memuse;
847                                                         rd->memuse += memneeded + 1;
848                                                 }
849 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
850                                         }
851 #endif
852                                         intalloc = t;
853                                 }
854 #ifdef HAS_ADDRESS_REGISTER_FILE
855                                 }
856 #endif
857
858                         }
859                 }
860         }
861 }
862
863 static void reg_init_temp(methodinfo *m, registerdata *rd)
864 {
865         rd->freememtop = 0;
866 #if defined(HAS_4BYTE_STACKSLOT)
867         rd->freememtop_2 = 0;
868 #endif
869
870         rd->freetmpinttop = 0;
871         rd->freesavinttop = 0;
872         rd->freetmpflttop = 0;
873         rd->freesavflttop = 0;
874 #ifdef HAS_ADDRESS_REGISTER_FILE
875         rd->freetmpadrtop = 0;
876         rd->freesavadrtop = 0;
877 #endif
878
879         rd->freearginttop = 0;
880         rd->freeargflttop = 0;
881 #ifdef HAS_ADDRESS_REGISTER_FILE
882         rd->freeargadrtop = 0;
883 #endif
884
885         if (m->isleafmethod) {
886                 /* Don't use not used Argument Registers in Leafmethods -> they could */
887                 /* already be in use for Locals passed as parameter to this Method    */
888                 rd->argintreguse = INT_ARG_CNT;
889                 rd->argfltreguse = FLT_ARG_CNT;
890 #ifdef HAS_ADDRESS_REGISTER_FILE
891                 rd->argadrreguse = ADR_ARG_CNT;
892 #endif
893         }
894 }
895
896
897 #define reg_new_temp(rd,s) if (s->varkind == TEMPVAR) reg_new_temp_func(rd, s)
898
899 static void reg_new_temp_func(registerdata *rd, stackptr s)
900 {
901         s4 intregsneeded;
902         s4 memneeded;
903         s4 tryagain;
904
905         /* Try to allocate a saved register if there is no temporary one          */
906         /* available. This is what happens during the second run.                 */
907         tryagain = (s->flags & SAVEDVAR) ? 1 : 2;
908
909 #ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
910         intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
911 #else
912         intregsneeded = 0;
913 #endif
914 #if defined(HAS_4BYTE_STACKSLOT)
915         memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
916 #else
917         memneeded = 0;
918 #endif
919
920         for(; tryagain; --tryagain) {
921                 if (tryagain == 1) {
922                         if (!(s->flags & SAVEDVAR))
923                                 s->flags |= SAVEDTMP;
924 #ifdef HAS_ADDRESS_REGISTER_FILE
925                         if (IS_ADR_TYPE(s->type)) {
926                                 if (rd->freesavadrtop > 0) {
927                                         s->regoff = rd->freesavadrregs[--rd->freesavadrtop];
928                                         return;
929                                 } else if (rd->savadrreguse > 0) {
930                                         s->regoff = rd->savadrregs[--rd->savadrreguse];
931                                         return;
932                                 }
933                         } else
934 #endif
935                         {
936                                 if (IS_FLT_DBL_TYPE(s->type)) {
937                                         if (rd->freesavflttop > 0) {
938                                                 s->regoff = rd->freesavfltregs[--rd->freesavflttop];
939                                                 return;
940                                         } else if (rd->savfltreguse > 0) {
941                                                 s->regoff = rd->savfltregs[--rd->savfltreguse];
942                                                 return;
943                                         }
944                                 } else {
945 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
946                                         /*
947                                          * for i386 put all longs in memory
948                                          */
949                                         if (!IS_2_WORD_TYPE(s->type))
950 #endif
951                                         {
952                                                 if (rd->freesavinttop > intregsneeded) {
953                                                         rd->freesavinttop -= intregsneeded + 1;
954 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
955                                                         if (intregsneeded)
956                                                                 s->regoff = PACK_REGS(
957                                                                 rd->freesavintregs[rd->freesavinttop],
958                                                                         rd->freesavintregs[rd->freesavinttop + 1]);
959                                                 else
960 #endif
961                                                                 s->regoff =
962                                                                         rd->freesavintregs[rd->freesavinttop];
963                                                         return;
964                                                 } else if (rd->savintreguse > intregsneeded) {
965                                                         rd->savintreguse -= intregsneeded + 1;
966 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
967                                                         if (intregsneeded)
968                                                                 s->regoff = PACK_REGS(
969                                                                         rd->savintregs[rd->savintreguse],
970                                                                 rd->savintregs[rd->savintreguse + 1]);
971                                                         else
972 #endif
973                                                                 s->regoff = rd->savintregs[rd->savintreguse];
974                                                         return;
975                                                 }
976                                         }
977                                 }
978                         }
979                 } else { /* tryagain == 2 */
980 #ifdef HAS_ADDRESS_REGISTER_FILE
981                         if (IS_ADR_TYPE(s->type)) {
982                                 if (rd->freetmpadrtop > 0) {
983                                         s->regoff = rd->freetmpadrregs[--rd->freetmpadrtop];
984                                         return;
985                                 } else if (rd->tmpadrreguse > 0) {
986                                         s->regoff = rd->tmpadrregs[--rd->tmpadrreguse];
987                                         return;
988                                 }
989                         } else
990 #endif
991                         {
992                                 if (IS_FLT_DBL_TYPE(s->type)) {
993                                         if (rd->freeargflttop > 0) {
994                                                 s->regoff = rd->freeargfltregs[--rd->freeargflttop];
995                                                 s->flags |= TMPARG;
996                                                 return;
997                                         } else if (rd->argfltreguse < FLT_ARG_CNT) {
998                                                 s->regoff = rd->argfltregs[rd->argfltreguse++];
999                                                 s->flags |= TMPARG;
1000                                                 return;
1001                                         } else if (rd->freetmpflttop > 0) {
1002                                                 s->regoff = rd->freetmpfltregs[--rd->freetmpflttop];
1003                                                 return;
1004                                         } else if (rd->tmpfltreguse > 0) {
1005                                                 s->regoff = rd->tmpfltregs[--rd->tmpfltreguse];
1006                                                 return;
1007                                         }
1008
1009                                 } else {
1010 #if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1011                                         /*
1012                                          * for i386 put all longs in memory
1013                                          */
1014                                         if (!IS_2_WORD_TYPE(s->type))
1015 #endif
1016                                         {
1017                                                 if (rd->freearginttop > intregsneeded) {
1018                                                         rd->freearginttop -= intregsneeded + 1;
1019                                                         s->flags |= TMPARG;
1020 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1021                                                         if (intregsneeded) 
1022                                                                 s->regoff = PACK_REGS(
1023                                                                         rd->freeargintregs[rd->freearginttop],
1024                                                                 rd->freeargintregs[rd->freearginttop + 1]);
1025                                                         else
1026 #endif
1027                                                                 s->regoff =
1028                                                                         rd->freeargintregs[rd->freearginttop];
1029                                                         return;
1030                                                 } else if (rd->argintreguse 
1031                                                                    < INT_ARG_CNT - intregsneeded) {
1032 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1033                                                         if (intregsneeded) 
1034                                                                 s->regoff = PACK_REGS(
1035                                                                         rd->argintregs[rd->argintreguse],
1036                                                                     rd->argintregs[rd->argintreguse + 1]);
1037                                                         else
1038 #endif
1039                                                                 s->regoff = rd->argintregs[rd->argintreguse];
1040                                                         s->flags |= TMPARG;
1041                                                         rd->argintreguse += intregsneeded + 1;
1042                                                         return;
1043                                                 } else if (rd->freetmpinttop > intregsneeded) {
1044                                                         rd->freetmpinttop -= intregsneeded + 1;
1045 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1046                                                         if (intregsneeded) 
1047                                                                 s->regoff = PACK_REGS(
1048                                                                         rd->freetmpintregs[rd->freetmpinttop],
1049                                                                     rd->freetmpintregs[rd->freetmpinttop + 1]);
1050                                                         else
1051 #endif
1052                                                                 s->regoff = rd->freetmpintregs[rd->freetmpinttop];
1053                                                         return;
1054                                                 } else if (rd->tmpintreguse > intregsneeded) {
1055                                                         rd->tmpintreguse -= intregsneeded + 1;
1056 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1057                                                         if (intregsneeded) 
1058                                                                 s->regoff = PACK_REGS(
1059                                                                         rd->tmpintregs[rd->tmpintreguse],
1060                                                                     rd->tmpintregs[rd->tmpintreguse + 1]);
1061                                                         else
1062 #endif
1063                                                                 s->regoff = rd->tmpintregs[rd->tmpintreguse];
1064                                                         return;
1065                                                 }
1066                                         } /* if (!IS_2_WORD_TYPE(s->type)) */
1067                                 } /* if (IS_FLT_DBL_TYPE(s->type)) */
1068                         } /* if (IS_ADR_TYPE(s->type)) */
1069                 } /* if (tryagain == 1) else */
1070         } /* for(; tryagain; --tryagain) */
1071
1072 #if defined(HAS_4BYTE_STACKSLOT)
1073         if ((memneeded == 1) && (rd->freememtop_2 > 0)) {
1074                 rd->freememtop_2--;
1075                 s->regoff = rd->freemem_2[rd->freememtop_2];
1076         } else
1077 #endif /*defined(HAS_4BYTE_STACKSLOT) */
1078                 if ((memneeded == 0) && (rd->freememtop > 0)) {
1079                         rd->freememtop--;;
1080                         s->regoff = rd->freemem[rd->freememtop];
1081                 } else {
1082 #if defined(HAS_4BYTE_STACKSLOT)
1083                         /* align 2 Word Types */
1084                         if ((memneeded) && ((rd->memuse & 1) == 1)) { 
1085                                 /* Put patched memory slot on freemem */
1086                                 rd->freemem[rd->freememtop++] = rd->memuse;
1087                                 rd->memuse++;
1088                         }
1089 #endif /*defined(HAS_4BYTE_STACKSLOT) */
1090                         s->regoff = rd->memuse;
1091                         rd->memuse += memneeded + 1;
1092                 }
1093         s->flags |= INMEMORY;
1094 }
1095
1096
1097 #define reg_free_temp(rd,s) if (s->varkind == TEMPVAR) reg_free_temp_func(rd, s)
1098
1099 static void reg_free_temp_func(registerdata *rd, stackptr s)
1100 {
1101         s4 intregsneeded;
1102         s4 memneeded;
1103
1104 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1105         intregsneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
1106 #else
1107         intregsneeded = 0;
1108 #endif
1109
1110 #if defined(HAS_4BYTE_STACKSLOT)
1111         memneeded = (IS_2_WORD_TYPE(s->type)) ? 1 : 0;
1112 #else
1113         memneeded = 0;
1114 #endif
1115
1116         if (s->flags & INMEMORY) {
1117 #if defined(HAS_4BYTE_STACKSLOT)
1118                 if (memneeded > 0) {
1119                         rd->freemem_2[rd->freememtop_2] = s->regoff;
1120                         rd->freememtop_2++;
1121                 } else 
1122 #endif
1123                 {
1124                         rd->freemem[rd->freememtop] = s->regoff;
1125                         rd->freememtop++;
1126                 }
1127
1128 #ifdef HAS_ADDRESS_REGISTER_FILE
1129         } else if (IS_ADR_TYPE(s->type)) {
1130                 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1131                         s->flags &= ~SAVEDTMP;
1132                         rd->freesavadrregs[rd->freesavadrtop++] = s->regoff;
1133                 } else
1134                         rd->freetmpadrregs[rd->freetmpadrtop++] = s->regoff;
1135 #endif
1136         } else if (IS_FLT_DBL_TYPE(s->type)) {
1137                 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1138                         s->flags &= ~SAVEDTMP;
1139                         rd->freesavfltregs[rd->freesavflttop++] = s->regoff;
1140                 } else if (s->flags & TMPARG) {
1141                         s->flags &= ~TMPARG;
1142                         rd->freeargfltregs[rd->freeargflttop++] = s->regoff;
1143                 } else
1144                         rd->freetmpfltregs[rd->freetmpflttop++] = s->regoff;
1145         } else { /* IS_INT_LNG_TYPE */
1146                 if (s->flags & (SAVEDVAR | SAVEDTMP)) {
1147                         s->flags &= ~SAVEDTMP;
1148 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1149                         if (intregsneeded) {
1150                                 rd->freesavintregs[rd->freesavinttop] =
1151                                         GET_LOW_REG(s->regoff);
1152                                 rd->freesavintregs[rd->freesavinttop + 1] =
1153                                         GET_HIGH_REG(s->regoff);
1154                         } else
1155 #endif
1156                                 rd->freesavintregs[rd->freesavinttop] = s->regoff;
1157                         rd->freesavinttop += intregsneeded + 1;
1158
1159                 } else if (s->flags & TMPARG) {
1160                         s->flags &= ~TMPARG;
1161 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1162                         if (intregsneeded) {
1163                                 rd->freeargintregs[rd->freearginttop] =
1164                                         GET_LOW_REG(s->regoff);
1165                                 rd->freeargintregs[rd->freearginttop + 1] =
1166                                         GET_HIGH_REG(s->regoff);
1167                         } else 
1168 #endif
1169                                 rd->freeargintregs[rd->freearginttop] = s->regoff;
1170                         rd->freearginttop += intregsneeded + 1;
1171                 } else {
1172 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
1173                         if (intregsneeded) {
1174                                 rd->freetmpintregs[rd->freetmpinttop] =
1175                                         GET_LOW_REG(s->regoff);
1176                                 rd->freetmpintregs[rd->freetmpinttop + 1] =
1177                                         GET_HIGH_REG(s->regoff);
1178                         } else
1179 #endif
1180                                 rd->freetmpintregs[rd->freetmpinttop] = s->regoff;
1181                         rd->freetmpinttop += intregsneeded + 1;
1182                 }
1183         }
1184 }
1185
1186
1187
1188 static void allocate_scratch_registers(methodinfo *m, registerdata *rd)
1189 {
1190         s4                  opcode;
1191         s4                  i;
1192         s4                  len;
1193         stackptr            src;
1194         stackptr            dst;
1195         instruction        *iptr;
1196         basicblock         *bptr;
1197         methodinfo         *lm;
1198         builtintable_entry *bte;
1199         methoddesc         *md;
1200
1201         /* initialize temp registers */
1202         reg_init_temp(m, rd);
1203
1204         bptr = m->basicblocks;
1205
1206         while (bptr != NULL) {
1207                 if (bptr->flags >= BBREACHED) {
1208                         dst = bptr->instack;
1209
1210
1211                         iptr = bptr->iinstr;
1212                         len = bptr->icount;
1213
1214                         while (--len >= 0)  {
1215                                 src = dst;
1216                                 dst = iptr->dst;
1217                                 opcode = iptr->opc;
1218
1219                                 switch (opcode) {
1220
1221                                         /* pop 0 push 0 */
1222
1223                                 case ICMD_NOP:
1224                                 case ICMD_ELSE_ICONST:
1225                                 case ICMD_CHECKNULL:
1226                                 case ICMD_IINC:
1227                                 case ICMD_JSR:
1228                                 case ICMD_RET:
1229                                 case ICMD_RETURN:
1230                                 case ICMD_GOTO:
1231                                 case ICMD_PUTSTATICCONST:
1232                                 case ICMD_INLINE_START:
1233                                 case ICMD_INLINE_END:
1234                                         break;
1235
1236                                         /* pop 0 push 1 const */
1237                                         
1238                                 case ICMD_ICONST:
1239                                 case ICMD_LCONST:
1240                                 case ICMD_FCONST:
1241                                 case ICMD_DCONST:
1242                                 case ICMD_ACONST:
1243
1244                                         /* pop 0 push 1 load */
1245                                         
1246                                 case ICMD_ILOAD:
1247                                 case ICMD_LLOAD:
1248                                 case ICMD_FLOAD:
1249                                 case ICMD_DLOAD:
1250                                 case ICMD_ALOAD:
1251                                         reg_new_temp(rd, dst);
1252                                         break;
1253
1254                                         /* pop 2 push 1 */
1255
1256                                 case ICMD_IALOAD:
1257                                 case ICMD_LALOAD:
1258                                 case ICMD_FALOAD:
1259                                 case ICMD_DALOAD:
1260                                 case ICMD_AALOAD:
1261
1262                                 case ICMD_BALOAD:
1263                                 case ICMD_CALOAD:
1264                                 case ICMD_SALOAD:
1265                                         reg_free_temp(rd, src);
1266                                         reg_free_temp(rd, src->prev);
1267                                         reg_new_temp(rd, dst);
1268                                         break;
1269
1270                                         /* pop 3 push 0 */
1271
1272                                 case ICMD_IASTORE:
1273                                 case ICMD_LASTORE:
1274                                 case ICMD_FASTORE:
1275                                 case ICMD_DASTORE:
1276                                 case ICMD_AASTORE:
1277
1278                                 case ICMD_BASTORE:
1279                                 case ICMD_CASTORE:
1280                                 case ICMD_SASTORE:
1281                                         reg_free_temp(rd, src);
1282                                         reg_free_temp(rd, src->prev);
1283                                         reg_free_temp(rd, src->prev->prev);
1284                                         break;
1285
1286                                         /* pop 1 push 0 store */
1287
1288                                 case ICMD_ISTORE:
1289                                 case ICMD_LSTORE:
1290                                 case ICMD_FSTORE:
1291                                 case ICMD_DSTORE:
1292                                 case ICMD_ASTORE:
1293
1294                                         /* pop 1 push 0 */
1295
1296                                 case ICMD_POP:
1297
1298                                 case ICMD_IRETURN:
1299                                 case ICMD_LRETURN:
1300                                 case ICMD_FRETURN:
1301                                 case ICMD_DRETURN:
1302                                 case ICMD_ARETURN:
1303
1304                                 case ICMD_ATHROW:
1305
1306                                 case ICMD_PUTSTATIC:
1307                                 case ICMD_PUTFIELDCONST:
1308
1309                                         /* pop 1 push 0 branch */
1310
1311                                 case ICMD_IFNULL:
1312                                 case ICMD_IFNONNULL:
1313
1314                                 case ICMD_IFEQ:
1315                                 case ICMD_IFNE:
1316                                 case ICMD_IFLT:
1317                                 case ICMD_IFGE:
1318                                 case ICMD_IFGT:
1319                                 case ICMD_IFLE:
1320
1321                                 case ICMD_IF_LEQ:
1322                                 case ICMD_IF_LNE:
1323                                 case ICMD_IF_LLT:
1324                                 case ICMD_IF_LGE:
1325                                 case ICMD_IF_LGT:
1326                                 case ICMD_IF_LLE:
1327
1328                                         /* pop 1 push 0 table branch */
1329
1330                                 case ICMD_TABLESWITCH:
1331                                 case ICMD_LOOKUPSWITCH:
1332
1333                                 case ICMD_MONITORENTER:
1334                                 case ICMD_MONITOREXIT:
1335                                         reg_free_temp(rd, src);
1336                                         break;
1337
1338                                         /* pop 2 push 0 branch */
1339
1340                                 case ICMD_IF_ICMPEQ:
1341                                 case ICMD_IF_ICMPNE:
1342                                 case ICMD_IF_ICMPLT:
1343                                 case ICMD_IF_ICMPGE:
1344                                 case ICMD_IF_ICMPGT:
1345                                 case ICMD_IF_ICMPLE:
1346
1347                                 case ICMD_IF_LCMPEQ:
1348                                 case ICMD_IF_LCMPNE:
1349                                 case ICMD_IF_LCMPLT:
1350                                 case ICMD_IF_LCMPGE:
1351                                 case ICMD_IF_LCMPGT:
1352                                 case ICMD_IF_LCMPLE:
1353
1354                                 case ICMD_IF_ACMPEQ:
1355                                 case ICMD_IF_ACMPNE:
1356
1357                                         /* pop 2 push 0 */
1358
1359                                 case ICMD_POP2:
1360
1361                                 case ICMD_PUTFIELD:
1362
1363                                 case ICMD_IASTORECONST:
1364                                 case ICMD_LASTORECONST:
1365                                 case ICMD_AASTORECONST:
1366                                 case ICMD_BASTORECONST:
1367                                 case ICMD_CASTORECONST:
1368                                 case ICMD_SASTORECONST:
1369                                         reg_free_temp(rd, src);
1370                                         reg_free_temp(rd, src->prev);
1371                                         break;
1372
1373                                         /* pop 0 push 1 dup */
1374                                         
1375                                 case ICMD_DUP:
1376                                         reg_new_temp(rd, dst);
1377                                         break;
1378
1379                                         /* pop 0 push 2 dup */
1380                                         
1381                                 case ICMD_DUP2:
1382                                         reg_new_temp(rd, dst->prev);
1383                                         reg_new_temp(rd, dst);
1384                                         break;
1385
1386                                         /* pop 2 push 3 dup */
1387                                         
1388                                 case ICMD_DUP_X1:
1389                                         reg_free_temp(rd, src);
1390                                         reg_new_temp(rd, dst);
1391                                         reg_free_temp(rd, src->prev);
1392                                         reg_new_temp(rd, dst->prev);
1393                                         reg_new_temp(rd, dst->prev->prev);
1394                                         break;
1395
1396                                         /* pop 3 push 4 dup */
1397                                         
1398                                 case ICMD_DUP_X2:
1399                                         reg_free_temp(rd, src);
1400                                         reg_new_temp(rd, dst);
1401                                         reg_free_temp(rd, src->prev);
1402                                         reg_new_temp(rd, dst->prev);
1403                                         reg_free_temp(rd, src->prev->prev);
1404                                         reg_new_temp(rd, dst->prev->prev);
1405                                         reg_new_temp(rd, dst->prev->prev->prev);
1406                                         break;
1407
1408                                         /* pop 3 push 5 dup */
1409                                         
1410                                 case ICMD_DUP2_X1:
1411                                         reg_free_temp(rd, src);
1412                                         reg_new_temp(rd, dst);
1413                                         reg_free_temp(rd, src->prev);
1414                                         reg_new_temp(rd, dst->prev);
1415                                         reg_free_temp(rd, src->prev->prev);
1416                                         reg_new_temp(rd, dst->prev->prev);
1417                                         reg_new_temp(rd, dst->prev->prev->prev);
1418                                         reg_new_temp(rd, dst->prev->prev->prev->prev);
1419                                         break;
1420
1421                                         /* pop 4 push 6 dup */
1422                                         
1423                                 case ICMD_DUP2_X2:
1424                                         reg_free_temp(rd, src);
1425                                         reg_new_temp(rd, dst);
1426                                         reg_free_temp(rd, src->prev);
1427                                         reg_new_temp(rd, dst->prev);
1428                                         reg_free_temp(rd, src->prev->prev);
1429                                         reg_new_temp(rd, dst->prev->prev);
1430                                         reg_free_temp(rd, src->prev->prev->prev);
1431                                         reg_new_temp(rd, dst->prev->prev->prev);
1432                                         reg_new_temp(rd, dst->prev->prev->prev->prev);
1433                                         reg_new_temp(rd, dst->prev->prev->prev->prev->prev);
1434                                         break;
1435
1436                                         /* pop 2 push 2 swap */
1437                                         
1438                                 case ICMD_SWAP:
1439                                         reg_free_temp(rd, src);
1440                                         reg_new_temp(rd, dst->prev);
1441                                         reg_free_temp(rd, src->prev);
1442                                         reg_new_temp(rd, dst);
1443                                         break;
1444
1445                                         /* pop 2 push 1 */
1446                                         
1447                                 case ICMD_IADD:
1448                                 case ICMD_ISUB:
1449                                 case ICMD_IMUL:
1450                                 case ICMD_IDIV:
1451                                 case ICMD_IREM:
1452
1453                                 case ICMD_ISHL:
1454                                 case ICMD_ISHR:
1455                                 case ICMD_IUSHR:
1456                                 case ICMD_IAND:
1457                                 case ICMD_IOR:
1458                                 case ICMD_IXOR:
1459
1460                                 case ICMD_LADD:
1461                                 case ICMD_LSUB:
1462                                 case ICMD_LMUL:
1463                                 case ICMD_LDIV:
1464                                 case ICMD_LREM:
1465
1466                                 case ICMD_LOR:
1467                                 case ICMD_LAND:
1468                                 case ICMD_LXOR:
1469
1470                                 case ICMD_LSHL:
1471                                 case ICMD_LSHR:
1472                                 case ICMD_LUSHR:
1473
1474                                 case ICMD_FADD:
1475                                 case ICMD_FSUB:
1476                                 case ICMD_FMUL:
1477                                 case ICMD_FDIV:
1478                                 case ICMD_FREM:
1479
1480                                 case ICMD_DADD:
1481                                 case ICMD_DSUB:
1482                                 case ICMD_DMUL:
1483                                 case ICMD_DDIV:
1484                                 case ICMD_DREM:
1485
1486                                 case ICMD_LCMP:
1487                                 case ICMD_FCMPL:
1488                                 case ICMD_FCMPG:
1489                                 case ICMD_DCMPL:
1490                                 case ICMD_DCMPG:
1491                                         reg_free_temp(rd, src);
1492                                         reg_free_temp(rd, src->prev);
1493                                         reg_new_temp(rd, dst);
1494                                         break;
1495
1496                                         /* pop 1 push 1 */
1497                                         
1498                                 case ICMD_IADDCONST:
1499                                 case ICMD_ISUBCONST:
1500                                 case ICMD_IMULCONST:
1501                                 case ICMD_IMULPOW2:
1502                                 case ICMD_IDIVPOW2:
1503                                 case ICMD_IREMPOW2:
1504                                 case ICMD_IANDCONST:
1505                                 case ICMD_IORCONST:
1506                                 case ICMD_IXORCONST:
1507                                 case ICMD_ISHLCONST:
1508                                 case ICMD_ISHRCONST:
1509                                 case ICMD_IUSHRCONST:
1510
1511                                 case ICMD_LADDCONST:
1512                                 case ICMD_LSUBCONST:
1513                                 case ICMD_LMULCONST:
1514                                 case ICMD_LMULPOW2:
1515                                 case ICMD_LDIVPOW2:
1516                                 case ICMD_LREMPOW2:
1517                                 case ICMD_LANDCONST:
1518                                 case ICMD_LORCONST:
1519                                 case ICMD_LXORCONST:
1520                                 case ICMD_LSHLCONST:
1521                                 case ICMD_LSHRCONST:
1522                                 case ICMD_LUSHRCONST:
1523
1524                                 case ICMD_IFEQ_ICONST:
1525                                 case ICMD_IFNE_ICONST:
1526                                 case ICMD_IFLT_ICONST:
1527                                 case ICMD_IFGE_ICONST:
1528                                 case ICMD_IFGT_ICONST:
1529                                 case ICMD_IFLE_ICONST:
1530
1531                                 case ICMD_INEG:
1532                                 case ICMD_INT2BYTE:
1533                                 case ICMD_INT2CHAR:
1534                                 case ICMD_INT2SHORT:
1535                                 case ICMD_LNEG:
1536                                 case ICMD_FNEG:
1537                                 case ICMD_DNEG:
1538
1539                                 case ICMD_I2L:
1540                                 case ICMD_I2F:
1541                                 case ICMD_I2D:
1542                                 case ICMD_L2I:
1543                                 case ICMD_L2F:
1544                                 case ICMD_L2D:
1545                                 case ICMD_F2I:
1546                                 case ICMD_F2L:
1547                                 case ICMD_F2D:
1548                                 case ICMD_D2I:
1549                                 case ICMD_D2L:
1550                                 case ICMD_D2F:
1551
1552                                 case ICMD_CHECKCAST:
1553
1554                                 case ICMD_ARRAYLENGTH:
1555                                 case ICMD_INSTANCEOF:
1556
1557                                 case ICMD_NEWARRAY:
1558                                 case ICMD_ANEWARRAY:
1559
1560                                 case ICMD_GETFIELD:
1561                                         reg_free_temp(rd, src);
1562                                         reg_new_temp(rd, dst);
1563                                         break;
1564
1565                                         /* pop 0 push 1 */
1566                                         
1567                                 case ICMD_GETSTATIC:
1568
1569                                 case ICMD_NEW:
1570                                         reg_new_temp(rd, dst);
1571                                         break;
1572
1573                                         /* pop many push any */
1574                                         
1575                                 case ICMD_INVOKESTATIC:
1576                                 case ICMD_INVOKESPECIAL:
1577                                 case ICMD_INVOKEVIRTUAL:
1578                                 case ICMD_INVOKEINTERFACE:
1579                                         lm = iptr->val.a;
1580
1581                                         if (lm)
1582                                                 md = lm->parseddesc;
1583                                         else {
1584                                                 unresolved_method *um = iptr->target;
1585                                                 md = um->methodref->parseddesc.md;
1586                                         }
1587                                         i = md->paramcount;
1588                                         while (--i >= 0) {
1589                                                 reg_free_temp(rd, src);
1590                                                 src = src->prev;
1591                                         }
1592                                         if (md->returntype.type != TYPE_VOID)
1593                                                 reg_new_temp(rd, dst);
1594                                         break;
1595
1596                                 case ICMD_BUILTIN:
1597                                         bte = iptr->val.a;
1598                                         md = bte->md;
1599                                         i = md->paramcount;
1600                                         while (--i >= 0) {
1601                                                 reg_free_temp(rd, src);
1602                                                 src = src->prev;
1603                                         }
1604                                         if (md->returntype.type != TYPE_VOID)
1605                                                 reg_new_temp(rd, dst);
1606                                         break;
1607
1608                                 case ICMD_MULTIANEWARRAY:
1609                                         i = iptr->op1;
1610                                         while (--i >= 0) {
1611                                                 reg_free_temp(rd, src);
1612                                                 src = src->prev;
1613                                         }
1614                                         reg_new_temp(rd, dst);
1615                                         break;
1616
1617                                 default:
1618                                         throw_cacao_exception_exit(string_java_lang_InternalError,
1619                                                                                            "Unknown ICMD %d during register allocation",
1620                                                                                            iptr->opc);
1621                                 } /* switch */
1622                                 iptr++;
1623                         } /* while instructions */
1624                 } /* if */
1625                 bptr = bptr->next;
1626         } /* while blocks */
1627 }
1628
1629
1630 #ifdef STATISTICS
1631 void reg_make_statistics( methodinfo *m, codegendata *cd, registerdata *rd) {
1632         int i,type;
1633         s4 len;
1634         stackptr    src, src_old;
1635         stackptr    dst;
1636         instruction *iptr;
1637         basicblock  *bptr;
1638         int size_interface; /* == maximum size of in/out stack at basic block boundaries */
1639         bool in_register;
1640
1641         in_register = true;
1642
1643         size_interface = 0;
1644
1645                 /* count how many local variables are held in memory or register */
1646                 for(i=0; i < cd->maxlocals; i++)
1647                         for (type=0; type <=4; type++)
1648                                 if (rd->locals[i][type].type != -1) { /* valid local */
1649                                         if (rd->locals[i][type].flags & INMEMORY) {
1650                                                 count_locals_spilled++;
1651                                                 in_register=false;
1652                                         }
1653                                         else
1654                                                 count_locals_register++;
1655                                 }
1656                 /* count how many stack slots are held in memory or register */
1657
1658                 bptr = m->basicblocks;
1659                 while (bptr != NULL) {
1660                         if (bptr->flags >= BBREACHED) {
1661
1662 #if defined(ENABLE_LSRA)
1663                         if (!opt_lsra) {
1664 #endif  
1665                                 /* check for memory moves from interface to BB instack */
1666                                 dst = bptr->instack;
1667                                 len = bptr->indepth;
1668                                 
1669                                 if (len > size_interface) size_interface = len;
1670
1671                                 while (dst != NULL) {
1672                                         len--;
1673                                         if (dst->varkind != STACKVAR) {
1674                                                 if ( (dst->flags & INMEMORY) ||
1675                                                          (rd->interfaces[len][dst->type].flags & INMEMORY) || 
1676                                                          ( (dst->flags & INMEMORY) && 
1677                                                            (rd->interfaces[len][dst->type].flags & INMEMORY) && 
1678                                                            (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1679                                                 {
1680                                                         /* one in memory or both inmemory at different offsets */
1681                                                         count_mem_move_bb++;
1682                                                         in_register=false;
1683                                                 }
1684                                         }
1685
1686                                         dst = dst->prev;
1687                                 }
1688
1689                                 /* check for memory moves from BB outstack to interface */
1690                                 dst = bptr->outstack;
1691                                 len = bptr->outdepth;
1692                                 if (len > size_interface) size_interface = len;
1693
1694                                 while (dst) {
1695                                         len--;
1696                                         if (dst->varkind != STACKVAR) {
1697                                                 if ( (dst->flags & INMEMORY) || \
1698                                                          (rd->interfaces[len][dst->type].flags & INMEMORY) || \
1699                                                          ( (dst->flags & INMEMORY) && \
1700                                                            (rd->interfaces[len][dst->type].flags & INMEMORY) && \
1701                                                            (dst->regoff != rd->interfaces[len][dst->type].regoff) ))
1702                                                 {
1703                                                         /* one in memory or both inmemory at different offsets */
1704                                                         count_mem_move_bb++;
1705                                                         in_register=false;
1706                                                 }
1707                                         }
1708
1709                                         dst = dst->prev;
1710                                 }
1711 #if defined(ENABLE_LSRA)
1712                         }
1713 #endif  
1714
1715
1716                                 dst = bptr->instack;
1717                                 iptr = bptr->iinstr;
1718                                 len = bptr->icount;
1719                                 src_old = NULL;
1720
1721                                 while (--len >= 0)  {
1722                                         src = dst;
1723                                         dst = iptr->dst;
1724
1725                                         if ((src!= NULL) && (src != src_old)) { /* new stackslot */
1726                                                 switch (src->varkind) {
1727                                                 case TEMPVAR:
1728                                                 case STACKVAR:
1729                                                         if (!(src->flags & INMEMORY)) 
1730                                                                 count_ss_register++;
1731                                                         else {
1732                                                                 count_ss_spilled++;
1733                                                                 in_register=false;
1734                                                         }                               
1735                                                         break;
1736                                                         /*                                      case LOCALVAR: */
1737                                                         /*                                              if (!(rd->locals[src->varnum][src->type].flags & INMEMORY)) */
1738                                                         /*                                                      count_ss_register++; */
1739                                                         /*                                              else */
1740                                                         /*                                                      count_ss_spilled++; */
1741                                                         /*                                              break; */
1742                                                 case ARGVAR:
1743                                                         if (!(src->flags & INMEMORY)) 
1744                                                                 count_argument_mem_ss++;
1745                                                         else
1746                                                                 count_argument_reg_ss++;
1747                                                         break;
1748
1749
1750                                                         /*                                              if (IS_FLT_DBL_TYPE(src->type)) { */
1751                                                         /*                                                      if (src->varnum < FLT_ARG_CNT) { */
1752                                                         /*                                                              count_ss_register++; */
1753                                                         /*                                                              break; */
1754                                                         /*                                                      } */
1755                                                         /*                                              } else { */
1756                                                         /* #if defined(__POWERPC__) */
1757                                                         /*                                                      if (src->varnum < INT_ARG_CNT - (IS_2_WORD_TYPE(src->type) != 0)) { */
1758                                                         /* #else */
1759                                                         /*                                                      if (src->varnum < INT_ARG_CNT) { */
1760                                                         /* #endif */
1761                                                         /*                                                              count_ss_register++; */
1762                                                         /*                                                              break; */
1763                                                         /*                                                      } */
1764                                                         /*                                              } */
1765                                                         /*                                              count_ss_spilled++; */
1766                                                         /*                                              break; */
1767                                                 }
1768                                         }
1769                                         src_old = src;
1770                                         
1771                                         iptr++;
1772                                 } /* while instructions */
1773                         } /* if */
1774                         bptr = bptr->next;
1775                 } /* while blocks */
1776                 count_interface_size += size_interface; /* accummulate the size of the interface (between bb boundaries) */
1777                 if (in_register) count_method_in_register++;
1778 }
1779 #endif
1780 /*
1781  * These are local overrides for various environment variables in Emacs.
1782  * Please do not remove this and leave it at the end of the file, where
1783  * Emacs will automagically detect them.
1784  * ---------------------------------------------------------------------
1785  * Local variables:
1786  * mode: c
1787  * indent-tabs-mode: t
1788  * c-basic-offset: 4
1789  * tab-width: 4
1790  * End:
1791  */