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