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