1 /* src/vm/jit/s390/codegen.c - machine code generator for s390
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32 #include "vm/jit/s390/arch.h"
33 #include "vm/jit/s390/codegen.h"
34 #include "vm/jit/s390/emit.h"
35 #include "vm/jit/s390/md-abi.h"
37 #include "native/jni.h"
38 #include "native/localref.h"
39 #include "native/native.h"
41 #include "mm/memory.h"
43 #include "threads/lock-common.h"
45 #include "vmcore/loader.h"
46 #include "vmcore/options.h"
47 #include "vmcore/statistics.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
53 #include "vm/stringlocal.h"
56 #include "vm/jit/abi.h"
57 #if defined(ENABLE_LSRA)
58 # include "vm/jit/allocator/lsra.h"
60 #include "vm/jit/asmpart.h"
61 #include "vm/jit/codegen-common.h"
62 #include "vm/jit/dseg.h"
63 #include "vm/jit/emit-common.h"
64 #include "vm/jit/jit.h"
65 #include "vm/jit/linenumbertable.h"
66 #include "vm/jit/methodheader.h"
67 #include "vm/jit/parse.h"
68 #include "vm/jit/patcher-common.h"
69 #include "vm/jit/reg.h"
70 #include "vm/jit/replace.h"
71 #include "vm/jit/stacktrace.h"
72 #include "vm/jit/trap.h"
75 /* DO__LOG generates a call to do__log. No registers are destroyed,
76 * so you may use it anywhere. regs is an array containing all general
81 static void do__log(u4 *regs) {
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); \
91 N_LM(R0, R15, 96, REG_SP); \
94 /* If the following macro is defined, workaround code for hercules quirks
98 /* #define SUPPORT_HERCULES 1 */
100 /* codegen *********************************************************************
102 Generates machine code.
104 *******************************************************************************/
108 Layout of stackframe:
111 ===============================================================================
112 return_address (stackframesize - 1) * 8
113 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
115 saved_int_reg[rd->savintreguse]
116 saved_flt_reg[FLT_SAV_CNT - 1]
118 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
120 return_value_tmp (rd->memuse + 1) * 8
121 monitorenter_argument (rd->memuse) * 8
123 local[rd->memuse - 1] (rd->memuse - 1) * 8
131 bool codegen_emit(jitdata *jd)
137 s4 len, s1, s2, s3, d, dd, disp;
142 constant_classref *cr;
143 unresolved_class *uc;
144 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
145 unresolved_method *um;
146 builtintable_entry *bte;
149 unresolved_field *uf;
152 rplpoint *replacementpoint;
156 /* get required compiler data */
163 /* prevent compiler warnings */
176 /* space to save used callee saved registers */
178 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
179 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
181 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
184 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
187 #if defined(ENABLE_THREADS)
188 /* Space to save argument of monitor_enter and Return Values to
189 survive monitor_exit. The stack position for the argument can
190 not be shared with place to save the return register
191 since both values reside in R2. */
193 if (checksync && code_is_synchronized(code)) {
194 /* 1 slot space to save argument of monitor_enter */
195 /* 1 slot to temporary store return value before monitor_exit */
196 cd->stackframesize += 2;
200 /* Keep stack of non-leaf functions 16-byte aligned for calls into
201 native code e.g. libc or jni (alignment problems with
204 if (!code_is_leafmethod(code) || opt_verbosecall )
205 /* TODO really 16 bytes ? */
206 cd->stackframesize = (cd->stackframesize + 2) & ~2;
208 /* create method header */
210 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
211 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
213 code->synchronizedoffset = rd->memuse * 8;
215 /* REMOVEME: We still need it for exception handling in assembler. */
217 if (code_is_leafmethod(code))
218 (void) dseg_add_unique_s4(cd, 1);
220 (void) dseg_add_unique_s4(cd, 0);
222 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
223 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
227 M_AADD_IMM(N_PV_OFFSET, REG_PV);
229 /* create stack frame (if necessary) */
231 if (cd->stackframesize) {
232 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
235 /* store return address */
237 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
239 /* generate method profiling code */
241 #if defined(ENABLE_PROFILING)
242 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
243 /* count frequency */
244 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
245 ICONST(REG_ITMP2, 1);
246 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
247 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
253 /* save used callee saved registers and return address */
255 p = cd->stackframesize - 1;
257 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
258 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
260 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
261 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
264 /* take arguments out of register or stack frame */
268 for (p = 0, l = 0; p < md->paramcount; p++) {
269 t = md->paramtypes[p].type;
270 varindex = jd->local_map[l * 5 + t];
274 if (IS_2_WORD_TYPE(t))
277 if (varindex == UNUSED)
282 s1 = md->params[p].regoff;
284 if (IS_INT_LNG_TYPE(t)) { /* integer args */
285 if (IS_2_WORD_TYPE(t)) {
293 if (!md->params[p].inmemory) { /* register arguments */
294 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
295 if (IS_2_WORD_TYPE(t)) {
296 M_LNGMOVE(s2, var->vv.regoff);
298 M_INTMOVE(s2, var->vv.regoff);
300 } else { /* reg arg -> spilled */
301 if (IS_2_WORD_TYPE(t)) {
302 M_LST(s2, REG_SP, var->vv.regoff);
304 M_IST(s2, REG_SP, var->vv.regoff);
308 } else { /* stack arguments */
309 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
310 if (IS_2_WORD_TYPE(t)) {
311 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
313 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
315 } else { /* stack arg -> spilled */
316 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
320 } else { /* floating args */
321 if (!md->params[p].inmemory) { /* register arguments */
323 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
324 M_FLTMOVE(s2, var->vv.regoff);
326 } else { /* reg arg -> spilled */
327 if (IS_2_WORD_TYPE(t))
328 M_DST(s2, REG_SP, var->vv.regoff);
330 M_FST(s2, REG_SP, var->vv.regoff);
333 } else { /* stack arguments */
334 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
335 if (IS_2_WORD_TYPE(t))
336 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
339 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
341 } else { /* stack-arg -> spilled */
342 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
343 var->vv.regoff = cd->stackframesize * 8 + s1;
349 /* save monitorenter argument */
351 #if defined(ENABLE_THREADS)
352 if (checksync && code_is_synchronized(code)) {
353 /* stack offset for monitor argument */
358 if (opt_verbosecall) {
359 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
361 for (p = 0; p < INT_ARG_CNT; p++)
362 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
364 for (p = 0; p < FLT_ARG_CNT; p++)
365 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
367 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
371 /* decide which monitor enter function to call */
373 if (m->flags & ACC_STATIC) {
374 disp = dseg_add_address(cd, &m->clazz->object.header);
375 M_ALD_DSEG(REG_A0, disp);
379 M_BNE(SZ_BRC + SZ_ILL);
380 M_ILL(TRAP_NullPointerException);
383 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
384 M_ALD_DSEG(REG_ITMP2, disp);
386 M_AST(REG_A0, REG_SP, s1 * 8);
388 M_ASUB_IMM(96, REG_SP);
390 M_AADD_IMM(96, REG_SP);
393 if (opt_verbosecall) {
394 for (p = 0; p < INT_ARG_CNT; p++)
395 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
397 for (p = 0; p < FLT_ARG_CNT; p++)
398 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
400 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
407 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
408 emit_verbosecall_enter(jd);
409 #endif /* !defined(NDEBUG) */
413 /* end of header generation */
415 /* create replacement points */
417 REPLACEMENT_POINTS_INIT(cd, jd);
419 /* walk through all basic blocks */
421 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
423 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
425 if (bptr->flags >= BBREACHED) {
427 /* branch resolving */
429 codegen_resolve_branchrefs(cd, bptr);
431 /* handle replacement points */
433 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
435 /* copy interface registers to their destination */
440 #if defined(ENABLE_PROFILING)
441 /* generate basicblock profiling code */
443 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
444 /* count frequency */
446 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
447 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
448 ICONST(REG_ITMP2, 1);
449 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
450 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
452 /* if this is an exception handler, start profiling again */
454 if (bptr->type == BBTYPE_EXH)
459 #if defined(ENABLE_LSRA)
463 src = bptr->invars[len];
464 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
465 if (bptr->type == BBTYPE_EXH) {
466 /* d = reg_of_var(rd, src, REG_ITMP1); */
467 if (!IS_INMEMORY(src->flags))
471 M_INTMOVE(REG_ITMP3_XPTR, d);
472 emit_store(jd, NULL, src, d);
482 var = VAR(bptr->invars[len]);
483 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
484 if (bptr->type == BBTYPE_EXH) {
485 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
486 M_INTMOVE(REG_ITMP3_XPTR, d);
487 emit_store(jd, NULL, var, d);
491 assert((var->flags & INOUT));
494 #if defined(ENABLE_LSRA)
497 /* walk through all instructions */
502 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
503 if (iptr->line != currentline) {
504 linenumbertable_list_entry_add(cd, iptr->line);
505 currentline = iptr->line;
508 MCODECHECK(1024); /* 1KB should be enough */
511 case ICMD_NOP: /* ... ==> ... */
512 case ICMD_POP: /* ..., value ==> ... */
513 case ICMD_POP2: /* ..., value, value ==> ... */
516 case ICMD_INLINE_START:
518 REPLACEMENT_POINT_INLINE_START(cd, iptr);
521 case ICMD_INLINE_BODY:
523 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
524 linenumbertable_list_entry_add_inline_start(cd, iptr);
525 linenumbertable_list_entry_add(cd, iptr->line);
528 case ICMD_INLINE_END:
530 linenumbertable_list_entry_add_inline_end(cd, iptr);
531 linenumbertable_list_entry_add(cd, iptr->line);
534 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
535 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
536 emit_nullpointer_check(cd, iptr, s1);
539 /* constant operations ************************************************/
541 case ICMD_ICONST: /* ... ==> ..., constant */
542 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
543 ICONST(d, iptr->sx.val.i);
544 emit_store_dst(jd, iptr, d);
547 case ICMD_LCONST: /* ... ==> ..., constant */
549 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
550 LCONST(d, iptr->sx.val.l);
551 emit_store_dst(jd, iptr, d);
554 case ICMD_FCONST: /* ... ==> ..., constant */
555 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
556 disp = dseg_add_float(cd, iptr->sx.val.f);
557 M_FLD_DSEG(d, disp, REG_ITMP1);
558 emit_store_dst(jd, iptr, d);
561 case ICMD_DCONST: /* ... ==> ..., constant */
562 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
563 disp = dseg_add_double(cd, iptr->sx.val.d);
564 M_DLD_DSEG(d, disp, REG_ITMP1);
565 emit_store_dst(jd, iptr, d);
568 case ICMD_ACONST: /* ... ==> ..., constant */
569 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
571 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
572 cr = iptr->sx.val.c.ref;
573 disp = dseg_add_unique_address(cd, cr);
575 /* PROFILE_CYCLE_STOP; */
577 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
580 /* PROFILE_CYCLE_START; */
584 if (iptr->sx.val.anyptr == 0) {
587 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
590 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
591 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
593 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
595 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
601 emit_store_dst(jd, iptr, d);
605 /* load/store/copy/move operations ************************************/
607 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
608 case ICMD_ALOAD: /* s1 = local variable */
612 case ICMD_ISTORE: /* ..., value ==> ... */
623 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
627 /* integer operations *************************************************/
629 case ICMD_INEG: /* ..., value ==> ..., - value */
631 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
632 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
634 emit_store_dst(jd, iptr, d);
638 case ICMD_LNEG: /* ..., value ==> ..., - value */
640 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
641 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
642 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
643 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
644 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
645 N_AHI(GET_HIGH_REG(d), -1);
646 emit_store_dst(jd, iptr, d);
649 case ICMD_I2L: /* ..., value ==> ..., value */
651 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
652 if (! N_IS_EVEN_ODD(d)) {
653 d = REG_ITMP31_PACKED;
655 assert(N_IS_EVEN_ODD(d));
657 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
659 M_INTMOVE(s1, GET_HIGH_REG(d));
660 M_SRDA_IMM(32, GET_HIGH_REG(d));
662 emit_copy_dst(jd, iptr, d);
663 emit_store_dst(jd, iptr, d);
666 case ICMD_L2I: /* ..., value ==> ..., value */
667 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
668 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
669 M_INTMOVE(GET_LOW_REG(s1), d);
670 emit_store_dst(jd, iptr, d);
673 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
674 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
675 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
679 emit_store_dst(jd, iptr, d);
682 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
683 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
684 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
688 emit_store_dst(jd, iptr, d);
691 case ICMD_INT2SHORT: /* ..., 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_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
703 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
704 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
705 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
712 emit_store_dst(jd, iptr, d);
717 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
718 /* sx.val.i = constant */
719 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
720 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
723 if (N_VALID_IMM(iptr->sx.val.i)) {
724 M_IADD_IMM(iptr->sx.val.i, d);
726 ICONST(REG_ITMP2, iptr->sx.val.i);
727 M_IADD(REG_ITMP2, d);
729 emit_store_dst(jd, iptr, d);
732 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
734 /* M, (r, q) -> (r, q) */
736 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
738 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
739 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
740 dd = GET_HIGH_REG(d);
749 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
750 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
760 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
761 N_AHI(GET_HIGH_REG(d), 1);
763 emit_store_dst(jd, iptr, d);
766 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
767 /* sx.val.l = constant */
769 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
770 dd = GET_HIGH_REG(d);
772 s1 = emit_load_s1_high(jd, iptr, dd);
773 s3 = iptr->sx.val.l >> 32;
777 if (N_VALID_IMM(s3)) {
780 ICONST(REG_ITMP3, s3);
781 M_IADD(REG_ITMP3, dd);
785 s1 = emit_load_s1_low(jd, iptr, dd);
786 s3 = iptr->sx.val.l & 0xffffffff;
787 ICONST(REG_ITMP3, s3);
790 N_ALR(dd, REG_ITMP3);
792 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
793 N_AHI(GET_HIGH_REG(d), 1);
795 emit_store_dst(jd, iptr, d);
798 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
800 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
801 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
802 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
804 M_INTMOVE(s1, REG_ITMP1);
805 M_ISUB(s2, REG_ITMP1);
806 M_INTMOVE(REG_ITMP1, d);
811 emit_store_dst(jd, iptr, d);
815 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
816 /* sx.val.i = constant */
818 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
819 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
822 if (N_VALID_IMM(-iptr->sx.val.i)) {
823 M_ISUB_IMM(iptr->sx.val.i, d);
825 ICONST(REG_ITMP2, iptr->sx.val.i);
826 M_ISUB(REG_ITMP2, d);
828 emit_store_dst(jd, iptr, d);
832 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
834 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
836 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
837 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
838 dd = GET_HIGH_REG(d);
841 M_INTMOVE(s2, REG_ITMP3);
848 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
849 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
853 M_INTMOVE(s2, REG_ITMP3);
860 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
861 N_AHI(GET_HIGH_REG(d), -1);
863 emit_store_dst(jd, iptr, d);
866 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
867 /* sx.val.l = constant */
869 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
871 dd = GET_HIGH_REG(d);
872 s1 = emit_load_s1_high(jd, iptr, dd);
873 s3 = iptr->sx.val.l >> 32;
877 if (N_VALID_IMM(-s3)) {
880 ICONST(REG_ITMP3, s3);
881 M_ISUB(REG_ITMP3, dd);
885 s1 = emit_load_s1_low(jd, iptr, dd);
886 s3 = iptr->sx.val.l & 0xffffffff;
887 ICONST(REG_ITMP3, s3);
890 N_SLR(dd, REG_ITMP3);
892 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
893 N_AHI(GET_HIGH_REG(d), -1);
895 emit_store_dst(jd, iptr, d);
898 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
900 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
901 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
902 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
909 emit_store_dst(jd, iptr, d);
913 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
914 /* sx.val.i = constant */
915 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
916 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
918 if (iptr->sx.val.i == 2) {
920 } else if (N_VALID_IMM(iptr->sx.val.i)) {
921 M_IMUL_IMM(iptr->sx.val.i, d);
923 disp = dseg_add_s4(cd, iptr->sx.val.i);
924 M_ILD_DSEG(REG_ITMP2, disp);
925 M_IMUL(REG_ITMP2, d);
927 emit_store_dst(jd, iptr, d);
930 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
931 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
933 /* load s1 into r0 */
935 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
936 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
937 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
939 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
941 /* extend s1 to long */
943 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
947 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
953 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
954 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
957 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
958 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
962 emit_store_dst(jd, iptr, d);
966 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
967 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
969 bte = iptr->sx.s23.s3.bte;
972 /* test s2 for zero */
974 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
975 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
976 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
977 emit_arithmetic_check(cd, iptr, REG_ITMP3);
981 disp = dseg_add_functionptr(cd, bte->fp);
985 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
987 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
988 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
992 M_ASUB_IMM(96, REG_SP);
993 M_ALD_DSEG(REG_ITMP2, disp);
994 M_JSR(REG_RA, REG_ITMP2);
995 M_AADD_IMM(96, REG_SP);
999 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1000 M_LNGMOVE(REG_RESULT_PACKED, d);
1001 emit_store_dst(jd, iptr, d);
1005 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1006 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1007 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1009 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1010 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1011 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1013 /* Use only 5 bits of sencond operand. */
1015 M_INTMOVE(s2, REG_ITMP2);
1017 ICONST(REG_ITMP3, 0x1F);
1018 M_IAND(REG_ITMP3, s2);
1022 switch (iptr->opc) {
1035 emit_store_dst(jd, iptr, d);
1038 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1039 /* sx.val.i = constant */
1043 assert(iptr->sx.val.i <= 32);
1045 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1046 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1053 s3 = (1 << iptr->sx.val.i) - 1;
1055 if (N_VALID_IMM(s3)) {
1058 ICONST(REG_ITMP1, -1);
1059 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1060 M_IADD(REG_ITMP1, d);
1063 N_BRC_BACK_PATCH(ref);
1065 M_SRA_IMM(iptr->sx.val.i, d);
1067 emit_store_dst(jd, iptr, d);
1072 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1073 /* sx.val.i = constant */
1075 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1076 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1079 M_MOV(s1, REG_ITMP1);
1083 ICONST(REG_ITMP3, iptr->sx.val.i);
1086 M_IAND(REG_ITMP3, d);
1089 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1095 emit_store_dst(jd, iptr, d);
1099 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1100 /* sx.val.i = constant */
1101 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1102 /* sx.val.i = constant */
1103 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1104 /* sx.val.i = constant */
1105 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1106 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1110 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1112 switch (iptr->opc) {
1113 case ICMD_ISHLCONST:
1116 case ICMD_ISHRCONST:
1119 case ICMD_IUSHRCONST:
1126 emit_store_dst(jd, iptr, d);
1129 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1131 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1133 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1135 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1137 /* Use only 6 bits of second operand */
1139 M_INTMOVE(s2, REG_ITMP2);
1141 ICONST(REG_ITMP1, 0x3F);
1142 M_IAND(REG_ITMP1, s2);
1144 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1145 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1147 /* Destination must be even-odd pair */
1149 if (! N_IS_EVEN_ODD(d)) {
1150 d = REG_ITMP31_PACKED;
1153 assert(N_IS_EVEN_ODD(d));
1157 switch (iptr->opc) {
1159 M_SLDL(s2, GET_HIGH_REG(d));
1162 M_SRDA(s2, GET_HIGH_REG(d));
1165 M_SRDL(s2, GET_HIGH_REG(d));
1171 emit_copy_dst(jd, iptr, d);
1172 emit_store_dst(jd, iptr, d);
1176 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1177 /* sx.val.i = constant */
1178 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1179 /* sx.val.i = constant */
1180 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1181 /* sx.val.l = constant */
1184 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1185 if (! N_IS_EVEN_ODD(d)) {
1186 d = REG_ITMP31_PACKED;
1188 assert(N_IS_EVEN_ODD(d));
1190 s1 = emit_load_s1(jd, iptr, d);
1194 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1196 switch (iptr->opc) {
1197 case ICMD_LSHLCONST:
1198 N_SLDL(GET_HIGH_REG(d), disp, RN);
1200 case ICMD_LSHRCONST:
1201 N_SRDA(GET_HIGH_REG(d), disp, RN);
1203 case ICMD_LUSHRCONST:
1204 N_SRDL(GET_HIGH_REG(d), disp, RN);
1207 N_SLDL(GET_HIGH_REG(d), disp, RN);
1213 emit_copy_dst(jd, iptr, d);
1214 emit_store_dst(jd, iptr, d);
1217 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1219 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1220 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1221 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1228 emit_store_dst(jd, iptr, d);
1232 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1234 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1235 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1236 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1243 emit_store_dst(jd, iptr, d);
1247 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1249 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1250 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1251 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1258 emit_store_dst(jd, iptr, d);
1264 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1265 /* sx.val.i = constant */
1266 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1267 /* sx.val.i = constant */
1268 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1269 /* sx.val.i = constant */
1271 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1272 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1275 ICONST(REG_ITMP2, iptr->sx.val.i);
1277 switch (iptr->opc) {
1278 case ICMD_IANDCONST:
1279 M_IAND(REG_ITMP2, d);
1281 case ICMD_IXORCONST:
1282 M_IXOR(REG_ITMP2, d);
1285 M_IOR(REG_ITMP2, d);
1291 emit_store_dst(jd, iptr, d);
1295 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1296 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1297 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1299 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1301 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1302 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1303 dd = GET_LOW_REG(d);
1305 switch (iptr->opc) {
1334 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1335 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1336 dd = GET_HIGH_REG(d);
1338 switch (iptr->opc) {
1367 emit_store_dst(jd, iptr, d);
1370 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1371 /* sx.val.l = constant */
1372 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1373 /* sx.val.l = constant */
1374 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1375 /* sx.val.l = constant */
1377 /* TODO should use memory operand to access data segment, not load */
1379 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1381 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1382 s3 = iptr->sx.val.l & 0xffffffff;
1384 M_INTMOVE(s1, GET_LOW_REG(d));
1386 ICONST(REG_ITMP3, s3);
1388 switch (iptr->opc) {
1389 case ICMD_LANDCONST:
1390 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1392 case ICMD_LXORCONST:
1393 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1396 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1402 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1403 s3 = iptr->sx.val.l >> 32;
1405 M_INTMOVE(s1, GET_HIGH_REG(d));
1407 ICONST(REG_ITMP3, s3);
1409 switch (iptr->opc) {
1410 case ICMD_LANDCONST:
1411 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1413 case ICMD_LXORCONST:
1414 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1417 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1423 emit_store_dst(jd, iptr, d);
1427 /* floating operations ************************************************/
1429 case ICMD_FNEG: /* ..., value ==> ..., - value */
1430 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1431 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1433 emit_store_dst(jd, iptr, d);
1436 case ICMD_DNEG: /* ..., value ==> ..., - value */
1437 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1438 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1440 emit_store_dst(jd, iptr, d);
1443 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1444 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1445 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1446 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1453 emit_store_dst(jd, iptr, d);
1456 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1457 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1458 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1459 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1466 emit_store_dst(jd, iptr, d);
1469 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1470 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1471 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1472 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1476 emit_store_dst(jd, iptr, d);
1479 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1480 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1481 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1482 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1486 emit_store_dst(jd, iptr, d);
1489 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1490 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1491 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1492 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1499 emit_store_dst(jd, iptr, d);
1502 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1503 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1504 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1505 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1512 emit_store_dst(jd, iptr, d);
1515 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1516 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1517 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1518 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1522 emit_store_dst(jd, iptr, d);
1525 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1526 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1527 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1528 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1532 emit_store_dst(jd, iptr, d);
1535 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1536 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1537 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1539 emit_store_dst(jd, iptr, d);
1542 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1543 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1544 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1546 emit_store_dst(jd, iptr, d);
1549 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1553 #ifdef SUPPORT_HERCULES
1557 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1558 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1562 switch (iptr->opc) {
1571 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1572 N_LHI(d, 0); /* Load 0 */
1573 ref1 = cd->mcodeptr;
1574 N_BRC(DD_ANY, 0); /* Exit */
1578 switch (iptr->opc) {
1587 #ifdef SUPPORT_HERCULES
1588 /* Hercules does the conversion using a plain C conversion.
1589 * According to manual, real hardware should *NOT* require this.
1591 * Corner case: Positive float leads to INT_MIN (overflow).
1594 switch (iptr->opc) {
1603 ref2 = cd->mcodeptr;
1604 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1608 ref3 = cd->mcodeptr;
1609 M_BGE(0); /* If integer result is negative, continue */
1611 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1612 M_ILD_DSEG(d, disp);
1614 N_BRC_BACK_PATCH(ref1);
1615 #ifdef SUPPORT_HERCULES
1616 N_BRC_BACK_PATCH(ref2);
1617 N_BRC_BACK_PATCH(ref3);
1619 emit_store_dst(jd, iptr, d);
1623 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1625 #ifdef SUPPORT_HERCULES
1628 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1629 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1630 #ifdef SUPPORT_HERCULES
1633 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1634 disp = dseg_add_double(cd, 0.0 / 0.0);
1635 M_DLD_DSEG(d, disp, REG_ITMP1);
1636 emit_label_br(cd, BRANCH_LABEL_1);
1637 N_BRC_BACK_PATCH(ref);
1640 #ifdef SUPPORT_HERCULES
1641 emit_label(cd, BRANCH_LABEL_1);
1643 emit_store_dst(jd, iptr, d);
1647 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1648 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1649 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1651 emit_store_dst(jd, iptr, d);
1654 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1655 /* == => 0, < => 1, > => -1 */
1659 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1660 /* == => 0, < => 1, > => -1 */
1663 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1664 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1665 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1667 switch (iptr->opc) {
1679 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1680 SZ_BRC + SZ_BRC + SZ_BRC
1683 N_BRC( /* load -1 */
1684 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1685 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1690 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1693 N_LHI(d, 1); /* GT */
1694 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1695 N_LHI(d, -1); /* LT */
1696 M_BR(SZ_BRC + SZ_LHI);
1697 N_LHI(d, 0); /* EQ */
1699 emit_store_dst(jd, iptr, d);
1704 /* memory operations **************************************************/
1706 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1708 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1709 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1711 /* implicit null-pointer check */
1712 M_ILD(d, s1, OFFSET(java_array_t, size));
1713 emit_store_dst(jd, iptr, d);
1717 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1718 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1719 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1720 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1722 /* implicit null-pointer check */
1723 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1725 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1730 emit_store_dst(jd, iptr, d);
1733 case ICMD_CALOAD: /* ..., 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 M_INTMOVE(s2, REG_ITMP2);
1743 M_SLL_IMM(1, REG_ITMP2);
1745 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1747 /* N_LH does sign extends, undo ! */
1752 emit_store_dst(jd, iptr, d);
1755 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1756 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1757 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1758 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1760 /* implicit null-pointer check */
1761 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1763 M_INTMOVE(s2, REG_ITMP2);
1764 M_SLL_IMM(1, REG_ITMP2);
1766 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1767 emit_store_dst(jd, iptr, d);
1770 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1771 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1772 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1773 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1775 /* implicit null-pointer check */
1776 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1778 M_INTMOVE(s2, REG_ITMP2);
1779 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1780 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1781 emit_store_dst(jd, iptr, d);
1784 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1786 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1787 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1789 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1791 /* implicit null-pointer check */
1792 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1794 M_INTMOVE(s2, REG_ITMP2);
1795 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1798 GET_LOW_REG(d) /* maybe itmp3 */,
1799 OFFSET(java_longarray_t, data[0]) + 4,
1800 REG_ITMP2, s1 /* maybe itmp1 */
1804 GET_HIGH_REG(d) /* maybe itmp1 */,
1805 OFFSET(java_longarray_t, data[0]),
1806 REG_ITMP2, s1 /* maybe itmp1 */
1809 emit_store_dst(jd, iptr, d);
1813 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1815 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1816 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1817 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1819 /* implicit null-pointer check */
1820 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1822 M_INTMOVE(s2, REG_ITMP2);
1823 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1825 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1827 emit_store_dst(jd, iptr, d);
1830 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1831 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1832 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1833 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1835 /* implicit null-pointer check */
1836 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1838 M_INTMOVE(s2, REG_ITMP2);
1839 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1841 N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1843 emit_store_dst(jd, iptr, d);
1846 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1847 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1848 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1849 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1851 /* implicit null-pointer check */
1852 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1854 M_INTMOVE(s2, REG_ITMP2);
1855 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1856 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1857 emit_store_dst(jd, iptr, d);
1860 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1861 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1862 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1863 /* implicit null-pointer check */
1864 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1865 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1867 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1870 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1872 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1873 s2 = emit_load_s2(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);
1878 M_INTMOVE(s2, REG_ITMP2);
1879 M_SLL_IMM(1, REG_ITMP2);
1881 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1885 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1886 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1887 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1888 /* implicit null-pointer check */
1889 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1890 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1892 M_INTMOVE(s2, REG_ITMP2);
1893 M_SLL_IMM(1, REG_ITMP2);
1895 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1898 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1900 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1901 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1902 /* implicit null-pointer check */
1903 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1905 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1907 M_INTMOVE(s2, REG_ITMP2);
1908 M_SLL_IMM(2, REG_ITMP2);
1910 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1913 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1915 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1916 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1917 /* implicit null-pointer check */
1918 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1920 M_INTMOVE(s2, REG_ITMP2);
1921 M_SLL_IMM(3, REG_ITMP2);
1923 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1924 N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1);
1925 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1926 N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1);
1929 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1930 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1931 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1932 /* implicit null-pointer check */
1933 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1934 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1936 M_INTMOVE(s2, REG_ITMP2);
1937 M_SLL_IMM(2, REG_ITMP2);
1939 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1942 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1943 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1944 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1945 /* implicit null-pointer check */
1946 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1947 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1949 M_INTMOVE(s2, REG_ITMP2);
1950 M_SLL_IMM(3, REG_ITMP2);
1952 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1955 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1957 s1 = emit_load_s1(jd, iptr, REG_A0);
1958 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1959 /* implicit null-pointer check */
1960 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1961 s3 = emit_load_s3(jd, iptr, REG_A1);
1963 M_INTMOVE(s1, REG_A0);
1964 M_INTMOVE(s3, REG_A1);
1966 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1967 M_ALD_DSEG(REG_ITMP2, disp);
1968 M_ASUB_IMM(96, REG_SP);
1969 M_JSR(REG_RA, REG_ITMP2);
1970 M_AADD_IMM(96, REG_SP);
1972 emit_arraystore_check(cd, iptr);
1974 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1975 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1976 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1978 M_INTMOVE(s2, REG_ITMP2);
1979 M_SLL_IMM(2, REG_ITMP2);
1980 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1983 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1984 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1989 case ICMD_GETSTATIC: /* ... ==> ..., value */
1991 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1992 uf = iptr->sx.s23.s3.uf;
1993 fieldtype = uf->fieldref->parseddesc.fd->type;
1994 disp = dseg_add_unique_address(cd, NULL);
1996 /* PROFILE_CYCLE_STOP; */
1998 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2000 /* PROFILE_CYCLE_START; */
2003 fi = iptr->sx.s23.s3.fmiref->p.field;
2004 fieldtype = fi->type;
2005 disp = dseg_add_address(cd, fi->value);
2007 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
2010 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
2012 PROFILE_CYCLE_START;
2016 M_ALD_DSEG(REG_ITMP1, disp);
2018 switch (fieldtype) {
2020 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2021 M_ILD(d, REG_ITMP1, 0);
2024 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2025 M_LLD(d, REG_ITMP1, 0);
2028 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2029 M_ALD(d, REG_ITMP1, 0);
2032 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2033 M_FLD(d, REG_ITMP1, 0);
2036 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2037 M_DLD(d, REG_ITMP1, 0);
2041 emit_store_dst(jd, iptr, d);
2045 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2047 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2048 uf = iptr->sx.s23.s3.uf;
2049 fieldtype = uf->fieldref->parseddesc.fd->type;
2050 disp = dseg_add_unique_address(cd, uf);
2052 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2055 fi = iptr->sx.s23.s3.fmiref->p.field;
2056 fieldtype = fi->type;
2057 disp = dseg_add_address(cd, fi->value);
2059 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
2061 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
2062 PROFILE_CYCLE_START;
2066 M_ALD_DSEG(REG_ITMP1, disp);
2067 switch (fieldtype) {
2069 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2070 M_IST(s1, REG_ITMP1, 0);
2073 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2074 M_LST(s1, REG_ITMP1, 0);
2077 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2078 M_AST(s1, REG_ITMP1, 0);
2081 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2082 M_FST(s1, REG_ITMP1, 0);
2085 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2086 M_DST(s1, REG_ITMP1, 0);
2091 case ICMD_GETFIELD: /* ... ==> ..., value */
2093 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2094 emit_nullpointer_check(cd, iptr, s1);
2096 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2097 uf = iptr->sx.s23.s3.uf;
2098 fieldtype = uf->fieldref->parseddesc.fd->type;
2101 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2104 fi = iptr->sx.s23.s3.fmiref->p.field;
2105 fieldtype = fi->type;
2109 switch (fieldtype) {
2111 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2115 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2116 if (GET_HIGH_REG(d) == s1) {
2117 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2118 M_ILD(GET_HIGH_REG(d), s1, disp);
2121 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2122 M_ILD(GET_HIGH_REG(d), s1, disp);
2126 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2130 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2134 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2138 emit_store_dst(jd, iptr, d);
2141 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2145 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2146 emit_nullpointer_check(cd, iptr, s1);
2148 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2149 uf = iptr->sx.s23.s3.uf;
2150 fieldtype = uf->fieldref->parseddesc.fd->type;
2154 fi = iptr->sx.s23.s3.fmiref->p.field;
2155 fieldtype = fi->type;
2159 /* We can't add a patcher ref behind this load,
2160 * because the patcher would destroy REG_ITMP3.
2162 * We pass in the disp parameter, how many bytes
2163 * to skip to the to the actual store.
2165 * XXX this relies on patcher_add_patch_ref internals
2168 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2169 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2174 if (IS_INT_LNG_TYPE(fieldtype)) {
2175 if (IS_2_WORD_TYPE(fieldtype))
2176 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2178 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2180 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2183 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2184 ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2187 switch (fieldtype) {
2189 M_IST(s2, s1, disp);
2192 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2193 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2196 M_AST(s2, s1, disp);
2199 M_FST(s2, s1, disp);
2202 M_DST(s2, s1, disp);
2209 /* branch operations **************************************************/
2211 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2213 /* PROFILE_CYCLE_STOP; */
2215 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2216 M_INTMOVE(s1, REG_ITMP3_XPTR);
2218 #ifdef ENABLE_VERIFIER
2219 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2220 uc = iptr->sx.s23.s2.uc;
2222 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2224 #endif /* ENABLE_VERIFIER */
2226 disp = dseg_add_functionptr(cd, asm_handle_exception);
2227 M_ALD_DSEG(REG_ITMP1, disp);
2228 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2233 case ICMD_GOTO: /* ... ==> ... */
2234 case ICMD_RET: /* ... ==> ... */
2236 emit_br(cd, iptr->dst.block);
2240 case ICMD_JSR: /* ... ==> ... */
2242 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2246 case ICMD_IFNULL: /* ..., value ==> ... */
2247 case ICMD_IFNONNULL: /* ..., value ==> ... */
2248 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2250 switch (iptr->opc) {
2252 emit_beq(cd, iptr->dst.block);
2254 case ICMD_IFNONNULL:
2255 emit_bne(cd, iptr->dst.block);
2260 case ICMD_IFEQ: /* ..., value ==> ... */
2261 case ICMD_IFLT: /* ..., value ==> ... */
2262 case ICMD_IFLE: /* ..., value ==> ... */
2263 case ICMD_IFNE: /* ..., value ==> ... */
2264 case ICMD_IFGT: /* ..., value ==> ... */
2265 case ICMD_IFGE: /* ..., value ==> ... */
2267 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2269 if (N_VALID_IMM(iptr->sx.val.i))
2270 M_ICMP_IMM(s1, iptr->sx.val.i);
2272 disp = dseg_add_s4(cd, iptr->sx.val.i);
2273 if (N_VALID_DSEG_DISP(disp)) {
2274 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2276 ICONST(REG_ITMP2, disp);
2277 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2281 switch (iptr->opc) {
2283 emit_blt(cd, iptr->dst.block);
2286 emit_ble(cd, iptr->dst.block);
2289 emit_bne(cd, iptr->dst.block);
2292 emit_bgt(cd, iptr->dst.block);
2295 emit_bge(cd, iptr->dst.block);
2298 emit_beq(cd, iptr->dst.block);
2304 case ICMD_IF_LLT: /* ..., value ==> ... */
2305 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2311 /* ATTENTION: compare high words signed and low words unsigned */
2313 # define LABEL_OUT BRANCH_LABEL_1
2315 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2317 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2318 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2320 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2321 if (N_VALID_DSEG_DISP(disp)) {
2322 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2324 ICONST(REG_ITMP2, disp);
2325 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2332 emit_blt(cd, iptr->dst.block);
2333 /* EQ ... fall through */
2334 emit_label_bgt(cd, LABEL_OUT);
2338 emit_bgt(cd, iptr->dst.block);
2339 /* EQ ... fall through */
2340 emit_label_blt(cd, LABEL_OUT);
2343 /* EQ ... fall through */
2344 emit_label_bne(cd, LABEL_OUT);
2347 /* EQ ... fall through */
2348 emit_bne(cd, iptr->dst.block);
2354 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2356 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2357 if (N_VALID_DSEG_DISP(disp)) {
2358 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2360 ICONST(REG_ITMP2, disp);
2361 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2366 emit_blt(cd, iptr->dst.block);
2367 emit_label(cd, LABEL_OUT);
2370 emit_ble(cd, iptr->dst.block);
2371 emit_label(cd, LABEL_OUT);
2374 emit_bgt(cd, iptr->dst.block);
2375 emit_label(cd, LABEL_OUT);
2378 emit_bge(cd, iptr->dst.block);
2379 emit_label(cd, LABEL_OUT);
2382 emit_beq(cd, iptr->dst.block);
2383 emit_label(cd, LABEL_OUT);
2386 emit_bne(cd, iptr->dst.block);
2395 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2396 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2398 /* Compare addresses as 31 bit unsigned integers */
2400 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2401 M_LDA(REG_ITMP1, s1, 0);
2403 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2404 M_LDA(REG_ITMP2, s2, 0);
2406 M_CMP(REG_ITMP1, REG_ITMP2);
2408 switch (iptr->opc) {
2409 case ICMD_IF_ACMPEQ:
2410 emit_beq(cd, iptr->dst.block);
2412 case ICMD_IF_ACMPNE:
2413 emit_bne(cd, iptr->dst.block);
2419 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2420 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2421 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2422 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2423 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2424 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2426 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2427 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2429 switch (iptr->opc) {
2430 case ICMD_IF_ICMPEQ:
2431 emit_beq(cd, iptr->dst.block);
2433 case ICMD_IF_ICMPNE:
2434 emit_bne(cd, iptr->dst.block);
2436 case ICMD_IF_ICMPLT:
2437 emit_blt(cd, iptr->dst.block);
2439 case ICMD_IF_ICMPGT:
2440 emit_bgt(cd, iptr->dst.block);
2442 case ICMD_IF_ICMPLE:
2443 emit_ble(cd, iptr->dst.block);
2445 case ICMD_IF_ICMPGE:
2446 emit_bge(cd, iptr->dst.block);
2452 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2453 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2454 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2455 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2456 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2457 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2462 /* ATTENTION: compare high words signed and low words unsigned */
2464 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2465 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2470 case ICMD_IF_LCMPLT:
2471 case ICMD_IF_LCMPLE:
2472 emit_blt(cd, iptr->dst.block);
2473 /* EQ ... fall through */
2474 out_ref = cd->mcodeptr;
2477 case ICMD_IF_LCMPGT:
2478 case ICMD_IF_LCMPGE:
2479 emit_bgt(cd, iptr->dst.block);
2480 /* EQ ... fall through */
2481 out_ref = cd->mcodeptr;
2484 case ICMD_IF_LCMPEQ:
2485 /* EQ ... fall through */
2486 out_ref = cd->mcodeptr;
2489 case ICMD_IF_LCMPNE:
2490 /* EQ ... fall through */
2491 emit_bne(cd, iptr->dst.block);
2497 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2498 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2503 case ICMD_IF_LCMPLT:
2504 emit_blt(cd, iptr->dst.block);
2506 case ICMD_IF_LCMPLE:
2507 emit_ble(cd, iptr->dst.block);
2509 case ICMD_IF_LCMPGT:
2510 emit_bgt(cd, iptr->dst.block);
2512 case ICMD_IF_LCMPGE:
2513 emit_bge(cd, iptr->dst.block);
2515 case ICMD_IF_LCMPEQ:
2516 emit_beq(cd, iptr->dst.block);
2518 case ICMD_IF_LCMPNE:
2519 emit_bne(cd, iptr->dst.block);
2525 if (out_ref != NULL) {
2526 N_BRC_BACK_PATCH(out_ref);
2532 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2534 REPLACEMENT_POINT_RETURN(cd, iptr);
2535 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2536 M_INTMOVE(s1, REG_RESULT);
2537 goto nowperformreturn;
2539 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2541 REPLACEMENT_POINT_RETURN(cd, iptr);
2542 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2543 M_INTMOVE(s1, REG_RESULT);
2545 #ifdef ENABLE_VERIFIER
2546 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2547 unresolved_class *uc = iptr->sx.s23.s2.uc;
2550 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2551 PROFILE_CYCLE_START;
2553 #endif /* ENABLE_VERIFIER */
2554 goto nowperformreturn;
2556 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2558 REPLACEMENT_POINT_RETURN(cd, iptr);
2559 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2560 M_LNGMOVE(s1, REG_RESULT_PACKED);
2561 goto nowperformreturn;
2563 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2566 REPLACEMENT_POINT_RETURN(cd, iptr);
2567 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2568 M_FLTMOVE(s1, REG_FRESULT);
2569 goto nowperformreturn;
2571 case ICMD_RETURN: /* ... ==> ... */
2573 REPLACEMENT_POINT_RETURN(cd, iptr);
2579 p = cd->stackframesize;
2581 /* call trace function */
2583 #if !defined(NDEBUG)
2584 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2585 emit_verbosecall_exit(jd);
2586 #endif /* !defined(NDEBUG) */
2588 #if defined(ENABLE_THREADS)
2589 if (checksync && code_is_synchronized(code)) {
2590 /* we need to save the proper return value */
2592 switch (iptr->opc) {
2594 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2598 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2601 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2604 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2608 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2610 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2611 M_ALD_DSEG(REG_ITMP2, disp);
2613 M_ASUB_IMM(96, REG_SP);
2615 M_AADD_IMM(96, REG_SP);
2617 /* and now restore the proper return value */
2619 switch (iptr->opc) {
2621 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2625 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2628 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2631 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2637 /* restore return address */
2639 p--; M_ALD(REG_RA, REG_SP, p * 8);
2641 /* restore saved registers */
2643 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2644 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2646 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2647 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2650 /* deallocate stack */
2652 if (cd->stackframesize)
2653 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2655 /* generate method profiling code */
2663 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2666 branch_target_t *table;
2668 table = iptr->dst.table;
2670 l = iptr->sx.s23.s2.tablelow;
2671 i = iptr->sx.s23.s3.tablehigh;
2673 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2674 M_INTMOVE(s1, REG_ITMP1);
2678 } else if (N_VALID_IMM(-l)) {
2679 M_ISUB_IMM(l, REG_ITMP1);
2681 ICONST(REG_ITMP2, l);
2682 M_ISUB(REG_ITMP2, REG_ITMP1);
2685 /* number of targets */
2691 ICONST(REG_ITMP2, i);
2692 M_ICMPU(REG_ITMP1, REG_ITMP2);
2693 emit_bge(cd, table[0].block);
2695 /* build jump table top down and use address of lowest entry */
2700 dseg_add_target(cd, table->block);
2705 /* length of dataseg after last dseg_add_target is used by load */
2707 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2708 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2709 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2710 M_JMP(RN, REG_ITMP1);
2715 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2718 lookup_target_t *lookup;
2720 lookup = iptr->dst.lookup;
2722 i = iptr->sx.s23.s2.lookupcount;
2724 MCODECHECK(8 + ((7 + 6) * i) + 5);
2725 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2728 if (N_VALID_IMM(lookup->value)) {
2729 M_ICMP_IMM(s1, lookup->value);
2731 ICONST(REG_ITMP2, lookup->value);
2732 M_ICMP(REG_ITMP2, s1);
2734 emit_beq(cd, lookup->target.block);
2738 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2743 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2745 bte = iptr->sx.s23.s3.bte;
2749 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2750 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2751 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2752 case ICMD_INVOKEINTERFACE:
2754 REPLACEMENT_POINT_INVOKE(cd, iptr);
2756 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2758 um = iptr->sx.s23.s3.um;
2759 md = um->methodref->parseddesc.md;
2762 lm = iptr->sx.s23.s3.fmiref->p.method;
2764 md = lm->parseddesc;
2768 s3 = md->paramcount;
2770 MCODECHECK((s3 << 1) + 64);
2772 /* copy arguments to registers or stack location */
2774 for (s3 = s3 - 1; s3 >= 0; s3--) {
2775 var = VAR(iptr->sx.s23.s2.args[s3]);
2777 /* Already Preallocated? */
2778 if (var->flags & PREALLOC)
2781 if (IS_INT_LNG_TYPE(var->type)) {
2782 if (!md->params[s3].inmemory) {
2783 if (IS_2_WORD_TYPE(var->type)) {
2785 GET_LOW_REG(md->params[s3].regoff),
2786 GET_HIGH_REG(md->params[s3].regoff)
2788 d = emit_load(jd, iptr, var, s1);
2792 s1 = md->params[s3].regoff;
2793 d = emit_load(jd, iptr, var, s1);
2798 if (IS_2_WORD_TYPE(var->type)) {
2799 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2800 M_LST(d, REG_SP, md->params[s3].regoff);
2803 d = emit_load(jd, iptr, var, REG_ITMP1);
2804 M_IST(d, REG_SP, md->params[s3].regoff);
2809 if (!md->params[s3].inmemory) {
2810 s1 = md->params[s3].regoff;
2811 d = emit_load(jd, iptr, var, s1);
2815 d = emit_load(jd, iptr, var, REG_FTMP1);
2816 if (IS_2_WORD_TYPE(var->type))
2817 M_DST(d, REG_SP, md->params[s3].regoff);
2819 M_FST(d, REG_SP, md->params[s3].regoff);
2824 /* generate method profiling code */
2828 switch (iptr->opc) {
2830 if (bte->stub == NULL) {
2831 disp = dseg_add_functionptr(cd, bte->fp);
2832 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2834 disp = dseg_add_functionptr(cd, bte->stub);
2837 if (N_VALID_DSEG_DISP(disp)) {
2838 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2840 N_LHI(REG_ITMP1, disp);
2841 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2845 case ICMD_INVOKESPECIAL:
2847 /* Implicit NULL pointer check */
2848 M_ILD(REG_ITMP1, REG_A0, 0);
2852 case ICMD_INVOKESTATIC:
2854 disp = dseg_add_unique_address(cd, um);
2856 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2860 disp = dseg_add_address(cd, lm->stubroutine);
2862 if (N_VALID_DSEG_DISP(disp)) {
2863 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2865 N_LHI(REG_ITMP1, disp);
2866 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2870 case ICMD_INVOKEVIRTUAL:
2871 /* TODO softnull REG_A0 */
2874 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2879 s1 = OFFSET(vftbl_t, table[0]) +
2880 sizeof(methodptr) * lm->vftblindex;
2883 /* implicit null-pointer check */
2885 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2886 M_ALD(REG_PV, REG_METHODPTR, s1);
2889 case ICMD_INVOKEINTERFACE:
2890 /* TODO softnull REG_A0 */
2892 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2893 * and -0xFFF in index register (itmp1)
2897 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2903 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2904 sizeof(methodptr*) * lm->clazz->index;
2906 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2909 /* Implicit null-pointer check */
2910 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2911 N_LHI(REG_ITMP2, s1);
2912 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2913 M_ALD(REG_PV, REG_METHODPTR, s2);
2917 /* generate the actual call */
2920 emit_restore_pv(cd);
2922 /* post call finalization */
2924 switch (iptr->opc) {
2926 if (bte->stub == NULL) {
2927 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2932 /* generate method profiling code */
2934 PROFILE_CYCLE_START;
2936 /* store size of call code in replacement point */
2938 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2940 /* store return value */
2942 d = md->returntype.type;
2944 if (d != TYPE_VOID) {
2945 if (IS_INT_LNG_TYPE(d)) {
2946 if (IS_2_WORD_TYPE(d)) {
2947 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2948 M_LNGMOVE(REG_RESULT_PACKED, s1);
2951 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2952 M_INTMOVE(REG_RESULT, s1);
2956 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2957 M_FLTMOVE(REG_FRESULT, s1);
2959 emit_store_dst(jd, iptr, s1);
2965 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2967 /* val.a: (classinfo*) superclass */
2969 /* superclass is an interface:
2971 * OK if ((sub == NULL) ||
2972 * (sub->vftbl->interfacetablelength > super->index) &&
2973 * (sub->vftbl->interfacetable[-super->index] != NULL));
2975 * superclass is a class:
2977 * OK if ((sub == NULL) || (0
2978 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2979 * super->vftbl->diffval));
2982 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2983 /* object type cast-check */
2986 vftbl_t *supervftbl;
2989 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2990 # define LABEL_CLASS BRANCH_LABEL_2
2991 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2992 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2993 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2995 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3001 super = iptr->sx.s23.s3.c.cls;
3002 superindex = super->index;
3003 supervftbl = super->vftbl;
3006 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3007 CODEGEN_CRITICAL_SECTION_NEW;
3009 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3011 /* if class is not resolved, check which code to call */
3013 if (super == NULL) {
3015 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3017 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3019 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3020 iptr->sx.s23.s3.c.ref,
3023 ICONST(REG_ITMP3, ACC_INTERFACE);
3025 if (N_VALID_DSEG_DISP(disp)) {
3026 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3028 ICONST(REG_ITMP2, disp);
3029 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3031 emit_label_beq(cd, LABEL_CLASS);
3034 /* interface checkcast code */
3036 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3037 if (super == NULL) {
3038 patcher_add_patch_ref(jd,
3039 PATCHER_checkcast_instanceof_interface,
3040 iptr->sx.s23.s3.c.ref,
3044 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3047 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3048 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3049 M_ISUB_IMM(superindex, REG_ITMP3);
3050 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3053 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3054 superindex * sizeof(methodptr*))
3056 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3057 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3059 if (super == NULL) {
3060 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3064 /* class checkcast code */
3066 if (super == NULL) {
3067 emit_label(cd, LABEL_CLASS);
3070 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3071 if (super == NULL) {
3072 disp = dseg_add_unique_address(cd, NULL);
3074 patcher_add_patch_ref(jd,
3075 PATCHER_resolve_classref_to_vftbl,
3076 iptr->sx.s23.s3.c.ref,
3080 disp = dseg_add_address(cd, supervftbl);
3082 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3086 CODEGEN_CRITICAL_SECTION_START;
3088 /* REG_ITMP3 := baseval(s1) */
3089 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3090 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3092 /* REG_ITMP2 := baseval(class) */
3093 M_ALD_DSEG(REG_ITMP2, disp);
3094 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3096 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3097 M_ISUB(REG_ITMP2, REG_ITMP3);
3099 /* REG_ITMP2 := diffval(class) */
3100 M_ALD_DSEG(REG_ITMP2, disp);
3101 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3103 CODEGEN_CRITICAL_SECTION_END;
3105 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3107 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3108 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3109 /* Branch if greater then */
3111 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3112 M_ALD_DSEG(REG_ITMP3, disp);
3114 CODEGEN_CRITICAL_SECTION_START;
3116 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3117 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3118 M_ISUB(REG_ITMP3, REG_ITMP2);
3119 M_ALD_DSEG(REG_ITMP3, disp);
3120 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3122 CODEGEN_CRITICAL_SECTION_END;
3124 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3125 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3126 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3127 /* Branch if greater then */
3129 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3132 if (super == NULL) {
3133 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3134 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3135 } else if (super->flags & ACC_INTERFACE) {
3136 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3138 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3141 d = codegen_reg_of_dst(jd, iptr, s1);
3143 # undef LABEL_EXIT_CHECK_NULL
3145 # undef LABEL_EXIT_INTERFACE_NULL
3146 # undef LABEL_EXIT_INTERFACE_DONE
3147 # undef LABEL_EXIT_CLASS_NULL
3150 /* array type cast-check */
3152 s1 = emit_load_s1(jd, iptr, REG_A0);
3153 M_INTMOVE(s1, REG_A0);
3155 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3156 disp = dseg_add_unique_address(cd, NULL);
3158 patcher_add_patch_ref(jd,
3159 PATCHER_resolve_classref_to_classinfo,
3160 iptr->sx.s23.s3.c.ref,
3164 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3166 M_ALD_DSEG(REG_A1, disp);
3167 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3168 M_ALD_DSEG(REG_ITMP1, disp);
3169 M_ASUB_IMM(96, REG_SP);
3170 M_JSR(REG_RA, REG_ITMP1);
3171 M_AADD_IMM(96, REG_SP);
3173 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3174 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3176 d = codegen_reg_of_dst(jd, iptr, s1);
3180 emit_store_dst(jd, iptr, d);
3183 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3184 /* val.a: (classinfo*) superclass */
3186 /* superclass is an interface:
3188 * return (sub != NULL) &&
3189 * (sub->vftbl->interfacetablelength > super->index) &&
3190 * (sub->vftbl->interfacetable[-super->index] != NULL);
3192 * superclass is a class:
3194 * return ((sub != NULL) && (0
3195 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3196 * super->vftbl->diffvall));
3198 * If superclass is unresolved, we include both code snippets
3199 * above, a patcher resolves the class' flags and we select
3200 * the right code at runtime.
3205 vftbl_t *supervftbl;
3208 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3214 super = iptr->sx.s23.s3.c.cls;
3215 superindex = super->index;
3216 supervftbl = super->vftbl;
3219 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3220 # define LABEL_CLASS BRANCH_LABEL_2
3221 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3222 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3223 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3224 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3226 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3227 CODEGEN_CRITICAL_SECTION_NEW;
3229 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3230 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3232 M_MOV(s1, REG_ITMP1);
3236 /* if class is not resolved, check which code to call */
3238 if (super == NULL) {
3242 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3244 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3246 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3247 iptr->sx.s23.s3.c.ref, disp);
3249 ICONST(REG_ITMP3, ACC_INTERFACE);
3251 if (N_VALID_DSEG_DISP(disp)) {
3252 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3254 ICONST(REG_ITMP2, disp);
3255 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3258 emit_label_beq(cd, LABEL_CLASS);
3261 /* interface instanceof code */
3263 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3264 if (super == NULL) {
3265 /* If d == REG_ITMP2, then it's destroyed in check
3270 patcher_add_patch_ref(jd,
3271 PATCHER_checkcast_instanceof_interface,
3272 iptr->sx.s23.s3.c.ref, 0);
3277 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3280 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3281 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3282 M_ISUB_IMM(superindex, REG_ITMP3);
3284 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3288 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3289 superindex * sizeof(methodptr*))
3291 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3293 /* d := (REG_ITMP1 != 0) */
3295 N_LTR(d, REG_ITMP1);
3296 M_BEQ(SZ_BRC + SZ_LHI);
3299 if (super == NULL) {
3300 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3304 /* class instanceof code */
3306 if (super == NULL) {
3307 emit_label(cd, LABEL_CLASS);
3310 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3311 if (super == NULL) {
3312 disp = dseg_add_unique_address(cd, NULL);
3314 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3315 iptr->sx.s23.s3.c.ref,
3319 disp = dseg_add_address(cd, supervftbl);
3324 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3327 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3328 M_ALD_DSEG(REG_ITMP2, disp);
3330 CODEGEN_CRITICAL_SECTION_START;
3332 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3333 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3334 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3336 CODEGEN_CRITICAL_SECTION_END;
3338 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3340 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3342 M_BGT(SZ_BRC + SZ_LHI);
3346 if (super == NULL) {
3347 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3348 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3349 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3350 } else if (super->flags & ACC_INTERFACE) {
3351 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3352 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3354 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3357 # undef LABEL_EXIT_CHECK_NULL
3359 # undef LABEL_EXIT_INTERFACE_NULL
3360 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3361 # undef LABEL_EXIT_INTERFACE_DONE
3362 # undef LABEL_EXIT_CLASS_NULL
3364 emit_store_dst(jd, iptr, d);
3370 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3372 /* check for negative sizes and copy sizes to stack if necessary */
3374 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3377 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3379 /* copy SAVEDVAR sizes to stack */
3380 var = VAR(iptr->sx.s23.s2.args[s1]);
3382 /* Already Preallocated? */
3383 if (!(var->flags & PREALLOC)) {
3384 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3385 M_IST(s2, REG_SP, s1 * 4);
3389 /* is a patcher function set? */
3391 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3392 disp = dseg_add_unique_address(cd, 0);
3394 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3395 iptr->sx.s23.s3.c.ref,
3399 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3401 /* a0 = dimension count */
3403 ICONST(REG_A0, iptr->s1.argcount);
3405 /* a1 = classinfo */
3407 M_ALD_DSEG(REG_A1, disp);
3409 /* a2 = pointer to dimensions = stack pointer */
3411 M_MOV(REG_SP, REG_A2);
3413 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3414 M_ALD_DSEG(REG_ITMP1, disp);
3415 M_ASUB_IMM(96, REG_SP);
3416 M_JSR(REG_RA, REG_ITMP1);
3417 M_AADD_IMM(96, REG_SP);
3419 /* check for exception before result assignment */
3421 emit_exception_check(cd, iptr);
3423 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3424 M_INTMOVE(REG_RESULT, s1);
3425 emit_store_dst(jd, iptr, s1);
3430 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3434 } /* for instruction */
3436 MCODECHECK(512); /* XXX require a lower number? */
3438 /* At the end of a basic block we may have to append some nops,
3439 because the patcher stub calling code might be longer than the
3440 actual instruction. So codepatching does not change the
3441 following block unintentionally. */
3443 if (cd->mcodeptr < cd->lastmcodeptr) {
3444 while (cd->mcodeptr < cd->lastmcodeptr) {
3449 } /* if (bptr -> flags >= BBREACHED) */
3450 } /* for basic block */
3452 /* generate stubs */
3454 emit_patcher_traps(jd);
3456 /* everything's ok */
3461 /* codegen_emit_stub_native ****************************************************
3463 Emits a stub routine which calls a native method.
3465 *******************************************************************************/
3468 arguments on stack \
3469 -------------------------------------------------| <- SP on nativestub entry
3471 callee saved int regs (none) |
3472 callee saved float regs (none) | stack frame like in cacao
3473 local variable slots (none) |
3474 arguments for calling methods (none) /
3475 ------------------------------------------------------------------ <- datasp
3480 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3481 0 - 96 register save area for callee /
3482 -------------------------------------------------------- <- SP native method
3484 SP after method entry
3487 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3498 /* get required compiler data */
3504 /* set some variables */
3508 /* calculate stackframe size */
3510 cd->stackframesize =
3511 1 + /* return address */
3512 sizeof(stackframeinfo_t) / 8 +
3513 sizeof(localref_table) / 8 +
3516 (96 / 8); /* linkage area */
3518 /* keep stack 8-byte aligned */
3520 /*ALIGN_2(cd->stackframesize);*/
3522 /* create method header */
3524 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3525 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3526 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3527 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3528 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3532 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3533 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3535 /* store return address */
3537 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3539 #if defined(ENABLE_GC_CACAO)
3540 /* Save callee saved integer registers in stackframeinfo (GC may
3541 need to recover them during a collection). */
3543 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3544 OFFSET(stackframeinfo_t, intregs);
3546 for (i = 0; i < INT_SAV_CNT; i++)
3547 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3550 /* save integer and float argument registers */
3552 for (i = 0; i < md->paramcount; i++) {
3553 if (!md->params[i].inmemory) {
3554 s1 = md->params[i].regoff;
3556 switch (md->paramtypes[i].type) {
3559 M_IST(s1, REG_SP, 96 + i * 8);
3562 M_LST(s1, REG_SP, 96 + i * 8);
3566 M_DST(s1, REG_SP, 96 + i * 8);
3572 /* create native stack info */
3574 M_MOV(REG_SP, REG_A0);
3575 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3576 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3577 M_ALD_DSEG(REG_ITMP2, disp);
3580 /* remember class argument */
3582 if (m->flags & ACC_STATIC)
3583 M_MOV(REG_RESULT, REG_ITMP3);
3585 /* restore integer and float argument registers */
3587 for (i = 0; i < md->paramcount; i++) {
3588 if (!md->params[i].inmemory) {
3589 s1 = md->params[i].regoff;
3591 switch (md->paramtypes[i].type) {
3594 M_ILD(s1, REG_SP, 96 + i * 8);
3597 M_LLD(s1, REG_SP, 96 + i * 8);
3601 M_DLD(s1, REG_SP, 96 + i * 8);
3607 /* copy or spill arguments to new locations */
3609 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3610 t = md->paramtypes[i].type;
3612 if (IS_INT_LNG_TYPE(t)) {
3613 if (!md->params[i].inmemory) {
3614 s1 = md->params[i].regoff;
3615 s2 = nmd->params[j].regoff;
3617 if (!nmd->params[j].inmemory) {
3618 if (IS_2_WORD_TYPE(t))
3624 if (IS_2_WORD_TYPE(t))
3625 M_LST(s1, REG_SP, s2);
3627 M_IST(s1, REG_SP, s2);
3631 s1 = md->params[i].regoff + cd->stackframesize * 8;
3632 s2 = nmd->params[j].regoff;
3634 if (IS_2_WORD_TYPE(t)) {
3635 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3637 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3642 /* We only copy spilled float arguments, as the float
3643 argument registers keep unchanged. */
3645 if (md->params[i].inmemory) {
3646 s1 = md->params[i].regoff + cd->stackframesize * 8;
3647 s2 = nmd->params[j].regoff;
3649 if (IS_2_WORD_TYPE(t)) {
3650 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3652 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3658 /* Handle native Java methods. */
3660 if (m->flags & ACC_NATIVE) {
3661 /* put class into second argument register */
3663 if (m->flags & ACC_STATIC)
3664 M_MOV(REG_ITMP3, REG_A1);
3666 /* put env into first argument register */
3668 disp = dseg_add_address(cd, _Jv_env);
3669 M_ALD_DSEG(REG_A0, disp);
3672 /* Call native function. */
3674 disp = dseg_add_functionptr(cd, f);
3675 M_ALD_DSEG(REG_ITMP2, disp);
3678 /* save return value */
3680 switch (md->returntype.type) {
3683 M_IST(REG_RESULT, REG_SP, 96);
3686 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3690 M_DST(REG_FRESULT, REG_SP, 96);
3696 /* remove native stackframe info */
3698 M_MOV(REG_SP, REG_A0);
3699 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3700 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3701 M_ALD_DSEG(REG_ITMP1, disp);
3704 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3706 /* restore return value */
3708 switch (md->returntype.type) {
3711 M_ILD(REG_RESULT, REG_SP, 96);
3714 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3718 M_DLD(REG_FRESULT, REG_SP, 96);
3724 #if defined(ENABLE_GC_CACAO)
3725 /* Restore callee saved integer registers from stackframeinfo (GC
3726 might have modified them during a collection). */
3728 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3729 OFFSET(stackframeinfo_t, intregs);
3731 for (i = 0; i < INT_SAV_CNT; i++)
3732 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3735 /* load return address */
3737 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3739 /* remove stackframe */
3741 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3743 /* check for exception */
3745 M_TEST(REG_ITMP3_XPTR);
3746 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3750 /* handle exception */
3752 M_MOV(REG_RA, REG_ITMP1_XPC);
3753 M_ASUB_IMM(2, REG_ITMP1_XPC);
3755 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3756 M_ALD_DSEG(REG_ITMP2, disp);
3757 M_JMP(RN, REG_ITMP2);
3761 * These are local overrides for various environment variables in Emacs.
3762 * Please do not remove this and leave it at the end of the file, where
3763 * Emacs will automagically detect them.
3764 * ---------------------------------------------------------------------
3767 * indent-tabs-mode: t
3771 * vim:noexpandtab:sw=4:ts=4: