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