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