1 /* src/vm/jit/s390/codegen.c - machine code generator for s390
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
8 This file is part of CACAO.
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.
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.
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
34 #include "native/jni.h"
35 #include "native/localref.h"
36 #include "native/native.h"
38 #include "mm/memory.h"
40 #if defined(ENABLE_THREADS)
41 # include "threads/lock-common.h"
42 # include "threads/native/lock.h"
45 #include "vmcore/loader.h"
46 #include "vmcore/options.h"
47 #include "vmcore/statistics.h"
48 #include "vm/builtin.h"
49 #include "vm/exceptions.h"
50 #include "vm/global.h"
51 #include "vm/jit/abi.h"
52 #if defined(ENABLE_LSRA)
53 # include "vm/jit/allocator/lsra.h"
55 #include "vm/jit/asmpart.h"
56 #include "vm/jit/codegen-common.h"
57 #include "vm/jit/dseg.h"
58 #include "vm/jit/emit-common.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/methodheader.h"
61 #include "vm/jit/parse.h"
62 #include "vm/jit/patcher-common.h"
63 #include "vm/jit/reg.h"
64 #include "vm/jit/replace.h"
65 #include "vm/jit/s390/arch.h"
66 #include "vm/jit/s390/codegen.h"
67 #include "vm/jit/s390/emit.h"
68 #include "vm/jit/s390/md-abi.h"
69 #include "vm/jit/stacktrace.h"
71 #include "vm/stringlocal.h"
74 /* DO__LOG generates a call to do__log. No registers are destroyed,
75 * so you may use it anywhere. regs is an array containing all general
79 static void do__log(u4 *regs) {
80 /* insert stuff here */
84 N_AHI(REG_SP, -200); \
85 N_STM(R0, R15, 96, REG_SP); \
86 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
87 N_LA(R2, 96, RN, REG_SP); \
89 N_LM(R0, R15, 96, REG_SP); \
92 #define SUPPORT_HERCULES 1
94 /* codegen *********************************************************************
96 Generates machine code.
98 *******************************************************************************/
102 Layout of stackframe:
105 ===============================================================================
106 return_address (stackframesize - 1) * 8
107 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
109 saved_int_reg[rd->savintreguse]
110 saved_flt_reg[FLT_SAV_CNT - 1]
112 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
114 return_value_tmp (rd->memuse + 1) * 8
115 monitorenter_argument (rd->memuse) * 8
117 local[rd->memuse - 1] (rd->memuse - 1) * 8
125 bool codegen_emit(jitdata *jd)
131 s4 len, s1, s2, s3, d, dd, disp;
134 varinfo *var, *var1, *var2, *dst;
138 constant_classref *cr;
139 unresolved_class *uc;
140 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
141 unresolved_method *um;
142 builtintable_entry *bte;
145 unresolved_field *uf;
148 rplpoint *replacementpoint;
152 /* get required compiler data */
159 /* prevent compiler warnings */
172 /* space to save used callee saved registers */
174 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
175 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
177 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
180 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
183 #if defined(ENABLE_THREADS)
184 /* Space to save argument of monitor_enter and Return Values to
185 survive monitor_exit. The stack position for the argument can
186 not be shared with place to save the return register
187 since both values reside in R2. */
189 if (checksync && code_is_synchronized(code)) {
190 /* 1 slot space to save argument of monitor_enter */
191 /* 1 slot to temporary store return value before monitor_exit */
192 cd->stackframesize += 2;
196 /* Keep stack of non-leaf functions 16-byte aligned for calls into
197 native code e.g. libc or jni (alignment problems with
200 if (!code_is_leafmethod(code) || opt_verbosecall )
201 /* TODO really 16 bytes ? */
202 cd->stackframesize = (cd->stackframesize + 2) & ~2;
204 /* create method header */
206 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
207 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
209 /* IsSync contains the offset relative to the stack pointer for the
210 argument of monitor_exit used in the exception handler. Since the
211 offset could be zero and give a wrong meaning of the flag it is
214 /* XXX Remove this "offset by one". */
216 code->synchronizedoffset = (rd->memuse + 1) * 8;
218 /* REMOVEME dummy IsSync */
219 (void) dseg_add_unique_s4(cd, 0);
221 /* REMOVEME: We still need it for exception handling in assembler. */
223 if (code_is_leafmethod(code))
224 (void) dseg_add_unique_s4(cd, 1);
226 (void) dseg_add_unique_s4(cd, 0);
228 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
229 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
231 (void) dseg_addlinenumbertablesize(cd);
233 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
235 /* create exception table */
237 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
238 dseg_add_target(cd, ex->start);
239 dseg_add_target(cd, ex->end);
240 dseg_add_target(cd, ex->handler);
241 (void) dseg_add_unique_address(cd, ex->catchtype.any);
246 M_AADD_IMM(N_PV_OFFSET, REG_PV);
248 /* create stack frame (if necessary) */
250 if (cd->stackframesize) {
251 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
254 /* store return address */
256 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
258 /* generate method profiling code */
260 #if defined(ENABLE_PROFILING)
261 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
262 /* count frequency */
263 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
264 ICONST(REG_ITMP2, 1);
265 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
266 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
272 /* save used callee saved registers and return address */
274 p = cd->stackframesize - 1;
276 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
277 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
279 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
280 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
283 /* take arguments out of register or stack frame */
287 for (p = 0, l = 0; p < md->paramcount; p++) {
288 t = md->paramtypes[p].type;
289 varindex = jd->local_map[l * 5 + t];
293 if (IS_2_WORD_TYPE(t))
296 if (varindex == UNUSED)
301 s1 = md->params[p].regoff;
303 if (IS_INT_LNG_TYPE(t)) { /* integer args */
304 if (IS_2_WORD_TYPE(t)) {
312 if (!md->params[p].inmemory) { /* register arguments */
313 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
314 if (IS_2_WORD_TYPE(t)) {
315 M_LNGMOVE(s2, var->vv.regoff);
317 M_INTMOVE(s2, var->vv.regoff);
319 } else { /* reg arg -> spilled */
320 if (IS_2_WORD_TYPE(t)) {
321 M_LST(s2, REG_SP, var->vv.regoff);
323 M_IST(s2, REG_SP, var->vv.regoff);
327 } else { /* stack arguments */
328 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
329 if (IS_2_WORD_TYPE(t)) {
330 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
332 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
334 } else { /* stack arg -> spilled */
335 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
339 } else { /* floating args */
340 if (!md->params[p].inmemory) { /* register arguments */
342 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
343 M_FLTMOVE(s2, var->vv.regoff);
345 } else { /* reg arg -> spilled */
346 if (IS_2_WORD_TYPE(t))
347 M_DST(s2, REG_SP, var->vv.regoff);
349 M_FST(s2, REG_SP, var->vv.regoff);
352 } else { /* stack arguments */
353 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
354 if (IS_2_WORD_TYPE(t))
355 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
358 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
360 } else { /* stack-arg -> spilled */
361 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
362 var->vv.regoff = cd->stackframesize * 8 + s1;
368 /* save monitorenter argument */
370 #if defined(ENABLE_THREADS)
371 if (checksync && code_is_synchronized(code)) {
372 /* stack offset for monitor argument */
377 if (opt_verbosecall) {
378 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
380 for (p = 0; p < INT_ARG_CNT; p++)
381 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
383 for (p = 0; p < FLT_ARG_CNT; p++)
384 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
386 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
390 /* decide which monitor enter function to call */
392 if (m->flags & ACC_STATIC) {
393 disp = dseg_add_address(cd, &m->class->object.header);
394 M_ALD_DSEG(REG_A0, disp);
398 M_BNE(SZ_BRC + SZ_ILL);
399 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
402 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
403 M_ALD_DSEG(REG_ITMP2, disp);
405 M_AST(REG_A0, REG_SP, s1 * 8);
407 M_ASUB_IMM(96, REG_SP);
409 M_AADD_IMM(96, REG_SP);
412 if (opt_verbosecall) {
413 for (p = 0; p < INT_ARG_CNT; p++)
414 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
416 for (p = 0; p < FLT_ARG_CNT; p++)
417 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
419 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
426 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
427 emit_verbosecall_enter(jd);
428 #endif /* !defined(NDEBUG) */
432 /* end of header generation */
434 /* create replacement points */
436 REPLACEMENT_POINTS_INIT(cd, jd);
438 /* walk through all basic blocks */
440 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
442 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
444 if (bptr->flags >= BBREACHED) {
446 /* branch resolving */
448 codegen_resolve_branchrefs(cd, bptr);
450 /* handle replacement points */
452 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
454 /* copy interface registers to their destination */
459 #if defined(ENABLE_PROFILING)
460 /* generate basicblock profiling code */
462 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
463 /* count frequency */
465 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
466 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
467 ICONST(REG_ITMP2, 1);
468 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
469 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
471 /* if this is an exception handler, start profiling again */
473 if (bptr->type == BBTYPE_EXH)
478 #if defined(ENABLE_LSRA)
482 src = bptr->invars[len];
483 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
484 if (bptr->type == BBTYPE_EXH) {
485 /* d = reg_of_var(rd, src, REG_ITMP1); */
486 if (!IS_INMEMORY(src->flags))
490 M_INTMOVE(REG_ITMP3_XPTR, d);
491 emit_store(jd, NULL, src, d);
501 var = VAR(bptr->invars[len]);
502 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
503 if (bptr->type == BBTYPE_EXH) {
504 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
505 M_INTMOVE(REG_ITMP3_XPTR, d);
506 emit_store(jd, NULL, var, d);
510 assert((var->flags & INOUT));
513 #if defined(ENABLE_LSRA)
516 /* walk through all instructions */
521 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
522 if (iptr->line != currentline) {
523 dseg_addlinenumber(cd, iptr->line);
524 currentline = iptr->line;
527 MCODECHECK(1024); /* 1KB should be enough */
530 case ICMD_NOP: /* ... ==> ... */
531 case ICMD_POP: /* ..., value ==> ... */
532 case ICMD_POP2: /* ..., value, value ==> ... */
535 case ICMD_INLINE_START:
537 REPLACEMENT_POINT_INLINE_START(cd, iptr);
540 case ICMD_INLINE_BODY:
542 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
543 dseg_addlinenumber_inline_start(cd, iptr);
544 dseg_addlinenumber(cd, iptr->line);
547 case ICMD_INLINE_END:
549 dseg_addlinenumber_inline_end(cd, iptr);
550 dseg_addlinenumber(cd, iptr->line);
553 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
554 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
555 emit_nullpointer_check(cd, iptr, s1);
558 /* constant operations ************************************************/
560 case ICMD_ICONST: /* ... ==> ..., constant */
561 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
562 ICONST(d, iptr->sx.val.i);
563 emit_store_dst(jd, iptr, d);
566 case ICMD_LCONST: /* ... ==> ..., constant */
568 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
569 LCONST(d, iptr->sx.val.l);
570 emit_store_dst(jd, iptr, d);
573 case ICMD_FCONST: /* ... ==> ..., constant */
574 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
575 disp = dseg_add_float(cd, iptr->sx.val.f);
576 M_FLD_DSEG(d, disp, REG_ITMP1);
577 emit_store_dst(jd, iptr, d);
580 case ICMD_DCONST: /* ... ==> ..., constant */
581 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
582 disp = dseg_add_double(cd, iptr->sx.val.d);
583 M_DLD_DSEG(d, disp, REG_ITMP1);
584 emit_store_dst(jd, iptr, d);
587 case ICMD_ACONST: /* ... ==> ..., constant */
588 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
590 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
591 cr = iptr->sx.val.c.ref;
592 disp = dseg_add_unique_address(cd, cr);
594 /* PROFILE_CYCLE_STOP; */
596 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
599 /* PROFILE_CYCLE_START; */
603 if (iptr->sx.val.anyptr == 0) {
606 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
609 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
610 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
612 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
614 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
620 emit_store_dst(jd, iptr, d);
624 /* load/store/copy/move operations ************************************/
626 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
627 case ICMD_ALOAD: /* s1 = local variable */
631 case ICMD_ISTORE: /* ..., value ==> ... */
642 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
646 /* integer operations *************************************************/
648 case ICMD_INEG: /* ..., value ==> ..., - value */
650 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
651 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
653 emit_store_dst(jd, iptr, d);
657 case ICMD_LNEG: /* ..., value ==> ..., - value */
659 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
660 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
661 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
662 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
663 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
664 N_AHI(GET_HIGH_REG(d), -1);
665 emit_store_dst(jd, iptr, d);
668 case ICMD_I2L: /* ..., value ==> ..., value */
670 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
671 if (! N_IS_EVEN_ODD(d)) {
672 d = REG_ITMP31_PACKED;
674 assert(N_IS_EVEN_ODD(d));
676 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
678 M_INTMOVE(s1, GET_HIGH_REG(d));
679 M_SRDA_IMM(32, GET_HIGH_REG(d));
681 emit_copy_dst(jd, iptr, d);
682 emit_store_dst(jd, iptr, d);
685 case ICMD_L2I: /* ..., value ==> ..., value */
686 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
687 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
688 M_INTMOVE(GET_LOW_REG(s1), d);
689 emit_store_dst(jd, iptr, d);
692 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
693 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
694 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
698 emit_store_dst(jd, iptr, d);
701 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
702 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
703 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
707 emit_store_dst(jd, iptr, d);
710 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
712 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
713 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
717 emit_store_dst(jd, iptr, d);
720 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
722 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
723 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
724 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
731 emit_store_dst(jd, iptr, d);
736 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
737 /* sx.val.i = constant */
738 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
739 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
742 if (N_VALID_IMM(iptr->sx.val.i)) {
743 M_IADD_IMM(iptr->sx.val.i, d);
745 ICONST(REG_ITMP2, iptr->sx.val.i);
746 M_IADD(REG_ITMP2, d);
748 emit_store_dst(jd, iptr, d);
751 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
753 /* M, (r, q) -> (r, q) */
755 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
757 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
758 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
759 dd = GET_HIGH_REG(d);
768 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
769 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
779 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
780 N_AHI(GET_HIGH_REG(d), 1);
782 emit_store_dst(jd, iptr, d);
785 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
786 /* sx.val.l = constant */
788 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
789 dd = GET_HIGH_REG(d);
791 s1 = emit_load_s1_high(jd, iptr, dd);
792 s3 = iptr->sx.val.l >> 32;
796 if (N_VALID_IMM(s3)) {
799 ICONST(REG_ITMP3, s3);
800 M_IADD(REG_ITMP3, dd);
804 s1 = emit_load_s1_low(jd, iptr, dd);
805 s3 = iptr->sx.val.l & 0xffffffff;
806 ICONST(REG_ITMP3, s3);
809 N_ALR(dd, REG_ITMP3);
811 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
812 N_AHI(GET_HIGH_REG(d), 1);
814 emit_store_dst(jd, iptr, d);
817 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
819 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
820 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
821 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
823 M_INTMOVE(s1, REG_ITMP1);
824 M_ISUB(s2, REG_ITMP1);
825 M_INTMOVE(REG_ITMP1, d);
830 emit_store_dst(jd, iptr, d);
834 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
835 /* sx.val.i = constant */
837 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
838 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
841 if (N_VALID_IMM(-iptr->sx.val.i)) {
842 M_ISUB_IMM(iptr->sx.val.i, d);
844 ICONST(REG_ITMP2, iptr->sx.val.i);
845 M_ISUB(REG_ITMP2, d);
847 emit_store_dst(jd, iptr, d);
851 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
853 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
855 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
856 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
857 dd = GET_HIGH_REG(d);
860 M_INTMOVE(s2, REG_ITMP3);
867 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
868 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
872 M_INTMOVE(s2, REG_ITMP3);
879 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
880 N_AHI(GET_HIGH_REG(d), -1);
882 emit_store_dst(jd, iptr, d);
885 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
886 /* sx.val.l = constant */
888 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
890 dd = GET_HIGH_REG(d);
891 s1 = emit_load_s1_high(jd, iptr, dd);
892 s3 = iptr->sx.val.l >> 32;
896 if (N_VALID_IMM(-s3)) {
899 ICONST(REG_ITMP3, s3);
900 M_ISUB(REG_ITMP3, dd);
904 s1 = emit_load_s1_low(jd, iptr, dd);
905 s3 = iptr->sx.val.l & 0xffffffff;
906 ICONST(REG_ITMP3, s3);
909 N_SLR(dd, REG_ITMP3);
911 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
912 N_AHI(GET_HIGH_REG(d), -1);
914 emit_store_dst(jd, iptr, d);
917 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
919 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
920 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
921 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
928 emit_store_dst(jd, iptr, d);
932 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
933 /* sx.val.i = constant */
934 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
935 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
937 if (iptr->sx.val.i == 2) {
939 } else if (N_VALID_IMM(iptr->sx.val.i)) {
940 M_IMUL_IMM(iptr->sx.val.i, d);
942 disp = dseg_add_s4(cd, iptr->sx.val.i);
943 M_ILD_DSEG(REG_ITMP2, disp);
944 M_IMUL(REG_ITMP2, d);
946 emit_store_dst(jd, iptr, d);
949 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
950 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
952 /* load s1 into r0 */
954 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
955 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
956 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
958 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
960 /* extend s1 to long */
962 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
966 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
972 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
973 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
976 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
977 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
981 emit_store_dst(jd, iptr, d);
985 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
986 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
988 bte = iptr->sx.s23.s3.bte;
991 /* test s2 for zero */
993 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
994 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
995 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
996 emit_arithmetic_check(cd, iptr, REG_ITMP3);
1000 disp = dseg_add_functionptr(cd, bte->fp);
1002 /* load arguments */
1004 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
1006 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
1007 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
1011 M_ASUB_IMM(96, REG_SP);
1012 M_ALD_DSEG(REG_ITMP2, disp);
1013 M_JSR(REG_RA, REG_ITMP2);
1014 M_AADD_IMM(96, REG_SP);
1018 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1019 M_LNGMOVE(REG_RESULT_PACKED, d);
1020 emit_store_dst(jd, iptr, d);
1024 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1025 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1026 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1028 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1029 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1030 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1032 /* Use only 5 bits of sencond operand. */
1034 M_INTMOVE(s2, REG_ITMP2);
1036 ICONST(REG_ITMP3, 0x1F);
1037 M_IAND(REG_ITMP3, s2);
1041 switch (iptr->opc) {
1054 emit_store_dst(jd, iptr, d);
1057 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1058 /* sx.val.i = constant */
1062 assert(iptr->sx.val.i <= 32);
1064 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1065 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1072 s3 = (1 << iptr->sx.val.i) - 1;
1074 if (N_VALID_IMM(s3)) {
1077 ICONST(REG_ITMP1, -1);
1078 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1079 M_IADD(REG_ITMP1, d);
1082 N_BRC_BACK_PATCH(ref);
1084 M_SRA_IMM(iptr->sx.val.i, d);
1086 emit_store_dst(jd, iptr, d);
1091 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1092 /* sx.val.i = constant */
1094 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1095 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1098 M_MOV(s1, REG_ITMP1);
1102 ICONST(REG_ITMP3, iptr->sx.val.i);
1105 M_IAND(REG_ITMP3, d);
1108 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1114 emit_store_dst(jd, iptr, d);
1118 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1119 /* sx.val.i = constant */
1120 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1121 /* sx.val.i = constant */
1122 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1123 /* sx.val.i = constant */
1124 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1125 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1129 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1131 switch (iptr->opc) {
1132 case ICMD_ISHLCONST:
1135 case ICMD_ISHRCONST:
1138 case ICMD_IUSHRCONST:
1145 emit_store_dst(jd, iptr, d);
1148 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1150 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1152 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1154 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1156 /* Use only 6 bits of second operand */
1158 M_INTMOVE(s2, REG_ITMP2);
1160 ICONST(REG_ITMP1, 0x3F);
1161 M_IAND(REG_ITMP1, s2);
1163 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1164 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1166 /* Destination must be even-odd pair */
1168 if (! N_IS_EVEN_ODD(d)) {
1169 d = REG_ITMP31_PACKED;
1172 assert(N_IS_EVEN_ODD(d));
1176 switch (iptr->opc) {
1178 M_SLDL(s2, GET_HIGH_REG(d));
1181 M_SRDA(s2, GET_HIGH_REG(d));
1184 M_SRDL(s2, GET_HIGH_REG(d));
1190 emit_copy_dst(jd, iptr, d);
1191 emit_store_dst(jd, iptr, d);
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 */
1203 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1204 if (! N_IS_EVEN_ODD(d)) {
1205 d = REG_ITMP31_PACKED;
1207 assert(N_IS_EVEN_ODD(d));
1209 s1 = emit_load_s1(jd, iptr, d);
1213 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1215 switch (iptr->opc) {
1216 case ICMD_LSHLCONST:
1217 N_SLDL(GET_HIGH_REG(d), disp, RN);
1219 case ICMD_LSHRCONST:
1220 N_SRDA(GET_HIGH_REG(d), disp, RN);
1222 case ICMD_LUSHRCONST:
1223 N_SRDL(GET_HIGH_REG(d), disp, RN);
1226 N_SLDL(GET_HIGH_REG(d), disp, RN);
1232 emit_copy_dst(jd, iptr, d);
1233 emit_store_dst(jd, iptr, d);
1236 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1238 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1239 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1240 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1247 emit_store_dst(jd, iptr, d);
1251 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1253 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1254 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1255 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1262 emit_store_dst(jd, iptr, d);
1266 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1268 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1269 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1270 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1277 emit_store_dst(jd, iptr, d);
1283 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1284 /* sx.val.i = constant */
1285 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1286 /* sx.val.i = constant */
1287 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1288 /* sx.val.i = constant */
1290 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1291 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1294 ICONST(REG_ITMP2, iptr->sx.val.i);
1296 switch (iptr->opc) {
1297 case ICMD_IANDCONST:
1298 M_IAND(REG_ITMP2, d);
1300 case ICMD_IXORCONST:
1301 M_IXOR(REG_ITMP2, d);
1304 M_IOR(REG_ITMP2, d);
1310 emit_store_dst(jd, iptr, d);
1314 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1315 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1316 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1318 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1320 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1321 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1322 dd = GET_LOW_REG(d);
1324 switch (iptr->opc) {
1353 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1354 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1355 dd = GET_HIGH_REG(d);
1357 switch (iptr->opc) {
1386 emit_store_dst(jd, iptr, d);
1389 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1390 /* sx.val.l = constant */
1391 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1392 /* sx.val.l = constant */
1393 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1394 /* sx.val.l = constant */
1396 /* TODO should use memory operand to access data segment, not load */
1398 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1400 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1401 s3 = iptr->sx.val.l & 0xffffffff;
1403 M_INTMOVE(s1, GET_LOW_REG(d));
1405 ICONST(REG_ITMP3, s3);
1407 switch (iptr->opc) {
1408 case ICMD_LANDCONST:
1409 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1411 case ICMD_LXORCONST:
1412 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1415 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1421 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1422 s3 = iptr->sx.val.l >> 32;
1424 M_INTMOVE(s1, GET_HIGH_REG(d));
1426 ICONST(REG_ITMP3, s3);
1428 switch (iptr->opc) {
1429 case ICMD_LANDCONST:
1430 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1432 case ICMD_LXORCONST:
1433 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1436 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1442 emit_store_dst(jd, iptr, d);
1446 /* floating operations ************************************************/
1448 case ICMD_FNEG: /* ..., value ==> ..., - value */
1449 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1450 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1452 emit_store_dst(jd, iptr, d);
1455 case ICMD_DNEG: /* ..., value ==> ..., - value */
1456 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1457 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1459 emit_store_dst(jd, iptr, d);
1462 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1463 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1464 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1465 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1472 emit_store_dst(jd, iptr, d);
1475 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1476 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1477 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1478 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1485 emit_store_dst(jd, iptr, d);
1488 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1489 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1490 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1491 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1495 emit_store_dst(jd, iptr, d);
1498 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1499 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1500 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1501 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1505 emit_store_dst(jd, iptr, d);
1508 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1509 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1510 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1511 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1518 emit_store_dst(jd, iptr, d);
1521 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1522 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1523 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1524 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1531 emit_store_dst(jd, iptr, d);
1534 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1535 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1536 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1537 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1541 emit_store_dst(jd, iptr, d);
1544 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1545 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1546 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1547 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1551 emit_store_dst(jd, iptr, d);
1554 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1555 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1556 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1558 emit_store_dst(jd, iptr, d);
1561 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1562 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1563 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1565 emit_store_dst(jd, iptr, d);
1568 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1572 #ifdef SUPPORT_HERCULES
1576 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1577 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1581 switch (iptr->opc) {
1590 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1591 N_LHI(d, 0); /* Load 0 */
1592 ref1 = cd->mcodeptr;
1593 N_BRC(DD_ANY, 0); /* Exit */
1597 switch (iptr->opc) {
1606 #ifdef SUPPORT_HERCULES
1607 /* Hercules does the conversion using a plain C conversion.
1608 * According to manual, real hardware should *NOT* require this.
1610 * Corner case: Positive float leads to INT_MIN (overflow).
1613 switch (iptr->opc) {
1622 ref2 = cd->mcodeptr;
1623 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1627 ref3 = cd->mcodeptr;
1628 M_BGE(0); /* If integer result is negative, continue */
1630 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1631 M_ILD_DSEG(d, disp);
1633 N_BRC_BACK_PATCH(ref1);
1634 #ifdef SUPPORT_HERCULES
1635 N_BRC_BACK_PATCH(ref2);
1636 N_BRC_BACK_PATCH(ref3);
1638 emit_store_dst(jd, iptr, d);
1642 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1645 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1646 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1647 #ifdef SUPPORT_HERCULES
1650 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1651 disp = dseg_add_double(cd, 0.0 / 0.0);
1652 M_DLD_DSEG(d, disp, REG_ITMP1);
1653 emit_label_br(cd, BRANCH_LABEL_1);
1654 N_BRC_BACK_PATCH(ref);
1657 #ifdef SUPPORT_HERCULES
1658 emit_label(cd, BRANCH_LABEL_1);
1660 emit_store_dst(jd, iptr, d);
1664 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1665 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1666 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1668 emit_store_dst(jd, iptr, d);
1671 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1672 /* == => 0, < => 1, > => -1 */
1676 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1677 /* == => 0, < => 1, > => -1 */
1680 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1681 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1682 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1684 switch (iptr->opc) {
1696 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1697 SZ_BRC + SZ_BRC + SZ_BRC
1700 N_BRC( /* load -1 */
1701 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1702 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1707 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1710 N_LHI(d, 1); /* GT */
1711 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1712 N_LHI(d, -1); /* LT */
1713 M_BR(SZ_BRC + SZ_LHI);
1714 N_LHI(d, 0); /* EQ */
1716 emit_store_dst(jd, iptr, d);
1721 /* memory operations **************************************************/
1723 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1725 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1726 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1728 /* implicit null-pointer check */
1729 M_ILD(d, s1, OFFSET(java_array_t, size));
1730 emit_store_dst(jd, iptr, d);
1734 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1735 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1736 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1737 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1739 /* implicit null-pointer check */
1740 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1742 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1747 emit_store_dst(jd, iptr, d);
1750 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1752 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1753 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1754 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1756 /* implicit null-pointer check */
1757 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1759 M_INTMOVE(s2, REG_ITMP2);
1760 M_SLL_IMM(1, REG_ITMP2);
1762 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1764 /* N_LH does sign extends, undo ! */
1769 emit_store_dst(jd, iptr, d);
1772 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1773 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1774 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1775 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1777 /* implicit null-pointer check */
1778 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1780 M_INTMOVE(s2, REG_ITMP2);
1781 M_SLL_IMM(1, REG_ITMP2);
1783 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1784 emit_store_dst(jd, iptr, d);
1787 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1788 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1789 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1790 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1792 /* implicit null-pointer check */
1793 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1795 M_INTMOVE(s2, REG_ITMP2);
1796 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1797 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1798 emit_store_dst(jd, iptr, d);
1801 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1803 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1804 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1806 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1808 /* implicit null-pointer check */
1809 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1811 M_INTMOVE(s2, REG_ITMP2);
1812 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1815 GET_LOW_REG(d) /* maybe itmp3 */,
1816 OFFSET(java_intarray_t, data[0]) + 4,
1817 REG_ITMP2, s1 /* maybe itmp1 */
1821 GET_HIGH_REG(d) /* maybe itmp1 */,
1822 OFFSET(java_intarray_t, data[0]),
1823 REG_ITMP2, s1 /* maybe itmp1 */
1826 emit_store_dst(jd, iptr, d);
1830 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1832 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1833 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1834 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1836 /* implicit null-pointer check */
1837 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1839 M_INTMOVE(s2, REG_ITMP2);
1840 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1842 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1844 emit_store_dst(jd, iptr, d);
1847 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1848 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1849 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1850 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1852 /* implicit null-pointer check */
1853 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1855 M_INTMOVE(s2, REG_ITMP2);
1856 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1858 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1860 emit_store_dst(jd, iptr, d);
1863 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1864 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1865 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1866 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1868 /* implicit null-pointer check */
1869 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1871 M_INTMOVE(s2, REG_ITMP2);
1872 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1873 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1874 emit_store_dst(jd, iptr, d);
1877 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1878 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1879 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1880 /* implicit null-pointer check */
1881 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1882 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1884 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1887 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1889 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1890 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1891 /* implicit null-pointer check */
1892 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1893 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1895 M_INTMOVE(s2, REG_ITMP2);
1896 M_SLL_IMM(1, REG_ITMP2);
1898 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1902 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1903 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1904 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1905 /* implicit null-pointer check */
1906 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1907 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1909 M_INTMOVE(s2, REG_ITMP2);
1910 M_SLL_IMM(1, REG_ITMP2);
1912 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1915 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1917 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1918 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1919 /* implicit null-pointer check */
1920 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1922 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1924 M_INTMOVE(s2, REG_ITMP2);
1925 M_SLL_IMM(2, REG_ITMP2);
1927 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1930 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1932 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1933 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1934 /* implicit null-pointer check */
1935 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1937 M_INTMOVE(s2, REG_ITMP2);
1938 M_SLL_IMM(3, REG_ITMP2);
1940 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1941 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1942 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1943 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1946 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1947 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1948 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1949 /* implicit null-pointer check */
1950 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1951 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1953 M_INTMOVE(s2, REG_ITMP2);
1954 M_SLL_IMM(2, REG_ITMP2);
1956 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1959 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1960 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1961 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1962 /* implicit null-pointer check */
1963 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1964 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1966 M_INTMOVE(s2, REG_ITMP2);
1967 M_SLL_IMM(3, REG_ITMP2);
1969 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1972 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1974 s1 = emit_load_s1(jd, iptr, REG_A0);
1975 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1976 /* implicit null-pointer check */
1977 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1978 s3 = emit_load_s3(jd, iptr, REG_A1);
1980 M_INTMOVE(s1, REG_A0);
1981 M_INTMOVE(s3, REG_A1);
1983 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1984 M_ALD_DSEG(REG_ITMP2, disp);
1985 M_ASUB_IMM(96, REG_SP);
1986 M_JSR(REG_RA, REG_ITMP2);
1987 M_AADD_IMM(96, REG_SP);
1989 emit_arraystore_check(cd, iptr);
1991 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1992 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1993 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1995 M_INTMOVE(s2, REG_ITMP2);
1996 M_SLL_IMM(2, REG_ITMP2);
1997 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
2000 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
2001 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2006 case ICMD_GETSTATIC: /* ... ==> ..., value */
2008 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2009 uf = iptr->sx.s23.s3.uf;
2010 fieldtype = uf->fieldref->parseddesc.fd->type;
2011 disp = dseg_add_unique_address(cd, NULL);
2013 /* PROFILE_CYCLE_STOP; */
2015 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2017 /* PROFILE_CYCLE_START; */
2020 fi = iptr->sx.s23.s3.fmiref->p.field;
2021 fieldtype = fi->type;
2022 disp = dseg_add_address(cd, fi->value);
2024 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2027 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
2029 PROFILE_CYCLE_START;
2033 M_ALD_DSEG(REG_ITMP1, disp);
2035 switch (fieldtype) {
2037 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2038 M_ILD(d, REG_ITMP1, 0);
2041 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2042 M_LLD(d, REG_ITMP1, 0);
2045 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2046 M_ALD(d, REG_ITMP1, 0);
2049 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2050 M_FLD(d, REG_ITMP1, 0);
2053 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2054 M_DLD(d, REG_ITMP1, 0);
2058 emit_store_dst(jd, iptr, d);
2062 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2064 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2065 uf = iptr->sx.s23.s3.uf;
2066 fieldtype = uf->fieldref->parseddesc.fd->type;
2067 disp = dseg_add_unique_address(cd, uf);
2069 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2072 fi = iptr->sx.s23.s3.fmiref->p.field;
2073 fieldtype = fi->type;
2074 disp = dseg_add_address(cd, fi->value);
2076 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2078 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
2079 PROFILE_CYCLE_START;
2083 M_ALD_DSEG(REG_ITMP1, disp);
2084 switch (fieldtype) {
2086 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2087 M_IST(s1, REG_ITMP1, 0);
2090 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2091 M_LST(s1, REG_ITMP1, 0);
2094 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2095 M_AST(s1, REG_ITMP1, 0);
2098 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2099 M_FST(s1, REG_ITMP1, 0);
2102 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2103 M_DST(s1, REG_ITMP1, 0);
2108 case ICMD_GETFIELD: /* ... ==> ..., value */
2110 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2111 emit_nullpointer_check(cd, iptr, s1);
2113 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2114 uf = iptr->sx.s23.s3.uf;
2115 fieldtype = uf->fieldref->parseddesc.fd->type;
2118 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2121 fi = iptr->sx.s23.s3.fmiref->p.field;
2122 fieldtype = fi->type;
2126 switch (fieldtype) {
2128 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2132 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2133 if (GET_HIGH_REG(d) == s1) {
2134 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2135 M_ILD(GET_HIGH_REG(d), s1, disp);
2138 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2139 M_ILD(GET_HIGH_REG(d), s1, disp);
2143 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2147 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2151 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2155 emit_store_dst(jd, iptr, d);
2158 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2162 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2163 emit_nullpointer_check(cd, iptr, s1);
2165 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2166 uf = iptr->sx.s23.s3.uf;
2167 fieldtype = uf->fieldref->parseddesc.fd->type;
2171 fi = iptr->sx.s23.s3.fmiref->p.field;
2172 fieldtype = fi->type;
2176 /* We can't add a patcher ref behind this load,
2177 * because the patcher would destroy REG_ITMP3.
2179 * We pass in the disp parameter, how many bytes
2180 * to skip to the to the actual store.
2182 * XXX this relies on patcher_add_patch_ref internals
2185 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2186 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2191 if (IS_INT_LNG_TYPE(fieldtype)) {
2192 if (IS_2_WORD_TYPE(fieldtype))
2193 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2195 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2197 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2200 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2201 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2204 switch (fieldtype) {
2206 M_IST(s2, s1, disp);
2209 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2210 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2213 M_AST(s2, s1, disp);
2216 M_FST(s2, s1, disp);
2219 M_DST(s2, s1, disp);
2226 /* branch operations **************************************************/
2228 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2230 /* PROFILE_CYCLE_STOP; */
2232 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2233 M_INTMOVE(s1, REG_ITMP3_XPTR);
2235 #ifdef ENABLE_VERIFIER
2236 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2237 uc = iptr->sx.s23.s2.uc;
2239 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2241 #endif /* ENABLE_VERIFIER */
2243 disp = dseg_add_functionptr(cd, asm_handle_exception);
2244 M_ALD_DSEG(REG_ITMP1, disp);
2245 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2250 case ICMD_GOTO: /* ... ==> ... */
2251 case ICMD_RET: /* ... ==> ... */
2253 emit_br(cd, iptr->dst.block);
2257 case ICMD_JSR: /* ... ==> ... */
2259 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2263 case ICMD_IFNULL: /* ..., value ==> ... */
2264 case ICMD_IFNONNULL: /* ..., value ==> ... */
2265 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2267 switch (iptr->opc) {
2269 emit_beq(cd, iptr->dst.block);
2271 case ICMD_IFNONNULL:
2272 emit_bne(cd, iptr->dst.block);
2277 case ICMD_IFEQ: /* ..., value ==> ... */
2278 case ICMD_IFLT: /* ..., value ==> ... */
2279 case ICMD_IFLE: /* ..., value ==> ... */
2280 case ICMD_IFNE: /* ..., value ==> ... */
2281 case ICMD_IFGT: /* ..., value ==> ... */
2282 case ICMD_IFGE: /* ..., value ==> ... */
2284 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2286 if (N_VALID_IMM(iptr->sx.val.i))
2287 M_ICMP_IMM(s1, iptr->sx.val.i);
2289 disp = dseg_add_s4(cd, iptr->sx.val.i);
2290 if (N_VALID_DSEG_DISP(disp)) {
2291 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2293 ICONST(REG_ITMP2, disp);
2294 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2298 switch (iptr->opc) {
2300 emit_blt(cd, iptr->dst.block);
2303 emit_ble(cd, iptr->dst.block);
2306 emit_bne(cd, iptr->dst.block);
2309 emit_bgt(cd, iptr->dst.block);
2312 emit_bge(cd, iptr->dst.block);
2315 emit_beq(cd, iptr->dst.block);
2321 case ICMD_IF_LLT: /* ..., value ==> ... */
2322 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2328 /* ATTENTION: compare high words signed and low words unsigned */
2330 # define LABEL_OUT BRANCH_LABEL_1
2332 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2334 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2335 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2337 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2338 if (N_VALID_DSEG_DISP(disp)) {
2339 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2341 ICONST(REG_ITMP2, disp);
2342 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2349 emit_blt(cd, iptr->dst.block);
2350 /* EQ ... fall through */
2351 emit_label_bgt(cd, LABEL_OUT);
2355 emit_bgt(cd, iptr->dst.block);
2356 /* EQ ... fall through */
2357 emit_label_blt(cd, LABEL_OUT);
2360 /* EQ ... fall through */
2361 emit_label_bne(cd, LABEL_OUT);
2364 /* EQ ... fall through */
2365 emit_bne(cd, iptr->dst.block);
2371 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2373 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2374 if (N_VALID_DSEG_DISP(disp)) {
2375 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2377 ICONST(REG_ITMP2, disp);
2378 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2383 emit_blt(cd, iptr->dst.block);
2384 emit_label(cd, LABEL_OUT);
2387 emit_ble(cd, iptr->dst.block);
2388 emit_label(cd, LABEL_OUT);
2391 emit_bgt(cd, iptr->dst.block);
2392 emit_label(cd, LABEL_OUT);
2395 emit_bge(cd, iptr->dst.block);
2396 emit_label(cd, LABEL_OUT);
2399 emit_beq(cd, iptr->dst.block);
2400 emit_label(cd, LABEL_OUT);
2403 emit_bne(cd, iptr->dst.block);
2412 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2413 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2415 /* Compare addresses as 31 bit unsigned integers */
2417 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2418 M_LDA(REG_ITMP1, s1, 0);
2420 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2421 M_LDA(REG_ITMP2, s2, 0);
2423 M_CMP(REG_ITMP1, REG_ITMP2);
2425 switch (iptr->opc) {
2426 case ICMD_IF_ACMPEQ:
2427 emit_beq(cd, iptr->dst.block);
2429 case ICMD_IF_ACMPNE:
2430 emit_bne(cd, iptr->dst.block);
2436 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2437 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2438 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2439 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2440 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2441 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2443 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2444 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2446 switch (iptr->opc) {
2447 case ICMD_IF_ICMPEQ:
2448 emit_beq(cd, iptr->dst.block);
2450 case ICMD_IF_ICMPNE:
2451 emit_bne(cd, iptr->dst.block);
2453 case ICMD_IF_ICMPLT:
2454 emit_blt(cd, iptr->dst.block);
2456 case ICMD_IF_ICMPGT:
2457 emit_bgt(cd, iptr->dst.block);
2459 case ICMD_IF_ICMPLE:
2460 emit_ble(cd, iptr->dst.block);
2462 case ICMD_IF_ICMPGE:
2463 emit_bge(cd, iptr->dst.block);
2469 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2470 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2471 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2472 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2473 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2474 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2479 /* ATTENTION: compare high words signed and low words unsigned */
2481 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2482 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2487 case ICMD_IF_LCMPLT:
2488 case ICMD_IF_LCMPLE:
2489 emit_blt(cd, iptr->dst.block);
2490 /* EQ ... fall through */
2491 out_ref = cd->mcodeptr;
2494 case ICMD_IF_LCMPGT:
2495 case ICMD_IF_LCMPGE:
2496 emit_bgt(cd, iptr->dst.block);
2497 /* EQ ... fall through */
2498 out_ref = cd->mcodeptr;
2501 case ICMD_IF_LCMPEQ:
2502 /* EQ ... fall through */
2503 out_ref = cd->mcodeptr;
2506 case ICMD_IF_LCMPNE:
2507 /* EQ ... fall through */
2508 emit_bne(cd, iptr->dst.block);
2514 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2515 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2520 case ICMD_IF_LCMPLT:
2521 emit_blt(cd, iptr->dst.block);
2523 case ICMD_IF_LCMPLE:
2524 emit_ble(cd, iptr->dst.block);
2526 case ICMD_IF_LCMPGT:
2527 emit_bgt(cd, iptr->dst.block);
2529 case ICMD_IF_LCMPGE:
2530 emit_bge(cd, iptr->dst.block);
2532 case ICMD_IF_LCMPEQ:
2533 emit_beq(cd, iptr->dst.block);
2535 case ICMD_IF_LCMPNE:
2536 emit_bne(cd, iptr->dst.block);
2542 if (out_ref != NULL) {
2543 N_BRC_BACK_PATCH(out_ref);
2549 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2551 REPLACEMENT_POINT_RETURN(cd, iptr);
2552 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2553 M_INTMOVE(s1, REG_RESULT);
2554 goto nowperformreturn;
2556 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2558 REPLACEMENT_POINT_RETURN(cd, iptr);
2559 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2560 M_INTMOVE(s1, REG_RESULT);
2562 #ifdef ENABLE_VERIFIER
2563 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2564 unresolved_class *uc = iptr->sx.s23.s2.uc;
2567 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2568 PROFILE_CYCLE_START;
2570 #endif /* ENABLE_VERIFIER */
2571 goto nowperformreturn;
2573 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2575 REPLACEMENT_POINT_RETURN(cd, iptr);
2576 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2577 M_LNGMOVE(s1, REG_RESULT_PACKED);
2578 goto nowperformreturn;
2580 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2583 REPLACEMENT_POINT_RETURN(cd, iptr);
2584 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2585 M_FLTMOVE(s1, REG_FRESULT);
2586 goto nowperformreturn;
2588 case ICMD_RETURN: /* ... ==> ... */
2590 REPLACEMENT_POINT_RETURN(cd, iptr);
2596 p = cd->stackframesize;
2598 /* call trace function */
2600 #if !defined(NDEBUG)
2601 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2602 emit_verbosecall_exit(jd);
2603 #endif /* !defined(NDEBUG) */
2605 #if defined(ENABLE_THREADS)
2606 if (checksync && code_is_synchronized(code)) {
2607 /* we need to save the proper return value */
2609 switch (iptr->opc) {
2611 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2615 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2618 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2621 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2625 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2627 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2628 M_ALD_DSEG(REG_ITMP2, disp);
2630 M_ASUB_IMM(96, REG_SP);
2632 M_AADD_IMM(96, REG_SP);
2634 /* and now restore the proper return value */
2636 switch (iptr->opc) {
2638 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2642 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2645 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2648 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2654 /* restore return address */
2656 p--; M_ALD(REG_RA, REG_SP, p * 8);
2658 /* restore saved registers */
2660 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2661 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2663 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2664 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2667 /* deallocate stack */
2669 if (cd->stackframesize)
2670 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2672 /* generate method profiling code */
2680 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2683 branch_target_t *table;
2685 table = iptr->dst.table;
2687 l = iptr->sx.s23.s2.tablelow;
2688 i = iptr->sx.s23.s3.tablehigh;
2690 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2691 M_INTMOVE(s1, REG_ITMP1);
2695 } else if (N_VALID_IMM(-l)) {
2696 M_ISUB_IMM(l, REG_ITMP1);
2698 ICONST(REG_ITMP2, l);
2699 M_ISUB(REG_ITMP2, REG_ITMP1);
2702 /* number of targets */
2708 ICONST(REG_ITMP2, i);
2709 M_ICMPU(REG_ITMP1, REG_ITMP2);
2710 emit_bge(cd, table[0].block);
2712 /* build jump table top down and use address of lowest entry */
2717 dseg_add_target(cd, table->block);
2722 /* length of dataseg after last dseg_add_target is used by load */
2724 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2725 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2726 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2727 M_JMP(RN, REG_ITMP1);
2732 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2735 lookup_target_t *lookup;
2737 lookup = iptr->dst.lookup;
2739 i = iptr->sx.s23.s2.lookupcount;
2741 MCODECHECK(8 + ((7 + 6) * i) + 5);
2742 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2745 if (N_VALID_IMM(lookup->value)) {
2746 M_ICMP_IMM(s1, lookup->value);
2748 ICONST(REG_ITMP2, lookup->value);
2749 M_ICMP(REG_ITMP2, s1);
2751 emit_beq(cd, lookup->target.block);
2755 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2760 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2762 bte = iptr->sx.s23.s3.bte;
2766 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2767 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2768 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2769 case ICMD_INVOKEINTERFACE:
2771 REPLACEMENT_POINT_INVOKE(cd, iptr);
2773 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2775 um = iptr->sx.s23.s3.um;
2776 md = um->methodref->parseddesc.md;
2779 lm = iptr->sx.s23.s3.fmiref->p.method;
2781 md = lm->parseddesc;
2785 s3 = md->paramcount;
2787 MCODECHECK((s3 << 1) + 64);
2789 /* copy arguments to registers or stack location */
2791 for (s3 = s3 - 1; s3 >= 0; s3--) {
2792 var = VAR(iptr->sx.s23.s2.args[s3]);
2794 /* Already Preallocated? */
2795 if (var->flags & PREALLOC)
2798 if (IS_INT_LNG_TYPE(var->type)) {
2799 if (!md->params[s3].inmemory) {
2800 if (IS_2_WORD_TYPE(var->type)) {
2802 GET_LOW_REG(md->params[s3].regoff),
2803 GET_HIGH_REG(md->params[s3].regoff)
2805 d = emit_load(jd, iptr, var, s1);
2809 s1 = md->params[s3].regoff;
2810 d = emit_load(jd, iptr, var, s1);
2815 if (IS_2_WORD_TYPE(var->type)) {
2816 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2817 M_LST(d, REG_SP, md->params[s3].regoff);
2820 d = emit_load(jd, iptr, var, REG_ITMP1);
2821 M_IST(d, REG_SP, md->params[s3].regoff);
2826 if (!md->params[s3].inmemory) {
2827 s1 = md->params[s3].regoff;
2828 d = emit_load(jd, iptr, var, s1);
2832 d = emit_load(jd, iptr, var, REG_FTMP1);
2833 if (IS_2_WORD_TYPE(var->type))
2834 M_DST(d, REG_SP, md->params[s3].regoff);
2836 M_FST(d, REG_SP, md->params[s3].regoff);
2841 /* generate method profiling code */
2845 switch (iptr->opc) {
2847 if (bte->stub == NULL) {
2848 disp = dseg_add_functionptr(cd, bte->fp);
2849 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2851 disp = dseg_add_functionptr(cd, bte->stub);
2854 if (N_VALID_DSEG_DISP(disp)) {
2855 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2857 N_LHI(REG_ITMP1, disp);
2858 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2862 case ICMD_INVOKESPECIAL:
2864 /* Implicit NULL pointer check */
2865 M_ILD(REG_ITMP1, REG_A0, 0);
2869 case ICMD_INVOKESTATIC:
2871 disp = dseg_add_unique_address(cd, um);
2873 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2877 disp = dseg_add_address(cd, lm->stubroutine);
2879 if (N_VALID_DSEG_DISP(disp)) {
2880 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2882 N_LHI(REG_ITMP1, disp);
2883 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2887 case ICMD_INVOKEVIRTUAL:
2888 /* TODO softnull REG_A0 */
2891 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2896 s1 = OFFSET(vftbl_t, table[0]) +
2897 sizeof(methodptr) * lm->vftblindex;
2900 /* implicit null-pointer check */
2902 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2903 M_ALD(REG_PV, REG_METHODPTR, s1);
2906 case ICMD_INVOKEINTERFACE:
2907 /* TODO softnull REG_A0 */
2909 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2910 * and -0xFFF in index register (itmp1)
2914 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2920 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2921 sizeof(methodptr*) * lm->class->index;
2923 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2926 /* Implicit null-pointer check */
2927 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2928 N_LHI(REG_ITMP2, s1);
2929 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2930 M_ALD(REG_PV, REG_METHODPTR, s2);
2934 /* generate the actual call */
2937 emit_restore_pv(cd);
2939 /* post call finalization */
2941 switch (iptr->opc) {
2943 if (bte->stub == NULL) {
2944 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2949 /* generate method profiling code */
2951 PROFILE_CYCLE_START;
2953 /* store size of call code in replacement point */
2955 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2957 /* store return value */
2959 d = md->returntype.type;
2961 if (d != TYPE_VOID) {
2962 if (IS_INT_LNG_TYPE(d)) {
2963 if (IS_2_WORD_TYPE(d)) {
2964 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2965 M_LNGMOVE(REG_RESULT_PACKED, s1);
2968 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2969 M_INTMOVE(REG_RESULT, s1);
2973 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2974 M_FLTMOVE(REG_FRESULT, s1);
2976 emit_store_dst(jd, iptr, s1);
2982 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2984 /* val.a: (classinfo*) superclass */
2986 /* superclass is an interface:
2988 * OK if ((sub == NULL) ||
2989 * (sub->vftbl->interfacetablelength > super->index) &&
2990 * (sub->vftbl->interfacetable[-super->index] != NULL));
2992 * superclass is a class:
2994 * OK if ((sub == NULL) || (0
2995 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2996 * super->vftbl->diffval));
2999 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
3000 /* object type cast-check */
3003 vftbl_t *supervftbl;
3006 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3007 # define LABEL_CLASS BRANCH_LABEL_2
3008 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3009 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
3010 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
3012 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3018 super = iptr->sx.s23.s3.c.cls;
3019 superindex = super->index;
3020 supervftbl = super->vftbl;
3023 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3024 CODEGEN_CRITICAL_SECTION_NEW;
3026 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3028 /* if class is not resolved, check which code to call */
3030 if (super == NULL) {
3032 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3034 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3036 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3037 iptr->sx.s23.s3.c.ref,
3040 ICONST(REG_ITMP3, ACC_INTERFACE);
3042 if (N_VALID_DSEG_DISP(disp)) {
3043 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3045 ICONST(REG_ITMP2, disp);
3046 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3048 emit_label_beq(cd, LABEL_CLASS);
3051 /* interface checkcast code */
3053 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3054 if (super == NULL) {
3055 patcher_add_patch_ref(jd,
3056 PATCHER_checkcast_instanceof_interface,
3057 iptr->sx.s23.s3.c.ref,
3061 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3064 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3065 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3066 M_ISUB_IMM(superindex, REG_ITMP3);
3067 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3070 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3071 superindex * sizeof(methodptr*))
3073 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3074 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3076 if (super == NULL) {
3077 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3081 /* class checkcast code */
3083 if (super == NULL) {
3084 emit_label(cd, LABEL_CLASS);
3087 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3088 if (super == NULL) {
3089 disp = dseg_add_unique_address(cd, NULL);
3091 patcher_add_patch_ref(jd,
3092 PATCHER_resolve_classref_to_vftbl,
3093 iptr->sx.s23.s3.c.ref,
3097 disp = dseg_add_address(cd, supervftbl);
3099 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3103 CODEGEN_CRITICAL_SECTION_START;
3105 /* REG_ITMP3 := baseval(s1) */
3106 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3107 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3109 /* REG_ITMP2 := baseval(class) */
3110 M_ALD_DSEG(REG_ITMP2, disp);
3111 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3113 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3114 M_ISUB(REG_ITMP2, REG_ITMP3);
3116 /* REG_ITMP2 := diffval(class) */
3117 M_ALD_DSEG(REG_ITMP2, disp);
3118 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3120 CODEGEN_CRITICAL_SECTION_END;
3122 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3124 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3125 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3126 /* Branch if greater then */
3128 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3129 M_ALD_DSEG(REG_ITMP3, disp);
3131 CODEGEN_CRITICAL_SECTION_START;
3133 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3134 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3135 M_ISUB(REG_ITMP3, REG_ITMP2);
3136 M_ALD_DSEG(REG_ITMP3, disp);
3137 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3139 CODEGEN_CRITICAL_SECTION_END;
3141 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3142 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3143 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3144 /* Branch if greater then */
3146 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3149 if (super == NULL) {
3150 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3151 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3152 } else if (super->flags & ACC_INTERFACE) {
3153 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3155 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3158 d = codegen_reg_of_dst(jd, iptr, s1);
3160 # undef LABEL_EXIT_CHECK_NULL
3162 # undef LABEL_EXIT_INTERFACE_NULL
3163 # undef LABEL_EXIT_INTERFACE_DONE
3164 # undef LABEL_EXIT_CLASS_NULL
3167 /* array type cast-check */
3169 s1 = emit_load_s1(jd, iptr, REG_A0);
3170 M_INTMOVE(s1, REG_A0);
3172 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3173 disp = dseg_add_unique_address(cd, NULL);
3175 patcher_add_patch_ref(jd,
3176 PATCHER_resolve_classref_to_classinfo,
3177 iptr->sx.s23.s3.c.ref,
3181 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3183 M_ALD_DSEG(REG_A1, disp);
3184 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3185 M_ALD_DSEG(REG_ITMP1, disp);
3186 M_ASUB_IMM(96, REG_SP);
3187 M_JSR(REG_RA, REG_ITMP1);
3188 M_AADD_IMM(96, REG_SP);
3190 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3191 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3193 d = codegen_reg_of_dst(jd, iptr, s1);
3197 emit_store_dst(jd, iptr, d);
3200 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3201 /* val.a: (classinfo*) superclass */
3203 /* superclass is an interface:
3205 * return (sub != NULL) &&
3206 * (sub->vftbl->interfacetablelength > super->index) &&
3207 * (sub->vftbl->interfacetable[-super->index] != NULL);
3209 * superclass is a class:
3211 * return ((sub != NULL) && (0
3212 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3213 * super->vftbl->diffvall));
3215 * If superclass is unresolved, we include both code snippets
3216 * above, a patcher resolves the class' flags and we select
3217 * the right code at runtime.
3222 vftbl_t *supervftbl;
3225 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3231 super = iptr->sx.s23.s3.c.cls;
3232 superindex = super->index;
3233 supervftbl = super->vftbl;
3236 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3237 # define LABEL_CLASS BRANCH_LABEL_2
3238 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3239 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3240 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3241 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3243 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3244 CODEGEN_CRITICAL_SECTION_NEW;
3246 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3247 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3249 M_MOV(s1, REG_ITMP1);
3253 /* if class is not resolved, check which code to call */
3255 if (super == NULL) {
3259 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3261 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3263 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3264 iptr->sx.s23.s3.c.ref, disp);
3266 ICONST(REG_ITMP3, ACC_INTERFACE);
3268 if (N_VALID_DSEG_DISP(disp)) {
3269 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3271 ICONST(REG_ITMP2, disp);
3272 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3275 emit_label_beq(cd, LABEL_CLASS);
3278 /* interface instanceof code */
3280 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3281 if (super == NULL) {
3282 /* If d == REG_ITMP2, then it's destroyed in check
3287 patcher_add_patch_ref(jd,
3288 PATCHER_checkcast_instanceof_interface,
3289 iptr->sx.s23.s3.c.ref, 0);
3294 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3297 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3298 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3299 M_ISUB_IMM(superindex, REG_ITMP3);
3301 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3305 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3306 superindex * sizeof(methodptr*))
3308 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3310 /* d := (REG_ITMP1 != 0) */
3312 N_LTR(d, REG_ITMP1);
3313 M_BEQ(SZ_BRC + SZ_LHI);
3316 if (super == NULL) {
3317 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3321 /* class instanceof code */
3323 if (super == NULL) {
3324 emit_label(cd, LABEL_CLASS);
3327 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3328 if (super == NULL) {
3329 disp = dseg_add_unique_address(cd, NULL);
3331 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3332 iptr->sx.s23.s3.c.ref,
3336 disp = dseg_add_address(cd, supervftbl);
3341 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3344 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3345 M_ALD_DSEG(REG_ITMP2, disp);
3347 CODEGEN_CRITICAL_SECTION_START;
3349 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3350 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3351 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3353 CODEGEN_CRITICAL_SECTION_END;
3355 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3357 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3359 M_BGT(SZ_BRC + SZ_LHI);
3363 if (super == NULL) {
3364 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3365 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3366 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3367 } else if (super->flags & ACC_INTERFACE) {
3368 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3369 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3371 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3374 # undef LABEL_EXIT_CHECK_NULL
3376 # undef LABEL_EXIT_INTERFACE_NULL
3377 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3378 # undef LABEL_EXIT_INTERFACE_DONE
3379 # undef LABEL_EXIT_CLASS_NULL
3381 emit_store_dst(jd, iptr, d);
3387 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3389 /* check for negative sizes and copy sizes to stack if necessary */
3391 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3394 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3396 /* copy SAVEDVAR sizes to stack */
3397 var = VAR(iptr->sx.s23.s2.args[s1]);
3399 /* Already Preallocated? */
3400 if (!(var->flags & PREALLOC)) {
3401 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3402 M_IST(s2, REG_SP, s1 * 4);
3406 /* is a patcher function set? */
3408 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3409 disp = dseg_add_unique_address(cd, 0);
3411 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3412 iptr->sx.s23.s3.c.ref,
3416 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3418 /* a0 = dimension count */
3420 ICONST(REG_A0, iptr->s1.argcount);
3422 /* a1 = classinfo */
3424 M_ALD_DSEG(REG_A1, disp);
3426 /* a2 = pointer to dimensions = stack pointer */
3428 M_MOV(REG_SP, REG_A2);
3430 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3431 M_ALD_DSEG(REG_ITMP1, disp);
3432 M_ASUB_IMM(96, REG_SP);
3433 M_JSR(REG_RA, REG_ITMP1);
3434 M_AADD_IMM(96, REG_SP);
3436 /* check for exception before result assignment */
3438 emit_exception_check(cd, iptr);
3440 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3441 M_INTMOVE(REG_RESULT, s1);
3442 emit_store_dst(jd, iptr, s1);
3447 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3451 } /* for instruction */
3453 MCODECHECK(512); /* XXX require a lower number? */
3455 /* At the end of a basic block we may have to append some nops,
3456 because the patcher stub calling code might be longer than the
3457 actual instruction. So codepatching does not change the
3458 following block unintentionally. */
3460 if (cd->mcodeptr < cd->lastmcodeptr) {
3461 while (cd->mcodeptr < cd->lastmcodeptr) {
3466 } /* if (bptr -> flags >= BBREACHED) */
3467 } /* for basic block */
3469 dseg_createlinenumbertable(cd);
3471 /* generate stubs */
3473 emit_patcher_traps(jd);
3475 /* everything's ok */
3481 /* codegen_emit_stub_compiler **************************************************
3483 Emits a stub routine which calls the compiler.
3485 *******************************************************************************/
3487 void codegen_emit_stub_compiler(jitdata *jd)
3492 /* get required compiler data */
3497 /* code for the stub */
3499 /* don't touch ITMP2 as it cointains the return address */
3501 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3503 /* REG_METHODPTR (REG_ITMP1) already used */
3504 M_ILD_DSEG(REG_ITMP3, -2 * SIZEOF_VOID_P); /* methodinfo */
3505 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3510 /* codegen_emit_stub_native ****************************************************
3512 Emits a stub routine which calls a native method.
3514 *******************************************************************************/
3517 arguments on stack \
3518 -------------------------------------------------| <- SP on nativestub entry
3520 callee saved int regs (none) |
3521 callee saved float regs (none) | stack frame like in cacao
3522 local variable slots (none) |
3523 arguments for calling methods (none) /
3524 ------------------------------------------------------------------ <- datasp
3529 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3530 0 - 96 register save area for callee /
3531 -------------------------------------------------------- <- SP native method
3533 SP after method entry
3536 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3542 s4 i, j; /* count variables */
3547 /* get required compiler data */
3553 /* set some variables */
3557 /* calculate stackframe size */
3559 cd->stackframesize =
3560 1 + /* return address */
3561 sizeof(stackframeinfo_t) / 8 +
3562 sizeof(localref_table) / 8 +
3565 (96 / 8); /* linkage area */
3567 /* keep stack 8-byte aligned */
3569 /*ALIGN_2(cd->stackframesize);*/
3571 /* create method header */
3573 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3574 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3575 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3576 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3577 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3578 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3579 (void) dseg_addlinenumbertablesize(cd);
3580 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3584 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3585 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3587 /* store return address */
3589 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3591 /* get function address (this must happen before the stackframeinfo) */
3593 funcdisp = dseg_add_functionptr(cd, f);
3596 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
3598 #if defined(ENABLE_GC_CACAO)
3599 /* Save callee saved integer registers in stackframeinfo (GC may
3600 need to recover them during a collection). */
3602 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3603 OFFSET(stackframeinfo_t, intregs);
3605 for (i = 0; i < INT_SAV_CNT; i++)
3606 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3609 /* save integer and float argument registers */
3611 for (i = 0; i < md->paramcount; i++) {
3612 if (!md->params[i].inmemory) {
3613 s1 = md->params[i].regoff;
3615 switch (md->paramtypes[i].type) {
3618 M_IST(s1, REG_SP, 96 + i * 8);
3621 M_LST(s1, REG_SP, 96 + i * 8);
3625 M_DST(s1, REG_SP, 96 + i * 8);
3631 /* create native stack info */
3633 M_MOV(REG_SP, REG_A0);
3634 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3635 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3636 M_ALD_DSEG(REG_ITMP2, disp);
3639 /* remember class argument */
3641 if (m->flags & ACC_STATIC)
3642 M_MOV(REG_RESULT, REG_ITMP3);
3644 /* restore integer and float argument registers */
3646 for (i = 0; i < md->paramcount; i++) {
3647 if (!md->params[i].inmemory) {
3648 s1 = md->params[i].regoff;
3650 switch (md->paramtypes[i].type) {
3653 M_ILD(s1, REG_SP, 96 + i * 8);
3656 M_LLD(s1, REG_SP, 96 + i * 8);
3660 M_DLD(s1, REG_SP, 96 + i * 8);
3666 /* copy or spill arguments to new locations */
3668 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3669 t = md->paramtypes[i].type;
3671 if (IS_INT_LNG_TYPE(t)) {
3672 if (!md->params[i].inmemory) {
3673 s1 = md->params[i].regoff;
3674 s2 = nmd->params[j].regoff;
3676 if (!nmd->params[j].inmemory) {
3677 if (IS_2_WORD_TYPE(t))
3683 if (IS_2_WORD_TYPE(t))
3684 M_LST(s1, REG_SP, s2);
3686 M_IST(s1, REG_SP, s2);
3690 s1 = md->params[i].regoff + cd->stackframesize * 8;
3691 s2 = nmd->params[j].regoff;
3693 if (IS_2_WORD_TYPE(t)) {
3694 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3696 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3701 /* We only copy spilled float arguments, as the float
3702 argument registers keep unchanged. */
3704 if (md->params[i].inmemory) {
3705 s1 = md->params[i].regoff + cd->stackframesize * 8;
3706 s2 = nmd->params[j].regoff;
3708 if (IS_2_WORD_TYPE(t)) {
3709 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3711 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3717 /* Handle native Java methods. */
3719 if (m->flags & ACC_NATIVE) {
3720 /* put class into second argument register */
3722 if (m->flags & ACC_STATIC)
3723 M_MOV(REG_ITMP3, REG_A1);
3725 /* put env into first argument register */
3727 disp = dseg_add_address(cd, _Jv_env);
3728 M_ALD_DSEG(REG_A0, disp);
3731 /* generate the actual native call */
3733 M_ALD_DSEG(REG_ITMP2, funcdisp);
3736 /* save return value */
3738 switch (md->returntype.type) {
3741 M_IST(REG_RESULT, REG_SP, 96);
3744 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3748 M_DST(REG_FRESULT, REG_SP, 96);
3754 /* remove native stackframe info */
3756 M_MOV(REG_SP, REG_A0);
3757 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3758 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3759 M_ALD_DSEG(REG_ITMP1, disp);
3762 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3764 /* restore return value */
3766 switch (md->returntype.type) {
3769 M_ILD(REG_RESULT, REG_SP, 96);
3772 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3776 M_DLD(REG_FRESULT, REG_SP, 96);
3782 #if defined(ENABLE_GC_CACAO)
3783 /* Restore callee saved integer registers from stackframeinfo (GC
3784 might have modified them during a collection). */
3786 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3787 OFFSET(stackframeinfo_t, intregs);
3789 for (i = 0; i < INT_SAV_CNT; i++)
3790 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3793 /* load return address */
3795 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3797 /* remove stackframe */
3799 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3801 /* check for exception */
3803 M_TEST(REG_ITMP3_XPTR);
3804 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3808 /* handle exception */
3810 M_MOV(REG_RA, REG_ITMP1_XPC);
3812 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3813 M_ALD_DSEG(REG_ITMP2, disp);
3814 M_JMP(RN, REG_ITMP2);
3816 /* generate patcher traps */
3818 emit_patcher_traps(jd);
3822 * These are local overrides for various environment variables in Emacs.
3823 * Please do not remove this and leave it at the end of the file, where
3824 * Emacs will automagically detect them.
3825 * ---------------------------------------------------------------------
3828 * indent-tabs-mode: t
3832 * vim:noexpandtab:sw=4:ts=4: