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