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 "vm/builtin.h"
46 #include "vm/exceptions.hpp"
47 #include "vm/global.h"
48 #include "vm/loader.h"
49 #include "vm/options.h"
50 #include "vm/statistics.h"
54 #include "vm/jit/abi.h"
55 #if defined(ENABLE_LSRA)
56 # include "vm/jit/allocator/lsra.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/codegen-common.h"
60 #include "vm/jit/dseg.h"
61 #include "vm/jit/emit-common.h"
62 #include "vm/jit/jit.h"
63 #include "vm/jit/linenumbertable.h"
64 #include "vm/jit/methodheader.h"
65 #include "vm/jit/parse.h"
66 #include "vm/jit/patcher-common.h"
67 #include "vm/jit/reg.h"
68 #include "vm/jit/replace.h"
69 #include "vm/jit/stacktrace.hpp"
70 #include "vm/jit/trap.h"
73 /* DO__LOG generates a call to do__log. No registers are destroyed,
74 * so you may use it anywhere. regs is an array containing all general
79 static void do__log(u4 *regs) {
84 N_AHI(REG_SP, -200); \
85 N_STM(R0, R15, 96, REG_SP); \
86 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
87 N_LA(R2, 96, RN, REG_SP); \
89 N_LM(R0, R15, 96, REG_SP); \
92 /* If the following macro is defined, workaround code for hercules quirks
96 /* #define SUPPORT_HERCULES 1 */
98 /* codegen *********************************************************************
100 Generates machine code.
102 *******************************************************************************/
106 Layout of stackframe:
109 ===============================================================================
110 return_address (stackframesize - 1) * 8
111 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
113 saved_int_reg[rd->savintreguse]
114 saved_flt_reg[FLT_SAV_CNT - 1]
116 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
118 return_value_tmp (rd->memuse + 1) * 8
119 monitorenter_argument (rd->memuse) * 8
121 local[rd->memuse - 1] (rd->memuse - 1) * 8
129 bool codegen_emit(jitdata *jd)
135 s4 len, s1, s2, s3, d, dd, disp;
140 constant_classref *cr;
141 unresolved_class *uc;
142 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
143 unresolved_method *um;
144 builtintable_entry *bte;
147 unresolved_field *uf;
150 rplpoint *replacementpoint;
154 /* get required compiler data */
161 /* prevent compiler warnings */
174 /* space to save used callee saved registers */
176 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
177 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
179 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
182 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
185 #if defined(ENABLE_THREADS)
186 /* Space to save argument of monitor_enter and Return Values to
187 survive monitor_exit. The stack position for the argument can
188 not be shared with place to save the return register
189 since both values reside in R2. */
191 if (checksync && code_is_synchronized(code)) {
192 /* 1 slot space to save argument of monitor_enter */
193 /* 1 slot to temporary store return value before monitor_exit */
194 cd->stackframesize += 2;
198 /* Keep stack of non-leaf functions 16-byte aligned for calls into
199 native code e.g. libc or jni (alignment problems with
202 if (!code_is_leafmethod(code) || opt_verbosecall )
203 /* TODO really 16 bytes ? */
204 cd->stackframesize = (cd->stackframesize + 2) & ~2;
206 /* create method header */
208 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
209 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
211 code->synchronizedoffset = rd->memuse * 8;
213 /* REMOVEME: We still need it for exception handling in assembler. */
215 if (code_is_leafmethod(code))
216 (void) dseg_add_unique_s4(cd, 1);
218 (void) dseg_add_unique_s4(cd, 0);
220 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
221 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
225 M_AADD_IMM(N_PV_OFFSET, REG_PV);
227 /* create stack frame (if necessary) */
229 if (cd->stackframesize) {
230 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
233 /* store return address */
235 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
237 /* generate method profiling code */
239 #if defined(ENABLE_PROFILING)
240 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
241 /* count frequency */
242 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
243 ICONST(REG_ITMP2, 1);
244 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
245 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
251 /* save used callee saved registers and return address */
253 p = cd->stackframesize - 1;
255 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
256 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
258 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
259 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
262 /* take arguments out of register or stack frame */
266 for (p = 0, l = 0; p < md->paramcount; p++) {
267 t = md->paramtypes[p].type;
268 varindex = jd->local_map[l * 5 + t];
272 if (IS_2_WORD_TYPE(t))
275 if (varindex == UNUSED)
280 s1 = md->params[p].regoff;
282 if (IS_INT_LNG_TYPE(t)) { /* integer args */
283 if (IS_2_WORD_TYPE(t)) {
291 if (!md->params[p].inmemory) { /* register arguments */
292 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
293 if (IS_2_WORD_TYPE(t)) {
294 M_LNGMOVE(s2, var->vv.regoff);
296 M_INTMOVE(s2, var->vv.regoff);
298 } else { /* reg arg -> spilled */
299 if (IS_2_WORD_TYPE(t)) {
300 M_LST(s2, REG_SP, var->vv.regoff);
302 M_IST(s2, REG_SP, var->vv.regoff);
306 } else { /* stack arguments */
307 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
308 if (IS_2_WORD_TYPE(t)) {
309 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
311 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
313 } else { /* stack arg -> spilled */
314 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
318 } else { /* floating args */
319 if (!md->params[p].inmemory) { /* register arguments */
321 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
322 M_FLTMOVE(s2, var->vv.regoff);
324 } else { /* reg arg -> spilled */
325 if (IS_2_WORD_TYPE(t))
326 M_DST(s2, REG_SP, var->vv.regoff);
328 M_FST(s2, REG_SP, var->vv.regoff);
331 } else { /* stack arguments */
332 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
333 if (IS_2_WORD_TYPE(t))
334 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
337 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
339 } else { /* stack-arg -> spilled */
340 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
341 var->vv.regoff = cd->stackframesize * 8 + s1;
347 /* save monitorenter argument */
349 #if defined(ENABLE_THREADS)
350 if (checksync && code_is_synchronized(code)) {
351 /* stack offset for monitor argument */
356 if (opt_verbosecall) {
357 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
359 for (p = 0; p < INT_ARG_CNT; p++)
360 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
362 for (p = 0; p < FLT_ARG_CNT; p++)
363 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
365 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
369 /* decide which monitor enter function to call */
371 if (m->flags & ACC_STATIC) {
372 disp = dseg_add_address(cd, &m->clazz->object.header);
373 M_ALD_DSEG(REG_A0, disp);
377 M_BNE(SZ_BRC + SZ_ILL);
378 M_ILL(TRAP_NullPointerException);
381 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
382 M_ALD_DSEG(REG_ITMP2, disp);
384 M_AST(REG_A0, REG_SP, s1 * 8);
386 M_ASUB_IMM(96, REG_SP);
388 M_AADD_IMM(96, REG_SP);
391 if (opt_verbosecall) {
392 for (p = 0; p < INT_ARG_CNT; p++)
393 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
395 for (p = 0; p < FLT_ARG_CNT; p++)
396 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
398 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
405 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
406 emit_verbosecall_enter(jd);
407 #endif /* !defined(NDEBUG) */
411 /* end of header generation */
413 /* create replacement points */
415 REPLACEMENT_POINTS_INIT(cd, jd);
417 /* walk through all basic blocks */
419 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
421 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
423 if (bptr->flags >= BBREACHED) {
425 /* branch resolving */
427 codegen_resolve_branchrefs(cd, bptr);
429 /* handle replacement points */
431 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
433 /* copy interface registers to their destination */
438 #if defined(ENABLE_PROFILING)
439 /* generate basicblock profiling code */
441 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
442 /* count frequency */
444 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
445 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
446 ICONST(REG_ITMP2, 1);
447 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
448 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
450 /* if this is an exception handler, start profiling again */
452 if (bptr->type == BBTYPE_EXH)
457 #if defined(ENABLE_LSRA)
461 src = bptr->invars[len];
462 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
463 if (bptr->type == BBTYPE_EXH) {
464 /* d = reg_of_var(rd, src, REG_ITMP1); */
465 if (!IS_INMEMORY(src->flags))
469 M_INTMOVE(REG_ITMP3_XPTR, d);
470 emit_store(jd, NULL, src, d);
480 var = VAR(bptr->invars[len]);
481 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
482 if (bptr->type == BBTYPE_EXH) {
483 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
484 M_INTMOVE(REG_ITMP3_XPTR, d);
485 emit_store(jd, NULL, var, d);
489 assert((var->flags & INOUT));
492 #if defined(ENABLE_LSRA)
495 /* walk through all instructions */
500 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
501 if (iptr->line != currentline) {
502 linenumbertable_list_entry_add(cd, iptr->line);
503 currentline = iptr->line;
506 MCODECHECK(1024); /* 1KB should be enough */
509 case ICMD_NOP: /* ... ==> ... */
510 case ICMD_POP: /* ..., value ==> ... */
511 case ICMD_POP2: /* ..., value, value ==> ... */
514 case ICMD_INLINE_START:
516 REPLACEMENT_POINT_INLINE_START(cd, iptr);
519 case ICMD_INLINE_BODY:
521 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
522 linenumbertable_list_entry_add_inline_start(cd, iptr);
523 linenumbertable_list_entry_add(cd, iptr->line);
526 case ICMD_INLINE_END:
528 linenumbertable_list_entry_add_inline_end(cd, iptr);
529 linenumbertable_list_entry_add(cd, iptr->line);
532 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
533 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
534 emit_nullpointer_check(cd, iptr, s1);
537 /* constant operations ************************************************/
539 case ICMD_ICONST: /* ... ==> ..., constant */
540 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
541 ICONST(d, iptr->sx.val.i);
542 emit_store_dst(jd, iptr, d);
545 case ICMD_LCONST: /* ... ==> ..., constant */
547 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
548 LCONST(d, iptr->sx.val.l);
549 emit_store_dst(jd, iptr, d);
552 case ICMD_FCONST: /* ... ==> ..., constant */
553 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
554 disp = dseg_add_float(cd, iptr->sx.val.f);
555 M_FLD_DSEG(d, disp, REG_ITMP1);
556 emit_store_dst(jd, iptr, d);
559 case ICMD_DCONST: /* ... ==> ..., constant */
560 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
561 disp = dseg_add_double(cd, iptr->sx.val.d);
562 M_DLD_DSEG(d, disp, REG_ITMP1);
563 emit_store_dst(jd, iptr, d);
566 case ICMD_ACONST: /* ... ==> ..., constant */
567 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
569 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
570 cr = iptr->sx.val.c.ref;
571 disp = dseg_add_unique_address(cd, cr);
573 /* PROFILE_CYCLE_STOP; */
575 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
578 /* PROFILE_CYCLE_START; */
582 if (iptr->sx.val.anyptr == 0) {
585 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
588 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
589 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
591 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
593 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
599 emit_store_dst(jd, iptr, d);
603 /* load/store/copy/move operations ************************************/
605 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
606 case ICMD_ALOAD: /* s1 = local variable */
610 case ICMD_ISTORE: /* ..., value ==> ... */
621 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
625 /* integer operations *************************************************/
627 case ICMD_INEG: /* ..., value ==> ..., - value */
629 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
630 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
632 emit_store_dst(jd, iptr, d);
636 case ICMD_LNEG: /* ..., value ==> ..., - value */
638 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
639 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
640 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
641 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
642 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
643 N_AHI(GET_HIGH_REG(d), -1);
644 emit_store_dst(jd, iptr, d);
647 case ICMD_I2L: /* ..., value ==> ..., value */
649 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
650 if (! N_IS_EVEN_ODD(d)) {
651 d = REG_ITMP31_PACKED;
653 assert(N_IS_EVEN_ODD(d));
655 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
657 M_INTMOVE(s1, GET_HIGH_REG(d));
658 M_SRDA_IMM(32, GET_HIGH_REG(d));
660 emit_copy_dst(jd, iptr, d);
661 emit_store_dst(jd, iptr, d);
664 case ICMD_L2I: /* ..., value ==> ..., value */
665 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
666 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
667 M_INTMOVE(GET_LOW_REG(s1), d);
668 emit_store_dst(jd, iptr, d);
671 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
672 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
673 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
677 emit_store_dst(jd, iptr, d);
680 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
681 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
682 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
686 emit_store_dst(jd, iptr, d);
689 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
691 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
692 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
696 emit_store_dst(jd, iptr, d);
699 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
701 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
702 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
703 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
710 emit_store_dst(jd, iptr, d);
715 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
716 /* sx.val.i = constant */
717 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
718 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
721 if (N_VALID_IMM(iptr->sx.val.i)) {
722 M_IADD_IMM(iptr->sx.val.i, d);
724 ICONST(REG_ITMP2, iptr->sx.val.i);
725 M_IADD(REG_ITMP2, d);
727 emit_store_dst(jd, iptr, d);
730 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
732 /* M, (r, q) -> (r, q) */
734 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
736 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
737 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
738 dd = GET_HIGH_REG(d);
747 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
748 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
758 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
759 N_AHI(GET_HIGH_REG(d), 1);
761 emit_store_dst(jd, iptr, d);
764 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
765 /* sx.val.l = constant */
767 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
768 dd = GET_HIGH_REG(d);
770 s1 = emit_load_s1_high(jd, iptr, dd);
771 s3 = iptr->sx.val.l >> 32;
775 if (N_VALID_IMM(s3)) {
778 ICONST(REG_ITMP3, s3);
779 M_IADD(REG_ITMP3, dd);
783 s1 = emit_load_s1_low(jd, iptr, dd);
784 s3 = iptr->sx.val.l & 0xffffffff;
785 ICONST(REG_ITMP3, s3);
788 N_ALR(dd, REG_ITMP3);
790 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
791 N_AHI(GET_HIGH_REG(d), 1);
793 emit_store_dst(jd, iptr, d);
796 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
798 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
799 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
800 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
802 M_INTMOVE(s1, REG_ITMP1);
803 M_ISUB(s2, REG_ITMP1);
804 M_INTMOVE(REG_ITMP1, d);
809 emit_store_dst(jd, iptr, d);
813 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
814 /* sx.val.i = constant */
816 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
817 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
820 if (N_VALID_IMM(-iptr->sx.val.i)) {
821 M_ISUB_IMM(iptr->sx.val.i, d);
823 ICONST(REG_ITMP2, iptr->sx.val.i);
824 M_ISUB(REG_ITMP2, d);
826 emit_store_dst(jd, iptr, d);
830 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
832 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
834 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
835 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
836 dd = GET_HIGH_REG(d);
839 M_INTMOVE(s2, REG_ITMP3);
846 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
847 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
851 M_INTMOVE(s2, REG_ITMP3);
858 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
859 N_AHI(GET_HIGH_REG(d), -1);
861 emit_store_dst(jd, iptr, d);
864 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
865 /* sx.val.l = constant */
867 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
869 dd = GET_HIGH_REG(d);
870 s1 = emit_load_s1_high(jd, iptr, dd);
871 s3 = iptr->sx.val.l >> 32;
875 if (N_VALID_IMM(-s3)) {
878 ICONST(REG_ITMP3, s3);
879 M_ISUB(REG_ITMP3, dd);
883 s1 = emit_load_s1_low(jd, iptr, dd);
884 s3 = iptr->sx.val.l & 0xffffffff;
885 ICONST(REG_ITMP3, s3);
888 N_SLR(dd, REG_ITMP3);
890 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
891 N_AHI(GET_HIGH_REG(d), -1);
893 emit_store_dst(jd, iptr, d);
896 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
898 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
899 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
900 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
907 emit_store_dst(jd, iptr, d);
911 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
912 /* sx.val.i = constant */
913 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
914 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
916 if (iptr->sx.val.i == 2) {
918 } else if (N_VALID_IMM(iptr->sx.val.i)) {
919 M_IMUL_IMM(iptr->sx.val.i, d);
921 disp = dseg_add_s4(cd, iptr->sx.val.i);
922 M_ILD_DSEG(REG_ITMP2, disp);
923 M_IMUL(REG_ITMP2, d);
925 emit_store_dst(jd, iptr, d);
928 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
929 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
931 /* load s1 into r0 */
933 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
934 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
935 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
937 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
939 /* extend s1 to long */
941 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
945 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
951 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
952 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
955 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
956 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
960 emit_store_dst(jd, iptr, d);
964 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
965 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
967 bte = iptr->sx.s23.s3.bte;
970 /* test s2 for zero */
972 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
973 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
974 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
975 emit_arithmetic_check(cd, iptr, REG_ITMP3);
979 disp = dseg_add_functionptr(cd, bte->fp);
983 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
985 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
986 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
990 M_ASUB_IMM(96, REG_SP);
991 M_ALD_DSEG(REG_ITMP2, disp);
992 M_JSR(REG_RA, REG_ITMP2);
993 M_AADD_IMM(96, REG_SP);
997 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
998 M_LNGMOVE(REG_RESULT_PACKED, d);
999 emit_store_dst(jd, iptr, d);
1003 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1004 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1005 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1007 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1008 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1009 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1011 /* Use only 5 bits of sencond operand. */
1013 M_INTMOVE(s2, REG_ITMP2);
1015 ICONST(REG_ITMP3, 0x1F);
1016 M_IAND(REG_ITMP3, s2);
1020 switch (iptr->opc) {
1033 emit_store_dst(jd, iptr, d);
1036 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1037 /* sx.val.i = constant */
1041 assert(iptr->sx.val.i <= 32);
1043 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1044 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1051 s3 = (1 << iptr->sx.val.i) - 1;
1053 if (N_VALID_IMM(s3)) {
1056 ICONST(REG_ITMP1, -1);
1057 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1058 M_IADD(REG_ITMP1, d);
1061 N_BRC_BACK_PATCH(ref);
1063 M_SRA_IMM(iptr->sx.val.i, d);
1065 emit_store_dst(jd, iptr, d);
1070 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1071 /* sx.val.i = constant */
1073 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1074 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1077 M_MOV(s1, REG_ITMP1);
1081 ICONST(REG_ITMP3, iptr->sx.val.i);
1084 M_IAND(REG_ITMP3, d);
1087 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1093 emit_store_dst(jd, iptr, d);
1097 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1098 /* sx.val.i = constant */
1099 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1100 /* sx.val.i = constant */
1101 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1102 /* sx.val.i = constant */
1103 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1104 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1108 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1110 switch (iptr->opc) {
1111 case ICMD_ISHLCONST:
1114 case ICMD_ISHRCONST:
1117 case ICMD_IUSHRCONST:
1124 emit_store_dst(jd, iptr, d);
1127 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1129 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1131 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1133 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1135 /* Use only 6 bits of second operand */
1137 M_INTMOVE(s2, REG_ITMP2);
1139 ICONST(REG_ITMP1, 0x3F);
1140 M_IAND(REG_ITMP1, s2);
1142 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1143 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1145 /* Destination must be even-odd pair */
1147 if (! N_IS_EVEN_ODD(d)) {
1148 d = REG_ITMP31_PACKED;
1151 assert(N_IS_EVEN_ODD(d));
1155 switch (iptr->opc) {
1157 M_SLDL(s2, GET_HIGH_REG(d));
1160 M_SRDA(s2, GET_HIGH_REG(d));
1163 M_SRDL(s2, GET_HIGH_REG(d));
1169 emit_copy_dst(jd, iptr, d);
1170 emit_store_dst(jd, iptr, d);
1174 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1175 /* sx.val.i = constant */
1176 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1177 /* sx.val.i = constant */
1178 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1179 /* sx.val.l = constant */
1182 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1183 if (! N_IS_EVEN_ODD(d)) {
1184 d = REG_ITMP31_PACKED;
1186 assert(N_IS_EVEN_ODD(d));
1188 s1 = emit_load_s1(jd, iptr, d);
1192 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1194 switch (iptr->opc) {
1195 case ICMD_LSHLCONST:
1196 N_SLDL(GET_HIGH_REG(d), disp, RN);
1198 case ICMD_LSHRCONST:
1199 N_SRDA(GET_HIGH_REG(d), disp, RN);
1201 case ICMD_LUSHRCONST:
1202 N_SRDL(GET_HIGH_REG(d), disp, RN);
1205 N_SLDL(GET_HIGH_REG(d), disp, RN);
1211 emit_copy_dst(jd, iptr, d);
1212 emit_store_dst(jd, iptr, d);
1215 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1217 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1218 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1219 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1226 emit_store_dst(jd, iptr, d);
1230 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1232 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1233 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1234 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1241 emit_store_dst(jd, iptr, d);
1245 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1247 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1248 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1249 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1256 emit_store_dst(jd, iptr, d);
1262 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1263 /* sx.val.i = constant */
1264 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1265 /* sx.val.i = constant */
1266 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1267 /* sx.val.i = constant */
1269 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1270 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1273 ICONST(REG_ITMP2, iptr->sx.val.i);
1275 switch (iptr->opc) {
1276 case ICMD_IANDCONST:
1277 M_IAND(REG_ITMP2, d);
1279 case ICMD_IXORCONST:
1280 M_IXOR(REG_ITMP2, d);
1283 M_IOR(REG_ITMP2, d);
1289 emit_store_dst(jd, iptr, d);
1293 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1294 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1295 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1297 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1299 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1300 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1301 dd = GET_LOW_REG(d);
1303 switch (iptr->opc) {
1332 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1333 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1334 dd = GET_HIGH_REG(d);
1336 switch (iptr->opc) {
1365 emit_store_dst(jd, iptr, d);
1368 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1369 /* sx.val.l = constant */
1370 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1371 /* sx.val.l = constant */
1372 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1373 /* sx.val.l = constant */
1375 /* TODO should use memory operand to access data segment, not load */
1377 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1379 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1380 s3 = iptr->sx.val.l & 0xffffffff;
1382 M_INTMOVE(s1, GET_LOW_REG(d));
1384 ICONST(REG_ITMP3, s3);
1386 switch (iptr->opc) {
1387 case ICMD_LANDCONST:
1388 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1390 case ICMD_LXORCONST:
1391 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1394 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1400 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1401 s3 = iptr->sx.val.l >> 32;
1403 M_INTMOVE(s1, GET_HIGH_REG(d));
1405 ICONST(REG_ITMP3, s3);
1407 switch (iptr->opc) {
1408 case ICMD_LANDCONST:
1409 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1411 case ICMD_LXORCONST:
1412 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1415 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1421 emit_store_dst(jd, iptr, d);
1425 /* floating operations ************************************************/
1427 case ICMD_FNEG: /* ..., value ==> ..., - value */
1428 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1429 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1431 emit_store_dst(jd, iptr, d);
1434 case ICMD_DNEG: /* ..., value ==> ..., - value */
1435 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1436 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1438 emit_store_dst(jd, iptr, d);
1441 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1442 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1443 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1444 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1451 emit_store_dst(jd, iptr, d);
1454 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1455 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1456 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1457 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1464 emit_store_dst(jd, iptr, d);
1467 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1468 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1469 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1470 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1474 emit_store_dst(jd, iptr, d);
1477 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1478 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1479 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1480 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1484 emit_store_dst(jd, iptr, d);
1487 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1488 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1489 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1490 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1497 emit_store_dst(jd, iptr, d);
1500 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1501 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1502 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1503 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1510 emit_store_dst(jd, iptr, d);
1513 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1514 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1515 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1516 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1520 emit_store_dst(jd, iptr, d);
1523 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1524 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1525 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1526 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1530 emit_store_dst(jd, iptr, d);
1533 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1534 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1535 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1537 emit_store_dst(jd, iptr, d);
1540 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1541 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1542 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1544 emit_store_dst(jd, iptr, d);
1547 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1551 #ifdef SUPPORT_HERCULES
1555 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1556 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1560 switch (iptr->opc) {
1569 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1570 N_LHI(d, 0); /* Load 0 */
1571 ref1 = cd->mcodeptr;
1572 N_BRC(DD_ANY, 0); /* Exit */
1576 switch (iptr->opc) {
1585 #ifdef SUPPORT_HERCULES
1586 /* Hercules does the conversion using a plain C conversion.
1587 * According to manual, real hardware should *NOT* require this.
1589 * Corner case: Positive float leads to INT_MIN (overflow).
1592 switch (iptr->opc) {
1601 ref2 = cd->mcodeptr;
1602 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1606 ref3 = cd->mcodeptr;
1607 M_BGE(0); /* If integer result is negative, continue */
1609 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1610 M_ILD_DSEG(d, disp);
1612 N_BRC_BACK_PATCH(ref1);
1613 #ifdef SUPPORT_HERCULES
1614 N_BRC_BACK_PATCH(ref2);
1615 N_BRC_BACK_PATCH(ref3);
1617 emit_store_dst(jd, iptr, d);
1621 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1623 #ifdef SUPPORT_HERCULES
1626 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1627 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1628 #ifdef SUPPORT_HERCULES
1631 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1632 disp = dseg_add_double(cd, 0.0 / 0.0);
1633 M_DLD_DSEG(d, disp, REG_ITMP1);
1634 emit_label_br(cd, BRANCH_LABEL_1);
1635 N_BRC_BACK_PATCH(ref);
1638 #ifdef SUPPORT_HERCULES
1639 emit_label(cd, BRANCH_LABEL_1);
1641 emit_store_dst(jd, iptr, d);
1645 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1646 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1647 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1649 emit_store_dst(jd, iptr, d);
1652 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1653 /* == => 0, < => 1, > => -1 */
1657 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1658 /* == => 0, < => 1, > => -1 */
1661 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1662 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1663 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1665 switch (iptr->opc) {
1677 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1678 SZ_BRC + SZ_BRC + SZ_BRC
1681 N_BRC( /* load -1 */
1682 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1683 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1688 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1691 N_LHI(d, 1); /* GT */
1692 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1693 N_LHI(d, -1); /* LT */
1694 M_BR(SZ_BRC + SZ_LHI);
1695 N_LHI(d, 0); /* EQ */
1697 emit_store_dst(jd, iptr, d);
1702 /* memory operations **************************************************/
1704 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1706 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1707 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1709 /* implicit null-pointer check */
1710 M_ILD(d, s1, OFFSET(java_array_t, size));
1711 emit_store_dst(jd, iptr, d);
1715 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1716 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1717 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1718 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1720 /* implicit null-pointer check */
1721 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1723 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1728 emit_store_dst(jd, iptr, d);
1731 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1733 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1734 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1735 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1737 /* implicit null-pointer check */
1738 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1740 M_INTMOVE(s2, REG_ITMP2);
1741 M_SLL_IMM(1, REG_ITMP2);
1743 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1745 /* N_LH does sign extends, undo ! */
1750 emit_store_dst(jd, iptr, d);
1753 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1754 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1755 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1756 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1758 /* implicit null-pointer check */
1759 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1761 M_INTMOVE(s2, REG_ITMP2);
1762 M_SLL_IMM(1, REG_ITMP2);
1764 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1765 emit_store_dst(jd, iptr, d);
1768 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1769 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1770 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1771 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1773 /* implicit null-pointer check */
1774 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1776 M_INTMOVE(s2, REG_ITMP2);
1777 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1778 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1779 emit_store_dst(jd, iptr, d);
1782 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1784 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1785 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1787 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1789 /* implicit null-pointer check */
1790 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1792 M_INTMOVE(s2, REG_ITMP2);
1793 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1796 GET_LOW_REG(d) /* maybe itmp3 */,
1797 OFFSET(java_longarray_t, data[0]) + 4,
1798 REG_ITMP2, s1 /* maybe itmp1 */
1802 GET_HIGH_REG(d) /* maybe itmp1 */,
1803 OFFSET(java_longarray_t, data[0]),
1804 REG_ITMP2, s1 /* maybe itmp1 */
1807 emit_store_dst(jd, iptr, d);
1811 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1813 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1814 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1815 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1817 /* implicit null-pointer check */
1818 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1820 M_INTMOVE(s2, REG_ITMP2);
1821 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1823 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1825 emit_store_dst(jd, iptr, d);
1828 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1829 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1830 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1831 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1833 /* implicit null-pointer check */
1834 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1836 M_INTMOVE(s2, REG_ITMP2);
1837 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1839 N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1841 emit_store_dst(jd, iptr, d);
1844 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1845 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1846 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1847 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1849 /* implicit null-pointer check */
1850 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1852 M_INTMOVE(s2, REG_ITMP2);
1853 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1854 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1855 emit_store_dst(jd, iptr, d);
1858 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1859 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1860 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1861 /* implicit null-pointer check */
1862 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1863 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1865 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1868 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1870 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1871 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1872 /* implicit null-pointer check */
1873 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1874 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1876 M_INTMOVE(s2, REG_ITMP2);
1877 M_SLL_IMM(1, REG_ITMP2);
1879 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1883 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1884 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1885 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1886 /* implicit null-pointer check */
1887 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1888 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1890 M_INTMOVE(s2, REG_ITMP2);
1891 M_SLL_IMM(1, REG_ITMP2);
1893 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1896 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1898 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1899 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1900 /* implicit null-pointer check */
1901 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1903 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1905 M_INTMOVE(s2, REG_ITMP2);
1906 M_SLL_IMM(2, REG_ITMP2);
1908 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1911 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1913 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1914 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1915 /* implicit null-pointer check */
1916 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1918 M_INTMOVE(s2, REG_ITMP2);
1919 M_SLL_IMM(3, REG_ITMP2);
1921 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1922 N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1);
1923 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1924 N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1);
1927 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1928 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1929 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1930 /* implicit null-pointer check */
1931 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1932 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1934 M_INTMOVE(s2, REG_ITMP2);
1935 M_SLL_IMM(2, REG_ITMP2);
1937 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1940 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1941 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1942 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1943 /* implicit null-pointer check */
1944 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1945 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1947 M_INTMOVE(s2, REG_ITMP2);
1948 M_SLL_IMM(3, REG_ITMP2);
1950 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1953 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1955 s1 = emit_load_s1(jd, iptr, REG_A0);
1956 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1957 /* implicit null-pointer check */
1958 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1959 s3 = emit_load_s3(jd, iptr, REG_A1);
1961 M_INTMOVE(s1, REG_A0);
1962 M_INTMOVE(s3, REG_A1);
1964 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1965 M_ALD_DSEG(REG_ITMP2, disp);
1966 M_ASUB_IMM(96, REG_SP);
1967 M_JSR(REG_RA, REG_ITMP2);
1968 M_AADD_IMM(96, REG_SP);
1970 emit_arraystore_check(cd, iptr);
1972 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1973 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1974 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1976 M_INTMOVE(s2, REG_ITMP2);
1977 M_SLL_IMM(2, REG_ITMP2);
1978 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1981 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1982 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1987 case ICMD_GETSTATIC: /* ... ==> ..., value */
1989 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1990 uf = iptr->sx.s23.s3.uf;
1991 fieldtype = uf->fieldref->parseddesc.fd->type;
1992 disp = dseg_add_unique_address(cd, NULL);
1994 /* PROFILE_CYCLE_STOP; */
1996 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1998 /* PROFILE_CYCLE_START; */
2001 fi = iptr->sx.s23.s3.fmiref->p.field;
2002 fieldtype = fi->type;
2003 disp = dseg_add_address(cd, fi->value);
2005 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
2008 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
2010 PROFILE_CYCLE_START;
2014 M_ALD_DSEG(REG_ITMP1, disp);
2016 switch (fieldtype) {
2018 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2019 M_ILD(d, REG_ITMP1, 0);
2022 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2023 M_LLD(d, REG_ITMP1, 0);
2026 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2027 M_ALD(d, REG_ITMP1, 0);
2030 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2031 M_FLD(d, REG_ITMP1, 0);
2034 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2035 M_DLD(d, REG_ITMP1, 0);
2039 emit_store_dst(jd, iptr, d);
2043 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2045 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2046 uf = iptr->sx.s23.s3.uf;
2047 fieldtype = uf->fieldref->parseddesc.fd->type;
2048 disp = dseg_add_unique_address(cd, uf);
2050 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2053 fi = iptr->sx.s23.s3.fmiref->p.field;
2054 fieldtype = fi->type;
2055 disp = dseg_add_address(cd, fi->value);
2057 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
2059 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
2060 PROFILE_CYCLE_START;
2064 M_ALD_DSEG(REG_ITMP1, disp);
2065 switch (fieldtype) {
2067 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2068 M_IST(s1, REG_ITMP1, 0);
2071 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2072 M_LST(s1, REG_ITMP1, 0);
2075 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2076 M_AST(s1, REG_ITMP1, 0);
2079 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2080 M_FST(s1, REG_ITMP1, 0);
2083 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2084 M_DST(s1, REG_ITMP1, 0);
2089 case ICMD_GETFIELD: /* ... ==> ..., value */
2091 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2092 emit_nullpointer_check(cd, iptr, s1);
2094 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2095 uf = iptr->sx.s23.s3.uf;
2096 fieldtype = uf->fieldref->parseddesc.fd->type;
2099 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2102 fi = iptr->sx.s23.s3.fmiref->p.field;
2103 fieldtype = fi->type;
2107 switch (fieldtype) {
2109 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2113 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2114 if (GET_HIGH_REG(d) == s1) {
2115 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2116 M_ILD(GET_HIGH_REG(d), s1, disp);
2119 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2120 M_ILD(GET_HIGH_REG(d), s1, disp);
2124 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2128 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2132 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2136 emit_store_dst(jd, iptr, d);
2139 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2143 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2144 emit_nullpointer_check(cd, iptr, s1);
2146 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2147 uf = iptr->sx.s23.s3.uf;
2148 fieldtype = uf->fieldref->parseddesc.fd->type;
2152 fi = iptr->sx.s23.s3.fmiref->p.field;
2153 fieldtype = fi->type;
2157 /* We can't add a patcher ref behind this load,
2158 * because the patcher would destroy REG_ITMP3.
2160 * We pass in the disp parameter, how many bytes
2161 * to skip to the to the actual store.
2163 * XXX this relies on patcher_add_patch_ref internals
2166 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2167 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2172 if (IS_INT_LNG_TYPE(fieldtype)) {
2173 if (IS_2_WORD_TYPE(fieldtype))
2174 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2176 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2178 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2181 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2182 ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2185 switch (fieldtype) {
2187 M_IST(s2, s1, disp);
2190 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2191 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2194 M_AST(s2, s1, disp);
2197 M_FST(s2, s1, disp);
2200 M_DST(s2, s1, disp);
2207 /* branch operations **************************************************/
2209 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2211 /* PROFILE_CYCLE_STOP; */
2213 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2214 M_INTMOVE(s1, REG_ITMP3_XPTR);
2216 #ifdef ENABLE_VERIFIER
2217 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2218 uc = iptr->sx.s23.s2.uc;
2220 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2222 #endif /* ENABLE_VERIFIER */
2224 disp = dseg_add_functionptr(cd, asm_handle_exception);
2225 M_ALD_DSEG(REG_ITMP1, disp);
2226 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2231 case ICMD_GOTO: /* ... ==> ... */
2232 case ICMD_RET: /* ... ==> ... */
2234 emit_br(cd, iptr->dst.block);
2238 case ICMD_JSR: /* ... ==> ... */
2240 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2244 case ICMD_IFNULL: /* ..., value ==> ... */
2245 case ICMD_IFNONNULL: /* ..., value ==> ... */
2246 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2248 switch (iptr->opc) {
2250 emit_beq(cd, iptr->dst.block);
2252 case ICMD_IFNONNULL:
2253 emit_bne(cd, iptr->dst.block);
2258 case ICMD_IFEQ: /* ..., value ==> ... */
2259 case ICMD_IFLT: /* ..., value ==> ... */
2260 case ICMD_IFLE: /* ..., value ==> ... */
2261 case ICMD_IFNE: /* ..., value ==> ... */
2262 case ICMD_IFGT: /* ..., value ==> ... */
2263 case ICMD_IFGE: /* ..., value ==> ... */
2265 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2267 if (N_VALID_IMM(iptr->sx.val.i))
2268 M_ICMP_IMM(s1, iptr->sx.val.i);
2270 disp = dseg_add_s4(cd, iptr->sx.val.i);
2271 if (N_VALID_DSEG_DISP(disp)) {
2272 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2274 ICONST(REG_ITMP2, disp);
2275 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2279 switch (iptr->opc) {
2281 emit_blt(cd, iptr->dst.block);
2284 emit_ble(cd, iptr->dst.block);
2287 emit_bne(cd, iptr->dst.block);
2290 emit_bgt(cd, iptr->dst.block);
2293 emit_bge(cd, iptr->dst.block);
2296 emit_beq(cd, iptr->dst.block);
2302 case ICMD_IF_LLT: /* ..., value ==> ... */
2303 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2309 /* ATTENTION: compare high words signed and low words unsigned */
2311 # define LABEL_OUT BRANCH_LABEL_1
2313 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2315 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2316 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2318 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2319 if (N_VALID_DSEG_DISP(disp)) {
2320 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2322 ICONST(REG_ITMP2, disp);
2323 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2330 emit_blt(cd, iptr->dst.block);
2331 /* EQ ... fall through */
2332 emit_label_bgt(cd, LABEL_OUT);
2336 emit_bgt(cd, iptr->dst.block);
2337 /* EQ ... fall through */
2338 emit_label_blt(cd, LABEL_OUT);
2341 /* EQ ... fall through */
2342 emit_label_bne(cd, LABEL_OUT);
2345 /* EQ ... fall through */
2346 emit_bne(cd, iptr->dst.block);
2352 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2354 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2355 if (N_VALID_DSEG_DISP(disp)) {
2356 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2358 ICONST(REG_ITMP2, disp);
2359 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2364 emit_blt(cd, iptr->dst.block);
2365 emit_label(cd, LABEL_OUT);
2368 emit_ble(cd, iptr->dst.block);
2369 emit_label(cd, LABEL_OUT);
2372 emit_bgt(cd, iptr->dst.block);
2373 emit_label(cd, LABEL_OUT);
2376 emit_bge(cd, iptr->dst.block);
2377 emit_label(cd, LABEL_OUT);
2380 emit_beq(cd, iptr->dst.block);
2381 emit_label(cd, LABEL_OUT);
2384 emit_bne(cd, iptr->dst.block);
2393 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2394 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2396 /* Compare addresses as 31 bit unsigned integers */
2398 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2399 M_LDA(REG_ITMP1, s1, 0);
2401 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2402 M_LDA(REG_ITMP2, s2, 0);
2404 M_CMP(REG_ITMP1, REG_ITMP2);
2406 switch (iptr->opc) {
2407 case ICMD_IF_ACMPEQ:
2408 emit_beq(cd, iptr->dst.block);
2410 case ICMD_IF_ACMPNE:
2411 emit_bne(cd, iptr->dst.block);
2417 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2418 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2419 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2420 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2421 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2422 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2424 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2425 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2427 switch (iptr->opc) {
2428 case ICMD_IF_ICMPEQ:
2429 emit_beq(cd, iptr->dst.block);
2431 case ICMD_IF_ICMPNE:
2432 emit_bne(cd, iptr->dst.block);
2434 case ICMD_IF_ICMPLT:
2435 emit_blt(cd, iptr->dst.block);
2437 case ICMD_IF_ICMPGT:
2438 emit_bgt(cd, iptr->dst.block);
2440 case ICMD_IF_ICMPLE:
2441 emit_ble(cd, iptr->dst.block);
2443 case ICMD_IF_ICMPGE:
2444 emit_bge(cd, iptr->dst.block);
2450 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2451 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2452 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2453 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2454 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2455 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2460 /* ATTENTION: compare high words signed and low words unsigned */
2462 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2463 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2468 case ICMD_IF_LCMPLT:
2469 case ICMD_IF_LCMPLE:
2470 emit_blt(cd, iptr->dst.block);
2471 /* EQ ... fall through */
2472 out_ref = cd->mcodeptr;
2475 case ICMD_IF_LCMPGT:
2476 case ICMD_IF_LCMPGE:
2477 emit_bgt(cd, iptr->dst.block);
2478 /* EQ ... fall through */
2479 out_ref = cd->mcodeptr;
2482 case ICMD_IF_LCMPEQ:
2483 /* EQ ... fall through */
2484 out_ref = cd->mcodeptr;
2487 case ICMD_IF_LCMPNE:
2488 /* EQ ... fall through */
2489 emit_bne(cd, iptr->dst.block);
2495 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2496 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2501 case ICMD_IF_LCMPLT:
2502 emit_blt(cd, iptr->dst.block);
2504 case ICMD_IF_LCMPLE:
2505 emit_ble(cd, iptr->dst.block);
2507 case ICMD_IF_LCMPGT:
2508 emit_bgt(cd, iptr->dst.block);
2510 case ICMD_IF_LCMPGE:
2511 emit_bge(cd, iptr->dst.block);
2513 case ICMD_IF_LCMPEQ:
2514 emit_beq(cd, iptr->dst.block);
2516 case ICMD_IF_LCMPNE:
2517 emit_bne(cd, iptr->dst.block);
2523 if (out_ref != NULL) {
2524 N_BRC_BACK_PATCH(out_ref);
2530 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2532 REPLACEMENT_POINT_RETURN(cd, iptr);
2533 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2534 M_INTMOVE(s1, REG_RESULT);
2535 goto nowperformreturn;
2537 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2539 REPLACEMENT_POINT_RETURN(cd, iptr);
2540 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2541 M_INTMOVE(s1, REG_RESULT);
2543 #ifdef ENABLE_VERIFIER
2544 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2545 unresolved_class *uc = iptr->sx.s23.s2.uc;
2548 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2549 PROFILE_CYCLE_START;
2551 #endif /* ENABLE_VERIFIER */
2552 goto nowperformreturn;
2554 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2556 REPLACEMENT_POINT_RETURN(cd, iptr);
2557 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2558 M_LNGMOVE(s1, REG_RESULT_PACKED);
2559 goto nowperformreturn;
2561 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2564 REPLACEMENT_POINT_RETURN(cd, iptr);
2565 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2566 M_FLTMOVE(s1, REG_FRESULT);
2567 goto nowperformreturn;
2569 case ICMD_RETURN: /* ... ==> ... */
2571 REPLACEMENT_POINT_RETURN(cd, iptr);
2577 p = cd->stackframesize;
2579 /* call trace function */
2581 #if !defined(NDEBUG)
2582 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2583 emit_verbosecall_exit(jd);
2584 #endif /* !defined(NDEBUG) */
2586 #if defined(ENABLE_THREADS)
2587 if (checksync && code_is_synchronized(code)) {
2588 /* we need to save the proper return value */
2590 switch (iptr->opc) {
2592 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2596 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2599 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2602 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2606 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2608 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2609 M_ALD_DSEG(REG_ITMP2, disp);
2611 M_ASUB_IMM(96, REG_SP);
2613 M_AADD_IMM(96, REG_SP);
2615 /* and now restore the proper return value */
2617 switch (iptr->opc) {
2619 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2623 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2626 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2629 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2635 /* restore return address */
2637 p--; M_ALD(REG_RA, REG_SP, p * 8);
2639 /* restore saved registers */
2641 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2642 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2644 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2645 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2648 /* deallocate stack */
2650 if (cd->stackframesize)
2651 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2653 /* generate method profiling code */
2661 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2664 branch_target_t *table;
2666 table = iptr->dst.table;
2668 l = iptr->sx.s23.s2.tablelow;
2669 i = iptr->sx.s23.s3.tablehigh;
2671 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2672 M_INTMOVE(s1, REG_ITMP1);
2676 } else if (N_VALID_IMM(-l)) {
2677 M_ISUB_IMM(l, REG_ITMP1);
2679 ICONST(REG_ITMP2, l);
2680 M_ISUB(REG_ITMP2, REG_ITMP1);
2683 /* number of targets */
2689 ICONST(REG_ITMP2, i);
2690 M_ICMPU(REG_ITMP1, REG_ITMP2);
2691 emit_bge(cd, table[0].block);
2693 /* build jump table top down and use address of lowest entry */
2698 dseg_add_target(cd, table->block);
2703 /* length of dataseg after last dseg_add_target is used by load */
2705 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2706 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2707 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2708 M_JMP(RN, REG_ITMP1);
2713 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2716 lookup_target_t *lookup;
2718 lookup = iptr->dst.lookup;
2720 i = iptr->sx.s23.s2.lookupcount;
2722 MCODECHECK(8 + ((7 + 6) * i) + 5);
2723 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2726 if (N_VALID_IMM(lookup->value)) {
2727 M_ICMP_IMM(s1, lookup->value);
2729 ICONST(REG_ITMP2, lookup->value);
2730 M_ICMP(REG_ITMP2, s1);
2732 emit_beq(cd, lookup->target.block);
2736 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2741 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2743 bte = iptr->sx.s23.s3.bte;
2747 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2748 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2749 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2750 case ICMD_INVOKEINTERFACE:
2752 REPLACEMENT_POINT_INVOKE(cd, iptr);
2754 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2756 um = iptr->sx.s23.s3.um;
2757 md = um->methodref->parseddesc.md;
2760 lm = iptr->sx.s23.s3.fmiref->p.method;
2762 md = lm->parseddesc;
2766 s3 = md->paramcount;
2768 MCODECHECK((s3 << 1) + 64);
2770 /* copy arguments to registers or stack location */
2772 for (s3 = s3 - 1; s3 >= 0; s3--) {
2773 var = VAR(iptr->sx.s23.s2.args[s3]);
2775 /* Already Preallocated? */
2776 if (var->flags & PREALLOC)
2779 if (IS_INT_LNG_TYPE(var->type)) {
2780 if (!md->params[s3].inmemory) {
2781 if (IS_2_WORD_TYPE(var->type)) {
2783 GET_LOW_REG(md->params[s3].regoff),
2784 GET_HIGH_REG(md->params[s3].regoff)
2786 d = emit_load(jd, iptr, var, s1);
2790 s1 = md->params[s3].regoff;
2791 d = emit_load(jd, iptr, var, s1);
2796 if (IS_2_WORD_TYPE(var->type)) {
2797 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2798 M_LST(d, REG_SP, md->params[s3].regoff);
2801 d = emit_load(jd, iptr, var, REG_ITMP1);
2802 M_IST(d, REG_SP, md->params[s3].regoff);
2807 if (!md->params[s3].inmemory) {
2808 s1 = md->params[s3].regoff;
2809 d = emit_load(jd, iptr, var, s1);
2813 d = emit_load(jd, iptr, var, REG_FTMP1);
2814 if (IS_2_WORD_TYPE(var->type))
2815 M_DST(d, REG_SP, md->params[s3].regoff);
2817 M_FST(d, REG_SP, md->params[s3].regoff);
2822 /* generate method profiling code */
2826 switch (iptr->opc) {
2828 if (bte->stub == NULL) {
2829 disp = dseg_add_functionptr(cd, bte->fp);
2830 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2832 disp = dseg_add_functionptr(cd, bte->stub);
2835 if (N_VALID_DSEG_DISP(disp)) {
2836 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2838 N_LHI(REG_ITMP1, disp);
2839 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2843 case ICMD_INVOKESPECIAL:
2845 /* Implicit NULL pointer check */
2846 M_ILD(REG_ITMP1, REG_A0, 0);
2850 case ICMD_INVOKESTATIC:
2852 disp = dseg_add_unique_address(cd, um);
2854 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2858 disp = dseg_add_address(cd, lm->stubroutine);
2860 if (N_VALID_DSEG_DISP(disp)) {
2861 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2863 N_LHI(REG_ITMP1, disp);
2864 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2868 case ICMD_INVOKEVIRTUAL:
2869 /* TODO softnull REG_A0 */
2872 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2877 s1 = OFFSET(vftbl_t, table[0]) +
2878 sizeof(methodptr) * lm->vftblindex;
2881 /* implicit null-pointer check */
2883 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2884 M_ALD(REG_PV, REG_METHODPTR, s1);
2887 case ICMD_INVOKEINTERFACE:
2888 /* TODO softnull REG_A0 */
2890 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2891 * and -0xFFF in index register (itmp1)
2895 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2901 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2902 sizeof(methodptr*) * lm->clazz->index;
2904 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2907 /* Implicit null-pointer check */
2908 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2909 N_LHI(REG_ITMP2, s1);
2910 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2911 M_ALD(REG_PV, REG_METHODPTR, s2);
2915 /* generate the actual call */
2918 emit_restore_pv(cd);
2920 /* post call finalization */
2922 switch (iptr->opc) {
2924 if (bte->stub == NULL) {
2925 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2930 /* generate method profiling code */
2932 PROFILE_CYCLE_START;
2934 /* store size of call code in replacement point */
2936 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2938 /* store return value */
2940 d = md->returntype.type;
2942 if (d != TYPE_VOID) {
2943 if (IS_INT_LNG_TYPE(d)) {
2944 if (IS_2_WORD_TYPE(d)) {
2945 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2946 M_LNGMOVE(REG_RESULT_PACKED, s1);
2949 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2950 M_INTMOVE(REG_RESULT, s1);
2954 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2955 M_FLTMOVE(REG_FRESULT, s1);
2957 emit_store_dst(jd, iptr, s1);
2963 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2965 /* val.a: (classinfo*) superclass */
2967 /* superclass is an interface:
2969 * OK if ((sub == NULL) ||
2970 * (sub->vftbl->interfacetablelength > super->index) &&
2971 * (sub->vftbl->interfacetable[-super->index] != NULL));
2973 * superclass is a class:
2975 * OK if ((sub == NULL) || (0
2976 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2977 * super->vftbl->diffval));
2980 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2981 /* object type cast-check */
2984 vftbl_t *supervftbl;
2987 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2988 # define LABEL_CLASS BRANCH_LABEL_2
2989 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2990 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2991 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2993 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2999 super = iptr->sx.s23.s3.c.cls;
3000 superindex = super->index;
3001 supervftbl = super->vftbl;
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 /* REG_ITMP3 := baseval(s1) */
3082 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3083 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3085 /* REG_ITMP2 := baseval(class) */
3086 M_ALD_DSEG(REG_ITMP2, disp);
3087 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3089 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3090 M_ISUB(REG_ITMP2, REG_ITMP3);
3092 /* REG_ITMP2 := diffval(class) */
3093 M_ALD_DSEG(REG_ITMP2, disp);
3094 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3096 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3098 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3099 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3100 /* Branch if greater then */
3102 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3103 M_ALD_DSEG(REG_ITMP3, disp);
3105 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3106 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3107 M_ISUB(REG_ITMP3, REG_ITMP2);
3108 M_ALD_DSEG(REG_ITMP3, disp);
3109 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3111 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3112 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3113 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3114 /* Branch if greater then */
3116 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3119 if (super == NULL) {
3120 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3121 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3122 } else if (super->flags & ACC_INTERFACE) {
3123 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3125 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3128 d = codegen_reg_of_dst(jd, iptr, s1);
3130 # undef LABEL_EXIT_CHECK_NULL
3132 # undef LABEL_EXIT_INTERFACE_NULL
3133 # undef LABEL_EXIT_INTERFACE_DONE
3134 # undef LABEL_EXIT_CLASS_NULL
3137 /* array type cast-check */
3139 s1 = emit_load_s1(jd, iptr, REG_A0);
3140 M_INTMOVE(s1, REG_A0);
3142 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3143 disp = dseg_add_unique_address(cd, NULL);
3145 patcher_add_patch_ref(jd,
3146 PATCHER_resolve_classref_to_classinfo,
3147 iptr->sx.s23.s3.c.ref,
3151 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3153 M_ALD_DSEG(REG_A1, disp);
3154 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3155 M_ALD_DSEG(REG_ITMP1, disp);
3156 M_ASUB_IMM(96, REG_SP);
3157 M_JSR(REG_RA, REG_ITMP1);
3158 M_AADD_IMM(96, REG_SP);
3160 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3161 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3163 d = codegen_reg_of_dst(jd, iptr, s1);
3167 emit_store_dst(jd, iptr, d);
3170 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3171 /* val.a: (classinfo*) superclass */
3173 /* superclass is an interface:
3175 * return (sub != NULL) &&
3176 * (sub->vftbl->interfacetablelength > super->index) &&
3177 * (sub->vftbl->interfacetable[-super->index] != NULL);
3179 * superclass is a class:
3181 * return ((sub != NULL) && (0
3182 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3183 * super->vftbl->diffvall));
3185 * If superclass is unresolved, we include both code snippets
3186 * above, a patcher resolves the class' flags and we select
3187 * the right code at runtime.
3192 vftbl_t *supervftbl;
3195 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3201 super = iptr->sx.s23.s3.c.cls;
3202 superindex = super->index;
3203 supervftbl = super->vftbl;
3206 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3207 # define LABEL_CLASS BRANCH_LABEL_2
3208 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3209 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3210 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3211 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3213 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3214 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3216 M_MOV(s1, REG_ITMP1);
3220 /* if class is not resolved, check which code to call */
3222 if (super == NULL) {
3226 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3228 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3230 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3231 iptr->sx.s23.s3.c.ref, disp);
3233 ICONST(REG_ITMP3, ACC_INTERFACE);
3235 if (N_VALID_DSEG_DISP(disp)) {
3236 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3238 ICONST(REG_ITMP2, disp);
3239 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3242 emit_label_beq(cd, LABEL_CLASS);
3245 /* interface instanceof code */
3247 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3248 if (super == NULL) {
3249 /* If d == REG_ITMP2, then it's destroyed in check
3254 patcher_add_patch_ref(jd,
3255 PATCHER_checkcast_instanceof_interface,
3256 iptr->sx.s23.s3.c.ref, 0);
3261 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3264 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3265 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3266 M_ISUB_IMM(superindex, REG_ITMP3);
3268 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3272 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3273 superindex * sizeof(methodptr*))
3275 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3277 /* d := (REG_ITMP1 != 0) */
3279 N_LTR(d, REG_ITMP1);
3280 M_BEQ(SZ_BRC + SZ_LHI);
3283 if (super == NULL) {
3284 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3288 /* class instanceof code */
3290 if (super == NULL) {
3291 emit_label(cd, LABEL_CLASS);
3294 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3295 if (super == NULL) {
3296 disp = dseg_add_unique_address(cd, NULL);
3298 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3299 iptr->sx.s23.s3.c.ref,
3303 disp = dseg_add_address(cd, supervftbl);
3308 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3311 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3312 M_ALD_DSEG(REG_ITMP2, disp);
3314 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3315 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3316 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3318 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3320 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3322 M_BGT(SZ_BRC + SZ_LHI);
3326 if (super == NULL) {
3327 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3328 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3329 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3330 } else if (super->flags & ACC_INTERFACE) {
3331 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3332 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3334 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3337 # undef LABEL_EXIT_CHECK_NULL
3339 # undef LABEL_EXIT_INTERFACE_NULL
3340 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3341 # undef LABEL_EXIT_INTERFACE_DONE
3342 # undef LABEL_EXIT_CLASS_NULL
3344 emit_store_dst(jd, iptr, d);
3350 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3352 /* check for negative sizes and copy sizes to stack if necessary */
3354 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3357 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3359 /* copy SAVEDVAR sizes to stack */
3360 var = VAR(iptr->sx.s23.s2.args[s1]);
3362 /* Already Preallocated? */
3363 if (!(var->flags & PREALLOC)) {
3364 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3365 M_IST(s2, REG_SP, s1 * 4);
3369 /* is a patcher function set? */
3371 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3372 disp = dseg_add_unique_address(cd, 0);
3374 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3375 iptr->sx.s23.s3.c.ref,
3379 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3381 /* a0 = dimension count */
3383 ICONST(REG_A0, iptr->s1.argcount);
3385 /* a1 = classinfo */
3387 M_ALD_DSEG(REG_A1, disp);
3389 /* a2 = pointer to dimensions = stack pointer */
3391 M_MOV(REG_SP, REG_A2);
3393 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3394 M_ALD_DSEG(REG_ITMP1, disp);
3395 M_ASUB_IMM(96, REG_SP);
3396 M_JSR(REG_RA, REG_ITMP1);
3397 M_AADD_IMM(96, REG_SP);
3399 /* check for exception before result assignment */
3401 emit_exception_check(cd, iptr);
3403 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3404 M_INTMOVE(REG_RESULT, s1);
3405 emit_store_dst(jd, iptr, s1);
3410 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3414 } /* for instruction */
3416 MCODECHECK(512); /* XXX require a lower number? */
3418 /* At the end of a basic block we may have to append some nops,
3419 because the patcher stub calling code might be longer than the
3420 actual instruction. So codepatching does not change the
3421 following block unintentionally. */
3423 if (cd->mcodeptr < cd->lastmcodeptr) {
3424 while (cd->mcodeptr < cd->lastmcodeptr) {
3429 } /* if (bptr -> flags >= BBREACHED) */
3430 } /* for basic block */
3432 /* generate stubs */
3434 emit_patcher_traps(jd);
3436 /* everything's ok */
3441 /* codegen_emit_stub_native ****************************************************
3443 Emits a stub routine which calls a native method.
3445 *******************************************************************************/
3448 arguments on stack \
3449 -------------------------------------------------| <- SP on nativestub entry
3451 callee saved int regs (none) |
3452 callee saved float regs (none) | stack frame like in cacao
3453 local variable slots (none) |
3454 arguments for calling methods (none) /
3455 ------------------------------------------------------------------ <- datasp
3460 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3461 0 - 96 register save area for callee /
3462 -------------------------------------------------------- <- SP native method
3464 SP after method entry
3467 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3478 /* get required compiler data */
3484 /* set some variables */
3488 /* calculate stackframe size */
3490 cd->stackframesize =
3491 1 + /* return address */
3492 sizeof(stackframeinfo_t) / 8 +
3493 sizeof(localref_table) / 8 +
3496 (96 / 8); /* linkage area */
3498 /* keep stack 8-byte aligned */
3500 /*ALIGN_2(cd->stackframesize);*/
3502 /* create method header */
3504 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3505 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3506 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3507 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3508 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3512 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3513 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3515 /* store return address */
3517 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3519 #if defined(ENABLE_GC_CACAO)
3520 /* Save callee saved integer registers in stackframeinfo (GC may
3521 need to recover them during a collection). */
3523 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3524 OFFSET(stackframeinfo_t, intregs);
3526 for (i = 0; i < INT_SAV_CNT; i++)
3527 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3530 /* save integer and float argument registers */
3532 for (i = 0; i < md->paramcount; i++) {
3533 if (!md->params[i].inmemory) {
3534 s1 = md->params[i].regoff;
3536 switch (md->paramtypes[i].type) {
3539 M_IST(s1, REG_SP, 96 + i * 8);
3542 M_LST(s1, REG_SP, 96 + i * 8);
3546 M_DST(s1, REG_SP, 96 + i * 8);
3552 /* create native stack info */
3554 M_MOV(REG_SP, REG_A0);
3555 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3556 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3557 M_ALD_DSEG(REG_ITMP2, disp);
3560 /* remember class argument */
3562 if (m->flags & ACC_STATIC)
3563 M_MOV(REG_RESULT, REG_ITMP3);
3565 /* restore integer and float argument registers */
3567 for (i = 0; i < md->paramcount; i++) {
3568 if (!md->params[i].inmemory) {
3569 s1 = md->params[i].regoff;
3571 switch (md->paramtypes[i].type) {
3574 M_ILD(s1, REG_SP, 96 + i * 8);
3577 M_LLD(s1, REG_SP, 96 + i * 8);
3581 M_DLD(s1, REG_SP, 96 + i * 8);
3587 /* copy or spill arguments to new locations */
3589 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3590 t = md->paramtypes[i].type;
3592 if (IS_INT_LNG_TYPE(t)) {
3593 if (!md->params[i].inmemory) {
3594 s1 = md->params[i].regoff;
3595 s2 = nmd->params[j].regoff;
3597 if (!nmd->params[j].inmemory) {
3598 if (IS_2_WORD_TYPE(t))
3604 if (IS_2_WORD_TYPE(t))
3605 M_LST(s1, REG_SP, s2);
3607 M_IST(s1, REG_SP, s2);
3611 s1 = md->params[i].regoff + cd->stackframesize * 8;
3612 s2 = nmd->params[j].regoff;
3614 if (IS_2_WORD_TYPE(t)) {
3615 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3617 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3622 /* We only copy spilled float arguments, as the float
3623 argument registers keep unchanged. */
3625 if (md->params[i].inmemory) {
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);
3638 /* Handle native Java methods. */
3640 if (m->flags & ACC_NATIVE) {
3641 /* put class into second argument register */
3643 if (m->flags & ACC_STATIC)
3644 M_MOV(REG_ITMP3, REG_A1);
3646 /* put env into first argument register */
3648 disp = dseg_add_address(cd, VM_get_jnienv());
3649 M_ALD_DSEG(REG_A0, disp);
3652 /* Call native function. */
3654 disp = dseg_add_functionptr(cd, f);
3655 M_ALD_DSEG(REG_ITMP2, disp);
3658 /* save return value */
3660 switch (md->returntype.type) {
3663 M_IST(REG_RESULT, REG_SP, 96);
3666 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3670 M_DST(REG_FRESULT, REG_SP, 96);
3676 /* remove native stackframe info */
3678 M_MOV(REG_SP, REG_A0);
3679 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3680 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3681 M_ALD_DSEG(REG_ITMP1, disp);
3684 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3686 /* restore return value */
3688 switch (md->returntype.type) {
3691 M_ILD(REG_RESULT, REG_SP, 96);
3694 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3698 M_DLD(REG_FRESULT, REG_SP, 96);
3704 #if defined(ENABLE_GC_CACAO)
3705 /* Restore callee saved integer registers from stackframeinfo (GC
3706 might have modified them during a collection). */
3708 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3709 OFFSET(stackframeinfo_t, intregs);
3711 for (i = 0; i < INT_SAV_CNT; i++)
3712 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3715 /* load return address */
3717 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3719 /* remove stackframe */
3721 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3723 /* check for exception */
3725 M_TEST(REG_ITMP3_XPTR);
3726 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3730 /* handle exception */
3732 M_MOV(REG_RA, REG_ITMP1_XPC);
3733 M_ASUB_IMM(2, REG_ITMP1_XPC);
3735 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3736 M_ALD_DSEG(REG_ITMP2, disp);
3737 M_JMP(RN, REG_ITMP2);
3741 * These are local overrides for various environment variables in Emacs.
3742 * Please do not remove this and leave it at the end of the file, where
3743 * Emacs will automagically detect them.
3744 * ---------------------------------------------------------------------
3747 * indent-tabs-mode: t
3751 * vim:noexpandtab:sw=4:ts=4: