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