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/localref.hpp"
38 #include "native/native.hpp"
40 #include "mm/memory.hpp"
42 #include "threads/lock.hpp"
44 #include "vm/jit/builtin.hpp"
45 #include "vm/exceptions.hpp"
46 #include "vm/global.h"
47 #include "vm/loader.hpp"
48 #include "vm/options.h"
49 #include "vm/statistics.h"
53 #include "vm/jit/abi.h"
54 #if defined(ENABLE_LSRA)
55 # include "vm/jit/allocator/lsra.h"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/codegen-common.hpp"
59 #include "vm/jit/dseg.h"
60 #include "vm/jit/emit-common.hpp"
61 #include "vm/jit/jit.hpp"
62 #include "vm/jit/linenumbertable.hpp"
63 #include "vm/jit/methodheader.h"
64 #include "vm/jit/parse.hpp"
65 #include "vm/jit/patcher-common.hpp"
66 #include "vm/jit/reg.h"
67 #include "vm/jit/replace.hpp"
68 #include "vm/jit/stacktrace.hpp"
69 #include "vm/jit/trap.hpp"
72 /* DO__LOG generates a call to do__log. No registers are destroyed,
73 * so you may use it anywhere. regs is an array containing all general
78 static void do__log(u4 *regs) {
83 N_AHI(REG_SP, -200); \
84 N_STM(R0, R15, 96, REG_SP); \
85 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
86 N_LA(R2, 96, RN, REG_SP); \
88 N_LM(R0, R15, 96, REG_SP); \
91 /* If the following macro is defined, workaround code for hercules quirks
95 /* #define SUPPORT_HERCULES 1 */
97 /* codegen *********************************************************************
99 Generates machine code.
101 *******************************************************************************/
105 Layout of stackframe:
108 ===============================================================================
109 return_address (stackframesize - 1) * 8
110 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
112 saved_int_reg[rd->savintreguse]
113 saved_flt_reg[FLT_SAV_CNT - 1]
115 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
117 return_value_tmp (rd->memuse + 1) * 8
118 monitorenter_argument (rd->memuse) * 8
120 local[rd->memuse - 1] (rd->memuse - 1) * 8
128 bool codegen_emit(jitdata *jd)
134 s4 len, s1, s2, s3, d, dd, disp;
139 constant_classref *cr;
140 unresolved_class *uc;
141 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
142 unresolved_method *um;
143 builtintable_entry *bte;
146 unresolved_field *uf;
149 rplpoint *replacementpoint;
153 /* get required compiler data */
160 /* prevent compiler warnings */
173 /* space to save used callee saved registers */
175 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
176 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
178 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
181 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
184 #if defined(ENABLE_THREADS)
185 /* Space to save argument of monitor_enter and Return Values to
186 survive monitor_exit. The stack position for the argument can
187 not be shared with place to save the return register
188 since both values reside in R2. */
190 if (checksync && code_is_synchronized(code)) {
191 /* 1 slot space to save argument of monitor_enter */
192 /* 1 slot to temporary store return value before monitor_exit */
193 cd->stackframesize += 2;
197 /* Keep stack of non-leaf functions 16-byte aligned for calls into
198 native code e.g. libc or jni (alignment problems with
201 if (!code_is_leafmethod(code) || opt_verbosecall )
202 /* TODO really 16 bytes ? */
203 cd->stackframesize = (cd->stackframesize + 2) & ~2;
205 /* create method header */
207 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
208 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
210 code->synchronizedoffset = rd->memuse * 8;
212 /* REMOVEME: We still need it for exception handling in assembler. */
214 if (code_is_leafmethod(code))
215 (void) dseg_add_unique_s4(cd, 1);
217 (void) dseg_add_unique_s4(cd, 0);
219 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
220 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
224 M_AADD_IMM(N_PV_OFFSET, REG_PV);
226 /* create stack frame (if necessary) */
228 if (cd->stackframesize) {
229 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
232 /* store return address */
234 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
236 /* generate method profiling code */
238 #if defined(ENABLE_PROFILING)
239 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
240 /* count frequency */
241 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
242 ICONST(REG_ITMP2, 1);
243 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
244 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
250 /* save used callee saved registers and return address */
252 p = cd->stackframesize - 1;
254 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
255 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
257 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
258 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
261 /* take arguments out of register or stack frame */
265 for (p = 0, l = 0; p < md->paramcount; p++) {
266 t = md->paramtypes[p].type;
267 varindex = jd->local_map[l * 5 + t];
271 if (IS_2_WORD_TYPE(t))
274 if (varindex == UNUSED)
279 s1 = md->params[p].regoff;
281 if (IS_INT_LNG_TYPE(t)) { /* integer args */
282 if (IS_2_WORD_TYPE(t)) {
290 if (!md->params[p].inmemory) { /* register arguments */
291 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
292 if (IS_2_WORD_TYPE(t)) {
293 M_LNGMOVE(s2, var->vv.regoff);
295 M_INTMOVE(s2, var->vv.regoff);
297 } else { /* reg arg -> spilled */
298 if (IS_2_WORD_TYPE(t)) {
299 M_LST(s2, REG_SP, var->vv.regoff);
301 M_IST(s2, REG_SP, var->vv.regoff);
305 } else { /* stack arguments */
306 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
307 if (IS_2_WORD_TYPE(t)) {
308 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
310 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
312 } else { /* stack arg -> spilled */
313 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
317 } else { /* floating args */
318 if (!md->params[p].inmemory) { /* register arguments */
320 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
321 M_FLTMOVE(s2, var->vv.regoff);
323 } else { /* reg arg -> spilled */
324 if (IS_2_WORD_TYPE(t))
325 M_DST(s2, REG_SP, var->vv.regoff);
327 M_FST(s2, REG_SP, var->vv.regoff);
330 } else { /* stack arguments */
331 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
332 if (IS_2_WORD_TYPE(t))
333 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
336 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
338 } else { /* stack-arg -> spilled */
339 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
340 var->vv.regoff = cd->stackframesize * 8 + s1;
346 /* save monitorenter argument */
348 #if defined(ENABLE_THREADS)
349 if (checksync && code_is_synchronized(code)) {
350 /* stack offset for monitor argument */
355 if (opt_verbosecall) {
356 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
358 for (p = 0; p < INT_ARG_CNT; p++)
359 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
361 for (p = 0; p < FLT_ARG_CNT; p++)
362 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
364 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
368 /* decide which monitor enter function to call */
370 if (m->flags & ACC_STATIC) {
371 disp = dseg_add_address(cd, &m->clazz->object.header);
372 M_ALD_DSEG(REG_A0, disp);
376 M_BNE(SZ_BRC + SZ_ILL);
377 M_ILL(TRAP_NullPointerException);
380 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
381 M_ALD_DSEG(REG_ITMP2, disp);
383 M_AST(REG_A0, REG_SP, s1 * 8);
385 M_ASUB_IMM(96, REG_SP);
387 M_AADD_IMM(96, REG_SP);
390 if (opt_verbosecall) {
391 for (p = 0; p < INT_ARG_CNT; p++)
392 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
394 for (p = 0; p < FLT_ARG_CNT; p++)
395 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
397 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
404 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
405 emit_verbosecall_enter(jd);
406 #endif /* !defined(NDEBUG) */
410 /* end of header generation */
412 /* create replacement points */
414 REPLACEMENT_POINTS_INIT(cd, jd);
416 /* walk through all basic blocks */
418 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
420 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
422 if (bptr->flags >= BBREACHED) {
424 /* branch resolving */
426 codegen_resolve_branchrefs(cd, bptr);
428 /* handle replacement points */
430 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
432 /* copy interface registers to their destination */
437 #if defined(ENABLE_PROFILING)
438 /* generate basicblock profiling code */
440 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
441 /* count frequency */
443 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
444 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
445 ICONST(REG_ITMP2, 1);
446 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
447 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
449 /* if this is an exception handler, start profiling again */
451 if (bptr->type == BBTYPE_EXH)
456 #if defined(ENABLE_LSRA)
460 src = bptr->invars[len];
461 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
462 if (bptr->type == BBTYPE_EXH) {
463 /* d = reg_of_var(rd, src, REG_ITMP1); */
464 if (!IS_INMEMORY(src->flags))
468 M_INTMOVE(REG_ITMP3_XPTR, d);
469 emit_store(jd, NULL, src, d);
479 var = VAR(bptr->invars[len]);
480 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
481 if (bptr->type == BBTYPE_EXH) {
482 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
483 M_INTMOVE(REG_ITMP3_XPTR, d);
484 emit_store(jd, NULL, var, d);
488 assert((var->flags & INOUT));
491 #if defined(ENABLE_LSRA)
494 /* walk through all instructions */
499 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
500 if (iptr->line != currentline) {
501 linenumbertable_list_entry_add(cd, iptr->line);
502 currentline = iptr->line;
505 MCODECHECK(1024); /* 1KB should be enough */
508 case ICMD_NOP: /* ... ==> ... */
509 case ICMD_POP: /* ..., value ==> ... */
510 case ICMD_POP2: /* ..., value, value ==> ... */
513 case ICMD_INLINE_START:
515 REPLACEMENT_POINT_INLINE_START(cd, iptr);
518 case ICMD_INLINE_BODY:
520 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
521 linenumbertable_list_entry_add_inline_start(cd, iptr);
522 linenumbertable_list_entry_add(cd, iptr->line);
525 case ICMD_INLINE_END:
527 linenumbertable_list_entry_add_inline_end(cd, iptr);
528 linenumbertable_list_entry_add(cd, iptr->line);
531 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
532 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
533 emit_nullpointer_check(cd, iptr, s1);
536 /* constant operations ************************************************/
538 case ICMD_ICONST: /* ... ==> ..., constant */
539 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
540 ICONST(d, iptr->sx.val.i);
541 emit_store_dst(jd, iptr, d);
544 case ICMD_LCONST: /* ... ==> ..., constant */
546 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
547 LCONST(d, iptr->sx.val.l);
548 emit_store_dst(jd, iptr, d);
551 case ICMD_FCONST: /* ... ==> ..., constant */
552 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
553 disp = dseg_add_float(cd, iptr->sx.val.f);
554 M_FLD_DSEG(d, disp, REG_ITMP1);
555 emit_store_dst(jd, iptr, d);
558 case ICMD_DCONST: /* ... ==> ..., constant */
559 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
560 disp = dseg_add_double(cd, iptr->sx.val.d);
561 M_DLD_DSEG(d, disp, REG_ITMP1);
562 emit_store_dst(jd, iptr, d);
565 case ICMD_ACONST: /* ... ==> ..., constant */
566 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
568 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
569 cr = iptr->sx.val.c.ref;
570 disp = dseg_add_unique_address(cd, cr);
572 /* PROFILE_CYCLE_STOP; */
574 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
577 /* PROFILE_CYCLE_START; */
581 if (iptr->sx.val.anyptr == 0) {
584 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
587 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
588 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
590 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
592 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
598 emit_store_dst(jd, iptr, d);
602 /* load/store/copy/move operations ************************************/
604 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
605 case ICMD_ALOAD: /* s1 = local variable */
609 case ICMD_ISTORE: /* ..., value ==> ... */
620 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
624 /* integer operations *************************************************/
626 case ICMD_INEG: /* ..., value ==> ..., - value */
628 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
629 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
631 emit_store_dst(jd, iptr, d);
635 case ICMD_LNEG: /* ..., value ==> ..., - value */
637 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
638 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
639 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
640 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
641 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
642 N_AHI(GET_HIGH_REG(d), -1);
643 emit_store_dst(jd, iptr, d);
646 case ICMD_I2L: /* ..., value ==> ..., value */
648 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
649 if (! N_IS_EVEN_ODD(d)) {
650 d = REG_ITMP31_PACKED;
652 assert(N_IS_EVEN_ODD(d));
654 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
656 M_INTMOVE(s1, GET_HIGH_REG(d));
657 M_SRDA_IMM(32, GET_HIGH_REG(d));
659 emit_copy_dst(jd, iptr, d);
660 emit_store_dst(jd, iptr, d);
663 case ICMD_L2I: /* ..., value ==> ..., value */
664 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
665 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
666 M_INTMOVE(GET_LOW_REG(s1), d);
667 emit_store_dst(jd, iptr, d);
670 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
671 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
672 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
676 emit_store_dst(jd, iptr, d);
679 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
680 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
681 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
685 emit_store_dst(jd, iptr, d);
688 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
690 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
691 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
695 emit_store_dst(jd, iptr, d);
698 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
700 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
701 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
702 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
709 emit_store_dst(jd, iptr, d);
714 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
715 /* sx.val.i = constant */
716 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
717 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
720 if (N_VALID_IMM(iptr->sx.val.i)) {
721 M_IADD_IMM(iptr->sx.val.i, d);
723 ICONST(REG_ITMP2, iptr->sx.val.i);
724 M_IADD(REG_ITMP2, d);
726 emit_store_dst(jd, iptr, d);
729 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
731 /* M, (r, q) -> (r, q) */
733 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
735 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
736 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
737 dd = GET_HIGH_REG(d);
746 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
747 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
757 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
758 N_AHI(GET_HIGH_REG(d), 1);
760 emit_store_dst(jd, iptr, d);
763 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
764 /* sx.val.l = constant */
766 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
767 dd = GET_HIGH_REG(d);
769 s1 = emit_load_s1_high(jd, iptr, dd);
770 s3 = iptr->sx.val.l >> 32;
774 if (N_VALID_IMM(s3)) {
777 ICONST(REG_ITMP3, s3);
778 M_IADD(REG_ITMP3, dd);
782 s1 = emit_load_s1_low(jd, iptr, dd);
783 s3 = iptr->sx.val.l & 0xffffffff;
784 ICONST(REG_ITMP3, s3);
787 N_ALR(dd, REG_ITMP3);
789 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
790 N_AHI(GET_HIGH_REG(d), 1);
792 emit_store_dst(jd, iptr, d);
795 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
797 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
798 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
799 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
801 M_INTMOVE(s1, REG_ITMP1);
802 M_ISUB(s2, REG_ITMP1);
803 M_INTMOVE(REG_ITMP1, d);
808 emit_store_dst(jd, iptr, d);
812 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
813 /* sx.val.i = constant */
815 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
816 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
819 if (N_VALID_IMM(-iptr->sx.val.i)) {
820 M_ISUB_IMM(iptr->sx.val.i, d);
822 ICONST(REG_ITMP2, iptr->sx.val.i);
823 M_ISUB(REG_ITMP2, d);
825 emit_store_dst(jd, iptr, d);
829 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
831 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
833 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
834 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
835 dd = GET_HIGH_REG(d);
838 M_INTMOVE(s2, REG_ITMP3);
845 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
846 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
850 M_INTMOVE(s2, REG_ITMP3);
857 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
858 N_AHI(GET_HIGH_REG(d), -1);
860 emit_store_dst(jd, iptr, d);
863 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
864 /* sx.val.l = constant */
866 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
868 dd = GET_HIGH_REG(d);
869 s1 = emit_load_s1_high(jd, iptr, dd);
870 s3 = iptr->sx.val.l >> 32;
874 if (N_VALID_IMM(-s3)) {
877 ICONST(REG_ITMP3, s3);
878 M_ISUB(REG_ITMP3, dd);
882 s1 = emit_load_s1_low(jd, iptr, dd);
883 s3 = iptr->sx.val.l & 0xffffffff;
884 ICONST(REG_ITMP3, s3);
887 N_SLR(dd, REG_ITMP3);
889 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
890 N_AHI(GET_HIGH_REG(d), -1);
892 emit_store_dst(jd, iptr, d);
895 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
897 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
898 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
899 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
906 emit_store_dst(jd, iptr, d);
910 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
911 /* sx.val.i = constant */
912 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
913 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
915 if (iptr->sx.val.i == 2) {
917 } else if (N_VALID_IMM(iptr->sx.val.i)) {
918 M_IMUL_IMM(iptr->sx.val.i, d);
920 disp = dseg_add_s4(cd, iptr->sx.val.i);
921 M_ILD_DSEG(REG_ITMP2, disp);
922 M_IMUL(REG_ITMP2, d);
924 emit_store_dst(jd, iptr, d);
927 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
928 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
930 /* load s1 into r0 */
932 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
933 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
934 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
936 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
938 /* extend s1 to long */
940 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
944 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
950 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
951 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
954 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
955 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
959 emit_store_dst(jd, iptr, d);
963 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
964 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
966 bte = iptr->sx.s23.s3.bte;
969 /* test s2 for zero */
971 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
972 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
973 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
974 emit_arithmetic_check(cd, iptr, REG_ITMP3);
978 disp = dseg_add_functionptr(cd, bte->fp);
982 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
984 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
985 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
989 M_ASUB_IMM(96, REG_SP);
990 M_ALD_DSEG(REG_ITMP2, disp);
991 M_JSR(REG_RA, REG_ITMP2);
992 M_AADD_IMM(96, REG_SP);
996 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
997 M_LNGMOVE(REG_RESULT_PACKED, d);
998 emit_store_dst(jd, iptr, d);
1002 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1003 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1004 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1006 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1007 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1008 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1010 /* Use only 5 bits of sencond operand. */
1012 M_INTMOVE(s2, REG_ITMP2);
1014 ICONST(REG_ITMP3, 0x1F);
1015 M_IAND(REG_ITMP3, s2);
1019 switch (iptr->opc) {
1032 emit_store_dst(jd, iptr, d);
1035 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1036 /* sx.val.i = constant */
1040 assert(iptr->sx.val.i <= 32);
1042 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1043 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1050 s3 = (1 << iptr->sx.val.i) - 1;
1052 if (N_VALID_IMM(s3)) {
1055 ICONST(REG_ITMP1, -1);
1056 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1057 M_IADD(REG_ITMP1, d);
1060 N_BRC_BACK_PATCH(ref);
1062 M_SRA_IMM(iptr->sx.val.i, d);
1064 emit_store_dst(jd, iptr, d);
1069 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1070 /* sx.val.i = constant */
1072 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1073 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1076 M_MOV(s1, REG_ITMP1);
1080 ICONST(REG_ITMP3, iptr->sx.val.i);
1083 M_IAND(REG_ITMP3, d);
1086 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1092 emit_store_dst(jd, iptr, d);
1096 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1097 /* sx.val.i = constant */
1098 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1099 /* sx.val.i = constant */
1100 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1101 /* sx.val.i = constant */
1102 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1103 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1107 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1109 switch (iptr->opc) {
1110 case ICMD_ISHLCONST:
1113 case ICMD_ISHRCONST:
1116 case ICMD_IUSHRCONST:
1123 emit_store_dst(jd, iptr, d);
1126 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1128 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1130 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1132 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1134 /* Use only 6 bits of second operand */
1136 M_INTMOVE(s2, REG_ITMP2);
1138 ICONST(REG_ITMP1, 0x3F);
1139 M_IAND(REG_ITMP1, s2);
1141 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1142 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1144 /* Destination must be even-odd pair */
1146 if (! N_IS_EVEN_ODD(d)) {
1147 d = REG_ITMP31_PACKED;
1150 assert(N_IS_EVEN_ODD(d));
1154 switch (iptr->opc) {
1156 M_SLDL(s2, GET_HIGH_REG(d));
1159 M_SRDA(s2, GET_HIGH_REG(d));
1162 M_SRDL(s2, GET_HIGH_REG(d));
1168 emit_copy_dst(jd, iptr, d);
1169 emit_store_dst(jd, iptr, d);
1173 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1174 /* sx.val.i = constant */
1175 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1176 /* sx.val.i = constant */
1177 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1178 /* sx.val.l = constant */
1181 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1182 if (! N_IS_EVEN_ODD(d)) {
1183 d = REG_ITMP31_PACKED;
1185 assert(N_IS_EVEN_ODD(d));
1187 s1 = emit_load_s1(jd, iptr, d);
1191 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1193 switch (iptr->opc) {
1194 case ICMD_LSHLCONST:
1195 N_SLDL(GET_HIGH_REG(d), disp, RN);
1197 case ICMD_LSHRCONST:
1198 N_SRDA(GET_HIGH_REG(d), disp, RN);
1200 case ICMD_LUSHRCONST:
1201 N_SRDL(GET_HIGH_REG(d), disp, RN);
1204 N_SLDL(GET_HIGH_REG(d), disp, RN);
1210 emit_copy_dst(jd, iptr, d);
1211 emit_store_dst(jd, iptr, d);
1214 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1216 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1217 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1218 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1225 emit_store_dst(jd, iptr, d);
1229 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1231 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1232 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1233 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1240 emit_store_dst(jd, iptr, d);
1244 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1246 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1247 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1248 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1255 emit_store_dst(jd, iptr, d);
1261 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1262 /* sx.val.i = constant */
1263 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1264 /* sx.val.i = constant */
1265 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1266 /* sx.val.i = constant */
1268 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1269 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1272 ICONST(REG_ITMP2, iptr->sx.val.i);
1274 switch (iptr->opc) {
1275 case ICMD_IANDCONST:
1276 M_IAND(REG_ITMP2, d);
1278 case ICMD_IXORCONST:
1279 M_IXOR(REG_ITMP2, d);
1282 M_IOR(REG_ITMP2, d);
1288 emit_store_dst(jd, iptr, d);
1292 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1293 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1294 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1296 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1298 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1299 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1300 dd = GET_LOW_REG(d);
1302 switch (iptr->opc) {
1331 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1332 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1333 dd = GET_HIGH_REG(d);
1335 switch (iptr->opc) {
1364 emit_store_dst(jd, iptr, d);
1367 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1368 /* sx.val.l = constant */
1369 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1370 /* sx.val.l = constant */
1371 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1372 /* sx.val.l = constant */
1374 /* TODO should use memory operand to access data segment, not load */
1376 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1378 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1379 s3 = iptr->sx.val.l & 0xffffffff;
1381 M_INTMOVE(s1, GET_LOW_REG(d));
1383 ICONST(REG_ITMP3, s3);
1385 switch (iptr->opc) {
1386 case ICMD_LANDCONST:
1387 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1389 case ICMD_LXORCONST:
1390 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1393 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1399 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1400 s3 = iptr->sx.val.l >> 32;
1402 M_INTMOVE(s1, GET_HIGH_REG(d));
1404 ICONST(REG_ITMP3, s3);
1406 switch (iptr->opc) {
1407 case ICMD_LANDCONST:
1408 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1410 case ICMD_LXORCONST:
1411 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1414 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1420 emit_store_dst(jd, iptr, d);
1424 /* floating operations ************************************************/
1426 case ICMD_FNEG: /* ..., value ==> ..., - value */
1427 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1428 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1430 emit_store_dst(jd, iptr, d);
1433 case ICMD_DNEG: /* ..., value ==> ..., - value */
1434 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1435 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1437 emit_store_dst(jd, iptr, d);
1440 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1441 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1442 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1443 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1450 emit_store_dst(jd, iptr, d);
1453 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1454 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1455 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1456 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1463 emit_store_dst(jd, iptr, d);
1466 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1467 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1468 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1469 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1473 emit_store_dst(jd, iptr, d);
1476 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1477 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1478 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1479 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1483 emit_store_dst(jd, iptr, d);
1486 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1487 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1488 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1489 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1496 emit_store_dst(jd, iptr, d);
1499 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1500 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1501 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1502 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1509 emit_store_dst(jd, iptr, d);
1512 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1513 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1514 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1515 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1519 emit_store_dst(jd, iptr, d);
1522 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1523 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1524 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1525 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1529 emit_store_dst(jd, iptr, d);
1532 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1533 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1534 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1536 emit_store_dst(jd, iptr, d);
1539 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1540 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1541 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1543 emit_store_dst(jd, iptr, d);
1546 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1550 #ifdef SUPPORT_HERCULES
1554 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1555 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1559 switch (iptr->opc) {
1568 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1569 N_LHI(d, 0); /* Load 0 */
1570 ref1 = cd->mcodeptr;
1571 N_BRC(DD_ANY, 0); /* Exit */
1575 switch (iptr->opc) {
1584 #ifdef SUPPORT_HERCULES
1585 /* Hercules does the conversion using a plain C conversion.
1586 * According to manual, real hardware should *NOT* require this.
1588 * Corner case: Positive float leads to INT_MIN (overflow).
1591 switch (iptr->opc) {
1600 ref2 = cd->mcodeptr;
1601 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1605 ref3 = cd->mcodeptr;
1606 M_BGE(0); /* If integer result is negative, continue */
1608 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1609 M_ILD_DSEG(d, disp);
1611 N_BRC_BACK_PATCH(ref1);
1612 #ifdef SUPPORT_HERCULES
1613 N_BRC_BACK_PATCH(ref2);
1614 N_BRC_BACK_PATCH(ref3);
1616 emit_store_dst(jd, iptr, d);
1620 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1622 #ifdef SUPPORT_HERCULES
1625 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1626 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1627 #ifdef SUPPORT_HERCULES
1630 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1631 disp = dseg_add_double(cd, 0.0 / 0.0);
1632 M_DLD_DSEG(d, disp, REG_ITMP1);
1633 emit_label_br(cd, BRANCH_LABEL_1);
1634 N_BRC_BACK_PATCH(ref);
1637 #ifdef SUPPORT_HERCULES
1638 emit_label(cd, BRANCH_LABEL_1);
1640 emit_store_dst(jd, iptr, d);
1644 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1645 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1646 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1648 emit_store_dst(jd, iptr, d);
1651 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1652 /* == => 0, < => 1, > => -1 */
1656 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1657 /* == => 0, < => 1, > => -1 */
1660 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1661 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1662 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1664 switch (iptr->opc) {
1676 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1677 SZ_BRC + SZ_BRC + SZ_BRC
1680 N_BRC( /* load -1 */
1681 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1682 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1687 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1690 N_LHI(d, 1); /* GT */
1691 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1692 N_LHI(d, -1); /* LT */
1693 M_BR(SZ_BRC + SZ_LHI);
1694 N_LHI(d, 0); /* EQ */
1696 emit_store_dst(jd, iptr, d);
1701 /* memory operations **************************************************/
1703 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1705 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1706 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1708 /* implicit null-pointer check */
1709 M_ILD(d, s1, OFFSET(java_array_t, size));
1710 emit_store_dst(jd, iptr, d);
1714 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1715 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1716 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1717 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1719 /* implicit null-pointer check */
1720 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1722 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1727 emit_store_dst(jd, iptr, d);
1730 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1732 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1733 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1734 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1736 /* implicit null-pointer check */
1737 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1739 M_INTMOVE(s2, REG_ITMP2);
1740 M_SLL_IMM(1, REG_ITMP2);
1742 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1744 /* N_LH does sign extends, undo ! */
1749 emit_store_dst(jd, iptr, d);
1752 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1753 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1754 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1755 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1757 /* implicit null-pointer check */
1758 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1760 M_INTMOVE(s2, REG_ITMP2);
1761 M_SLL_IMM(1, REG_ITMP2);
1763 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1764 emit_store_dst(jd, iptr, d);
1767 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1768 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1769 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1770 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1772 /* implicit null-pointer check */
1773 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1775 M_INTMOVE(s2, REG_ITMP2);
1776 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1777 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1778 emit_store_dst(jd, iptr, d);
1781 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1783 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1784 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1786 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1788 /* implicit null-pointer check */
1789 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1791 M_INTMOVE(s2, REG_ITMP2);
1792 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1795 GET_LOW_REG(d) /* maybe itmp3 */,
1796 OFFSET(java_longarray_t, data[0]) + 4,
1797 REG_ITMP2, s1 /* maybe itmp1 */
1801 GET_HIGH_REG(d) /* maybe itmp1 */,
1802 OFFSET(java_longarray_t, data[0]),
1803 REG_ITMP2, s1 /* maybe itmp1 */
1806 emit_store_dst(jd, iptr, d);
1810 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1812 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1813 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1814 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1816 /* implicit null-pointer check */
1817 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1819 M_INTMOVE(s2, REG_ITMP2);
1820 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1822 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1824 emit_store_dst(jd, iptr, d);
1827 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1828 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1829 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1830 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1832 /* implicit null-pointer check */
1833 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1835 M_INTMOVE(s2, REG_ITMP2);
1836 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1838 N_LD(d, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1840 emit_store_dst(jd, iptr, d);
1843 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1844 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1845 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1846 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1848 /* implicit null-pointer check */
1849 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1851 M_INTMOVE(s2, REG_ITMP2);
1852 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1853 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1854 emit_store_dst(jd, iptr, d);
1857 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1858 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1859 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1860 /* implicit null-pointer check */
1861 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1862 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1864 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1867 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1869 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1870 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1871 /* implicit null-pointer check */
1872 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1873 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1875 M_INTMOVE(s2, REG_ITMP2);
1876 M_SLL_IMM(1, REG_ITMP2);
1878 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1882 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1883 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1884 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1885 /* implicit null-pointer check */
1886 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1887 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1889 M_INTMOVE(s2, REG_ITMP2);
1890 M_SLL_IMM(1, REG_ITMP2);
1892 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1895 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1897 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1898 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1899 /* implicit null-pointer check */
1900 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1902 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1904 M_INTMOVE(s2, REG_ITMP2);
1905 M_SLL_IMM(2, REG_ITMP2);
1907 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1910 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1912 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1913 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1914 /* implicit null-pointer check */
1915 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1917 M_INTMOVE(s2, REG_ITMP2);
1918 M_SLL_IMM(3, REG_ITMP2);
1920 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1921 N_ST(s3, OFFSET(java_longarray_t, data[0]), REG_ITMP2, s1);
1922 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1923 N_ST(s3, OFFSET(java_longarray_t, data[0]) + 4, REG_ITMP2, s1);
1926 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1927 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1928 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1929 /* implicit null-pointer check */
1930 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1931 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1933 M_INTMOVE(s2, REG_ITMP2);
1934 M_SLL_IMM(2, REG_ITMP2);
1936 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1939 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1940 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1941 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1942 /* implicit null-pointer check */
1943 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1944 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1946 M_INTMOVE(s2, REG_ITMP2);
1947 M_SLL_IMM(3, REG_ITMP2);
1949 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1952 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1954 s1 = emit_load_s1(jd, iptr, REG_A0);
1955 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1956 /* implicit null-pointer check */
1957 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1958 s3 = emit_load_s3(jd, iptr, REG_A1);
1960 M_INTMOVE(s1, REG_A0);
1961 M_INTMOVE(s3, REG_A1);
1963 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1964 M_ALD_DSEG(REG_ITMP2, disp);
1965 M_ASUB_IMM(96, REG_SP);
1966 M_JSR(REG_RA, REG_ITMP2);
1967 M_AADD_IMM(96, REG_SP);
1969 emit_arraystore_check(cd, iptr);
1971 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1972 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1973 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1975 M_INTMOVE(s2, REG_ITMP2);
1976 M_SLL_IMM(2, REG_ITMP2);
1977 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1980 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1981 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1986 case ICMD_GETSTATIC: /* ... ==> ..., value */
1988 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1989 uf = iptr->sx.s23.s3.uf;
1990 fieldtype = uf->fieldref->parseddesc.fd->type;
1991 disp = dseg_add_unique_address(cd, NULL);
1993 /* PROFILE_CYCLE_STOP; */
1995 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1997 /* PROFILE_CYCLE_START; */
2000 fi = iptr->sx.s23.s3.fmiref->p.field;
2001 fieldtype = fi->type;
2002 disp = dseg_add_address(cd, fi->value);
2004 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
2007 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
2009 PROFILE_CYCLE_START;
2013 M_ALD_DSEG(REG_ITMP1, disp);
2015 switch (fieldtype) {
2017 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2018 M_ILD(d, REG_ITMP1, 0);
2021 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2022 M_LLD(d, REG_ITMP1, 0);
2025 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2026 M_ALD(d, REG_ITMP1, 0);
2029 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2030 M_FLD(d, REG_ITMP1, 0);
2033 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2034 M_DLD(d, REG_ITMP1, 0);
2038 emit_store_dst(jd, iptr, d);
2042 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2044 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2045 uf = iptr->sx.s23.s3.uf;
2046 fieldtype = uf->fieldref->parseddesc.fd->type;
2047 disp = dseg_add_unique_address(cd, uf);
2049 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2052 fi = iptr->sx.s23.s3.fmiref->p.field;
2053 fieldtype = fi->type;
2054 disp = dseg_add_address(cd, fi->value);
2056 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
2058 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
2059 PROFILE_CYCLE_START;
2063 M_ALD_DSEG(REG_ITMP1, disp);
2064 switch (fieldtype) {
2066 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2067 M_IST(s1, REG_ITMP1, 0);
2070 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2071 M_LST(s1, REG_ITMP1, 0);
2074 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2075 M_AST(s1, REG_ITMP1, 0);
2078 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2079 M_FST(s1, REG_ITMP1, 0);
2082 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2083 M_DST(s1, REG_ITMP1, 0);
2088 case ICMD_GETFIELD: /* ... ==> ..., value */
2090 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2091 emit_nullpointer_check(cd, iptr, s1);
2093 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2094 uf = iptr->sx.s23.s3.uf;
2095 fieldtype = uf->fieldref->parseddesc.fd->type;
2098 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2101 fi = iptr->sx.s23.s3.fmiref->p.field;
2102 fieldtype = fi->type;
2106 switch (fieldtype) {
2108 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2112 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2113 if (GET_HIGH_REG(d) == s1) {
2114 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2115 M_ILD(GET_HIGH_REG(d), s1, disp);
2118 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2119 M_ILD(GET_HIGH_REG(d), s1, disp);
2123 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2127 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2131 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2135 emit_store_dst(jd, iptr, d);
2138 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2142 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2143 emit_nullpointer_check(cd, iptr, s1);
2145 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2146 uf = iptr->sx.s23.s3.uf;
2147 fieldtype = uf->fieldref->parseddesc.fd->type;
2151 fi = iptr->sx.s23.s3.fmiref->p.field;
2152 fieldtype = fi->type;
2156 /* We can't add a patcher ref behind this load,
2157 * because the patcher would destroy REG_ITMP3.
2159 * We pass in the disp parameter, how many bytes
2160 * to skip to the to the actual store.
2162 * XXX this relies on patcher_add_patch_ref internals
2165 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2166 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2171 if (IS_INT_LNG_TYPE(fieldtype)) {
2172 if (IS_2_WORD_TYPE(fieldtype))
2173 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2175 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2177 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2180 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2181 ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2184 switch (fieldtype) {
2186 M_IST(s2, s1, disp);
2189 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2190 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2193 M_AST(s2, s1, disp);
2196 M_FST(s2, s1, disp);
2199 M_DST(s2, s1, disp);
2206 /* branch operations **************************************************/
2208 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2210 /* PROFILE_CYCLE_STOP; */
2212 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2213 M_INTMOVE(s1, REG_ITMP3_XPTR);
2215 #ifdef ENABLE_VERIFIER
2216 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2217 uc = iptr->sx.s23.s2.uc;
2219 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2221 #endif /* ENABLE_VERIFIER */
2223 disp = dseg_add_functionptr(cd, asm_handle_exception);
2224 M_ALD_DSEG(REG_ITMP1, disp);
2225 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2230 case ICMD_GOTO: /* ... ==> ... */
2231 case ICMD_RET: /* ... ==> ... */
2233 emit_br(cd, iptr->dst.block);
2237 case ICMD_JSR: /* ... ==> ... */
2239 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2243 case ICMD_IFNULL: /* ..., value ==> ... */
2244 case ICMD_IFNONNULL: /* ..., value ==> ... */
2245 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2247 switch (iptr->opc) {
2249 emit_beq(cd, iptr->dst.block);
2251 case ICMD_IFNONNULL:
2252 emit_bne(cd, iptr->dst.block);
2257 case ICMD_IFEQ: /* ..., value ==> ... */
2258 case ICMD_IFLT: /* ..., value ==> ... */
2259 case ICMD_IFLE: /* ..., value ==> ... */
2260 case ICMD_IFNE: /* ..., value ==> ... */
2261 case ICMD_IFGT: /* ..., value ==> ... */
2262 case ICMD_IFGE: /* ..., value ==> ... */
2264 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2266 if (N_VALID_IMM(iptr->sx.val.i))
2267 M_ICMP_IMM(s1, iptr->sx.val.i);
2269 disp = dseg_add_s4(cd, iptr->sx.val.i);
2270 if (N_VALID_DSEG_DISP(disp)) {
2271 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2273 ICONST(REG_ITMP2, disp);
2274 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2278 switch (iptr->opc) {
2280 emit_blt(cd, iptr->dst.block);
2283 emit_ble(cd, iptr->dst.block);
2286 emit_bne(cd, iptr->dst.block);
2289 emit_bgt(cd, iptr->dst.block);
2292 emit_bge(cd, iptr->dst.block);
2295 emit_beq(cd, iptr->dst.block);
2301 case ICMD_IF_LLT: /* ..., value ==> ... */
2302 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2308 /* ATTENTION: compare high words signed and low words unsigned */
2310 # define LABEL_OUT BRANCH_LABEL_1
2312 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2314 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2315 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2317 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2318 if (N_VALID_DSEG_DISP(disp)) {
2319 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2321 ICONST(REG_ITMP2, disp);
2322 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2329 emit_blt(cd, iptr->dst.block);
2330 /* EQ ... fall through */
2331 emit_label_bgt(cd, LABEL_OUT);
2335 emit_bgt(cd, iptr->dst.block);
2336 /* EQ ... fall through */
2337 emit_label_blt(cd, LABEL_OUT);
2340 /* EQ ... fall through */
2341 emit_label_bne(cd, LABEL_OUT);
2344 /* EQ ... fall through */
2345 emit_bne(cd, iptr->dst.block);
2351 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2353 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2354 if (N_VALID_DSEG_DISP(disp)) {
2355 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2357 ICONST(REG_ITMP2, disp);
2358 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2363 emit_blt(cd, iptr->dst.block);
2364 emit_label(cd, LABEL_OUT);
2367 emit_ble(cd, iptr->dst.block);
2368 emit_label(cd, LABEL_OUT);
2371 emit_bgt(cd, iptr->dst.block);
2372 emit_label(cd, LABEL_OUT);
2375 emit_bge(cd, iptr->dst.block);
2376 emit_label(cd, LABEL_OUT);
2379 emit_beq(cd, iptr->dst.block);
2380 emit_label(cd, LABEL_OUT);
2383 emit_bne(cd, iptr->dst.block);
2392 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2393 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2395 /* Compare addresses as 31 bit unsigned integers */
2397 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2398 M_LDA(REG_ITMP1, s1, 0);
2400 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2401 M_LDA(REG_ITMP2, s2, 0);
2403 M_CMP(REG_ITMP1, REG_ITMP2);
2405 switch (iptr->opc) {
2406 case ICMD_IF_ACMPEQ:
2407 emit_beq(cd, iptr->dst.block);
2409 case ICMD_IF_ACMPNE:
2410 emit_bne(cd, iptr->dst.block);
2416 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2417 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2418 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2419 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2420 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2421 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2423 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2424 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2426 switch (iptr->opc) {
2427 case ICMD_IF_ICMPEQ:
2428 emit_beq(cd, iptr->dst.block);
2430 case ICMD_IF_ICMPNE:
2431 emit_bne(cd, iptr->dst.block);
2433 case ICMD_IF_ICMPLT:
2434 emit_blt(cd, iptr->dst.block);
2436 case ICMD_IF_ICMPGT:
2437 emit_bgt(cd, iptr->dst.block);
2439 case ICMD_IF_ICMPLE:
2440 emit_ble(cd, iptr->dst.block);
2442 case ICMD_IF_ICMPGE:
2443 emit_bge(cd, iptr->dst.block);
2449 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2450 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2451 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2452 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2453 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2454 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2459 /* ATTENTION: compare high words signed and low words unsigned */
2461 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2462 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2467 case ICMD_IF_LCMPLT:
2468 case ICMD_IF_LCMPLE:
2469 emit_blt(cd, iptr->dst.block);
2470 /* EQ ... fall through */
2471 out_ref = cd->mcodeptr;
2474 case ICMD_IF_LCMPGT:
2475 case ICMD_IF_LCMPGE:
2476 emit_bgt(cd, iptr->dst.block);
2477 /* EQ ... fall through */
2478 out_ref = cd->mcodeptr;
2481 case ICMD_IF_LCMPEQ:
2482 /* EQ ... fall through */
2483 out_ref = cd->mcodeptr;
2486 case ICMD_IF_LCMPNE:
2487 /* EQ ... fall through */
2488 emit_bne(cd, iptr->dst.block);
2494 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2495 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2500 case ICMD_IF_LCMPLT:
2501 emit_blt(cd, iptr->dst.block);
2503 case ICMD_IF_LCMPLE:
2504 emit_ble(cd, iptr->dst.block);
2506 case ICMD_IF_LCMPGT:
2507 emit_bgt(cd, iptr->dst.block);
2509 case ICMD_IF_LCMPGE:
2510 emit_bge(cd, iptr->dst.block);
2512 case ICMD_IF_LCMPEQ:
2513 emit_beq(cd, iptr->dst.block);
2515 case ICMD_IF_LCMPNE:
2516 emit_bne(cd, iptr->dst.block);
2522 if (out_ref != NULL) {
2523 N_BRC_BACK_PATCH(out_ref);
2529 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2531 REPLACEMENT_POINT_RETURN(cd, iptr);
2532 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2533 M_INTMOVE(s1, REG_RESULT);
2534 goto nowperformreturn;
2536 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2538 REPLACEMENT_POINT_RETURN(cd, iptr);
2539 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2540 M_INTMOVE(s1, REG_RESULT);
2542 #ifdef ENABLE_VERIFIER
2543 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2544 unresolved_class *uc = iptr->sx.s23.s2.uc;
2547 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2548 PROFILE_CYCLE_START;
2550 #endif /* ENABLE_VERIFIER */
2551 goto nowperformreturn;
2553 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2555 REPLACEMENT_POINT_RETURN(cd, iptr);
2556 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2557 M_LNGMOVE(s1, REG_RESULT_PACKED);
2558 goto nowperformreturn;
2560 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2563 REPLACEMENT_POINT_RETURN(cd, iptr);
2564 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2565 M_FLTMOVE(s1, REG_FRESULT);
2566 goto nowperformreturn;
2568 case ICMD_RETURN: /* ... ==> ... */
2570 REPLACEMENT_POINT_RETURN(cd, iptr);
2576 p = cd->stackframesize;
2578 /* call trace function */
2580 #if !defined(NDEBUG)
2581 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2582 emit_verbosecall_exit(jd);
2583 #endif /* !defined(NDEBUG) */
2585 #if defined(ENABLE_THREADS)
2586 if (checksync && code_is_synchronized(code)) {
2587 /* we need to save the proper return value */
2589 switch (iptr->opc) {
2591 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2595 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2598 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2601 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2605 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2607 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2608 M_ALD_DSEG(REG_ITMP2, disp);
2610 M_ASUB_IMM(96, REG_SP);
2612 M_AADD_IMM(96, REG_SP);
2614 /* and now restore the proper return value */
2616 switch (iptr->opc) {
2618 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2622 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2625 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2628 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2634 /* restore return address */
2636 p--; M_ALD(REG_RA, REG_SP, p * 8);
2638 /* restore saved registers */
2640 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2641 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2643 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2644 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2647 /* deallocate stack */
2649 if (cd->stackframesize)
2650 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2652 /* generate method profiling code */
2660 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2663 branch_target_t *table;
2665 table = iptr->dst.table;
2667 l = iptr->sx.s23.s2.tablelow;
2668 i = iptr->sx.s23.s3.tablehigh;
2670 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2671 M_INTMOVE(s1, REG_ITMP1);
2675 } else if (N_VALID_IMM(-l)) {
2676 M_ISUB_IMM(l, REG_ITMP1);
2678 ICONST(REG_ITMP2, l);
2679 M_ISUB(REG_ITMP2, REG_ITMP1);
2682 /* number of targets */
2688 ICONST(REG_ITMP2, i);
2689 M_ICMPU(REG_ITMP1, REG_ITMP2);
2690 emit_bge(cd, table[0].block);
2692 /* build jump table top down and use address of lowest entry */
2697 dseg_add_target(cd, table->block);
2702 /* length of dataseg after last dseg_add_target is used by load */
2704 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2705 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2706 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2707 M_JMP(RN, REG_ITMP1);
2712 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2715 lookup_target_t *lookup;
2717 lookup = iptr->dst.lookup;
2719 i = iptr->sx.s23.s2.lookupcount;
2721 MCODECHECK(8 + ((7 + 6) * i) + 5);
2722 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2725 if (N_VALID_IMM(lookup->value)) {
2726 M_ICMP_IMM(s1, lookup->value);
2728 ICONST(REG_ITMP2, lookup->value);
2729 M_ICMP(REG_ITMP2, s1);
2731 emit_beq(cd, lookup->target.block);
2735 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2740 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2742 bte = iptr->sx.s23.s3.bte;
2746 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2747 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2748 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2749 case ICMD_INVOKEINTERFACE:
2751 REPLACEMENT_POINT_INVOKE(cd, iptr);
2753 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2755 um = iptr->sx.s23.s3.um;
2756 md = um->methodref->parseddesc.md;
2759 lm = iptr->sx.s23.s3.fmiref->p.method;
2761 md = lm->parseddesc;
2765 s3 = md->paramcount;
2767 MCODECHECK((s3 << 1) + 64);
2769 /* copy arguments to registers or stack location */
2771 for (s3 = s3 - 1; s3 >= 0; s3--) {
2772 var = VAR(iptr->sx.s23.s2.args[s3]);
2774 /* Already Preallocated? */
2775 if (var->flags & PREALLOC)
2778 if (IS_INT_LNG_TYPE(var->type)) {
2779 if (!md->params[s3].inmemory) {
2780 if (IS_2_WORD_TYPE(var->type)) {
2782 GET_LOW_REG(md->params[s3].regoff),
2783 GET_HIGH_REG(md->params[s3].regoff)
2785 d = emit_load(jd, iptr, var, s1);
2789 s1 = md->params[s3].regoff;
2790 d = emit_load(jd, iptr, var, s1);
2795 if (IS_2_WORD_TYPE(var->type)) {
2796 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2797 M_LST(d, REG_SP, md->params[s3].regoff);
2800 d = emit_load(jd, iptr, var, REG_ITMP1);
2801 M_IST(d, REG_SP, md->params[s3].regoff);
2806 if (!md->params[s3].inmemory) {
2807 s1 = md->params[s3].regoff;
2808 d = emit_load(jd, iptr, var, s1);
2812 d = emit_load(jd, iptr, var, REG_FTMP1);
2813 if (IS_2_WORD_TYPE(var->type))
2814 M_DST(d, REG_SP, md->params[s3].regoff);
2816 M_FST(d, REG_SP, md->params[s3].regoff);
2821 /* generate method profiling code */
2825 switch (iptr->opc) {
2827 if (bte->stub == NULL) {
2828 disp = dseg_add_functionptr(cd, bte->fp);
2829 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2831 disp = dseg_add_functionptr(cd, bte->stub);
2834 if (N_VALID_DSEG_DISP(disp)) {
2835 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2837 N_LHI(REG_ITMP1, disp);
2838 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2842 case ICMD_INVOKESPECIAL:
2844 /* Implicit NULL pointer check */
2845 M_ILD(REG_ITMP1, REG_A0, 0);
2849 case ICMD_INVOKESTATIC:
2851 disp = dseg_add_unique_address(cd, um);
2853 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2857 disp = dseg_add_address(cd, lm->stubroutine);
2859 if (N_VALID_DSEG_DISP(disp)) {
2860 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2862 N_LHI(REG_ITMP1, disp);
2863 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2867 case ICMD_INVOKEVIRTUAL:
2868 /* TODO softnull REG_A0 */
2871 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2876 s1 = OFFSET(vftbl_t, table[0]) +
2877 sizeof(methodptr) * lm->vftblindex;
2880 /* implicit null-pointer check */
2882 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2883 M_ALD(REG_PV, REG_METHODPTR, s1);
2886 case ICMD_INVOKEINTERFACE:
2887 /* TODO softnull REG_A0 */
2889 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2890 * and -0xFFF in index register (itmp1)
2894 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2900 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2901 sizeof(methodptr*) * lm->clazz->index;
2903 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2906 /* Implicit null-pointer check */
2907 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2908 N_LHI(REG_ITMP2, s1);
2909 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2910 M_ALD(REG_PV, REG_METHODPTR, s2);
2914 /* generate the actual call */
2917 emit_restore_pv(cd);
2919 /* post call finalization */
2921 switch (iptr->opc) {
2923 if (bte->stub == NULL) {
2924 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2929 /* generate method profiling code */
2931 PROFILE_CYCLE_START;
2933 /* store size of call code in replacement point */
2935 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2937 /* store return value */
2939 d = md->returntype.type;
2941 if (d != TYPE_VOID) {
2942 if (IS_INT_LNG_TYPE(d)) {
2943 if (IS_2_WORD_TYPE(d)) {
2944 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2945 M_LNGMOVE(REG_RESULT_PACKED, s1);
2948 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2949 M_INTMOVE(REG_RESULT, s1);
2953 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2954 M_FLTMOVE(REG_FRESULT, s1);
2956 emit_store_dst(jd, iptr, s1);
2962 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2964 /* val.a: (classinfo*) superclass */
2966 /* superclass is an interface:
2968 * OK if ((sub == NULL) ||
2969 * (sub->vftbl->interfacetablelength > super->index) &&
2970 * (sub->vftbl->interfacetable[-super->index] != NULL));
2972 * superclass is a class:
2974 * OK if ((sub == NULL) || (0
2975 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2976 * super->vftbl->diffval));
2979 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2980 /* object type cast-check */
2983 vftbl_t *supervftbl;
2986 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2987 # define LABEL_CLASS BRANCH_LABEL_2
2988 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2989 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2990 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2992 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2998 super = iptr->sx.s23.s3.c.cls;
2999 superindex = super->index;
3000 supervftbl = super->vftbl;
3003 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3005 /* if class is not resolved, check which code to call */
3007 if (super == NULL) {
3009 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3011 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3013 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3014 iptr->sx.s23.s3.c.ref,
3017 ICONST(REG_ITMP3, ACC_INTERFACE);
3019 if (N_VALID_DSEG_DISP(disp)) {
3020 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3022 ICONST(REG_ITMP2, disp);
3023 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3025 emit_label_beq(cd, LABEL_CLASS);
3028 /* interface checkcast code */
3030 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3031 if (super == NULL) {
3032 patcher_add_patch_ref(jd,
3033 PATCHER_checkcast_instanceof_interface,
3034 iptr->sx.s23.s3.c.ref,
3038 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3041 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3042 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3043 M_ISUB_IMM(superindex, REG_ITMP3);
3044 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3047 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3048 superindex * sizeof(methodptr*))
3050 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3051 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3053 if (super == NULL) {
3054 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3058 /* class checkcast code */
3060 if (super == NULL) {
3061 emit_label(cd, LABEL_CLASS);
3064 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3065 if (super == NULL) {
3066 disp = dseg_add_unique_address(cd, NULL);
3068 patcher_add_patch_ref(jd,
3069 PATCHER_resolve_classref_to_vftbl,
3070 iptr->sx.s23.s3.c.ref,
3074 disp = dseg_add_address(cd, supervftbl);
3076 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3080 /* REG_ITMP3 := baseval(s1) */
3081 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3082 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3084 /* REG_ITMP2 := baseval(class) */
3085 M_ALD_DSEG(REG_ITMP2, disp);
3086 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3088 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3089 M_ISUB(REG_ITMP2, REG_ITMP3);
3091 /* REG_ITMP2 := diffval(class) */
3092 M_ALD_DSEG(REG_ITMP2, disp);
3093 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3095 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3097 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3098 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3099 /* Branch if greater then */
3101 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3102 M_ALD_DSEG(REG_ITMP3, disp);
3104 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3105 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3106 M_ISUB(REG_ITMP3, REG_ITMP2);
3107 M_ALD_DSEG(REG_ITMP3, disp);
3108 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3110 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3111 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3112 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3113 /* Branch if greater then */
3115 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3118 if (super == NULL) {
3119 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3120 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3121 } else if (super->flags & ACC_INTERFACE) {
3122 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3124 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3127 d = codegen_reg_of_dst(jd, iptr, s1);
3129 # undef LABEL_EXIT_CHECK_NULL
3131 # undef LABEL_EXIT_INTERFACE_NULL
3132 # undef LABEL_EXIT_INTERFACE_DONE
3133 # undef LABEL_EXIT_CLASS_NULL
3136 /* array type cast-check */
3138 s1 = emit_load_s1(jd, iptr, REG_A0);
3139 M_INTMOVE(s1, REG_A0);
3141 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3142 disp = dseg_add_unique_address(cd, NULL);
3144 patcher_add_patch_ref(jd,
3145 PATCHER_resolve_classref_to_classinfo,
3146 iptr->sx.s23.s3.c.ref,
3150 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3152 M_ALD_DSEG(REG_A1, disp);
3153 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3154 M_ALD_DSEG(REG_ITMP1, disp);
3155 M_ASUB_IMM(96, REG_SP);
3156 M_JSR(REG_RA, REG_ITMP1);
3157 M_AADD_IMM(96, REG_SP);
3159 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3160 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3162 d = codegen_reg_of_dst(jd, iptr, s1);
3166 emit_store_dst(jd, iptr, d);
3169 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3170 /* val.a: (classinfo*) superclass */
3172 /* superclass is an interface:
3174 * return (sub != NULL) &&
3175 * (sub->vftbl->interfacetablelength > super->index) &&
3176 * (sub->vftbl->interfacetable[-super->index] != NULL);
3178 * superclass is a class:
3180 * return ((sub != NULL) && (0
3181 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3182 * super->vftbl->diffvall));
3184 * If superclass is unresolved, we include both code snippets
3185 * above, a patcher resolves the class' flags and we select
3186 * the right code at runtime.
3191 vftbl_t *supervftbl;
3194 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3200 super = iptr->sx.s23.s3.c.cls;
3201 superindex = super->index;
3202 supervftbl = super->vftbl;
3205 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3206 # define LABEL_CLASS BRANCH_LABEL_2
3207 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3208 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3209 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3210 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3212 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3213 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3215 M_MOV(s1, REG_ITMP1);
3219 /* if class is not resolved, check which code to call */
3221 if (super == NULL) {
3225 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3227 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3229 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3230 iptr->sx.s23.s3.c.ref, disp);
3232 ICONST(REG_ITMP3, ACC_INTERFACE);
3234 if (N_VALID_DSEG_DISP(disp)) {
3235 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3237 ICONST(REG_ITMP2, disp);
3238 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3241 emit_label_beq(cd, LABEL_CLASS);
3244 /* interface instanceof code */
3246 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3247 if (super == NULL) {
3248 /* If d == REG_ITMP2, then it's destroyed in check
3253 patcher_add_patch_ref(jd,
3254 PATCHER_checkcast_instanceof_interface,
3255 iptr->sx.s23.s3.c.ref, 0);
3260 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3263 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3264 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3265 M_ISUB_IMM(superindex, REG_ITMP3);
3267 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3271 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3272 superindex * sizeof(methodptr*))
3274 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3276 /* d := (REG_ITMP1 != 0) */
3278 N_LTR(d, REG_ITMP1);
3279 M_BEQ(SZ_BRC + SZ_LHI);
3282 if (super == NULL) {
3283 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3287 /* class instanceof code */
3289 if (super == NULL) {
3290 emit_label(cd, LABEL_CLASS);
3293 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3294 if (super == NULL) {
3295 disp = dseg_add_unique_address(cd, NULL);
3297 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3298 iptr->sx.s23.s3.c.ref,
3302 disp = dseg_add_address(cd, supervftbl);
3307 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3310 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3311 M_ALD_DSEG(REG_ITMP2, disp);
3313 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3314 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3315 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3317 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3319 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3321 M_BGT(SZ_BRC + SZ_LHI);
3325 if (super == NULL) {
3326 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3327 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3328 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3329 } else if (super->flags & ACC_INTERFACE) {
3330 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3331 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3333 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3336 # undef LABEL_EXIT_CHECK_NULL
3338 # undef LABEL_EXIT_INTERFACE_NULL
3339 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3340 # undef LABEL_EXIT_INTERFACE_DONE
3341 # undef LABEL_EXIT_CLASS_NULL
3343 emit_store_dst(jd, iptr, d);
3349 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3351 /* check for negative sizes and copy sizes to stack if necessary */
3353 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3356 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3358 /* copy SAVEDVAR sizes to stack */
3359 var = VAR(iptr->sx.s23.s2.args[s1]);
3361 /* Already Preallocated? */
3362 if (!(var->flags & PREALLOC)) {
3363 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3364 M_IST(s2, REG_SP, s1 * 4);
3368 /* is a patcher function set? */
3370 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3371 disp = dseg_add_unique_address(cd, 0);
3373 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3374 iptr->sx.s23.s3.c.ref,
3378 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3380 /* a0 = dimension count */
3382 ICONST(REG_A0, iptr->s1.argcount);
3384 /* a1 = classinfo */
3386 M_ALD_DSEG(REG_A1, disp);
3388 /* a2 = pointer to dimensions = stack pointer */
3390 M_MOV(REG_SP, REG_A2);
3392 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3393 M_ALD_DSEG(REG_ITMP1, disp);
3394 M_ASUB_IMM(96, REG_SP);
3395 M_JSR(REG_RA, REG_ITMP1);
3396 M_AADD_IMM(96, REG_SP);
3398 /* check for exception before result assignment */
3400 emit_exception_check(cd, iptr);
3402 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3403 M_INTMOVE(REG_RESULT, s1);
3404 emit_store_dst(jd, iptr, s1);
3409 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3413 } /* for instruction */
3415 MCODECHECK(512); /* XXX require a lower number? */
3417 /* At the end of a basic block we may have to append some nops,
3418 because the patcher stub calling code might be longer than the
3419 actual instruction. So codepatching does not change the
3420 following block unintentionally. */
3422 if (cd->mcodeptr < cd->lastmcodeptr) {
3423 while (cd->mcodeptr < cd->lastmcodeptr) {
3428 } /* if (bptr -> flags >= BBREACHED) */
3429 } /* for basic block */
3431 /* generate stubs */
3433 emit_patcher_traps(jd);
3435 /* everything's ok */
3440 /* codegen_emit_stub_native ****************************************************
3442 Emits a stub routine which calls a native method.
3444 *******************************************************************************/
3447 arguments on stack \
3448 -------------------------------------------------| <- SP on nativestub entry
3450 callee saved int regs (none) |
3451 callee saved float regs (none) | stack frame like in cacao
3452 local variable slots (none) |
3453 arguments for calling methods (none) /
3454 ------------------------------------------------------------------ <- datasp
3459 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3460 0 - 96 register save area for callee /
3461 -------------------------------------------------------- <- SP native method
3463 SP after method entry
3466 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3477 /* get required compiler data */
3483 /* set some variables */
3487 /* calculate stackframe size */
3489 cd->stackframesize =
3490 1 + /* return address */
3491 sizeof(stackframeinfo_t) / 8 +
3492 sizeof(localref_table) / 8 +
3495 (96 / 8); /* linkage area */
3497 /* keep stack 8-byte aligned */
3499 /*ALIGN_2(cd->stackframesize);*/
3501 /* create method header */
3503 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3504 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3505 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3506 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3507 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3511 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3512 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3514 /* store return address */
3516 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3518 #if defined(ENABLE_GC_CACAO)
3519 /* Save callee saved integer registers in stackframeinfo (GC may
3520 need to recover them during a collection). */
3522 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3523 OFFSET(stackframeinfo_t, intregs);
3525 for (i = 0; i < INT_SAV_CNT; i++)
3526 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3529 /* save integer and float argument registers */
3531 for (i = 0; i < md->paramcount; i++) {
3532 if (!md->params[i].inmemory) {
3533 s1 = md->params[i].regoff;
3535 switch (md->paramtypes[i].type) {
3538 M_IST(s1, REG_SP, 96 + i * 8);
3541 M_LST(s1, REG_SP, 96 + i * 8);
3545 M_DST(s1, REG_SP, 96 + i * 8);
3551 /* create native stack info */
3553 M_MOV(REG_SP, REG_A0);
3554 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3555 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3556 M_ALD_DSEG(REG_ITMP2, disp);
3559 /* remember class argument */
3561 if (m->flags & ACC_STATIC)
3562 M_MOV(REG_RESULT, REG_ITMP3);
3564 /* restore integer and float argument registers */
3566 for (i = 0; i < md->paramcount; i++) {
3567 if (!md->params[i].inmemory) {
3568 s1 = md->params[i].regoff;
3570 switch (md->paramtypes[i].type) {
3573 M_ILD(s1, REG_SP, 96 + i * 8);
3576 M_LLD(s1, REG_SP, 96 + i * 8);
3580 M_DLD(s1, REG_SP, 96 + i * 8);
3586 /* copy or spill arguments to new locations */
3588 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3589 t = md->paramtypes[i].type;
3591 if (IS_INT_LNG_TYPE(t)) {
3592 if (!md->params[i].inmemory) {
3593 s1 = md->params[i].regoff;
3594 s2 = nmd->params[j].regoff;
3596 if (!nmd->params[j].inmemory) {
3597 if (IS_2_WORD_TYPE(t))
3603 if (IS_2_WORD_TYPE(t))
3604 M_LST(s1, REG_SP, s2);
3606 M_IST(s1, REG_SP, s2);
3610 s1 = md->params[i].regoff + cd->stackframesize * 8;
3611 s2 = nmd->params[j].regoff;
3613 if (IS_2_WORD_TYPE(t)) {
3614 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3616 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3621 /* We only copy spilled float arguments, as the float
3622 argument registers keep unchanged. */
3624 if (md->params[i].inmemory) {
3625 s1 = md->params[i].regoff + cd->stackframesize * 8;
3626 s2 = nmd->params[j].regoff;
3628 if (IS_2_WORD_TYPE(t)) {
3629 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3631 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3637 /* Handle native Java methods. */
3639 if (m->flags & ACC_NATIVE) {
3640 /* put class into second argument register */
3642 if (m->flags & ACC_STATIC)
3643 M_MOV(REG_ITMP3, REG_A1);
3645 /* put env into first argument register */
3647 disp = dseg_add_address(cd, VM_get_jnienv());
3648 M_ALD_DSEG(REG_A0, disp);
3651 /* Call native function. */
3653 disp = dseg_add_functionptr(cd, f);
3654 M_ALD_DSEG(REG_ITMP2, disp);
3657 /* save return value */
3659 switch (md->returntype.type) {
3662 M_IST(REG_RESULT, REG_SP, 96);
3665 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3669 M_DST(REG_FRESULT, REG_SP, 96);
3675 /* remove native stackframe info */
3677 M_MOV(REG_SP, REG_A0);
3678 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3679 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3680 M_ALD_DSEG(REG_ITMP1, disp);
3683 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3685 /* restore return value */
3687 switch (md->returntype.type) {
3690 M_ILD(REG_RESULT, REG_SP, 96);
3693 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3697 M_DLD(REG_FRESULT, REG_SP, 96);
3703 #if defined(ENABLE_GC_CACAO)
3704 /* Restore callee saved integer registers from stackframeinfo (GC
3705 might have modified them during a collection). */
3707 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3708 OFFSET(stackframeinfo_t, intregs);
3710 for (i = 0; i < INT_SAV_CNT; i++)
3711 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3714 /* load return address */
3716 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3718 /* remove stackframe */
3720 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3722 /* check for exception */
3724 M_TEST(REG_ITMP3_XPTR);
3725 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3729 /* handle exception */
3731 M_MOV(REG_RA, REG_ITMP1_XPC);
3732 M_ASUB_IMM(2, REG_ITMP1_XPC);
3734 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3735 M_ALD_DSEG(REG_ITMP2, disp);
3736 M_JMP(RN, REG_ITMP2);
3740 * These are local overrides for various environment variables in Emacs.
3741 * Please do not remove this and leave it at the end of the file, where
3742 * Emacs will automagically detect them.
3743 * ---------------------------------------------------------------------
3746 * indent-tabs-mode: t
3750 * vim:noexpandtab:sw=4:ts=4: