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