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