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