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