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