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