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