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