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