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