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