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