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