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