1 /* src/vm/jit/s390/codegen.c - machine code generator for s390
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "native/jni.h"
35 #include "native/localref.h"
36 #include "native/native.h"
38 #include "mm/memory.h"
40 #if defined(ENABLE_THREADS)
41 # include "threads/lock-common.h"
42 # include "threads/native/lock.h"
45 #include "vmcore/loader.h"
46 #include "vmcore/options.h"
47 #include "vmcore/statistics.h"
48 #include "vm/builtin.h"
49 #include "vm/exceptions.h"
50 #include "vm/global.h"
51 #include "vm/jit/abi.h"
52 #if defined(ENABLE_LSRA)
53 # include "vm/jit/allocator/lsra.h"
55 #include "vm/jit/asmpart.h"
56 #include "vm/jit/codegen-common.h"
57 #include "vm/jit/dseg.h"
58 #include "vm/jit/emit-common.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/methodheader.h"
61 #include "vm/jit/parse.h"
62 #include "vm/jit/patcher-common.h"
63 #include "vm/jit/reg.h"
64 #include "vm/jit/replace.h"
65 #include "vm/jit/s390/arch.h"
66 #include "vm/jit/s390/codegen.h"
67 #include "vm/jit/s390/emit.h"
68 #include "vm/jit/s390/md-abi.h"
69 #include "vm/jit/stacktrace.h"
71 #include "vm/stringlocal.h"
74 /* DO__LOG generates a call to do__log. No registers are destroyed,
75 * so you may use it anywhere. regs is an array containing all general
79 static void do__log(u4 *regs) {
80 /* insert stuff here */
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 #define SUPPORT_HERCULES 1
94 /* codegen *********************************************************************
96 Generates machine code.
98 *******************************************************************************/
102 Layout of stackframe:
105 ===============================================================================
106 return_address (stackframesize - 1) * 8
107 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
109 saved_int_reg[rd->savintreguse]
110 saved_flt_reg[FLT_SAV_CNT - 1]
112 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
114 return_value_tmp (rd->memuse + 1) * 8
115 monitorenter_argument (rd->memuse) * 8
117 local[rd->memuse - 1] (rd->memuse - 1) * 8
125 bool codegen_emit(jitdata *jd)
131 s4 len, s1, s2, s3, d, dd, disp;
134 varinfo *var, *var1, *var2, *dst;
138 constant_classref *cr;
139 unresolved_class *uc;
140 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
141 unresolved_method *um;
142 builtintable_entry *bte;
145 unresolved_field *uf;
148 rplpoint *replacementpoint;
152 /* get required compiler data */
159 /* prevent compiler warnings */
172 /* space to save used callee saved registers */
174 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
175 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
177 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
180 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
183 #if defined(ENABLE_THREADS)
184 /* Space to save argument of monitor_enter and Return Values to
185 survive monitor_exit. The stack position for the argument can
186 not be shared with place to save the return register
187 since both values reside in R2. */
189 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
190 /* 1 slot space to save argument of monitor_enter */
191 /* 1 slot to temporary store return value before monitor_exit */
192 cd->stackframesize += 2;
196 /* Keep stack of non-leaf functions 16-byte aligned for calls into
197 native code e.g. libc or jni (alignment problems with
200 if (!jd->isleafmethod || opt_verbosecall )
201 /* TODO really 16 bytes ? */
202 cd->stackframesize = (cd->stackframesize + 2) & ~2;
204 /* create method header */
206 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
207 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
209 #if defined(ENABLE_THREADS)
210 /* IsSync contains the offset relative to the stack pointer for the
211 argument of monitor_exit used in the exception handler. Since the
212 offset could be zero and give a wrong meaning of the flag it is
216 if (checksync && (m->flags & ACC_SYNCHRONIZED))
217 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync */
220 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
222 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
223 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
224 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
226 (void) dseg_addlinenumbertablesize(cd);
228 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
230 /* create exception table */
232 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
233 dseg_add_target(cd, ex->start);
234 dseg_add_target(cd, ex->end);
235 dseg_add_target(cd, ex->handler);
236 (void) dseg_add_unique_address(cd, ex->catchtype.any);
241 M_AADD_IMM(N_PV_OFFSET, REG_PV);
243 /* create stack frame (if necessary) */
245 if (cd->stackframesize) {
246 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
249 /* store return address */
251 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
253 /* generate method profiling code */
255 #if defined(ENABLE_PROFILING)
256 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
257 /* count frequency */
258 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
259 ICONST(REG_ITMP2, 1);
260 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
261 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
267 /* save used callee saved registers and return address */
269 p = cd->stackframesize - 1;
271 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
272 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
274 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
275 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
278 /* take arguments out of register or stack frame */
282 for (p = 0, l = 0; p < md->paramcount; p++) {
283 t = md->paramtypes[p].type;
284 varindex = jd->local_map[l * 5 + t];
288 if (IS_2_WORD_TYPE(t))
291 if (varindex == UNUSED)
296 s1 = md->params[p].regoff;
298 if (IS_INT_LNG_TYPE(t)) { /* integer args */
299 if (IS_2_WORD_TYPE(t)) {
307 if (!md->params[p].inmemory) { /* register arguments */
308 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
309 if (IS_2_WORD_TYPE(t)) {
310 M_LNGMOVE(s2, var->vv.regoff);
312 M_INTMOVE(s2, var->vv.regoff);
314 } else { /* reg arg -> spilled */
315 if (IS_2_WORD_TYPE(t)) {
316 M_LST(s2, REG_SP, var->vv.regoff);
318 M_IST(s2, REG_SP, var->vv.regoff);
322 } else { /* stack arguments */
323 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
324 if (IS_2_WORD_TYPE(t)) {
325 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
327 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
329 } else { /* stack arg -> spilled */
330 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
334 } else { /* floating args */
335 if (!md->params[p].inmemory) { /* register arguments */
337 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
338 M_FLTMOVE(s2, var->vv.regoff);
340 } else { /* reg arg -> spilled */
341 if (IS_2_WORD_TYPE(t))
342 M_DST(s2, REG_SP, var->vv.regoff);
344 M_FST(s2, REG_SP, var->vv.regoff);
347 } else { /* stack arguments */
348 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
349 if (IS_2_WORD_TYPE(t))
350 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
353 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
355 } else { /* stack-arg -> spilled */
356 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
357 var->vv.regoff = cd->stackframesize * 8 + s1;
363 /* save monitorenter argument */
365 #if defined(ENABLE_THREADS)
366 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
367 /* stack offset for monitor argument */
372 if (opt_verbosecall) {
373 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
375 for (p = 0; p < INT_ARG_CNT; p++)
376 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
378 for (p = 0; p < FLT_ARG_CNT; p++)
379 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
381 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
385 /* decide which monitor enter function to call */
387 if (m->flags & ACC_STATIC) {
388 disp = dseg_add_address(cd, &m->class->object.header);
389 M_ALD_DSEG(REG_A0, disp);
393 M_BNE(SZ_BRC + SZ_ILL);
394 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
397 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
398 M_ALD_DSEG(REG_ITMP2, disp);
400 M_AST(REG_A0, REG_SP, s1 * 8);
402 M_ASUB_IMM(96, REG_SP);
404 M_AADD_IMM(96, REG_SP);
407 if (opt_verbosecall) {
408 for (p = 0; p < INT_ARG_CNT; p++)
409 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
411 for (p = 0; p < FLT_ARG_CNT; p++)
412 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
414 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
421 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
422 emit_verbosecall_enter(jd);
423 #endif /* !defined(NDEBUG) */
427 /* end of header generation */
429 /* create replacement points */
431 REPLACEMENT_POINTS_INIT(cd, jd);
433 /* walk through all basic blocks */
435 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
437 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
439 if (bptr->flags >= BBREACHED) {
441 /* branch resolving */
443 codegen_resolve_branchrefs(cd, bptr);
445 /* handle replacement points */
447 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
449 /* copy interface registers to their destination */
454 #if defined(ENABLE_PROFILING)
455 /* generate basicblock profiling code */
457 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
458 /* count frequency */
460 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
461 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
462 ICONST(REG_ITMP2, 1);
463 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
464 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
466 /* if this is an exception handler, start profiling again */
468 if (bptr->type == BBTYPE_EXH)
473 #if defined(ENABLE_LSRA)
477 src = bptr->invars[len];
478 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
479 if (bptr->type == BBTYPE_EXH) {
480 /* d = reg_of_var(rd, src, REG_ITMP1); */
481 if (!IS_INMEMORY(src->flags))
485 M_INTMOVE(REG_ITMP3_XPTR, d);
486 emit_store(jd, NULL, src, d);
496 var = VAR(bptr->invars[len]);
497 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
498 if (bptr->type == BBTYPE_EXH) {
499 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
500 M_INTMOVE(REG_ITMP3_XPTR, d);
501 emit_store(jd, NULL, var, d);
505 assert((var->flags & INOUT));
508 #if defined(ENABLE_LSRA)
511 /* walk through all instructions */
516 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
517 if (iptr->line != currentline) {
518 dseg_addlinenumber(cd, iptr->line);
519 currentline = iptr->line;
522 MCODECHECK(1024); /* 1KB should be enough */
525 case ICMD_NOP: /* ... ==> ... */
526 case ICMD_POP: /* ..., value ==> ... */
527 case ICMD_POP2: /* ..., value, value ==> ... */
530 case ICMD_INLINE_START:
532 REPLACEMENT_POINT_INLINE_START(cd, iptr);
535 case ICMD_INLINE_BODY:
537 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
538 dseg_addlinenumber_inline_start(cd, iptr);
539 dseg_addlinenumber(cd, iptr->line);
542 case ICMD_INLINE_END:
544 dseg_addlinenumber_inline_end(cd, iptr);
545 dseg_addlinenumber(cd, iptr->line);
548 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
549 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
550 emit_nullpointer_check(cd, iptr, s1);
553 /* constant operations ************************************************/
555 case ICMD_ICONST: /* ... ==> ..., constant */
556 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
557 ICONST(d, iptr->sx.val.i);
558 emit_store_dst(jd, iptr, d);
561 case ICMD_LCONST: /* ... ==> ..., constant */
563 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
564 LCONST(d, iptr->sx.val.l);
565 emit_store_dst(jd, iptr, d);
568 case ICMD_FCONST: /* ... ==> ..., constant */
569 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
570 disp = dseg_add_float(cd, iptr->sx.val.f);
571 M_FLD_DSEG(d, disp, REG_ITMP1);
572 emit_store_dst(jd, iptr, d);
575 case ICMD_DCONST: /* ... ==> ..., constant */
576 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
577 disp = dseg_add_double(cd, iptr->sx.val.d);
578 M_DLD_DSEG(d, disp, REG_ITMP1);
579 emit_store_dst(jd, iptr, d);
582 case ICMD_ACONST: /* ... ==> ..., constant */
583 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
585 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
586 cr = iptr->sx.val.c.ref;
587 disp = dseg_add_unique_address(cd, cr);
589 /* PROFILE_CYCLE_STOP; */
591 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
594 /* PROFILE_CYCLE_START; */
598 if (iptr->sx.val.anyptr == 0) {
601 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
604 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
605 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
607 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
609 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
615 emit_store_dst(jd, iptr, d);
619 /* load/store/copy/move operations ************************************/
621 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
622 case ICMD_ALOAD: /* s1 = local variable */
626 case ICMD_ISTORE: /* ..., value ==> ... */
637 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
641 /* integer operations *************************************************/
643 case ICMD_INEG: /* ..., value ==> ..., - value */
645 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
646 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
648 emit_store_dst(jd, iptr, d);
652 case ICMD_LNEG: /* ..., value ==> ..., - value */
654 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
655 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
656 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
657 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
658 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
659 N_AHI(GET_HIGH_REG(d), -1);
660 emit_store_dst(jd, iptr, d);
663 case ICMD_I2L: /* ..., value ==> ..., value */
665 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
666 if (! N_IS_EVEN_ODD(d)) {
667 d = REG_ITMP31_PACKED;
669 assert(N_IS_EVEN_ODD(d));
671 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
673 M_INTMOVE(s1, GET_HIGH_REG(d));
674 M_SRDA_IMM(32, GET_HIGH_REG(d));
676 emit_copy_dst(jd, iptr, d);
677 emit_store_dst(jd, iptr, d);
680 case ICMD_L2I: /* ..., value ==> ..., value */
681 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
682 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
683 M_INTMOVE(GET_LOW_REG(s1), d);
684 emit_store_dst(jd, iptr, d);
687 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
688 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
689 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
693 emit_store_dst(jd, iptr, d);
696 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
697 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
698 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
702 emit_store_dst(jd, iptr, d);
705 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
707 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
708 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
712 emit_store_dst(jd, iptr, d);
715 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
717 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
718 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
719 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
726 emit_store_dst(jd, iptr, d);
731 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
732 /* sx.val.i = constant */
733 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
734 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
737 if (N_VALID_IMM(iptr->sx.val.i)) {
738 M_IADD_IMM(iptr->sx.val.i, d);
740 ICONST(REG_ITMP2, iptr->sx.val.i);
741 M_IADD(REG_ITMP2, d);
743 emit_store_dst(jd, iptr, d);
746 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
748 /* M, (r, q) -> (r, q) */
750 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
752 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
753 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
754 dd = GET_HIGH_REG(d);
763 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
764 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
774 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
775 N_AHI(GET_HIGH_REG(d), 1);
777 emit_store_dst(jd, iptr, d);
780 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
781 /* sx.val.l = constant */
783 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
784 dd = GET_HIGH_REG(d);
786 s1 = emit_load_s1_high(jd, iptr, dd);
787 s3 = iptr->sx.val.l >> 32;
791 if (N_VALID_IMM(s3)) {
794 ICONST(REG_ITMP3, s3);
795 M_IADD(REG_ITMP3, dd);
799 s1 = emit_load_s1_low(jd, iptr, dd);
800 s3 = iptr->sx.val.l & 0xffffffff;
801 ICONST(REG_ITMP3, s3);
804 N_ALR(dd, REG_ITMP3);
806 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
807 N_AHI(GET_HIGH_REG(d), 1);
809 emit_store_dst(jd, iptr, d);
812 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
814 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
815 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
816 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
818 M_INTMOVE(s1, REG_ITMP1);
819 M_ISUB(s2, REG_ITMP1);
820 M_INTMOVE(REG_ITMP1, d);
825 emit_store_dst(jd, iptr, d);
829 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
830 /* sx.val.i = constant */
832 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
833 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
836 if (N_VALID_IMM(-iptr->sx.val.i)) {
837 M_ISUB_IMM(iptr->sx.val.i, d);
839 ICONST(REG_ITMP2, iptr->sx.val.i);
840 M_ISUB(REG_ITMP2, d);
842 emit_store_dst(jd, iptr, d);
846 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
848 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
850 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
851 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
852 dd = GET_HIGH_REG(d);
855 M_INTMOVE(s2, REG_ITMP3);
862 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
863 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
867 M_INTMOVE(s2, REG_ITMP3);
874 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
875 N_AHI(GET_HIGH_REG(d), -1);
877 emit_store_dst(jd, iptr, d);
880 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
881 /* sx.val.l = constant */
883 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
885 dd = GET_HIGH_REG(d);
886 s1 = emit_load_s1_high(jd, iptr, dd);
887 s3 = iptr->sx.val.l >> 32;
891 if (N_VALID_IMM(-s3)) {
894 ICONST(REG_ITMP3, s3);
895 M_ISUB(REG_ITMP3, dd);
899 s1 = emit_load_s1_low(jd, iptr, dd);
900 s3 = iptr->sx.val.l & 0xffffffff;
901 ICONST(REG_ITMP3, s3);
904 N_SLR(dd, REG_ITMP3);
906 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
907 N_AHI(GET_HIGH_REG(d), -1);
909 emit_store_dst(jd, iptr, d);
912 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
914 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
915 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
916 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
923 emit_store_dst(jd, iptr, d);
927 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
928 /* sx.val.i = constant */
929 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
930 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
932 if (iptr->sx.val.i == 2) {
934 } else if (N_VALID_IMM(iptr->sx.val.i)) {
935 M_IMUL_IMM(iptr->sx.val.i, d);
937 disp = dseg_add_s4(cd, iptr->sx.val.i);
938 M_ILD_DSEG(REG_ITMP2, disp);
939 M_IMUL(REG_ITMP2, d);
941 emit_store_dst(jd, iptr, d);
944 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
945 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
947 /* load s1 into r0 */
949 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
950 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
951 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
953 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
955 /* extend s1 to long */
957 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
961 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
967 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
968 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
971 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
972 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
976 emit_store_dst(jd, iptr, d);
980 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
981 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
983 bte = iptr->sx.s23.s3.bte;
986 /* test s2 for zero */
988 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
989 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
990 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
991 emit_arithmetic_check(cd, iptr, REG_ITMP3);
995 disp = dseg_add_functionptr(cd, bte->fp);
999 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
1001 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
1002 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
1006 M_ASUB_IMM(96, REG_SP);
1007 M_ALD_DSEG(REG_ITMP2, disp);
1008 M_JSR(REG_RA, REG_ITMP2);
1009 M_AADD_IMM(96, REG_SP);
1013 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1014 M_LNGMOVE(REG_RESULT_PACKED, d);
1015 emit_store_dst(jd, iptr, d);
1019 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1020 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1021 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1023 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1024 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1025 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1027 /* Use only 5 bits of sencond operand. */
1029 M_INTMOVE(s2, REG_ITMP2);
1031 ICONST(REG_ITMP3, 0x1F);
1032 M_IAND(REG_ITMP3, s2);
1036 switch (iptr->opc) {
1049 emit_store_dst(jd, iptr, d);
1052 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1053 /* sx.val.i = constant */
1057 assert(iptr->sx.val.i <= 32);
1059 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1060 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1067 s3 = (1 << iptr->sx.val.i) - 1;
1069 if (N_VALID_IMM(s3)) {
1072 ICONST(REG_ITMP1, -1);
1073 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1074 M_IADD(REG_ITMP1, d);
1077 N_BRC_BACK_PATCH(ref);
1079 M_SRA_IMM(iptr->sx.val.i, d);
1081 emit_store_dst(jd, iptr, d);
1086 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1087 /* sx.val.i = constant */
1089 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1090 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1093 M_MOV(s1, REG_ITMP1);
1097 ICONST(REG_ITMP3, iptr->sx.val.i);
1100 M_IAND(REG_ITMP3, d);
1103 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1109 emit_store_dst(jd, iptr, d);
1113 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1114 /* sx.val.i = constant */
1115 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1116 /* sx.val.i = constant */
1117 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1118 /* sx.val.i = constant */
1119 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1120 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1124 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1126 switch (iptr->opc) {
1127 case ICMD_ISHLCONST:
1130 case ICMD_ISHRCONST:
1133 case ICMD_IUSHRCONST:
1140 emit_store_dst(jd, iptr, d);
1143 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1145 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1147 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1149 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1151 /* Use only 6 bits of second operand */
1153 M_INTMOVE(s2, REG_ITMP2);
1155 ICONST(REG_ITMP1, 0x3F);
1156 M_IAND(REG_ITMP1, s2);
1158 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1159 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1161 /* Destination must be even-odd pair */
1163 if (! N_IS_EVEN_ODD(d)) {
1164 d = REG_ITMP31_PACKED;
1167 assert(N_IS_EVEN_ODD(d));
1171 switch (iptr->opc) {
1173 M_SLDL(s2, GET_HIGH_REG(d));
1176 M_SRDA(s2, GET_HIGH_REG(d));
1179 M_SRDL(s2, GET_HIGH_REG(d));
1185 emit_copy_dst(jd, iptr, d);
1186 emit_store_dst(jd, iptr, d);
1190 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1191 /* sx.val.i = constant */
1192 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1193 /* sx.val.i = constant */
1194 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1195 /* sx.val.l = constant */
1198 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1199 if (! N_IS_EVEN_ODD(d)) {
1200 d = REG_ITMP31_PACKED;
1202 assert(N_IS_EVEN_ODD(d));
1204 s1 = emit_load_s1(jd, iptr, d);
1208 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1210 switch (iptr->opc) {
1211 case ICMD_LSHLCONST:
1212 N_SLDL(GET_HIGH_REG(d), disp, RN);
1214 case ICMD_LSHRCONST:
1215 N_SRDA(GET_HIGH_REG(d), disp, RN);
1217 case ICMD_LUSHRCONST:
1218 N_SRDL(GET_HIGH_REG(d), disp, RN);
1221 N_SLDL(GET_HIGH_REG(d), disp, RN);
1227 emit_copy_dst(jd, iptr, d);
1228 emit_store_dst(jd, iptr, d);
1231 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1233 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1234 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1235 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1242 emit_store_dst(jd, iptr, d);
1246 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1248 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1249 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1250 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1257 emit_store_dst(jd, iptr, d);
1261 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1263 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1264 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1265 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1272 emit_store_dst(jd, iptr, d);
1278 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1279 /* sx.val.i = constant */
1280 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1281 /* sx.val.i = constant */
1282 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1283 /* sx.val.i = constant */
1285 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1286 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1289 ICONST(REG_ITMP2, iptr->sx.val.i);
1291 switch (iptr->opc) {
1292 case ICMD_IANDCONST:
1293 M_IAND(REG_ITMP2, d);
1295 case ICMD_IXORCONST:
1296 M_IXOR(REG_ITMP2, d);
1299 M_IOR(REG_ITMP2, d);
1305 emit_store_dst(jd, iptr, d);
1309 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1310 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1311 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1313 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1315 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1316 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1317 dd = GET_LOW_REG(d);
1319 switch (iptr->opc) {
1348 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1349 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1350 dd = GET_HIGH_REG(d);
1352 switch (iptr->opc) {
1381 emit_store_dst(jd, iptr, d);
1384 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1385 /* sx.val.l = constant */
1386 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1387 /* sx.val.l = constant */
1388 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1389 /* sx.val.l = constant */
1391 /* TODO should use memory operand to access data segment, not load */
1393 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1395 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1396 s3 = iptr->sx.val.l & 0xffffffff;
1398 M_INTMOVE(s1, GET_LOW_REG(d));
1400 ICONST(REG_ITMP3, s3);
1402 switch (iptr->opc) {
1403 case ICMD_LANDCONST:
1404 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1406 case ICMD_LXORCONST:
1407 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1410 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1416 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1417 s3 = iptr->sx.val.l >> 32;
1419 M_INTMOVE(s1, GET_HIGH_REG(d));
1421 ICONST(REG_ITMP3, s3);
1423 switch (iptr->opc) {
1424 case ICMD_LANDCONST:
1425 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1427 case ICMD_LXORCONST:
1428 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1431 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1437 emit_store_dst(jd, iptr, d);
1441 /* floating operations ************************************************/
1443 case ICMD_FNEG: /* ..., value ==> ..., - value */
1444 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1445 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1447 emit_store_dst(jd, iptr, d);
1450 case ICMD_DNEG: /* ..., value ==> ..., - value */
1451 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1452 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1454 emit_store_dst(jd, iptr, d);
1457 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1458 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1459 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1460 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1467 emit_store_dst(jd, iptr, d);
1470 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1471 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1472 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1473 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1480 emit_store_dst(jd, iptr, d);
1483 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1484 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1485 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1486 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1490 emit_store_dst(jd, iptr, d);
1493 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1494 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1495 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1496 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1500 emit_store_dst(jd, iptr, d);
1503 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1504 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1505 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1506 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1513 emit_store_dst(jd, iptr, d);
1516 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1517 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1518 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1519 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1526 emit_store_dst(jd, iptr, d);
1529 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1530 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1531 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1532 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1536 emit_store_dst(jd, iptr, d);
1539 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1540 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1541 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1542 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1546 emit_store_dst(jd, iptr, d);
1549 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1550 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1551 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1553 emit_store_dst(jd, iptr, d);
1556 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1557 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1558 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1560 emit_store_dst(jd, iptr, d);
1563 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1567 #ifdef SUPPORT_HERCULES
1571 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1572 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1576 switch (iptr->opc) {
1585 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1586 N_LHI(d, 0); /* Load 0 */
1587 ref1 = cd->mcodeptr;
1588 N_BRC(DD_ANY, 0); /* Exit */
1592 switch (iptr->opc) {
1601 #ifdef SUPPORT_HERCULES
1602 /* Hercules does the conversion using a plain C conversion.
1603 * According to manual, real hardware should *NOT* require this.
1605 * Corner case: Positive float leads to INT_MIN (overflow).
1608 switch (iptr->opc) {
1617 ref2 = cd->mcodeptr;
1618 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1622 ref3 = cd->mcodeptr;
1623 M_BGE(0); /* If integer result is negative, continue */
1625 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1626 M_ILD_DSEG(d, disp);
1628 N_BRC_BACK_PATCH(ref1);
1629 #ifdef SUPPORT_HERCULES
1630 N_BRC_BACK_PATCH(ref2);
1631 N_BRC_BACK_PATCH(ref3);
1633 emit_store_dst(jd, iptr, d);
1637 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1640 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1641 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1642 #ifdef SUPPORT_HERCULES
1645 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1646 disp = dseg_add_double(cd, 0.0 / 0.0);
1647 M_DLD_DSEG(d, disp, REG_ITMP1);
1648 emit_label_br(cd, BRANCH_LABEL_1);
1649 N_BRC_BACK_PATCH(ref);
1652 #ifdef SUPPORT_HERCULES
1653 emit_label(cd, BRANCH_LABEL_1);
1655 emit_store_dst(jd, iptr, d);
1659 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1660 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1661 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1663 emit_store_dst(jd, iptr, d);
1666 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1667 /* == => 0, < => 1, > => -1 */
1671 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1672 /* == => 0, < => 1, > => -1 */
1675 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1676 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1677 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1679 switch (iptr->opc) {
1691 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1692 SZ_BRC + SZ_BRC + SZ_BRC
1695 N_BRC( /* load -1 */
1696 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1697 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1702 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1705 N_LHI(d, 1); /* GT */
1706 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1707 N_LHI(d, -1); /* LT */
1708 M_BR(SZ_BRC + SZ_LHI);
1709 N_LHI(d, 0); /* EQ */
1711 emit_store_dst(jd, iptr, d);
1716 /* memory operations **************************************************/
1718 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1720 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1721 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1723 /* implicit null-pointer check */
1724 M_ILD(d, s1, OFFSET(java_array_t, size));
1725 emit_store_dst(jd, iptr, d);
1729 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1730 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1731 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1732 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1734 /* implicit null-pointer check */
1735 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1737 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1742 emit_store_dst(jd, iptr, d);
1745 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1747 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1748 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1749 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1751 /* implicit null-pointer check */
1752 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1754 M_INTMOVE(s2, REG_ITMP2);
1755 M_SLL_IMM(1, REG_ITMP2);
1757 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1759 /* N_LH does sign extends, undo ! */
1764 emit_store_dst(jd, iptr, d);
1767 case ICMD_SALOAD: /* ..., 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(1, REG_ITMP2);
1778 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1779 emit_store_dst(jd, iptr, d);
1782 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1783 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1784 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1785 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1787 /* implicit null-pointer check */
1788 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1790 M_INTMOVE(s2, REG_ITMP2);
1791 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1792 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1793 emit_store_dst(jd, iptr, d);
1796 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1798 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1799 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1801 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1803 /* implicit null-pointer check */
1804 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1806 M_INTMOVE(s2, REG_ITMP2);
1807 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1810 GET_LOW_REG(d) /* maybe itmp3 */,
1811 OFFSET(java_intarray_t, data[0]) + 4,
1812 REG_ITMP2, s1 /* maybe itmp1 */
1816 GET_HIGH_REG(d) /* maybe itmp1 */,
1817 OFFSET(java_intarray_t, data[0]),
1818 REG_ITMP2, s1 /* maybe itmp1 */
1821 emit_store_dst(jd, iptr, d);
1825 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1827 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1828 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1829 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1831 /* implicit null-pointer check */
1832 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1834 M_INTMOVE(s2, REG_ITMP2);
1835 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1837 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1839 emit_store_dst(jd, iptr, d);
1842 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1843 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1844 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1845 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1847 /* implicit null-pointer check */
1848 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1850 M_INTMOVE(s2, REG_ITMP2);
1851 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1853 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1855 emit_store_dst(jd, iptr, d);
1858 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1859 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1860 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1861 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1863 /* implicit null-pointer check */
1864 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1866 M_INTMOVE(s2, REG_ITMP2);
1867 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1868 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1869 emit_store_dst(jd, iptr, d);
1872 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1873 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1874 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1875 /* implicit null-pointer check */
1876 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1877 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1879 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1882 case ICMD_CASTORE: /* ..., 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_chararray_t, data[0]), REG_ITMP2, s1);
1897 case ICMD_SASTORE: /* ..., 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);
1902 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1904 M_INTMOVE(s2, REG_ITMP2);
1905 M_SLL_IMM(1, REG_ITMP2);
1907 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1910 case ICMD_IASTORE: /* ..., 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 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1919 M_INTMOVE(s2, REG_ITMP2);
1920 M_SLL_IMM(2, REG_ITMP2);
1922 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1925 case ICMD_LASTORE: /* ..., 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);
1932 M_INTMOVE(s2, REG_ITMP2);
1933 M_SLL_IMM(3, REG_ITMP2);
1935 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1936 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1937 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1938 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1941 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1942 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1943 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1944 /* implicit null-pointer check */
1945 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1946 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1948 M_INTMOVE(s2, REG_ITMP2);
1949 M_SLL_IMM(2, REG_ITMP2);
1951 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1954 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1955 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
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_FTMP1);
1961 M_INTMOVE(s2, REG_ITMP2);
1962 M_SLL_IMM(3, REG_ITMP2);
1964 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1967 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1969 s1 = emit_load_s1(jd, iptr, REG_A0);
1970 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1971 /* implicit null-pointer check */
1972 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1973 s3 = emit_load_s3(jd, iptr, REG_A1);
1975 M_INTMOVE(s1, REG_A0);
1976 M_INTMOVE(s3, REG_A1);
1978 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1979 M_ALD_DSEG(REG_ITMP2, disp);
1980 M_ASUB_IMM(96, REG_SP);
1981 M_JSR(REG_RA, REG_ITMP2);
1982 M_AADD_IMM(96, REG_SP);
1984 emit_arraystore_check(cd, iptr);
1986 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1987 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1988 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1990 M_INTMOVE(s2, REG_ITMP2);
1991 M_SLL_IMM(2, REG_ITMP2);
1992 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1995 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1996 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2001 case ICMD_GETSTATIC: /* ... ==> ..., value */
2003 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2004 uf = iptr->sx.s23.s3.uf;
2005 fieldtype = uf->fieldref->parseddesc.fd->type;
2006 disp = dseg_add_unique_address(cd, NULL);
2008 /* PROFILE_CYCLE_STOP; */
2010 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2012 /* PROFILE_CYCLE_START; */
2015 fi = iptr->sx.s23.s3.fmiref->p.field;
2016 fieldtype = fi->type;
2017 disp = dseg_add_address(cd, fi->value);
2019 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2022 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
2024 PROFILE_CYCLE_START;
2028 M_ALD_DSEG(REG_ITMP1, disp);
2030 switch (fieldtype) {
2032 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2033 M_ILD(d, REG_ITMP1, 0);
2036 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2037 M_LLD(d, REG_ITMP1, 0);
2040 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2041 M_ALD(d, REG_ITMP1, 0);
2044 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2045 M_FLD(d, REG_ITMP1, 0);
2048 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2049 M_DLD(d, REG_ITMP1, 0);
2053 emit_store_dst(jd, iptr, d);
2057 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2059 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2060 uf = iptr->sx.s23.s3.uf;
2061 fieldtype = uf->fieldref->parseddesc.fd->type;
2062 disp = dseg_add_unique_address(cd, uf);
2064 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2067 fi = iptr->sx.s23.s3.fmiref->p.field;
2068 fieldtype = fi->type;
2069 disp = dseg_add_address(cd, fi->value);
2071 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2073 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
2074 PROFILE_CYCLE_START;
2078 M_ALD_DSEG(REG_ITMP1, disp);
2079 switch (fieldtype) {
2081 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2082 M_IST(s1, REG_ITMP1, 0);
2085 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2086 M_LST(s1, REG_ITMP1, 0);
2089 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2090 M_AST(s1, REG_ITMP1, 0);
2093 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2094 M_FST(s1, REG_ITMP1, 0);
2097 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2098 M_DST(s1, REG_ITMP1, 0);
2103 case ICMD_GETFIELD: /* ... ==> ..., value */
2105 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2106 emit_nullpointer_check(cd, iptr, s1);
2108 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2109 uf = iptr->sx.s23.s3.uf;
2110 fieldtype = uf->fieldref->parseddesc.fd->type;
2113 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2116 fi = iptr->sx.s23.s3.fmiref->p.field;
2117 fieldtype = fi->type;
2121 switch (fieldtype) {
2123 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2127 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2128 if (GET_HIGH_REG(d) == s1) {
2129 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2130 M_ILD(GET_HIGH_REG(d), s1, disp);
2133 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2134 M_ILD(GET_HIGH_REG(d), s1, disp);
2138 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2142 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2146 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2150 emit_store_dst(jd, iptr, d);
2153 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2157 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2158 emit_nullpointer_check(cd, iptr, s1);
2160 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2161 uf = iptr->sx.s23.s3.uf;
2162 fieldtype = uf->fieldref->parseddesc.fd->type;
2166 fi = iptr->sx.s23.s3.fmiref->p.field;
2167 fieldtype = fi->type;
2171 /* We can't add a patcher ref behind this load,
2172 * because the patcher would destroy REG_ITMP3.
2174 * We pass in the disp parameter, how many bytes
2175 * to skip to the to the actual store.
2177 * XXX this relies on patcher_add_patch_ref internals
2180 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2181 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2186 if (IS_INT_LNG_TYPE(fieldtype)) {
2187 if (IS_2_WORD_TYPE(fieldtype))
2188 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2190 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2192 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2195 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2196 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2199 switch (fieldtype) {
2201 M_IST(s2, s1, disp);
2204 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2205 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2208 M_AST(s2, s1, disp);
2211 M_FST(s2, s1, disp);
2214 M_DST(s2, s1, disp);
2221 /* branch operations **************************************************/
2223 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2225 /* PROFILE_CYCLE_STOP; */
2227 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2228 M_INTMOVE(s1, REG_ITMP3_XPTR);
2230 #ifdef ENABLE_VERIFIER
2231 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2232 uc = iptr->sx.s23.s2.uc;
2234 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2236 #endif /* ENABLE_VERIFIER */
2238 disp = dseg_add_functionptr(cd, asm_handle_exception);
2239 M_ALD_DSEG(REG_ITMP1, disp);
2240 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2245 case ICMD_GOTO: /* ... ==> ... */
2246 case ICMD_RET: /* ... ==> ... */
2248 emit_br(cd, iptr->dst.block);
2252 case ICMD_JSR: /* ... ==> ... */
2254 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2258 case ICMD_IFNULL: /* ..., value ==> ... */
2259 case ICMD_IFNONNULL: /* ..., value ==> ... */
2260 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2262 switch (iptr->opc) {
2264 emit_beq(cd, iptr->dst.block);
2266 case ICMD_IFNONNULL:
2267 emit_bne(cd, iptr->dst.block);
2272 case ICMD_IFEQ: /* ..., value ==> ... */
2273 case ICMD_IFLT: /* ..., value ==> ... */
2274 case ICMD_IFLE: /* ..., value ==> ... */
2275 case ICMD_IFNE: /* ..., value ==> ... */
2276 case ICMD_IFGT: /* ..., value ==> ... */
2277 case ICMD_IFGE: /* ..., value ==> ... */
2279 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2281 if (N_VALID_IMM(iptr->sx.val.i))
2282 M_ICMP_IMM(s1, iptr->sx.val.i);
2284 disp = dseg_add_s4(cd, iptr->sx.val.i);
2285 if (N_VALID_DSEG_DISP(disp)) {
2286 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2288 ICONST(REG_ITMP2, disp);
2289 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2293 switch (iptr->opc) {
2295 emit_blt(cd, iptr->dst.block);
2298 emit_ble(cd, iptr->dst.block);
2301 emit_bne(cd, iptr->dst.block);
2304 emit_bgt(cd, iptr->dst.block);
2307 emit_bge(cd, iptr->dst.block);
2310 emit_beq(cd, iptr->dst.block);
2316 case ICMD_IF_LLT: /* ..., value ==> ... */
2317 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2323 /* ATTENTION: compare high words signed and low words unsigned */
2325 # define LABEL_OUT BRANCH_LABEL_1
2327 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2329 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2330 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2332 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2333 if (N_VALID_DSEG_DISP(disp)) {
2334 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2336 ICONST(REG_ITMP2, disp);
2337 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2344 emit_blt(cd, iptr->dst.block);
2345 /* EQ ... fall through */
2346 emit_label_bgt(cd, LABEL_OUT);
2350 emit_bgt(cd, iptr->dst.block);
2351 /* EQ ... fall through */
2352 emit_label_blt(cd, LABEL_OUT);
2355 /* EQ ... fall through */
2356 emit_label_bne(cd, LABEL_OUT);
2359 /* EQ ... fall through */
2360 emit_bne(cd, iptr->dst.block);
2366 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2368 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2369 if (N_VALID_DSEG_DISP(disp)) {
2370 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2372 ICONST(REG_ITMP2, disp);
2373 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2378 emit_blt(cd, iptr->dst.block);
2379 emit_label(cd, LABEL_OUT);
2382 emit_ble(cd, iptr->dst.block);
2383 emit_label(cd, LABEL_OUT);
2386 emit_bgt(cd, iptr->dst.block);
2387 emit_label(cd, LABEL_OUT);
2390 emit_bge(cd, iptr->dst.block);
2391 emit_label(cd, LABEL_OUT);
2394 emit_beq(cd, iptr->dst.block);
2395 emit_label(cd, LABEL_OUT);
2398 emit_bne(cd, iptr->dst.block);
2407 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2408 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2410 /* Compare addresses as 31 bit unsigned integers */
2412 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2413 M_LDA(REG_ITMP1, s1, 0);
2415 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2416 M_LDA(REG_ITMP2, s2, 0);
2418 M_CMP(REG_ITMP1, REG_ITMP2);
2420 switch (iptr->opc) {
2421 case ICMD_IF_ACMPEQ:
2422 emit_beq(cd, iptr->dst.block);
2424 case ICMD_IF_ACMPNE:
2425 emit_bne(cd, iptr->dst.block);
2431 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2432 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2433 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2434 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2435 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2436 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2438 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2439 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2441 switch (iptr->opc) {
2442 case ICMD_IF_ICMPEQ:
2443 emit_beq(cd, iptr->dst.block);
2445 case ICMD_IF_ICMPNE:
2446 emit_bne(cd, iptr->dst.block);
2448 case ICMD_IF_ICMPLT:
2449 emit_blt(cd, iptr->dst.block);
2451 case ICMD_IF_ICMPGT:
2452 emit_bgt(cd, iptr->dst.block);
2454 case ICMD_IF_ICMPLE:
2455 emit_ble(cd, iptr->dst.block);
2457 case ICMD_IF_ICMPGE:
2458 emit_bge(cd, iptr->dst.block);
2464 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2465 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2466 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2467 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2468 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2469 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2474 /* ATTENTION: compare high words signed and low words unsigned */
2476 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2477 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2482 case ICMD_IF_LCMPLT:
2483 case ICMD_IF_LCMPLE:
2484 emit_blt(cd, iptr->dst.block);
2485 /* EQ ... fall through */
2486 out_ref = cd->mcodeptr;
2489 case ICMD_IF_LCMPGT:
2490 case ICMD_IF_LCMPGE:
2491 emit_bgt(cd, iptr->dst.block);
2492 /* EQ ... fall through */
2493 out_ref = cd->mcodeptr;
2496 case ICMD_IF_LCMPEQ:
2497 /* EQ ... fall through */
2498 out_ref = cd->mcodeptr;
2501 case ICMD_IF_LCMPNE:
2502 /* EQ ... fall through */
2503 emit_bne(cd, iptr->dst.block);
2509 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2510 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2515 case ICMD_IF_LCMPLT:
2516 emit_blt(cd, iptr->dst.block);
2518 case ICMD_IF_LCMPLE:
2519 emit_ble(cd, iptr->dst.block);
2521 case ICMD_IF_LCMPGT:
2522 emit_bgt(cd, iptr->dst.block);
2524 case ICMD_IF_LCMPGE:
2525 emit_bge(cd, iptr->dst.block);
2527 case ICMD_IF_LCMPEQ:
2528 emit_beq(cd, iptr->dst.block);
2530 case ICMD_IF_LCMPNE:
2531 emit_bne(cd, iptr->dst.block);
2537 if (out_ref != NULL) {
2538 N_BRC_BACK_PATCH(out_ref);
2544 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2546 REPLACEMENT_POINT_RETURN(cd, iptr);
2547 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2548 M_INTMOVE(s1, REG_RESULT);
2549 goto nowperformreturn;
2551 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2553 REPLACEMENT_POINT_RETURN(cd, iptr);
2554 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2555 M_INTMOVE(s1, REG_RESULT);
2557 #ifdef ENABLE_VERIFIER
2558 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2559 unresolved_class *uc = iptr->sx.s23.s2.uc;
2562 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2563 PROFILE_CYCLE_START;
2565 #endif /* ENABLE_VERIFIER */
2566 goto nowperformreturn;
2568 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2570 REPLACEMENT_POINT_RETURN(cd, iptr);
2571 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2572 M_LNGMOVE(s1, REG_RESULT_PACKED);
2573 goto nowperformreturn;
2575 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2578 REPLACEMENT_POINT_RETURN(cd, iptr);
2579 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2580 M_FLTMOVE(s1, REG_FRESULT);
2581 goto nowperformreturn;
2583 case ICMD_RETURN: /* ... ==> ... */
2585 REPLACEMENT_POINT_RETURN(cd, iptr);
2591 p = cd->stackframesize;
2593 /* call trace function */
2595 #if !defined(NDEBUG)
2596 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2597 emit_verbosecall_exit(jd);
2598 #endif /* !defined(NDEBUG) */
2600 #if defined(ENABLE_THREADS)
2601 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2602 /* we need to save the proper return value */
2604 switch (iptr->opc) {
2606 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2610 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2613 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2616 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2620 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2622 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2623 M_ALD_DSEG(REG_ITMP2, disp);
2625 M_ASUB_IMM(96, REG_SP);
2627 M_AADD_IMM(96, REG_SP);
2629 /* and now restore the proper return value */
2631 switch (iptr->opc) {
2633 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2637 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2640 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2643 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2649 /* restore return address */
2651 p--; M_ALD(REG_RA, REG_SP, p * 8);
2653 /* restore saved registers */
2655 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2656 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2658 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2659 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2662 /* deallocate stack */
2664 if (cd->stackframesize)
2665 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2667 /* generate method profiling code */
2675 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2678 branch_target_t *table;
2680 table = iptr->dst.table;
2682 l = iptr->sx.s23.s2.tablelow;
2683 i = iptr->sx.s23.s3.tablehigh;
2685 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2686 M_INTMOVE(s1, REG_ITMP1);
2690 } else if (N_VALID_IMM(-l)) {
2691 M_ISUB_IMM(l, REG_ITMP1);
2693 ICONST(REG_ITMP2, l);
2694 M_ISUB(REG_ITMP2, REG_ITMP1);
2697 /* number of targets */
2703 ICONST(REG_ITMP2, i);
2704 M_ICMPU(REG_ITMP1, REG_ITMP2);
2705 emit_bge(cd, table[0].block);
2707 /* build jump table top down and use address of lowest entry */
2712 dseg_add_target(cd, table->block);
2717 /* length of dataseg after last dseg_add_target is used by load */
2719 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2720 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2721 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2722 M_JMP(RN, REG_ITMP1);
2727 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2730 lookup_target_t *lookup;
2732 lookup = iptr->dst.lookup;
2734 i = iptr->sx.s23.s2.lookupcount;
2736 MCODECHECK(8 + ((7 + 6) * i) + 5);
2737 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2740 if (N_VALID_IMM(lookup->value)) {
2741 M_ICMP_IMM(s1, lookup->value);
2743 ICONST(REG_ITMP2, lookup->value);
2744 M_ICMP(REG_ITMP2, s1);
2746 emit_beq(cd, lookup->target.block);
2750 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2755 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2757 bte = iptr->sx.s23.s3.bte;
2761 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2762 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2763 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2764 case ICMD_INVOKEINTERFACE:
2766 REPLACEMENT_POINT_INVOKE(cd, iptr);
2768 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2770 um = iptr->sx.s23.s3.um;
2771 md = um->methodref->parseddesc.md;
2774 lm = iptr->sx.s23.s3.fmiref->p.method;
2776 md = lm->parseddesc;
2780 s3 = md->paramcount;
2782 MCODECHECK((s3 << 1) + 64);
2784 /* copy arguments to registers or stack location */
2786 for (s3 = s3 - 1; s3 >= 0; s3--) {
2787 var = VAR(iptr->sx.s23.s2.args[s3]);
2789 /* Already Preallocated? */
2790 if (var->flags & PREALLOC)
2793 if (IS_INT_LNG_TYPE(var->type)) {
2794 if (!md->params[s3].inmemory) {
2795 if (IS_2_WORD_TYPE(var->type)) {
2797 GET_LOW_REG(md->params[s3].regoff),
2798 GET_HIGH_REG(md->params[s3].regoff)
2800 d = emit_load(jd, iptr, var, s1);
2804 s1 = md->params[s3].regoff;
2805 d = emit_load(jd, iptr, var, s1);
2810 if (IS_2_WORD_TYPE(var->type)) {
2811 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2812 M_LST(d, REG_SP, md->params[s3].regoff);
2815 d = emit_load(jd, iptr, var, REG_ITMP1);
2816 M_IST(d, REG_SP, md->params[s3].regoff);
2821 if (!md->params[s3].inmemory) {
2822 s1 = md->params[s3].regoff;
2823 d = emit_load(jd, iptr, var, s1);
2827 d = emit_load(jd, iptr, var, REG_FTMP1);
2828 if (IS_2_WORD_TYPE(var->type))
2829 M_DST(d, REG_SP, md->params[s3].regoff);
2831 M_FST(d, REG_SP, md->params[s3].regoff);
2836 /* generate method profiling code */
2840 switch (iptr->opc) {
2842 if (bte->stub == NULL) {
2843 disp = dseg_add_functionptr(cd, bte->fp);
2844 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2846 disp = dseg_add_functionptr(cd, bte->stub);
2849 if (N_VALID_DSEG_DISP(disp)) {
2850 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2852 N_LHI(REG_ITMP1, disp);
2853 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2857 case ICMD_INVOKESPECIAL:
2859 /* Implicit NULL pointer check */
2860 M_ILD(REG_ITMP1, REG_A0, 0);
2864 case ICMD_INVOKESTATIC:
2866 disp = dseg_add_unique_address(cd, um);
2868 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2872 disp = dseg_add_address(cd, lm->stubroutine);
2874 if (N_VALID_DSEG_DISP(disp)) {
2875 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2877 N_LHI(REG_ITMP1, disp);
2878 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2882 case ICMD_INVOKEVIRTUAL:
2883 /* TODO softnull REG_A0 */
2886 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2891 s1 = OFFSET(vftbl_t, table[0]) +
2892 sizeof(methodptr) * lm->vftblindex;
2895 /* implicit null-pointer check */
2897 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2898 M_ALD(REG_PV, REG_METHODPTR, s1);
2901 case ICMD_INVOKEINTERFACE:
2902 /* TODO softnull REG_A0 */
2904 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2905 * and -0xFFF in index register (itmp1)
2909 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2915 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2916 sizeof(methodptr*) * lm->class->index;
2918 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2921 /* Implicit null-pointer check */
2922 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2923 N_LHI(REG_ITMP2, s1);
2924 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2925 M_ALD(REG_PV, REG_METHODPTR, s2);
2929 /* generate the actual call */
2932 emit_restore_pv(cd);
2934 /* post call finalization */
2936 switch (iptr->opc) {
2938 if (bte->stub == NULL) {
2939 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2944 /* generate method profiling code */
2946 PROFILE_CYCLE_START;
2948 /* store size of call code in replacement point */
2950 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2952 /* store return value */
2954 d = md->returntype.type;
2956 if (d != TYPE_VOID) {
2957 if (IS_INT_LNG_TYPE(d)) {
2958 if (IS_2_WORD_TYPE(d)) {
2959 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2960 M_LNGMOVE(REG_RESULT_PACKED, s1);
2963 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2964 M_INTMOVE(REG_RESULT, s1);
2968 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2969 M_FLTMOVE(REG_FRESULT, s1);
2971 emit_store_dst(jd, iptr, s1);
2977 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2979 /* val.a: (classinfo*) superclass */
2981 /* superclass is an interface:
2983 * OK if ((sub == NULL) ||
2984 * (sub->vftbl->interfacetablelength > super->index) &&
2985 * (sub->vftbl->interfacetable[-super->index] != NULL));
2987 * superclass is a class:
2989 * OK if ((sub == NULL) || (0
2990 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2991 * super->vftbl->diffval));
2994 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2995 /* object type cast-check */
2998 vftbl_t *supervftbl;
3001 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3002 # define LABEL_CLASS BRANCH_LABEL_2
3003 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3004 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
3005 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
3007 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3013 super = iptr->sx.s23.s3.c.cls;
3014 superindex = super->index;
3015 supervftbl = super->vftbl;
3018 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3019 CODEGEN_CRITICAL_SECTION_NEW;
3021 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3023 /* if class is not resolved, check which code to call */
3025 if (super == NULL) {
3027 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3029 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3031 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3032 iptr->sx.s23.s3.c.ref,
3035 ICONST(REG_ITMP3, ACC_INTERFACE);
3037 if (N_VALID_DSEG_DISP(disp)) {
3038 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3040 ICONST(REG_ITMP2, disp);
3041 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3043 emit_label_beq(cd, LABEL_CLASS);
3046 /* interface checkcast code */
3048 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3049 if (super == NULL) {
3050 patcher_add_patch_ref(jd,
3051 PATCHER_checkcast_instanceof_interface,
3052 iptr->sx.s23.s3.c.ref,
3056 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3059 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3060 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3061 M_ISUB_IMM(superindex, REG_ITMP3);
3062 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3065 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3066 superindex * sizeof(methodptr*))
3068 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3069 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3071 if (super == NULL) {
3072 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3076 /* class checkcast code */
3078 if (super == NULL) {
3079 emit_label(cd, LABEL_CLASS);
3082 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3083 if (super == NULL) {
3084 disp = dseg_add_unique_address(cd, NULL);
3086 patcher_add_patch_ref(jd,
3087 PATCHER_resolve_classref_to_vftbl,
3088 iptr->sx.s23.s3.c.ref,
3092 disp = dseg_add_address(cd, supervftbl);
3094 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3098 CODEGEN_CRITICAL_SECTION_START;
3100 /* REG_ITMP3 := baseval(s1) */
3101 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3102 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3104 /* REG_ITMP2 := baseval(class) */
3105 M_ALD_DSEG(REG_ITMP2, disp);
3106 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3108 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3109 M_ISUB(REG_ITMP2, REG_ITMP3);
3111 /* REG_ITMP2 := diffval(class) */
3112 M_ALD_DSEG(REG_ITMP2, disp);
3113 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3115 CODEGEN_CRITICAL_SECTION_END;
3117 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3119 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3120 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3121 /* Branch if greater then */
3123 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3124 M_ALD_DSEG(REG_ITMP3, disp);
3126 CODEGEN_CRITICAL_SECTION_START;
3128 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3129 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3130 M_ISUB(REG_ITMP3, REG_ITMP2);
3131 M_ALD_DSEG(REG_ITMP3, disp);
3132 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3134 CODEGEN_CRITICAL_SECTION_END;
3136 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3137 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3138 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3139 /* Branch if greater then */
3141 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3144 if (super == NULL) {
3145 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3146 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3147 } else if (super->flags & ACC_INTERFACE) {
3148 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3150 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3153 d = codegen_reg_of_dst(jd, iptr, s1);
3155 # undef LABEL_EXIT_CHECK_NULL
3157 # undef LABEL_EXIT_INTERFACE_NULL
3158 # undef LABEL_EXIT_INTERFACE_DONE
3159 # undef LABEL_EXIT_CLASS_NULL
3162 /* array type cast-check */
3164 s1 = emit_load_s1(jd, iptr, REG_A0);
3165 M_INTMOVE(s1, REG_A0);
3167 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3168 disp = dseg_add_unique_address(cd, NULL);
3170 patcher_add_patch_ref(jd,
3171 PATCHER_resolve_classref_to_classinfo,
3172 iptr->sx.s23.s3.c.ref,
3176 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3178 M_ALD_DSEG(REG_A1, disp);
3179 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3180 M_ALD_DSEG(REG_ITMP1, disp);
3181 M_ASUB_IMM(96, REG_SP);
3182 M_JSR(REG_RA, REG_ITMP1);
3183 M_AADD_IMM(96, REG_SP);
3185 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3186 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3188 d = codegen_reg_of_dst(jd, iptr, s1);
3192 emit_store_dst(jd, iptr, d);
3195 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3196 /* val.a: (classinfo*) superclass */
3198 /* superclass is an interface:
3200 * return (sub != NULL) &&
3201 * (sub->vftbl->interfacetablelength > super->index) &&
3202 * (sub->vftbl->interfacetable[-super->index] != NULL);
3204 * superclass is a class:
3206 * return ((sub != NULL) && (0
3207 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3208 * super->vftbl->diffvall));
3210 * If superclass is unresolved, we include both code snippets
3211 * above, a patcher resolves the class' flags and we select
3212 * the right code at runtime.
3217 vftbl_t *supervftbl;
3220 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3226 super = iptr->sx.s23.s3.c.cls;
3227 superindex = super->index;
3228 supervftbl = super->vftbl;
3231 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3232 # define LABEL_CLASS BRANCH_LABEL_2
3233 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3234 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3235 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3236 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3238 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3239 CODEGEN_CRITICAL_SECTION_NEW;
3241 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3242 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3244 M_MOV(s1, REG_ITMP1);
3248 /* if class is not resolved, check which code to call */
3250 if (super == NULL) {
3254 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3256 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3258 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3259 iptr->sx.s23.s3.c.ref, disp);
3261 ICONST(REG_ITMP3, ACC_INTERFACE);
3263 if (N_VALID_DSEG_DISP(disp)) {
3264 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3266 ICONST(REG_ITMP2, disp);
3267 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3270 emit_label_beq(cd, LABEL_CLASS);
3273 /* interface instanceof code */
3275 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3276 if (super == NULL) {
3277 /* If d == REG_ITMP2, then it's destroyed in check
3282 patcher_add_patch_ref(jd,
3283 PATCHER_checkcast_instanceof_interface,
3284 iptr->sx.s23.s3.c.ref, 0);
3289 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3292 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3293 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3294 M_ISUB_IMM(superindex, REG_ITMP3);
3296 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3300 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3301 superindex * sizeof(methodptr*))
3303 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3305 /* d := (REG_ITMP1 != 0) */
3307 N_LTR(d, REG_ITMP1);
3308 M_BEQ(SZ_BRC + SZ_LHI);
3311 if (super == NULL) {
3312 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3316 /* class instanceof code */
3318 if (super == NULL) {
3319 emit_label(cd, LABEL_CLASS);
3322 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3323 if (super == NULL) {
3324 disp = dseg_add_unique_address(cd, NULL);
3326 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3327 iptr->sx.s23.s3.c.ref,
3331 disp = dseg_add_address(cd, supervftbl);
3336 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3339 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3340 M_ALD_DSEG(REG_ITMP2, disp);
3342 CODEGEN_CRITICAL_SECTION_START;
3344 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3345 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3346 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3348 CODEGEN_CRITICAL_SECTION_END;
3350 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3352 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3354 M_BGT(SZ_BRC + SZ_LHI);
3358 if (super == NULL) {
3359 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3360 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3361 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3362 } else if (super->flags & ACC_INTERFACE) {
3363 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3364 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3366 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3369 # undef LABEL_EXIT_CHECK_NULL
3371 # undef LABEL_EXIT_INTERFACE_NULL
3372 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3373 # undef LABEL_EXIT_INTERFACE_DONE
3374 # undef LABEL_EXIT_CLASS_NULL
3376 emit_store_dst(jd, iptr, d);
3382 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3384 /* check for negative sizes and copy sizes to stack if necessary */
3386 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3389 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3391 /* copy SAVEDVAR sizes to stack */
3392 var = VAR(iptr->sx.s23.s2.args[s1]);
3394 /* Already Preallocated? */
3395 if (!(var->flags & PREALLOC)) {
3396 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3397 M_IST(s2, REG_SP, s1 * 4);
3401 /* is a patcher function set? */
3403 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3404 disp = dseg_add_unique_address(cd, 0);
3406 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3407 iptr->sx.s23.s3.c.ref,
3411 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3413 /* a0 = dimension count */
3415 ICONST(REG_A0, iptr->s1.argcount);
3417 /* a1 = classinfo */
3419 M_ALD_DSEG(REG_A1, disp);
3421 /* a2 = pointer to dimensions = stack pointer */
3423 M_MOV(REG_SP, REG_A2);
3425 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3426 M_ALD_DSEG(REG_ITMP1, disp);
3427 M_ASUB_IMM(96, REG_SP);
3428 M_JSR(REG_RA, REG_ITMP1);
3429 M_AADD_IMM(96, REG_SP);
3431 /* check for exception before result assignment */
3433 emit_exception_check(cd, iptr);
3435 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3436 M_INTMOVE(REG_RESULT, s1);
3437 emit_store_dst(jd, iptr, s1);
3442 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3446 } /* for instruction */
3448 MCODECHECK(512); /* XXX require a lower number? */
3450 /* At the end of a basic block we may have to append some nops,
3451 because the patcher stub calling code might be longer than the
3452 actual instruction. So codepatching does not change the
3453 following block unintentionally. */
3455 if (cd->mcodeptr < cd->lastmcodeptr) {
3456 while (cd->mcodeptr < cd->lastmcodeptr) {
3461 } /* if (bptr -> flags >= BBREACHED) */
3462 } /* for basic block */
3464 dseg_createlinenumbertable(cd);
3466 /* generate stubs */
3468 emit_patcher_traps(jd);
3470 /* everything's ok */
3476 /* codegen_emit_stub_compiler **************************************************
3478 Emits a stub routine which calls the compiler.
3480 *******************************************************************************/
3482 void codegen_emit_stub_compiler(jitdata *jd)
3487 /* get required compiler data */
3492 /* code for the stub */
3494 /* don't touch ITMP2 as it cointains the return address */
3496 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3498 /* REG_METHODPTR (REG_ITMP1) already used */
3499 M_ILD_DSEG(REG_ITMP3, -2 * SIZEOF_VOID_P); /* methodinfo */
3500 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3505 /* codegen_emit_stub_native ****************************************************
3507 Emits a stub routine which calls a native method.
3509 *******************************************************************************/
3512 arguments on stack \
3513 -------------------------------------------------| <- SP on nativestub entry
3515 callee saved int regs (none) |
3516 callee saved float regs (none) | stack frame like in cacao
3517 local variable slots (none) |
3518 arguments for calling methods (none) /
3519 ------------------------------------------------------------------ <- datasp
3524 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3525 0 - 96 register save area for callee /
3526 -------------------------------------------------------- <- SP native method
3528 SP after method entry
3531 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3537 s4 i, j; /* count variables */
3542 /* get required compiler data */
3548 /* set some variables */
3552 /* calculate stackframe size */
3554 cd->stackframesize =
3555 1 + /* return address */
3556 sizeof(stackframeinfo) / 8 +
3557 sizeof(localref_table) / 8 +
3560 (96 / 8); /* linkage area */
3562 /* keep stack 8-byte aligned */
3564 /*ALIGN_2(cd->stackframesize);*/
3566 /* create method header */
3568 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3569 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3570 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3571 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3572 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3573 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3574 (void) dseg_addlinenumbertablesize(cd);
3575 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3579 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3580 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3582 /* store return address */
3584 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3586 /* get function address (this must happen before the stackframeinfo) */
3588 funcdisp = dseg_add_functionptr(cd, f);
3591 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
3593 #if defined(ENABLE_GC_CACAO)
3594 /* Save callee saved integer registers in stackframeinfo (GC may
3595 need to recover them during a collection). */
3597 disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
3598 OFFSET(stackframeinfo, intregs);
3600 for (i = 0; i < INT_SAV_CNT; i++)
3601 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3604 /* save integer and float argument registers */
3606 for (i = 0; i < md->paramcount; i++) {
3607 if (!md->params[i].inmemory) {
3608 s1 = md->params[i].regoff;
3610 switch (md->paramtypes[i].type) {
3613 M_IST(s1, REG_SP, 96 + i * 8);
3616 M_LST(s1, REG_SP, 96 + i * 8);
3620 M_DST(s1, REG_SP, 96 + i * 8);
3626 /* create native stack info */
3628 M_MOV(REG_SP, REG_A0);
3629 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3630 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3631 M_ALD_DSEG(REG_ITMP2, disp);
3634 /* remember class argument */
3636 if (m->flags & ACC_STATIC)
3637 M_MOV(REG_RESULT, REG_ITMP3);
3639 /* restore integer and float argument registers */
3641 for (i = 0; i < md->paramcount; i++) {
3642 if (!md->params[i].inmemory) {
3643 s1 = md->params[i].regoff;
3645 switch (md->paramtypes[i].type) {
3648 M_ILD(s1, REG_SP, 96 + i * 8);
3651 M_LLD(s1, REG_SP, 96 + i * 8);
3655 M_DLD(s1, REG_SP, 96 + i * 8);
3661 /* copy or spill arguments to new locations */
3663 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3664 t = md->paramtypes[i].type;
3666 if (IS_INT_LNG_TYPE(t)) {
3667 if (!md->params[i].inmemory) {
3668 s1 = md->params[i].regoff;
3669 s2 = nmd->params[j].regoff;
3671 if (!nmd->params[j].inmemory) {
3672 if (IS_2_WORD_TYPE(t))
3678 if (IS_2_WORD_TYPE(t))
3679 M_LST(s1, REG_SP, s2);
3681 M_IST(s1, REG_SP, s2);
3685 s1 = md->params[i].regoff + cd->stackframesize * 8;
3686 s2 = nmd->params[j].regoff;
3688 if (IS_2_WORD_TYPE(t)) {
3689 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3691 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3696 /* We only copy spilled float arguments, as the float
3697 argument registers keep unchanged. */
3699 if (md->params[i].inmemory) {
3700 s1 = md->params[i].regoff + cd->stackframesize * 8;
3701 s2 = nmd->params[j].regoff;
3703 if (IS_2_WORD_TYPE(t)) {
3704 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3706 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3712 /* Handle native Java methods. */
3714 if (m->flags & ACC_NATIVE) {
3715 /* put class into second argument register */
3717 if (m->flags & ACC_STATIC)
3718 M_MOV(REG_ITMP3, REG_A1);
3720 /* put env into first argument register */
3722 disp = dseg_add_address(cd, _Jv_env);
3723 M_ALD_DSEG(REG_A0, disp);
3726 /* generate the actual native call */
3728 M_ALD_DSEG(REG_ITMP2, funcdisp);
3731 /* save return value */
3733 switch (md->returntype.type) {
3736 M_IST(REG_RESULT, REG_SP, 96);
3739 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3743 M_DST(REG_FRESULT, REG_SP, 96);
3749 /* remove native stackframe info */
3751 M_MOV(REG_SP, REG_A0);
3752 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3753 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3754 M_ALD_DSEG(REG_ITMP1, disp);
3757 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3759 /* restore return value */
3761 switch (md->returntype.type) {
3764 M_ILD(REG_RESULT, REG_SP, 96);
3767 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3771 M_DLD(REG_FRESULT, REG_SP, 96);
3777 #if defined(ENABLE_GC_CACAO)
3778 /* Restore callee saved integer registers from stackframeinfo (GC
3779 might have modified them during a collection). */
3781 disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
3782 OFFSET(stackframeinfo, intregs);
3784 for (i = 0; i < INT_SAV_CNT; i++)
3785 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3788 /* load return address */
3790 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3792 /* remove stackframe */
3794 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3796 /* check for exception */
3798 M_TEST(REG_ITMP3_XPTR);
3799 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3803 /* handle exception */
3805 M_MOV(REG_RA, REG_ITMP1_XPC);
3807 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3808 M_ALD_DSEG(REG_ITMP2, disp);
3809 M_JMP(RN, REG_ITMP2);
3811 /* generate patcher traps */
3813 emit_patcher_traps(jd);
3817 * These are local overrides for various environment variables in Emacs.
3818 * Please do not remove this and leave it at the end of the file, where
3819 * Emacs will automagically detect them.
3820 * ---------------------------------------------------------------------
3823 * indent-tabs-mode: t
3827 * vim:noexpandtab:sw=4:ts=4: