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 "native/jni.h"
33 #include "native/localref.h"
34 #include "native/native.h"
36 #include "mm/memory.h"
38 #include "threads/lock-common.h"
40 #include "vmcore/loader.h"
41 #include "vmcore/options.h"
42 #include "vmcore/statistics.h"
43 #include "vm/builtin.h"
44 #include "vm/exceptions.h"
45 #include "vm/global.h"
46 #include "vm/jit/abi.h"
47 #if defined(ENABLE_LSRA)
48 # include "vm/jit/allocator/lsra.h"
50 #include "vm/jit/asmpart.h"
51 #include "vm/jit/codegen-common.h"
52 #include "vm/jit/dseg.h"
53 #include "vm/jit/emit-common.h"
54 #include "vm/jit/jit.h"
55 #include "vm/jit/linenumbertable.h"
56 #include "vm/jit/methodheader.h"
57 #include "vm/jit/parse.h"
58 #include "vm/jit/patcher-common.h"
59 #include "vm/jit/reg.h"
60 #include "vm/jit/replace.h"
61 #include "vm/jit/s390/arch.h"
62 #include "vm/jit/s390/codegen.h"
63 #include "vm/jit/s390/emit.h"
64 #include "vm/jit/s390/md-abi.h"
65 #include "vm/jit/stacktrace.h"
67 #include "vm/stringlocal.h"
70 /* DO__LOG generates a call to do__log. No registers are destroyed,
71 * so you may use it anywhere. regs is an array containing all general
76 static void do__log(u4 *regs) {
81 N_AHI(REG_SP, -200); \
82 N_STM(R0, R15, 96, REG_SP); \
83 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
84 N_LA(R2, 96, RN, REG_SP); \
86 N_LM(R0, R15, 96, REG_SP); \
89 /* If the following macro is defined, workaround code for hercules quirks
93 /* #define SUPPORT_HERCULES 1 */
95 /* codegen *********************************************************************
97 Generates machine code.
99 *******************************************************************************/
103 Layout of stackframe:
106 ===============================================================================
107 return_address (stackframesize - 1) * 8
108 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
110 saved_int_reg[rd->savintreguse]
111 saved_flt_reg[FLT_SAV_CNT - 1]
113 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
115 return_value_tmp (rd->memuse + 1) * 8
116 monitorenter_argument (rd->memuse) * 8
118 local[rd->memuse - 1] (rd->memuse - 1) * 8
126 bool codegen_emit(jitdata *jd)
132 s4 len, s1, s2, s3, d, dd, disp;
137 constant_classref *cr;
138 unresolved_class *uc;
139 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
140 unresolved_method *um;
141 builtintable_entry *bte;
144 unresolved_field *uf;
147 rplpoint *replacementpoint;
151 /* get required compiler data */
158 /* prevent compiler warnings */
171 /* space to save used callee saved registers */
173 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
174 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
176 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
179 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
182 #if defined(ENABLE_THREADS)
183 /* Space to save argument of monitor_enter and Return Values to
184 survive monitor_exit. The stack position for the argument can
185 not be shared with place to save the return register
186 since both values reside in R2. */
188 if (checksync && code_is_synchronized(code)) {
189 /* 1 slot space to save argument of monitor_enter */
190 /* 1 slot to temporary store return value before monitor_exit */
191 cd->stackframesize += 2;
195 /* Keep stack of non-leaf functions 16-byte aligned for calls into
196 native code e.g. libc or jni (alignment problems with
199 if (!code_is_leafmethod(code) || opt_verbosecall )
200 /* TODO really 16 bytes ? */
201 cd->stackframesize = (cd->stackframesize + 2) & ~2;
203 /* create method header */
205 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
206 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
208 code->synchronizedoffset = rd->memuse * 8;
210 /* REMOVEME: We still need it for exception handling in assembler. */
212 if (code_is_leafmethod(code))
213 (void) dseg_add_unique_s4(cd, 1);
215 (void) dseg_add_unique_s4(cd, 0);
217 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
218 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
222 M_AADD_IMM(N_PV_OFFSET, REG_PV);
224 /* create stack frame (if necessary) */
226 if (cd->stackframesize) {
227 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
230 /* store return address */
232 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
234 /* generate method profiling code */
236 #if defined(ENABLE_PROFILING)
237 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
238 /* count frequency */
239 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
240 ICONST(REG_ITMP2, 1);
241 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
242 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
248 /* save used callee saved registers and return address */
250 p = cd->stackframesize - 1;
252 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
253 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
255 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
256 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
259 /* take arguments out of register or stack frame */
263 for (p = 0, l = 0; p < md->paramcount; p++) {
264 t = md->paramtypes[p].type;
265 varindex = jd->local_map[l * 5 + t];
269 if (IS_2_WORD_TYPE(t))
272 if (varindex == UNUSED)
277 s1 = md->params[p].regoff;
279 if (IS_INT_LNG_TYPE(t)) { /* integer args */
280 if (IS_2_WORD_TYPE(t)) {
288 if (!md->params[p].inmemory) { /* register arguments */
289 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
290 if (IS_2_WORD_TYPE(t)) {
291 M_LNGMOVE(s2, var->vv.regoff);
293 M_INTMOVE(s2, var->vv.regoff);
295 } else { /* reg arg -> spilled */
296 if (IS_2_WORD_TYPE(t)) {
297 M_LST(s2, REG_SP, var->vv.regoff);
299 M_IST(s2, REG_SP, var->vv.regoff);
303 } else { /* stack arguments */
304 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
305 if (IS_2_WORD_TYPE(t)) {
306 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
308 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
310 } else { /* stack arg -> spilled */
311 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
315 } else { /* floating args */
316 if (!md->params[p].inmemory) { /* register arguments */
318 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
319 M_FLTMOVE(s2, var->vv.regoff);
321 } else { /* reg arg -> spilled */
322 if (IS_2_WORD_TYPE(t))
323 M_DST(s2, REG_SP, var->vv.regoff);
325 M_FST(s2, REG_SP, var->vv.regoff);
328 } else { /* stack arguments */
329 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
330 if (IS_2_WORD_TYPE(t))
331 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
334 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
336 } else { /* stack-arg -> spilled */
337 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
338 var->vv.regoff = cd->stackframesize * 8 + s1;
344 /* save monitorenter argument */
346 #if defined(ENABLE_THREADS)
347 if (checksync && code_is_synchronized(code)) {
348 /* stack offset for monitor argument */
353 if (opt_verbosecall) {
354 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
356 for (p = 0; p < INT_ARG_CNT; p++)
357 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
359 for (p = 0; p < FLT_ARG_CNT; p++)
360 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
362 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
366 /* decide which monitor enter function to call */
368 if (m->flags & ACC_STATIC) {
369 disp = dseg_add_address(cd, &m->class->object.header);
370 M_ALD_DSEG(REG_A0, disp);
374 M_BNE(SZ_BRC + SZ_ILL);
375 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
378 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
379 M_ALD_DSEG(REG_ITMP2, disp);
381 M_AST(REG_A0, REG_SP, s1 * 8);
383 M_ASUB_IMM(96, REG_SP);
385 M_AADD_IMM(96, REG_SP);
388 if (opt_verbosecall) {
389 for (p = 0; p < INT_ARG_CNT; p++)
390 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
392 for (p = 0; p < FLT_ARG_CNT; p++)
393 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
395 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
402 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
403 emit_verbosecall_enter(jd);
404 #endif /* !defined(NDEBUG) */
408 /* end of header generation */
410 /* create replacement points */
412 REPLACEMENT_POINTS_INIT(cd, jd);
414 /* walk through all basic blocks */
416 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
418 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
420 if (bptr->flags >= BBREACHED) {
422 /* branch resolving */
424 codegen_resolve_branchrefs(cd, bptr);
426 /* handle replacement points */
428 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
430 /* copy interface registers to their destination */
435 #if defined(ENABLE_PROFILING)
436 /* generate basicblock profiling code */
438 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
439 /* count frequency */
441 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
442 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
443 ICONST(REG_ITMP2, 1);
444 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
445 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
447 /* if this is an exception handler, start profiling again */
449 if (bptr->type == BBTYPE_EXH)
454 #if defined(ENABLE_LSRA)
458 src = bptr->invars[len];
459 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
460 if (bptr->type == BBTYPE_EXH) {
461 /* d = reg_of_var(rd, src, REG_ITMP1); */
462 if (!IS_INMEMORY(src->flags))
466 M_INTMOVE(REG_ITMP3_XPTR, d);
467 emit_store(jd, NULL, src, d);
477 var = VAR(bptr->invars[len]);
478 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
479 if (bptr->type == BBTYPE_EXH) {
480 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
481 M_INTMOVE(REG_ITMP3_XPTR, d);
482 emit_store(jd, NULL, var, d);
486 assert((var->flags & INOUT));
489 #if defined(ENABLE_LSRA)
492 /* walk through all instructions */
497 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
498 if (iptr->line != currentline) {
499 linenumbertable_list_entry_add(cd, iptr->line);
500 currentline = iptr->line;
503 MCODECHECK(1024); /* 1KB should be enough */
506 case ICMD_NOP: /* ... ==> ... */
507 case ICMD_POP: /* ..., value ==> ... */
508 case ICMD_POP2: /* ..., value, value ==> ... */
511 case ICMD_INLINE_START:
513 REPLACEMENT_POINT_INLINE_START(cd, iptr);
516 case ICMD_INLINE_BODY:
518 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
519 linenumbertable_list_entry_add_inline_start(cd, iptr);
520 linenumbertable_list_entry_add(cd, iptr->line);
523 case ICMD_INLINE_END:
525 linenumbertable_list_entry_add_inline_end(cd, iptr);
526 linenumbertable_list_entry_add(cd, iptr->line);
529 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
530 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
531 emit_nullpointer_check(cd, iptr, s1);
534 /* constant operations ************************************************/
536 case ICMD_ICONST: /* ... ==> ..., constant */
537 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
538 ICONST(d, iptr->sx.val.i);
539 emit_store_dst(jd, iptr, d);
542 case ICMD_LCONST: /* ... ==> ..., constant */
544 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
545 LCONST(d, iptr->sx.val.l);
546 emit_store_dst(jd, iptr, d);
549 case ICMD_FCONST: /* ... ==> ..., constant */
550 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
551 disp = dseg_add_float(cd, iptr->sx.val.f);
552 M_FLD_DSEG(d, disp, REG_ITMP1);
553 emit_store_dst(jd, iptr, d);
556 case ICMD_DCONST: /* ... ==> ..., constant */
557 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
558 disp = dseg_add_double(cd, iptr->sx.val.d);
559 M_DLD_DSEG(d, disp, REG_ITMP1);
560 emit_store_dst(jd, iptr, d);
563 case ICMD_ACONST: /* ... ==> ..., constant */
564 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
566 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
567 cr = iptr->sx.val.c.ref;
568 disp = dseg_add_unique_address(cd, cr);
570 /* PROFILE_CYCLE_STOP; */
572 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
575 /* PROFILE_CYCLE_START; */
579 if (iptr->sx.val.anyptr == 0) {
582 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
585 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
586 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
588 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
590 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
596 emit_store_dst(jd, iptr, d);
600 /* load/store/copy/move operations ************************************/
602 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
603 case ICMD_ALOAD: /* s1 = local variable */
607 case ICMD_ISTORE: /* ..., value ==> ... */
618 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
622 /* integer operations *************************************************/
624 case ICMD_INEG: /* ..., value ==> ..., - value */
626 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
627 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
629 emit_store_dst(jd, iptr, d);
633 case ICMD_LNEG: /* ..., value ==> ..., - value */
635 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
636 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
637 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
638 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
639 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
640 N_AHI(GET_HIGH_REG(d), -1);
641 emit_store_dst(jd, iptr, d);
644 case ICMD_I2L: /* ..., value ==> ..., value */
646 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
647 if (! N_IS_EVEN_ODD(d)) {
648 d = REG_ITMP31_PACKED;
650 assert(N_IS_EVEN_ODD(d));
652 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
654 M_INTMOVE(s1, GET_HIGH_REG(d));
655 M_SRDA_IMM(32, GET_HIGH_REG(d));
657 emit_copy_dst(jd, iptr, d);
658 emit_store_dst(jd, iptr, d);
661 case ICMD_L2I: /* ..., value ==> ..., value */
662 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
663 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
664 M_INTMOVE(GET_LOW_REG(s1), d);
665 emit_store_dst(jd, iptr, d);
668 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
669 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
670 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
674 emit_store_dst(jd, iptr, d);
677 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
678 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
679 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
683 emit_store_dst(jd, iptr, d);
686 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
688 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
689 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
693 emit_store_dst(jd, iptr, d);
696 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
698 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
699 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
700 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
707 emit_store_dst(jd, iptr, d);
712 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
713 /* sx.val.i = constant */
714 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
715 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
718 if (N_VALID_IMM(iptr->sx.val.i)) {
719 M_IADD_IMM(iptr->sx.val.i, d);
721 ICONST(REG_ITMP2, iptr->sx.val.i);
722 M_IADD(REG_ITMP2, d);
724 emit_store_dst(jd, iptr, d);
727 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
729 /* M, (r, q) -> (r, q) */
731 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
733 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
734 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
735 dd = GET_HIGH_REG(d);
744 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
745 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
755 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
756 N_AHI(GET_HIGH_REG(d), 1);
758 emit_store_dst(jd, iptr, d);
761 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
762 /* sx.val.l = constant */
764 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
765 dd = GET_HIGH_REG(d);
767 s1 = emit_load_s1_high(jd, iptr, dd);
768 s3 = iptr->sx.val.l >> 32;
772 if (N_VALID_IMM(s3)) {
775 ICONST(REG_ITMP3, s3);
776 M_IADD(REG_ITMP3, dd);
780 s1 = emit_load_s1_low(jd, iptr, dd);
781 s3 = iptr->sx.val.l & 0xffffffff;
782 ICONST(REG_ITMP3, s3);
785 N_ALR(dd, REG_ITMP3);
787 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
788 N_AHI(GET_HIGH_REG(d), 1);
790 emit_store_dst(jd, iptr, d);
793 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
795 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
796 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
797 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
799 M_INTMOVE(s1, REG_ITMP1);
800 M_ISUB(s2, REG_ITMP1);
801 M_INTMOVE(REG_ITMP1, d);
806 emit_store_dst(jd, iptr, d);
810 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
811 /* sx.val.i = constant */
813 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
814 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
817 if (N_VALID_IMM(-iptr->sx.val.i)) {
818 M_ISUB_IMM(iptr->sx.val.i, d);
820 ICONST(REG_ITMP2, iptr->sx.val.i);
821 M_ISUB(REG_ITMP2, d);
823 emit_store_dst(jd, iptr, d);
827 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
829 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
831 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
832 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
833 dd = GET_HIGH_REG(d);
836 M_INTMOVE(s2, REG_ITMP3);
843 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
844 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
848 M_INTMOVE(s2, REG_ITMP3);
855 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
856 N_AHI(GET_HIGH_REG(d), -1);
858 emit_store_dst(jd, iptr, d);
861 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
862 /* sx.val.l = constant */
864 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
866 dd = GET_HIGH_REG(d);
867 s1 = emit_load_s1_high(jd, iptr, dd);
868 s3 = iptr->sx.val.l >> 32;
872 if (N_VALID_IMM(-s3)) {
875 ICONST(REG_ITMP3, s3);
876 M_ISUB(REG_ITMP3, dd);
880 s1 = emit_load_s1_low(jd, iptr, dd);
881 s3 = iptr->sx.val.l & 0xffffffff;
882 ICONST(REG_ITMP3, s3);
885 N_SLR(dd, REG_ITMP3);
887 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
888 N_AHI(GET_HIGH_REG(d), -1);
890 emit_store_dst(jd, iptr, d);
893 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
895 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
896 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
897 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
904 emit_store_dst(jd, iptr, d);
908 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
909 /* sx.val.i = constant */
910 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
911 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
913 if (iptr->sx.val.i == 2) {
915 } else if (N_VALID_IMM(iptr->sx.val.i)) {
916 M_IMUL_IMM(iptr->sx.val.i, d);
918 disp = dseg_add_s4(cd, iptr->sx.val.i);
919 M_ILD_DSEG(REG_ITMP2, disp);
920 M_IMUL(REG_ITMP2, d);
922 emit_store_dst(jd, iptr, d);
925 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
926 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
928 /* load s1 into r0 */
930 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
931 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
932 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
934 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
936 /* extend s1 to long */
938 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
942 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
948 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
949 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
952 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
953 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
957 emit_store_dst(jd, iptr, d);
961 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
962 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
964 bte = iptr->sx.s23.s3.bte;
967 /* test s2 for zero */
969 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
970 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
971 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
972 emit_arithmetic_check(cd, iptr, REG_ITMP3);
976 disp = dseg_add_functionptr(cd, bte->fp);
980 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
982 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
983 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
987 M_ASUB_IMM(96, REG_SP);
988 M_ALD_DSEG(REG_ITMP2, disp);
989 M_JSR(REG_RA, REG_ITMP2);
990 M_AADD_IMM(96, REG_SP);
994 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
995 M_LNGMOVE(REG_RESULT_PACKED, d);
996 emit_store_dst(jd, iptr, d);
1000 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1001 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1002 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1004 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1005 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1006 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1008 /* Use only 5 bits of sencond operand. */
1010 M_INTMOVE(s2, REG_ITMP2);
1012 ICONST(REG_ITMP3, 0x1F);
1013 M_IAND(REG_ITMP3, s2);
1017 switch (iptr->opc) {
1030 emit_store_dst(jd, iptr, d);
1033 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1034 /* sx.val.i = constant */
1038 assert(iptr->sx.val.i <= 32);
1040 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1041 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1048 s3 = (1 << iptr->sx.val.i) - 1;
1050 if (N_VALID_IMM(s3)) {
1053 ICONST(REG_ITMP1, -1);
1054 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1055 M_IADD(REG_ITMP1, d);
1058 N_BRC_BACK_PATCH(ref);
1060 M_SRA_IMM(iptr->sx.val.i, d);
1062 emit_store_dst(jd, iptr, d);
1067 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1068 /* sx.val.i = constant */
1070 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1071 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1074 M_MOV(s1, REG_ITMP1);
1078 ICONST(REG_ITMP3, iptr->sx.val.i);
1081 M_IAND(REG_ITMP3, d);
1084 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1090 emit_store_dst(jd, iptr, d);
1094 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1095 /* sx.val.i = constant */
1096 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1097 /* sx.val.i = constant */
1098 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1099 /* sx.val.i = constant */
1100 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1101 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1105 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1107 switch (iptr->opc) {
1108 case ICMD_ISHLCONST:
1111 case ICMD_ISHRCONST:
1114 case ICMD_IUSHRCONST:
1121 emit_store_dst(jd, iptr, d);
1124 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1126 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1128 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1130 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1132 /* Use only 6 bits of second operand */
1134 M_INTMOVE(s2, REG_ITMP2);
1136 ICONST(REG_ITMP1, 0x3F);
1137 M_IAND(REG_ITMP1, s2);
1139 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1140 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1142 /* Destination must be even-odd pair */
1144 if (! N_IS_EVEN_ODD(d)) {
1145 d = REG_ITMP31_PACKED;
1148 assert(N_IS_EVEN_ODD(d));
1152 switch (iptr->opc) {
1154 M_SLDL(s2, GET_HIGH_REG(d));
1157 M_SRDA(s2, GET_HIGH_REG(d));
1160 M_SRDL(s2, GET_HIGH_REG(d));
1166 emit_copy_dst(jd, iptr, d);
1167 emit_store_dst(jd, iptr, d);
1171 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1172 /* sx.val.i = constant */
1173 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1174 /* sx.val.i = constant */
1175 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1176 /* sx.val.l = constant */
1179 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1180 if (! N_IS_EVEN_ODD(d)) {
1181 d = REG_ITMP31_PACKED;
1183 assert(N_IS_EVEN_ODD(d));
1185 s1 = emit_load_s1(jd, iptr, d);
1189 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1191 switch (iptr->opc) {
1192 case ICMD_LSHLCONST:
1193 N_SLDL(GET_HIGH_REG(d), disp, RN);
1195 case ICMD_LSHRCONST:
1196 N_SRDA(GET_HIGH_REG(d), disp, RN);
1198 case ICMD_LUSHRCONST:
1199 N_SRDL(GET_HIGH_REG(d), disp, RN);
1202 N_SLDL(GET_HIGH_REG(d), disp, RN);
1208 emit_copy_dst(jd, iptr, d);
1209 emit_store_dst(jd, iptr, d);
1212 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1214 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1215 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1216 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1223 emit_store_dst(jd, iptr, d);
1227 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1229 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1230 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1231 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1238 emit_store_dst(jd, iptr, d);
1242 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1244 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1245 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1246 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1253 emit_store_dst(jd, iptr, d);
1259 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1260 /* sx.val.i = constant */
1261 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1262 /* sx.val.i = constant */
1263 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1264 /* sx.val.i = constant */
1266 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1267 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1270 ICONST(REG_ITMP2, iptr->sx.val.i);
1272 switch (iptr->opc) {
1273 case ICMD_IANDCONST:
1274 M_IAND(REG_ITMP2, d);
1276 case ICMD_IXORCONST:
1277 M_IXOR(REG_ITMP2, d);
1280 M_IOR(REG_ITMP2, d);
1286 emit_store_dst(jd, iptr, d);
1290 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1291 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1292 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1294 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1296 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1297 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1298 dd = GET_LOW_REG(d);
1300 switch (iptr->opc) {
1329 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1330 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1331 dd = GET_HIGH_REG(d);
1333 switch (iptr->opc) {
1362 emit_store_dst(jd, iptr, d);
1365 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1366 /* sx.val.l = constant */
1367 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1368 /* sx.val.l = constant */
1369 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1370 /* sx.val.l = constant */
1372 /* TODO should use memory operand to access data segment, not load */
1374 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1376 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1377 s3 = iptr->sx.val.l & 0xffffffff;
1379 M_INTMOVE(s1, GET_LOW_REG(d));
1381 ICONST(REG_ITMP3, s3);
1383 switch (iptr->opc) {
1384 case ICMD_LANDCONST:
1385 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1387 case ICMD_LXORCONST:
1388 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1391 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1397 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1398 s3 = iptr->sx.val.l >> 32;
1400 M_INTMOVE(s1, GET_HIGH_REG(d));
1402 ICONST(REG_ITMP3, s3);
1404 switch (iptr->opc) {
1405 case ICMD_LANDCONST:
1406 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1408 case ICMD_LXORCONST:
1409 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1412 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1418 emit_store_dst(jd, iptr, d);
1422 /* floating operations ************************************************/
1424 case ICMD_FNEG: /* ..., value ==> ..., - value */
1425 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1426 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1428 emit_store_dst(jd, iptr, d);
1431 case ICMD_DNEG: /* ..., value ==> ..., - value */
1432 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1433 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1435 emit_store_dst(jd, iptr, d);
1438 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1439 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1440 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1441 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1448 emit_store_dst(jd, iptr, d);
1451 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1452 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1453 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1454 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1461 emit_store_dst(jd, iptr, d);
1464 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1465 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1466 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1467 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1471 emit_store_dst(jd, iptr, d);
1474 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1475 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1476 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1477 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1481 emit_store_dst(jd, iptr, d);
1484 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1485 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1486 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1487 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1494 emit_store_dst(jd, iptr, d);
1497 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1498 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1499 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1500 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1507 emit_store_dst(jd, iptr, d);
1510 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1511 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1512 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1513 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1517 emit_store_dst(jd, iptr, d);
1520 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1521 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1522 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1523 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1527 emit_store_dst(jd, iptr, d);
1530 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1531 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1532 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1534 emit_store_dst(jd, iptr, d);
1537 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1538 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1539 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1541 emit_store_dst(jd, iptr, d);
1544 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1548 #ifdef SUPPORT_HERCULES
1552 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1553 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1557 switch (iptr->opc) {
1566 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1567 N_LHI(d, 0); /* Load 0 */
1568 ref1 = cd->mcodeptr;
1569 N_BRC(DD_ANY, 0); /* Exit */
1573 switch (iptr->opc) {
1582 #ifdef SUPPORT_HERCULES
1583 /* Hercules does the conversion using a plain C conversion.
1584 * According to manual, real hardware should *NOT* require this.
1586 * Corner case: Positive float leads to INT_MIN (overflow).
1589 switch (iptr->opc) {
1598 ref2 = cd->mcodeptr;
1599 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1603 ref3 = cd->mcodeptr;
1604 M_BGE(0); /* If integer result is negative, continue */
1606 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1607 M_ILD_DSEG(d, disp);
1609 N_BRC_BACK_PATCH(ref1);
1610 #ifdef SUPPORT_HERCULES
1611 N_BRC_BACK_PATCH(ref2);
1612 N_BRC_BACK_PATCH(ref3);
1614 emit_store_dst(jd, iptr, d);
1618 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1620 #ifdef SUPPORT_HERCULES
1623 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1624 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1625 #ifdef SUPPORT_HERCULES
1628 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1629 disp = dseg_add_double(cd, 0.0 / 0.0);
1630 M_DLD_DSEG(d, disp, REG_ITMP1);
1631 emit_label_br(cd, BRANCH_LABEL_1);
1632 N_BRC_BACK_PATCH(ref);
1635 #ifdef SUPPORT_HERCULES
1636 emit_label(cd, BRANCH_LABEL_1);
1638 emit_store_dst(jd, iptr, d);
1642 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1643 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1644 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1646 emit_store_dst(jd, iptr, d);
1649 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1650 /* == => 0, < => 1, > => -1 */
1654 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1655 /* == => 0, < => 1, > => -1 */
1658 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1659 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1660 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1662 switch (iptr->opc) {
1674 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1675 SZ_BRC + SZ_BRC + SZ_BRC
1678 N_BRC( /* load -1 */
1679 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1680 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1685 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1688 N_LHI(d, 1); /* GT */
1689 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1690 N_LHI(d, -1); /* LT */
1691 M_BR(SZ_BRC + SZ_LHI);
1692 N_LHI(d, 0); /* EQ */
1694 emit_store_dst(jd, iptr, d);
1699 /* memory operations **************************************************/
1701 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1703 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1704 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1706 /* implicit null-pointer check */
1707 M_ILD(d, s1, OFFSET(java_array_t, size));
1708 emit_store_dst(jd, iptr, d);
1712 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1713 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1714 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1715 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1717 /* implicit null-pointer check */
1718 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1720 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1725 emit_store_dst(jd, iptr, d);
1728 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1730 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1731 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1732 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1734 /* implicit null-pointer check */
1735 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1737 M_INTMOVE(s2, REG_ITMP2);
1738 M_SLL_IMM(1, REG_ITMP2);
1740 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1742 /* N_LH does sign extends, undo ! */
1747 emit_store_dst(jd, iptr, d);
1750 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1751 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1752 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1753 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1755 /* implicit null-pointer check */
1756 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1758 M_INTMOVE(s2, REG_ITMP2);
1759 M_SLL_IMM(1, REG_ITMP2);
1761 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1762 emit_store_dst(jd, iptr, d);
1765 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1766 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1767 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1768 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1770 /* implicit null-pointer check */
1771 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1773 M_INTMOVE(s2, REG_ITMP2);
1774 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1775 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1776 emit_store_dst(jd, iptr, d);
1779 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1781 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1782 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1784 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1786 /* implicit null-pointer check */
1787 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1789 M_INTMOVE(s2, REG_ITMP2);
1790 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1793 GET_LOW_REG(d) /* maybe itmp3 */,
1794 OFFSET(java_intarray_t, data[0]) + 4,
1795 REG_ITMP2, s1 /* maybe itmp1 */
1799 GET_HIGH_REG(d) /* maybe itmp1 */,
1800 OFFSET(java_intarray_t, data[0]),
1801 REG_ITMP2, s1 /* maybe itmp1 */
1804 emit_store_dst(jd, iptr, d);
1808 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1810 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1811 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1812 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1814 /* implicit null-pointer check */
1815 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1817 M_INTMOVE(s2, REG_ITMP2);
1818 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1820 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1822 emit_store_dst(jd, iptr, d);
1825 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1826 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1827 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1828 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1830 /* implicit null-pointer check */
1831 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1833 M_INTMOVE(s2, REG_ITMP2);
1834 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1836 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1838 emit_store_dst(jd, iptr, d);
1841 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1842 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1843 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1844 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1846 /* implicit null-pointer check */
1847 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1849 M_INTMOVE(s2, REG_ITMP2);
1850 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1851 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1852 emit_store_dst(jd, iptr, d);
1855 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1856 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1857 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1858 /* implicit null-pointer check */
1859 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1860 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1862 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1865 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1867 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1868 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1869 /* implicit null-pointer check */
1870 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1871 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1873 M_INTMOVE(s2, REG_ITMP2);
1874 M_SLL_IMM(1, REG_ITMP2);
1876 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1880 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1881 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1882 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1883 /* implicit null-pointer check */
1884 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1885 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1887 M_INTMOVE(s2, REG_ITMP2);
1888 M_SLL_IMM(1, REG_ITMP2);
1890 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1893 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1895 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1896 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1897 /* implicit null-pointer check */
1898 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1900 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1902 M_INTMOVE(s2, REG_ITMP2);
1903 M_SLL_IMM(2, REG_ITMP2);
1905 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1908 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1910 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1911 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1912 /* implicit null-pointer check */
1913 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1915 M_INTMOVE(s2, REG_ITMP2);
1916 M_SLL_IMM(3, REG_ITMP2);
1918 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1919 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1920 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1921 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1924 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1925 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1926 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1927 /* implicit null-pointer check */
1928 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1929 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1931 M_INTMOVE(s2, REG_ITMP2);
1932 M_SLL_IMM(2, REG_ITMP2);
1934 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1937 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1938 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1939 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1940 /* implicit null-pointer check */
1941 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1942 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1944 M_INTMOVE(s2, REG_ITMP2);
1945 M_SLL_IMM(3, REG_ITMP2);
1947 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1950 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1952 s1 = emit_load_s1(jd, iptr, REG_A0);
1953 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1954 /* implicit null-pointer check */
1955 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1956 s3 = emit_load_s3(jd, iptr, REG_A1);
1958 M_INTMOVE(s1, REG_A0);
1959 M_INTMOVE(s3, REG_A1);
1961 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1962 M_ALD_DSEG(REG_ITMP2, disp);
1963 M_ASUB_IMM(96, REG_SP);
1964 M_JSR(REG_RA, REG_ITMP2);
1965 M_AADD_IMM(96, REG_SP);
1967 emit_arraystore_check(cd, iptr);
1969 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1970 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1971 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1973 M_INTMOVE(s2, REG_ITMP2);
1974 M_SLL_IMM(2, REG_ITMP2);
1975 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1978 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1979 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1984 case ICMD_GETSTATIC: /* ... ==> ..., value */
1986 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1987 uf = iptr->sx.s23.s3.uf;
1988 fieldtype = uf->fieldref->parseddesc.fd->type;
1989 disp = dseg_add_unique_address(cd, NULL);
1991 /* PROFILE_CYCLE_STOP; */
1993 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1995 /* PROFILE_CYCLE_START; */
1998 fi = iptr->sx.s23.s3.fmiref->p.field;
1999 fieldtype = fi->type;
2000 disp = dseg_add_address(cd, fi->value);
2002 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2005 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
2007 PROFILE_CYCLE_START;
2011 M_ALD_DSEG(REG_ITMP1, disp);
2013 switch (fieldtype) {
2015 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2016 M_ILD(d, REG_ITMP1, 0);
2019 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2020 M_LLD(d, REG_ITMP1, 0);
2023 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2024 M_ALD(d, REG_ITMP1, 0);
2027 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2028 M_FLD(d, REG_ITMP1, 0);
2031 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2032 M_DLD(d, REG_ITMP1, 0);
2036 emit_store_dst(jd, iptr, d);
2040 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2042 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2043 uf = iptr->sx.s23.s3.uf;
2044 fieldtype = uf->fieldref->parseddesc.fd->type;
2045 disp = dseg_add_unique_address(cd, uf);
2047 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2050 fi = iptr->sx.s23.s3.fmiref->p.field;
2051 fieldtype = fi->type;
2052 disp = dseg_add_address(cd, fi->value);
2054 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2056 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
2057 PROFILE_CYCLE_START;
2061 M_ALD_DSEG(REG_ITMP1, disp);
2062 switch (fieldtype) {
2064 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2065 M_IST(s1, REG_ITMP1, 0);
2068 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2069 M_LST(s1, REG_ITMP1, 0);
2072 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2073 M_AST(s1, REG_ITMP1, 0);
2076 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2077 M_FST(s1, REG_ITMP1, 0);
2080 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2081 M_DST(s1, REG_ITMP1, 0);
2086 case ICMD_GETFIELD: /* ... ==> ..., value */
2088 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2089 emit_nullpointer_check(cd, iptr, s1);
2091 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2092 uf = iptr->sx.s23.s3.uf;
2093 fieldtype = uf->fieldref->parseddesc.fd->type;
2096 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2099 fi = iptr->sx.s23.s3.fmiref->p.field;
2100 fieldtype = fi->type;
2104 switch (fieldtype) {
2106 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2110 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2111 if (GET_HIGH_REG(d) == s1) {
2112 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2113 M_ILD(GET_HIGH_REG(d), s1, disp);
2116 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2117 M_ILD(GET_HIGH_REG(d), s1, disp);
2121 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2125 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2129 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2133 emit_store_dst(jd, iptr, d);
2136 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2140 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2141 emit_nullpointer_check(cd, iptr, s1);
2143 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2144 uf = iptr->sx.s23.s3.uf;
2145 fieldtype = uf->fieldref->parseddesc.fd->type;
2149 fi = iptr->sx.s23.s3.fmiref->p.field;
2150 fieldtype = fi->type;
2154 /* We can't add a patcher ref behind this load,
2155 * because the patcher would destroy REG_ITMP3.
2157 * We pass in the disp parameter, how many bytes
2158 * to skip to the to the actual store.
2160 * XXX this relies on patcher_add_patch_ref internals
2163 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2164 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2169 if (IS_INT_LNG_TYPE(fieldtype)) {
2170 if (IS_2_WORD_TYPE(fieldtype))
2171 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2173 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2175 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2178 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2179 ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2182 switch (fieldtype) {
2184 M_IST(s2, s1, disp);
2187 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2188 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2191 M_AST(s2, s1, disp);
2194 M_FST(s2, s1, disp);
2197 M_DST(s2, s1, disp);
2204 /* branch operations **************************************************/
2206 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2208 /* PROFILE_CYCLE_STOP; */
2210 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2211 M_INTMOVE(s1, REG_ITMP3_XPTR);
2213 #ifdef ENABLE_VERIFIER
2214 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2215 uc = iptr->sx.s23.s2.uc;
2217 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2219 #endif /* ENABLE_VERIFIER */
2221 disp = dseg_add_functionptr(cd, asm_handle_exception);
2222 M_ALD_DSEG(REG_ITMP1, disp);
2223 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2228 case ICMD_GOTO: /* ... ==> ... */
2229 case ICMD_RET: /* ... ==> ... */
2231 emit_br(cd, iptr->dst.block);
2235 case ICMD_JSR: /* ... ==> ... */
2237 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2241 case ICMD_IFNULL: /* ..., value ==> ... */
2242 case ICMD_IFNONNULL: /* ..., value ==> ... */
2243 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2245 switch (iptr->opc) {
2247 emit_beq(cd, iptr->dst.block);
2249 case ICMD_IFNONNULL:
2250 emit_bne(cd, iptr->dst.block);
2255 case ICMD_IFEQ: /* ..., value ==> ... */
2256 case ICMD_IFLT: /* ..., value ==> ... */
2257 case ICMD_IFLE: /* ..., value ==> ... */
2258 case ICMD_IFNE: /* ..., value ==> ... */
2259 case ICMD_IFGT: /* ..., value ==> ... */
2260 case ICMD_IFGE: /* ..., value ==> ... */
2262 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2264 if (N_VALID_IMM(iptr->sx.val.i))
2265 M_ICMP_IMM(s1, iptr->sx.val.i);
2267 disp = dseg_add_s4(cd, iptr->sx.val.i);
2268 if (N_VALID_DSEG_DISP(disp)) {
2269 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2271 ICONST(REG_ITMP2, disp);
2272 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2276 switch (iptr->opc) {
2278 emit_blt(cd, iptr->dst.block);
2281 emit_ble(cd, iptr->dst.block);
2284 emit_bne(cd, iptr->dst.block);
2287 emit_bgt(cd, iptr->dst.block);
2290 emit_bge(cd, iptr->dst.block);
2293 emit_beq(cd, iptr->dst.block);
2299 case ICMD_IF_LLT: /* ..., value ==> ... */
2300 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2306 /* ATTENTION: compare high words signed and low words unsigned */
2308 # define LABEL_OUT BRANCH_LABEL_1
2310 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2312 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2313 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2315 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2316 if (N_VALID_DSEG_DISP(disp)) {
2317 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2319 ICONST(REG_ITMP2, disp);
2320 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2327 emit_blt(cd, iptr->dst.block);
2328 /* EQ ... fall through */
2329 emit_label_bgt(cd, LABEL_OUT);
2333 emit_bgt(cd, iptr->dst.block);
2334 /* EQ ... fall through */
2335 emit_label_blt(cd, LABEL_OUT);
2338 /* EQ ... fall through */
2339 emit_label_bne(cd, LABEL_OUT);
2342 /* EQ ... fall through */
2343 emit_bne(cd, iptr->dst.block);
2349 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2351 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2352 if (N_VALID_DSEG_DISP(disp)) {
2353 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2355 ICONST(REG_ITMP2, disp);
2356 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2361 emit_blt(cd, iptr->dst.block);
2362 emit_label(cd, LABEL_OUT);
2365 emit_ble(cd, iptr->dst.block);
2366 emit_label(cd, LABEL_OUT);
2369 emit_bgt(cd, iptr->dst.block);
2370 emit_label(cd, LABEL_OUT);
2373 emit_bge(cd, iptr->dst.block);
2374 emit_label(cd, LABEL_OUT);
2377 emit_beq(cd, iptr->dst.block);
2378 emit_label(cd, LABEL_OUT);
2381 emit_bne(cd, iptr->dst.block);
2390 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2391 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2393 /* Compare addresses as 31 bit unsigned integers */
2395 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2396 M_LDA(REG_ITMP1, s1, 0);
2398 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2399 M_LDA(REG_ITMP2, s2, 0);
2401 M_CMP(REG_ITMP1, REG_ITMP2);
2403 switch (iptr->opc) {
2404 case ICMD_IF_ACMPEQ:
2405 emit_beq(cd, iptr->dst.block);
2407 case ICMD_IF_ACMPNE:
2408 emit_bne(cd, iptr->dst.block);
2414 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2415 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2416 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2417 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2418 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2419 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2421 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2422 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2424 switch (iptr->opc) {
2425 case ICMD_IF_ICMPEQ:
2426 emit_beq(cd, iptr->dst.block);
2428 case ICMD_IF_ICMPNE:
2429 emit_bne(cd, iptr->dst.block);
2431 case ICMD_IF_ICMPLT:
2432 emit_blt(cd, iptr->dst.block);
2434 case ICMD_IF_ICMPGT:
2435 emit_bgt(cd, iptr->dst.block);
2437 case ICMD_IF_ICMPLE:
2438 emit_ble(cd, iptr->dst.block);
2440 case ICMD_IF_ICMPGE:
2441 emit_bge(cd, iptr->dst.block);
2447 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2448 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2449 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2450 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2451 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2452 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2457 /* ATTENTION: compare high words signed and low words unsigned */
2459 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2460 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2465 case ICMD_IF_LCMPLT:
2466 case ICMD_IF_LCMPLE:
2467 emit_blt(cd, iptr->dst.block);
2468 /* EQ ... fall through */
2469 out_ref = cd->mcodeptr;
2472 case ICMD_IF_LCMPGT:
2473 case ICMD_IF_LCMPGE:
2474 emit_bgt(cd, iptr->dst.block);
2475 /* EQ ... fall through */
2476 out_ref = cd->mcodeptr;
2479 case ICMD_IF_LCMPEQ:
2480 /* EQ ... fall through */
2481 out_ref = cd->mcodeptr;
2484 case ICMD_IF_LCMPNE:
2485 /* EQ ... fall through */
2486 emit_bne(cd, iptr->dst.block);
2492 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2493 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2498 case ICMD_IF_LCMPLT:
2499 emit_blt(cd, iptr->dst.block);
2501 case ICMD_IF_LCMPLE:
2502 emit_ble(cd, iptr->dst.block);
2504 case ICMD_IF_LCMPGT:
2505 emit_bgt(cd, iptr->dst.block);
2507 case ICMD_IF_LCMPGE:
2508 emit_bge(cd, iptr->dst.block);
2510 case ICMD_IF_LCMPEQ:
2511 emit_beq(cd, iptr->dst.block);
2513 case ICMD_IF_LCMPNE:
2514 emit_bne(cd, iptr->dst.block);
2520 if (out_ref != NULL) {
2521 N_BRC_BACK_PATCH(out_ref);
2527 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2529 REPLACEMENT_POINT_RETURN(cd, iptr);
2530 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2531 M_INTMOVE(s1, REG_RESULT);
2532 goto nowperformreturn;
2534 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2536 REPLACEMENT_POINT_RETURN(cd, iptr);
2537 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2538 M_INTMOVE(s1, REG_RESULT);
2540 #ifdef ENABLE_VERIFIER
2541 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2542 unresolved_class *uc = iptr->sx.s23.s2.uc;
2545 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2546 PROFILE_CYCLE_START;
2548 #endif /* ENABLE_VERIFIER */
2549 goto nowperformreturn;
2551 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2553 REPLACEMENT_POINT_RETURN(cd, iptr);
2554 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2555 M_LNGMOVE(s1, REG_RESULT_PACKED);
2556 goto nowperformreturn;
2558 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2561 REPLACEMENT_POINT_RETURN(cd, iptr);
2562 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2563 M_FLTMOVE(s1, REG_FRESULT);
2564 goto nowperformreturn;
2566 case ICMD_RETURN: /* ... ==> ... */
2568 REPLACEMENT_POINT_RETURN(cd, iptr);
2574 p = cd->stackframesize;
2576 /* call trace function */
2578 #if !defined(NDEBUG)
2579 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2580 emit_verbosecall_exit(jd);
2581 #endif /* !defined(NDEBUG) */
2583 #if defined(ENABLE_THREADS)
2584 if (checksync && code_is_synchronized(code)) {
2585 /* we need to save the proper return value */
2587 switch (iptr->opc) {
2589 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2593 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2596 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2599 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2603 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2605 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2606 M_ALD_DSEG(REG_ITMP2, disp);
2608 M_ASUB_IMM(96, REG_SP);
2610 M_AADD_IMM(96, REG_SP);
2612 /* and now restore the proper return value */
2614 switch (iptr->opc) {
2616 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2620 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2623 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2626 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2632 /* restore return address */
2634 p--; M_ALD(REG_RA, REG_SP, p * 8);
2636 /* restore saved registers */
2638 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2639 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2641 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2642 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2645 /* deallocate stack */
2647 if (cd->stackframesize)
2648 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2650 /* generate method profiling code */
2658 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2661 branch_target_t *table;
2663 table = iptr->dst.table;
2665 l = iptr->sx.s23.s2.tablelow;
2666 i = iptr->sx.s23.s3.tablehigh;
2668 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2669 M_INTMOVE(s1, REG_ITMP1);
2673 } else if (N_VALID_IMM(-l)) {
2674 M_ISUB_IMM(l, REG_ITMP1);
2676 ICONST(REG_ITMP2, l);
2677 M_ISUB(REG_ITMP2, REG_ITMP1);
2680 /* number of targets */
2686 ICONST(REG_ITMP2, i);
2687 M_ICMPU(REG_ITMP1, REG_ITMP2);
2688 emit_bge(cd, table[0].block);
2690 /* build jump table top down and use address of lowest entry */
2695 dseg_add_target(cd, table->block);
2700 /* length of dataseg after last dseg_add_target is used by load */
2702 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2703 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2704 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2705 M_JMP(RN, REG_ITMP1);
2710 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2713 lookup_target_t *lookup;
2715 lookup = iptr->dst.lookup;
2717 i = iptr->sx.s23.s2.lookupcount;
2719 MCODECHECK(8 + ((7 + 6) * i) + 5);
2720 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2723 if (N_VALID_IMM(lookup->value)) {
2724 M_ICMP_IMM(s1, lookup->value);
2726 ICONST(REG_ITMP2, lookup->value);
2727 M_ICMP(REG_ITMP2, s1);
2729 emit_beq(cd, lookup->target.block);
2733 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2738 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2740 bte = iptr->sx.s23.s3.bte;
2744 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2745 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2746 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2747 case ICMD_INVOKEINTERFACE:
2749 REPLACEMENT_POINT_INVOKE(cd, iptr);
2751 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2753 um = iptr->sx.s23.s3.um;
2754 md = um->methodref->parseddesc.md;
2757 lm = iptr->sx.s23.s3.fmiref->p.method;
2759 md = lm->parseddesc;
2763 s3 = md->paramcount;
2765 MCODECHECK((s3 << 1) + 64);
2767 /* copy arguments to registers or stack location */
2769 for (s3 = s3 - 1; s3 >= 0; s3--) {
2770 var = VAR(iptr->sx.s23.s2.args[s3]);
2772 /* Already Preallocated? */
2773 if (var->flags & PREALLOC)
2776 if (IS_INT_LNG_TYPE(var->type)) {
2777 if (!md->params[s3].inmemory) {
2778 if (IS_2_WORD_TYPE(var->type)) {
2780 GET_LOW_REG(md->params[s3].regoff),
2781 GET_HIGH_REG(md->params[s3].regoff)
2783 d = emit_load(jd, iptr, var, s1);
2787 s1 = md->params[s3].regoff;
2788 d = emit_load(jd, iptr, var, s1);
2793 if (IS_2_WORD_TYPE(var->type)) {
2794 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2795 M_LST(d, REG_SP, md->params[s3].regoff);
2798 d = emit_load(jd, iptr, var, REG_ITMP1);
2799 M_IST(d, REG_SP, md->params[s3].regoff);
2804 if (!md->params[s3].inmemory) {
2805 s1 = md->params[s3].regoff;
2806 d = emit_load(jd, iptr, var, s1);
2810 d = emit_load(jd, iptr, var, REG_FTMP1);
2811 if (IS_2_WORD_TYPE(var->type))
2812 M_DST(d, REG_SP, md->params[s3].regoff);
2814 M_FST(d, REG_SP, md->params[s3].regoff);
2819 /* generate method profiling code */
2823 switch (iptr->opc) {
2825 if (bte->stub == NULL) {
2826 disp = dseg_add_functionptr(cd, bte->fp);
2827 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2829 disp = dseg_add_functionptr(cd, bte->stub);
2832 if (N_VALID_DSEG_DISP(disp)) {
2833 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2835 N_LHI(REG_ITMP1, disp);
2836 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2840 case ICMD_INVOKESPECIAL:
2842 /* Implicit NULL pointer check */
2843 M_ILD(REG_ITMP1, REG_A0, 0);
2847 case ICMD_INVOKESTATIC:
2849 disp = dseg_add_unique_address(cd, um);
2851 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2855 disp = dseg_add_address(cd, lm->stubroutine);
2857 if (N_VALID_DSEG_DISP(disp)) {
2858 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2860 N_LHI(REG_ITMP1, disp);
2861 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2865 case ICMD_INVOKEVIRTUAL:
2866 /* TODO softnull REG_A0 */
2869 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2874 s1 = OFFSET(vftbl_t, table[0]) +
2875 sizeof(methodptr) * lm->vftblindex;
2878 /* implicit null-pointer check */
2880 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2881 M_ALD(REG_PV, REG_METHODPTR, s1);
2884 case ICMD_INVOKEINTERFACE:
2885 /* TODO softnull REG_A0 */
2887 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2888 * and -0xFFF in index register (itmp1)
2892 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2898 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2899 sizeof(methodptr*) * lm->class->index;
2901 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2904 /* Implicit null-pointer check */
2905 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2906 N_LHI(REG_ITMP2, s1);
2907 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2908 M_ALD(REG_PV, REG_METHODPTR, s2);
2912 /* generate the actual call */
2915 emit_restore_pv(cd);
2917 /* post call finalization */
2919 switch (iptr->opc) {
2921 if (bte->stub == NULL) {
2922 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2927 /* generate method profiling code */
2929 PROFILE_CYCLE_START;
2931 /* store size of call code in replacement point */
2933 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2935 /* store return value */
2937 d = md->returntype.type;
2939 if (d != TYPE_VOID) {
2940 if (IS_INT_LNG_TYPE(d)) {
2941 if (IS_2_WORD_TYPE(d)) {
2942 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2943 M_LNGMOVE(REG_RESULT_PACKED, s1);
2946 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2947 M_INTMOVE(REG_RESULT, s1);
2951 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2952 M_FLTMOVE(REG_FRESULT, s1);
2954 emit_store_dst(jd, iptr, s1);
2960 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2962 /* val.a: (classinfo*) superclass */
2964 /* superclass is an interface:
2966 * OK if ((sub == NULL) ||
2967 * (sub->vftbl->interfacetablelength > super->index) &&
2968 * (sub->vftbl->interfacetable[-super->index] != NULL));
2970 * superclass is a class:
2972 * OK if ((sub == NULL) || (0
2973 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2974 * super->vftbl->diffval));
2977 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2978 /* object type cast-check */
2981 vftbl_t *supervftbl;
2984 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2985 # define LABEL_CLASS BRANCH_LABEL_2
2986 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2987 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2988 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2990 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2996 super = iptr->sx.s23.s3.c.cls;
2997 superindex = super->index;
2998 supervftbl = super->vftbl;
3001 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3002 CODEGEN_CRITICAL_SECTION_NEW;
3004 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3006 /* if class is not resolved, check which code to call */
3008 if (super == NULL) {
3010 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3012 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3014 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3015 iptr->sx.s23.s3.c.ref,
3018 ICONST(REG_ITMP3, ACC_INTERFACE);
3020 if (N_VALID_DSEG_DISP(disp)) {
3021 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3023 ICONST(REG_ITMP2, disp);
3024 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3026 emit_label_beq(cd, LABEL_CLASS);
3029 /* interface checkcast code */
3031 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3032 if (super == NULL) {
3033 patcher_add_patch_ref(jd,
3034 PATCHER_checkcast_instanceof_interface,
3035 iptr->sx.s23.s3.c.ref,
3039 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3042 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3043 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3044 M_ISUB_IMM(superindex, REG_ITMP3);
3045 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3048 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3049 superindex * sizeof(methodptr*))
3051 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3052 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3054 if (super == NULL) {
3055 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3059 /* class checkcast code */
3061 if (super == NULL) {
3062 emit_label(cd, LABEL_CLASS);
3065 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3066 if (super == NULL) {
3067 disp = dseg_add_unique_address(cd, NULL);
3069 patcher_add_patch_ref(jd,
3070 PATCHER_resolve_classref_to_vftbl,
3071 iptr->sx.s23.s3.c.ref,
3075 disp = dseg_add_address(cd, supervftbl);
3077 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3081 CODEGEN_CRITICAL_SECTION_START;
3083 /* REG_ITMP3 := baseval(s1) */
3084 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3085 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3087 /* REG_ITMP2 := baseval(class) */
3088 M_ALD_DSEG(REG_ITMP2, disp);
3089 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3091 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3092 M_ISUB(REG_ITMP2, REG_ITMP3);
3094 /* REG_ITMP2 := diffval(class) */
3095 M_ALD_DSEG(REG_ITMP2, disp);
3096 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3098 CODEGEN_CRITICAL_SECTION_END;
3100 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3102 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3103 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3104 /* Branch if greater then */
3106 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3107 M_ALD_DSEG(REG_ITMP3, disp);
3109 CODEGEN_CRITICAL_SECTION_START;
3111 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3112 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3113 M_ISUB(REG_ITMP3, REG_ITMP2);
3114 M_ALD_DSEG(REG_ITMP3, disp);
3115 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3117 CODEGEN_CRITICAL_SECTION_END;
3119 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3120 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3121 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3122 /* Branch if greater then */
3124 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3127 if (super == NULL) {
3128 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3129 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3130 } else if (super->flags & ACC_INTERFACE) {
3131 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3133 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3136 d = codegen_reg_of_dst(jd, iptr, s1);
3138 # undef LABEL_EXIT_CHECK_NULL
3140 # undef LABEL_EXIT_INTERFACE_NULL
3141 # undef LABEL_EXIT_INTERFACE_DONE
3142 # undef LABEL_EXIT_CLASS_NULL
3145 /* array type cast-check */
3147 s1 = emit_load_s1(jd, iptr, REG_A0);
3148 M_INTMOVE(s1, REG_A0);
3150 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3151 disp = dseg_add_unique_address(cd, NULL);
3153 patcher_add_patch_ref(jd,
3154 PATCHER_resolve_classref_to_classinfo,
3155 iptr->sx.s23.s3.c.ref,
3159 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3161 M_ALD_DSEG(REG_A1, disp);
3162 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3163 M_ALD_DSEG(REG_ITMP1, disp);
3164 M_ASUB_IMM(96, REG_SP);
3165 M_JSR(REG_RA, REG_ITMP1);
3166 M_AADD_IMM(96, REG_SP);
3168 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3169 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3171 d = codegen_reg_of_dst(jd, iptr, s1);
3175 emit_store_dst(jd, iptr, d);
3178 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3179 /* val.a: (classinfo*) superclass */
3181 /* superclass is an interface:
3183 * return (sub != NULL) &&
3184 * (sub->vftbl->interfacetablelength > super->index) &&
3185 * (sub->vftbl->interfacetable[-super->index] != NULL);
3187 * superclass is a class:
3189 * return ((sub != NULL) && (0
3190 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3191 * super->vftbl->diffvall));
3193 * If superclass is unresolved, we include both code snippets
3194 * above, a patcher resolves the class' flags and we select
3195 * the right code at runtime.
3200 vftbl_t *supervftbl;
3203 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3209 super = iptr->sx.s23.s3.c.cls;
3210 superindex = super->index;
3211 supervftbl = super->vftbl;
3214 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3215 # define LABEL_CLASS BRANCH_LABEL_2
3216 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3217 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3218 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3219 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3221 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3222 CODEGEN_CRITICAL_SECTION_NEW;
3224 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3225 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3227 M_MOV(s1, REG_ITMP1);
3231 /* if class is not resolved, check which code to call */
3233 if (super == NULL) {
3237 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3239 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3241 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3242 iptr->sx.s23.s3.c.ref, disp);
3244 ICONST(REG_ITMP3, ACC_INTERFACE);
3246 if (N_VALID_DSEG_DISP(disp)) {
3247 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3249 ICONST(REG_ITMP2, disp);
3250 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3253 emit_label_beq(cd, LABEL_CLASS);
3256 /* interface instanceof code */
3258 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3259 if (super == NULL) {
3260 /* If d == REG_ITMP2, then it's destroyed in check
3265 patcher_add_patch_ref(jd,
3266 PATCHER_checkcast_instanceof_interface,
3267 iptr->sx.s23.s3.c.ref, 0);
3272 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3275 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3276 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3277 M_ISUB_IMM(superindex, REG_ITMP3);
3279 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3283 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3284 superindex * sizeof(methodptr*))
3286 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3288 /* d := (REG_ITMP1 != 0) */
3290 N_LTR(d, REG_ITMP1);
3291 M_BEQ(SZ_BRC + SZ_LHI);
3294 if (super == NULL) {
3295 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3299 /* class instanceof code */
3301 if (super == NULL) {
3302 emit_label(cd, LABEL_CLASS);
3305 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3306 if (super == NULL) {
3307 disp = dseg_add_unique_address(cd, NULL);
3309 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3310 iptr->sx.s23.s3.c.ref,
3314 disp = dseg_add_address(cd, supervftbl);
3319 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3322 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3323 M_ALD_DSEG(REG_ITMP2, disp);
3325 CODEGEN_CRITICAL_SECTION_START;
3327 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3328 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3329 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3331 CODEGEN_CRITICAL_SECTION_END;
3333 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3335 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3337 M_BGT(SZ_BRC + SZ_LHI);
3341 if (super == NULL) {
3342 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3343 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3344 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3345 } else if (super->flags & ACC_INTERFACE) {
3346 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3347 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3349 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3352 # undef LABEL_EXIT_CHECK_NULL
3354 # undef LABEL_EXIT_INTERFACE_NULL
3355 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3356 # undef LABEL_EXIT_INTERFACE_DONE
3357 # undef LABEL_EXIT_CLASS_NULL
3359 emit_store_dst(jd, iptr, d);
3365 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3367 /* check for negative sizes and copy sizes to stack if necessary */
3369 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3372 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3374 /* copy SAVEDVAR sizes to stack */
3375 var = VAR(iptr->sx.s23.s2.args[s1]);
3377 /* Already Preallocated? */
3378 if (!(var->flags & PREALLOC)) {
3379 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3380 M_IST(s2, REG_SP, s1 * 4);
3384 /* is a patcher function set? */
3386 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3387 disp = dseg_add_unique_address(cd, 0);
3389 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3390 iptr->sx.s23.s3.c.ref,
3394 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3396 /* a0 = dimension count */
3398 ICONST(REG_A0, iptr->s1.argcount);
3400 /* a1 = classinfo */
3402 M_ALD_DSEG(REG_A1, disp);
3404 /* a2 = pointer to dimensions = stack pointer */
3406 M_MOV(REG_SP, REG_A2);
3408 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3409 M_ALD_DSEG(REG_ITMP1, disp);
3410 M_ASUB_IMM(96, REG_SP);
3411 M_JSR(REG_RA, REG_ITMP1);
3412 M_AADD_IMM(96, REG_SP);
3414 /* check for exception before result assignment */
3416 emit_exception_check(cd, iptr);
3418 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3419 M_INTMOVE(REG_RESULT, s1);
3420 emit_store_dst(jd, iptr, s1);
3425 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3429 } /* for instruction */
3431 MCODECHECK(512); /* XXX require a lower number? */
3433 /* At the end of a basic block we may have to append some nops,
3434 because the patcher stub calling code might be longer than the
3435 actual instruction. So codepatching does not change the
3436 following block unintentionally. */
3438 if (cd->mcodeptr < cd->lastmcodeptr) {
3439 while (cd->mcodeptr < cd->lastmcodeptr) {
3444 } /* if (bptr -> flags >= BBREACHED) */
3445 } /* for basic block */
3447 /* generate stubs */
3449 emit_patcher_traps(jd);
3451 /* everything's ok */
3456 /* codegen_emit_stub_native ****************************************************
3458 Emits a stub routine which calls a native method.
3460 *******************************************************************************/
3463 arguments on stack \
3464 -------------------------------------------------| <- SP on nativestub entry
3466 callee saved int regs (none) |
3467 callee saved float regs (none) | stack frame like in cacao
3468 local variable slots (none) |
3469 arguments for calling methods (none) /
3470 ------------------------------------------------------------------ <- datasp
3475 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3476 0 - 96 register save area for callee /
3477 -------------------------------------------------------- <- SP native method
3479 SP after method entry
3482 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3493 /* get required compiler data */
3499 /* set some variables */
3503 /* calculate stackframe size */
3505 cd->stackframesize =
3506 1 + /* return address */
3507 sizeof(stackframeinfo_t) / 8 +
3508 sizeof(localref_table) / 8 +
3511 (96 / 8); /* linkage area */
3513 /* keep stack 8-byte aligned */
3515 /*ALIGN_2(cd->stackframesize);*/
3517 /* create method header */
3519 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3520 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3521 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3522 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3523 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3527 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3528 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3530 /* store return address */
3532 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3534 #if defined(ENABLE_GC_CACAO)
3535 /* Save callee saved integer registers in stackframeinfo (GC may
3536 need to recover them during a collection). */
3538 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3539 OFFSET(stackframeinfo_t, intregs);
3541 for (i = 0; i < INT_SAV_CNT; i++)
3542 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3545 /* save integer and float argument registers */
3547 for (i = 0; i < md->paramcount; i++) {
3548 if (!md->params[i].inmemory) {
3549 s1 = md->params[i].regoff;
3551 switch (md->paramtypes[i].type) {
3554 M_IST(s1, REG_SP, 96 + i * 8);
3557 M_LST(s1, REG_SP, 96 + i * 8);
3561 M_DST(s1, REG_SP, 96 + i * 8);
3567 /* create native stack info */
3569 M_MOV(REG_SP, REG_A0);
3570 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3571 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3572 M_ALD_DSEG(REG_ITMP2, disp);
3575 /* remember class argument */
3577 if (m->flags & ACC_STATIC)
3578 M_MOV(REG_RESULT, REG_ITMP3);
3580 /* restore integer and float argument registers */
3582 for (i = 0; i < md->paramcount; i++) {
3583 if (!md->params[i].inmemory) {
3584 s1 = md->params[i].regoff;
3586 switch (md->paramtypes[i].type) {
3589 M_ILD(s1, REG_SP, 96 + i * 8);
3592 M_LLD(s1, REG_SP, 96 + i * 8);
3596 M_DLD(s1, REG_SP, 96 + i * 8);
3602 /* copy or spill arguments to new locations */
3604 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3605 t = md->paramtypes[i].type;
3607 if (IS_INT_LNG_TYPE(t)) {
3608 if (!md->params[i].inmemory) {
3609 s1 = md->params[i].regoff;
3610 s2 = nmd->params[j].regoff;
3612 if (!nmd->params[j].inmemory) {
3613 if (IS_2_WORD_TYPE(t))
3619 if (IS_2_WORD_TYPE(t))
3620 M_LST(s1, REG_SP, s2);
3622 M_IST(s1, REG_SP, s2);
3626 s1 = md->params[i].regoff + cd->stackframesize * 8;
3627 s2 = nmd->params[j].regoff;
3629 if (IS_2_WORD_TYPE(t)) {
3630 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3632 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3637 /* We only copy spilled float arguments, as the float
3638 argument registers keep unchanged. */
3640 if (md->params[i].inmemory) {
3641 s1 = md->params[i].regoff + cd->stackframesize * 8;
3642 s2 = nmd->params[j].regoff;
3644 if (IS_2_WORD_TYPE(t)) {
3645 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3647 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3653 /* Handle native Java methods. */
3655 if (m->flags & ACC_NATIVE) {
3656 /* put class into second argument register */
3658 if (m->flags & ACC_STATIC)
3659 M_MOV(REG_ITMP3, REG_A1);
3661 /* put env into first argument register */
3663 disp = dseg_add_address(cd, _Jv_env);
3664 M_ALD_DSEG(REG_A0, disp);
3667 /* Call native function. */
3669 disp = dseg_add_functionptr(cd, f);
3670 M_ALD_DSEG(REG_ITMP2, disp);
3673 /* save return value */
3675 switch (md->returntype.type) {
3678 M_IST(REG_RESULT, REG_SP, 96);
3681 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3685 M_DST(REG_FRESULT, REG_SP, 96);
3691 /* remove native stackframe info */
3693 M_MOV(REG_SP, REG_A0);
3694 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3695 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3696 M_ALD_DSEG(REG_ITMP1, disp);
3699 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3701 /* restore return value */
3703 switch (md->returntype.type) {
3706 M_ILD(REG_RESULT, REG_SP, 96);
3709 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3713 M_DLD(REG_FRESULT, REG_SP, 96);
3719 #if defined(ENABLE_GC_CACAO)
3720 /* Restore callee saved integer registers from stackframeinfo (GC
3721 might have modified them during a collection). */
3723 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3724 OFFSET(stackframeinfo_t, intregs);
3726 for (i = 0; i < INT_SAV_CNT; i++)
3727 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3730 /* load return address */
3732 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3734 /* remove stackframe */
3736 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3738 /* check for exception */
3740 M_TEST(REG_ITMP3_XPTR);
3741 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3745 /* handle exception */
3747 M_MOV(REG_RA, REG_ITMP1_XPC);
3748 M_ASUB_IMM(2, REG_ITMP1_XPC);
3750 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3751 M_ALD_DSEG(REG_ITMP2, disp);
3752 M_JMP(RN, REG_ITMP2);
3756 * These are local overrides for various environment variables in Emacs.
3757 * Please do not remove this and leave it at the end of the file, where
3758 * Emacs will automagically detect them.
3759 * ---------------------------------------------------------------------
3762 * indent-tabs-mode: t
3766 * vim:noexpandtab:sw=4:ts=4: