65436188e208022b61f29fbbebba9d6de329bf29
[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 5279 2006-08-25 11:55:21Z 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_LNGMOVE(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_LRETURN:      /* ..., retvalue ==> ...                      */
2496                 case ICMD_IRETURN:      /* ..., retvalue ==> ...                      */
2497
2498                         s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
2499                         M_LNGMOVE(s1, REG_RESULT);
2500                         goto nowperformreturn;
2501
2502                 case ICMD_ARETURN:      /* ..., retvalue ==> ...                      */
2503
2504                         s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
2505                         M_LNGMOVE(s1, REG_RESULT);
2506
2507 #ifdef ENABLE_VERIFIER
2508                         if (iptr->val.a) {
2509                                 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2510                                                                         (unresolved_class *) iptr->val.a, 0);
2511
2512                                 if (opt_showdisassemble)
2513                                         M_NOP;
2514                         }
2515 #endif /* ENABLE_VERIFIER */
2516
2517                         goto nowperformreturn;
2518
2519                 case ICMD_FRETURN:      /* ..., retvalue ==> ...                      */
2520                 case ICMD_DRETURN:
2521
2522                         s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
2523                         M_FLTMOVE(s1, REG_FRESULT);
2524                         goto nowperformreturn;
2525
2526                 case ICMD_RETURN:      /* ...  ==> ...                                */
2527
2528 nowperformreturn:
2529                         {
2530                         s4 i, p;
2531                         
2532                         p = stackframesize;
2533
2534                         /* call trace function */
2535
2536                         if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
2537                                 M_MFLR(REG_ZERO);
2538                                 M_LDA(REG_SP, REG_SP, -(LA_SIZE+PA_SIZE+10*8));
2539                                 M_DST(REG_FRESULT, REG_SP, LA_SIZE+PA_SIZE+0*8);
2540                                 M_LST(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
2541                                 M_AST(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
2542
2543                                 /* keep this order */
2544                                 switch (iptr->opc) {
2545                                 case ICMD_IRETURN:
2546                                 case ICMD_ARETURN:
2547 #if defined(__DARWIN__)
2548                                         M_MOV(REG_RESULT, rd->argintregs[2]);
2549                                         M_CLR(rd->argintregs[1]);
2550 #else
2551                                         M_MOV(REG_RESULT, rd->argintregs[3]);
2552                                         M_CLR(rd->argintregs[2]);
2553 #endif
2554                                         break;
2555
2556                                 case ICMD_LRETURN:
2557 #if defined(__DARWIN__)
2558                                         M_MOV(REG_RESULT, rd->argintregs[1]);
2559 #else
2560                                         M_MOV(REG_RESULT, rd->argintregs[2]);
2561 #endif
2562                                         break;
2563                                 }
2564
2565                                 disp = dseg_addaddress(cd, m);
2566                                 M_ALD(rd->argintregs[0], REG_PV, disp);
2567
2568                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2569                                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2570                                 disp = dseg_addaddress(cd, builtin_displaymethodstop);
2571                                 M_ALD(REG_ITMP2, REG_PV, disp);
2572                                 M_MTCTR(REG_ITMP2);
2573                                 M_JSR;
2574
2575                                 M_DLD(REG_FRESULT, REG_SP, LA_SIZE+PA_SIZE+0*8);
2576                                 M_LLD(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
2577                                 M_ALD(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
2578                                 M_LDA(REG_SP, REG_SP, LA_SIZE+PA_SIZE+10*8);
2579                                 M_MTLR(REG_ZERO);
2580                         }
2581                         
2582 #if defined(ENABLE_THREADS)
2583                         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2584                                 disp = dseg_addaddress(cd, LOCK_monitor_exit);
2585                                 M_ALD(REG_ITMP3, REG_PV, disp);
2586                                 M_MTCTR(REG_ITMP3);
2587
2588                                 /* we need to save the proper return value */
2589
2590                                 switch (iptr->opc) {
2591                                 case ICMD_LRETURN:
2592                                         /*M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8); FIXME*/
2593                                         /* fall through */
2594                                 case ICMD_IRETURN:
2595                                 case ICMD_ARETURN:
2596                                         M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2597                                         break;
2598                                 case ICMD_FRETURN:
2599                                         M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2600                                         break;
2601                                 case ICMD_DRETURN:
2602                                         M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2603                                         break;
2604                                 }
2605
2606                                 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 4);
2607                                 M_JSR;
2608
2609                                 /* and now restore the proper return value */
2610
2611                                 switch (iptr->opc) {
2612                                 case ICMD_LRETURN:
2613                                         /*M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8); FIXME*/
2614                                         /* fall through */
2615                                 case ICMD_IRETURN:
2616                                 case ICMD_ARETURN:
2617                                         M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2618                                         break;
2619                                 case ICMD_FRETURN:
2620                                         M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2621                                         break;
2622                                 case ICMD_DRETURN:
2623                                         M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2624                                         break;
2625                                 }
2626                         }
2627 #endif
2628
2629                         /* restore return address                                         */
2630
2631                         if (!jd->isleafmethod) {
2632                                 /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
2633                                    may have a displacement overflow. */
2634
2635                                 M_ALD(REG_ITMP1, REG_SP, p * 8 + LA_LR_OFFSET);
2636                                 M_MTLR(REG_ITMP1);
2637                         }
2638
2639                         /* restore saved registers                                        */
2640
2641                         for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2642                                 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2643                         }
2644                         for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2645                                 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2646                         }
2647
2648                         /* deallocate stack                                               */
2649
2650                         if (stackframesize)
2651                                 M_LDA(REG_SP, REG_SP, stackframesize * 8);
2652
2653                         M_RET;
2654                         ALIGNCODENOP;
2655                         }
2656                         break;
2657
2658
2659                 case ICMD_TABLESWITCH:  /* ..., index ==> ...                         */
2660                         {
2661                         s4 i, l, *s4ptr;
2662                         void **tptr;
2663
2664                         tptr = (void **) iptr->target;
2665
2666                         s4ptr = iptr->val.a;
2667                         l = s4ptr[1];                          /* low     */
2668                         i = s4ptr[2];                          /* high    */
2669                         
2670                         s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2671                         if (l == 0) {
2672                                 M_INTMOVE(s1, REG_ITMP1);
2673                         } else if (l <= 32768) {
2674                                 M_LDA(REG_ITMP1, s1, -l);
2675                         } else {
2676                                 ICONST(REG_ITMP2, l);
2677                                 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2678                         }
2679                         i = i - l + 1;
2680
2681                         /* range check */
2682
2683                         M_CMPUI(REG_ITMP1, i - 1);
2684                         M_BGT(0);
2685                         codegen_addreference(cd, (basicblock *) tptr[0]);
2686
2687                         /* build jump table top down and use address of lowest entry */
2688
2689                         /* s4ptr += 3 + i; */
2690                         tptr += i;
2691
2692                         while (--i >= 0) {
2693                                 dseg_addtarget(cd, (basicblock *) tptr[0]); 
2694                                 --tptr;
2695                         }
2696                         }
2697
2698                         /* length of dataseg after last dseg_addtarget is used by load */
2699
2700                         M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2701                         M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2702                         M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2703                         M_MTCTR(REG_ITMP2);
2704                         M_RTS;
2705                         ALIGNCODENOP;
2706                         break;
2707
2708
2709                 case ICMD_LOOKUPSWITCH: /* ..., key ==> ...                           */
2710                         {
2711                         s4 i, l, val, *s4ptr;
2712                         void **tptr;
2713
2714                         tptr = (void **) iptr->target;
2715
2716                         s4ptr = iptr->val.a;
2717                         l = s4ptr[0];                          /* default  */
2718                         i = s4ptr[1];                          /* count    */
2719                         
2720                         MCODECHECK((i<<2)+8);
2721                         s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2722                         while (--i >= 0) {
2723                                 s4ptr += 2;
2724                                 ++tptr;
2725
2726                                 val = s4ptr[0];
2727                                 if ((val >= -32768) && (val <= 32767)) {
2728                                         M_CMPI(s1, val);
2729                                 } else {
2730                                         a = dseg_adds4(cd, val);
2731                                         M_ILD(REG_ITMP2, REG_PV, a);
2732                                         M_CMP(s1, REG_ITMP2);
2733                                 }
2734                                 M_BEQ(0);
2735                                 codegen_addreference(cd, (basicblock *) tptr[0]); 
2736                         }
2737
2738                         M_BR(0);
2739                         tptr = (void **) iptr->target;
2740                         codegen_addreference(cd, (basicblock *) tptr[0]);
2741
2742                         ALIGNCODENOP;
2743                         break;
2744                         }
2745
2746
2747                 case ICMD_BUILTIN:      /* ..., [arg1, [arg2 ...]] ==> ...            */
2748                                         /* op1 = arg count val.a = builtintable entry */
2749
2750                         bte = iptr->val.a;
2751                         md = bte->md;
2752                         goto gen_method;
2753
2754                 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
2755                                         /* op1 = arg count, val.a = method pointer    */
2756
2757                 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2758                 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
2759                 case ICMD_INVOKEINTERFACE:
2760
2761                         if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2762                                 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
2763                                 lm = NULL;
2764                         }
2765                         else {
2766                                 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
2767                                 md = lm->parseddesc;
2768                         }
2769
2770 gen_method:
2771                         s3 = md->paramcount;
2772
2773                         MCODECHECK((s3 << 1) + 64);
2774
2775                         /* copy arguments to registers or stack location */
2776
2777                         for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2778                                 if (src->varkind == ARGVAR)
2779                                         continue;
2780                                 if (IS_INT_LNG_TYPE(src->type)) {
2781                                         if (!md->params[s3].inmemory) {
2782                                                 if (IS_2_WORD_TYPE(src->type)) {
2783                                                         s1 = rd->argintregs[md->params[s3].regoff];     /* removed PACKREGS */
2784                                                         d = emit_load_s1(jd, iptr, src, s1);
2785                                                         M_LNGMOVE(d, s1);
2786                                                 } else {
2787                                                         s1 = rd->argintregs[md->params[s3].regoff];
2788                                                         d = emit_load_s1(jd, iptr, src, s1);
2789                                                         M_INTMOVE(d, s1);
2790                                                 }
2791
2792                                         } else {
2793                                                 if (IS_2_WORD_TYPE(src->type)) {
2794                                                         d = emit_load_s1(jd, iptr, src, REG_ITMP1);
2795                                                         M_LST(d, REG_SP, md->params[s3].regoff * 4);    /* XXX */
2796                                                 } else {
2797                                                         d = emit_load_s1(jd, iptr, src, REG_ITMP1);
2798                                                         M_IST(d, REG_SP, md->params[s3].regoff * 4);
2799                                                 }
2800                                         }
2801                                                 
2802                                 } else {
2803                                         if (!md->params[s3].inmemory) {
2804                                                 s1 = rd->argfltregs[md->params[s3].regoff];
2805                                                 d = emit_load_s1(jd, iptr, src, s1);
2806                                                 M_FLTMOVE(d, s1);
2807
2808                                         } else {
2809                                                 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
2810                                                 if (IS_2_WORD_TYPE(src->type))
2811                                                         M_DST(d, REG_SP, md->params[s3].regoff * 4);
2812                                                 else
2813                                                         M_FST(d, REG_SP, md->params[s3].regoff * 4);
2814                                         }
2815                                 }
2816                         } /* end of for */
2817
2818                         switch (iptr->opc) {
2819                         case ICMD_BUILTIN:
2820                                 disp = dseg_addaddress(cd, bte->fp);
2821                                 d = md->returntype.type;
2822
2823                                 M_ALD(REG_PV, REG_PV, disp);  /* pointer to built-in-function */
2824                                 M_MTCTR(REG_PV);
2825                                 M_JSR;
2826                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2827                                 M_MFLR(REG_ITMP1);
2828                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2829
2830                                 /* if op1 == true, we need to check for an exception */
2831
2832                                 if (iptr->op1 == true) {
2833                                         M_CMPI(REG_RESULT, 0);
2834                                         M_BEQ(0);
2835                                         codegen_add_fillinstacktrace_ref(cd);
2836                                 }
2837                                 break;
2838
2839                         case ICMD_INVOKESPECIAL:
2840                                 gen_nullptr_check(rd->argintregs[0]);
2841                                 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr   */
2842                                 /* fall through */
2843
2844                         case ICMD_INVOKESTATIC:
2845                                 if (lm == NULL) {
2846                                         unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
2847
2848                                         disp = dseg_addaddress(cd, NULL);
2849
2850                                         codegen_addpatchref(cd, PATCHER_invokestatic_special,
2851                                                                                 um, disp);
2852
2853                                         if (opt_showdisassemble)
2854                                                 M_NOP;
2855
2856                                         d = md->returntype.type;
2857
2858                                 } else {
2859                                         disp = dseg_addaddress(cd, lm->stubroutine);
2860                                         d = md->returntype.type;
2861                                 }
2862
2863                                 M_ALD(REG_PV, REG_PV, disp);
2864                                 M_MTCTR(REG_PV);
2865                                 M_JSR;
2866                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2867                                 M_MFLR(REG_ITMP1);
2868                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2869                                 break;
2870
2871                         case ICMD_INVOKEVIRTUAL:
2872                                 gen_nullptr_check(rd->argintregs[0]);
2873
2874                                 if (lm == NULL) {
2875                                         unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
2876
2877                                         codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2878
2879                                         if (opt_showdisassemble)
2880                                                 M_NOP;
2881
2882                                         s1 = 0;
2883                                         d = md->returntype.type;
2884
2885                                 } else {
2886                                         s1 = OFFSET(vftbl_t, table[0]) +
2887                                                 sizeof(methodptr) * lm->vftblindex;
2888                                         d = md->returntype.type;
2889                                 }
2890
2891                                 M_ALD(REG_METHODPTR, rd->argintregs[0],
2892                                           OFFSET(java_objectheader, vftbl));
2893                                 M_ALD(REG_PV, REG_METHODPTR, s1);
2894                                 M_MTCTR(REG_PV);
2895                                 M_JSR;
2896                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2897                                 M_MFLR(REG_ITMP1);
2898                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2899                                 break;
2900
2901                         case ICMD_INVOKEINTERFACE:
2902                                 gen_nullptr_check(rd->argintregs[0]);
2903
2904                                 if (lm == NULL) {
2905                                         unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
2906
2907                                         codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2908
2909                                         if (opt_showdisassemble)
2910                                                 M_NOP;
2911
2912                                         s1 = 0;
2913                                         s2 = 0;
2914                                         d = md->returntype.type;
2915
2916                                 } else {
2917                                         s1 = OFFSET(vftbl_t, interfacetable[0]) -
2918                                                 sizeof(methodptr*) * lm->class->index;
2919
2920                                         s2 = sizeof(methodptr) * (lm - lm->class->methods);
2921
2922                                         d = md->returntype.type;
2923                                 }
2924
2925                                 M_ALD(REG_METHODPTR, rd->argintregs[0],
2926                                           OFFSET(java_objectheader, vftbl));    
2927                                 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2928                                 M_ALD(REG_PV, REG_METHODPTR, s2);
2929                                 M_MTCTR(REG_PV);
2930                                 M_JSR;
2931                                 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2932                                 M_MFLR(REG_ITMP1);
2933                                 M_LDA(REG_PV, REG_ITMP1, -disp);
2934                                 break;
2935                         }
2936
2937                         /* d contains return type */
2938
2939                         if (d != TYPE_VOID) {
2940                                 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2941                                         if (IS_2_WORD_TYPE(iptr->dst->type)) {
2942                                                 /*s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, 
2943                                                                                 PACK_REGS(REG_RESULT2, REG_RESULT)); FIXME*/
2944                                                 /*M_LNGMOVE(PACK_REGS(REG_RESULT2, REG_RESULT), s1); FIXME*/
2945                                         } else {
2946                                                 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
2947                                                 M_INTMOVE(REG_RESULT, s1);
2948                                         }
2949                                 } else {
2950                                         s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FRESULT);
2951                                         M_FLTMOVE(REG_FRESULT, s1);
2952                                 }
2953                                 emit_store(jd, iptr, iptr->dst, s1);
2954                         }
2955                         break;
2956
2957
2958                 case ICMD_CHECKCAST:  /* ..., objectref ==> ..., objectref            */
2959                                       /* op1:   0 == array, 1 == class                */
2960                                       /* val.a: (classinfo*) superclass               */
2961
2962                         /*  superclass is an interface:
2963                          *
2964                          *  OK if ((sub == NULL) ||
2965                          *         (sub->vftbl->interfacetablelength > super->index) &&
2966                          *         (sub->vftbl->interfacetable[-super->index] != NULL));
2967                          *
2968                          *  superclass is a class:
2969                          *
2970                          *  OK if ((sub == NULL) || (0
2971                          *         <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2972                          *         super->vftbl->diffvall));
2973                          */
2974
2975                         if (iptr->op1 == 1) {
2976                                 /* object type cast-check */
2977
2978                                 classinfo *super;
2979                                 vftbl_t   *supervftbl;
2980                                 s4         superindex;
2981
2982                                 super = (classinfo *) iptr->val.a;
2983
2984                                 if (!super) {
2985                                         superindex = 0;
2986                                         supervftbl = NULL;
2987
2988                                 } else {
2989                                         superindex = super->index;
2990                                         supervftbl = super->vftbl;
2991                                 }
2992                         
2993 #if defined(ENABLE_THREADS)
2994                                 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2995 #endif
2996                                 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2997
2998                                 /* calculate interface checkcast code size */
2999
3000                                 s2 = 7;
3001                                 if (!super)
3002                                         s2 += (opt_showdisassemble ? 1 : 0);
3003
3004                                 /* calculate class checkcast code size */
3005
3006                                 s3 = 8 + (s1 == REG_ITMP1);
3007                                 if (!super)
3008                                         s3 += (opt_showdisassemble ? 1 : 0);
3009
3010                                 /* if class is not resolved, check which code to call */
3011
3012                                 if (!super) {
3013                                         M_TST(s1);
3014                                         M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
3015
3016                                         disp = dseg_adds4(cd, 0);                     /* super->flags */
3017
3018                                         codegen_addpatchref(cd,
3019                                                                                 PATCHER_checkcast_instanceof_flags,
3020                                                                                 (constant_classref *) iptr->target,
3021                                                                                 disp);
3022
3023                                         if (opt_showdisassemble)
3024                                                 M_NOP;
3025
3026                                         M_ILD(REG_ITMP2, REG_PV, disp);
3027                                         M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3028                                         M_BEQ(s2 + 1);
3029                                 }
3030
3031                                 /* interface checkcast code */
3032
3033                                 if (!super || (super->flags & ACC_INTERFACE)) {
3034                                         if (super) {
3035                                                 M_TST(s1);
3036                                                 M_BEQ(s2);
3037
3038                                         } else {
3039                                                 codegen_addpatchref(cd,
3040                                                                                         PATCHER_checkcast_instanceof_interface,
3041                                                                                         (constant_classref *) iptr->target,
3042                                                                                         0);
3043
3044                                                 if (opt_showdisassemble)
3045                                                         M_NOP;
3046                                         }
3047
3048                                         M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3049                                         M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3050                                         M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
3051                                         M_BLE(0);
3052                                         codegen_add_classcastexception_ref(cd, s1);     /*XXX s1?? */
3053                                         M_ALD(REG_ITMP3, REG_ITMP2,
3054                                                   OFFSET(vftbl_t, interfacetable[0]) -
3055                                                   superindex * sizeof(methodptr*));
3056                                         M_TST(REG_ITMP3);
3057                                         M_BEQ(0);
3058                                         codegen_add_classcastexception_ref(cd, s1);     /*XXX s1??*/
3059
3060                                         if (!super)
3061                                                 M_BR(s3);
3062                                 }
3063
3064                                 /* class checkcast code */
3065
3066                                 if (!super || !(super->flags & ACC_INTERFACE)) {
3067                                         disp = dseg_addaddress(cd, supervftbl);
3068
3069                                         if (super) {
3070                                                 M_TST(s1);
3071                                                 M_BEQ(s3);
3072
3073                                         } else {
3074                                                 codegen_addpatchref(cd, PATCHER_checkcast_class,
3075                                                                                         (constant_classref *) iptr->target,
3076                                                                                         disp);
3077
3078                                                 if (opt_showdisassemble)
3079                                                         M_NOP;
3080                                         }
3081
3082                                         M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3083 #if defined(ENABLE_THREADS)
3084                                         codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3085 #endif
3086                                         M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3087                                         M_ALD(REG_ITMP2, REG_PV, disp);
3088                                         if (s1 != REG_ITMP1) {
3089                                                 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
3090                                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3091 #if defined(ENABLE_THREADS)
3092                                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3093 #endif
3094                                                 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
3095                                         } else {
3096                                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3097                                                 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3098                                                 M_ALD(REG_ITMP2, REG_PV, disp);
3099                                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3100 #if defined(ENABLE_THREADS)
3101                                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3102 #endif
3103                                         }
3104                                         M_CMPU(REG_ITMP3, REG_ITMP2);
3105                                         M_BGT(0);
3106                                         codegen_add_classcastexception_ref(cd, s1); /* XXX s1? */
3107                                 }
3108                                 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
3109
3110                         } else {
3111                                 /* array type cast-check */
3112
3113                                 s1 = emit_load_s1(jd, iptr, src, rd->argintregs[0]);
3114                                 M_INTMOVE(s1, rd->argintregs[0]);
3115
3116                                 disp = dseg_addaddress(cd, iptr->val.a);
3117
3118                                 if (iptr->val.a == NULL) {
3119                                         codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
3120                                                                                 (constant_classref *) iptr->target,
3121                                                                                 disp);
3122
3123                                         if (opt_showdisassemble)
3124                                                 M_NOP;
3125                                 }
3126
3127                                 M_ALD(rd->argintregs[1], REG_PV, disp);
3128                                 disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
3129                                 M_ALD(REG_ITMP2, REG_PV, disp);
3130                                 M_MTCTR(REG_ITMP2);
3131                                 M_JSR;
3132                                 M_TST(REG_RESULT);
3133                                 M_BEQ(0);
3134                                 codegen_add_classcastexception_ref(cd, s1); /* XXX s1? */
3135
3136                                 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3137                                 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, s1);
3138                         }
3139                         M_INTMOVE(s1, d);
3140                         emit_store(jd, iptr, iptr->dst, d);
3141                         break;
3142
3143                 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult            */
3144                                       /* val.a: (classinfo*) superclass               */
3145
3146                         /*  superclass is an interface:
3147                          *
3148                          *  return (sub != NULL) &&
3149                          *         (sub->vftbl->interfacetablelength > super->index) &&
3150                          *         (sub->vftbl->interfacetable[-super->index] != NULL);
3151                          *
3152                          *  superclass is a class:
3153                          *
3154                          *  return ((sub != NULL) && (0
3155                          *          <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3156                          *          super->vftbl->diffvall));
3157                          */
3158
3159                         {
3160                         classinfo *super;
3161                         vftbl_t   *supervftbl;
3162                         s4         superindex;
3163
3164                         super = (classinfo *) iptr->val.a;
3165
3166                         if (!super) {
3167                                 superindex = 0;
3168                                 supervftbl = NULL;
3169
3170                         } else {
3171                                 superindex = super->index;
3172                                 supervftbl = super->vftbl;
3173                         }
3174                         
3175 #if defined(ENABLE_THREADS)
3176             codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3177 #endif
3178                         s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3179                         d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3180                         if (s1 == d) {
3181                                 M_MOV(s1, REG_ITMP1);
3182                                 s1 = REG_ITMP1;
3183                         }
3184
3185                         /* calculate interface instanceof code size */
3186
3187                         s2 = 8;
3188                         if (!super)
3189                                 s2 += (opt_showdisassemble ? 1 : 0);
3190
3191                         /* calculate class instanceof code size */
3192
3193                         s3 = 10;
3194                         if (!super)
3195                                 s3 += (opt_showdisassemble ? 1 : 0);
3196
3197                         M_CLR(d);
3198
3199                         /* if class is not resolved, check which code to call */
3200
3201                         if (!super) {
3202                                 M_TST(s1);
3203                                 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
3204
3205                                 disp = dseg_adds4(cd, 0);                     /* super->flags */
3206
3207                                 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3208                                                                         (constant_classref *) iptr->target, disp);
3209
3210                                 if (opt_showdisassemble)
3211                                         M_NOP;
3212
3213                                 M_ILD(REG_ITMP3, REG_PV, disp);
3214                                 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
3215                                 M_BEQ(s2 + 1);
3216                         }
3217
3218                         /* interface instanceof code */
3219
3220                         if (!super || (super->flags & ACC_INTERFACE)) {
3221                                 if (super) {
3222                                         M_TST(s1);
3223                                         M_BEQ(s2);
3224
3225                                 } else {
3226                                         codegen_addpatchref(cd,
3227                                                                                 PATCHER_checkcast_instanceof_interface,
3228                                                                                 (constant_classref *) iptr->target, 0);
3229
3230                                         if (opt_showdisassemble)
3231                                                 M_NOP;
3232                                 }
3233
3234                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3235                                 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3236                                 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
3237                                 M_BLE(4);
3238                                 M_ALD(REG_ITMP1, REG_ITMP1,
3239                                           OFFSET(vftbl_t, interfacetable[0]) -
3240                                           superindex * sizeof(methodptr*));
3241                                 M_TST(REG_ITMP1);
3242                                 M_BEQ(1);
3243                                 M_IADD_IMM(REG_ZERO, 1, d);
3244
3245                                 if (!super)
3246                                         M_BR(s3);
3247                         }
3248
3249                         /* class instanceof code */
3250
3251                         if (!super || !(super->flags & ACC_INTERFACE)) {
3252                                 disp = dseg_addaddress(cd, supervftbl);
3253
3254                                 if (super) {
3255                                         M_TST(s1);
3256                                         M_BEQ(s3);
3257
3258                                 } else {
3259                                         codegen_addpatchref(cd, PATCHER_instanceof_class,
3260                                                                                 (constant_classref *) iptr->target,
3261                                                                                 disp);
3262
3263                                         if (opt_showdisassemble) {
3264                                                 M_NOP;
3265                                         }
3266                                 }
3267
3268                                 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3269                                 M_ALD(REG_ITMP2, REG_PV, disp);
3270 #if defined(ENABLE_THREADS)
3271                                 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3272 #endif
3273                                 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3274                                 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3275                                 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3276 #if defined(ENABLE_THREADS)
3277                                 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3278 #endif
3279                                 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3280                                 M_CMPU(REG_ITMP1, REG_ITMP2);
3281                                 M_CLR(d);
3282                                 M_BGT(1);
3283                                 M_IADD_IMM(REG_ZERO, 1, d);
3284                         }
3285                         emit_store(jd, iptr, iptr->dst, d);
3286                         }
3287                         break;
3288
3289                 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref  */
3290                                       /* op1 = dimension, val.a = class               */
3291
3292                         /* check for negative sizes and copy sizes to stack if necessary  */
3293
3294                         MCODECHECK((iptr->op1 << 1) + 64);
3295
3296                         for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3297                                 /* copy SAVEDVAR sizes to stack */
3298
3299                                 if (src->varkind != ARGVAR) {
3300                                         s2 = emit_load_s2(jd, iptr, src, REG_ITMP1);
3301 #if defined(__DARWIN__)
3302                                         M_IST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 4);
3303 #else
3304                                         M_IST(s2, REG_SP, LA_SIZE + (s1 + 3) * 4);
3305 #endif
3306                                 }
3307                         }
3308
3309                         /* a0 = dimension count */
3310
3311                         ICONST(rd->argintregs[0], iptr->op1);
3312
3313                         /* is patcher function set? */
3314
3315                         if (iptr->val.a == NULL) {
3316                                 disp = dseg_addaddress(cd, NULL);
3317
3318                                 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
3319                                                                         (constant_classref *) iptr->target, disp);
3320
3321                                 if (opt_showdisassemble)
3322                                         M_NOP;
3323
3324                         } else {
3325                                 disp = dseg_addaddress(cd, iptr->val.a);
3326                         }
3327
3328                         /* a1 = arraydescriptor */
3329
3330                         M_ALD(rd->argintregs[1], REG_PV, disp);
3331
3332                         /* a2 = pointer to dimensions = stack pointer */
3333
3334 #if defined(__DARWIN__)
3335                         M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 4);
3336 #else
3337                         M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 4);
3338 #endif
3339
3340                         disp = dseg_addaddress(cd, BUILTIN_multianewarray);
3341                         M_ALD(REG_ITMP3, REG_PV, disp);
3342                         M_MTCTR(REG_ITMP3);
3343                         M_JSR;
3344
3345                         /* check for exception before result assignment */
3346
3347                         M_CMPI(REG_RESULT, 0);
3348                         M_BEQ(0);
3349                         codegen_add_fillinstacktrace_ref(cd);
3350
3351                         d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3352                         M_INTMOVE(REG_RESULT, d);
3353                         emit_store(jd, iptr, iptr->dst, d);
3354                         break;
3355
3356                 default:
3357                         *exceptionptr =
3358                                 new_internalerror("Unknown ICMD %d during code generation",
3359                                                                   iptr->opc);
3360                         return false;
3361         } /* switch */
3362                 
3363         } /* for instruction */
3364                 
3365         /* copy values to interface registers */
3366
3367         src = bptr->outstack;
3368         len = bptr->outdepth;
3369         MCODECHECK(64 + len);
3370 #if defined(ENABLE_LSRA)
3371         if (!opt_lsra)
3372 #endif
3373         while (src) {
3374                 len--;
3375                 if ((src->varkind != STACKVAR)) {
3376                         s2 = src->type;
3377                         if (IS_FLT_DBL_TYPE(s2)) {
3378                                 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
3379                                 if (!(rd->interfaces[len][s2].flags & INMEMORY))
3380                                         M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3381                                 else
3382                                         M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3383
3384                         } else {
3385                                 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3386                                 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3387                                         if (IS_2_WORD_TYPE(s2))
3388                                                 M_LNGMOVE(s1, rd->interfaces[len][s2].regoff);
3389                                         else
3390                                                 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3391
3392                                 } else {
3393                                         if (IS_2_WORD_TYPE(s2))
3394                                                 M_LST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3395                                         else
3396                                                 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3397                                 }
3398                         }
3399                 }
3400                 src = src->prev;
3401         }
3402         } /* if (bptr -> flags >= BBREACHED) */
3403         } /* for basic block */
3404
3405         dseg_createlinenumbertable(cd);
3406
3407
3408         /* generate exception and patcher stubs */
3409
3410         {
3411                 exceptionref *eref;
3412                 patchref     *pref;
3413                 u4            mcode;
3414                 u1           *savedmcodeptr;
3415                 u1           *tmpmcodeptr;
3416
3417                 savedmcodeptr = NULL;
3418
3419                 /* generate exception stubs */
3420
3421                 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
3422                         gen_resolvebranch(cd->mcodebase + eref->branchpos, 
3423                                                           eref->branchpos, cd->mcodeptr - cd->mcodebase);
3424
3425                         MCODECHECK(100);
3426
3427                         /* Check if the exception is an
3428                            ArrayIndexOutOfBoundsException.  If so, move index register
3429                            into REG_ITMP1. */
3430
3431                         if (eref->reg != -1)
3432                                 M_MOV(eref->reg, REG_ITMP1);
3433
3434                         /* calcuate exception address */
3435
3436                         M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
3437
3438                         /* move function to call into REG_ITMP3 */
3439
3440                         disp = dseg_addaddress(cd, eref->function);
3441                         M_ALD(REG_ITMP3, REG_PV, disp);
3442
3443                         if (savedmcodeptr != NULL) {
3444                                 disp = ((u4 *) savedmcodeptr) - (((u4 *) cd->mcodeptr) + 1);
3445                                 M_BR(disp);
3446
3447                         } else {
3448                                 savedmcodeptr = cd->mcodeptr;
3449
3450                                 if (jd->isleafmethod) {
3451                                         M_MFLR(REG_ZERO);
3452                                         M_AST(REG_ZERO, REG_SP, stackframesize * 8 + LA_LR_OFFSET);
3453                                 }
3454
3455                                 M_MOV(REG_PV, rd->argintregs[0]);
3456                                 M_MOV(REG_SP, rd->argintregs[1]);
3457
3458                                 if (jd->isleafmethod)
3459                                         M_MOV(REG_ZERO, rd->argintregs[2]);
3460                                 else
3461                                         M_ALD(rd->argintregs[2],
3462                                                   REG_SP, stackframesize * 8 + LA_LR_OFFSET);
3463
3464                                 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3465                                 M_MOV(REG_ITMP1, rd->argintregs[4]);
3466
3467                                 M_STDU(REG_SP, REG_SP, -(LA_SIZE + 6 * 8));
3468                                 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 8);
3469
3470                                 M_MTCTR(REG_ITMP3);
3471                                 M_JSR;
3472                                 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3473
3474                                 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 8);
3475                                 M_LADD_IMM(REG_SP, LA_SIZE + 6 * 8, REG_SP);
3476
3477                                 if (jd->isleafmethod) {
3478                                         /* XXX FIXME: REG_ZERO can cause problems here! */
3479                                         assert(stackframesize * 8 <= 32767);
3480
3481                                         M_ALD(REG_ZERO, REG_SP, stackframesize * 8 + LA_LR_OFFSET);
3482                                         M_MTLR(REG_ZERO);
3483                                 }
3484
3485                                 disp = dseg_addaddress(cd, asm_handle_exception);
3486                                 M_ALD(REG_ITMP3, REG_PV, disp);
3487                                 M_MTCTR(REG_ITMP3);
3488                                 M_RTS;
3489                         }
3490                 }
3491
3492
3493                 /* generate code patching stub call code */
3494
3495                 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3496                         /* check code segment size */
3497
3498                         MCODECHECK(16);
3499
3500                         /* Get machine code which is patched back in later. The
3501                            call is 1 instruction word long. */
3502
3503                         tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
3504
3505                         mcode = *((u4 *) tmpmcodeptr);
3506
3507                         /* Patch in the call to call the following code (done at
3508                            compile time). */
3509
3510                         savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
3511                         cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
3512
3513                         disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
3514                         M_BR(disp);
3515
3516                         cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
3517
3518                         /* create stack frame - keep stack 16-byte aligned */
3519
3520                         M_AADD_IMM(REG_SP, -8 * 8, REG_SP);
3521
3522                         /* calculate return address and move it onto the stack */
3523
3524                         M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
3525                         M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 8);
3526
3527                         /* move pointer to java_objectheader onto stack */
3528
3529 #if defined(ENABLE_THREADS)
3530                         /* order reversed because of data segment layout */
3531
3532                         (void) dseg_addaddress(cd, NULL);                         /* flcword    */
3533                         (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
3534                         disp = dseg_addaddress(cd, NULL);                         /* vftbl      */
3535
3536                         M_LDA(REG_ITMP3, REG_PV, disp);
3537                         M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 8);
3538 #else
3539                         /* do nothing */
3540 #endif
3541
3542                         /* move machine code onto stack */
3543
3544                         disp = dseg_adds4(cd, mcode);
3545                         M_ILD(REG_ITMP3, REG_PV, disp);
3546                         M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 8);
3547
3548                         /* move class/method/field reference onto stack */
3549
3550                         disp = dseg_addaddress(cd, pref->ref);
3551                         M_ALD(REG_ITMP3, REG_PV, disp);
3552                         M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 8);
3553
3554                         /* move data segment displacement onto stack */
3555
3556                         disp = dseg_addaddress(cd, pref->disp);
3557                         M_ILD(REG_ITMP3, REG_PV, disp);
3558                         M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 8);
3559
3560                         /* move patcher function pointer onto stack */
3561
3562                         disp = dseg_addaddress(cd, pref->patcher);
3563                         M_ALD(REG_ITMP3, REG_PV, disp);
3564                         M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
3565
3566                         disp = dseg_addaddress(cd, asm_patcher_wrapper);
3567                         M_ALD(REG_ITMP3, REG_PV, disp);
3568                         M_MTCTR(REG_ITMP3);
3569                         M_RTS;
3570                 }
3571
3572                 /* generate replacement-out stubs */
3573
3574                 {
3575                         int i;
3576
3577                         replacementpoint = jd->code->rplpoints;
3578
3579                         for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
3580                                 /* check code segment size */
3581
3582                                 MCODECHECK(100);
3583
3584                                 /* note start of stub code */
3585
3586                                 replacementpoint->outcode = (u1 *) (cd->mcodeptr - cd->mcodebase);
3587
3588                                 /* make machine code for patching */
3589
3590                                 tmpmcodeptr  = cd->mcodeptr;
3591                                 cd->mcodeptr = (u1 *) &(replacementpoint->mcode) + 1 /* big-endian */;
3592
3593                                 disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
3594                                 M_BR(disp);
3595
3596                                 cd->mcodeptr = tmpmcodeptr;
3597
3598                                 /* create stack frame - keep 16-byte aligned */
3599
3600                                 M_AADD_IMM(REG_SP, -4 * 4, REG_SP);
3601
3602                                 /* push address of `rplpoint` struct */
3603
3604                                 disp = dseg_addaddress(cd, replacementpoint);
3605                                 M_ALD(REG_ITMP3, REG_PV, disp);
3606                                 M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
3607
3608                                 /* jump to replacement function */
3609
3610                                 disp = dseg_addaddress(cd, asm_replacement_out);
3611                                 M_ALD(REG_ITMP3, REG_PV, disp);
3612                                 M_MTCTR(REG_ITMP3);
3613                                 M_RTS;
3614                         }
3615                 }
3616         }
3617
3618         codegen_finish(jd);
3619
3620         /* everything's ok */
3621
3622         return true;
3623 }
3624
3625
3626 /* createcompilerstub **********************************************************
3627
3628    Creates a stub routine which calls the compiler.
3629         
3630 *******************************************************************************/
3631
3632 #define COMPILERSTUB_DATASIZE    3 * SIZEOF_VOID_P
3633 #define COMPILERSTUB_CODESIZE    4 * 4
3634
3635 #define COMPILERSTUB_SIZE        COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
3636
3637
3638 u1 *createcompilerstub(methodinfo *m)
3639 {
3640         u1          *s;                     /* memory to hold the stub            */
3641         ptrint      *d;
3642         codeinfo    *code;
3643         codegendata *cd;
3644         s4           dumpsize;
3645
3646         s = CNEW(u1, COMPILERSTUB_SIZE);
3647
3648         /* set data pointer and code pointer */
3649
3650         d = (ptrint *) s;
3651         s = s + COMPILERSTUB_DATASIZE;
3652
3653         /* mark start of dump memory area */
3654
3655         dumpsize = dump_size();
3656
3657         cd = DNEW(codegendata);
3658         cd->mcodeptr = s;
3659
3660         /* Store the codeinfo pointer in the same place as in the
3661            methodheader for compiled methods. */
3662
3663         code = code_codeinfo_new(m);
3664
3665         d[0] = (ptrint) asm_call_jit_compiler;
3666         d[1] = (ptrint) m;
3667         d[2] = (ptrint) code;
3668
3669         M_ALD_INTERN(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P);
3670         M_ALD_INTERN(REG_PV, REG_PV, -3 * SIZEOF_VOID_P);
3671         M_MTCTR(REG_PV);
3672         M_RTS;
3673
3674         md_cacheflush((u1 *) d, COMPILERSTUB_SIZE);
3675
3676 #if defined(ENABLE_STATISTICS)
3677         if (opt_stat)
3678                 count_cstub_len += COMPILERSTUB_SIZE;
3679 #endif
3680
3681         /* release dump area */
3682
3683         dump_release(dumpsize);
3684
3685         return s;
3686 }
3687
3688
3689 /* createnativestub ************************************************************
3690
3691    Creates a stub routine which calls a native method.
3692
3693 *******************************************************************************/
3694
3695 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3696 {
3697         methodinfo   *m;
3698         codeinfo     *code;
3699         codegendata  *cd;
3700         registerdata *rd;
3701         s4            stackframesize;       /* size of stackframe if needed       */
3702         methoddesc   *md;
3703         s4            nativeparams;
3704         s4            i, j;                 /* count variables                    */
3705         s4            t;
3706         s4            s1, s2, disp;
3707         s4            funcdisp;
3708
3709         /* get required compiler data */
3710
3711         m    = jd->m;
3712         code = jd->code;
3713         cd   = jd->cd;
3714         rd   = jd->rd;
3715
3716         /* set some variables */
3717
3718         md = m->parseddesc;
3719         nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3720
3721         /* calculate stackframe size */
3722
3723         stackframesize =
3724                 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3725                 sizeof(localref_table) / SIZEOF_VOID_P +
3726                 4 +                             /* 4 stackframeinfo arguments (darwin)*/
3727                 nmd->paramcount * 2 +           /* assume all arguments are doubles   */
3728                 nmd->memuse;
3729
3730         stackframesize = (stackframesize + 3) & ~3; /* keep stack 16-byte aligned */
3731
3732         /* create method header */
3733
3734         (void) dseg_addaddress(cd, code);                      /* CodeinfoPointer */
3735         (void) dseg_adds4(cd, stackframesize * 4);             /* FrameSize       */
3736         (void) dseg_adds4(cd, 0);                              /* IsSync          */
3737         (void) dseg_adds4(cd, 0);                              /* IsLeaf          */
3738         (void) dseg_adds4(cd, 0);                              /* IntSave         */
3739         (void) dseg_adds4(cd, 0);                              /* FltSave         */
3740         (void) dseg_addlinenumbertablesize(cd);
3741         (void) dseg_adds4(cd, 0);                              /* ExTableSize     */
3742
3743         /* generate code */
3744
3745         M_MFLR(REG_ZERO);
3746         M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
3747         M_STDU(REG_SP, REG_SP, -(stackframesize * 8));
3748
3749         if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3750                 /* parent_argbase == stackframesize * 4 */
3751                 codegen_trace_args(jd, stackframesize * 4 , true);
3752
3753         /* get function address (this must happen before the stackframeinfo) */
3754
3755         funcdisp = dseg_addaddress(cd, f);
3756
3757 #if !defined(WITH_STATIC_CLASSPATH)
3758         if (f == NULL) {
3759                 codegen_addpatchref(cd, PATCHER_resolve_native, m, funcdisp);
3760
3761                 if (opt_showdisassemble)
3762                         M_NOP;
3763         }
3764 #endif
3765
3766         /* save integer and float argument registers */
3767
3768         j = 0;
3769
3770         for (i = 0; i < md->paramcount; i++) {
3771                 t = md->paramtypes[i].type;
3772
3773                 if (IS_INT_LNG_TYPE(t)) {
3774                         if (!md->params[i].inmemory) {
3775                                 s1 = md->params[i].regoff;
3776                                 if (IS_2_WORD_TYPE(t)) {
3777                                         M_IST(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3778                                         j++;
3779                                         M_IST(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3780                                 } else {
3781                                         M_IST(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3782                                 }
3783                                 j++;
3784                         }
3785                 }
3786         }
3787
3788         for (i = 0; i < md->paramcount; i++) {
3789                 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3790                         if (!md->params[i].inmemory) {
3791                                 s1 = md->params[i].regoff;
3792                                 M_DST(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 8);
3793                                 j++;
3794                         }
3795                 }
3796         }
3797
3798         /* create native stack info */
3799
3800         M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[0]);
3801         M_MOV(REG_PV, rd->argintregs[1]);
3802         M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[2]);
3803         M_ALD(rd->argintregs[3], REG_SP, stackframesize * 4 + LA_LR_OFFSET);
3804         disp = dseg_addaddress(cd, codegen_start_native_call);
3805         M_ALD(REG_ITMP1, REG_PV, disp);
3806         M_MTCTR(REG_ITMP1);
3807         M_JSR;
3808
3809         /* restore integer and float argument registers */
3810
3811         j = 0;
3812
3813         for (i = 0; i < md->paramcount; i++) {
3814                 t = md->paramtypes[i].type;
3815
3816                 if (IS_INT_LNG_TYPE(t)) {
3817                         if (!md->params[i].inmemory) {
3818                                 s1 = md->params[i].regoff;
3819
3820                                 if (IS_2_WORD_TYPE(t)) {
3821                                         M_ILD(rd->argintregs[GET_HIGH_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3822                                         j++;
3823                                         M_ILD(rd->argintregs[GET_LOW_REG(s1)], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3824                                 } else {
3825                                         M_ILD(rd->argintregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 4);
3826                                 }
3827                                 j++;
3828                         }
3829                 }
3830         }
3831
3832         for (i = 0; i < md->paramcount; i++) {
3833                 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3834                         if (!md->params[i].inmemory) {
3835                                 s1 = md->params[i].regoff;
3836                                 M_DLD(rd->argfltregs[s1], REG_SP, LA_SIZE + 4 * 4 + j * 8);
3837                                 j++;
3838                         }
3839                 }
3840         }
3841         
3842         /* copy or spill arguments to new locations */
3843
3844         for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3845                 t = md->paramtypes[i].type;
3846
3847                 if (IS_INT_LNG_TYPE(t)) {
3848                         if (!md->params[i].inmemory) {
3849                                 if (IS_2_WORD_TYPE(t))
3850                                         s1 = PACK_REGS(
3851                                                 rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
3852                                             rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
3853                                 else
3854                                         s1 = rd->argintregs[md->params[i].regoff];
3855
3856                                 if (!nmd->params[j].inmemory) {
3857                                         if (IS_2_WORD_TYPE(t)) {
3858                                                 s2 = PACK_REGS(
3859                                                    rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)],
3860                                                    rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]);
3861                                                 M_LNGMOVE(s1, s2);
3862                                         } else {
3863                                                 s2 = rd->argintregs[nmd->params[j].regoff];
3864                                                 M_INTMOVE(s1, s2);
3865                                         }
3866
3867                                 } else {
3868                                         s2 = nmd->params[j].regoff;
3869                                         if (IS_2_WORD_TYPE(t))
3870                                                 M_LST(s1, REG_SP, s2 * 4);
3871                                         else
3872                                                 M_IST(s1, REG_SP, s2 * 4);
3873                                 }
3874
3875                         } else {
3876                                 s1 = md->params[i].regoff + stackframesize;
3877                                 s2 = nmd->params[j].regoff;
3878
3879                                 M_ILD(REG_ITMP1, REG_SP, s1 * 4);
3880                                 if (IS_2_WORD_TYPE(t))
3881                                         M_ILD(REG_ITMP2, REG_SP, s1 * 4 + 4);
3882
3883                                 M_IST(REG_ITMP1, REG_SP, s2 * 4);
3884                                 if (IS_2_WORD_TYPE(t))
3885                                         M_IST(REG_ITMP2, REG_SP, s2 * 4 + 4);
3886                         }
3887
3888                 } else {
3889                         /* We only copy spilled float arguments, as the float
3890                            argument registers keep unchanged. */
3891
3892                         if (md->params[i].inmemory) {
3893                                 s1 = md->params[i].regoff + stackframesize;
3894                                 s2 = nmd->params[j].regoff;
3895
3896                                 if (IS_2_WORD_TYPE(t)) {
3897                                         M_DLD(REG_FTMP1, REG_SP, s1 * 4);
3898                                         M_DST(REG_FTMP1, REG_SP, s2 * 4);
3899
3900                                 } else {
3901                                         M_FLD(REG_FTMP1, REG_SP, s1 * 4);
3902                                         M_FST(REG_FTMP1, REG_SP, s2 * 4);
3903                                 }
3904                         }
3905                 }
3906         }
3907
3908         /* put class into second argument register */
3909
3910         if (m->flags & ACC_STATIC) {
3911                 disp = dseg_addaddress(cd, m->class);
3912                 M_ALD(rd->argintregs[1], REG_PV, disp);
3913         }
3914
3915         /* put env into first argument register */
3916
3917         disp = dseg_addaddress(cd, _Jv_env);
3918         M_ALD(rd->argintregs[0], REG_PV, disp);
3919
3920         /* generate the actual native call */
3921
3922         M_ALD(REG_ITMP3, REG_PV, funcdisp);
3923         M_MTCTR(REG_ITMP3);
3924         M_JSR;
3925
3926         /* save return value */
3927
3928         if (md->returntype.type != TYPE_VOID) {
3929                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
3930                         M_LST(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
3931                 }
3932                 else {
3933                         if (IS_2_WORD_TYPE(md->returntype.type))
3934                                 M_DST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
3935                         else
3936                                 M_FST(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);    /* FIXME, needed ?*/
3937                 }
3938         }
3939
3940         /* print call trace */
3941
3942         if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3943                  /* just restore the value we need, don't care about the other */
3944
3945                 if (md->returntype.type != TYPE_VOID) {
3946                         if (IS_INT_LNG_TYPE(md->returntype.type)) {
3947                                 M_LLD(REG_RESULT, REG_SP, LA_SIZE + 1 * 8);
3948                         }
3949                         else {
3950                                 if (IS_2_WORD_TYPE(md->returntype.type))
3951                                         M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);
3952                                 else
3953                                         M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 8);    /* FIXME, needed ? */
3954                         }
3955                 }
3956
3957                 M_LDA(REG_SP, REG_SP, -(LA_SIZE + PA_SIZE + (1 + 1 + 1 + 1) * 8));
3958
3959                 /* keep this order */
3960                 switch (md->returntype.type) {
3961                 case TYPE_INT:
3962                 case TYPE_ADR:
3963 #if defined(__DARWIN__)
3964                         M_MOV(REG_RESULT, rd->argintregs[2]);
3965                         M_CLR(rd->argintregs[1]);
3966 #else
3967                         M_MOV(REG_RESULT, rd->argintregs[3]);
3968                         M_CLR(rd->argintregs[2]);
3969 #endif
3970                         break;
3971
3972                 case TYPE_LNG:
3973 #if defined(__DARWIN__)
3974                         M_MOV(REG_RESULT, rd->argintregs[1]);
3975 #else
3976                         M_MOV(REG_RESULT, rd->argintregs[2]);
3977 #endif
3978                         break;
3979                 }
3980
3981                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3982                 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3983                 disp = dseg_addaddress(cd, m);
3984                 M_ALD(rd->argintregs[0], REG_PV, disp);
3985
3986                 disp = dseg_addaddress(cd, builtin_displaymethodstop);
3987                 M_ALD(REG_ITMP2, REG_PV, disp);
3988                 M_MTCTR(REG_ITMP2);
3989                 M_JSR;
3990
3991                 M_LDA(REG_SP, REG_SP, LA_SIZE + PA_SIZE + (1 + 1+ 1 + 1) * 8);
3992         }
3993
3994         /* remove native stackframe info */
3995
3996         M_AADD_IMM(REG_SP, stackframesize * 4, rd->argintregs[0]);
3997         disp = dseg_addaddress(cd, codegen_finish_native_call);
3998         M_ALD(REG_ITMP1, REG_PV, disp);
3999         M_MTCTR(REG_ITMP1);
4000         M_JSR;
4001         M_MOV(REG_RESULT, REG_ITMP1_XPTR);
4002
4003         /* restore return value */
4004
4005         if (md->returntype.type != TYPE_VOID) {
4006                 if (IS_INT_LNG_TYPE(md->returntype.type)) {
4007                         if (IS_2_WORD_TYPE(md->returntype.type))
4008                                 /*M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 2 * 4);FIXME*/
4009                         M_ILD(REG_RESULT, REG_SP, LA_SIZE + 1 * 4);
4010                 }
4011                 else {
4012                         if (IS_2_WORD_TYPE(md->returntype.type))
4013                                 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4014                         else
4015                                 M_FLD(REG_FRESULT, REG_SP, LA_SIZE + 1 * 4);
4016                 }
4017         }
4018
4019         M_ALD(REG_ITMP2_XPC, REG_SP, stackframesize * 8 + LA_LR_OFFSET);
4020         M_MTLR(REG_ITMP2_XPC);
4021         M_LDA(REG_SP, REG_SP, stackframesize * 8); /* remove stackframe           */
4022
4023         /* check for exception */
4024
4025         M_TST(REG_ITMP1_XPTR);
4026         M_BNE(1);                           /* if no exception then return        */
4027
4028         M_RET;
4029
4030         /* handle exception */
4031
4032         M_LADD_IMM(REG_ITMP2_XPC, -4, REG_ITMP2_XPC);  /* exception address       */
4033
4034         disp = dseg_addaddress(cd, asm_handle_nat_exception);
4035         M_ALD(REG_ITMP3, REG_PV, disp);
4036         M_MTCTR(REG_ITMP3);
4037         M_RTS;
4038
4039         /* generate patcher stub call code */
4040
4041         {
4042                 patchref *pref;
4043                 u4        mcode;
4044                 u1       *savedmcodeptr;
4045                 u1       *tmpmcodeptr;
4046
4047                 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4048                         /* Get machine code which is patched back in later. The
4049                            call is 1 instruction word long. */
4050
4051                         tmpmcodeptr = cd->mcodebase + pref->branchpos;
4052
4053                         mcode = *((u4 *) tmpmcodeptr);
4054
4055                         /* Patch in the call to call the following code (done at
4056                            compile time). */
4057
4058                         savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr          */
4059                         cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position */
4060
4061                         disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
4062                         M_BL(disp);
4063
4064                         cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr   */
4065
4066                         /* create stack frame - keep stack 16-byte aligned */
4067
4068                         M_AADD_IMM(REG_SP, -8 * 8, REG_SP);
4069
4070                         /* move return address onto stack */
4071
4072                         M_MFLR(REG_ZERO);
4073                         M_AST(REG_ZERO, REG_SP, 5 * 8);
4074
4075                         /* move pointer to java_objectheader onto stack */
4076
4077 #if defined(ENABLE_THREADS)
4078                         /* order reversed because of data segment layout */
4079
4080                         (void) dseg_addaddress(cd, NULL);                         /* flcword    */
4081                         (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
4082                         disp = dseg_addaddress(cd, NULL);                         /* vftbl      */
4083
4084                         M_LDA(REG_ITMP3, REG_PV, disp);
4085                         M_AST(REG_ITMP3, REG_SP, 4 * 8);
4086 #else
4087                         /* do nothing */
4088 #endif
4089
4090                         /* move machine code onto stack */
4091
4092                         disp = dseg_adds4(cd, mcode);
4093                         M_ILD(REG_ITMP3, REG_PV, disp);
4094                         M_IST(REG_ITMP3, REG_SP, 3 * 8);
4095
4096                         /* move class/method/field reference onto stack */
4097
4098                         disp = dseg_addaddress(cd, pref->ref);
4099                         M_ALD(REG_ITMP3, REG_PV, disp);
4100                         M_AST(REG_ITMP3, REG_SP, 2 * 8);
4101
4102                         /* move data segment displacement onto stack */
4103
4104                         disp = dseg_addaddress(cd, pref->disp);
4105                         M_ILD(REG_ITMP3, REG_PV, disp);
4106                         M_IST(REG_ITMP3, REG_SP, 1 * 8);
4107
4108                         /* move patcher function pointer onto stack */
4109
4110                         disp = dseg_addaddress(cd, pref->patcher);
4111                         M_ALD(REG_ITMP3, REG_PV, disp);
4112                         M_AST(REG_ITMP3, REG_SP, 0 * 8);
4113
4114                         disp = dseg_addaddress(cd, asm_patcher_wrapper);
4115                         M_ALD(REG_ITMP3, REG_PV, disp);
4116                         M_MTCTR(REG_ITMP3);
4117                         M_RTS;
4118                 }
4119         }
4120
4121         codegen_finish(jd);
4122
4123         return code->entrypoint;
4124 }
4125
4126
4127 void codegen_trace_args(jitdata *jd, s4 stackframesize, bool nativestub)
4128 {
4129         methodinfo   *m;
4130         codegendata  *cd;
4131         registerdata *rd;
4132         s4 s1, p, t, d;
4133         int stack_off;
4134         int stack_size;
4135         methoddesc *md;
4136
4137         /* get required compiler data */
4138
4139         m  = jd->m;
4140         cd = jd->cd;
4141         rd = jd->rd;
4142
4143         md = m->parseddesc;
4144         
4145         if (!nativestub)
4146                 M_MFLR(REG_ITMP3);
4147         /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
4148         /* For Darwin:                                                        */
4149         /* LA + TRACE_ARGS_NUM u8 args + methodinfo + LR                      */
4150         /* LA_SIZE(=6*4) + 8*8         + 4          + 4  + 0(Padding)         */
4151         /* 6 * 4 + 8 * 8 + 2 * 4 = 12 * 8 = 6 * 16                            */
4152         /* For Linux:                                                         */
4153         /* LA + (TRACE_ARGS_NUM - INT_ARG_CNT/2) u8 args + methodinfo         */
4154         /* + INT_ARG_CNT * 4 ( save integer registers) + LR + 8 + 8 (Padding) */
4155         /* LA_SIZE(=2*4) + 4 * 8 + 4 + 8 * 4 + 4 + 8                          */
4156         /* 2 * 4 + 4 * 8 + 10 * 4 + 1 * 8 + 8= 12 * 8 = 6 * 16                */
4157         
4158         /* in nativestubs no Place to save the LR (Link Register) would be needed */
4159         /* but since the stack frame has to be aligned the 4 Bytes would have to  */
4160         /* be padded again */
4161
4162 #if defined(__DARWIN__)
4163         stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
4164 #else
4165         stack_size = 6 * 16;
4166 #endif
4167         M_LDA(REG_SP, REG_SP, -stack_size);
4168
4169         /* Save LR */
4170         if (!nativestub)
4171                 M_IST(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4172
4173         M_CLR(REG_ITMP1);    /* clear help register */
4174
4175         /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
4176 #if defined(__DARWIN__)
4177         /* Copy Params starting from first to Stack                          */
4178         /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs    */ 
4179         /* are saved                                                         */
4180         p = 0;
4181 #else
4182         /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in   */
4183         /* integer argument regs                                             */
4184         /* all integer argument registers have to be saved                   */
4185         for (p = 0; p < 8; p++) {
4186                 d = rd->argintregs[p];
4187                 /* save integer argument registers */
4188                 M_IST(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4189         }
4190         p = 4;
4191 #endif
4192         stack_off = LA_SIZE;
4193         for (; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
4194                 t = md->paramtypes[p].type;
4195                 if (IS_INT_LNG_TYPE(t)) {
4196                         if (!md->params[p].inmemory) { /* Param in Arg Reg */
4197                                 if (IS_2_WORD_TYPE(t)) {
4198                                         M_IST(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4199                                                   , REG_SP, stack_off);
4200                                         M_IST(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4201                                                   , REG_SP, stack_off + 4);
4202                                 } else {
4203                                         M_IST(REG_ITMP1, REG_SP, stack_off);
4204                                         M_IST(rd->argintregs[md->params[p].regoff]
4205                                                   , REG_SP, stack_off + 4);
4206                                 }
4207                         } else { /* Param on Stack */
4208                                 s1 = (md->params[p].regoff + stackframesize) * 4 
4209                                         + stack_size;
4210                                 if (IS_2_WORD_TYPE(t)) {
4211                                         M_ILD(REG_ITMP2, REG_SP, s1);
4212                                         M_IST(REG_ITMP2, REG_SP, stack_off);
4213                                         M_ILD(REG_ITMP2, REG_SP, s1 + 4);
4214                                         M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4215                                 } else {
4216                                         M_IST(REG_ITMP1, REG_SP, stack_off);
4217                                         M_ILD(REG_ITMP2, REG_SP, s1);
4218                                         M_IST(REG_ITMP2, REG_SP, stack_off + 4);
4219                                 }
4220                         }
4221                 } else { /* IS_FLT_DBL_TYPE(t) */
4222                         if (!md->params[p].inmemory) { /* in Arg Reg */
4223                                 s1 = rd->argfltregs[md->params[p].regoff];
4224                                 if (!IS_2_WORD_TYPE(t)) {
4225                                         M_IST(REG_ITMP1, REG_SP, stack_off);
4226                                         M_FST(s1, REG_SP, stack_off + 4);
4227                                 } else {
4228                                         M_DST(s1, REG_SP, stack_off);
4229                                 }
4230                         } else { /* on Stack */
4231                                 /* this should not happen */
4232                         }
4233                 }
4234         }
4235
4236         /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
4237 #if defined(__DARWIN__)
4238         for (p = 0; p < 8; p++) {
4239                 d = rd->argintregs[p];
4240                 M_ILD(d, REG_SP, LA_SIZE + p * 4);
4241         }
4242 #else
4243         /* LINUX */
4244         /* Set integer and float argument registers vor trace_args call */
4245         /* offset to saved integer argument registers                   */
4246         stack_off = LA_SIZE + 4 * 8 + 4;
4247         for (p = 0; (p < 4) && (p < md->paramcount); p++) {
4248                 t = md->paramtypes[p].type;
4249                 if (IS_INT_LNG_TYPE(t)) {
4250                         /* "stretch" int types */
4251                         if (!IS_2_WORD_TYPE(t)) {
4252                                 M_CLR(rd->argintregs[2 * p]);
4253                                 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off);
4254                                 stack_off += 4;
4255                         } else {
4256                                 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off + 4);
4257                                 M_ILD(rd->argintregs[2 * p], REG_SP,stack_off);
4258                                 stack_off += 8;
4259                         }
4260                 } else { /* Float/Dbl */
4261                         if (!md->params[p].inmemory) { /* Param in Arg Reg */
4262                                 /* use reserved Place on Stack (sp + 5 * 16) to copy  */
4263                                 /* float/double arg reg to int reg                    */
4264                                 s1 = rd->argfltregs[md->params[p].regoff];
4265                                 if (!IS_2_WORD_TYPE(t)) {
4266                                         M_FST(s1, REG_SP, 5 * 16);
4267                                         M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16);
4268                                         M_CLR(rd->argintregs[2 * p]);
4269                                 } else {
4270                                         M_DST(s1, REG_SP, 5 * 16);
4271                                         M_ILD(rd->argintregs[2 * p + 1], REG_SP,  5 * 16 + 4);
4272                                         M_ILD(rd->argintregs[2 * p], REG_SP, 5 * 16);
4273                                 }
4274                         }
4275                 }
4276         }
4277 #endif
4278
4279         /* put methodinfo pointer on Stackframe */
4280         p = dseg_addaddress(cd, m);
4281         M_ALD(REG_ITMP1, REG_PV, p);
4282 #if defined(__DARWIN__)
4283         M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8); 
4284 #else
4285         M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
4286 #endif
4287         p = dseg_addaddress(cd, builtin_trace_args);
4288         M_ALD(REG_ITMP2, REG_PV, p);
4289         M_MTCTR(REG_ITMP2);
4290         M_JSR;
4291
4292 #if defined(__DARWIN__)
4293         /* restore integer argument registers from the reserved stack space */
4294
4295         stack_off = LA_SIZE;
4296         for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; 
4297                  p++, stack_off += 8) {
4298                 t = md->paramtypes[p].type;
4299
4300                 if (IS_INT_LNG_TYPE(t)) {
4301                         if (!md->params[p].inmemory) {
4302                                 if (IS_2_WORD_TYPE(t)) {
4303                                         M_ILD(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4304                                                   , REG_SP, stack_off);
4305                                         M_ILD(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4306                                                   , REG_SP, stack_off + 4);
4307                                 } else {
4308                                         M_ILD(rd->argintregs[md->params[p].regoff]
4309                                                   , REG_SP, stack_off + 4);
4310                                 }
4311                         }
4312                 }
4313         }
4314 #else
4315         /* LINUX */
4316         for (p = 0; p < 8; p++) {
4317                 d = rd->argintregs[p];
4318                 /* save integer argument registers */
4319                 M_ILD(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4320         }
4321 #endif
4322
4323         if (!nativestub)
4324                 M_ILD(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4325
4326         M_LDA(REG_SP, REG_SP, stack_size);
4327
4328         if (!nativestub)
4329                 M_MTLR(REG_ITMP3);
4330 }
4331
4332
4333 /*
4334  * These are local overrides for various environment variables in Emacs.
4335  * Please do not remove this and leave it at the end of the file, where
4336  * Emacs will automagically detect them.
4337  * ---------------------------------------------------------------------
4338  * Local variables:
4339  * mode: c
4340  * indent-tabs-mode: t
4341  * c-basic-offset: 4
4342  * tab-width: 4
4343  * End:
4344  * vim:noexpandtab:sw=4:ts=4:
4345  */