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