* createnativestub: Renamed _exceptionptr to _no_threads_exceptionptr.
[cacao.git] / src / vm / jit / powerpc / codegen.c
1 /* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC
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             Stefan Ring
29
30    Changes: Christian Thalinger
31             Christian Ullrich
32
33    $Id: codegen.c 3578 2005-11-05 16:31:41Z twisti $
34
35 */
36
37
38 #include <assert.h>
39 #include <stdio.h>
40 #include <signal.h>
41
42 #include "config.h"
43 #include "vm/types.h"
44
45 #include "md-abi.h"
46 #include "md-abi.inc"
47
48 #include "vm/jit/powerpc/arch.h"
49 #include "vm/jit/powerpc/codegen.h"
50
51 #include "cacao/cacao.h"
52 #include "native/native.h"
53 #include "vm/builtin.h"
54 #include "vm/global.h"
55 #include "vm/loader.h"
56 #include "vm/stringlocal.h"
57 #include "vm/tables.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/codegen.inc"
60 #include "vm/jit/jit.h"
61
62 #if defined(LSRA)
63 # include "vm/jit/lsra.inc"
64 #endif
65
66 #include "vm/jit/parse.h"
67 #include "vm/jit/patcher.h"
68 #include "vm/jit/reg.h"
69 #include "vm/jit/reg.inc"
70
71
72 s4 *codegen_trace_args( methodinfo *m, codegendata *cd, registerdata *rd,
73                                                 s4 *mcodeptr, s4 parentargs_base, bool nativestub);
74
75 /* codegen *********************************************************************
76
77    Generates machine code.
78
79 *******************************************************************************/
80
81 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
82 {
83         s4                  len, s1, s2, s3, d, disp;
84         ptrint              a;
85         s4                  parentargs_base;
86         s4                 *mcodeptr;
87         stackptr            src;
88         varinfo            *var;
89         basicblock         *bptr;
90         instruction        *iptr;
91         exceptiontable     *ex;
92         u2                  currentline;
93         methodinfo         *lm;             /* local methodinfo for ICMD_INVOKE*  */
94         builtintable_entry *bte;
95         methoddesc         *md;
96
97         /* prevent compiler warnings */
98
99         d = 0;
100         lm = NULL;
101         bte = NULL;
102
103         {
104         s4 i, p, t, l;
105         s4 savedregs_num;
106
107         savedregs_num = 0;
108
109         /* space to save used callee saved registers */
110
111         savedregs_num += (INT_SAV_CNT - rd->savintreguse);
112         savedregs_num += 2 * (FLT_SAV_CNT - rd->savfltreguse);
113
114         parentargs_base = rd->memuse + savedregs_num;
115
116 #if defined(USE_THREADS)
117         /* space to save argument of monitor_enter and Return Values to survive */
118     /* monitor_exit. The stack position for the argument can not be shared  */
119         /* with place to save the return register on PPC, since both values     */
120         /* reside in R3 */
121         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
122                 /* reserve 2 slots for long/double return values for monitorexit */
123
124                 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
125                         parentargs_base += 3;
126                 else
127                         parentargs_base += 2;
128         }
129
130 #endif
131
132         /* create method header */
133
134         parentargs_base = (parentargs_base + 3) & ~3;
135
136         (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
137         (void) dseg_adds4(cd, parentargs_base * 4);             /* FrameSize      */
138
139 #if defined(USE_THREADS)
140         /* IsSync contains the offset relative to the stack pointer for the
141            argument of monitor_exit used in the exception handler. Since the
142            offset could be zero and give a wrong meaning of the flag it is
143            offset by one.
144         */
145
146         if (checksync && (m->flags & ACC_SYNCHRONIZED))
147                 (void) dseg_adds4(cd, (rd->memuse + 1) * 4);        /* IsSync         */
148         else
149 #endif
150                 (void) dseg_adds4(cd, 0);                           /* IsSync         */
151                                                
152         (void) dseg_adds4(cd, m->isleafmethod);                 /* IsLeaf         */
153         (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse);  /* IntSave        */
154         (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse);  /* FltSave        */
155
156         dseg_addlinenumbertablesize(cd);
157
158         (void) dseg_adds4(cd, cd->exceptiontablelength);        /* ExTableSize    */
159
160         /* create exception table */
161
162         for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
163                 dseg_addtarget(cd, ex->start);
164                 dseg_addtarget(cd, ex->end);
165                 dseg_addtarget(cd, ex->handler);
166                 (void) dseg_addaddress(cd, ex->catchtype.cls);
167         }
168         
169         /* initialize mcode variables */
170         
171         mcodeptr = (s4 *) cd->mcodebase;
172         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
173         MCODECHECK(128 + m->paramcount);
174
175         /* create stack frame (if necessary) */
176
177         if (!m->isleafmethod) {
178                 M_MFLR(REG_ZERO);
179                 M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
180         }
181
182         if (parentargs_base) {
183                 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
184         }
185
186         /* save return address and used callee saved registers */
187
188         p = parentargs_base;
189         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
190                 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
191         }
192         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
193                 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
194         }
195
196         /* take arguments out of register or stack frame */
197
198         md = m->parseddesc;
199
200         for (p = 0, l = 0; p < md->paramcount; p++) {
201                 t = md->paramtypes[p].type;
202                 var = &(rd->locals[l][t]);
203                 l++;
204                 if (IS_2_WORD_TYPE(t))    /* increment local counter for 2 word types */
205                         l++;
206                 if (var->type < 0)
207                         continue;
208                 s1 = md->params[p].regoff;
209                 if (IS_INT_LNG_TYPE(t)) {                    /* integer args          */
210                         if (IS_2_WORD_TYPE(t))
211                                 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
212                                                            rd->argintregs[GET_HIGH_REG(s1)]);
213                         else
214                                 s2 = rd->argintregs[s1];
215                         if (!md->params[p].inmemory) {           /* register arguments    */
216                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
217                                         M_TINTMOVE(t, s2, var->regoff);
218
219                                 } else {                             /* reg arg -> spilled    */
220                                         if (IS_2_WORD_TYPE(t)) {
221                                                 M_IST(GET_HIGH_REG(s2), REG_SP, var->regoff * 4);
222                                                 M_IST(GET_LOW_REG(s2), REG_SP, var->regoff * 4 + 4);
223                                         } else {
224                                                 M_IST(s2, REG_SP, var->regoff * 4);
225                                         }
226                                 }
227
228                         } else {                                 /* stack arguments       */
229                                 if (!(var->flags & INMEMORY)) {      /* stack arg -> register */
230                                         if (IS_2_WORD_TYPE(t)) {
231                                                 M_ILD(GET_HIGH_REG(var->regoff), REG_SP,
232                                                           (parentargs_base + s1) * 4);
233                                                 M_ILD(GET_LOW_REG(var->regoff), REG_SP,
234                                                           (parentargs_base + s1) * 4 + 4);
235                                         } else {
236                                                 M_ILD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
237                                         }
238
239                                 } else {                             /* stack arg -> spilled  */
240 #if 1
241                                         M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4);
242                                         M_IST(REG_ITMP1, REG_SP, var->regoff * 4);
243                                         if (IS_2_WORD_TYPE(t)) {
244                                                 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4 +4);
245                                                 M_IST(REG_ITMP1, REG_SP, var->regoff * 4 + 4);
246                                         }
247 #else
248                                         /* Reuse Memory Position on Caller Stack */
249                                         var->regoff = parentargs_base + s1;
250 #endif
251                                 }
252                         }
253
254                 } else {                                     /* floating args         */
255                         if (!md->params[p].inmemory) {           /* register arguments    */
256                                 s2 = rd->argfltregs[s1];
257                                 if (!(var->flags & INMEMORY)) {      /* reg arg -> register   */
258                                         M_FLTMOVE(s2, var->regoff);
259
260                                 } else {                                         /* reg arg -> spilled    */
261                                         if (IS_2_WORD_TYPE(t))
262                                                 M_DST(s2, REG_SP, var->regoff * 4);
263                                         else
264                                                 M_FST(s2, REG_SP, var->regoff * 4);
265                                 }
266
267                         } else {                                 /* stack arguments       */
268                                 if (!(var->flags & INMEMORY)) {      /* stack-arg -> register */
269                                         if (IS_2_WORD_TYPE(t))
270                                                 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
271
272                                         else
273                                                 M_FLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
274
275                                 } else {                             /* stack-arg -> spilled  */
276 #if 1
277                                         if (IS_2_WORD_TYPE(t)) {
278                                                 M_DLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
279                                                 M_DST(REG_FTMP1, REG_SP, var->regoff * 4);
280                                                 var->regoff = parentargs_base + s1;
281
282                                         } else {
283                                                 M_FLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
284                                                 M_FST(REG_FTMP1, REG_SP, var->regoff * 4);
285                                         }
286 #else
287                                         /* Reuse Memory Position on Caller Stack */
288                                         var->regoff = parentargs_base + s1;
289 #endif
290                                 }
291                         }
292                 }
293         } /* end for */
294
295         /* save monitorenter argument */
296
297 #if defined(USE_THREADS)
298         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
299                 /* stack offset for monitor argument */
300
301                 s1 = rd->memuse;
302
303 #if 0
304                 if (runverbose) {
305                         M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT * 4 + FLT_ARG_CNT * 8));
306
307                         for (p = 0; p < INT_ARG_CNT; p++)
308                                 M_IST(rd->argintregs[p], REG_SP, p * 4);
309
310                         for (p = 0; p < FLT_ARG_CNT * 2; p += 2)
311                                 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
312
313                         s1 += INT_ARG_CNT + FLT_ARG_CNT;
314                 }
315 #endif
316
317                 /* decide which monitor enter function to call */
318
319                 if (m->flags & ACC_STATIC) {
320                         p = dseg_addaddress(cd, m->class);
321                         M_ALD(REG_ITMP1, REG_PV, p);
322                         M_AST(REG_ITMP1, REG_SP, s1 * 4);
323                         M_MOV(REG_ITMP1, rd->argintregs[0]);
324                         p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
325                         M_ALD(REG_ITMP3, REG_PV, p);
326                         M_MTCTR(REG_ITMP3);
327                         M_JSR;
328
329                 } else {
330                         M_TST(rd->argintregs[0]);
331                         M_BEQ(0);
332                         codegen_addxnullrefs(cd, mcodeptr);
333                         M_AST(rd->argintregs[0], REG_SP, s1 * 4);
334                         p = dseg_addaddress(cd, BUILTIN_monitorenter);
335                         M_ALD(REG_ITMP3, REG_PV, p);
336                         M_MTCTR(REG_ITMP3);
337                         M_JSR;
338                 }
339
340 #if 0
341                 if (runverbose) {
342                         for (p = 0; p < INT_ARG_CNT; p++)
343                                 M_ILD(rd->argintregs[p], REG_SP, p * 4);
344
345                         for (p = 0; p < FLT_ARG_CNT; p++)
346                                 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
347
348
349                         M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
350                 }
351 #endif
352         }
353 #endif
354
355         /* call trace function */
356
357         if (runverbose) {
358                 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, parentargs_base, false);
359
360         } /* if (runverbose) */
361         }
362
363         /* end of header generation */
364
365         /* walk through all basic blocks */
366         for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
367
368                 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
369
370                 if (bptr->flags >= BBREACHED) {
371
372                 /* branch resolving */
373
374                 {
375                 branchref *brefs;
376                 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
377                         gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos, 
378                                           brefs->branchpos,
379                                                           bptr->mpc);
380                         }
381                 }
382
383                 /* copy interface registers to their destination */
384
385                 src = bptr->instack;
386                 len = bptr->indepth;
387                 MCODECHECK(64+len);
388
389 #ifdef LSRA
390                 if (opt_lsra) {
391                         while (src != NULL) {
392                                 len--;
393                                 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
394                                         /* d = reg_of_var(m, src, REG_ITMP1); */
395                                         if (!(src->flags & INMEMORY))
396                                                 d= src->regoff;
397                                         else
398                                                 d=REG_ITMP1;
399                                         M_INTMOVE(REG_ITMP1, d);
400                                         store_reg_to_var_int(src, d);
401                                 }
402                                 src = src->prev;
403                         }
404                 } else {
405 #endif
406                 while (src != NULL) {
407                         len--;
408                         if ((len == 0) && (bptr->type != BBTYPE_STD)) {
409                                 d = reg_of_var(rd, src, REG_ITMP1);
410                                 M_INTMOVE(REG_ITMP1, d);
411                                 store_reg_to_var_int(src, d);
412                         } else {
413                                 if (src->type == TYPE_LNG)
414                                         d = reg_of_var(rd, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
415                                 else
416                                         d = reg_of_var(rd, src, REG_IFTMP);
417                                 if ((src->varkind != STACKVAR)) {
418                                         s2 = src->type;
419                                         if (IS_FLT_DBL_TYPE(s2)) {
420                                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
421                                                         s1 = rd->interfaces[len][s2].regoff;
422                                                         M_FLTMOVE(s1,d);
423                                                 } else {
424                                                         if (IS_2_WORD_TYPE(s2)) {
425                                                                 M_DLD(d, REG_SP,
426                                                                           4 * rd->interfaces[len][s2].regoff);
427                                                         } else {
428                                                                 M_FLD(d, REG_SP,
429                                                                           4 * rd->interfaces[len][s2].regoff);
430                                                         }       
431                                                 }
432                                                 store_reg_to_var_flt(src, d);
433                                         } else {
434                                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
435                                                         s1 = rd->interfaces[len][s2].regoff;
436                                                         M_TINTMOVE(s2,s1,d);
437                                                 } else {
438                                                         if (IS_2_WORD_TYPE(s2)) {
439                                                                 M_ILD(GET_HIGH_REG(d), REG_SP,
440                                                                           4 * rd->interfaces[len][s2].regoff);
441                                                                 M_ILD(GET_LOW_REG(d), REG_SP,
442                                                                           4 * rd->interfaces[len][s2].regoff + 4);
443                                                         } else {
444                                                                 M_ILD(d, REG_SP,
445                                                                           4 * rd->interfaces[len][s2].regoff);
446                                                         }
447                                                 }
448                                                 store_reg_to_var_int(src, d);
449                                         }
450                                 }
451                         }
452                         src = src->prev;
453                 }
454
455 #ifdef LSRA
456                 }
457 #endif
458                 /* walk through all instructions */
459                 
460                 src = bptr->instack;
461                 len = bptr->icount;
462                 currentline = 0;
463
464                 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
465                         if (iptr->line != currentline) {
466                                 dseg_addlinenumber(cd, iptr->line, (u1 *) mcodeptr);
467                                 currentline = iptr->line;
468                         }
469
470                         MCODECHECK(64);   /* an instruction usually needs < 64 words      */
471
472                         switch (iptr->opc) {
473                         case ICMD_NOP:    /* ...  ==> ...                                 */
474                         case ICMD_INLINE_START:
475                         case ICMD_INLINE_END:
476                                 break;
477
478                 case ICMD_CHECKNULL:  /* ..., objectref  ==> ..., objectref           */
479
480                         var_to_reg_int(s1, src, REG_ITMP1);
481                         M_TST(s1);
482                         M_BEQ(0);
483                         codegen_addxnullrefs(cd, mcodeptr);
484                         break;
485
486                 /* constant operations ************************************************/
487
488                 case ICMD_ICONST:     /* ...  ==> ..., constant                       */
489                                       /* op1 = 0, val.i = constant                    */
490
491                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
492                         ICONST(d, iptr->val.i);
493                         store_reg_to_var_int(iptr->dst, d);
494                         break;
495
496                 case ICMD_LCONST:     /* ...  ==> ..., constant                       */
497                                       /* op1 = 0, val.l = constant                    */
498
499                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
500                         LCONST(d, iptr->val.l);
501                         store_reg_to_var_int(iptr->dst, d);
502                         break;
503
504                 case ICMD_FCONST:     /* ...  ==> ..., constant                       */
505                                       /* op1 = 0, val.f = constant                    */
506
507                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
508                         a = dseg_addfloat(cd, iptr->val.f);
509                         M_FLD(d, REG_PV, a);
510                         store_reg_to_var_flt(iptr->dst, d);
511                         break;
512                         
513                 case ICMD_DCONST:     /* ...  ==> ..., constant                       */
514                                       /* op1 = 0, val.d = constant                    */
515
516                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
517                         a = dseg_adddouble(cd, iptr->val.d);
518                         M_DLD(d, REG_PV, a);
519                         store_reg_to_var_flt(iptr->dst, d);
520                         break;
521
522                 case ICMD_ACONST:     /* ...  ==> ..., constant                       */
523                                       /* op1 = 0, val.a = constant                    */
524
525                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
526                         ICONST(d, (u4) iptr->val.a);
527                         store_reg_to_var_int(iptr->dst, d);
528                         break;
529
530
531                 /* load/store operations **********************************************/
532
533                 case ICMD_ILOAD:      /* ...  ==> ..., content of local variable      */
534                 case ICMD_ALOAD:      /* op1 = local variable                         */
535
536                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
537                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
538                         if ((iptr->dst->varkind == LOCALVAR) &&
539                             (iptr->dst->varnum == iptr->op1))
540                                 break;
541                         if (var->flags & INMEMORY) {
542                                 M_ILD(d, REG_SP, var->regoff * 4);
543                         } else {
544                                 M_TINTMOVE(var->type, var->regoff, d);
545                         }
546                         store_reg_to_var_int(iptr->dst, d);
547                         break;
548
549                 case ICMD_LLOAD:      /* ...  ==> ..., content of local variable      */
550                                       /* op1 = local variable                         */
551
552                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
553                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
554                         if ((iptr->dst->varkind == LOCALVAR) &&
555                                 (iptr->dst->varnum == iptr->op1))
556                                 break;
557                         if (var->flags & INMEMORY) {
558                                 M_ILD(GET_HIGH_REG(d), REG_SP, var->regoff * 4);
559                                 M_ILD(GET_LOW_REG(d), REG_SP, var->regoff * 4 + 4);
560                         } else {
561                                 M_TINTMOVE(var->type, var->regoff, d);
562                         }
563                         store_reg_to_var_int(iptr->dst, d);
564                         break;
565
566                 case ICMD_FLOAD:      /* ...  ==> ..., content of local variable      */
567                 case ICMD_DLOAD:      /* op1 = local variable                         */
568
569                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
570                         if ((iptr->dst->varkind == LOCALVAR) &&
571                                 (iptr->dst->varnum == iptr->op1))
572                                 break;
573                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
574                         if (var->flags & INMEMORY)
575                                 if (IS_2_WORD_TYPE(var->type))
576                                         M_DLD(d, REG_SP, var->regoff * 4);
577                                 else
578                                         M_FLD(d, REG_SP, var->regoff * 4);
579                         else {
580                                 M_FLTMOVE(var->regoff, d);
581                         }
582                         store_reg_to_var_flt(iptr->dst, d);
583                         break;
584
585
586                 case ICMD_ISTORE:     /* ..., value  ==> ...                          */
587                 case ICMD_ASTORE:     /* op1 = local variable                         */
588
589                         if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
590                                 break;
591                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
592                         if (var->flags & INMEMORY) {
593                                 var_to_reg_int(s1, src, REG_ITMP1);
594                                 M_IST(s1, REG_SP, var->regoff * 4);
595                         } else {
596                                 var_to_reg_int(s1, src, var->regoff);
597                                 M_TINTMOVE(var->type, s1, var->regoff);
598                         }
599                         break;
600
601                 case ICMD_LSTORE:     /* ..., value  ==> ...                          */
602                                       /* op1 = local variable                         */
603
604                         if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
605                                 break;
606                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
607                         if (var->flags & INMEMORY) {
608                                 var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
609                                 M_IST(GET_HIGH_REG(s1), REG_SP, var->regoff * 4);
610                                 M_IST(GET_LOW_REG(s1), REG_SP, var->regoff * 4 + 4);
611                         } else {
612                                 var_to_reg_int(s1, src, var->regoff);
613                                 M_TINTMOVE(var->type, s1, var->regoff);
614                         }
615                         break;
616
617                 case ICMD_FSTORE:     /* ..., value  ==> ...                          */
618                 case ICMD_DSTORE:     /* op1 = local variable                         */
619
620                         if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
621                                 break;
622                         var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
623                         if (var->flags & INMEMORY) {
624                                 var_to_reg_flt(s1, src, REG_FTMP1);
625                                 if (var->type == TYPE_DBL)
626                                         M_DST(s1, REG_SP, var->regoff * 4);
627                                 else
628                                         M_FST(s1, REG_SP, var->regoff * 4);
629                         } else {
630                                 var_to_reg_flt(s1, src, var->regoff);
631                                 M_FLTMOVE(s1, var->regoff);
632                         }
633                         break;
634
635
636                 /* pop/dup/swap operations ********************************************/
637
638                 /* attention: double and longs are only one entry in CACAO ICMDs      */
639
640                 case ICMD_POP:        /* ..., value  ==> ...                          */
641                 case ICMD_POP2:       /* ..., value, value  ==> ...                   */
642                         break;
643
644                 case ICMD_DUP:        /* ..., a ==> ..., a, a                         */
645                         M_COPY(src, iptr->dst);
646                         break;
647
648                 case ICMD_DUP_X1:     /* ..., a, b ==> ..., b, a, b                   */
649
650                         M_COPY(src,       iptr->dst);
651                         M_COPY(src->prev, iptr->dst->prev);
652                         M_COPY(iptr->dst, iptr->dst->prev->prev);
653                         break;
654
655                 case ICMD_DUP_X2:     /* ..., a, b, c ==> ..., c, a, b, c             */
656
657                         M_COPY(src,             iptr->dst);
658                         M_COPY(src->prev,       iptr->dst->prev);
659                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
660                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
661                         break;
662
663                 case ICMD_DUP2:       /* ..., a, b ==> ..., a, b, a, b                */
664
665                         M_COPY(src,       iptr->dst);
666                         M_COPY(src->prev, iptr->dst->prev);
667                         break;
668
669                 case ICMD_DUP2_X1:    /* ..., a, b, c ==> ..., b, c, a, b, c          */
670
671                         M_COPY(src,             iptr->dst);
672                         M_COPY(src->prev,       iptr->dst->prev);
673                         M_COPY(src->prev->prev, iptr->dst->prev->prev);
674                         M_COPY(iptr->dst,       iptr->dst->prev->prev->prev);
675                         M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
676                         break;
677
678                 case ICMD_DUP2_X2:    /* ..., a, b, c, d ==> ..., c, d, a, b, c, d    */
679
680                         M_COPY(src,                   iptr->dst);
681                         M_COPY(src->prev,             iptr->dst->prev);
682                         M_COPY(src->prev->prev,       iptr->dst->prev->prev);
683                         M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
684                         M_COPY(iptr->dst,             iptr->dst->prev->prev->prev->prev);
685                         M_COPY(iptr->dst->prev,       iptr->dst->prev->prev->prev->prev->prev);
686                         break;
687
688                 case ICMD_SWAP:       /* ..., a, b ==> ..., b, a                      */
689
690                         M_COPY(src,       iptr->dst->prev);
691                         M_COPY(src->prev, iptr->dst);
692                         break;
693
694
695                 /* integer operations *************************************************/
696
697                 case ICMD_INEG:       /* ..., value  ==> ..., - value                 */
698
699                         var_to_reg_int(s1, src, REG_ITMP1); 
700                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
701                         M_NEG(s1, d);
702                         store_reg_to_var_int(iptr->dst, d);
703                         break;
704
705                 case ICMD_LNEG:       /* ..., value  ==> ..., - value                 */
706
707                         var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
708                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
709                         M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
710                         M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
711                         store_reg_to_var_int(iptr->dst, d);
712                         break;
713
714                 case ICMD_I2L:        /* ..., value  ==> ..., value                   */
715
716                         var_to_reg_int(s1, src, REG_ITMP2);
717                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
718                         M_INTMOVE(s1, GET_LOW_REG(d));
719                         M_SRA_IMM(GET_LOW_REG(d), 31, GET_HIGH_REG(d));
720                         store_reg_to_var_int(iptr->dst, d);
721                         break;
722
723                 case ICMD_L2I:        /* ..., value  ==> ..., value                   */
724
725                         var_to_reg_int_low(s1, src, REG_ITMP2);
726                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
727                         M_INTMOVE(s1, d);
728                         store_reg_to_var_int(iptr->dst, d);
729                         break;
730
731                 case ICMD_INT2BYTE:   /* ..., value  ==> ..., value                   */
732
733                         var_to_reg_int(s1, src, REG_ITMP1);
734                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
735                         M_BSEXT(s1, d);
736                         store_reg_to_var_int(iptr->dst, d);
737                         break;
738
739                 case ICMD_INT2CHAR:   /* ..., value  ==> ..., value                   */
740
741                         var_to_reg_int(s1, src, REG_ITMP1);
742                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
743                         M_CZEXT(s1, d);
744                         store_reg_to_var_int(iptr->dst, d);
745                         break;
746
747                 case ICMD_INT2SHORT:  /* ..., value  ==> ..., value                   */
748
749                         var_to_reg_int(s1, src, REG_ITMP1);
750                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
751                         M_SSEXT(s1, d);
752                         store_reg_to_var_int(iptr->dst, d);
753                         break;
754
755
756                 case ICMD_IADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
757
758                         var_to_reg_int(s1, src->prev, REG_ITMP1);
759                         var_to_reg_int(s2, src, REG_ITMP2);
760                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
761                         M_IADD(s1, s2, d);
762                         store_reg_to_var_int(iptr->dst, d);
763                         break;
764
765                 case ICMD_IADDCONST:  /* ..., value  ==> ..., value + constant        */
766                                       /* val.i = constant                             */
767
768                         var_to_reg_int(s1, src, REG_ITMP1);
769                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
770                         if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
771                                 M_IADD_IMM(s1, iptr->val.i, d);
772                         } else {
773                                 ICONST(REG_ITMP2, iptr->val.i);
774                                 M_IADD(s1, REG_ITMP2, d);
775                         }
776                         store_reg_to_var_int(iptr->dst, d);
777                         break;
778
779                 case ICMD_LADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
780
781                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
782                         var_to_reg_int_low(s2, src, REG_ITMP2);
783                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
784                         M_ADDC(s1, s2, GET_LOW_REG(d));
785                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
786                         var_to_reg_int_high(s2, src, REG_ITMP3);   /* don't use REG_ITMP2 */
787                         M_ADDE(s1, s2, GET_HIGH_REG(d));
788                         store_reg_to_var_int(iptr->dst, d);
789                         break;
790
791                 case ICMD_LADDCONST:  /* ..., value  ==> ..., value + constant        */
792                                       /* val.l = constant                             */
793
794                         s3 = iptr->val.l & 0xffffffff;
795                         var_to_reg_int_low(s1, src, REG_ITMP1);
796                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
797                         if ((s3 >= -32768) && (s3 <= 32767)) {
798                                 M_ADDIC(s1, s3, GET_LOW_REG(d));
799                         } else {
800                                 ICONST(REG_ITMP2, s3);
801                                 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
802                         }
803                         var_to_reg_int_high(s1, src, REG_ITMP1);
804                         s3 = iptr->val.l >> 32;
805                         if (s3 == -1) {
806                                 M_ADDME(s1, GET_HIGH_REG(d));
807                         } else if (s3 == 0) {
808                                 M_ADDZE(s1, GET_HIGH_REG(d));
809                         } else {
810                                 ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
811                                 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
812                         }
813                         store_reg_to_var_int(iptr->dst, d);
814                         break;
815
816                 case ICMD_ISUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
817
818                         var_to_reg_int(s1, src->prev, REG_ITMP1);
819                         var_to_reg_int(s2, src, REG_ITMP2);
820                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
821                         M_ISUB(s1, s2, d);
822                         store_reg_to_var_int(iptr->dst, d);
823                         break;
824
825                 case ICMD_ISUBCONST:  /* ..., value  ==> ..., value + constant        */
826                                       /* val.i = constant                             */
827
828                         var_to_reg_int(s1, src, REG_ITMP1);
829                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
830                         if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
831                                 M_IADD_IMM(s1, -iptr->val.i, d);
832                         } else {
833                                 ICONST(REG_ITMP2, -iptr->val.i);
834                                 M_IADD(s1, REG_ITMP2, d);
835                         }
836                         store_reg_to_var_int(iptr->dst, d);
837                         break;
838
839                 case ICMD_LSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
840
841                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
842                         var_to_reg_int_low(s2, src, REG_ITMP2);
843                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
844                         M_SUBC(s1, s2, GET_LOW_REG(d));
845                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
846                         var_to_reg_int_high(s2, src, REG_ITMP3);   /* don't use REG_ITMP2 */
847                         M_SUBE(s1, s2, GET_HIGH_REG(d));
848                         store_reg_to_var_int(iptr->dst, d);
849                         break;
850
851                 case ICMD_LSUBCONST:  /* ..., value  ==> ..., value - constant        */
852                                       /* val.l = constant                             */
853
854                         s3 = (-iptr->val.l) & 0xffffffff;
855                         var_to_reg_int_low(s1, src, REG_ITMP1);
856                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
857                         if ((s3 >= -32768) && (s3 <= 32767)) {
858                                 M_ADDIC(s1, s3, GET_LOW_REG(d));
859                         } else {
860                                 ICONST(REG_ITMP2, s3);
861                                 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
862                         }
863                         var_to_reg_int_high(s1, src, REG_ITMP1);
864                         s3 = (-iptr->val.l) >> 32;
865                         if (s3 == -1)
866                                 M_ADDME(s1, GET_HIGH_REG(d));
867                         else if (s3 == 0)
868                                 M_ADDZE(s1, GET_HIGH_REG(d));
869                         else {
870                                 ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
871                                 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
872                         }
873                         store_reg_to_var_int(iptr->dst, d);
874                         break;
875
876                 case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
877
878                         var_to_reg_int(s1, src->prev, REG_ITMP1);
879                         var_to_reg_int(s2, src, REG_ITMP2);
880                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
881                         M_TST(s2);
882                         M_BEQ(0);
883                         codegen_addxdivrefs(cd, mcodeptr);
884                         M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
885                         M_CMP(REG_ITMP3, s1);
886                         M_BNE(3 + (s1 != d));
887                         M_CMPI(s2, -1);
888                         M_BNE(1 + (s1 != d));
889                         M_INTMOVE(s1, d);
890                         M_BR(1);
891                         M_IDIV(s1, s2, d);
892                         store_reg_to_var_int(iptr->dst, d);
893                         break;
894
895                 case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
896
897                         var_to_reg_int(s1, src->prev, REG_ITMP1);
898                         var_to_reg_int(s2, src, REG_ITMP2);
899                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
900                         M_TST(s2);
901                         M_BEQ(0);
902                         codegen_addxdivrefs(cd, mcodeptr);
903                         M_LDAH(REG_ITMP3, REG_ZERO, 0x8000);
904                         M_CMP(REG_ITMP3, s1);
905                         M_BNE(4);
906                         M_CMPI(s2, -1);
907                         M_BNE(2);
908                         M_CLR(d);
909                         M_BR(3);
910                         M_IDIV(s1, s2, REG_ITMP3);
911                         M_IMUL(REG_ITMP3, s2, REG_ITMP3);
912                         M_ISUB(s1, REG_ITMP3, d);
913                         store_reg_to_var_int(iptr->dst, d);
914                         break;
915
916                 case ICMD_LDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
917                 case ICMD_LREM:       /* ..., val1, val2  ==> ..., val1 % val2        */
918
919                         bte = iptr->val.a;
920                         md = bte->md;
921
922                         var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
923                         M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
924                         M_BEQ(0);
925                         codegen_addxdivrefs(cd, mcodeptr);
926
927                         s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[1].regoff)],
928                                                    rd->argintregs[GET_HIGH_REG(md->params[1].regoff)]);
929                         M_TINTMOVE(TYPE_LNG, s2, s3);
930
931                         var_to_reg_int(s1, src->prev, PACK_REGS(REG_ITMP2, REG_ITMP1));
932                         s3 = PACK_REGS(rd->argintregs[GET_LOW_REG(md->params[0].regoff)],
933                                                    rd->argintregs[GET_HIGH_REG(md->params[0].regoff)]);
934                         M_TINTMOVE(TYPE_LNG, s1, s3);
935
936                         disp = dseg_addaddress(cd, bte->fp);
937                         M_ALD(REG_ITMP1, REG_PV, disp);
938                         M_MTCTR(REG_ITMP1);
939                         M_JSR;
940
941                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_RESULT2, REG_RESULT));
942                         M_TINTMOVE(TYPE_LNG, PACK_REGS(REG_RESULT2, REG_RESULT), d);
943                         store_reg_to_var_int(iptr->dst, d);
944                         break;
945
946                 case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
947
948                         var_to_reg_int(s1, src->prev, REG_ITMP1);
949                         var_to_reg_int(s2, src, REG_ITMP2);
950                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
951                         M_IMUL(s1, s2, d);
952                         store_reg_to_var_int(iptr->dst, d);
953                         break;
954
955                 case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant        */
956                                       /* val.i = constant                             */
957
958                         var_to_reg_int(s1, src, REG_ITMP1);
959                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
960                         if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
961                                 M_IMUL_IMM(s1, iptr->val.i, d);
962                         } else {
963                                 ICONST(REG_ITMP3, iptr->val.i);
964                                 M_IMUL(s1, REG_ITMP3, d);
965                         }
966                         store_reg_to_var_int(iptr->dst, d);
967                         break;
968
969                 case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value << constant       */
970                                       
971                         var_to_reg_int(s1, src, REG_ITMP1);
972                         d = reg_of_var(rd, iptr->dst, REG_ITMP3);
973                         M_SRA_IMM(s1, iptr->val.i, d);
974                         M_ADDZE(d, d);
975                         store_reg_to_var_int(iptr->dst, d);
976                         break;
977
978                 case ICMD_ISHL:       /* ..., val1, val2  ==> ..., val1 << val2       */
979
980                         var_to_reg_int(s1, src->prev, REG_ITMP1);
981                         var_to_reg_int(s2, src, REG_ITMP2);
982                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
983                         M_AND_IMM(s2, 0x1f, REG_ITMP3);
984                         M_SLL(s1, REG_ITMP3, d);
985                         store_reg_to_var_int(iptr->dst, d);
986                         break;
987
988                 case ICMD_ISHLCONST:  /* ..., value  ==> ..., value << constant       */
989                                       /* val.i = constant                             */
990
991                         var_to_reg_int(s1, src, REG_ITMP1);
992                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
993                         M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
994                         store_reg_to_var_int(iptr->dst, d);
995                         break;
996
997                 case ICMD_ISHR:       /* ..., val1, val2  ==> ..., val1 >> val2       */
998
999                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1000                         var_to_reg_int(s2, src, REG_ITMP2);
1001                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1002                         M_AND_IMM(s2, 0x1f, REG_ITMP3);
1003                         M_SRA(s1, REG_ITMP3, d);
1004                         store_reg_to_var_int(iptr->dst, d);
1005                         break;
1006
1007                 case ICMD_ISHRCONST:  /* ..., value  ==> ..., value >> constant       */
1008                                       /* val.i = constant                             */
1009
1010                         var_to_reg_int(s1, src, REG_ITMP1);
1011                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1012                         M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1013                         store_reg_to_var_int(iptr->dst, d);
1014                         break;
1015
1016                 case ICMD_IUSHR:      /* ..., val1, val2  ==> ..., val1 >>> val2      */
1017
1018                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1019                         var_to_reg_int(s2, src, REG_ITMP2);
1020                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1021                         M_AND_IMM(s2, 0x1f, REG_ITMP2);
1022                         M_SRL(s1, REG_ITMP2, d);
1023                         store_reg_to_var_int(iptr->dst, d);
1024                         break;
1025
1026                 case ICMD_IUSHRCONST: /* ..., value  ==> ..., value >>> constant      */
1027                                       /* val.i = constant                             */
1028
1029                         var_to_reg_int(s1, src, REG_ITMP1);
1030                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1031                         if (iptr->val.i & 0x1f) {
1032                                 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1033                         } else {
1034                                 M_INTMOVE(s1, d);
1035                         }
1036                         store_reg_to_var_int(iptr->dst, d);
1037                         break;
1038
1039                 case ICMD_IAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1040
1041                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1042                         var_to_reg_int(s2, src, REG_ITMP2);
1043                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1044                         M_AND(s1, s2, d);
1045                         store_reg_to_var_int(iptr->dst, d);
1046                         break;
1047
1048                 case ICMD_IANDCONST:  /* ..., value  ==> ..., value & constant        */
1049                                       /* val.i = constant                             */
1050
1051                         var_to_reg_int(s1, src, REG_ITMP1);
1052                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1053                         if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1054                                 M_AND_IMM(s1, iptr->val.i, d);
1055                                 }
1056                         /*
1057                         else if (iptr->val.i == 0xffffff) {
1058                                 M_RLWINM(s1, 0, 8, 31, d);
1059                                 }
1060                         */
1061                         else {
1062                                 ICONST(REG_ITMP3, iptr->val.i);
1063                                 M_AND(s1, REG_ITMP3, d);
1064                         }
1065                         store_reg_to_var_int(iptr->dst, d);
1066                         break;
1067
1068                 case ICMD_LAND:       /* ..., val1, val2  ==> ..., val1 & val2        */
1069
1070                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1071                         var_to_reg_int_low(s2, src, REG_ITMP2);
1072                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
1073                         M_AND(s1, s2, GET_LOW_REG(d));
1074                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1075                         var_to_reg_int_high(s2, src, REG_ITMP3);   /* don't use REG_ITMP2 */
1076                         M_AND(s1, s2, GET_HIGH_REG(d));
1077                         store_reg_to_var_int(iptr->dst, d);
1078                         break;
1079
1080                 case ICMD_LANDCONST:  /* ..., value  ==> ..., value & constant        */
1081                                       /* val.l = constant                             */
1082
1083                         s3 = iptr->val.l & 0xffffffff;
1084                         var_to_reg_int_low(s1, src, REG_ITMP1);
1085                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
1086                         if ((s3 >= 0) && (s3 <= 65535)) {
1087                                 M_AND_IMM(s1, s3, GET_LOW_REG(d));
1088                         } else {
1089                                 ICONST(REG_ITMP3, s3);
1090                                 M_AND(s1, REG_ITMP3, GET_LOW_REG(d));
1091                         }
1092                         var_to_reg_int_high(s1, src, REG_ITMP1);
1093                         s3 = iptr->val.l >> 32;
1094                         if ((s3 >= 0) && (s3 <= 65535)) {
1095                                 M_AND_IMM(s1, s3, GET_HIGH_REG(d));
1096                         } else {
1097                                 ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
1098                                 M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
1099                         }
1100                         store_reg_to_var_int(iptr->dst, d);
1101                         break;
1102
1103                 case ICMD_IREMPOW2:   /* ..., value  ==> ..., value % constant        */
1104                                       /* val.i = constant                             */
1105
1106                         var_to_reg_int(s1, src, REG_ITMP1);
1107                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1108                         M_MOV(s1, REG_ITMP2);
1109                         M_CMPI(s1, 0);
1110                         M_BGE(1 + 2*(iptr->val.i >= 32768));
1111                         if (iptr->val.i >= 32768) {
1112                                 M_ADDIS(REG_ZERO, iptr->val.i >> 16, REG_ITMP2);
1113                                 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1114                                 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1115                         } else {
1116                                 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1117                         }
1118                         {
1119                                 int b=0, m = iptr->val.i;
1120                                 while (m >>= 1)
1121                                         ++b;
1122                                 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1123                         }
1124                         M_ISUB(s1, REG_ITMP2, d);
1125                         store_reg_to_var_int(iptr->dst, d);
1126                         break;
1127
1128                 case ICMD_IOR:        /* ..., val1, val2  ==> ..., val1 | val2        */
1129
1130                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1131                         var_to_reg_int(s2, src, REG_ITMP2);
1132                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1133                         M_OR(s1, s2, d);
1134                         store_reg_to_var_int(iptr->dst, d);
1135                         break;
1136
1137                 case ICMD_IORCONST:   /* ..., value  ==> ..., value | constant        */
1138                                       /* val.i = constant                             */
1139
1140                         var_to_reg_int(s1, src, REG_ITMP1);
1141                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1142                         if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1143                                 M_OR_IMM(s1, iptr->val.i, d);
1144                         } else {
1145                                 ICONST(REG_ITMP3, iptr->val.i);
1146                                 M_OR(s1, REG_ITMP3, d);
1147                         }
1148                         store_reg_to_var_int(iptr->dst, d);
1149                         break;
1150
1151                 case ICMD_LOR:       /* ..., val1, val2  ==> ..., val1 | val2        */
1152
1153                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1154                         var_to_reg_int_low(s2, src, REG_ITMP2);
1155                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
1156                         M_OR(s1, s2, GET_LOW_REG(d));
1157                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1158                         var_to_reg_int_high(s2, src, REG_ITMP3);   /* don't use REG_ITMP2 */
1159                         M_OR(s1, s2, GET_HIGH_REG(d));
1160                         store_reg_to_var_int(iptr->dst, d);
1161                         break;
1162
1163                 case ICMD_LORCONST:   /* ..., value  ==> ..., value | constant        */
1164                                       /* val.l = constant                             */
1165
1166                         s3 = iptr->val.l & 0xffffffff;
1167                         var_to_reg_int_low(s1, src, REG_ITMP1);
1168                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
1169                         if ((s3 >= 0) && (s3 <= 65535)) {
1170                                 M_OR_IMM(s1, s3, GET_LOW_REG(d));
1171                         } else {
1172                                 ICONST(REG_ITMP3, s3);
1173                                 M_OR(s1, REG_ITMP3, GET_LOW_REG(d));
1174                         }
1175                         var_to_reg_int_high(s1, src, REG_ITMP1);
1176                         s3 = iptr->val.l >> 32;
1177                         if ((s3 >= 0) && (s3 <= 65535)) {
1178                                 M_OR_IMM(s1, s3, GET_HIGH_REG(d));
1179                         } else {
1180                                 ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
1181                                 M_OR(s1, REG_ITMP3, GET_HIGH_REG(d));
1182                         }
1183                         store_reg_to_var_int(iptr->dst, d);
1184                         break;
1185
1186                 case ICMD_IXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1187
1188                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1189                         var_to_reg_int(s2, src, REG_ITMP2);
1190                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1191                         M_XOR(s1, s2, d);
1192                         store_reg_to_var_int(iptr->dst, d);
1193                         break;
1194
1195                 case ICMD_IXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1196                                       /* val.i = constant                             */
1197
1198                         var_to_reg_int(s1, src, REG_ITMP1);
1199                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1200                         if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1201                                 M_XOR_IMM(s1, iptr->val.i, d);
1202                         } else {
1203                                 ICONST(REG_ITMP3, iptr->val.i);
1204                                 M_XOR(s1, REG_ITMP3, d);
1205                         }
1206                         store_reg_to_var_int(iptr->dst, d);
1207                         break;
1208
1209                 case ICMD_LXOR:       /* ..., val1, val2  ==> ..., val1 ^ val2        */
1210
1211                         var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1212                         var_to_reg_int_low(s2, src, REG_ITMP2);
1213                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
1214                         M_XOR(s1, s2, GET_LOW_REG(d));
1215                         var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1216                         var_to_reg_int_high(s2, src, REG_ITMP3);   /* don't use REG_ITMP2 */
1217                         M_XOR(s1, s2, GET_HIGH_REG(d));
1218                         store_reg_to_var_int(iptr->dst, d);
1219                         break;
1220
1221                 case ICMD_LXORCONST:  /* ..., value  ==> ..., value ^ constant        */
1222                                       /* val.l = constant                             */
1223
1224                         s3 = iptr->val.l & 0xffffffff;
1225                         var_to_reg_int_low(s1, src, REG_ITMP1);
1226                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
1227                         if ((s3 >= 0) && (s3 <= 65535)) {
1228                                 M_XOR_IMM(s1, s3, GET_LOW_REG(d));
1229                         } else {
1230                                 ICONST(REG_ITMP3, s3);
1231                                 M_XOR(s1, REG_ITMP3, GET_LOW_REG(d));
1232                         }
1233                         var_to_reg_int_high(s1, src, REG_ITMP1);
1234                         s3 = iptr->val.l >> 32;
1235                         if ((s3 >= 0) && (s3 <= 65535)) {
1236                                 M_XOR_IMM(s1, s3, GET_HIGH_REG(d));
1237                         } else {
1238                                 ICONST(REG_ITMP3, s3);                 /* don't use REG_ITMP2 */
1239                                 M_XOR(s1, REG_ITMP3, GET_HIGH_REG(d));
1240                         }
1241                         store_reg_to_var_int(iptr->dst, d);
1242                         break;
1243
1244                 case ICMD_LCMP:       /* ..., val1, val2  ==> ..., val1 cmp val2      */
1245                         /*******************************************************************
1246                 TODO: CHANGE THIS TO A VERSION THAT WORKS !!!
1247                         *******************************************************************/
1248                         var_to_reg_int_high(s1, src->prev, REG_ITMP3);
1249                         var_to_reg_int_high(s2, src, REG_ITMP2);
1250                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1251                         {
1252                                 int tempreg = false;
1253                                 int dreg;
1254                                 s4  *br1;
1255
1256                                 if (src->prev->flags & INMEMORY) {
1257                                         tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1258                                 } else {
1259                                         tempreg = tempreg || (d == GET_HIGH_REG(src->prev->regoff))
1260                                                         || (d == GET_LOW_REG(src->prev->regoff));
1261                                 }
1262                                 if (src->flags & INMEMORY) {
1263                                         tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1264                                 } else {
1265                                         tempreg = tempreg || (d == GET_HIGH_REG(src->regoff))
1266                                  || (d == GET_LOW_REG(src->regoff));
1267                                 }
1268
1269                                 dreg = tempreg ? REG_ITMP1 : d;
1270                                 M_IADD_IMM(REG_ZERO, 1, dreg);
1271                                 M_CMP(s1, s2);
1272                                 M_BGT(0);
1273                                 br1 = mcodeptr;
1274                                 M_BLT(0);
1275                                 var_to_reg_int_low(s1, src->prev, REG_ITMP3);
1276                                 var_to_reg_int_low(s2, src, REG_ITMP2);
1277                                 M_CMPU(s1, s2);
1278                                 M_BGT(3);
1279                                 M_BEQ(1);
1280                                 M_IADD_IMM(dreg, -1, dreg);
1281                                 M_IADD_IMM(dreg, -1, dreg);
1282                                 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1283                                 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1284                                 M_INTMOVE(dreg, d);
1285                         }
1286                         store_reg_to_var_int(iptr->dst, d);
1287                         break;
1288
1289                 case ICMD_IINC:       /* ..., value  ==> ..., value + constant        */
1290                                       /* op1 = variable, val.i = constant             */
1291
1292                         var = &(rd->locals[iptr->op1][TYPE_INT]);
1293                         if (var->flags & INMEMORY) {
1294                                 s1 = REG_ITMP1;
1295                                 M_ILD(s1, REG_SP, var->regoff * 4);
1296                         } else {
1297                                 s1 = var->regoff;
1298                         }
1299                         {
1300                                 u4 m = iptr->val.i;
1301                                 if (m & 0x8000)
1302                                         m += 65536;
1303                                 if (m & 0xffff0000)
1304                                         M_ADDIS(s1, m >> 16, s1);
1305                                 if (m & 0xffff)
1306                                         M_IADD_IMM(s1, m & 0xffff, s1);
1307                         }
1308                         if (var->flags & INMEMORY) {
1309                                 M_IST(s1, REG_SP, var->regoff * 4);
1310                         }
1311                         break;
1312
1313
1314                 /* floating operations ************************************************/
1315
1316                 case ICMD_FNEG:       /* ..., value  ==> ..., - value                 */
1317
1318                         var_to_reg_flt(s1, src, REG_FTMP1);
1319                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1320                         M_FMOVN(s1, d);
1321                         store_reg_to_var_flt(iptr->dst, d);
1322                         break;
1323
1324                 case ICMD_DNEG:       /* ..., value  ==> ..., - value                 */
1325
1326                         var_to_reg_flt(s1, src, REG_FTMP1);
1327                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1328                         M_FMOVN(s1, d);
1329                         store_reg_to_var_flt(iptr->dst, d);
1330                         break;
1331
1332                 case ICMD_FADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1333
1334                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1335                         var_to_reg_flt(s2, src, REG_FTMP2);
1336                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1337                         M_FADD(s1, s2, d);
1338                         store_reg_to_var_flt(iptr->dst, d);
1339                         break;
1340
1341                 case ICMD_DADD:       /* ..., val1, val2  ==> ..., val1 + val2        */
1342
1343                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1344                         var_to_reg_flt(s2, src, REG_FTMP2);
1345                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1346                         M_DADD(s1, s2, d);
1347                         store_reg_to_var_flt(iptr->dst, d);
1348                         break;
1349
1350                 case ICMD_FSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1351
1352                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1353                         var_to_reg_flt(s2, src, REG_FTMP2);
1354                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1355                         M_FSUB(s1, s2, d);
1356                         store_reg_to_var_flt(iptr->dst, d);
1357                         break;
1358
1359                 case ICMD_DSUB:       /* ..., val1, val2  ==> ..., val1 - val2        */
1360
1361                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1362                         var_to_reg_flt(s2, src, REG_FTMP2);
1363                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1364                         M_DSUB(s1, s2, d);
1365                         store_reg_to_var_flt(iptr->dst, d);
1366                         break;
1367
1368                 case ICMD_FMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1369
1370                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1371                         var_to_reg_flt(s2, src, REG_FTMP2);
1372                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1373                         M_FMUL(s1, s2, d);
1374                         store_reg_to_var_flt(iptr->dst, d);
1375                         break;
1376
1377                 case ICMD_DMUL:       /* ..., val1, val2  ==> ..., val1 * val2        */
1378
1379                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1380                         var_to_reg_flt(s2, src, REG_FTMP2);
1381                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1382                         M_DMUL(s1, s2, d);
1383                         store_reg_to_var_flt(iptr->dst, d);
1384                         break;
1385
1386                 case ICMD_FDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1387
1388                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1389                         var_to_reg_flt(s2, src, REG_FTMP2);
1390                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1391                         M_FDIV(s1, s2, d);
1392                         store_reg_to_var_flt(iptr->dst, d);
1393                         break;
1394
1395                 case ICMD_DDIV:       /* ..., val1, val2  ==> ..., val1 / val2        */
1396
1397                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1398                         var_to_reg_flt(s2, src, REG_FTMP2);
1399                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1400                         M_DDIV(s1, s2, d);
1401                         store_reg_to_var_flt(iptr->dst, d);
1402                         break;
1403                 
1404                 case ICMD_F2I:       /* ..., value  ==> ..., (int) value              */
1405                 case ICMD_D2I:
1406                         var_to_reg_flt(s1, src, REG_FTMP1);
1407                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1408                         M_CLR(d);
1409                         disp = dseg_addfloat(cd, 0.0);
1410                         M_FLD(REG_FTMP2, REG_PV, disp);
1411                         M_FCMPU(s1, REG_FTMP2);
1412                         M_BNAN(4);
1413                         disp = dseg_adds4(cd, 0);
1414                         M_CVTDL_C(s1, REG_FTMP1);
1415                         M_LDA(REG_ITMP1, REG_PV, disp);
1416                         M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1417                         M_ILD(d, REG_PV, disp);
1418                         store_reg_to_var_int(iptr->dst, d);
1419                         break;
1420                 
1421                 case ICMD_F2D:       /* ..., value  ==> ..., (double) value           */
1422
1423                         var_to_reg_flt(s1, src, REG_FTMP1);
1424                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1425                         M_FLTMOVE(s1, d);
1426                         store_reg_to_var_flt(iptr->dst, d);
1427                         break;
1428                                         
1429                 case ICMD_D2F:       /* ..., value  ==> ..., (double) value           */
1430
1431                         var_to_reg_flt(s1, src, REG_FTMP1);
1432                         d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1433                         M_CVTDF(s1, d);
1434                         store_reg_to_var_flt(iptr->dst, d);
1435                         break;
1436                 
1437                 case ICMD_FCMPL:      /* ..., val1, val2  ==> ..., val1 fcmpg val2    */
1438                 case ICMD_DCMPL:
1439                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1440                         var_to_reg_flt(s2, src, REG_FTMP2);
1441                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1442                         M_FCMPU(s2, s1);
1443                         M_IADD_IMM(REG_ZERO, -1, d);
1444                         M_BNAN(4);
1445                         M_BGT(3);
1446                         M_IADD_IMM(REG_ZERO, 0, d);
1447                         M_BGE(1);
1448                         M_IADD_IMM(REG_ZERO, 1, d);
1449                         store_reg_to_var_int(iptr->dst, d);
1450                         break;
1451
1452                 case ICMD_FCMPG:      /* ..., val1, val2  ==> ..., val1 fcmpl val2    */
1453                 case ICMD_DCMPG:
1454                         var_to_reg_flt(s1, src->prev, REG_FTMP1);
1455                         var_to_reg_flt(s2, src, REG_FTMP2);
1456                         d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1457                         M_FCMPU(s1, s2);
1458                         M_IADD_IMM(REG_ZERO, 1, d);
1459                         M_BNAN(4);
1460                         M_BGT(3);
1461                         M_IADD_IMM(REG_ZERO, 0, d);
1462                         M_BGE(1);
1463                         M_IADD_IMM(REG_ZERO, -1, d);
1464                         store_reg_to_var_int(iptr->dst, d);
1465                         break;
1466                         
1467
1468                 /* memory operations **************************************************/
1469
1470                 case ICMD_ARRAYLENGTH: /* ..., arrayref  ==> ..., length              */
1471
1472                         var_to_reg_int(s1, src, REG_ITMP1);
1473                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1474                         gen_nullptr_check(s1);
1475                         M_ILD(d, s1, OFFSET(java_arrayheader, size));
1476                         store_reg_to_var_int(iptr->dst, d);
1477                         break;
1478
1479                 case ICMD_BALOAD:     /* ..., arrayref, index  ==> ..., value         */
1480
1481                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1482                         var_to_reg_int(s2, src, REG_ITMP2);
1483                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1484                         if (iptr->op1 == 0) {
1485                                 gen_nullptr_check(s1);
1486                                 gen_bound_check;
1487                         }
1488                         M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1489                         M_LBZX(d, s1, REG_ITMP2);
1490                         M_BSEXT(d, d);
1491                         store_reg_to_var_int(iptr->dst, d);
1492                         break;                  
1493
1494                 case ICMD_CALOAD:     /* ..., arrayref, index  ==> ..., value         */
1495
1496                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1497                         var_to_reg_int(s2, src, REG_ITMP2);
1498                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1499                         if (iptr->op1 == 0) {
1500                                 gen_nullptr_check(s1);
1501                                 gen_bound_check;
1502                         }
1503                         M_SLL_IMM(s2, 1, REG_ITMP2);
1504                         M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1505                         M_LHZX(d, s1, REG_ITMP2);
1506                         store_reg_to_var_int(iptr->dst, d);
1507                         break;
1508
1509                 case ICMD_SALOAD:     /* ..., arrayref, index  ==> ..., value         */
1510
1511                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1512                         var_to_reg_int(s2, src, REG_ITMP2);
1513                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1514                         if (iptr->op1 == 0) {
1515                                 gen_nullptr_check(s1);
1516                                 gen_bound_check;
1517                         }
1518                         M_SLL_IMM(s2, 1, REG_ITMP2);
1519                         M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1520                         M_LHAX(d, s1, REG_ITMP2);
1521                         store_reg_to_var_int(iptr->dst, d);
1522                         break;
1523
1524                 case ICMD_IALOAD:     /* ..., arrayref, index  ==> ..., value         */
1525
1526                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1527                         var_to_reg_int(s2, src, REG_ITMP2);
1528                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1529                         if (iptr->op1 == 0) {
1530                                 gen_nullptr_check(s1);
1531                                 gen_bound_check;
1532                         }
1533                         M_SLL_IMM(s2, 2, REG_ITMP2);
1534                         M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1535                         M_LWZX(d, s1, REG_ITMP2);
1536                         store_reg_to_var_int(iptr->dst, d);
1537                         break;
1538
1539                 case ICMD_LALOAD:     /* ..., arrayref, index  ==> ..., value         */
1540
1541                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1542                         var_to_reg_int(s2, src, REG_ITMP2);
1543                         d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
1544                         if (iptr->op1 == 0) {
1545                                 gen_nullptr_check(s1);
1546                                 gen_bound_check;
1547                         }
1548                         M_SLL_IMM(s2, 3, REG_ITMP2);
1549                         M_IADD(s1, REG_ITMP2, REG_ITMP2);
1550                         M_ILD(GET_HIGH_REG(d), REG_ITMP2, OFFSET(java_longarray, data[0]));
1551                         M_ILD(GET_LOW_REG(d), REG_ITMP2, OFFSET(java_longarray,
1552                                                                                                         data[0]) + 4);
1553                         store_reg_to_var_int(iptr->dst, d);
1554                         break;
1555
1556                 case ICMD_FALOAD:     /* ..., arrayref, index  ==> ..., value         */
1557
1558                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1559                         var_to_reg_int(s2, src, REG_ITMP2);
1560                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1561                         if (iptr->op1 == 0) {
1562                                 gen_nullptr_check(s1);
1563                                 gen_bound_check;
1564                         }
1565                         M_SLL_IMM(s2, 2, REG_ITMP2);
1566                         M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1567                         M_LFSX(d, s1, REG_ITMP2);
1568                         store_reg_to_var_flt(iptr->dst, d);
1569                         break;
1570
1571                 case ICMD_DALOAD:     /* ..., arrayref, index  ==> ..., value         */
1572
1573                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1574                         var_to_reg_int(s2, src, REG_ITMP2);
1575                         d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1576                         if (iptr->op1 == 0) {
1577                                 gen_nullptr_check(s1);
1578                                 gen_bound_check;
1579                         }
1580                         M_SLL_IMM(s2, 3, REG_ITMP2);
1581                         M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1582                         M_LFDX(d, s1, REG_ITMP2);
1583                         store_reg_to_var_flt(iptr->dst, d);
1584                         break;
1585
1586                 case ICMD_AALOAD:     /* ..., arrayref, index  ==> ..., value         */
1587
1588                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1589                         var_to_reg_int(s2, src, REG_ITMP2);
1590                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1591                         if (iptr->op1 == 0) {
1592                                 gen_nullptr_check(s1);
1593                                 gen_bound_check;
1594                         }
1595                         M_SLL_IMM(s2, 2, REG_ITMP2);
1596                         M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1597                         M_LWZX(d, s1, REG_ITMP2);
1598                         store_reg_to_var_int(iptr->dst, d);
1599                         break;
1600
1601
1602                 case ICMD_BASTORE:    /* ..., arrayref, index, value  ==> ...         */
1603
1604                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1605                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1606                         if (iptr->op1 == 0) {
1607                                 gen_nullptr_check(s1);
1608                                 gen_bound_check;
1609                         }
1610                         var_to_reg_int(s3, src, REG_ITMP3);
1611                         M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1612                         M_STBX(s3, s1, REG_ITMP2);
1613                         break;
1614
1615                 case ICMD_CASTORE:    /* ..., arrayref, index, value  ==> ...         */
1616
1617                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1618                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1619                         if (iptr->op1 == 0) {
1620                                 gen_nullptr_check(s1);
1621                                 gen_bound_check;
1622                         }
1623                         var_to_reg_int(s3, src, REG_ITMP3);
1624                         M_SLL_IMM(s2, 1, REG_ITMP2);
1625                         M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1626                         M_STHX(s3, s1, REG_ITMP2);
1627                         break;
1628
1629                 case ICMD_SASTORE:    /* ..., arrayref, index, value  ==> ...         */
1630
1631                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1632                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1633                         if (iptr->op1 == 0) {
1634                                 gen_nullptr_check(s1);
1635                                 gen_bound_check;
1636                         }
1637                         var_to_reg_int(s3, src, REG_ITMP3);
1638                         M_SLL_IMM(s2, 1, REG_ITMP2);
1639                         M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1640                         M_STHX(s3, s1, REG_ITMP2);
1641                         break;
1642
1643                 case ICMD_IASTORE:    /* ..., arrayref, index, value  ==> ...         */
1644
1645                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1646                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1647                         if (iptr->op1 == 0) {
1648                                 gen_nullptr_check(s1);
1649                                 gen_bound_check;
1650                         }
1651                         var_to_reg_int(s3, src, REG_ITMP3);
1652                         M_SLL_IMM(s2, 2, REG_ITMP2);
1653                         M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1654                         M_STWX(s3, s1, REG_ITMP2);
1655                         break;
1656
1657                 case ICMD_LASTORE:    /* ..., arrayref, index, value  ==> ...         */
1658
1659                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1660                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1661                         if (iptr->op1 == 0) {
1662                                 gen_nullptr_check(s1);
1663                                 gen_bound_check;
1664                         }
1665                         var_to_reg_int_high(s3, src, REG_ITMP3);
1666                         M_SLL_IMM(s2, 3, REG_ITMP2);
1667                         M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
1668                         M_STWX(s3, s1, REG_ITMP2);
1669                         M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1670                         var_to_reg_int_low(s3, src, REG_ITMP3);
1671                         M_STWX(s3, s1, REG_ITMP2);
1672                         break;
1673
1674                 case ICMD_FASTORE:    /* ..., arrayref, index, value  ==> ...         */
1675
1676                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1677                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1678                         if (iptr->op1 == 0) {
1679                                 gen_nullptr_check(s1);
1680                                 gen_bound_check;
1681                         }
1682                         var_to_reg_flt(s3, src, REG_FTMP3);
1683                         M_SLL_IMM(s2, 2, REG_ITMP2);
1684                         M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1685                         M_STFSX(s3, s1, REG_ITMP2);
1686                         break;
1687
1688                 case ICMD_DASTORE:    /* ..., arrayref, index, value  ==> ...         */
1689
1690                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1691                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1692                         if (iptr->op1 == 0) {
1693                                 gen_nullptr_check(s1);
1694                                 gen_bound_check;
1695                         }
1696                         var_to_reg_flt(s3, src, REG_FTMP3);
1697                         M_SLL_IMM(s2, 3, REG_ITMP2);
1698                         M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1699                         M_STFDX(s3, s1, REG_ITMP2);
1700                         break;
1701
1702                 case ICMD_AASTORE:    /* ..., arrayref, index, value  ==> ...         */
1703
1704                         var_to_reg_int(s1, src->prev->prev, rd->argintregs[0]);
1705                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1706 /*                      if (iptr->op1 == 0) { */
1707                                 gen_nullptr_check(s1);
1708                                 gen_bound_check;
1709 /*                      } */
1710                         var_to_reg_int(s3, src, rd->argintregs[1]);
1711
1712                         M_INTMOVE(s1, rd->argintregs[0]);
1713                         M_INTMOVE(s3, rd->argintregs[1]);
1714                         bte = iptr->val.a;
1715                         disp = dseg_addaddress(cd, bte->fp);
1716                         M_ALD(REG_ITMP1, REG_PV, disp);
1717                         M_MTCTR(REG_ITMP1);
1718                         M_JSR;
1719                         M_TST(REG_RESULT);
1720                         M_BEQ(0);
1721                         codegen_addxstorerefs(cd, mcodeptr);
1722
1723                         var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1724                         var_to_reg_int(s2, src->prev, REG_ITMP2);
1725                         var_to_reg_int(s3, src, REG_ITMP3);
1726                         M_SLL_IMM(s2, 2, REG_ITMP2);
1727                         M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1728                         M_STWX(s3, s1, REG_ITMP2);
1729                         break;
1730
1731
1732                 case ICMD_GETSTATIC:  /* ...  ==> ..., value                          */
1733                                       /* op1 = type, val.a = field address            */
1734
1735                         if (!iptr->val.a) {
1736                                 disp = dseg_addaddress(cd, NULL);
1737
1738                                 codegen_addpatchref(cd, mcodeptr,
1739                                                                         PATCHER_get_putstatic,
1740                                                                         (unresolved_field *) iptr->target, disp);
1741
1742                                 if (opt_showdisassemble)
1743                                         M_NOP;
1744
1745                         } else {
1746                                 fieldinfo *fi = iptr->val.a;
1747
1748                                 disp = dseg_addaddress(cd, &(fi->value));
1749
1750                                 if (!fi->class->initialized) {
1751                                         codegen_addpatchref(cd, mcodeptr,
1752                                                                                 PATCHER_clinit, fi->class, disp);
1753
1754                                         if (opt_showdisassemble)
1755                                                 M_NOP;
1756                                 }
1757                         }
1758
1759                         M_ALD(REG_ITMP1, REG_PV, disp);
1760                         switch (iptr->op1) {
1761                         case TYPE_INT:
1762                                 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1763                                 M_ILD_INTERN(d, REG_ITMP1, 0);
1764                                 store_reg_to_var_int(iptr->dst, d);
1765                                 break;
1766                         case TYPE_LNG:
1767                                 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
1768                                 M_ILD_INTERN(GET_LOW_REG(d), REG_ITMP1, 4);/* keep this order */
1769                                 M_ILD_INTERN(GET_HIGH_REG(d), REG_ITMP1, 0);/*keep this order */
1770                                 store_reg_to_var_int(iptr->dst, d);
1771                                 break;
1772                         case TYPE_ADR:
1773                                 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1774                                 M_ALD_INTERN(d, REG_ITMP1, 0);
1775                                 store_reg_to_var_int(iptr->dst, d);
1776                                 break;
1777                         case TYPE_FLT:
1778                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1779                                 M_FLD_INTERN(d, REG_ITMP1, 0);
1780                                 store_reg_to_var_flt(iptr->dst, d);
1781                                 break;
1782                         case TYPE_DBL:                          
1783                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1784                                 M_DLD_INTERN(d, REG_ITMP1, 0);
1785                                 store_reg_to_var_flt(iptr->dst, d);
1786                                 break;
1787                         }
1788                         break;
1789
1790                 case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
1791                                       /* op1 = type, val.a = field address            */
1792
1793
1794                         if (!iptr->val.a) {
1795                                 disp = dseg_addaddress(cd, NULL);
1796
1797                                 codegen_addpatchref(cd, mcodeptr,
1798                                                                         PATCHER_get_putstatic,
1799                                                                         (unresolved_field *) iptr->target, disp);
1800
1801                                 if (opt_showdisassemble)
1802                                         M_NOP;
1803
1804                         } else {
1805                                 fieldinfo *fi = iptr->val.a;
1806
1807                                 disp = dseg_addaddress(cd, &(fi->value));
1808
1809                                 if (!fi->class->initialized) {
1810                                         codegen_addpatchref(cd, mcodeptr,
1811                                                                                 PATCHER_clinit, fi->class, disp);
1812
1813                                         if (opt_showdisassemble)
1814                                                 M_NOP;
1815                                 }
1816                         }
1817
1818                         M_ALD(REG_ITMP1, REG_PV, disp);
1819                         switch (iptr->op1) {
1820                         case TYPE_INT:
1821                                 var_to_reg_int(s2, src, REG_ITMP2);
1822                                 M_IST_INTERN(s2, REG_ITMP1, 0);
1823                                 break;
1824                         case TYPE_LNG:
1825                                 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1826                                 M_IST_INTERN(GET_HIGH_REG(s2), REG_ITMP1, 0);
1827                                 M_IST_INTERN(GET_LOW_REG(s2), REG_ITMP1, 4);
1828                                 break;
1829                         case TYPE_ADR:
1830                                 var_to_reg_int(s2, src, REG_ITMP2);
1831                                 M_AST_INTERN(s2, REG_ITMP1, 0);
1832                                 break;
1833                         case TYPE_FLT:
1834                                 var_to_reg_flt(s2, src, REG_FTMP2);
1835                                 M_FST_INTERN(s2, REG_ITMP1, 0);
1836                                 break;
1837                         case TYPE_DBL:
1838                                 var_to_reg_flt(s2, src, REG_FTMP2);
1839                                 M_DST_INTERN(s2, REG_ITMP1, 0);
1840                                 break;
1841                         }
1842                         break;
1843
1844
1845                 case ICMD_GETFIELD:   /* ...  ==> ..., value                          */
1846                                       /* op1 = type, val.i = field offset             */
1847
1848                         var_to_reg_int(s1, src, REG_ITMP1);
1849                         gen_nullptr_check(s1);
1850
1851                         if (!iptr->val.a) {
1852                                 codegen_addpatchref(cd, mcodeptr,
1853                                                                         PATCHER_get_putfield,
1854                                                                         (unresolved_field *) iptr->target, 0);
1855
1856                                 if (opt_showdisassemble)
1857                                         M_NOP;
1858
1859                                 disp = 0;
1860
1861                         } else {
1862                                 disp = ((fieldinfo *) (iptr->val.a))->offset;
1863                         }
1864
1865                         switch (iptr->op1) {
1866                         case TYPE_INT:
1867                                 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1868                                 M_ILD(d, s1, disp);
1869                                 store_reg_to_var_int(iptr->dst, d);
1870                                 break;
1871                         case TYPE_LNG:
1872                                 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
1873                                 M_ILD(GET_LOW_REG(d), s1, disp + 4);       /* keep this order */
1874                                 M_ILD(GET_HIGH_REG(d), s1, disp);          /* keep this order */
1875                                 store_reg_to_var_int(iptr->dst, d);
1876                                 break;
1877                         case TYPE_ADR:
1878                                 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
1879                                 M_ALD(d, s1, disp);
1880                                 store_reg_to_var_int(iptr->dst, d);
1881                                 break;
1882                         case TYPE_FLT:
1883                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1884                                 M_FLD(d, s1, disp);
1885                                 store_reg_to_var_flt(iptr->dst, d);
1886                                 break;
1887                         case TYPE_DBL:                          
1888                                 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1889                                 M_DLD(d, s1, disp);
1890                                 store_reg_to_var_flt(iptr->dst, d);
1891                                 break;
1892                         }
1893                         break;
1894
1895                 case ICMD_PUTFIELD:   /* ..., value  ==> ...                          */
1896                                       /* op1 = type, val.i = field offset             */
1897
1898                         var_to_reg_int(s1, src->prev, REG_ITMP1);
1899                         gen_nullptr_check(s1);
1900
1901                         if (!IS_FLT_DBL_TYPE(iptr->op1)) {
1902                                 if (IS_2_WORD_TYPE(iptr->op1)) {
1903                                         var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1904                                 } else {
1905                                         var_to_reg_int(s2, src, REG_ITMP2);
1906                                 }
1907                         } else {
1908                                 var_to_reg_flt(s2, src, REG_FTMP2);
1909                         }
1910
1911                         if (!iptr->val.a) {
1912                                 codegen_addpatchref(cd, mcodeptr,
1913                                                                         PATCHER_get_putfield,
1914                                                                         (unresolved_field *) iptr->target, 0);
1915
1916                                 if (opt_showdisassemble)
1917                                         M_NOP;
1918
1919                                 disp = 0;
1920
1921                         } else {
1922                                 disp = ((fieldinfo *) (iptr->val.a))->offset;
1923                         }
1924
1925                         switch (iptr->op1) {
1926                         case TYPE_INT:
1927                                 M_IST(s2, s1, disp);
1928                                 break;
1929                         case TYPE_LNG:
1930                                 M_IST(GET_LOW_REG(s2), s1, disp + 4);      /* keep this order */
1931                                 M_IST(GET_HIGH_REG(s2), s1, disp);         /* keep this order */
1932                                 break;
1933                         case TYPE_ADR:
1934                                 M_AST(s2, s1, disp);
1935                                 break;
1936                         case TYPE_FLT:
1937                                 M_FST(s2, s1, disp);
1938                                 break;
1939                         case TYPE_DBL:
1940                                 M_DST(s2, s1, disp);
1941                                 break;
1942                         }
1943                         break;
1944
1945
1946                 /* branch operations **************************************************/
1947
1948                 case ICMD_ATHROW:       /* ..., objectref ==> ... (, objectref)       */
1949
1950                         var_to_reg_int(s1, src, REG_ITMP1);
1951                         M_INTMOVE(s1, REG_ITMP1_XPTR);
1952
1953                         if (iptr->val.a) {
1954                                 codegen_addpatchref(cd, mcodeptr,
1955                                                                         PATCHER_athrow_areturn,
1956                                                                         (unresolved_class *) iptr->val.a, 0);
1957
1958                                 if (opt_showdisassemble)
1959                                         M_NOP;
1960                         }
1961
1962                         disp = dseg_addaddress(cd, asm_handle_exception);
1963                         M_ALD(REG_ITMP2, REG_PV, disp);
1964                         M_MTCTR(REG_ITMP2);
1965
1966                         if (m->isleafmethod) M_MFLR(REG_ITMP3);         /* save LR        */
1967                         M_BL(0);                                        /* get current PC */
1968                         M_MFLR(REG_ITMP2_XPC);
1969                         if (m->isleafmethod) M_MTLR(REG_ITMP3);         /* restore LR     */
1970                         M_RTS;                                          /* jump to CTR    */
1971
1972                         ALIGNCODENOP;
1973                         break;
1974
1975                 case ICMD_GOTO:         /* ... ==> ...                                */
1976                                         /* op1 = target JavaVM pc                     */
1977                         M_BR(0);
1978                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1979                         ALIGNCODENOP;
1980                         break;
1981
1982                 case ICMD_JSR:          /* ... ==> ...                                */
1983                                         /* op1 = target JavaVM pc                     */
1984
1985                         if (m->isleafmethod) M_MFLR(REG_ITMP2);
1986                         M_BL(0);
1987                         M_MFLR(REG_ITMP1);
1988                         M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
1989                         if (m->isleafmethod) M_MTLR(REG_ITMP2);
1990                         M_BR(0);
1991                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1992                         break;
1993                         
1994                 case ICMD_RET:          /* ... ==> ...                                */
1995                                         /* op1 = local variable                       */
1996
1997                         var = &(rd->locals[iptr->op1][TYPE_ADR]);
1998                         if (var->flags & INMEMORY) {
1999                                 M_ALD(REG_ITMP1, REG_SP, var->regoff * 4);
2000                                 M_MTCTR(REG_ITMP1);
2001                         } else {
2002                                 M_MTCTR(var->regoff);
2003                         }
2004                         M_RTS;
2005                         ALIGNCODENOP;
2006                         break;
2007
2008                 case ICMD_IFNULL:       /* ..., value ==> ...                         */
2009                                         /* op1 = target JavaVM pc                     */
2010
2011                         var_to_reg_int(s1, src, REG_ITMP1);
2012                         M_TST(s1);
2013                         M_BEQ(0);
2014                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2015                         break;
2016
2017                 case ICMD_IFNONNULL:    /* ..., value ==> ...                         */
2018                                         /* op1 = target JavaVM pc                     */
2019
2020                         var_to_reg_int(s1, src, REG_ITMP1);
2021                         M_TST(s1);
2022                         M_BNE(0);
2023                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2024                         break;
2025
2026                 case ICMD_IFLT:
2027                 case ICMD_IFLE:
2028                 case ICMD_IFNE:
2029                 case ICMD_IFGT:
2030                 case ICMD_IFGE:
2031                 case ICMD_IFEQ:         /* ..., value ==> ...                         */
2032                                         /* op1 = target JavaVM pc, val.i = constant   */
2033
2034                         var_to_reg_int(s1, src, REG_ITMP1);
2035                         if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2036                                 M_CMPI(s1, iptr->val.i);
2037                         } else {
2038                                 ICONST(REG_ITMP2, iptr->val.i);
2039                                 M_CMP(s1, REG_ITMP2);
2040                         }
2041                         switch (iptr->opc) {
2042                         case ICMD_IFLT:
2043                                 M_BLT(0);
2044                                 break;
2045                         case ICMD_IFLE:
2046                                 M_BLE(0);
2047                                 break;
2048                         case ICMD_IFNE:
2049                                 M_BNE(0);
2050                                 break;
2051                         case ICMD_IFGT:
2052                                 M_BGT(0);
2053                                 break;
2054                         case ICMD_IFGE:
2055                                 M_BGE(0);
2056                                 break;
2057                         case ICMD_IFEQ:
2058                                 M_BEQ(0);
2059                                 break;
2060                         }
2061                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2062                         break;
2063
2064
2065                 case ICMD_IF_LEQ:       /* ..., value ==> ...                         */
2066                                         /* op1 = target JavaVM pc, val.l = constant   */
2067
2068                         var_to_reg_int_low(s1, src, REG_ITMP1);
2069                         var_to_reg_int_high(s2, src, REG_ITMP2);
2070                         if (iptr->val.l == 0) {
2071                                 M_OR(s1, s2, REG_ITMP3);
2072                                 M_CMPI(REG_ITMP3, 0);
2073                         } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2074                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2075                                 M_BNE(2);
2076                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2077                         } else {
2078                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2079                                 M_CMP(s2, REG_ITMP3);
2080                                 M_BNE(3);
2081                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2082                                 M_CMP(s1, REG_ITMP3)
2083                         }
2084                         M_BEQ(0);
2085                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2086                         break;
2087                         
2088                 case ICMD_IF_LLT:       /* ..., value ==> ...                         */
2089                                         /* op1 = target JavaVM pc, val.l = constant   */
2090                         var_to_reg_int_low(s1, src, REG_ITMP1);
2091                         var_to_reg_int_high(s2, src, REG_ITMP2);
2092 /*                      if (iptr->val.l == 0) { */
2093 /*                              M_OR(s1, s2, REG_ITMP3); */
2094 /*                              M_CMPI(REG_ITMP3, 0); */
2095
2096 /*                      } else  */
2097                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2098                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2099                                 M_BLT(0);
2100                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2101                                 M_BGT(2);
2102                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2103                         } else {
2104                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2105                                 M_CMP(s2, REG_ITMP3);
2106                                 M_BLT(0);
2107                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2108                                 M_BGT(3);
2109                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2110                                 M_CMP(s1, REG_ITMP3)
2111                         }
2112                         M_BLT(0);
2113                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2114                         break;
2115                         
2116                 case ICMD_IF_LLE:       /* ..., value ==> ...                         */
2117                                         /* op1 = target JavaVM pc, val.l = constant   */
2118
2119                         var_to_reg_int_low(s1, src, REG_ITMP1);
2120                         var_to_reg_int_high(s2, src, REG_ITMP2);
2121 /*                      if (iptr->val.l == 0) { */
2122 /*                              M_OR(s1, s2, REG_ITMP3); */
2123 /*                              M_CMPI(REG_ITMP3, 0); */
2124
2125 /*                      } else  */
2126                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2127                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2128                                 M_BLT(0);
2129                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2130                                 M_BGT(2);
2131                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2132                         } else {
2133                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2134                                 M_CMP(s2, REG_ITMP3);
2135                                 M_BLT(0);
2136                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2137                                 M_BGT(3);
2138                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2139                                 M_CMP(s1, REG_ITMP3)
2140                         }
2141                         M_BLE(0);
2142                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2143                         break;
2144                         
2145                 case ICMD_IF_LNE:       /* ..., value ==> ...                         */
2146                                         /* op1 = target JavaVM pc, val.l = constant   */
2147
2148                         var_to_reg_int_low(s1, src, REG_ITMP1);
2149                         var_to_reg_int_high(s2, src, REG_ITMP2);
2150                         if (iptr->val.l == 0) {
2151                                 M_OR(s1, s2, REG_ITMP3);
2152                                 M_CMPI(REG_ITMP3, 0);
2153                         } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2154                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2155                                 M_BEQ(2);
2156                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2157                         } else {
2158                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2159                                 M_CMP(s2, REG_ITMP3);
2160                                 M_BEQ(3);
2161                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2162                                 M_CMP(s1, REG_ITMP3)
2163                         }
2164                         M_BNE(0);
2165                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2166                         break;
2167                         
2168                 case ICMD_IF_LGT:       /* ..., value ==> ...                         */
2169                                         /* op1 = target JavaVM pc, val.l = constant   */
2170
2171                         var_to_reg_int_low(s1, src, REG_ITMP1);
2172                         var_to_reg_int_high(s2, src, REG_ITMP2);
2173 /*                      if (iptr->val.l == 0) { */
2174 /*                              M_OR(s1, s2, REG_ITMP3); */
2175 /*                              M_CMPI(REG_ITMP3, 0); */
2176
2177 /*                      } else  */
2178                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2179                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2180                                 M_BGT(0);
2181                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2182                                 M_BLT(2);
2183                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2184                         } else {
2185                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2186                                 M_CMP(s2, REG_ITMP3);
2187                                 M_BGT(0);
2188                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2189                                 M_BLT(3);
2190                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2191                                 M_CMP(s1, REG_ITMP3)
2192                         }
2193                         M_BGT(0);
2194                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2195                         break;
2196                         
2197                 case ICMD_IF_LGE:       /* ..., value ==> ...                         */
2198                                         /* op1 = target JavaVM pc, val.l = constant   */
2199                         var_to_reg_int_low(s1, src, REG_ITMP1);
2200                         var_to_reg_int_high(s2, src, REG_ITMP2);
2201 /*                      if (iptr->val.l == 0) { */
2202 /*                              M_OR(s1, s2, REG_ITMP3); */
2203 /*                              M_CMPI(REG_ITMP3, 0); */
2204
2205 /*                      } else  */
2206                         if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2207                                 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2208                                 M_BGT(0);
2209                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2210                                 M_BLT(2);
2211                                 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2212                         } else {
2213                                 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2214                                 M_CMP(s2, REG_ITMP3);
2215                                 M_BGT(0);
2216                                 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2217                                 M_BLT(3);
2218                                 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2219                                 M_CMP(s1, REG_ITMP3)
2220                         }
2221                         M_BGE(0);
2222                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2223                         break;
2224
2225                         /* CUT: alle _L */
2226                 case ICMD_IF_ICMPEQ:    /* ..., value, value ==> ...                  */
2227                 case ICMD_IF_LCMPEQ:    /* op1 = target JavaVM pc                     */
2228                         /******************************************************************
2229             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2230                         *******************************************************************/
2231                 case ICMD_IF_ACMPEQ:
2232
2233                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2234                         var_to_reg_int(s2, src, REG_ITMP2);
2235                         M_CMP(s1, s2);
2236                         M_BEQ(0);
2237                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2238                         break;
2239
2240                 case ICMD_IF_ICMPNE:    /* ..., value, value ==> ...                  */
2241                 case ICMD_IF_LCMPNE:    /* op1 = target JavaVM pc                     */
2242                         /******************************************************************
2243             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2244                         *******************************************************************/
2245                 case ICMD_IF_ACMPNE:
2246
2247                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2248                         var_to_reg_int(s2, src, REG_ITMP2);
2249                         M_CMP(s1, s2);
2250                         M_BNE(0);
2251                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2252                         break;
2253
2254                 case ICMD_IF_ICMPLT:    /* ..., value, value ==> ...                  */
2255                 case ICMD_IF_LCMPLT:    /* op1 = target JavaVM pc                     */
2256                         /******************************************************************
2257             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2258                         *******************************************************************/
2259
2260                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2261                         var_to_reg_int(s2, src, REG_ITMP2);
2262                         M_CMP(s1, s2);
2263                         M_BLT(0);
2264                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2265                         break;
2266
2267                 case ICMD_IF_ICMPGT:    /* ..., value, value ==> ...                  */
2268                 case ICMD_IF_LCMPGT:    /* op1 = target JavaVM pc                     */
2269                         /******************************************************************
2270             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2271                         *******************************************************************/
2272
2273                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2274                         var_to_reg_int(s2, src, REG_ITMP2);
2275                         M_CMP(s1, s2);
2276                         M_BGT(0);
2277                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2278                         break;
2279
2280                 case ICMD_IF_ICMPLE:    /* ..., value, value ==> ...                  */
2281                 case ICMD_IF_LCMPLE:    /* op1 = target JavaVM pc                     */
2282                         /******************************************************************
2283             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2284                         *******************************************************************/
2285
2286                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2287                         var_to_reg_int(s2, src, REG_ITMP2);
2288                         M_CMP(s1, s2);
2289                         M_BLE(0);
2290                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2291                         break;
2292
2293                 case ICMD_IF_ICMPGE:    /* ..., value, value ==> ...                  */
2294                 case ICMD_IF_LCMPGE:    /* op1 = target JavaVM pc                     */
2295                         /******************************************************************
2296             TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2297                         *******************************************************************/
2298
2299                         var_to_reg_int(s1, src->prev, REG_ITMP1);
2300                         var_to_reg_int(s2, src, REG_ITMP2);
2301                         M_CMP(s1, s2);
2302                         M_BGE(0);
2303                         codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2304                         break;
2305
2306                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
2307
2308                         var_to_reg_int(s1, src, REG_RESULT);
2309                         M_TINTMOVE(src->type, s1, REG_RESULT);
2310                         goto nowperformreturn;
2311
2312                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
2313
2314                         var_to_reg_int(s1, src, REG_RESULT);
2315                         M_TINTMOVE(src->type, s1, REG_RESULT);
2316
2317                         if (iptr->val.a) {
2318                                 codegen_addpatchref(cd, mcodeptr,
2319                                                                         PATCHER_athrow_areturn,
2320                                                                         (unresolved_class *) iptr->val.a, 0);
2321
2322                                 if (opt_showdisassemble)
2323                                         M_NOP;
2324                         }
2325                         goto nowperformreturn;
2326
2327                 case ICMD_LRETURN:      /* ..., retvalue ==> ...                      */
2328
2329                         var_to_reg_int(s1, src, PACK_REGS(REG_RESULT2, REG_RESULT));
2330                         M_TINTMOVE(src->type, s1, PACK_REGS(REG_RESULT2, REG_RESULT));
2331                         goto nowperformreturn;
2332
2333                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
2334                 case ICMD_DRETURN:
2335
2336                         var_to_reg_flt(s1, src, REG_FRESULT);
2337                         M_FLTMOVE(s1, REG_FRESULT);
2338                         goto nowperformreturn;
2339
2340                 case ICMD_RETURN:      /* ...  ==> ...                                */
2341
2342 nowperformreturn:
2343                         {
2344                         s4 i, p;
2345                         
2346                         p = parentargs_base;
2347
2348                         /* call trace function */
2349
2350                         if (runverbose) {
2351                                 M_MFLR(REG_ZERO);
2352                                 M_LDA(REG_SP, REG_SP, -10 * 8);
2353                                 M_DST(REG_FRESULT, REG_SP, 48+0);
2354                                 M_IST(REG_RESULT, REG_SP, 48+8);
2355                                 M_AST(REG_ZERO, REG_SP, 48+12);
2356                                 M_IST(REG_RESULT2, REG_SP, 48+16);
2357
2358                                 /* keep this order */
2359                                 switch (iptr->opc) {
2360                                 case ICMD_IRETURN:
2361                                 case ICMD_ARETURN:
2362 #if defined(__DARWIN__)
2363                                         M_MOV(REG_RESULT, rd->argintregs[2]);
2364                                         M_CLR(rd->argintregs[1]);
2365 #else
2366                                         M_MOV(REG_RESULT, rd->argintregs[3]);
2367                                         M_CLR(rd->argintregs[2]);
2368 #endif
2369                                         break;
2370
2371                                 case ICMD_LRETURN:
2372 #if defined(__DARWIN__)
2373                                         M_MOV(REG_RESULT2, rd->argintregs[2]);
2374                                         M_MOV(REG_RESULT, rd->argintregs[1]);
2375 #else
2376                                         M_MOV(REG_RESULT2, rd->argintregs[3]);
2377                                         M_MOV(REG_RESULT, rd->argintregs[2]);
2378 #endif
2379                                         break;
2380                                 }
2381
2382                                 disp = dseg_addaddress(cd, m);
2383                                 M_ALD(rd->argintregs[0], REG_PV, disp);
2384
2385                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2386                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2387                                 disp = dseg_addaddress(cd, builtin_displaymethodstop);
2388                                 M_ALD(REG_ITMP2, REG_PV, disp);
2389                                 M_MTCTR(REG_ITMP2);
2390                                 M_JSR;
2391
2392                                 M_DLD(REG_FRESULT, REG_SP, 48+0);
2393                                 M_ILD(REG_RESULT, REG_SP, 48+8);
2394                                 M_ALD(REG_ZERO, REG_SP, 48+12);
2395                                 M_ILD(REG_RESULT2, REG_SP, 48+16);
2396                                 M_LDA(REG_SP, REG_SP, 10 * 8);
2397                                 M_MTLR(REG_ZERO);
2398                         }
2399                         
2400 #if defined(USE_THREADS)
2401                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2402                                 /* we need to save the proper return value */
2403                                 switch (iptr->opc) {
2404                                 case ICMD_LRETURN:
2405                                         M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2406                                         /* fall through */
2407                                 case ICMD_IRETURN:
2408                                 case ICMD_ARETURN:
2409                                         M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2410                                         break;
2411                                 case ICMD_FRETURN:
2412                                         M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2413                                         break;
2414                                 case ICMD_DRETURN:
2415                                         M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2416                                         break;
2417                                 }
2418
2419                                 disp = dseg_addaddress(cd, BUILTIN_monitorexit);
2420                                 M_ALD(REG_ITMP3, REG_PV, disp);
2421                                 M_MTCTR(REG_ITMP3);
2422                                 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 4);
2423                                 M_JSR;
2424
2425                                 /* and now restore the proper return value */
2426                                 switch (iptr->opc) {
2427                                 case ICMD_LRETURN:
2428                                         M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2429                                         /* fall through */
2430                                 case ICMD_IRETURN:
2431                                 case ICMD_ARETURN:
2432                                         M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2433                                         break;
2434                                 case ICMD_FRETURN:
2435                                         M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2436                                         break;
2437                                 case ICMD_DRETURN:
2438                                         M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2439                                         break;
2440                                 }
2441                         }
2442 #endif
2443
2444                         /* restore return address                                         */
2445
2446                         if (!m->isleafmethod) {
2447                                 M_ALD(REG_ZERO, REG_SP, p * 4 + LA_LR_OFFSET);
2448                                 M_MTLR(REG_ZERO);
2449                         }
2450
2451                         /* restore saved registers                                        */
2452
2453                         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2454                                 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2455                         }
2456                         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2457                                 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2458                         }
2459
2460                         /* deallocate stack                                               */
2461
2462                         if (parentargs_base)
2463                                 M_LDA(REG_SP, REG_SP, parentargs_base * 4);
2464
2465                         M_RET;
2466                         ALIGNCODENOP;
2467                         }
2468                         break;
2469
2470
2471                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2472                         {
2473                         s4 i, l, *s4ptr;
2474                         void **tptr;
2475
2476                         tptr = (void **) iptr->target;
2477
2478                         s4ptr = iptr->val.a;
2479                         l = s4ptr[1];                          /* low     */
2480                         i = s4ptr[2];                          /* high    */
2481                         
2482                         var_to_reg_int(s1, src, REG_ITMP1);
2483                         if (l == 0) {
2484                                 M_INTMOVE(s1, REG_ITMP1);
2485                         } else if (l <= 32768) {
2486                                 M_LDA(REG_ITMP1, s1, -l);
2487                         } else {
2488                                 ICONST(REG_ITMP2, l);
2489                                 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2490                         }
2491                         i = i - l + 1;
2492
2493                         /* range check */
2494
2495                         M_CMPUI(REG_ITMP1, i - 1);
2496                         M_BGT(0);
2497                         codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2498
2499                         /* build jump table top down and use address of lowest entry */
2500
2501                         /* s4ptr += 3 + i; */
2502                         tptr += i;
2503
2504                         while (--i >= 0) {
2505                                 dseg_addtarget(cd, (basicblock *) tptr[0]); 
2506                                 --tptr;
2507                         }
2508                         }
2509
2510                         /* length of dataseg after last dseg_addtarget is used by load */
2511
2512                         M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2513                         M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2514                         M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2515                         M_MTCTR(REG_ITMP2);
2516                         M_RTS;
2517                         ALIGNCODENOP;
2518                         break;
2519
2520
2521                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
2522                         {
2523                         s4 i, l, val, *s4ptr;
2524                         void **tptr;
2525
2526                         tptr = (void **) iptr->target;
2527
2528                         s4ptr = iptr->val.a;
2529                         l = s4ptr[0];                          /* default  */
2530                         i = s4ptr[1];                          /* count    */
2531                         
2532                         MCODECHECK((i<<2)+8);
2533                         var_to_reg_int(s1, src, REG_ITMP1);
2534                         while (--i >= 0) {
2535                                 s4ptr += 2;
2536                                 ++tptr;
2537
2538                                 val = s4ptr[0];
2539                                 if ((val >= -32768) && (val <= 32767)) {
2540                                         M_CMPI(s1, val);
2541                                 } else {
2542                                         a = dseg_adds4(cd, val);
2543                                         M_ILD(REG_ITMP2, REG_PV, a);
2544                                         M_CMP(s1, REG_ITMP2);
2545                                 }
2546                                 M_BEQ(0);
2547                                 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr); 
2548                         }
2549
2550                         M_BR(0);
2551                         tptr = (void **) iptr->target;
2552                         codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2553
2554                         ALIGNCODENOP;
2555                         break;
2556                         }
2557
2558
2559                 case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
2560                                         /* op1 = arg count val.a = builtintable entry */
2561
2562                         bte = iptr->val.a;
2563                         md = bte->md;
2564                         goto gen_method;
2565
2566                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2567                                         /* op1 = arg count, val.a = method pointer    */
2568
2569                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2570                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
2571                 case ICMD_INVOKEINTERFACE:
2572
2573                         lm = iptr->val.a;
2574
2575                         if (lm)
2576                                 md = lm->parseddesc;
2577                         else {
2578                                 unresolved_method *um = iptr->target;
2579                                 md = um->methodref->parseddesc.md;
2580                         }
2581
2582 gen_method:
2583                         s3 = md->paramcount;
2584
2585                         MCODECHECK((s3 << 1) + 64);
2586
2587                         /* copy arguments to registers or stack location */
2588
2589                         for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2590                                 if (src->varkind == ARGVAR)
2591                                         continue;
2592                                 if (IS_INT_LNG_TYPE(src->type)) {
2593                                         if (!md->params[s3].inmemory) {
2594                                                 if (IS_2_WORD_TYPE(src->type)) {
2595                                                         s1 = PACK_REGS(
2596                                                    rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2597                                                    rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]);
2598                                                 } else {
2599                                                         s1 = rd->argintregs[md->params[s3].regoff];
2600                                                 }
2601                                                 var_to_reg_int(d, src, s1);
2602                                                 M_TINTMOVE(src->type, d, s1);
2603                                         } else {
2604                                                 var_to_reg_int(d, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
2605                                                 M_IST(GET_HIGH_REG(d), REG_SP,
2606                                                           md->params[s3].regoff * 4);
2607                                                 if (IS_2_WORD_TYPE(src->type)) {
2608                                                         M_IST(GET_LOW_REG(d), 
2609                                                                   REG_SP, md->params[s3].regoff * 4 + 4);
2610                                                 }
2611                                         }
2612                                                 
2613                                 } else {
2614                                         if (!md->params[s3].inmemory) {
2615                                                 s1 = rd->argfltregs[md->params[s3].regoff];
2616                                                 var_to_reg_flt(d, src, s1);
2617                                                 M_FLTMOVE(d, s1);
2618                                         } else {
2619                                                 var_to_reg_flt(d, src, REG_FTMP1);
2620                                                 if (IS_2_WORD_TYPE(src->type)) {
2621                                                         M_DST(d, REG_SP, md->params[s3].regoff * 4);
2622                                                 } else {
2623                                                         M_FST(d, REG_SP, md->params[s3].regoff * 4);
2624                                                 }
2625                                         }
2626                                 }
2627                         } /* end of for */
2628
2629                         switch (iptr->opc) {
2630                         case ICMD_BUILTIN:
2631                                 if (iptr->target) {
2632                                         disp = dseg_addaddress(cd, NULL);
2633
2634                                         codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target,
2635                                                                                 disp);
2636
2637                                         if (opt_showdisassemble)
2638                                                 M_NOP;
2639
2640                                 } else {
2641                                         disp = dseg_addaddress(cd, bte->fp);
2642                                 }
2643
2644                                 d = md->returntype.type;
2645
2646                                 M_ALD(REG_PV, REG_PV, disp);  /* pointer to built-in-function */
2647                                 M_MTCTR(REG_PV);
2648                                 M_JSR;
2649                                 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2650                                 M_MFLR(REG_ITMP1);
2651                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2652
2653                                 /* if op1 == true, we need to check for an exception */
2654
2655                                 if (iptr->op1 == true) {
2656                                         M_CMPI(REG_RESULT, 0);
2657                                         M_BEQ(0);
2658                                         codegen_addxexceptionrefs(cd, mcodeptr);
2659                                 }
2660                                 break;
2661
2662                         case ICMD_INVOKESPECIAL:
2663                                 gen_nullptr_check(rd->argintregs[0]);
2664                                 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr   */
2665                                 /* fall through */
2666
2667                         case ICMD_INVOKESTATIC:
2668                                 if (!lm) {
2669                                         unresolved_method *um = iptr->target;
2670
2671                                         disp = dseg_addaddress(cd, NULL);
2672
2673                                         codegen_addpatchref(cd, mcodeptr,
2674                                                                                 PATCHER_invokestatic_special, um, disp);
2675
2676                                         if (opt_showdisassemble)
2677                                                 M_NOP;
2678
2679                                         d = md->returntype.type;
2680
2681                                 } else {
2682                                         disp = dseg_addaddress(cd, lm->stubroutine);
2683                                         d = md->returntype.type;
2684                                 }
2685
2686                                 M_ALD(REG_PV, REG_PV, disp);
2687                                 M_MTCTR(REG_PV);
2688                                 M_JSR;
2689                                 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2690                                 M_MFLR(REG_ITMP1);
2691                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2692                                 break;
2693
2694                         case ICMD_INVOKEVIRTUAL:
2695                                 gen_nullptr_check(rd->argintregs[0]);
2696
2697                                 if (!lm) {
2698                                         unresolved_method *um = iptr->target;
2699
2700                                         codegen_addpatchref(cd, mcodeptr,
2701                                                                                 PATCHER_invokevirtual, um, 0);
2702
2703                                         if (opt_showdisassemble)
2704                                                 M_NOP;
2705
2706                                         s1 = 0;
2707                                         d = md->returntype.type;
2708
2709                                 } else {
2710                                         s1 = OFFSET(vftbl_t, table[0]) +
2711                                                 sizeof(methodptr) * lm->vftblindex;
2712                                         d = md->returntype.type;
2713                                 }
2714
2715                                 M_ALD(REG_METHODPTR, rd->argintregs[0],
2716                                           OFFSET(java_objectheader, vftbl));
2717                                 M_ALD(REG_PV, REG_METHODPTR, s1);
2718                                 M_MTCTR(REG_PV);
2719                                 M_JSR;
2720                                 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2721                                 M_MFLR(REG_ITMP1);
2722                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2723                                 break;
2724
2725                         case ICMD_INVOKEINTERFACE:
2726                                 gen_nullptr_check(rd->argintregs[0]);
2727
2728                                 if (!lm) {
2729                                         unresolved_method *um = iptr->target;
2730
2731                                         codegen_addpatchref(cd, mcodeptr,
2732                                                                                 PATCHER_invokeinterface, um, 0);
2733
2734                                         if (opt_showdisassemble)
2735                                                 M_NOP;
2736
2737                                         s1 = 0;
2738                                         s2 = 0;
2739                                         d = md->returntype.type;
2740
2741                                 } else {
2742                                         s1 = OFFSET(vftbl_t, interfacetable[0]) -
2743                                                 sizeof(methodptr*) * lm->class->index;
2744
2745                                         s2 = sizeof(methodptr) * (lm - lm->class->methods);
2746
2747                                         d = md->returntype.type;
2748                                 }
2749
2750                                 M_ALD(REG_METHODPTR, rd->argintregs[0],
2751                                           OFFSET(java_objectheader, vftbl));    
2752                                 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2753                                 M_ALD(REG_PV, REG_METHODPTR, s2);
2754                                 M_MTCTR(REG_PV);
2755                                 M_JSR;
2756                                 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2757                                 M_MFLR(REG_ITMP1);
2758                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2759                                 break;
2760                         }
2761
2762                         /* d contains return type */
2763
2764                         if (d != TYPE_VOID) {
2765                                 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2766                                         if (IS_2_WORD_TYPE(iptr->dst->type)) {
2767                                                 s1 = reg_of_var(rd, iptr->dst,
2768                                                                                 PACK_REGS(REG_RESULT2, REG_RESULT));
2769                                                 M_TINTMOVE(iptr->dst->type,
2770                                                                    PACK_REGS(REG_RESULT2, REG_RESULT), s1);
2771                                         } else {
2772                                                 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2773                                                 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2774                                         }
2775                                         store_reg_to_var_int(iptr->dst, s1);
2776
2777                                 } else {
2778                                         s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2779                                         M_FLTMOVE(REG_FRESULT, s1);
2780                                         store_reg_to_var_flt(iptr->dst, s1);
2781                                 }
2782                         }
2783                         break;
2784
2785
2786                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
2787                                       /* val.a: (classinfo*) superclass               */
2788
2789                         /*  superclass is an interface:
2790                          *
2791                          *  OK if ((sub == NULL) ||
2792                          *         (sub->vftbl->interfacetablelength > super->index) &&
2793                          *         (sub->vftbl->interfacetable[-super->index] != NULL));
2794                          *
2795                          *  superclass is a class:
2796                          *
2797                          *  OK if ((sub == NULL) || (0
2798                          *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2799                          *         super->vftbl->diffvall));
2800                          */
2801
2802                         {
2803                         classinfo *super;
2804                         vftbl_t   *supervftbl;
2805                         s4         superindex;
2806
2807                         super = (classinfo *) iptr->val.a;
2808
2809                         if (!super) {
2810                                 superindex = 0;
2811                                 supervftbl = NULL;
2812
2813                         } else {
2814                                 superindex = super->index;
2815                                 supervftbl = super->vftbl;
2816                         }
2817                         
2818 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2819                         codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2820 #endif
2821                         var_to_reg_int(s1, src, REG_ITMP1);
2822
2823                         /* calculate interface checkcast code size */
2824
2825                         s2 = 7;
2826                         if (!super)
2827                                 s2 += (opt_showdisassemble ? 1 : 0);
2828
2829                         /* calculate class checkcast code size */
2830
2831                         s3 = 8 + (s1 == REG_ITMP1);
2832                         if (!super)
2833                                 s3 += (opt_showdisassemble ? 1 : 0);
2834
2835                         /* if class is not resolved, check which code to call */
2836
2837                         if (!super) {
2838                                 M_TST(s1);
2839                                 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
2840
2841                                 disp = dseg_adds4(cd, 0);                     /* super->flags */
2842
2843                                 codegen_addpatchref(cd, mcodeptr,
2844                                                                         PATCHER_checkcast_instanceof_flags,
2845                                                                         (constant_classref *) iptr->target, disp);
2846
2847                                 if (opt_showdisassemble)
2848                                         M_NOP;
2849
2850                                 M_ILD(REG_ITMP2, REG_PV, disp);
2851                                 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2852                                 M_BEQ(s2 + 1);
2853                         }
2854
2855                         /* interface checkcast code */
2856
2857                         if (!super || (super->flags & ACC_INTERFACE)) {
2858                                 if (super) {
2859                                         M_TST(s1);
2860                                         M_BEQ(s2);
2861
2862                                 } else {
2863                                         codegen_addpatchref(cd, mcodeptr,
2864                                                                                 PATCHER_checkcast_instanceof_interface,
2865                                                                                 (constant_classref *) iptr->target, 0);
2866
2867                                         if (opt_showdisassemble)
2868                                                 M_NOP;
2869                                 }
2870
2871                                 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2872                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2873                                 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2874                                 M_BLE(0);
2875                                 codegen_addxcastrefs(cd, mcodeptr);
2876                                 M_ALD(REG_ITMP3, REG_ITMP2,
2877                                           OFFSET(vftbl_t, interfacetable[0]) -
2878                                           superindex * sizeof(methodptr*));
2879                                 M_TST(REG_ITMP3);
2880                                 M_BEQ(0);
2881                                 codegen_addxcastrefs(cd, mcodeptr);
2882
2883                                 if (!super)
2884                                         M_BR(s3);
2885                         }
2886
2887                         /* class checkcast code */
2888
2889                         if (!super || !(super->flags & ACC_INTERFACE)) {
2890                                 disp = dseg_addaddress(cd, supervftbl);
2891
2892                                 if (super) {
2893                                         M_TST(s1);
2894                                         M_BEQ(s3);
2895
2896                                 } else {
2897                                         codegen_addpatchref(cd, mcodeptr,
2898                                                                                 PATCHER_checkcast_class,
2899                                                                                 (constant_classref *) iptr->target,
2900                                                                                 disp);
2901
2902                                         if (opt_showdisassemble)
2903                                                 M_NOP;
2904                                 }
2905
2906                                 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2907 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2908                                 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
2909 #endif
2910                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2911                                 M_ALD(REG_ITMP2, REG_PV, disp);
2912                                 if (s1 != REG_ITMP1) {
2913                                         M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2914                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2915 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2916                                         codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2917 #endif
2918                                         M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2919                                 } else {
2920                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2921                                         M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2922                                         M_ALD(REG_ITMP2, REG_PV, disp);
2923                                         M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2924 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2925                                         codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2926 #endif
2927                                 }
2928                                 M_CMPU(REG_ITMP3, REG_ITMP2);
2929                                 M_BGT(0);
2930                                 codegen_addxcastrefs(cd, mcodeptr);
2931                         }
2932                         d = reg_of_var(rd, iptr->dst, s1);
2933                         M_INTMOVE(s1, d);
2934                         store_reg_to_var_int(iptr->dst, d);
2935                         }
2936                         break;
2937
2938                 case ICMD_ARRAYCHECKCAST: /* ..., objectref ==> ..., objectref        */
2939                                           /* op1: 1... resolved, 0... not resolved    */
2940
2941                         var_to_reg_int(s1, src, rd->argintregs[0]);
2942                         M_INTMOVE(s1, rd->argintregs[0]);
2943
2944                         bte = iptr->val.a;
2945
2946                         disp = dseg_addaddress(cd, iptr->target);
2947
2948                         if (!iptr->op1) {
2949                                 codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target, disp);
2950
2951                                 if (opt_showdisassemble)
2952                                         M_NOP;
2953
2954                                 a = 0;
2955
2956                         } else {
2957                                 a = (ptrint) bte->fp;
2958                         }
2959
2960                         M_ALD(rd->argintregs[1], REG_PV, disp);
2961                         disp = dseg_addaddress(cd, a);
2962                         M_ALD(REG_ITMP2, REG_PV, disp);
2963                         M_MTCTR(REG_ITMP2);
2964                         M_JSR;
2965                         M_TST(REG_RESULT);
2966                         M_BEQ(0);
2967                         codegen_addxcastrefs(cd, mcodeptr);
2968
2969                         var_to_reg_int(s1, src, REG_ITMP1);
2970                         d = reg_of_var(rd, iptr->dst, s1);
2971                         M_INTMOVE(s1, d);
2972                         store_reg_to_var_int(iptr->dst, d);
2973                         break;
2974
2975
2976                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
2977                                       /* val.a: (classinfo*) superclass               */
2978
2979                         /*  superclass is an interface:
2980                          *
2981                          *  return (sub != NULL) &&
2982                          *         (sub->vftbl->interfacetablelength > super->index) &&
2983                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
2984                          *
2985                          *  superclass is a class:
2986                          *
2987                          *  return ((sub != NULL) && (0
2988                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2989                          *          super->vftbl->diffvall));
2990                          */
2991
2992                         {
2993                         classinfo *super;
2994                         vftbl_t   *supervftbl;
2995                         s4         superindex;
2996
2997                         super = (classinfo *) iptr->val.a;
2998
2999                         if (!super) {
3000                                 superindex = 0;
3001                                 supervftbl = NULL;
3002
3003                         } else {
3004                                 superindex = super->index;
3005                                 supervftbl = super->vftbl;
3006                         }
3007                         
3008 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3009             codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
3010 #endif
3011                         var_to_reg_int(s1, src, REG_ITMP1);
3012                         d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3013                         if (s1 == d) {
3014                                 M_MOV(s1, REG_ITMP1);
3015                                 s1 = REG_ITMP1;
3016                         }
3017
3018                         /* calculate interface instanceof code size */
3019
3020                         s2 = 8;
3021                         if (!super)
3022                                 s2 += (opt_showdisassemble ? 1 : 0);
3023
3024                         /* calculate class instanceof code size */
3025
3026                         s3 = 10;
3027                         if (!super)
3028                                 s3 += (opt_showdisassemble ? 1 : 0);
3029
3030                         M_CLR(d);
3031
3032                         /* if class is not resolved, check which code to call */
3033
3034                         if (!super) {
3035                                 M_TST(s1);
3036                                 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
3037
3038                                 disp = dseg_adds4(cd, 0);                     /* super->flags */
3039
3040                                 codegen_addpatchref(cd, mcodeptr,
3041                                                                         PATCHER_checkcast_instanceof_flags,
3042                                                                         (constant_classref *) iptr->target, disp);
3043
3044                                 if (opt_showdisassemble)
3045                                         M_NOP;
3046
3047                                 M_ILD(REG_ITMP3, REG_PV, disp);
3048                                 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3049                                 M_BEQ(s2 + 1);
3050                         }
3051
3052                         /* interface instanceof code */
3053
3054                         if (!super || (super->flags & ACC_INTERFACE)) {
3055                                 if (super) {
3056                                         M_TST(s1);
3057                                         M_BEQ(s2);
3058
3059                                 } else {
3060                                         codegen_addpatchref(cd, mcodeptr,
3061                                                                                 PATCHER_checkcast_instanceof_interface,
3062                                                                                 (constant_classref *) iptr->target, 0);
3063
3064                                         if (opt_showdisassemble)
3065                                                 M_NOP;
3066                                 }
3067
3068                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3069                                 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3070                                 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
3071                                 M_BLE(4);
3072                                 M_ALD(REG_ITMP1, REG_ITMP1,
3073                                           OFFSET(vftbl_t, interfacetable[0]) -
3074                                           superindex * sizeof(methodptr*));
3075                                 M_TST(REG_ITMP1);
3076                                 M_BEQ(1);
3077                                 M_IADD_IMM(REG_ZERO, 1, d);
3078
3079                                 if (!super)
3080                                         M_BR(s3);
3081                         }
3082
3083                         /* class instanceof code */
3084
3085                         if (!super || !(super->flags & ACC_INTERFACE)) {
3086                                 disp = dseg_addaddress(cd, supervftbl);
3087
3088                                 if (super) {
3089                                         M_TST(s1);
3090                                         M_BEQ(s3);
3091
3092                                 } else {
3093                                         codegen_addpatchref(cd, mcodeptr,
3094                                                                                 PATCHER_instanceof_class,
3095                                                                                 (constant_classref *) iptr->target,
3096                                                                                 disp);
3097
3098                                         if (opt_showdisassemble) {
3099                                                 M_NOP;
3100                                         }
3101                                 }
3102
3103                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3104                                 M_ALD(REG_ITMP2, REG_PV, disp);
3105 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3106                                 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3107 #endif
3108                                 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3109                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3110                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3111 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3112                                 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3113 #endif
3114                                 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3115                                 M_CMPU(REG_ITMP1, REG_ITMP2);
3116                                 M_CLR(d);
3117                                 M_BGT(1);
3118                                 M_IADD_IMM(REG_ZERO, 1, d);
3119                         }
3120                         store_reg_to_var_int(iptr->dst, d);
3121                         }
3122                         break;
3123
3124                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
3125                                       /* op1 = dimension, val.a = array descriptor    */
3126
3127                         /* check for negative sizes and copy sizes to stack if necessary  */
3128
3129                         MCODECHECK((iptr->op1 << 1) + 64);
3130
3131                         for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3132                                 /* copy SAVEDVAR sizes to stack */
3133
3134                                 if (src->varkind != ARGVAR) {
3135                                         var_to_reg_int(s2, src, REG_ITMP1);
3136 #if defined(__DARWIN__)
3137                                         M_IST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 4);
3138 #else
3139                                         M_IST(s2, REG_SP, LA_SIZE + (s1 + 3) * 4);
3140 #endif
3141                                 }
3142                         }
3143
3144                         /* a0 = dimension count */
3145
3146                         ICONST(rd->argintregs[0], iptr->op1);
3147
3148                         /* is patcher function set? */
3149
3150                         if (iptr->target) {
3151                                 disp = dseg_addaddress(cd, NULL);
3152
3153                                 codegen_addpatchref(cd, mcodeptr,
3154                                                                         (functionptr) (ptrint) iptr->target,
3155                                                                         iptr->val.a, disp);
3156
3157                                 if (opt_showdisassemble)
3158                                         M_NOP;
3159
3160                         } else {
3161                                 disp = dseg_addaddress(cd, iptr->val.a);
3162                         }
3163
3164                         /* a1 = arraydescriptor */
3165
3166                         M_ALD(rd->argintregs[1], REG_PV, disp);
3167
3168                         /* a2 = pointer to dimensions = stack pointer */
3169
3170 #if defined(__DARWIN__)
3171                         M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 4);
3172 #else
3173                         M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 4);
3174 #endif
3175
3176                         disp = dseg_addaddress(cd, BUILTIN_multianewarray);
3177                         M_ALD(REG_ITMP3, REG_PV, disp);
3178                         M_MTCTR(REG_ITMP3);
3179                         M_JSR;
3180
3181                         /* check for exception before result assignment */
3182
3183                         M_CMPI(REG_RESULT, 0);
3184                         M_BEQ(0);
3185                         codegen_addxexceptionrefs(cd, mcodeptr);
3186
3187                         d = reg_of_var(rd, iptr->dst, REG_RESULT);
3188                         M_INTMOVE(REG_RESULT, d);
3189                         store_reg_to_var_int(iptr->dst, d);
3190                         break;
3191
3192
3193                 default:
3194                         throw_cacao_exception_exit(string_java_lang_InternalError,
3195                                                                            "Unknown ICMD %d", iptr->opc);
3196         } /* switch */
3197                 
3198         } /* for instruction */
3199                 
3200         /* copy values to interface registers */
3201
3202         src = bptr->outstack;
3203         len = bptr->outdepth;
3204         MCODECHECK(64 + len);
3205 #ifdef LSRA
3206         if (!opt_lsra)
3207 #endif
3208         while (src) {
3209                 len--;
3210                 if ((src->varkind != STACKVAR)) {
3211                         s2 = src->type;
3212                         if (IS_FLT_DBL_TYPE(s2)) {
3213                                 var_to_reg_flt(s1, src, REG_FTMP1);
3214                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3215                                         M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3216
3217                                 } else {
3218                                         M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3219                                 }
3220
3221                         } else {
3222                                 var_to_reg_int(s1, src, REG_ITMP1);
3223                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3224                                         M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3225
3226                                 } else {
3227                                         if (IS_2_WORD_TYPE(s2)) {
3228                                                 M_IST(GET_HIGH_REG(s1),
3229                                                           REG_SP, rd->interfaces[len][s2].regoff * 4);
3230                                                 M_IST(GET_LOW_REG(s1), REG_SP,
3231                                                           rd->interfaces[len][s2].regoff * 4 + 4);
3232                                         } else {
3233                                                 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3234                                         }
3235
3236                                 }
3237                         }
3238                 }
3239                 src = src->prev;
3240         }
3241         } /* if (bptr -> flags >= BBREACHED) */
3242         } /* for basic block */
3243
3244         codegen_createlinenumbertable(cd);
3245
3246         {
3247
3248         s4        *xcodeptr;
3249         branchref *bref;
3250
3251         /* generate ArithemticException check stubs */
3252
3253         xcodeptr = NULL;
3254
3255         for (bref = cd->xdivrefs; bref != NULL; bref = bref->next) {
3256                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3257                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3258                                                           bref->branchpos,
3259                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3260                         continue;
3261                 }
3262
3263                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3264                                   bref->branchpos,
3265                                                   (u1 *) mcodeptr - cd->mcodebase);
3266
3267                 MCODECHECK(20);
3268
3269                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3270
3271                 if (xcodeptr != NULL) {
3272                         disp = xcodeptr - mcodeptr - 1;
3273                         M_BR(disp);
3274
3275                 } else {
3276                         xcodeptr = mcodeptr;
3277
3278                         if (m->isleafmethod) {
3279                                 M_MFLR(REG_ZERO);
3280                                 M_AST(REG_ZERO, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3281                         }
3282
3283                         M_MOV(REG_PV, rd->argintregs[0]);
3284                         M_MOV(REG_SP, rd->argintregs[1]);
3285
3286                         if (m->isleafmethod)
3287                                 M_MOV(REG_ZERO, rd->argintregs[2]);
3288                         else
3289                                 M_ALD(rd->argintregs[2],
3290                                           REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3291
3292                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3293
3294                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3295                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3296
3297                         disp = dseg_addaddress(cd, stacktrace_inline_arithmeticexception);
3298                         M_ALD(REG_ITMP1, REG_PV, disp);
3299                         M_MTCTR(REG_ITMP1);
3300                         M_JSR;
3301                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3302
3303                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3304                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3305
3306                         if (m->isleafmethod) {
3307                                 M_ALD(REG_ZERO, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3308                                 M_MTLR(REG_ZERO);
3309                         }
3310
3311                         disp = dseg_addaddress(cd, asm_handle_exception);
3312                         M_ALD(REG_ITMP3, REG_PV, disp);
3313                         M_MTCTR(REG_ITMP3);
3314                         M_RTS;
3315                 }
3316         }
3317
3318         /* generate ArrayIndexOutOfBoundsException stubs */
3319
3320         xcodeptr = NULL;
3321
3322         for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3323                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3324                                   bref->branchpos,
3325                                                   (u1 *) mcodeptr - cd->mcodebase);
3326
3327                 MCODECHECK(21);
3328
3329                 /* move index register into REG_ITMP1 */
3330
3331                 M_MOV(bref->reg, REG_ITMP1);
3332
3333                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3334
3335                 if (xcodeptr != NULL) {
3336                         disp = xcodeptr - mcodeptr - 1;
3337                         M_BR(disp);
3338
3339                 } else {
3340                         xcodeptr = mcodeptr;
3341
3342                         if (m->isleafmethod) {
3343                                 M_MFLR(REG_ZERO);
3344                                 M_AST(REG_ZERO, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3345                         }
3346
3347                         M_MOV(REG_PV, rd->argintregs[0]);
3348                         M_MOV(REG_SP, rd->argintregs[1]);
3349
3350                         if (m->isleafmethod)
3351                                 M_MOV(REG_ZERO, rd->argintregs[2]);
3352                         else
3353                                 M_ALD(rd->argintregs[2],
3354                                           REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3355
3356                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3357                         M_MOV(REG_ITMP1, rd->argintregs[4]);
3358
3359                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 6 * 4));
3360                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
3361
3362                         disp = dseg_addaddress(cd, stacktrace_inline_arrayindexoutofboundsexception);
3363                         M_ALD(REG_ITMP1, REG_PV, disp);
3364                         M_MTCTR(REG_ITMP1);
3365                         M_JSR;
3366                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3367
3368                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 4);
3369                         M_IADD_IMM(REG_SP, LA_SIZE + 6 * 4, REG_SP);
3370
3371                         if (m->isleafmethod) {
3372                                 M_ALD(REG_ZERO, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3373                                 M_MTLR(REG_ZERO);
3374                         }
3375
3376                         disp = dseg_addaddress(cd, asm_handle_exception);
3377                         M_ALD(REG_ITMP3, REG_PV, disp);
3378                         M_MTCTR(REG_ITMP3);
3379                         M_RTS;
3380                 }
3381         }
3382
3383         /* generate ArrayStoreException check stubs */
3384
3385         xcodeptr = NULL;
3386         
3387         for (bref = cd->xstorerefs; bref != NULL; bref = bref->next) {
3388                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3389                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3390                                                           bref->branchpos,
3391                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3392                         continue;
3393                 }
3394
3395                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3396                                   bref->branchpos,
3397                                                   (u1 *) mcodeptr - cd->mcodebase);
3398
3399                 MCODECHECK(15);
3400
3401                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3402
3403                 if (xcodeptr != NULL) {
3404                         disp = xcodeptr - mcodeptr - 1;
3405                         M_BR(disp);
3406
3407                 } else {
3408                         xcodeptr = mcodeptr;
3409
3410                         M_MOV(REG_PV, rd->argintregs[0]);
3411                         M_MOV(REG_SP, rd->argintregs[1]);
3412                         M_ALD(rd->argintregs[2],
3413                                   REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3414                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3415
3416                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3417                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3418
3419                         disp = dseg_addaddress(cd, stacktrace_inline_arraystoreexception);
3420                         M_ALD(REG_ITMP1, REG_PV, disp);
3421                         M_MTCTR(REG_ITMP1);
3422                         M_JSR;
3423                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3424
3425                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3426                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3427
3428                         disp = dseg_addaddress(cd, asm_handle_exception);
3429                         M_ALD(REG_ITMP3, REG_PV, disp);
3430                         M_MTCTR(REG_ITMP3);
3431                         M_RTS;
3432                 }
3433         }
3434
3435         /* generate ClassCastException stubs */
3436
3437         xcodeptr = NULL;
3438         
3439         for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3440                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3441                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3442                                                           bref->branchpos,
3443                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3444                         continue;
3445                 }
3446
3447                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3448                                   bref->branchpos,
3449                                                   (u1 *) mcodeptr - cd->mcodebase);
3450
3451                 MCODECHECK(20);
3452
3453                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3454
3455                 if (xcodeptr != NULL) {
3456                         disp = xcodeptr - mcodeptr - 1;
3457                         M_BR(disp);
3458
3459                 } else {
3460                         xcodeptr = mcodeptr;
3461
3462                         if (m->isleafmethod) {
3463                                 M_MFLR(REG_ZERO);
3464                                 M_AST(REG_ZERO, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3465                         }
3466
3467                         M_MOV(REG_PV, rd->argintregs[0]);
3468                         M_MOV(REG_SP, rd->argintregs[1]);
3469
3470                         if (m->isleafmethod)
3471                                 M_MOV(REG_ZERO, rd->argintregs[2]);
3472                         else
3473                                 M_ALD(rd->argintregs[2],
3474                                           REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3475
3476                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3477
3478                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3479                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3480
3481                         disp = dseg_addaddress(cd, stacktrace_inline_classcastexception);
3482                         M_ALD(REG_ITMP1, REG_PV, disp);
3483                         M_MTCTR(REG_ITMP1);
3484                         M_JSR;
3485                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3486
3487                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3488                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3489
3490                         if (m->isleafmethod) {
3491                                 M_ALD(REG_ZERO, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3492                                 M_MTLR(REG_ZERO);
3493                         }
3494
3495                         disp = dseg_addaddress(cd, asm_handle_exception);
3496                         M_ALD(REG_ITMP3, REG_PV, disp);
3497                         M_MTCTR(REG_ITMP3);
3498                         M_RTS;
3499                 }
3500         }
3501
3502         /* generate NullPointerException stubs */
3503
3504         xcodeptr = NULL;
3505
3506         for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3507                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3508                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3509                                                           bref->branchpos,
3510                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3511                         continue;
3512                 }
3513
3514                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3515                                   bref->branchpos,
3516                                                   (u1 *) mcodeptr - cd->mcodebase);
3517
3518                 MCODECHECK(20);
3519
3520                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3521
3522                 if (xcodeptr != NULL) {
3523                         disp = xcodeptr - mcodeptr - 1;
3524                         M_BR(disp);
3525
3526                 } else {
3527                         xcodeptr = mcodeptr;
3528
3529                         if (m->isleafmethod) {
3530                                 M_MFLR(REG_ZERO);
3531                                 M_AST(REG_ZERO, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3532                         }
3533
3534                         M_MOV(REG_PV, rd->argintregs[0]);
3535                         M_MOV(REG_SP, rd->argintregs[1]);
3536
3537                         if (m->isleafmethod)
3538                                 M_MOV(REG_ZERO, rd->argintregs[2]);
3539                         else
3540                                 M_ALD(rd->argintregs[2],
3541                                           REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3542
3543                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3544
3545                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3546                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3547
3548                         disp = dseg_addaddress(cd, stacktrace_inline_nullpointerexception);
3549                         M_ALD(REG_ITMP1, REG_PV, disp);
3550                         M_MTCTR(REG_ITMP1);
3551                         M_JSR;
3552                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3553
3554                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3555                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3556
3557                         if (m->isleafmethod) {
3558                                 M_ALD(REG_ZERO, REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3559                                 M_MTLR(REG_ZERO);
3560                         }
3561
3562                         disp = dseg_addaddress(cd, asm_handle_exception);
3563                         M_ALD(REG_ITMP3, REG_PV, disp);
3564                         M_MTCTR(REG_ITMP3);
3565                         M_RTS;
3566                 }
3567         }
3568
3569         /* generate exception check stubs */
3570
3571         xcodeptr = NULL;
3572
3573         for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3574                 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3575                         gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3576                                                           bref->branchpos,
3577                                                           (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3578                         continue;
3579                 }
3580
3581                 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos, 
3582                                   bref->branchpos,
3583                                                   (u1 *) mcodeptr - cd->mcodebase);
3584
3585                 MCODECHECK(16);
3586
3587                 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3588
3589                 if (xcodeptr != NULL) {
3590                         disp = xcodeptr - mcodeptr - 1;
3591                         M_BR(disp);
3592
3593                 } else {
3594                         xcodeptr = mcodeptr;
3595
3596                         M_MOV(REG_PV, rd->argintregs[0]);
3597                         M_MOV(REG_SP, rd->argintregs[1]);
3598                         M_ALD(rd->argintregs[2],
3599                                   REG_SP, parentargs_base * 4 + LA_LR_OFFSET);
3600                         M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3601
3602                         M_STWU(REG_SP, REG_SP, -(LA_SIZE + 5 * 4));
3603                         M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3604
3605                         disp = dseg_addaddress(cd, stacktrace_inline_fillInStackTrace);
3606                         M_ALD(REG_ITMP1, REG_PV, disp);
3607                         M_MTCTR(REG_ITMP1);
3608                         M_JSR;
3609                         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3610
3611                         M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 4 * 4);
3612                         M_IADD_IMM(REG_SP, LA_SIZE + 5 * 4, REG_SP);
3613
3614                         disp = dseg_addaddress(cd, asm_handle_exception);
3615                         M_ALD(REG_ITMP3, REG_PV, disp);
3616                         M_MTCTR(REG_ITMP3);
3617                         M_RTS;
3618                 }
3619         }
3620
3621         /* generate patcher stub call code */
3622
3623         {
3624                 patchref *pref;
3625                 u4        mcode;
3626                 s4       *tmpmcodeptr;
3627
3628                 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3629                         /* check code segment size */
3630
3631                         MCODECHECK(16);
3632
3633                         /* Get machine code which is patched back in later. The call is   */
3634                         /* 1 instruction word long.                                       */
3635
3636                         xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3637                         mcode = *xcodeptr;
3638
3639                         /* patch in the call to call the following code (done at compile  */
3640                         /* time)                                                          */
3641
3642                         tmpmcodeptr = mcodeptr;         /* save current mcodeptr          */
3643                         mcodeptr = xcodeptr;            /* set mcodeptr to patch position */
3644
3645                         M_BR(tmpmcodeptr - (xcodeptr + 1));
3646
3647                         mcodeptr = tmpmcodeptr;         /* restore the current mcodeptr   */
3648
3649                         /* create stack frame - keep stack 16-byte aligned */
3650
3651                         M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
3652
3653                         /* calculate return address and move it onto the stack */
3654
3655                         M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
3656                         M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 4);
3657
3658                         /* move pointer to java_objectheader onto stack */
3659
3660 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3661                         /* order reversed because of data segment layout */
3662
3663                         (void) dseg_addaddress(cd, get_dummyLR());          /* monitorPtr */
3664                         disp = dseg_addaddress(cd, NULL);                   /* vftbl      */
3665
3666                         M_LDA(REG_ITMP3, REG_PV, disp);
3667                         M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 4);
3668 #else
3669                         /* do nothing */
3670 #endif
3671
3672                         /* move machine code onto stack */
3673
3674                         disp = dseg_adds4(cd, mcode);
3675                         M_ILD(REG_ITMP3, REG_PV, disp);
3676                         M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 4);
3677
3678                         /* move class/method/field reference onto stack */
3679
3680                         disp = dseg_addaddress(cd, pref->ref);
3681                         M_ALD(REG_ITMP3, REG_PV, disp);
3682                         M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 4);
3683
3684                         /* move data segment displacement onto stack */
3685
3686                         disp = dseg_addaddress(cd, pref->disp);
3687                         M_ILD(REG_ITMP3, REG_PV, disp);
3688                         M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 4);
3689
3690                         /* move patcher function pointer onto stack */
3691
3692                         disp = dseg_addaddress(cd, pref->patcher);
3693                         M_ALD(REG_ITMP3, REG_PV, disp);
3694                         M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
3695
3696                         disp = dseg_addaddress(cd, asm_wrapper_patcher);
3697                         M_ALD(REG_ITMP3, REG_PV, disp);
3698                         M_MTCTR(REG_ITMP3);
3699                         M_RTS;
3700                 }
3701         }
3702
3703         }
3704
3705         codegen_finish(m, cd, (ptrint) ((u1 *) mcodeptr - cd->mcodebase));
3706
3707         asm_cacheflush((void *) (ptrint) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3708 }
3709
3710
3711 /* createcompilerstub **********************************************************
3712
3713    Creates a stub routine which calls the compiler.
3714         
3715 *******************************************************************************/
3716
3717 #define COMPSTUBSIZE 6
3718
3719 functionptr createcompilerstub(methodinfo *m)
3720 {
3721         s4 *s = CNEW(s4, COMPSTUBSIZE);     /* memory to hold the stub            */
3722         s4 *mcodeptr = s;                   /* code generation pointer            */
3723
3724         M_LDA(REG_ITMP1, REG_PV, 4 * 4);
3725         M_ALD_INTERN(REG_PV, REG_PV, 5 * 4);
3726         M_MTCTR(REG_PV);
3727         M_RTS;
3728
3729         s[4] = (s4) m;                      /* literals to be adressed            */
3730         s[5] = (s4) asm_call_jit_compiler;  /* jump directly via PV from above    */
3731
3732         asm_cacheflush((void *) s, (u1 *) mcodeptr - (u1 *) s);
3733
3734 #if defined(STATISTICS)
3735         if (opt_stat)
3736                 count_cstub_len += COMPSTUBSIZE * 4;
3737 #endif
3738
3739         return (functionptr) (ptrint) s;
3740 }
3741
3742
3743 /* createnativestub ************************************************************
3744
3745    Creates a stub routine which calls a native method.
3746
3747 *******************************************************************************/
3748
3749 functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
3750                                                          registerdata *rd, methoddesc *nmd)
3751 {
3752         s4         *mcodeptr;               /* code generation pointer            */
3753         s4          stackframesize;         /* size of stackframe if needed       */
3754         methoddesc *md;
3755         s4          nativeparams;
3756         s4          i, j;                   /* count variables                    */
3757         s4          t;
3758         s4          s1, s2, disp;
3759         s4          funcdisp;
3760
3761         /* set some variables */
3762
3763         md = m->parseddesc;
3764         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3765
3766         /* calculate stackframe size */
3767
3768         stackframesize =
3769                 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3770                 sizeof(localref_table) / SIZEOF_VOID_P +
3771                 4 +                             /* 4 stackframeinfo arguments (darwin)*/
3772                 nmd->paramcount * 2 +           /* assume all arguments are doubles   */
3773                 nmd->memuse;
3774
3775         stackframesize = (stackframesize + 3) & ~3; /* keep stack 16-byte aligned */
3776
3777
3778         /* create method header */
3779
3780         (void) dseg_addaddress(cd, m);                          /* MethodPointer  */
3781         (void) dseg_adds4(cd, stackframesize * 4);              /* FrameSize      */
3782         (void) dseg_adds4(cd, 0);                               /* IsSync         */
3783         (void) dseg_adds4(cd, 0);                               /* IsLeaf         */
3784         (void) dseg_adds4(cd, 0);                               /* IntSave        */
3785         (void) dseg_adds4(cd, 0);                               /* FltSave        */
3786         (void) dseg_addlinenumbertablesize(cd);
3787         (void) dseg_adds4(cd, 0);                               /* ExTableSize    */
3788
3789
3790         /* initialize mcode variables */
3791         
3792         mcodeptr = (s4 *) cd->mcodebase;
3793         cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
3794
3795
3796         /* generate code */
3797
3798         M_MFLR(REG_ZERO);
3799         M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
3800         M_STWU(REG_SP, REG_SP, -(stackframesize * 4));
3801
3802
3803         if (runverbose) {
3804                 /* parent_argbase == stackframesize * 4 */
3805                 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, stackframesize * 4 , 
3806                                                                           true);
3807         }
3808
3809
3810         /* get function address (this must happen before the stackframeinfo) */
3811
3812         funcdisp = dseg_addaddress(cd, f);
3813
3814 #if !defined(ENABLE_STATICVM)
3815         if (f == NULL) {
3816                 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m, funcdisp);
3817
3818                 if (opt_showdisassemble)
3819                         M_NOP;
3820         }
3821 #endif
3822
3823         /* save integer and float argument registers */
3824
3825         for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
3826                 t = md->paramtypes[i].type;
3827
3828                 if (IS_INT_LNG_TYPE(t)) {
3829                         s1 = md->params[i].regoff;
3830                         if (IS_2_WORD_TYPE(t)) {
3831                                 M_IST(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3832                                 j++;
3833                                 M_IST(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3834                                 j++;
3835                         } else {
3836                                 M_IST(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3837                                 j++;
3838                         }
3839                 }
3840         }
3841
3842         for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3843                 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3844                         s1 = md->params[i].regoff;
3845                         M_DST(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 8);
3846                         j++;
3847                 }
3848         }
3849
3850         /* create native stack info */
3851
3852         M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[0]);
3853         M_MOV(REG_PV, rd->argintregs[1]);
3854         M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[2]);
3855         M_ALD(rd->argintregs[3], REG_SP, stackframesize * 4 + LA_LR_OFFSET);
3856         disp = dseg_addaddress(cd, codegen_start_native_call);
3857         M_ALD(REG_ITMP1, REG_PV, disp);
3858         M_MTCTR(REG_ITMP1);
3859         M_JSR;
3860
3861         /* restore integer and float argument registers */
3862
3863         for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
3864                 t = md->paramtypes[i].type;
3865
3866                 if (IS_INT_LNG_TYPE(t)) {
3867                         s1 = md->params[i].regoff;
3868
3869                         if (IS_2_WORD_TYPE(t)) {
3870                                 M_ILD(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3871                                 j++;
3872                                 M_ILD(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3873                                 j++;
3874                         } else {
3875                                 M_ILD(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3876                                 j++;
3877                         }
3878                 }
3879         }
3880
3881         for (i = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3882                 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3883                         s1 = md->params[i].regoff;
3884                         M_DLD(rd->argfltregs[i], REG_SP, LA_SIZE + 4 * 4 + j * 8);
3885                         j++;
3886                 }
3887         }
3888         
3889         /* copy or spill arguments to new locations */
3890
3891         for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3892                 t = md->paramtypes[i].type;
3893
3894                 if (IS_INT_LNG_TYPE(t)) {
3895                         if (!md->params[i].inmemory) {
3896                                 if (IS_2_WORD_TYPE(t))
3897                                         s1 = PACK_REGS(
3898                                                 rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
3899                                             rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
3900                                 else
3901                                         s1 = rd->argintregs[md->params[i].regoff];
3902
3903                                 if (!nmd->params[j].inmemory) {
3904                                         if (IS_2_WORD_TYPE(t))
3905                                                 s2 = PACK_REGS(
3906                                                    rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)],
3907                                                    rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]);
3908                                         else
3909                                                 s2 = rd->argintregs[nmd->params[j].regoff];
3910                                         M_TINTMOVE(t, s1, s2);
3911
3912                                 } else {
3913                                         s2 = nmd->params[j].regoff;
3914                                         if (IS_2_WORD_TYPE(t)) {
3915                                                 M_IST(GET_HIGH_REG(s1), REG_SP, s2 * 4);
3916                                                 M_IST(GET_LOW_REG(s1), REG_SP, s2 * 4 + 4);
3917                                         } else {
3918                                                 M_IST(s1, REG_SP, s2 * 4);
3919                                         }
3920                                 }
3921
3922                         } else {
3923                                 s1 = md->params[i].regoff + stackframesize;
3924                                 s2 = nmd->params[j].regoff;
3925
3926                                 M_ILD(REG_ITMP1, REG_SP, s1 * 4);
3927                                 M_IST(REG_ITMP1, REG_SP, s2 * 4);
3928                                 if (IS_2_WORD_TYPE(t)) {
3929                                         M_ILD(REG_ITMP1, REG_SP, s1 * 4 + 4);
3930                                         M_IST(REG_ITMP1, REG_SP, s2 * 4 + 4);
3931                                 }
3932                         }
3933
3934                 } else {
3935                         /* We only copy spilled float arguments, as the float argument    */
3936                         /* registers keep unchanged.                                      */
3937
3938                         if (md->params[i].inmemory) {
3939                                 s1 = md->params[i].regoff + stackframesize;
3940                                 s2 = nmd->params[j].regoff;
3941
3942                                 if (IS_2_WORD_TYPE(t)) {
3943                                         M_DLD(REG_FTMP1, REG_SP, s1 * 4);
3944                                         M_DST(REG_FTMP1, REG_SP, s2 * 4);
3945
3946                                 } else {
3947                                         M_FLD(REG_FTMP1, REG_SP, s1 * 4);
3948                                         M_FST(REG_FTMP1, REG_SP, s2 * 4);
3949                                 }
3950                         }
3951                 }
3952         }
3953
3954         /* put class into second argument register */
3955
3956         if (m->flags & ACC_STATIC) {
3957                 disp = dseg_addaddress(cd, m->class);
3958                 M_ALD(rd->argintregs[1], REG_PV, disp);
3959         }
3960
3961         /* put env into first argument register */
3962
3963         disp = dseg_addaddress(cd, &env);
3964         M_ALD(rd->argintregs[0], REG_PV, disp);
3965
3966         /* generate the actual native call */
3967
3968         M_ALD(REG_ITMP3, REG_PV, funcdisp);
3969         M_MTCTR(REG_ITMP3);
3970         M_JSR;
3971
3972         /* save return value */
3973
3974         if (IS_INT_LNG_TYPE(md->returntype.type)) {
3975                 if (IS_2_WORD_TYPE(md->returntype.type))
3976                         M_IST(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
3977                 M_IST(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
3978         } else {
3979                 if (IS_2_WORD_TYPE(md->returntype.type))
3980                         M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
3981                 else
3982                         M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
3983         }
3984
3985         /* remove native stackframe info */
3986
3987         M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[0]);
3988         disp = dseg_addaddress(cd, codegen_finish_native_call);
3989         M_ALD(REG_ITMP1, REG_PV, disp);
3990         M_MTCTR(REG_ITMP1);
3991         M_JSR;
3992
3993         /* print call trace */
3994
3995         if (runverbose) {
3996                  /* just restore the value we need, don't care about the other */
3997
3998                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
3999                         if (IS_2_WORD_TYPE(md->returntype.type))
4000                                 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
4001                         M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
4002                 } else {
4003                         if (IS_2_WORD_TYPE(md->returntype.type))
4004                                 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4005                         else
4006                                 M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4007                 }
4008
4009                 M_LDA(REG_SP, REG_SP, -(LA_SIZE + (1 + 2 + 2 + 1) * 4));
4010
4011                 /* keep this order */
4012                 switch (md->returntype.type) {
4013                 case TYPE_INT:
4014                 case TYPE_ADR:
4015 #if defined(__DARWIN__)
4016                         M_MOV(REG_RESULT, rd->argintregs[2]);
4017                         M_CLR(rd->argintregs[1]);
4018 #else
4019                         M_MOV(REG_RESULT, rd->argintregs[3]);
4020                         M_CLR(rd->argintregs[2]);
4021 #endif
4022                         break;
4023
4024                 case TYPE_LNG:
4025 #if defined(__DARWIN__)
4026                         M_MOV(REG_RESULT2, rd->argintregs[2]);
4027                         M_MOV(REG_RESULT, rd->argintregs[1]);
4028 #else
4029                         M_MOV(REG_RESULT2, rd->argintregs[3]);
4030                         M_MOV(REG_RESULT, rd->argintregs[2]);
4031 #endif
4032                         break;
4033                 }
4034
4035                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4036                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4037                 disp = dseg_addaddress(cd, m);
4038                 M_ALD(rd->argintregs[0], REG_PV, disp);
4039
4040                 disp = dseg_addaddress(cd, builtin_displaymethodstop);
4041                 M_ALD(REG_ITMP2, REG_PV, disp);
4042                 M_MTCTR(REG_ITMP2);
4043                 M_JSR;
4044
4045                 M_LDA(REG_SP, REG_SP, LA_SIZE + (1 + 2 + 2 + 1) * 4);
4046         }
4047
4048         /* check for exception */
4049
4050 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4051         disp = dseg_addaddress(cd, builtin_get_exceptionptrptr);
4052         M_ALD(REG_ITMP1, REG_PV, disp);
4053         M_MTCTR(REG_ITMP1);
4054         M_JSR;
4055         M_MOV(REG_RESULT, REG_ITMP2);
4056 #else
4057         disp = dseg_addaddress(cd, &_no_threads_exceptionptr);
4058         M_ALD(REG_ITMP2, REG_PV, disp);
4059 #endif
4060         M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1     */
4061
4062         /* restore return value */
4063
4064         if (IS_INT_LNG_TYPE(md->returntype.type)) {
4065                 if (IS_2_WORD_TYPE(md->returntype.type))
4066                         M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);
4067                 M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
4068         } else {
4069                 if (IS_2_WORD_TYPE(md->returntype.type))
4070                         M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4071                 else
4072                         M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4073         }
4074
4075         M_TST(REG_ITMP1_XPTR);
4076         M_BNE(4);                           /* if no exception then return        */
4077
4078         M_ALD(REG_ZERO, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra   */
4079         M_MTLR(REG_ZERO);
4080         M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe           */
4081
4082         M_RET;
4083
4084         /* handle exception */
4085
4086         M_CLR(REG_ITMP3);
4087         M_AST(REG_ITMP3, REG_ITMP2, 0);     /* store NULL into exceptionptr       */
4088
4089         M_ALD(REG_ITMP2, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra   */
4090         M_MTLR(REG_ITMP2);
4091
4092         M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe           */
4093
4094         M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC);  /* fault address               */
4095
4096         disp = dseg_addaddress(cd, asm_handle_nat_exception);
4097         M_ALD(REG_ITMP3, REG_PV, disp);
4098         M_MTCTR(REG_ITMP3);
4099         M_RTS;
4100
4101         /* generate patcher stub call code */
4102
4103         {
4104                 patchref *pref;
4105                 s4       *xcodeptr;
4106                 s4        mcode;
4107                 s4       *tmpmcodeptr;
4108
4109                 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4110                         /* Get machine code which is patched back in later. The call is   */
4111                         /* 1 instruction word long.                                       */
4112
4113                         xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4114                         mcode = (u4) *xcodeptr;
4115
4116                         /* patch in the call to call the following code (done at compile  */
4117                         /* time)                                                          */
4118
4119                         tmpmcodeptr = mcodeptr;         /* save current mcodeptr          */
4120                         mcodeptr = xcodeptr;            /* set mcodeptr to patch position */
4121
4122                         M_BL(tmpmcodeptr - (xcodeptr + 1));
4123
4124                         mcodeptr = tmpmcodeptr;         /* restore the current mcodeptr   */
4125
4126                         /* create stack frame - keep stack 16-byte aligned                */
4127
4128                         M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
4129
4130                         /* move return address onto stack */
4131
4132                         M_MFLR(REG_ZERO);
4133                         M_AST(REG_ZERO, REG_SP, 5 * 4);
4134
4135                         /* move pointer to java_objectheader onto stack */
4136
4137 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4138                         /* order reversed because of data segment layout */
4139
4140                         (void) dseg_addaddress(cd, get_dummyLR());          /* monitorPtr */
4141                         disp = dseg_addaddress(cd, NULL);                   /* vftbl      */
4142
4143                         M_LDA(REG_ITMP3, REG_PV, disp);
4144                         M_AST(REG_ITMP3, REG_SP, 4 * 4);
4145 #else
4146                         /* do nothing */
4147 #endif
4148
4149                         /* move machine code onto stack */
4150
4151                         disp = dseg_adds4(cd, mcode);
4152                         M_ILD(REG_ITMP3, REG_PV, disp);
4153                         M_IST(REG_ITMP3, REG_SP, 3 * 4);
4154
4155                         /* move class/method/field reference onto stack */
4156
4157                         disp = dseg_addaddress(cd, pref->ref);
4158                         M_ALD(REG_ITMP3, REG_PV, disp);
4159                         M_AST(REG_ITMP3, REG_SP, 2 * 4);
4160
4161                         /* move data segment displacement onto stack */
4162
4163                         disp = dseg_addaddress(cd, pref->disp);
4164                         M_ILD(REG_ITMP3, REG_PV, disp);
4165                         M_IST(REG_ITMP3, REG_SP, 1 * 4);
4166
4167                         /* move patcher function pointer onto stack */
4168
4169                         disp = dseg_addaddress(cd, pref->patcher);
4170                         M_ALD(REG_ITMP3, REG_PV, disp);
4171                         M_AST(REG_ITMP3, REG_SP, 0 * 4);
4172
4173                         disp = dseg_addaddress(cd, asm_wrapper_patcher);
4174                         M_ALD(REG_ITMP3, REG_PV, disp);
4175                         M_MTCTR(REG_ITMP3);
4176                         M_RTS;
4177                 }
4178         }
4179
4180         codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4181
4182         asm_cacheflush((void *) (ptrint) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4183
4184         return m->entrypoint;
4185 }
4186
4187
4188 s4 *codegen_trace_args(methodinfo *m, codegendata *cd, registerdata *rd,
4189                                            s4 *mcodeptr, s4 parentargs_base, bool nativestub)
4190 {
4191         s4 s1, p, t, d;
4192         int stack_off;
4193         int stack_size;
4194         methoddesc *md;
4195
4196         md = m->parseddesc;
4197         
4198         if (!nativestub)
4199                 M_MFLR(REG_ITMP3);
4200         /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
4201         /* For Darwin:                                                        */
4202         /* LA + TRACE_ARGS_NUM u8 args + methodinfo + LR                      */
4203         /* LA_SIZE(=6*4) + 8*8         + 4          + 4  + 0(Padding)         */
4204         /* 6 * 4 + 8 * 8 + 2 * 4 = 12 * 8 = 6 * 16                            */
4205         /* For Linux:                                                         */
4206         /* LA + (TRACE_ARGS_NUM - INT_ARG_CNT/2) u8 args + methodinfo         */
4207         /* + INT_ARG_CNT * 4 ( save integer registers) + LR + 8 + 8 (Padding) */
4208         /* LA_SIZE(=2*4) + 4 * 8 + 4 + 8 * 4 + 4 + 8                          */
4209         /* 2 * 4 + 4 * 8 + 10 * 4 + 1 * 8 + 8= 12 * 8 = 6 * 16                */
4210         
4211         /* in nativestubs no Place to save the LR (Link Register) would be needed */
4212         /* but since the stack frame has to be aligned the 4 Bytes would have to  */
4213         /* be padded again */
4214
4215 #if defined(__DARWIN__)
4216         stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
4217 #else
4218         stack_size = 6 * 16;
4219 #endif
4220         M_LDA(REG_SP, REG_SP, -stack_size);
4221
4222         /* Save LR */
4223         if (!nativestub)
4224                 M_IST(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4225
4226         M_CLR(REG_ITMP1);    /* clear help register */
4227
4228         /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
4229 #if defined(__DARWIN__)
4230         /* Copy Params starting from first to Stack                          */
4231         /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs    */ 
4232         /* are saved                                                         */
4233         p = 0;
4234 #else
4235         /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in   */
4236         /* integer argument regs                                             */
4237         /* all integer argument registers have to be saved                   */
4238         for (p = 0; p < 8; p++) {
4239                 d = rd->argintregs[p];
4240                 /* save integer argument registers */
4241                 M_IST(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4242         }
4243         p = 4;
4244 #endif
4245         stack_off = LA_SIZE;
4246         for (; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
4247                 t = md->paramtypes[p].type;
4248                 if (IS_INT_LNG_TYPE(t)) {
4249                         if (!md->params[p].inmemory) { /* Param in Arg Reg */
4250                                 if (IS_2_WORD_TYPE(t)) {
4251                                         M_IST(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4252                                                   , REG_SP, stack_off);
4253                                         M_IST(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4254                                                   , REG_SP, stack_off + 4);
4255                                 } else {
4256                                         M_IST(REG_ITMP1, REG_SP, stack_off);
4257                                         M_IST(rd->argintregs[md->params[p].regoff]
4258                                                   , REG_SP, stack_off + 4);
4259                                 }
4260                         } else { /* Param on Stack */
4261                                 s1 = (md->params[p].regoff + parentargs_base) * 4 
4262                                         + stack_size;
4263                                 if (IS_2_WORD_TYPE(t)) {
4264                                         M_ILD(REG_ITMP2, REG_SP, s1);
4265                                         M_IST(REG_ITMP2, REG_SP, stack_off);
4266                                         M_ILD(REG_ITMP2, REG_SP, s1 + 4);
4267                                         M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4268                                 } else {
4269                                         M_IST(REG_ITMP1, REG_SP, stack_off);
4270                                         M_ILD(REG_ITMP2, REG_SP, s1);
4271                                         M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4272                                 }
4273                         }
4274                 } else { /* IS_FLT_DBL_TYPE(t) */
4275                         if (!md->params[p].inmemory) { /* in Arg Reg */
4276                                 s1 = rd->argfltregs[md->params[p].regoff];
4277                                 if (!IS_2_WORD_TYPE(t)) {
4278                                         M_IST(REG_ITMP1, REG_SP, stack_off);
4279                                         M_FST(s1, REG_SP, stack_off + 4);
4280                                 } else {
4281                                         M_DST(s1, REG_SP, stack_off);
4282                                 }
4283                         } else { /* on Stack */
4284                                 /* this should not happen */
4285                         }
4286                 }
4287         }
4288
4289         /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
4290 #if defined(__DARWIN__)
4291         for (p = 0; p < 8; p++) {
4292                 d = rd->argintregs[p];
4293                 M_ILD(d, REG_SP, LA_SIZE + p * 4);
4294         }
4295 #else
4296         /* LINUX */
4297         /* Set integer and float argument registers vor trace_args call */
4298         /* offset to saved integer argument registers                   */
4299         stack_off = LA_SIZE + 4 * 8 + 4;
4300         for (p = 0; (p < 4) && (p < md->paramcount); p++) {
4301                 t = md->paramtypes[p].type;
4302                 if (IS_INT_LNG_TYPE(t)) {
4303                         /* "stretch" int types */
4304                         if (!IS_2_WORD_TYPE(t)) {
4305                                 M_CLR(rd->argintregs[2 * p]);
4306                                 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off);
4307                                 stack_off += 4;
4308                         } else {
4309                                 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off + 4);
4310                                 M_ILD(rd->argintregs[2 * p], REG_SP,stack_off);
4311                                 stack_off += 8;
4312                         }
4313                 } else { /* Float/Dbl */
4314                         if (!md->params[p].inmemory) { /* Param in Arg Reg */
4315                                 /* use reserved Place on Stack (sp + 5 * 16) to copy  */
4316                                 /* float/double arg reg to int reg                    */
4317                                 s1 = rd->argfltregs[md->params[p].regoff];
4318                                 if (!IS_2_WORD_TYPE(t)) {
4319                                         M_FST(s1, REG_SP, 5 * 16);
4320                                         M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16);
4321                                         M_CLR(rd->argintregs[2 * p]);
4322                                 } else {
4323                                         M_DST(s1, REG_SP, 5 * 16);
4324                                         M_ILD(rd->argintregs[2 * p + 1], REG_SP,  5 * 16 + 4);
4325                                         M_ILD(rd->argintregs[2 * p], REG_SP, 5 * 16);
4326                                 }
4327                         }
4328                 }
4329         }
4330 #endif
4331
4332         /* put methodinfo pointer on Stackframe */
4333         p = dseg_addaddress(cd, m);
4334         M_ALD(REG_ITMP1, REG_PV, p);
4335 #if defined(__DARWIN__)
4336         M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8); 
4337 #else
4338         M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
4339 #endif
4340         p = dseg_addaddress(cd, builtin_trace_args);
4341         M_ALD(REG_ITMP2, REG_PV, p);
4342         M_MTCTR(REG_ITMP2);
4343         M_JSR;
4344
4345 #if defined(__DARWIN__)
4346         /* restore integer argument registers from the reserved stack space */
4347
4348         stack_off = LA_SIZE;
4349         for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; 
4350                  p++, stack_off += 8) {
4351                 t = md->paramtypes[p].type;
4352
4353                 if (IS_INT_LNG_TYPE(t)) {
4354                         if (!md->params[p].inmemory) {
4355                                 if (IS_2_WORD_TYPE(t)) {
4356                                         M_ILD(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4357                                                   , REG_SP, stack_off);
4358                                         M_ILD(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4359                                                   , REG_SP, stack_off + 4);
4360                                 } else {
4361                                         M_ILD(rd->argintregs[md->params[p].regoff]
4362                                                   , REG_SP, stack_off + 4);
4363                                 }
4364                         }
4365                 }
4366         }
4367 #else
4368         /* LINUX */
4369         for (p = 0; p < 8; p++) {
4370                 d = rd->argintregs[p];
4371                 /* save integer argument registers */
4372                 M_ILD(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4373         }
4374 #endif
4375
4376         if (!nativestub)
4377                 M_ILD(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4378
4379         M_LDA(REG_SP, REG_SP, stack_size);
4380         if (!nativestub)
4381                 M_MTLR(REG_ITMP3);
4382         return mcodeptr;
4383 }
4384
4385 /*
4386  * These are local overrides for various environment variables in Emacs.
4387  * Please do not remove this and leave it at the end of the file, where
4388  * Emacs will automagically detect them.
4389  * ---------------------------------------------------------------------
4390  * Local variables:
4391  * mode: c
4392  * indent-tabs-mode: t
4393  * c-basic-offset: 4
4394  * tab-width: 4
4395  * End:
4396  */