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