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