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