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