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