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);
2538 if (out_ref != NULL) {
2539 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2545 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2547 REPLACEMENT_POINT_RETURN(cd, iptr);
2548 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2549 M_INTMOVE(s1, REG_RESULT);
2550 goto nowperformreturn;
2552 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2554 REPLACEMENT_POINT_RETURN(cd, iptr);
2555 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2556 M_INTMOVE(s1, REG_RESULT);
2558 #ifdef ENABLE_VERIFIER
2559 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2560 unresolved_class *uc = iptr->sx.s23.s2.uc;
2563 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2564 PROFILE_CYCLE_START;
2566 #endif /* ENABLE_VERIFIER */
2567 goto nowperformreturn;
2569 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2571 REPLACEMENT_POINT_RETURN(cd, iptr);
2572 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2573 M_LNGMOVE(s1, REG_RESULT_PACKED);
2574 goto nowperformreturn;
2576 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2579 REPLACEMENT_POINT_RETURN(cd, iptr);
2580 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2581 M_FLTMOVE(s1, REG_FRESULT);
2582 goto nowperformreturn;
2584 case ICMD_RETURN: /* ... ==> ... */
2586 REPLACEMENT_POINT_RETURN(cd, iptr);
2592 p = cd->stackframesize;
2594 /* call trace function */
2596 #if !defined(NDEBUG)
2597 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2598 emit_verbosecall_exit(jd);
2599 #endif /* !defined(NDEBUG) */
2601 #if defined(ENABLE_THREADS)
2602 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2603 /* we need to save the proper return value */
2605 switch (iptr->opc) {
2607 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2611 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2614 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2617 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2621 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2623 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2624 M_ALD_DSEG(REG_ITMP2, disp);
2626 M_ASUB_IMM(96, REG_SP);
2628 M_AADD_IMM(96, REG_SP);
2630 /* and now restore the proper return value */
2632 switch (iptr->opc) {
2634 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2638 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2641 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2644 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2650 /* restore return address */
2652 p--; M_ALD(REG_RA, REG_SP, p * 8);
2654 /* restore saved registers */
2656 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2657 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2659 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2660 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2663 /* deallocate stack */
2665 if (cd->stackframesize)
2666 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2668 /* generate method profiling code */
2676 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2679 branch_target_t *table;
2681 table = iptr->dst.table;
2683 l = iptr->sx.s23.s2.tablelow;
2684 i = iptr->sx.s23.s3.tablehigh;
2686 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2687 M_INTMOVE(s1, REG_ITMP1);
2691 } else if (N_VALID_IMM(-l)) {
2692 M_ISUB_IMM(l, REG_ITMP1);
2694 ICONST(REG_ITMP2, l);
2695 M_ISUB(REG_ITMP2, REG_ITMP1);
2698 /* number of targets */
2704 ICONST(REG_ITMP2, i);
2705 M_ICMPU(REG_ITMP1, REG_ITMP2);
2706 emit_bge(cd, table[0].block);
2708 /* build jump table top down and use address of lowest entry */
2713 dseg_add_target(cd, table->block);
2718 /* length of dataseg after last dseg_add_target is used by load */
2720 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2721 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2722 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2723 M_JMP(RN, REG_ITMP1);
2728 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2731 lookup_target_t *lookup;
2733 lookup = iptr->dst.lookup;
2735 i = iptr->sx.s23.s2.lookupcount;
2737 MCODECHECK(8 + ((7 + 6) * i) + 5);
2738 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2741 if (N_VALID_IMM(lookup->value)) {
2742 M_ICMP_IMM(s1, lookup->value);
2744 ICONST(REG_ITMP2, lookup->value);
2745 M_ICMP(REG_ITMP2, s1);
2747 emit_beq(cd, lookup->target.block);
2751 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2756 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2758 bte = iptr->sx.s23.s3.bte;
2762 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2763 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2764 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2765 case ICMD_INVOKEINTERFACE:
2767 REPLACEMENT_POINT_INVOKE(cd, iptr);
2769 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2771 um = iptr->sx.s23.s3.um;
2772 md = um->methodref->parseddesc.md;
2775 lm = iptr->sx.s23.s3.fmiref->p.method;
2777 md = lm->parseddesc;
2781 s3 = md->paramcount;
2783 MCODECHECK((s3 << 1) + 64);
2785 /* copy arguments to registers or stack location */
2787 for (s3 = s3 - 1; s3 >= 0; s3--) {
2788 var = VAR(iptr->sx.s23.s2.args[s3]);
2790 /* Already Preallocated? */
2791 if (var->flags & PREALLOC)
2794 if (IS_INT_LNG_TYPE(var->type)) {
2795 if (!md->params[s3].inmemory) {
2796 if (IS_2_WORD_TYPE(var->type)) {
2798 GET_LOW_REG(md->params[s3].regoff),
2799 GET_HIGH_REG(md->params[s3].regoff)
2801 d = emit_load(jd, iptr, var, s1);
2805 s1 = md->params[s3].regoff;
2806 d = emit_load(jd, iptr, var, s1);
2811 if (IS_2_WORD_TYPE(var->type)) {
2812 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2813 M_LST(d, REG_SP, md->params[s3].regoff);
2816 d = emit_load(jd, iptr, var, REG_ITMP1);
2817 M_IST(d, REG_SP, md->params[s3].regoff);
2822 if (!md->params[s3].inmemory) {
2823 s1 = md->params[s3].regoff;
2824 d = emit_load(jd, iptr, var, s1);
2828 d = emit_load(jd, iptr, var, REG_FTMP1);
2829 if (IS_2_WORD_TYPE(var->type))
2830 M_DST(d, REG_SP, md->params[s3].regoff);
2832 M_FST(d, REG_SP, md->params[s3].regoff);
2837 /* generate method profiling code */
2841 switch (iptr->opc) {
2843 disp = dseg_add_functionptr(cd, bte->fp);
2845 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2846 if (N_VALID_DSEG_DISP(disp)) {
2847 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2849 N_LHI(REG_ITMP1, disp);
2850 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2854 case ICMD_INVOKESPECIAL:
2856 /* Implicit NULL pointer check */
2857 M_ILD(REG_ITMP1, REG_A0, 0);
2861 case ICMD_INVOKESTATIC:
2863 disp = dseg_add_unique_address(cd, um);
2865 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2869 disp = dseg_add_address(cd, lm->stubroutine);
2871 if (N_VALID_DSEG_DISP(disp)) {
2872 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2874 N_LHI(REG_ITMP1, disp);
2875 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2879 case ICMD_INVOKEVIRTUAL:
2880 /* TODO softnull REG_A0 */
2883 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2888 s1 = OFFSET(vftbl_t, table[0]) +
2889 sizeof(methodptr) * lm->vftblindex;
2892 /* implicit null-pointer check */
2894 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2895 M_ALD(REG_PV, REG_METHODPTR, s1);
2898 case ICMD_INVOKEINTERFACE:
2899 /* TODO softnull REG_A0 */
2901 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2902 * and -0xFFF in index register (itmp1)
2906 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2912 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2913 sizeof(methodptr*) * lm->class->index;
2915 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2918 /* Implicit null-pointer check */
2919 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2920 N_LHI(REG_ITMP2, s1);
2921 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2922 M_ALD(REG_PV, REG_METHODPTR, s2);
2926 /* generate the actual call */
2929 emit_restore_pv(cd);
2931 /* post call finalization */
2933 switch (iptr->opc) {
2935 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2936 emit_exception_check(cd, iptr); /* check for exception */
2940 /* generate method profiling code */
2942 PROFILE_CYCLE_START;
2944 /* store size of call code in replacement point */
2946 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2948 /* store return value */
2950 d = md->returntype.type;
2952 if (d != TYPE_VOID) {
2953 if (IS_INT_LNG_TYPE(d)) {
2954 if (IS_2_WORD_TYPE(d)) {
2955 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2956 M_LNGMOVE(REG_RESULT_PACKED, s1);
2959 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2960 M_INTMOVE(REG_RESULT, s1);
2964 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2965 M_FLTMOVE(REG_FRESULT, s1);
2967 emit_store_dst(jd, iptr, s1);
2973 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2975 /* val.a: (classinfo*) superclass */
2977 /* superclass is an interface:
2979 * OK if ((sub == NULL) ||
2980 * (sub->vftbl->interfacetablelength > super->index) &&
2981 * (sub->vftbl->interfacetable[-super->index] != NULL));
2983 * superclass is a class:
2985 * OK if ((sub == NULL) || (0
2986 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2987 * super->vftbl->diffval));
2990 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2991 /* object type cast-check */
2994 vftbl_t *supervftbl;
2997 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2998 # define LABEL_CLASS BRANCH_LABEL_2
2999 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3000 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
3001 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
3003 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3009 super = iptr->sx.s23.s3.c.cls;
3010 superindex = super->index;
3011 supervftbl = super->vftbl;
3014 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3015 CODEGEN_CRITICAL_SECTION_NEW;
3017 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3019 /* if class is not resolved, check which code to call */
3021 if (super == NULL) {
3023 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3025 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3027 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3028 iptr->sx.s23.s3.c.ref,
3031 ICONST(REG_ITMP3, ACC_INTERFACE);
3033 if (N_VALID_DSEG_DISP(disp)) {
3034 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3036 ICONST(REG_ITMP2, disp);
3037 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3039 emit_label_beq(cd, LABEL_CLASS);
3042 /* interface checkcast code */
3044 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3045 if (super == NULL) {
3046 patcher_add_patch_ref(jd,
3047 PATCHER_checkcast_instanceof_interface,
3048 iptr->sx.s23.s3.c.ref,
3052 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3055 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3056 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3057 M_ISUB_IMM(superindex, REG_ITMP3);
3058 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3061 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3062 superindex * sizeof(methodptr*))
3064 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3065 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3067 if (super == NULL) {
3068 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3072 /* class checkcast code */
3074 if (super == NULL) {
3075 emit_label(cd, LABEL_CLASS);
3078 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3079 if (super == NULL) {
3080 disp = dseg_add_unique_address(cd, NULL);
3082 patcher_add_patch_ref(jd,
3083 PATCHER_resolve_classref_to_vftbl,
3084 iptr->sx.s23.s3.c.ref,
3088 disp = dseg_add_address(cd, supervftbl);
3090 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3094 CODEGEN_CRITICAL_SECTION_START;
3096 /* REG_ITMP3 := baseval(s1) */
3097 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3098 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3100 /* REG_ITMP2 := baseval(class) */
3101 M_ALD_DSEG(REG_ITMP2, disp);
3102 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3104 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3105 M_ISUB(REG_ITMP2, REG_ITMP3);
3107 /* REG_ITMP2 := diffval(class) */
3108 M_ALD_DSEG(REG_ITMP2, disp);
3109 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3111 CODEGEN_CRITICAL_SECTION_END;
3113 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3115 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3116 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3117 /* Branch if greater then */
3119 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3120 M_ALD_DSEG(REG_ITMP3, disp);
3122 CODEGEN_CRITICAL_SECTION_START;
3124 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3125 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3126 M_ISUB(REG_ITMP3, REG_ITMP2);
3127 M_ALD_DSEG(REG_ITMP3, disp);
3128 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3130 CODEGEN_CRITICAL_SECTION_END;
3132 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3133 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3134 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3135 /* Branch if greater then */
3137 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3140 if (super == NULL) {
3141 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3142 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3143 } else if (super->flags & ACC_INTERFACE) {
3144 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3146 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3149 d = codegen_reg_of_dst(jd, iptr, s1);
3151 # undef LABEL_EXIT_CHECK_NULL
3153 # undef LABEL_EXIT_INTERFACE_NULL
3154 # undef LABEL_EXIT_INTERFACE_DONE
3155 # undef LABEL_EXIT_CLASS_NULL
3158 /* array type cast-check */
3160 s1 = emit_load_s1(jd, iptr, REG_A0);
3161 M_INTMOVE(s1, REG_A0);
3163 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3164 disp = dseg_add_unique_address(cd, NULL);
3166 patcher_add_patch_ref(jd,
3167 PATCHER_resolve_classref_to_classinfo,
3168 iptr->sx.s23.s3.c.ref,
3172 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3174 M_ALD_DSEG(REG_A1, disp);
3175 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3176 M_ALD_DSEG(REG_ITMP1, disp);
3177 M_ASUB_IMM(96, REG_SP);
3178 M_JSR(REG_RA, REG_ITMP1);
3179 M_AADD_IMM(96, REG_SP);
3181 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3182 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3184 d = codegen_reg_of_dst(jd, iptr, s1);
3188 emit_store_dst(jd, iptr, d);
3191 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3192 /* val.a: (classinfo*) superclass */
3194 /* superclass is an interface:
3196 * return (sub != NULL) &&
3197 * (sub->vftbl->interfacetablelength > super->index) &&
3198 * (sub->vftbl->interfacetable[-super->index] != NULL);
3200 * superclass is a class:
3202 * return ((sub != NULL) && (0
3203 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3204 * super->vftbl->diffvall));
3206 * If superclass is unresolved, we include both code snippets
3207 * above, a patcher resolves the class' flags and we select
3208 * the right code at runtime.
3213 vftbl_t *supervftbl;
3216 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3222 super = iptr->sx.s23.s3.c.cls;
3223 superindex = super->index;
3224 supervftbl = super->vftbl;
3227 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3228 # define LABEL_CLASS BRANCH_LABEL_2
3229 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3230 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3231 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3232 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3234 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3235 CODEGEN_CRITICAL_SECTION_NEW;
3237 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3238 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3240 M_MOV(s1, REG_ITMP1);
3244 /* if class is not resolved, check which code to call */
3246 if (super == NULL) {
3250 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3252 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3254 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3255 iptr->sx.s23.s3.c.ref, disp);
3257 ICONST(REG_ITMP3, ACC_INTERFACE);
3259 if (N_VALID_DSEG_DISP(disp)) {
3260 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3262 ICONST(REG_ITMP2, disp);
3263 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3266 emit_label_beq(cd, LABEL_CLASS);
3269 /* interface instanceof code */
3271 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3272 if (super == NULL) {
3273 /* If d == REG_ITMP2, then it's destroyed in check
3278 patcher_add_patch_ref(jd,
3279 PATCHER_checkcast_instanceof_interface,
3280 iptr->sx.s23.s3.c.ref, 0);
3285 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3288 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3289 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3290 M_ISUB_IMM(superindex, REG_ITMP3);
3292 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3296 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3297 superindex * sizeof(methodptr*))
3299 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3301 /* d := (REG_ITMP1 != 0) */
3303 N_LTR(d, REG_ITMP1);
3304 M_BEQ(SZ_BRC + SZ_LHI);
3307 if (super == NULL) {
3308 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3312 /* class instanceof code */
3314 if (super == NULL) {
3315 emit_label(cd, LABEL_CLASS);
3318 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3319 if (super == NULL) {
3320 disp = dseg_add_unique_address(cd, NULL);
3322 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3323 iptr->sx.s23.s3.c.ref,
3327 disp = dseg_add_address(cd, supervftbl);
3332 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3335 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3336 M_ALD_DSEG(REG_ITMP2, disp);
3338 CODEGEN_CRITICAL_SECTION_START;
3340 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3341 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3342 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3344 CODEGEN_CRITICAL_SECTION_END;
3346 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3348 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3350 M_BGT(SZ_BRC + SZ_LHI);
3354 if (super == NULL) {
3355 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3356 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3357 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3358 } else if (super->flags & ACC_INTERFACE) {
3359 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3360 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3362 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3365 # undef LABEL_EXIT_CHECK_NULL
3367 # undef LABEL_EXIT_INTERFACE_NULL
3368 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3369 # undef LABEL_EXIT_INTERFACE_DONE
3370 # undef LABEL_EXIT_CLASS_NULL
3372 emit_store_dst(jd, iptr, d);
3378 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3380 /* check for negative sizes and copy sizes to stack if necessary */
3382 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3385 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3387 /* copy SAVEDVAR sizes to stack */
3388 var = VAR(iptr->sx.s23.s2.args[s1]);
3390 /* Already Preallocated? */
3391 if (!(var->flags & PREALLOC)) {
3392 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3393 M_IST(s2, REG_SP, s1 * 4);
3397 /* is a patcher function set? */
3399 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3400 disp = dseg_add_unique_address(cd, 0);
3402 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3403 iptr->sx.s23.s3.c.ref,
3407 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3409 /* a0 = dimension count */
3411 ICONST(REG_A0, iptr->s1.argcount);
3413 /* a1 = classinfo */
3415 M_ALD_DSEG(REG_A1, disp);
3417 /* a2 = pointer to dimensions = stack pointer */
3419 M_MOV(REG_SP, REG_A2);
3421 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3422 M_ALD_DSEG(REG_ITMP1, disp);
3423 M_ASUB_IMM(96, REG_SP);
3424 M_JSR(REG_RA, REG_ITMP1);
3425 M_AADD_IMM(96, REG_SP);
3427 /* check for exception before result assignment */
3429 emit_exception_check(cd, iptr);
3431 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3432 M_INTMOVE(REG_RESULT, s1);
3433 emit_store_dst(jd, iptr, s1);
3438 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3442 } /* for instruction */
3444 MCODECHECK(512); /* XXX require a lower number? */
3446 /* At the end of a basic block we may have to append some nops,
3447 because the patcher stub calling code might be longer than the
3448 actual instruction. So codepatching does not change the
3449 following block unintentionally. */
3451 if (cd->mcodeptr < cd->lastmcodeptr) {
3452 while (cd->mcodeptr < cd->lastmcodeptr) {
3457 } /* if (bptr -> flags >= BBREACHED) */
3458 } /* for basic block */
3460 dseg_createlinenumbertable(cd);
3462 /* generate stubs */
3464 emit_patcher_traps(jd);
3466 /* everything's ok */
3472 /* codegen_emit_stub_compiler **************************************************
3474 Emits a stub routine which calls the compiler.
3476 *******************************************************************************/
3478 void codegen_emit_stub_compiler(jitdata *jd)
3483 /* get required compiler data */
3488 /* code for the stub */
3490 /* don't touch ITMP2 as it cointains the return address */
3492 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3494 /* REG_METHODPTR (REG_ITMP1) already used */
3495 M_ILD_DSEG(REG_ITMP3, -2 * SIZEOF_VOID_P); /* methodinfo */
3496 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3501 /* codegen_emit_stub_native ****************************************************
3503 Emits a stub routine which calls a native method.
3505 *******************************************************************************/
3508 arguments on stack \
3509 -------------------------------------------------| <- SP on nativestub entry
3511 callee saved int regs (none) |
3512 callee saved float regs (none) | stack frame like in cacao
3513 local variable slots (none) |
3514 arguments for calling methods (none) /
3515 ------------------------------------------------------------------ <- datasp
3520 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3521 0 - 96 register save area for callee /
3522 -------------------------------------------------------- <- SP native method
3524 SP after method entry
3527 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3535 s4 i, j; /* count variables */
3540 /* get required compiler data */
3547 /* initialize variables */
3550 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3552 /* calculate stack frame size */
3554 cd->stackframesize =
3555 1 + /* r14 - return address */ +
3556 ((sizeof(stackframeinfo) + 7) / 8) +
3557 ((sizeof(localref_table) + 7) / 8) +
3559 (INT_ARG_CNT + FLT_ARG_CNT) +
3560 nmd->memuse + /* parameter passing */
3561 (96 / 8) /* required by ABI */;
3563 /* create method header */
3565 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3566 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3567 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3568 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3569 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3570 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3571 (void) dseg_addlinenumbertablesize(cd);
3572 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3574 /* generate stub code */
3576 N_AHI(REG_SP, -(cd->stackframesize * 8));
3577 N_AHI(REG_PV, N_PV_OFFSET);
3579 /* save return address */
3581 N_ST(REG_RA, (cd->stackframesize - 1) * 8, RN, REG_SP);
3583 /* generate native method profiling code */
3585 #if defined(ENABLE_PROFILING)
3586 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3587 /* count frequency */
3588 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
3589 ICONST(REG_ITMP2, 1);
3590 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
3591 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
3595 #if !defined(NDEBUG)
3596 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3597 emit_verbosecall_enter(jd);
3600 /* get function address (this must happen before the stackframeinfo) */
3602 disp = dseg_add_functionptr(cd, f);
3605 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, disp);
3607 M_ALD_DSEG(REG_ITMP1, disp);
3609 j = 96 + (nmd->memuse * 8);
3611 /* todo some arg registers are not volatile in C-abi terms */
3613 /* save integer and float argument registers */
3615 for (i = 0; i < md->paramcount; i++) {
3616 if (! md->params[i].inmemory) {
3617 s1 = md->params[i].regoff;
3618 t = md->paramtypes[i].type;
3620 if (IS_INT_LNG_TYPE(t)) {
3621 if (IS_2_WORD_TYPE(t)) {
3622 /* todo store multiple */
3623 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3624 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3626 N_ST(s1, j, RN, REG_SP);
3629 if (IS_2_WORD_TYPE(t)) {
3630 N_STD(s1, j, RN, REG_SP);
3632 N_STE(s1, j, RN, REG_SP);
3640 N_ST(REG_ITMP1, j, RN, REG_SP);
3642 /* create dynamic stack info */
3644 M_MOV(REG_SP, REG_A0); /* currentsp */
3645 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3647 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3648 M_ALD_DSEG(REG_ITMP1, disp);
3650 M_CALL(REG_ITMP1); /* call */
3652 /* remember class argument */
3654 if (m->flags & ACC_STATIC)
3655 N_LR(REG_ITMP3, REG_RESULT);
3657 /* restore integer and float argument registers */
3659 j = 96 + (nmd->memuse * 8);
3661 for (i = 0; i < md->paramcount; i++) {
3662 if (! md->params[i].inmemory) {
3663 s1 = md->params[i].regoff;
3664 t = md->paramtypes[i].type;
3666 if (IS_INT_LNG_TYPE(t)) {
3667 if (IS_2_WORD_TYPE(t)) {
3668 /* todo load multiple ! */
3669 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3670 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3672 N_L(s1, j, RN, REG_SP);
3675 if (IS_2_WORD_TYPE(t)) {
3676 N_LD(s1, j, RN, REG_SP);
3678 N_LE(s1, j, RN, REG_SP);
3686 N_L(REG_ITMP1, j, RN, REG_SP);
3688 /* copy or spill arguments to new locations */
3690 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3691 t = md->paramtypes[i].type;
3693 if (IS_INT_LNG_TYPE(t)) {
3695 if (!md->params[i].inmemory) {
3697 s1 = md->params[i].regoff;
3699 if (!nmd->params[j].inmemory) {
3700 s2 = nmd->params[j].regoff;
3701 if (IS_2_WORD_TYPE(t)) {
3717 s2 = nmd->params[j].regoff;
3718 if (IS_2_WORD_TYPE(t)) {
3733 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3734 s2 = nmd->params[j].regoff;
3736 if (IS_2_WORD_TYPE(t)) {
3737 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3739 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3744 /* We only copy spilled float arguments, as the float argument */
3745 /* registers keep unchanged. */
3747 if (md->params[i].inmemory) {
3748 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3749 s2 = nmd->params[j].regoff;
3751 if (IS_2_WORD_TYPE(t)) {
3752 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3754 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3760 /* put class into second argument register */
3762 if (m->flags & ACC_STATIC)
3763 M_MOV(REG_ITMP3, REG_A1);
3765 /* put env into first argument register */
3767 disp = dseg_add_address(cd, _Jv_env);
3768 M_ILD_DSEG(REG_A0, disp);
3770 /* do the native function call */
3772 M_CALL(REG_ITMP1); /* call */
3774 /* save return value */
3776 t = md->returntype.type;
3778 if (t != TYPE_VOID) {
3779 if (IS_INT_LNG_TYPE(t)) {
3780 if (IS_2_WORD_TYPE(t)) {
3781 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3783 N_ST(REG_RESULT, 96, RN, REG_SP);
3786 if (IS_2_WORD_TYPE(t)) {
3787 N_STD(REG_FRESULT, 96, RN, REG_SP);
3789 N_STE(REG_FRESULT, 96, RN, REG_SP);
3794 #if !defined(NDEBUG)
3795 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3796 emit_verbosecall_exit(jd);
3799 /* remove native stackframe info */
3801 M_MOV(REG_SP, REG_A0); /* currentsp */
3802 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3803 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3804 M_ALD_DSEG(REG_ITMP1, disp);
3806 N_LR(REG_ITMP3, REG_RESULT);
3808 /* restore return value */
3810 if (t != TYPE_VOID) {
3811 if (IS_INT_LNG_TYPE(t)) {
3812 if (IS_2_WORD_TYPE(t)) {
3813 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3815 N_L(REG_RESULT, 96, RN, REG_SP);
3818 if (IS_2_WORD_TYPE(t)) {
3819 N_LD(REG_FRESULT, 96, RN, REG_SP);
3821 N_LE(REG_FRESULT, 96, RN, REG_SP);
3826 /* load return address */
3828 N_L(REG_ITMP2, (cd->stackframesize - 1) * 8, RN, REG_SP);
3830 /* remove stackframe */
3832 N_AHI(REG_SP, cd->stackframesize * 8);
3834 /* test for exception */
3836 N_LTR(REG_ITMP3, REG_ITMP3);
3837 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3841 N_BCR(DD_ANY, REG_ITMP2);
3843 /* handle exception */
3845 M_MOV(REG_ITMP3, REG_ITMP3_XPTR);
3846 M_MOV(REG_ITMP2, REG_ITMP1_XPC); /* get return address from stack */
3850 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3853 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3854 M_ALD_DSEG(REG_ITMP2, disp);
3855 M_JMP(RN, REG_ITMP2);
3857 /* generate patcher stubs */
3859 emit_patcher_traps(jd);
3863 * These are local overrides for various environment variables in Emacs.
3864 * Please do not remove this and leave it at the end of the file, where
3865 * Emacs will automagically detect them.
3866 * ---------------------------------------------------------------------
3869 * indent-tabs-mode: t
3873 * vim:noexpandtab:sw=4:ts=4: