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