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