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.hpp"
51 #include "vm/global.h"
55 #include "vm/jit/abi.h"
56 #if defined(ENABLE_LSRA)
57 # include "vm/jit/allocator/lsra.h"
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/codegen-common.h"
61 #include "vm/jit/dseg.h"
62 #include "vm/jit/emit-common.h"
63 #include "vm/jit/jit.h"
64 #include "vm/jit/linenumbertable.h"
65 #include "vm/jit/methodheader.h"
66 #include "vm/jit/parse.h"
67 #include "vm/jit/patcher-common.h"
68 #include "vm/jit/reg.h"
69 #include "vm/jit/replace.h"
70 #include "vm/jit/stacktrace.hpp"
71 #include "vm/jit/trap.h"
74 /* DO__LOG generates a call to do__log. No registers are destroyed,
75 * so you may use it anywhere. regs is an array containing all general
80 static void do__log(u4 *regs) {
85 N_AHI(REG_SP, -200); \
86 N_STM(R0, R15, 96, REG_SP); \
87 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
88 N_LA(R2, 96, RN, REG_SP); \
90 N_LM(R0, R15, 96, REG_SP); \
93 /* If the following macro is defined, workaround code for hercules quirks
97 /* #define SUPPORT_HERCULES 1 */
99 /* codegen *********************************************************************
101 Generates machine code.
103 *******************************************************************************/
107 Layout of stackframe:
110 ===============================================================================
111 return_address (stackframesize - 1) * 8
112 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
114 saved_int_reg[rd->savintreguse]
115 saved_flt_reg[FLT_SAV_CNT - 1]
117 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
119 return_value_tmp (rd->memuse + 1) * 8
120 monitorenter_argument (rd->memuse) * 8
122 local[rd->memuse - 1] (rd->memuse - 1) * 8
130 bool codegen_emit(jitdata *jd)
136 s4 len, s1, s2, s3, d, dd, disp;
141 constant_classref *cr;
142 unresolved_class *uc;
143 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
144 unresolved_method *um;
145 builtintable_entry *bte;
148 unresolved_field *uf;
151 rplpoint *replacementpoint;
155 /* get required compiler data */
162 /* prevent compiler warnings */
175 /* space to save used callee saved registers */
177 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
178 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
180 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
183 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
186 #if defined(ENABLE_THREADS)
187 /* Space to save argument of monitor_enter and Return Values to
188 survive monitor_exit. The stack position for the argument can
189 not be shared with place to save the return register
190 since both values reside in R2. */
192 if (checksync && code_is_synchronized(code)) {
193 /* 1 slot space to save argument of monitor_enter */
194 /* 1 slot to temporary store return value before monitor_exit */
195 cd->stackframesize += 2;
199 /* Keep stack of non-leaf functions 16-byte aligned for calls into
200 native code e.g. libc or jni (alignment problems with
203 if (!code_is_leafmethod(code) || opt_verbosecall )
204 /* TODO really 16 bytes ? */
205 cd->stackframesize = (cd->stackframesize + 2) & ~2;
207 /* create method header */
209 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
210 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
212 code->synchronizedoffset = rd->memuse * 8;
214 /* REMOVEME: We still need it for exception handling in assembler. */
216 if (code_is_leafmethod(code))
217 (void) dseg_add_unique_s4(cd, 1);
219 (void) dseg_add_unique_s4(cd, 0);
221 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
222 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
226 M_AADD_IMM(N_PV_OFFSET, REG_PV);
228 /* create stack frame (if necessary) */
230 if (cd->stackframesize) {
231 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
234 /* store return address */
236 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
238 /* generate method profiling code */
240 #if defined(ENABLE_PROFILING)
241 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
242 /* count frequency */
243 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
244 ICONST(REG_ITMP2, 1);
245 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
246 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
252 /* save used callee saved registers and return address */
254 p = cd->stackframesize - 1;
256 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
257 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
259 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
260 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
263 /* take arguments out of register or stack frame */
267 for (p = 0, l = 0; p < md->paramcount; p++) {
268 t = md->paramtypes[p].type;
269 varindex = jd->local_map[l * 5 + t];
273 if (IS_2_WORD_TYPE(t))
276 if (varindex == UNUSED)
281 s1 = md->params[p].regoff;
283 if (IS_INT_LNG_TYPE(t)) { /* integer args */
284 if (IS_2_WORD_TYPE(t)) {
292 if (!md->params[p].inmemory) { /* register arguments */
293 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
294 if (IS_2_WORD_TYPE(t)) {
295 M_LNGMOVE(s2, var->vv.regoff);
297 M_INTMOVE(s2, var->vv.regoff);
299 } else { /* reg arg -> spilled */
300 if (IS_2_WORD_TYPE(t)) {
301 M_LST(s2, REG_SP, var->vv.regoff);
303 M_IST(s2, REG_SP, var->vv.regoff);
307 } else { /* stack arguments */
308 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
309 if (IS_2_WORD_TYPE(t)) {
310 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
312 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
314 } else { /* stack arg -> spilled */
315 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
319 } else { /* floating args */
320 if (!md->params[p].inmemory) { /* register arguments */
322 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
323 M_FLTMOVE(s2, var->vv.regoff);
325 } else { /* reg arg -> spilled */
326 if (IS_2_WORD_TYPE(t))
327 M_DST(s2, REG_SP, var->vv.regoff);
329 M_FST(s2, REG_SP, var->vv.regoff);
332 } else { /* stack arguments */
333 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
334 if (IS_2_WORD_TYPE(t))
335 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
338 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
340 } else { /* stack-arg -> spilled */
341 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
342 var->vv.regoff = cd->stackframesize * 8 + s1;
348 /* save monitorenter argument */
350 #if defined(ENABLE_THREADS)
351 if (checksync && code_is_synchronized(code)) {
352 /* stack offset for monitor argument */
357 if (opt_verbosecall) {
358 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
360 for (p = 0; p < INT_ARG_CNT; p++)
361 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
363 for (p = 0; p < FLT_ARG_CNT; p++)
364 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
366 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
370 /* decide which monitor enter function to call */
372 if (m->flags & ACC_STATIC) {
373 disp = dseg_add_address(cd, &m->clazz->object.header);
374 M_ALD_DSEG(REG_A0, disp);
378 M_BNE(SZ_BRC + SZ_ILL);
379 M_ILL(TRAP_NullPointerException);
382 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
383 M_ALD_DSEG(REG_ITMP2, disp);
385 M_AST(REG_A0, REG_SP, s1 * 8);
387 M_ASUB_IMM(96, REG_SP);
389 M_AADD_IMM(96, REG_SP);
392 if (opt_verbosecall) {
393 for (p = 0; p < INT_ARG_CNT; p++)
394 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
396 for (p = 0; p < FLT_ARG_CNT; p++)
397 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
399 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
406 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
407 emit_verbosecall_enter(jd);
408 #endif /* !defined(NDEBUG) */
412 /* end of header generation */
414 /* create replacement points */
416 REPLACEMENT_POINTS_INIT(cd, jd);
418 /* walk through all basic blocks */
420 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
422 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
424 if (bptr->flags >= BBREACHED) {
426 /* branch resolving */
428 codegen_resolve_branchrefs(cd, bptr);
430 /* handle replacement points */
432 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
434 /* copy interface registers to their destination */
439 #if defined(ENABLE_PROFILING)
440 /* generate basicblock profiling code */
442 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
443 /* count frequency */
445 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
446 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
447 ICONST(REG_ITMP2, 1);
448 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
449 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
451 /* if this is an exception handler, start profiling again */
453 if (bptr->type == BBTYPE_EXH)
458 #if defined(ENABLE_LSRA)
462 src = bptr->invars[len];
463 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
464 if (bptr->type == BBTYPE_EXH) {
465 /* d = reg_of_var(rd, src, REG_ITMP1); */
466 if (!IS_INMEMORY(src->flags))
470 M_INTMOVE(REG_ITMP3_XPTR, d);
471 emit_store(jd, NULL, src, d);
481 var = VAR(bptr->invars[len]);
482 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
483 if (bptr->type == BBTYPE_EXH) {
484 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
485 M_INTMOVE(REG_ITMP3_XPTR, d);
486 emit_store(jd, NULL, var, d);
490 assert((var->flags & INOUT));
493 #if defined(ENABLE_LSRA)
496 /* walk through all instructions */
501 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
502 if (iptr->line != currentline) {
503 linenumbertable_list_entry_add(cd, iptr->line);
504 currentline = iptr->line;
507 MCODECHECK(1024); /* 1KB should be enough */
510 case ICMD_NOP: /* ... ==> ... */
511 case ICMD_POP: /* ..., value ==> ... */
512 case ICMD_POP2: /* ..., value, value ==> ... */
515 case ICMD_INLINE_START:
517 REPLACEMENT_POINT_INLINE_START(cd, iptr);
520 case ICMD_INLINE_BODY:
522 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
523 linenumbertable_list_entry_add_inline_start(cd, iptr);
524 linenumbertable_list_entry_add(cd, iptr->line);
527 case ICMD_INLINE_END:
529 linenumbertable_list_entry_add_inline_end(cd, iptr);
530 linenumbertable_list_entry_add(cd, iptr->line);
533 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
534 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
535 emit_nullpointer_check(cd, iptr, s1);
538 /* constant operations ************************************************/
540 case ICMD_ICONST: /* ... ==> ..., constant */
541 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
542 ICONST(d, iptr->sx.val.i);
543 emit_store_dst(jd, iptr, d);
546 case ICMD_LCONST: /* ... ==> ..., constant */
548 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
549 LCONST(d, iptr->sx.val.l);
550 emit_store_dst(jd, iptr, d);
553 case ICMD_FCONST: /* ... ==> ..., constant */
554 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
555 disp = dseg_add_float(cd, iptr->sx.val.f);
556 M_FLD_DSEG(d, disp, REG_ITMP1);
557 emit_store_dst(jd, iptr, d);
560 case ICMD_DCONST: /* ... ==> ..., constant */
561 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
562 disp = dseg_add_double(cd, iptr->sx.val.d);
563 M_DLD_DSEG(d, disp, REG_ITMP1);
564 emit_store_dst(jd, iptr, d);
567 case ICMD_ACONST: /* ... ==> ..., constant */
568 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
570 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
571 cr = iptr->sx.val.c.ref;
572 disp = dseg_add_unique_address(cd, cr);
574 /* PROFILE_CYCLE_STOP; */
576 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
579 /* PROFILE_CYCLE_START; */
583 if (iptr->sx.val.anyptr == 0) {
586 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
589 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
590 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
592 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
594 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
600 emit_store_dst(jd, iptr, d);
604 /* load/store/copy/move operations ************************************/
606 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
607 case ICMD_ALOAD: /* s1 = local variable */
611 case ICMD_ISTORE: /* ..., value ==> ... */
622 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
626 /* integer operations *************************************************/
628 case ICMD_INEG: /* ..., value ==> ..., - value */
630 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
631 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
633 emit_store_dst(jd, iptr, d);
637 case ICMD_LNEG: /* ..., value ==> ..., - value */
639 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
640 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
641 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
642 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
643 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
644 N_AHI(GET_HIGH_REG(d), -1);
645 emit_store_dst(jd, iptr, d);
648 case ICMD_I2L: /* ..., value ==> ..., value */
650 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
651 if (! N_IS_EVEN_ODD(d)) {
652 d = REG_ITMP31_PACKED;
654 assert(N_IS_EVEN_ODD(d));
656 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
658 M_INTMOVE(s1, GET_HIGH_REG(d));
659 M_SRDA_IMM(32, GET_HIGH_REG(d));
661 emit_copy_dst(jd, iptr, d);
662 emit_store_dst(jd, iptr, d);
665 case ICMD_L2I: /* ..., value ==> ..., value */
666 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
667 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
668 M_INTMOVE(GET_LOW_REG(s1), d);
669 emit_store_dst(jd, iptr, d);
672 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
673 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
674 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
678 emit_store_dst(jd, iptr, d);
681 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
682 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
683 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
687 emit_store_dst(jd, iptr, d);
690 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
692 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
693 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
697 emit_store_dst(jd, iptr, d);
700 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
702 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
703 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
704 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
711 emit_store_dst(jd, iptr, d);
716 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
717 /* sx.val.i = constant */
718 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
719 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
722 if (N_VALID_IMM(iptr->sx.val.i)) {
723 M_IADD_IMM(iptr->sx.val.i, d);
725 ICONST(REG_ITMP2, iptr->sx.val.i);
726 M_IADD(REG_ITMP2, d);
728 emit_store_dst(jd, iptr, d);
731 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
733 /* M, (r, q) -> (r, q) */
735 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
737 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
738 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
739 dd = GET_HIGH_REG(d);
748 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
749 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
759 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
760 N_AHI(GET_HIGH_REG(d), 1);
762 emit_store_dst(jd, iptr, d);
765 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
766 /* sx.val.l = constant */
768 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
769 dd = GET_HIGH_REG(d);
771 s1 = emit_load_s1_high(jd, iptr, dd);
772 s3 = iptr->sx.val.l >> 32;
776 if (N_VALID_IMM(s3)) {
779 ICONST(REG_ITMP3, s3);
780 M_IADD(REG_ITMP3, dd);
784 s1 = emit_load_s1_low(jd, iptr, dd);
785 s3 = iptr->sx.val.l & 0xffffffff;
786 ICONST(REG_ITMP3, s3);
789 N_ALR(dd, REG_ITMP3);
791 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
792 N_AHI(GET_HIGH_REG(d), 1);
794 emit_store_dst(jd, iptr, d);
797 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
799 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
800 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
801 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
803 M_INTMOVE(s1, REG_ITMP1);
804 M_ISUB(s2, REG_ITMP1);
805 M_INTMOVE(REG_ITMP1, d);
810 emit_store_dst(jd, iptr, d);
814 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
815 /* sx.val.i = constant */
817 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
818 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
821 if (N_VALID_IMM(-iptr->sx.val.i)) {
822 M_ISUB_IMM(iptr->sx.val.i, d);
824 ICONST(REG_ITMP2, iptr->sx.val.i);
825 M_ISUB(REG_ITMP2, d);
827 emit_store_dst(jd, iptr, d);
831 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
833 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
835 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
836 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
837 dd = GET_HIGH_REG(d);
840 M_INTMOVE(s2, REG_ITMP3);
847 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
848 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
852 M_INTMOVE(s2, REG_ITMP3);
859 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
860 N_AHI(GET_HIGH_REG(d), -1);
862 emit_store_dst(jd, iptr, d);
865 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
866 /* sx.val.l = constant */
868 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
870 dd = GET_HIGH_REG(d);
871 s1 = emit_load_s1_high(jd, iptr, dd);
872 s3 = iptr->sx.val.l >> 32;
876 if (N_VALID_IMM(-s3)) {
879 ICONST(REG_ITMP3, s3);
880 M_ISUB(REG_ITMP3, dd);
884 s1 = emit_load_s1_low(jd, iptr, dd);
885 s3 = iptr->sx.val.l & 0xffffffff;
886 ICONST(REG_ITMP3, s3);
889 N_SLR(dd, REG_ITMP3);
891 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
892 N_AHI(GET_HIGH_REG(d), -1);
894 emit_store_dst(jd, iptr, d);
897 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
899 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
900 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
901 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
908 emit_store_dst(jd, iptr, d);
912 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
913 /* sx.val.i = constant */
914 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
915 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
917 if (iptr->sx.val.i == 2) {
919 } else if (N_VALID_IMM(iptr->sx.val.i)) {
920 M_IMUL_IMM(iptr->sx.val.i, d);
922 disp = dseg_add_s4(cd, iptr->sx.val.i);
923 M_ILD_DSEG(REG_ITMP2, disp);
924 M_IMUL(REG_ITMP2, d);
926 emit_store_dst(jd, iptr, d);
929 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
930 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
932 /* load s1 into r0 */
934 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
935 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
936 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
938 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
940 /* extend s1 to long */
942 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
946 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
952 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
953 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
956 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
957 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
961 emit_store_dst(jd, iptr, d);
965 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
966 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
968 bte = iptr->sx.s23.s3.bte;
971 /* test s2 for zero */
973 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
974 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
975 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
976 emit_arithmetic_check(cd, iptr, REG_ITMP3);
980 disp = dseg_add_functionptr(cd, bte->fp);
984 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
986 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
987 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
991 M_ASUB_IMM(96, REG_SP);
992 M_ALD_DSEG(REG_ITMP2, disp);
993 M_JSR(REG_RA, REG_ITMP2);
994 M_AADD_IMM(96, REG_SP);
998 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
999 M_LNGMOVE(REG_RESULT_PACKED, d);
1000 emit_store_dst(jd, iptr, d);
1004 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1005 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1006 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1008 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1009 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1010 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1012 /* Use only 5 bits of sencond operand. */
1014 M_INTMOVE(s2, REG_ITMP2);
1016 ICONST(REG_ITMP3, 0x1F);
1017 M_IAND(REG_ITMP3, s2);
1021 switch (iptr->opc) {
1034 emit_store_dst(jd, iptr, d);
1037 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1038 /* sx.val.i = constant */
1042 assert(iptr->sx.val.i <= 32);
1044 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1045 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1052 s3 = (1 << iptr->sx.val.i) - 1;
1054 if (N_VALID_IMM(s3)) {
1057 ICONST(REG_ITMP1, -1);
1058 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1059 M_IADD(REG_ITMP1, d);
1062 N_BRC_BACK_PATCH(ref);
1064 M_SRA_IMM(iptr->sx.val.i, d);
1066 emit_store_dst(jd, iptr, d);
1071 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1072 /* sx.val.i = constant */
1074 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1075 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1078 M_MOV(s1, REG_ITMP1);
1082 ICONST(REG_ITMP3, iptr->sx.val.i);
1085 M_IAND(REG_ITMP3, d);
1088 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1094 emit_store_dst(jd, iptr, d);
1098 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1099 /* sx.val.i = constant */
1100 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1101 /* sx.val.i = constant */
1102 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1103 /* sx.val.i = constant */
1104 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1105 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1109 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1111 switch (iptr->opc) {
1112 case ICMD_ISHLCONST:
1115 case ICMD_ISHRCONST:
1118 case ICMD_IUSHRCONST:
1125 emit_store_dst(jd, iptr, d);
1128 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1130 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1132 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1134 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1136 /* Use only 6 bits of second operand */
1138 M_INTMOVE(s2, REG_ITMP2);
1140 ICONST(REG_ITMP1, 0x3F);
1141 M_IAND(REG_ITMP1, s2);
1143 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1144 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1146 /* Destination must be even-odd pair */
1148 if (! N_IS_EVEN_ODD(d)) {
1149 d = REG_ITMP31_PACKED;
1152 assert(N_IS_EVEN_ODD(d));
1156 switch (iptr->opc) {
1158 M_SLDL(s2, GET_HIGH_REG(d));
1161 M_SRDA(s2, GET_HIGH_REG(d));
1164 M_SRDL(s2, GET_HIGH_REG(d));
1170 emit_copy_dst(jd, iptr, d);
1171 emit_store_dst(jd, iptr, d);
1175 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1176 /* sx.val.i = constant */
1177 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1178 /* sx.val.i = constant */
1179 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1180 /* sx.val.l = constant */
1183 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1184 if (! N_IS_EVEN_ODD(d)) {
1185 d = REG_ITMP31_PACKED;
1187 assert(N_IS_EVEN_ODD(d));
1189 s1 = emit_load_s1(jd, iptr, d);
1193 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1195 switch (iptr->opc) {
1196 case ICMD_LSHLCONST:
1197 N_SLDL(GET_HIGH_REG(d), disp, RN);
1199 case ICMD_LSHRCONST:
1200 N_SRDA(GET_HIGH_REG(d), disp, RN);
1202 case ICMD_LUSHRCONST:
1203 N_SRDL(GET_HIGH_REG(d), disp, RN);
1206 N_SLDL(GET_HIGH_REG(d), disp, RN);
1212 emit_copy_dst(jd, iptr, d);
1213 emit_store_dst(jd, iptr, d);
1216 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1218 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1219 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1220 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1227 emit_store_dst(jd, iptr, d);
1231 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1233 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1234 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1235 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1242 emit_store_dst(jd, iptr, d);
1246 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1248 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1249 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1250 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1257 emit_store_dst(jd, iptr, d);
1263 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1264 /* sx.val.i = constant */
1265 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1266 /* sx.val.i = constant */
1267 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1268 /* sx.val.i = constant */
1270 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1271 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1274 ICONST(REG_ITMP2, iptr->sx.val.i);
1276 switch (iptr->opc) {
1277 case ICMD_IANDCONST:
1278 M_IAND(REG_ITMP2, d);
1280 case ICMD_IXORCONST:
1281 M_IXOR(REG_ITMP2, d);
1284 M_IOR(REG_ITMP2, d);
1290 emit_store_dst(jd, iptr, d);
1294 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1295 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1296 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1298 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1300 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1301 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1302 dd = GET_LOW_REG(d);
1304 switch (iptr->opc) {
1333 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1334 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1335 dd = GET_HIGH_REG(d);
1337 switch (iptr->opc) {
1366 emit_store_dst(jd, iptr, d);
1369 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1370 /* sx.val.l = constant */
1371 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1372 /* sx.val.l = constant */
1373 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1374 /* sx.val.l = constant */
1376 /* TODO should use memory operand to access data segment, not load */
1378 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1380 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1381 s3 = iptr->sx.val.l & 0xffffffff;
1383 M_INTMOVE(s1, GET_LOW_REG(d));
1385 ICONST(REG_ITMP3, s3);
1387 switch (iptr->opc) {
1388 case ICMD_LANDCONST:
1389 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1391 case ICMD_LXORCONST:
1392 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1395 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1401 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1402 s3 = iptr->sx.val.l >> 32;
1404 M_INTMOVE(s1, GET_HIGH_REG(d));
1406 ICONST(REG_ITMP3, s3);
1408 switch (iptr->opc) {
1409 case ICMD_LANDCONST:
1410 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1412 case ICMD_LXORCONST:
1413 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1416 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1422 emit_store_dst(jd, iptr, d);
1426 /* floating operations ************************************************/
1428 case ICMD_FNEG: /* ..., value ==> ..., - value */
1429 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1430 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1432 emit_store_dst(jd, iptr, d);
1435 case ICMD_DNEG: /* ..., value ==> ..., - value */
1436 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1437 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1439 emit_store_dst(jd, iptr, d);
1442 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1443 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1444 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1445 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1452 emit_store_dst(jd, iptr, d);
1455 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1456 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1457 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1458 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1465 emit_store_dst(jd, iptr, d);
1468 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1469 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1470 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1471 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1475 emit_store_dst(jd, iptr, d);
1478 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1479 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1480 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1481 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1485 emit_store_dst(jd, iptr, d);
1488 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1489 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1490 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1491 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1498 emit_store_dst(jd, iptr, d);
1501 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1502 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1503 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1504 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1511 emit_store_dst(jd, iptr, d);
1514 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1515 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1516 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1517 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1521 emit_store_dst(jd, iptr, d);
1524 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1525 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1526 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1527 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1531 emit_store_dst(jd, iptr, d);
1534 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1535 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1536 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1538 emit_store_dst(jd, iptr, d);
1541 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1542 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1543 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1545 emit_store_dst(jd, iptr, d);
1548 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1552 #ifdef SUPPORT_HERCULES
1556 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1557 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1561 switch (iptr->opc) {
1570 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1571 N_LHI(d, 0); /* Load 0 */
1572 ref1 = cd->mcodeptr;
1573 N_BRC(DD_ANY, 0); /* Exit */
1577 switch (iptr->opc) {
1586 #ifdef SUPPORT_HERCULES
1587 /* Hercules does the conversion using a plain C conversion.
1588 * According to manual, real hardware should *NOT* require this.
1590 * Corner case: Positive float leads to INT_MIN (overflow).
1593 switch (iptr->opc) {
1602 ref2 = cd->mcodeptr;
1603 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1607 ref3 = cd->mcodeptr;
1608 M_BGE(0); /* If integer result is negative, continue */
1610 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1611 M_ILD_DSEG(d, disp);
1613 N_BRC_BACK_PATCH(ref1);
1614 #ifdef SUPPORT_HERCULES
1615 N_BRC_BACK_PATCH(ref2);
1616 N_BRC_BACK_PATCH(ref3);
1618 emit_store_dst(jd, iptr, d);
1622 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1624 #ifdef SUPPORT_HERCULES
1627 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1628 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1629 #ifdef SUPPORT_HERCULES
1632 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1633 disp = dseg_add_double(cd, 0.0 / 0.0);
1634 M_DLD_DSEG(d, disp, REG_ITMP1);
1635 emit_label_br(cd, BRANCH_LABEL_1);
1636 N_BRC_BACK_PATCH(ref);
1639 #ifdef SUPPORT_HERCULES
1640 emit_label(cd, BRANCH_LABEL_1);
1642 emit_store_dst(jd, iptr, d);
1646 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1647 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1648 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1650 emit_store_dst(jd, iptr, d);
1653 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1654 /* == => 0, < => 1, > => -1 */
1658 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1659 /* == => 0, < => 1, > => -1 */
1662 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1663 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1664 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1666 switch (iptr->opc) {
1678 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1679 SZ_BRC + SZ_BRC + SZ_BRC
1682 N_BRC( /* load -1 */
1683 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1684 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1689 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1692 N_LHI(d, 1); /* GT */
1693 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1694 N_LHI(d, -1); /* LT */
1695 M_BR(SZ_BRC + SZ_LHI);
1696 N_LHI(d, 0); /* EQ */
1698 emit_store_dst(jd, iptr, d);
1703 /* memory operations **************************************************/
1705 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1707 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1708 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1710 /* implicit null-pointer check */
1711 M_ILD(d, s1, OFFSET(java_array_t, size));
1712 emit_store_dst(jd, iptr, d);
1716 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1717 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1718 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1719 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1721 /* implicit null-pointer check */
1722 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1724 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1729 emit_store_dst(jd, iptr, d);
1732 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1734 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1735 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1736 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1738 /* implicit null-pointer check */
1739 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1741 M_INTMOVE(s2, REG_ITMP2);
1742 M_SLL_IMM(1, REG_ITMP2);
1744 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1746 /* N_LH does sign extends, undo ! */
1751 emit_store_dst(jd, iptr, d);
1754 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1755 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1756 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1757 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1759 /* implicit null-pointer check */
1760 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1762 M_INTMOVE(s2, REG_ITMP2);
1763 M_SLL_IMM(1, REG_ITMP2);
1765 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1766 emit_store_dst(jd, iptr, d);
1769 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1770 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1771 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1772 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1774 /* implicit null-pointer check */
1775 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1777 M_INTMOVE(s2, REG_ITMP2);
1778 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1779 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1780 emit_store_dst(jd, iptr, d);
1783 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1785 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1786 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1788 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1790 /* implicit null-pointer check */
1791 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1793 M_INTMOVE(s2, REG_ITMP2);
1794 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1797 GET_LOW_REG(d) /* maybe itmp3 */,
1798 OFFSET(java_longarray_t, data[0]) + 4,
1799 REG_ITMP2, s1 /* maybe itmp1 */
1803 GET_HIGH_REG(d) /* maybe itmp1 */,
1804 OFFSET(java_longarray_t, data[0]),
1805 REG_ITMP2, s1 /* maybe itmp1 */
1808 emit_store_dst(jd, iptr, d);
1812 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1814 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1815 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1816 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1818 /* implicit null-pointer check */
1819 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1821 M_INTMOVE(s2, REG_ITMP2);
1822 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1824 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1826 emit_store_dst(jd, iptr, d);
1829 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1830 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1831 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1832 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1834 /* implicit null-pointer check */
1835 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1837 M_INTMOVE(s2, REG_ITMP2);
1838 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1840 N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1842 emit_store_dst(jd, iptr, d);
1845 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1846 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1847 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1848 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1850 /* implicit null-pointer check */
1851 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1853 M_INTMOVE(s2, REG_ITMP2);
1854 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1855 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1856 emit_store_dst(jd, iptr, d);
1859 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1860 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1861 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1862 /* implicit null-pointer check */
1863 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1864 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1866 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1869 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1871 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1872 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1873 /* implicit null-pointer check */
1874 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1875 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1877 M_INTMOVE(s2, REG_ITMP2);
1878 M_SLL_IMM(1, REG_ITMP2);
1880 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1884 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1885 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1886 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1887 /* implicit null-pointer check */
1888 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1889 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1891 M_INTMOVE(s2, REG_ITMP2);
1892 M_SLL_IMM(1, REG_ITMP2);
1894 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1897 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1899 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1900 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1901 /* implicit null-pointer check */
1902 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1904 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1906 M_INTMOVE(s2, REG_ITMP2);
1907 M_SLL_IMM(2, REG_ITMP2);
1909 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1912 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1914 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1915 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1916 /* implicit null-pointer check */
1917 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1919 M_INTMOVE(s2, REG_ITMP2);
1920 M_SLL_IMM(3, REG_ITMP2);
1922 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1923 N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1);
1924 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1925 N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1);
1928 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1929 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1930 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1931 /* implicit null-pointer check */
1932 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1933 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1935 M_INTMOVE(s2, REG_ITMP2);
1936 M_SLL_IMM(2, REG_ITMP2);
1938 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1941 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1942 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1943 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1944 /* implicit null-pointer check */
1945 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1946 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1948 M_INTMOVE(s2, REG_ITMP2);
1949 M_SLL_IMM(3, REG_ITMP2);
1951 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1954 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1956 s1 = emit_load_s1(jd, iptr, REG_A0);
1957 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1958 /* implicit null-pointer check */
1959 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1960 s3 = emit_load_s3(jd, iptr, REG_A1);
1962 M_INTMOVE(s1, REG_A0);
1963 M_INTMOVE(s3, REG_A1);
1965 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1966 M_ALD_DSEG(REG_ITMP2, disp);
1967 M_ASUB_IMM(96, REG_SP);
1968 M_JSR(REG_RA, REG_ITMP2);
1969 M_AADD_IMM(96, REG_SP);
1971 emit_arraystore_check(cd, iptr);
1973 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1974 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1975 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1977 M_INTMOVE(s2, REG_ITMP2);
1978 M_SLL_IMM(2, REG_ITMP2);
1979 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1982 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1983 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1988 case ICMD_GETSTATIC: /* ... ==> ..., value */
1990 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1991 uf = iptr->sx.s23.s3.uf;
1992 fieldtype = uf->fieldref->parseddesc.fd->type;
1993 disp = dseg_add_unique_address(cd, NULL);
1995 /* PROFILE_CYCLE_STOP; */
1997 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1999 /* PROFILE_CYCLE_START; */
2002 fi = iptr->sx.s23.s3.fmiref->p.field;
2003 fieldtype = fi->type;
2004 disp = dseg_add_address(cd, fi->value);
2006 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
2009 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
2011 PROFILE_CYCLE_START;
2015 M_ALD_DSEG(REG_ITMP1, disp);
2017 switch (fieldtype) {
2019 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2020 M_ILD(d, REG_ITMP1, 0);
2023 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2024 M_LLD(d, REG_ITMP1, 0);
2027 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2028 M_ALD(d, REG_ITMP1, 0);
2031 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2032 M_FLD(d, REG_ITMP1, 0);
2035 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2036 M_DLD(d, REG_ITMP1, 0);
2040 emit_store_dst(jd, iptr, d);
2044 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2046 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2047 uf = iptr->sx.s23.s3.uf;
2048 fieldtype = uf->fieldref->parseddesc.fd->type;
2049 disp = dseg_add_unique_address(cd, uf);
2051 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2054 fi = iptr->sx.s23.s3.fmiref->p.field;
2055 fieldtype = fi->type;
2056 disp = dseg_add_address(cd, fi->value);
2058 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
2060 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
2061 PROFILE_CYCLE_START;
2065 M_ALD_DSEG(REG_ITMP1, disp);
2066 switch (fieldtype) {
2068 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2069 M_IST(s1, REG_ITMP1, 0);
2072 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2073 M_LST(s1, REG_ITMP1, 0);
2076 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2077 M_AST(s1, REG_ITMP1, 0);
2080 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2081 M_FST(s1, REG_ITMP1, 0);
2084 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2085 M_DST(s1, REG_ITMP1, 0);
2090 case ICMD_GETFIELD: /* ... ==> ..., value */
2092 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2093 emit_nullpointer_check(cd, iptr, s1);
2095 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2096 uf = iptr->sx.s23.s3.uf;
2097 fieldtype = uf->fieldref->parseddesc.fd->type;
2100 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2103 fi = iptr->sx.s23.s3.fmiref->p.field;
2104 fieldtype = fi->type;
2108 switch (fieldtype) {
2110 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2114 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2115 if (GET_HIGH_REG(d) == s1) {
2116 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2117 M_ILD(GET_HIGH_REG(d), s1, disp);
2120 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2121 M_ILD(GET_HIGH_REG(d), s1, disp);
2125 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2129 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2133 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2137 emit_store_dst(jd, iptr, d);
2140 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2144 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2145 emit_nullpointer_check(cd, iptr, s1);
2147 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2148 uf = iptr->sx.s23.s3.uf;
2149 fieldtype = uf->fieldref->parseddesc.fd->type;
2153 fi = iptr->sx.s23.s3.fmiref->p.field;
2154 fieldtype = fi->type;
2158 /* We can't add a patcher ref behind this load,
2159 * because the patcher would destroy REG_ITMP3.
2161 * We pass in the disp parameter, how many bytes
2162 * to skip to the to the actual store.
2164 * XXX this relies on patcher_add_patch_ref internals
2167 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2168 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2173 if (IS_INT_LNG_TYPE(fieldtype)) {
2174 if (IS_2_WORD_TYPE(fieldtype))
2175 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2177 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2179 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2182 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2183 ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2186 switch (fieldtype) {
2188 M_IST(s2, s1, disp);
2191 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2192 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2195 M_AST(s2, s1, disp);
2198 M_FST(s2, s1, disp);
2201 M_DST(s2, s1, disp);
2208 /* branch operations **************************************************/
2210 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2212 /* PROFILE_CYCLE_STOP; */
2214 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2215 M_INTMOVE(s1, REG_ITMP3_XPTR);
2217 #ifdef ENABLE_VERIFIER
2218 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2219 uc = iptr->sx.s23.s2.uc;
2221 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2223 #endif /* ENABLE_VERIFIER */
2225 disp = dseg_add_functionptr(cd, asm_handle_exception);
2226 M_ALD_DSEG(REG_ITMP1, disp);
2227 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2232 case ICMD_GOTO: /* ... ==> ... */
2233 case ICMD_RET: /* ... ==> ... */
2235 emit_br(cd, iptr->dst.block);
2239 case ICMD_JSR: /* ... ==> ... */
2241 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2245 case ICMD_IFNULL: /* ..., value ==> ... */
2246 case ICMD_IFNONNULL: /* ..., value ==> ... */
2247 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2249 switch (iptr->opc) {
2251 emit_beq(cd, iptr->dst.block);
2253 case ICMD_IFNONNULL:
2254 emit_bne(cd, iptr->dst.block);
2259 case ICMD_IFEQ: /* ..., value ==> ... */
2260 case ICMD_IFLT: /* ..., value ==> ... */
2261 case ICMD_IFLE: /* ..., value ==> ... */
2262 case ICMD_IFNE: /* ..., value ==> ... */
2263 case ICMD_IFGT: /* ..., value ==> ... */
2264 case ICMD_IFGE: /* ..., value ==> ... */
2266 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2268 if (N_VALID_IMM(iptr->sx.val.i))
2269 M_ICMP_IMM(s1, iptr->sx.val.i);
2271 disp = dseg_add_s4(cd, iptr->sx.val.i);
2272 if (N_VALID_DSEG_DISP(disp)) {
2273 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2275 ICONST(REG_ITMP2, disp);
2276 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2280 switch (iptr->opc) {
2282 emit_blt(cd, iptr->dst.block);
2285 emit_ble(cd, iptr->dst.block);
2288 emit_bne(cd, iptr->dst.block);
2291 emit_bgt(cd, iptr->dst.block);
2294 emit_bge(cd, iptr->dst.block);
2297 emit_beq(cd, iptr->dst.block);
2303 case ICMD_IF_LLT: /* ..., value ==> ... */
2304 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2310 /* ATTENTION: compare high words signed and low words unsigned */
2312 # define LABEL_OUT BRANCH_LABEL_1
2314 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2316 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2317 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2319 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2320 if (N_VALID_DSEG_DISP(disp)) {
2321 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2323 ICONST(REG_ITMP2, disp);
2324 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2331 emit_blt(cd, iptr->dst.block);
2332 /* EQ ... fall through */
2333 emit_label_bgt(cd, LABEL_OUT);
2337 emit_bgt(cd, iptr->dst.block);
2338 /* EQ ... fall through */
2339 emit_label_blt(cd, LABEL_OUT);
2342 /* EQ ... fall through */
2343 emit_label_bne(cd, LABEL_OUT);
2346 /* EQ ... fall through */
2347 emit_bne(cd, iptr->dst.block);
2353 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2355 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2356 if (N_VALID_DSEG_DISP(disp)) {
2357 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2359 ICONST(REG_ITMP2, disp);
2360 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2365 emit_blt(cd, iptr->dst.block);
2366 emit_label(cd, LABEL_OUT);
2369 emit_ble(cd, iptr->dst.block);
2370 emit_label(cd, LABEL_OUT);
2373 emit_bgt(cd, iptr->dst.block);
2374 emit_label(cd, LABEL_OUT);
2377 emit_bge(cd, iptr->dst.block);
2378 emit_label(cd, LABEL_OUT);
2381 emit_beq(cd, iptr->dst.block);
2382 emit_label(cd, LABEL_OUT);
2385 emit_bne(cd, iptr->dst.block);
2394 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2395 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2397 /* Compare addresses as 31 bit unsigned integers */
2399 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2400 M_LDA(REG_ITMP1, s1, 0);
2402 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2403 M_LDA(REG_ITMP2, s2, 0);
2405 M_CMP(REG_ITMP1, REG_ITMP2);
2407 switch (iptr->opc) {
2408 case ICMD_IF_ACMPEQ:
2409 emit_beq(cd, iptr->dst.block);
2411 case ICMD_IF_ACMPNE:
2412 emit_bne(cd, iptr->dst.block);
2418 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2419 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2420 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2421 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2422 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2423 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2425 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2426 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2428 switch (iptr->opc) {
2429 case ICMD_IF_ICMPEQ:
2430 emit_beq(cd, iptr->dst.block);
2432 case ICMD_IF_ICMPNE:
2433 emit_bne(cd, iptr->dst.block);
2435 case ICMD_IF_ICMPLT:
2436 emit_blt(cd, iptr->dst.block);
2438 case ICMD_IF_ICMPGT:
2439 emit_bgt(cd, iptr->dst.block);
2441 case ICMD_IF_ICMPLE:
2442 emit_ble(cd, iptr->dst.block);
2444 case ICMD_IF_ICMPGE:
2445 emit_bge(cd, iptr->dst.block);
2451 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2452 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2453 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2454 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2455 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2456 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2461 /* ATTENTION: compare high words signed and low words unsigned */
2463 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2464 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2469 case ICMD_IF_LCMPLT:
2470 case ICMD_IF_LCMPLE:
2471 emit_blt(cd, iptr->dst.block);
2472 /* EQ ... fall through */
2473 out_ref = cd->mcodeptr;
2476 case ICMD_IF_LCMPGT:
2477 case ICMD_IF_LCMPGE:
2478 emit_bgt(cd, iptr->dst.block);
2479 /* EQ ... fall through */
2480 out_ref = cd->mcodeptr;
2483 case ICMD_IF_LCMPEQ:
2484 /* EQ ... fall through */
2485 out_ref = cd->mcodeptr;
2488 case ICMD_IF_LCMPNE:
2489 /* EQ ... fall through */
2490 emit_bne(cd, iptr->dst.block);
2496 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2497 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2502 case ICMD_IF_LCMPLT:
2503 emit_blt(cd, iptr->dst.block);
2505 case ICMD_IF_LCMPLE:
2506 emit_ble(cd, iptr->dst.block);
2508 case ICMD_IF_LCMPGT:
2509 emit_bgt(cd, iptr->dst.block);
2511 case ICMD_IF_LCMPGE:
2512 emit_bge(cd, iptr->dst.block);
2514 case ICMD_IF_LCMPEQ:
2515 emit_beq(cd, iptr->dst.block);
2517 case ICMD_IF_LCMPNE:
2518 emit_bne(cd, iptr->dst.block);
2524 if (out_ref != NULL) {
2525 N_BRC_BACK_PATCH(out_ref);
2531 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2533 REPLACEMENT_POINT_RETURN(cd, iptr);
2534 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2535 M_INTMOVE(s1, REG_RESULT);
2536 goto nowperformreturn;
2538 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2540 REPLACEMENT_POINT_RETURN(cd, iptr);
2541 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2542 M_INTMOVE(s1, REG_RESULT);
2544 #ifdef ENABLE_VERIFIER
2545 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2546 unresolved_class *uc = iptr->sx.s23.s2.uc;
2549 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2550 PROFILE_CYCLE_START;
2552 #endif /* ENABLE_VERIFIER */
2553 goto nowperformreturn;
2555 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2557 REPLACEMENT_POINT_RETURN(cd, iptr);
2558 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2559 M_LNGMOVE(s1, REG_RESULT_PACKED);
2560 goto nowperformreturn;
2562 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2565 REPLACEMENT_POINT_RETURN(cd, iptr);
2566 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2567 M_FLTMOVE(s1, REG_FRESULT);
2568 goto nowperformreturn;
2570 case ICMD_RETURN: /* ... ==> ... */
2572 REPLACEMENT_POINT_RETURN(cd, iptr);
2578 p = cd->stackframesize;
2580 /* call trace function */
2582 #if !defined(NDEBUG)
2583 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2584 emit_verbosecall_exit(jd);
2585 #endif /* !defined(NDEBUG) */
2587 #if defined(ENABLE_THREADS)
2588 if (checksync && code_is_synchronized(code)) {
2589 /* we need to save the proper return value */
2591 switch (iptr->opc) {
2593 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2597 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2600 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2603 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2607 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2609 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2610 M_ALD_DSEG(REG_ITMP2, disp);
2612 M_ASUB_IMM(96, REG_SP);
2614 M_AADD_IMM(96, REG_SP);
2616 /* and now restore the proper return value */
2618 switch (iptr->opc) {
2620 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2624 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2627 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2630 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2636 /* restore return address */
2638 p--; M_ALD(REG_RA, REG_SP, p * 8);
2640 /* restore saved registers */
2642 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2643 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2645 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2646 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2649 /* deallocate stack */
2651 if (cd->stackframesize)
2652 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2654 /* generate method profiling code */
2662 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2665 branch_target_t *table;
2667 table = iptr->dst.table;
2669 l = iptr->sx.s23.s2.tablelow;
2670 i = iptr->sx.s23.s3.tablehigh;
2672 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2673 M_INTMOVE(s1, REG_ITMP1);
2677 } else if (N_VALID_IMM(-l)) {
2678 M_ISUB_IMM(l, REG_ITMP1);
2680 ICONST(REG_ITMP2, l);
2681 M_ISUB(REG_ITMP2, REG_ITMP1);
2684 /* number of targets */
2690 ICONST(REG_ITMP2, i);
2691 M_ICMPU(REG_ITMP1, REG_ITMP2);
2692 emit_bge(cd, table[0].block);
2694 /* build jump table top down and use address of lowest entry */
2699 dseg_add_target(cd, table->block);
2704 /* length of dataseg after last dseg_add_target is used by load */
2706 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2707 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2708 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2709 M_JMP(RN, REG_ITMP1);
2714 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2717 lookup_target_t *lookup;
2719 lookup = iptr->dst.lookup;
2721 i = iptr->sx.s23.s2.lookupcount;
2723 MCODECHECK(8 + ((7 + 6) * i) + 5);
2724 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2727 if (N_VALID_IMM(lookup->value)) {
2728 M_ICMP_IMM(s1, lookup->value);
2730 ICONST(REG_ITMP2, lookup->value);
2731 M_ICMP(REG_ITMP2, s1);
2733 emit_beq(cd, lookup->target.block);
2737 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2742 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2744 bte = iptr->sx.s23.s3.bte;
2748 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2749 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2750 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2751 case ICMD_INVOKEINTERFACE:
2753 REPLACEMENT_POINT_INVOKE(cd, iptr);
2755 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2757 um = iptr->sx.s23.s3.um;
2758 md = um->methodref->parseddesc.md;
2761 lm = iptr->sx.s23.s3.fmiref->p.method;
2763 md = lm->parseddesc;
2767 s3 = md->paramcount;
2769 MCODECHECK((s3 << 1) + 64);
2771 /* copy arguments to registers or stack location */
2773 for (s3 = s3 - 1; s3 >= 0; s3--) {
2774 var = VAR(iptr->sx.s23.s2.args[s3]);
2776 /* Already Preallocated? */
2777 if (var->flags & PREALLOC)
2780 if (IS_INT_LNG_TYPE(var->type)) {
2781 if (!md->params[s3].inmemory) {
2782 if (IS_2_WORD_TYPE(var->type)) {
2784 GET_LOW_REG(md->params[s3].regoff),
2785 GET_HIGH_REG(md->params[s3].regoff)
2787 d = emit_load(jd, iptr, var, s1);
2791 s1 = md->params[s3].regoff;
2792 d = emit_load(jd, iptr, var, s1);
2797 if (IS_2_WORD_TYPE(var->type)) {
2798 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2799 M_LST(d, REG_SP, md->params[s3].regoff);
2802 d = emit_load(jd, iptr, var, REG_ITMP1);
2803 M_IST(d, REG_SP, md->params[s3].regoff);
2808 if (!md->params[s3].inmemory) {
2809 s1 = md->params[s3].regoff;
2810 d = emit_load(jd, iptr, var, s1);
2814 d = emit_load(jd, iptr, var, REG_FTMP1);
2815 if (IS_2_WORD_TYPE(var->type))
2816 M_DST(d, REG_SP, md->params[s3].regoff);
2818 M_FST(d, REG_SP, md->params[s3].regoff);
2823 /* generate method profiling code */
2827 switch (iptr->opc) {
2829 if (bte->stub == NULL) {
2830 disp = dseg_add_functionptr(cd, bte->fp);
2831 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2833 disp = dseg_add_functionptr(cd, bte->stub);
2836 if (N_VALID_DSEG_DISP(disp)) {
2837 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2839 N_LHI(REG_ITMP1, disp);
2840 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2844 case ICMD_INVOKESPECIAL:
2846 /* Implicit NULL pointer check */
2847 M_ILD(REG_ITMP1, REG_A0, 0);
2851 case ICMD_INVOKESTATIC:
2853 disp = dseg_add_unique_address(cd, um);
2855 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2859 disp = dseg_add_address(cd, lm->stubroutine);
2861 if (N_VALID_DSEG_DISP(disp)) {
2862 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2864 N_LHI(REG_ITMP1, disp);
2865 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2869 case ICMD_INVOKEVIRTUAL:
2870 /* TODO softnull REG_A0 */
2873 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2878 s1 = OFFSET(vftbl_t, table[0]) +
2879 sizeof(methodptr) * lm->vftblindex;
2882 /* implicit null-pointer check */
2884 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2885 M_ALD(REG_PV, REG_METHODPTR, s1);
2888 case ICMD_INVOKEINTERFACE:
2889 /* TODO softnull REG_A0 */
2891 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2892 * and -0xFFF in index register (itmp1)
2896 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2902 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2903 sizeof(methodptr*) * lm->clazz->index;
2905 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2908 /* Implicit null-pointer check */
2909 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2910 N_LHI(REG_ITMP2, s1);
2911 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2912 M_ALD(REG_PV, REG_METHODPTR, s2);
2916 /* generate the actual call */
2919 emit_restore_pv(cd);
2921 /* post call finalization */
2923 switch (iptr->opc) {
2925 if (bte->stub == NULL) {
2926 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2931 /* generate method profiling code */
2933 PROFILE_CYCLE_START;
2935 /* store size of call code in replacement point */
2937 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2939 /* store return value */
2941 d = md->returntype.type;
2943 if (d != TYPE_VOID) {
2944 if (IS_INT_LNG_TYPE(d)) {
2945 if (IS_2_WORD_TYPE(d)) {
2946 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2947 M_LNGMOVE(REG_RESULT_PACKED, s1);
2950 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2951 M_INTMOVE(REG_RESULT, s1);
2955 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2956 M_FLTMOVE(REG_FRESULT, s1);
2958 emit_store_dst(jd, iptr, s1);
2964 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2966 /* val.a: (classinfo*) superclass */
2968 /* superclass is an interface:
2970 * OK if ((sub == NULL) ||
2971 * (sub->vftbl->interfacetablelength > super->index) &&
2972 * (sub->vftbl->interfacetable[-super->index] != NULL));
2974 * superclass is a class:
2976 * OK if ((sub == NULL) || (0
2977 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2978 * super->vftbl->diffval));
2981 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2982 /* object type cast-check */
2985 vftbl_t *supervftbl;
2988 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2989 # define LABEL_CLASS BRANCH_LABEL_2
2990 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2991 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2992 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2994 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3000 super = iptr->sx.s23.s3.c.cls;
3001 superindex = super->index;
3002 supervftbl = super->vftbl;
3005 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3007 /* if class is not resolved, check which code to call */
3009 if (super == NULL) {
3011 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3013 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3015 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3016 iptr->sx.s23.s3.c.ref,
3019 ICONST(REG_ITMP3, ACC_INTERFACE);
3021 if (N_VALID_DSEG_DISP(disp)) {
3022 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3024 ICONST(REG_ITMP2, disp);
3025 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3027 emit_label_beq(cd, LABEL_CLASS);
3030 /* interface checkcast code */
3032 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3033 if (super == NULL) {
3034 patcher_add_patch_ref(jd,
3035 PATCHER_checkcast_instanceof_interface,
3036 iptr->sx.s23.s3.c.ref,
3040 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3043 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3044 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3045 M_ISUB_IMM(superindex, REG_ITMP3);
3046 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3049 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3050 superindex * sizeof(methodptr*))
3052 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3053 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3055 if (super == NULL) {
3056 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3060 /* class checkcast code */
3062 if (super == NULL) {
3063 emit_label(cd, LABEL_CLASS);
3066 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3067 if (super == NULL) {
3068 disp = dseg_add_unique_address(cd, NULL);
3070 patcher_add_patch_ref(jd,
3071 PATCHER_resolve_classref_to_vftbl,
3072 iptr->sx.s23.s3.c.ref,
3076 disp = dseg_add_address(cd, supervftbl);
3078 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3082 /* REG_ITMP3 := baseval(s1) */
3083 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3084 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3086 /* REG_ITMP2 := baseval(class) */
3087 M_ALD_DSEG(REG_ITMP2, disp);
3088 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3090 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3091 M_ISUB(REG_ITMP2, REG_ITMP3);
3093 /* REG_ITMP2 := diffval(class) */
3094 M_ALD_DSEG(REG_ITMP2, disp);
3095 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3097 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3099 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3100 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3101 /* Branch if greater then */
3103 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3104 M_ALD_DSEG(REG_ITMP3, disp);
3106 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3107 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3108 M_ISUB(REG_ITMP3, REG_ITMP2);
3109 M_ALD_DSEG(REG_ITMP3, disp);
3110 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3112 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3113 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3114 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3115 /* Branch if greater then */
3117 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3120 if (super == NULL) {
3121 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3122 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3123 } else if (super->flags & ACC_INTERFACE) {
3124 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3126 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3129 d = codegen_reg_of_dst(jd, iptr, s1);
3131 # undef LABEL_EXIT_CHECK_NULL
3133 # undef LABEL_EXIT_INTERFACE_NULL
3134 # undef LABEL_EXIT_INTERFACE_DONE
3135 # undef LABEL_EXIT_CLASS_NULL
3138 /* array type cast-check */
3140 s1 = emit_load_s1(jd, iptr, REG_A0);
3141 M_INTMOVE(s1, REG_A0);
3143 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3144 disp = dseg_add_unique_address(cd, NULL);
3146 patcher_add_patch_ref(jd,
3147 PATCHER_resolve_classref_to_classinfo,
3148 iptr->sx.s23.s3.c.ref,
3152 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3154 M_ALD_DSEG(REG_A1, disp);
3155 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3156 M_ALD_DSEG(REG_ITMP1, disp);
3157 M_ASUB_IMM(96, REG_SP);
3158 M_JSR(REG_RA, REG_ITMP1);
3159 M_AADD_IMM(96, REG_SP);
3161 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3162 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3164 d = codegen_reg_of_dst(jd, iptr, s1);
3168 emit_store_dst(jd, iptr, d);
3171 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3172 /* val.a: (classinfo*) superclass */
3174 /* superclass is an interface:
3176 * return (sub != NULL) &&
3177 * (sub->vftbl->interfacetablelength > super->index) &&
3178 * (sub->vftbl->interfacetable[-super->index] != NULL);
3180 * superclass is a class:
3182 * return ((sub != NULL) && (0
3183 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3184 * super->vftbl->diffvall));
3186 * If superclass is unresolved, we include both code snippets
3187 * above, a patcher resolves the class' flags and we select
3188 * the right code at runtime.
3193 vftbl_t *supervftbl;
3196 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3202 super = iptr->sx.s23.s3.c.cls;
3203 superindex = super->index;
3204 supervftbl = super->vftbl;
3207 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3208 # define LABEL_CLASS BRANCH_LABEL_2
3209 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3210 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3211 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3212 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3214 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3215 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3217 M_MOV(s1, REG_ITMP1);
3221 /* if class is not resolved, check which code to call */
3223 if (super == NULL) {
3227 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3229 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3231 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3232 iptr->sx.s23.s3.c.ref, disp);
3234 ICONST(REG_ITMP3, ACC_INTERFACE);
3236 if (N_VALID_DSEG_DISP(disp)) {
3237 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3239 ICONST(REG_ITMP2, disp);
3240 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3243 emit_label_beq(cd, LABEL_CLASS);
3246 /* interface instanceof code */
3248 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3249 if (super == NULL) {
3250 /* If d == REG_ITMP2, then it's destroyed in check
3255 patcher_add_patch_ref(jd,
3256 PATCHER_checkcast_instanceof_interface,
3257 iptr->sx.s23.s3.c.ref, 0);
3262 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3265 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3266 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3267 M_ISUB_IMM(superindex, REG_ITMP3);
3269 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3273 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3274 superindex * sizeof(methodptr*))
3276 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3278 /* d := (REG_ITMP1 != 0) */
3280 N_LTR(d, REG_ITMP1);
3281 M_BEQ(SZ_BRC + SZ_LHI);
3284 if (super == NULL) {
3285 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3289 /* class instanceof code */
3291 if (super == NULL) {
3292 emit_label(cd, LABEL_CLASS);
3295 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3296 if (super == NULL) {
3297 disp = dseg_add_unique_address(cd, NULL);
3299 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3300 iptr->sx.s23.s3.c.ref,
3304 disp = dseg_add_address(cd, supervftbl);
3309 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3312 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3313 M_ALD_DSEG(REG_ITMP2, disp);
3315 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3316 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3317 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3319 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3321 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3323 M_BGT(SZ_BRC + SZ_LHI);
3327 if (super == NULL) {
3328 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3329 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3330 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3331 } else if (super->flags & ACC_INTERFACE) {
3332 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3333 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3335 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3338 # undef LABEL_EXIT_CHECK_NULL
3340 # undef LABEL_EXIT_INTERFACE_NULL
3341 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3342 # undef LABEL_EXIT_INTERFACE_DONE
3343 # undef LABEL_EXIT_CLASS_NULL
3345 emit_store_dst(jd, iptr, d);
3351 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3353 /* check for negative sizes and copy sizes to stack if necessary */
3355 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3358 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3360 /* copy SAVEDVAR sizes to stack */
3361 var = VAR(iptr->sx.s23.s2.args[s1]);
3363 /* Already Preallocated? */
3364 if (!(var->flags & PREALLOC)) {
3365 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3366 M_IST(s2, REG_SP, s1 * 4);
3370 /* is a patcher function set? */
3372 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3373 disp = dseg_add_unique_address(cd, 0);
3375 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3376 iptr->sx.s23.s3.c.ref,
3380 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3382 /* a0 = dimension count */
3384 ICONST(REG_A0, iptr->s1.argcount);
3386 /* a1 = classinfo */
3388 M_ALD_DSEG(REG_A1, disp);
3390 /* a2 = pointer to dimensions = stack pointer */
3392 M_MOV(REG_SP, REG_A2);
3394 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3395 M_ALD_DSEG(REG_ITMP1, disp);
3396 M_ASUB_IMM(96, REG_SP);
3397 M_JSR(REG_RA, REG_ITMP1);
3398 M_AADD_IMM(96, REG_SP);
3400 /* check for exception before result assignment */
3402 emit_exception_check(cd, iptr);
3404 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3405 M_INTMOVE(REG_RESULT, s1);
3406 emit_store_dst(jd, iptr, s1);
3411 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3415 } /* for instruction */
3417 MCODECHECK(512); /* XXX require a lower number? */
3419 /* At the end of a basic block we may have to append some nops,
3420 because the patcher stub calling code might be longer than the
3421 actual instruction. So codepatching does not change the
3422 following block unintentionally. */
3424 if (cd->mcodeptr < cd->lastmcodeptr) {
3425 while (cd->mcodeptr < cd->lastmcodeptr) {
3430 } /* if (bptr -> flags >= BBREACHED) */
3431 } /* for basic block */
3433 /* generate stubs */
3435 emit_patcher_traps(jd);
3437 /* everything's ok */
3442 /* codegen_emit_stub_native ****************************************************
3444 Emits a stub routine which calls a native method.
3446 *******************************************************************************/
3449 arguments on stack \
3450 -------------------------------------------------| <- SP on nativestub entry
3452 callee saved int regs (none) |
3453 callee saved float regs (none) | stack frame like in cacao
3454 local variable slots (none) |
3455 arguments for calling methods (none) /
3456 ------------------------------------------------------------------ <- datasp
3461 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3462 0 - 96 register save area for callee /
3463 -------------------------------------------------------- <- SP native method
3465 SP after method entry
3468 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3479 /* get required compiler data */
3485 /* set some variables */
3489 /* calculate stackframe size */
3491 cd->stackframesize =
3492 1 + /* return address */
3493 sizeof(stackframeinfo_t) / 8 +
3494 sizeof(localref_table) / 8 +
3497 (96 / 8); /* linkage area */
3499 /* keep stack 8-byte aligned */
3501 /*ALIGN_2(cd->stackframesize);*/
3503 /* create method header */
3505 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3506 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3507 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3508 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3509 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3513 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3514 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3516 /* store return address */
3518 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3520 #if defined(ENABLE_GC_CACAO)
3521 /* Save callee saved integer registers in stackframeinfo (GC may
3522 need to recover them during a collection). */
3524 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3525 OFFSET(stackframeinfo_t, intregs);
3527 for (i = 0; i < INT_SAV_CNT; i++)
3528 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3531 /* save integer and float argument registers */
3533 for (i = 0; i < md->paramcount; i++) {
3534 if (!md->params[i].inmemory) {
3535 s1 = md->params[i].regoff;
3537 switch (md->paramtypes[i].type) {
3540 M_IST(s1, REG_SP, 96 + i * 8);
3543 M_LST(s1, REG_SP, 96 + i * 8);
3547 M_DST(s1, REG_SP, 96 + i * 8);
3553 /* create native stack info */
3555 M_MOV(REG_SP, REG_A0);
3556 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3557 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3558 M_ALD_DSEG(REG_ITMP2, disp);
3561 /* remember class argument */
3563 if (m->flags & ACC_STATIC)
3564 M_MOV(REG_RESULT, REG_ITMP3);
3566 /* restore integer and float argument registers */
3568 for (i = 0; i < md->paramcount; i++) {
3569 if (!md->params[i].inmemory) {
3570 s1 = md->params[i].regoff;
3572 switch (md->paramtypes[i].type) {
3575 M_ILD(s1, REG_SP, 96 + i * 8);
3578 M_LLD(s1, REG_SP, 96 + i * 8);
3582 M_DLD(s1, REG_SP, 96 + i * 8);
3588 /* copy or spill arguments to new locations */
3590 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3591 t = md->paramtypes[i].type;
3593 if (IS_INT_LNG_TYPE(t)) {
3594 if (!md->params[i].inmemory) {
3595 s1 = md->params[i].regoff;
3596 s2 = nmd->params[j].regoff;
3598 if (!nmd->params[j].inmemory) {
3599 if (IS_2_WORD_TYPE(t))
3605 if (IS_2_WORD_TYPE(t))
3606 M_LST(s1, REG_SP, s2);
3608 M_IST(s1, REG_SP, s2);
3612 s1 = md->params[i].regoff + cd->stackframesize * 8;
3613 s2 = nmd->params[j].regoff;
3615 if (IS_2_WORD_TYPE(t)) {
3616 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3618 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3623 /* We only copy spilled float arguments, as the float
3624 argument registers keep unchanged. */
3626 if (md->params[i].inmemory) {
3627 s1 = md->params[i].regoff + cd->stackframesize * 8;
3628 s2 = nmd->params[j].regoff;
3630 if (IS_2_WORD_TYPE(t)) {
3631 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3633 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3639 /* Handle native Java methods. */
3641 if (m->flags & ACC_NATIVE) {
3642 /* put class into second argument register */
3644 if (m->flags & ACC_STATIC)
3645 M_MOV(REG_ITMP3, REG_A1);
3647 /* put env into first argument register */
3649 disp = dseg_add_address(cd, VM_get_jnienv());
3650 M_ALD_DSEG(REG_A0, disp);
3653 /* Call native function. */
3655 disp = dseg_add_functionptr(cd, f);
3656 M_ALD_DSEG(REG_ITMP2, disp);
3659 /* save return value */
3661 switch (md->returntype.type) {
3664 M_IST(REG_RESULT, REG_SP, 96);
3667 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3671 M_DST(REG_FRESULT, REG_SP, 96);
3677 /* remove native stackframe info */
3679 M_MOV(REG_SP, REG_A0);
3680 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3681 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3682 M_ALD_DSEG(REG_ITMP1, disp);
3685 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3687 /* restore return value */
3689 switch (md->returntype.type) {
3692 M_ILD(REG_RESULT, REG_SP, 96);
3695 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3699 M_DLD(REG_FRESULT, REG_SP, 96);
3705 #if defined(ENABLE_GC_CACAO)
3706 /* Restore callee saved integer registers from stackframeinfo (GC
3707 might have modified them during a collection). */
3709 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3710 OFFSET(stackframeinfo_t, intregs);
3712 for (i = 0; i < INT_SAV_CNT; i++)
3713 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3716 /* load return address */
3718 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3720 /* remove stackframe */
3722 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3724 /* check for exception */
3726 M_TEST(REG_ITMP3_XPTR);
3727 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3731 /* handle exception */
3733 M_MOV(REG_RA, REG_ITMP1_XPC);
3734 M_ASUB_IMM(2, REG_ITMP1_XPC);
3736 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3737 M_ALD_DSEG(REG_ITMP2, disp);
3738 M_JMP(RN, REG_ITMP2);
3742 * These are local overrides for various environment variables in Emacs.
3743 * Please do not remove this and leave it at the end of the file, where
3744 * Emacs will automagically detect them.
3745 * ---------------------------------------------------------------------
3748 * indent-tabs-mode: t
3752 * vim:noexpandtab:sw=4:ts=4: