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