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