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 && code_is_synchronized(code)) {
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 (!code_is_leafmethod(code) || 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 /* IsSync contains the offset relative to the stack pointer for the
210 argument of monitor_exit used in the exception handler. Since the
211 offset could be zero and give a wrong meaning of the flag it is
214 /* XXX Remove this "offset by one". */
216 code->synchronizedoffset = (rd->memuse + 1) * 8;
218 /* REMOVEME: We still need it for exception handling in assembler. */
220 if (code_is_leafmethod(code))
221 (void) dseg_add_unique_s4(cd, 1);
223 (void) dseg_add_unique_s4(cd, 0);
225 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
226 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
228 (void) dseg_addlinenumbertablesize(cd);
230 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
232 /* create exception table */
234 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
235 dseg_add_target(cd, ex->start);
236 dseg_add_target(cd, ex->end);
237 dseg_add_target(cd, ex->handler);
238 (void) dseg_add_unique_address(cd, ex->catchtype.any);
243 M_AADD_IMM(N_PV_OFFSET, REG_PV);
245 /* create stack frame (if necessary) */
247 if (cd->stackframesize) {
248 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
251 /* store return address */
253 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
255 /* generate method profiling code */
257 #if defined(ENABLE_PROFILING)
258 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
259 /* count frequency */
260 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
261 ICONST(REG_ITMP2, 1);
262 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
263 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
269 /* save used callee saved registers and return address */
271 p = cd->stackframesize - 1;
273 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
274 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
276 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
277 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
280 /* take arguments out of register or stack frame */
284 for (p = 0, l = 0; p < md->paramcount; p++) {
285 t = md->paramtypes[p].type;
286 varindex = jd->local_map[l * 5 + t];
290 if (IS_2_WORD_TYPE(t))
293 if (varindex == UNUSED)
298 s1 = md->params[p].regoff;
300 if (IS_INT_LNG_TYPE(t)) { /* integer args */
301 if (IS_2_WORD_TYPE(t)) {
309 if (!md->params[p].inmemory) { /* register arguments */
310 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
311 if (IS_2_WORD_TYPE(t)) {
312 M_LNGMOVE(s2, var->vv.regoff);
314 M_INTMOVE(s2, var->vv.regoff);
316 } else { /* reg arg -> spilled */
317 if (IS_2_WORD_TYPE(t)) {
318 M_LST(s2, REG_SP, var->vv.regoff);
320 M_IST(s2, REG_SP, var->vv.regoff);
324 } else { /* stack arguments */
325 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
326 if (IS_2_WORD_TYPE(t)) {
327 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
329 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
331 } else { /* stack arg -> spilled */
332 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
336 } else { /* floating args */
337 if (!md->params[p].inmemory) { /* register arguments */
339 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
340 M_FLTMOVE(s2, var->vv.regoff);
342 } else { /* reg arg -> spilled */
343 if (IS_2_WORD_TYPE(t))
344 M_DST(s2, REG_SP, var->vv.regoff);
346 M_FST(s2, REG_SP, var->vv.regoff);
349 } else { /* stack arguments */
350 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
351 if (IS_2_WORD_TYPE(t))
352 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
355 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
357 } else { /* stack-arg -> spilled */
358 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
359 var->vv.regoff = cd->stackframesize * 8 + s1;
365 /* save monitorenter argument */
367 #if defined(ENABLE_THREADS)
368 if (checksync && code_is_synchronized(code)) {
369 /* stack offset for monitor argument */
374 if (opt_verbosecall) {
375 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
377 for (p = 0; p < INT_ARG_CNT; p++)
378 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
380 for (p = 0; p < FLT_ARG_CNT; p++)
381 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
383 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
387 /* decide which monitor enter function to call */
389 if (m->flags & ACC_STATIC) {
390 disp = dseg_add_address(cd, &m->class->object.header);
391 M_ALD_DSEG(REG_A0, disp);
395 M_BNE(SZ_BRC + SZ_ILL);
396 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
399 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
400 M_ALD_DSEG(REG_ITMP2, disp);
402 M_AST(REG_A0, REG_SP, s1 * 8);
404 M_ASUB_IMM(96, REG_SP);
406 M_AADD_IMM(96, REG_SP);
409 if (opt_verbosecall) {
410 for (p = 0; p < INT_ARG_CNT; p++)
411 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
413 for (p = 0; p < FLT_ARG_CNT; p++)
414 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
416 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
423 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
424 emit_verbosecall_enter(jd);
425 #endif /* !defined(NDEBUG) */
429 /* end of header generation */
431 /* create replacement points */
433 REPLACEMENT_POINTS_INIT(cd, jd);
435 /* walk through all basic blocks */
437 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
439 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
441 if (bptr->flags >= BBREACHED) {
443 /* branch resolving */
445 codegen_resolve_branchrefs(cd, bptr);
447 /* handle replacement points */
449 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
451 /* copy interface registers to their destination */
456 #if defined(ENABLE_PROFILING)
457 /* generate basicblock profiling code */
459 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
460 /* count frequency */
462 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
463 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
464 ICONST(REG_ITMP2, 1);
465 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
466 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
468 /* if this is an exception handler, start profiling again */
470 if (bptr->type == BBTYPE_EXH)
475 #if defined(ENABLE_LSRA)
479 src = bptr->invars[len];
480 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
481 if (bptr->type == BBTYPE_EXH) {
482 /* d = reg_of_var(rd, src, REG_ITMP1); */
483 if (!IS_INMEMORY(src->flags))
487 M_INTMOVE(REG_ITMP3_XPTR, d);
488 emit_store(jd, NULL, src, d);
498 var = VAR(bptr->invars[len]);
499 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
500 if (bptr->type == BBTYPE_EXH) {
501 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
502 M_INTMOVE(REG_ITMP3_XPTR, d);
503 emit_store(jd, NULL, var, d);
507 assert((var->flags & INOUT));
510 #if defined(ENABLE_LSRA)
513 /* walk through all instructions */
518 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
519 if (iptr->line != currentline) {
520 dseg_addlinenumber(cd, iptr->line);
521 currentline = iptr->line;
524 MCODECHECK(1024); /* 1KB should be enough */
527 case ICMD_NOP: /* ... ==> ... */
528 case ICMD_POP: /* ..., value ==> ... */
529 case ICMD_POP2: /* ..., value, value ==> ... */
532 case ICMD_INLINE_START:
534 REPLACEMENT_POINT_INLINE_START(cd, iptr);
537 case ICMD_INLINE_BODY:
539 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
540 dseg_addlinenumber_inline_start(cd, iptr);
541 dseg_addlinenumber(cd, iptr->line);
544 case ICMD_INLINE_END:
546 dseg_addlinenumber_inline_end(cd, iptr);
547 dseg_addlinenumber(cd, iptr->line);
550 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
551 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
552 emit_nullpointer_check(cd, iptr, s1);
555 /* constant operations ************************************************/
557 case ICMD_ICONST: /* ... ==> ..., constant */
558 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
559 ICONST(d, iptr->sx.val.i);
560 emit_store_dst(jd, iptr, d);
563 case ICMD_LCONST: /* ... ==> ..., constant */
565 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
566 LCONST(d, iptr->sx.val.l);
567 emit_store_dst(jd, iptr, d);
570 case ICMD_FCONST: /* ... ==> ..., constant */
571 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
572 disp = dseg_add_float(cd, iptr->sx.val.f);
573 M_FLD_DSEG(d, disp, REG_ITMP1);
574 emit_store_dst(jd, iptr, d);
577 case ICMD_DCONST: /* ... ==> ..., constant */
578 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
579 disp = dseg_add_double(cd, iptr->sx.val.d);
580 M_DLD_DSEG(d, disp, REG_ITMP1);
581 emit_store_dst(jd, iptr, d);
584 case ICMD_ACONST: /* ... ==> ..., constant */
585 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
587 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
588 cr = iptr->sx.val.c.ref;
589 disp = dseg_add_unique_address(cd, cr);
591 /* PROFILE_CYCLE_STOP; */
593 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
596 /* PROFILE_CYCLE_START; */
600 if (iptr->sx.val.anyptr == 0) {
603 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
606 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
607 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
609 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
611 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
617 emit_store_dst(jd, iptr, d);
621 /* load/store/copy/move operations ************************************/
623 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
624 case ICMD_ALOAD: /* s1 = local variable */
628 case ICMD_ISTORE: /* ..., value ==> ... */
639 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
643 /* integer operations *************************************************/
645 case ICMD_INEG: /* ..., value ==> ..., - value */
647 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
648 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
650 emit_store_dst(jd, iptr, d);
654 case ICMD_LNEG: /* ..., value ==> ..., - value */
656 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
657 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
658 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
659 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
660 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
661 N_AHI(GET_HIGH_REG(d), -1);
662 emit_store_dst(jd, iptr, d);
665 case ICMD_I2L: /* ..., value ==> ..., value */
667 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
668 if (! N_IS_EVEN_ODD(d)) {
669 d = REG_ITMP31_PACKED;
671 assert(N_IS_EVEN_ODD(d));
673 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
675 M_INTMOVE(s1, GET_HIGH_REG(d));
676 M_SRDA_IMM(32, GET_HIGH_REG(d));
678 emit_copy_dst(jd, iptr, d);
679 emit_store_dst(jd, iptr, d);
682 case ICMD_L2I: /* ..., value ==> ..., value */
683 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
684 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
685 M_INTMOVE(GET_LOW_REG(s1), d);
686 emit_store_dst(jd, iptr, d);
689 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
690 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
691 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
695 emit_store_dst(jd, iptr, d);
698 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
699 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
700 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
704 emit_store_dst(jd, iptr, d);
707 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
709 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
710 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
714 emit_store_dst(jd, iptr, d);
717 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
719 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
720 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
721 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
728 emit_store_dst(jd, iptr, d);
733 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
734 /* sx.val.i = constant */
735 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
736 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
739 if (N_VALID_IMM(iptr->sx.val.i)) {
740 M_IADD_IMM(iptr->sx.val.i, d);
742 ICONST(REG_ITMP2, iptr->sx.val.i);
743 M_IADD(REG_ITMP2, d);
745 emit_store_dst(jd, iptr, d);
748 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
750 /* M, (r, q) -> (r, q) */
752 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
754 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
755 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
756 dd = GET_HIGH_REG(d);
765 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
766 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
776 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
777 N_AHI(GET_HIGH_REG(d), 1);
779 emit_store_dst(jd, iptr, d);
782 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
783 /* sx.val.l = constant */
785 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
786 dd = GET_HIGH_REG(d);
788 s1 = emit_load_s1_high(jd, iptr, dd);
789 s3 = iptr->sx.val.l >> 32;
793 if (N_VALID_IMM(s3)) {
796 ICONST(REG_ITMP3, s3);
797 M_IADD(REG_ITMP3, dd);
801 s1 = emit_load_s1_low(jd, iptr, dd);
802 s3 = iptr->sx.val.l & 0xffffffff;
803 ICONST(REG_ITMP3, s3);
806 N_ALR(dd, REG_ITMP3);
808 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
809 N_AHI(GET_HIGH_REG(d), 1);
811 emit_store_dst(jd, iptr, d);
814 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
816 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
817 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
818 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
820 M_INTMOVE(s1, REG_ITMP1);
821 M_ISUB(s2, REG_ITMP1);
822 M_INTMOVE(REG_ITMP1, d);
827 emit_store_dst(jd, iptr, d);
831 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
832 /* sx.val.i = constant */
834 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
835 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
838 if (N_VALID_IMM(-iptr->sx.val.i)) {
839 M_ISUB_IMM(iptr->sx.val.i, d);
841 ICONST(REG_ITMP2, iptr->sx.val.i);
842 M_ISUB(REG_ITMP2, d);
844 emit_store_dst(jd, iptr, d);
848 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
850 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
852 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
853 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
854 dd = GET_HIGH_REG(d);
857 M_INTMOVE(s2, REG_ITMP3);
864 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
865 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
869 M_INTMOVE(s2, REG_ITMP3);
876 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
877 N_AHI(GET_HIGH_REG(d), -1);
879 emit_store_dst(jd, iptr, d);
882 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
883 /* sx.val.l = constant */
885 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
887 dd = GET_HIGH_REG(d);
888 s1 = emit_load_s1_high(jd, iptr, dd);
889 s3 = iptr->sx.val.l >> 32;
893 if (N_VALID_IMM(-s3)) {
896 ICONST(REG_ITMP3, s3);
897 M_ISUB(REG_ITMP3, dd);
901 s1 = emit_load_s1_low(jd, iptr, dd);
902 s3 = iptr->sx.val.l & 0xffffffff;
903 ICONST(REG_ITMP3, s3);
906 N_SLR(dd, REG_ITMP3);
908 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
909 N_AHI(GET_HIGH_REG(d), -1);
911 emit_store_dst(jd, iptr, d);
914 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
916 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
917 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
918 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
925 emit_store_dst(jd, iptr, d);
929 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
930 /* sx.val.i = constant */
931 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
932 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
934 if (iptr->sx.val.i == 2) {
936 } else if (N_VALID_IMM(iptr->sx.val.i)) {
937 M_IMUL_IMM(iptr->sx.val.i, d);
939 disp = dseg_add_s4(cd, iptr->sx.val.i);
940 M_ILD_DSEG(REG_ITMP2, disp);
941 M_IMUL(REG_ITMP2, d);
943 emit_store_dst(jd, iptr, d);
946 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
947 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
949 /* load s1 into r0 */
951 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
952 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
953 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
955 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
957 /* extend s1 to long */
959 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
963 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
969 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
970 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
973 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
974 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
978 emit_store_dst(jd, iptr, d);
982 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
983 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
985 bte = iptr->sx.s23.s3.bte;
988 /* test s2 for zero */
990 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
991 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
992 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
993 emit_arithmetic_check(cd, iptr, REG_ITMP3);
997 disp = dseg_add_functionptr(cd, bte->fp);
1001 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
1003 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
1004 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
1008 M_ASUB_IMM(96, REG_SP);
1009 M_ALD_DSEG(REG_ITMP2, disp);
1010 M_JSR(REG_RA, REG_ITMP2);
1011 M_AADD_IMM(96, REG_SP);
1015 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1016 M_LNGMOVE(REG_RESULT_PACKED, d);
1017 emit_store_dst(jd, iptr, d);
1021 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1022 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1023 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1025 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1026 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1027 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1029 /* Use only 5 bits of sencond operand. */
1031 M_INTMOVE(s2, REG_ITMP2);
1033 ICONST(REG_ITMP3, 0x1F);
1034 M_IAND(REG_ITMP3, s2);
1038 switch (iptr->opc) {
1051 emit_store_dst(jd, iptr, d);
1054 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1055 /* sx.val.i = constant */
1059 assert(iptr->sx.val.i <= 32);
1061 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1062 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1069 s3 = (1 << iptr->sx.val.i) - 1;
1071 if (N_VALID_IMM(s3)) {
1074 ICONST(REG_ITMP1, -1);
1075 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1076 M_IADD(REG_ITMP1, d);
1079 N_BRC_BACK_PATCH(ref);
1081 M_SRA_IMM(iptr->sx.val.i, d);
1083 emit_store_dst(jd, iptr, d);
1088 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1089 /* sx.val.i = constant */
1091 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1092 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1095 M_MOV(s1, REG_ITMP1);
1099 ICONST(REG_ITMP3, iptr->sx.val.i);
1102 M_IAND(REG_ITMP3, d);
1105 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1111 emit_store_dst(jd, iptr, d);
1115 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1116 /* sx.val.i = constant */
1117 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1118 /* sx.val.i = constant */
1119 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1120 /* sx.val.i = constant */
1121 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1122 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1126 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1128 switch (iptr->opc) {
1129 case ICMD_ISHLCONST:
1132 case ICMD_ISHRCONST:
1135 case ICMD_IUSHRCONST:
1142 emit_store_dst(jd, iptr, d);
1145 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1147 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1149 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1151 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1153 /* Use only 6 bits of second operand */
1155 M_INTMOVE(s2, REG_ITMP2);
1157 ICONST(REG_ITMP1, 0x3F);
1158 M_IAND(REG_ITMP1, s2);
1160 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1161 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1163 /* Destination must be even-odd pair */
1165 if (! N_IS_EVEN_ODD(d)) {
1166 d = REG_ITMP31_PACKED;
1169 assert(N_IS_EVEN_ODD(d));
1173 switch (iptr->opc) {
1175 M_SLDL(s2, GET_HIGH_REG(d));
1178 M_SRDA(s2, GET_HIGH_REG(d));
1181 M_SRDL(s2, GET_HIGH_REG(d));
1187 emit_copy_dst(jd, iptr, d);
1188 emit_store_dst(jd, iptr, d);
1192 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1193 /* sx.val.i = constant */
1194 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1195 /* sx.val.i = constant */
1196 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1197 /* sx.val.l = constant */
1200 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1201 if (! N_IS_EVEN_ODD(d)) {
1202 d = REG_ITMP31_PACKED;
1204 assert(N_IS_EVEN_ODD(d));
1206 s1 = emit_load_s1(jd, iptr, d);
1210 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1212 switch (iptr->opc) {
1213 case ICMD_LSHLCONST:
1214 N_SLDL(GET_HIGH_REG(d), disp, RN);
1216 case ICMD_LSHRCONST:
1217 N_SRDA(GET_HIGH_REG(d), disp, RN);
1219 case ICMD_LUSHRCONST:
1220 N_SRDL(GET_HIGH_REG(d), disp, RN);
1223 N_SLDL(GET_HIGH_REG(d), disp, RN);
1229 emit_copy_dst(jd, iptr, d);
1230 emit_store_dst(jd, iptr, d);
1233 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1235 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1236 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1237 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1244 emit_store_dst(jd, iptr, d);
1248 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1250 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1251 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1252 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1259 emit_store_dst(jd, iptr, d);
1263 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1265 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1266 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1267 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1274 emit_store_dst(jd, iptr, d);
1280 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1281 /* sx.val.i = constant */
1282 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1283 /* sx.val.i = constant */
1284 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1285 /* sx.val.i = constant */
1287 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1288 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1291 ICONST(REG_ITMP2, iptr->sx.val.i);
1293 switch (iptr->opc) {
1294 case ICMD_IANDCONST:
1295 M_IAND(REG_ITMP2, d);
1297 case ICMD_IXORCONST:
1298 M_IXOR(REG_ITMP2, d);
1301 M_IOR(REG_ITMP2, d);
1307 emit_store_dst(jd, iptr, d);
1311 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1312 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1313 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1315 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1317 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1318 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1319 dd = GET_LOW_REG(d);
1321 switch (iptr->opc) {
1350 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1351 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1352 dd = GET_HIGH_REG(d);
1354 switch (iptr->opc) {
1383 emit_store_dst(jd, iptr, d);
1386 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1387 /* sx.val.l = constant */
1388 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1389 /* sx.val.l = constant */
1390 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1391 /* sx.val.l = constant */
1393 /* TODO should use memory operand to access data segment, not load */
1395 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1397 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1398 s3 = iptr->sx.val.l & 0xffffffff;
1400 M_INTMOVE(s1, GET_LOW_REG(d));
1402 ICONST(REG_ITMP3, s3);
1404 switch (iptr->opc) {
1405 case ICMD_LANDCONST:
1406 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1408 case ICMD_LXORCONST:
1409 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1412 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1418 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1419 s3 = iptr->sx.val.l >> 32;
1421 M_INTMOVE(s1, GET_HIGH_REG(d));
1423 ICONST(REG_ITMP3, s3);
1425 switch (iptr->opc) {
1426 case ICMD_LANDCONST:
1427 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1429 case ICMD_LXORCONST:
1430 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1433 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1439 emit_store_dst(jd, iptr, d);
1443 /* floating operations ************************************************/
1445 case ICMD_FNEG: /* ..., value ==> ..., - value */
1446 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1447 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1449 emit_store_dst(jd, iptr, d);
1452 case ICMD_DNEG: /* ..., value ==> ..., - value */
1453 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1454 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1456 emit_store_dst(jd, iptr, d);
1459 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1460 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1461 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1462 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1469 emit_store_dst(jd, iptr, d);
1472 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1473 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1474 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1475 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1482 emit_store_dst(jd, iptr, d);
1485 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1486 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1487 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1488 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1492 emit_store_dst(jd, iptr, d);
1495 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1496 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1497 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1498 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1502 emit_store_dst(jd, iptr, d);
1505 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1506 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1507 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1508 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1515 emit_store_dst(jd, iptr, d);
1518 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1519 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1520 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1521 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1528 emit_store_dst(jd, iptr, d);
1531 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1532 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1533 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1534 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1538 emit_store_dst(jd, iptr, d);
1541 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1542 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1543 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1544 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1548 emit_store_dst(jd, iptr, d);
1551 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1552 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1553 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1555 emit_store_dst(jd, iptr, d);
1558 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1559 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1560 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1562 emit_store_dst(jd, iptr, d);
1565 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1569 #ifdef SUPPORT_HERCULES
1573 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1574 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1578 switch (iptr->opc) {
1587 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1588 N_LHI(d, 0); /* Load 0 */
1589 ref1 = cd->mcodeptr;
1590 N_BRC(DD_ANY, 0); /* Exit */
1594 switch (iptr->opc) {
1603 #ifdef SUPPORT_HERCULES
1604 /* Hercules does the conversion using a plain C conversion.
1605 * According to manual, real hardware should *NOT* require this.
1607 * Corner case: Positive float leads to INT_MIN (overflow).
1610 switch (iptr->opc) {
1619 ref2 = cd->mcodeptr;
1620 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1624 ref3 = cd->mcodeptr;
1625 M_BGE(0); /* If integer result is negative, continue */
1627 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1628 M_ILD_DSEG(d, disp);
1630 N_BRC_BACK_PATCH(ref1);
1631 #ifdef SUPPORT_HERCULES
1632 N_BRC_BACK_PATCH(ref2);
1633 N_BRC_BACK_PATCH(ref3);
1635 emit_store_dst(jd, iptr, d);
1639 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1642 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1643 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1644 #ifdef SUPPORT_HERCULES
1647 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1648 disp = dseg_add_double(cd, 0.0 / 0.0);
1649 M_DLD_DSEG(d, disp, REG_ITMP1);
1650 emit_label_br(cd, BRANCH_LABEL_1);
1651 N_BRC_BACK_PATCH(ref);
1654 #ifdef SUPPORT_HERCULES
1655 emit_label(cd, BRANCH_LABEL_1);
1657 emit_store_dst(jd, iptr, d);
1661 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1662 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1663 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1665 emit_store_dst(jd, iptr, d);
1668 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1669 /* == => 0, < => 1, > => -1 */
1673 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1674 /* == => 0, < => 1, > => -1 */
1677 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1678 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1679 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1681 switch (iptr->opc) {
1693 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1694 SZ_BRC + SZ_BRC + SZ_BRC
1697 N_BRC( /* load -1 */
1698 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1699 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1704 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1707 N_LHI(d, 1); /* GT */
1708 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1709 N_LHI(d, -1); /* LT */
1710 M_BR(SZ_BRC + SZ_LHI);
1711 N_LHI(d, 0); /* EQ */
1713 emit_store_dst(jd, iptr, d);
1718 /* memory operations **************************************************/
1720 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1722 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1723 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1725 /* implicit null-pointer check */
1726 M_ILD(d, s1, OFFSET(java_array_t, size));
1727 emit_store_dst(jd, iptr, d);
1731 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1732 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1733 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1734 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1736 /* implicit null-pointer check */
1737 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1739 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1744 emit_store_dst(jd, iptr, d);
1747 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1749 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1750 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1751 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1753 /* implicit null-pointer check */
1754 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1756 M_INTMOVE(s2, REG_ITMP2);
1757 M_SLL_IMM(1, REG_ITMP2);
1759 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1761 /* N_LH does sign extends, undo ! */
1766 emit_store_dst(jd, iptr, d);
1769 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1770 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1771 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1772 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1774 /* implicit null-pointer check */
1775 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1777 M_INTMOVE(s2, REG_ITMP2);
1778 M_SLL_IMM(1, REG_ITMP2);
1780 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1781 emit_store_dst(jd, iptr, d);
1784 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1785 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1786 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1787 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1789 /* implicit null-pointer check */
1790 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1792 M_INTMOVE(s2, REG_ITMP2);
1793 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1794 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1795 emit_store_dst(jd, iptr, d);
1798 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1800 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1801 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1803 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1805 /* implicit null-pointer check */
1806 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1808 M_INTMOVE(s2, REG_ITMP2);
1809 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1812 GET_LOW_REG(d) /* maybe itmp3 */,
1813 OFFSET(java_intarray_t, data[0]) + 4,
1814 REG_ITMP2, s1 /* maybe itmp1 */
1818 GET_HIGH_REG(d) /* maybe itmp1 */,
1819 OFFSET(java_intarray_t, data[0]),
1820 REG_ITMP2, s1 /* maybe itmp1 */
1823 emit_store_dst(jd, iptr, d);
1827 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1829 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1830 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1831 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1833 /* implicit null-pointer check */
1834 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1836 M_INTMOVE(s2, REG_ITMP2);
1837 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1839 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1841 emit_store_dst(jd, iptr, d);
1844 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1845 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1846 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1847 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1849 /* implicit null-pointer check */
1850 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1852 M_INTMOVE(s2, REG_ITMP2);
1853 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1855 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1857 emit_store_dst(jd, iptr, d);
1860 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1861 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1862 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1863 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1865 /* implicit null-pointer check */
1866 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1868 M_INTMOVE(s2, REG_ITMP2);
1869 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1870 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1871 emit_store_dst(jd, iptr, d);
1874 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1875 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1876 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1877 /* implicit null-pointer check */
1878 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1879 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1881 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1884 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1886 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1887 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1888 /* implicit null-pointer check */
1889 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1890 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1892 M_INTMOVE(s2, REG_ITMP2);
1893 M_SLL_IMM(1, REG_ITMP2);
1895 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1899 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1900 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1901 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1902 /* implicit null-pointer check */
1903 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1904 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1906 M_INTMOVE(s2, REG_ITMP2);
1907 M_SLL_IMM(1, REG_ITMP2);
1909 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1912 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1914 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1915 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1916 /* implicit null-pointer check */
1917 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1919 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1921 M_INTMOVE(s2, REG_ITMP2);
1922 M_SLL_IMM(2, REG_ITMP2);
1924 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1927 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1929 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1930 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1931 /* implicit null-pointer check */
1932 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1934 M_INTMOVE(s2, REG_ITMP2);
1935 M_SLL_IMM(3, REG_ITMP2);
1937 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1938 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1939 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1940 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1943 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1944 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1945 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1946 /* implicit null-pointer check */
1947 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1948 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1950 M_INTMOVE(s2, REG_ITMP2);
1951 M_SLL_IMM(2, REG_ITMP2);
1953 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1956 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1957 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1958 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1959 /* implicit null-pointer check */
1960 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1961 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1963 M_INTMOVE(s2, REG_ITMP2);
1964 M_SLL_IMM(3, REG_ITMP2);
1966 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1969 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1971 s1 = emit_load_s1(jd, iptr, REG_A0);
1972 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1973 /* implicit null-pointer check */
1974 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1975 s3 = emit_load_s3(jd, iptr, REG_A1);
1977 M_INTMOVE(s1, REG_A0);
1978 M_INTMOVE(s3, REG_A1);
1980 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1981 M_ALD_DSEG(REG_ITMP2, disp);
1982 M_ASUB_IMM(96, REG_SP);
1983 M_JSR(REG_RA, REG_ITMP2);
1984 M_AADD_IMM(96, REG_SP);
1986 emit_arraystore_check(cd, iptr);
1988 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1989 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1990 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1992 M_INTMOVE(s2, REG_ITMP2);
1993 M_SLL_IMM(2, REG_ITMP2);
1994 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1997 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1998 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2003 case ICMD_GETSTATIC: /* ... ==> ..., value */
2005 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2006 uf = iptr->sx.s23.s3.uf;
2007 fieldtype = uf->fieldref->parseddesc.fd->type;
2008 disp = dseg_add_unique_address(cd, NULL);
2010 /* PROFILE_CYCLE_STOP; */
2012 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2014 /* PROFILE_CYCLE_START; */
2017 fi = iptr->sx.s23.s3.fmiref->p.field;
2018 fieldtype = fi->type;
2019 disp = dseg_add_address(cd, fi->value);
2021 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2024 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
2026 PROFILE_CYCLE_START;
2030 M_ALD_DSEG(REG_ITMP1, disp);
2032 switch (fieldtype) {
2034 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2035 M_ILD(d, REG_ITMP1, 0);
2038 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2039 M_LLD(d, REG_ITMP1, 0);
2042 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2043 M_ALD(d, REG_ITMP1, 0);
2046 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2047 M_FLD(d, REG_ITMP1, 0);
2050 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2051 M_DLD(d, REG_ITMP1, 0);
2055 emit_store_dst(jd, iptr, d);
2059 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2061 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2062 uf = iptr->sx.s23.s3.uf;
2063 fieldtype = uf->fieldref->parseddesc.fd->type;
2064 disp = dseg_add_unique_address(cd, uf);
2066 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2069 fi = iptr->sx.s23.s3.fmiref->p.field;
2070 fieldtype = fi->type;
2071 disp = dseg_add_address(cd, fi->value);
2073 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2075 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
2076 PROFILE_CYCLE_START;
2080 M_ALD_DSEG(REG_ITMP1, disp);
2081 switch (fieldtype) {
2083 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2084 M_IST(s1, REG_ITMP1, 0);
2087 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2088 M_LST(s1, REG_ITMP1, 0);
2091 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2092 M_AST(s1, REG_ITMP1, 0);
2095 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2096 M_FST(s1, REG_ITMP1, 0);
2099 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2100 M_DST(s1, REG_ITMP1, 0);
2105 case ICMD_GETFIELD: /* ... ==> ..., value */
2107 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2108 emit_nullpointer_check(cd, iptr, s1);
2110 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2111 uf = iptr->sx.s23.s3.uf;
2112 fieldtype = uf->fieldref->parseddesc.fd->type;
2115 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2118 fi = iptr->sx.s23.s3.fmiref->p.field;
2119 fieldtype = fi->type;
2123 switch (fieldtype) {
2125 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2129 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2130 if (GET_HIGH_REG(d) == s1) {
2131 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2132 M_ILD(GET_HIGH_REG(d), s1, disp);
2135 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2136 M_ILD(GET_HIGH_REG(d), s1, disp);
2140 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2144 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2148 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2152 emit_store_dst(jd, iptr, d);
2155 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2159 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2160 emit_nullpointer_check(cd, iptr, s1);
2162 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2163 uf = iptr->sx.s23.s3.uf;
2164 fieldtype = uf->fieldref->parseddesc.fd->type;
2168 fi = iptr->sx.s23.s3.fmiref->p.field;
2169 fieldtype = fi->type;
2173 /* We can't add a patcher ref behind this load,
2174 * because the patcher would destroy REG_ITMP3.
2176 * We pass in the disp parameter, how many bytes
2177 * to skip to the to the actual store.
2179 * XXX this relies on patcher_add_patch_ref internals
2182 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2183 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2188 if (IS_INT_LNG_TYPE(fieldtype)) {
2189 if (IS_2_WORD_TYPE(fieldtype))
2190 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2192 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2194 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2197 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2198 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2201 switch (fieldtype) {
2203 M_IST(s2, s1, disp);
2206 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2207 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2210 M_AST(s2, s1, disp);
2213 M_FST(s2, s1, disp);
2216 M_DST(s2, s1, disp);
2223 /* branch operations **************************************************/
2225 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2227 /* PROFILE_CYCLE_STOP; */
2229 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2230 M_INTMOVE(s1, REG_ITMP3_XPTR);
2232 #ifdef ENABLE_VERIFIER
2233 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2234 uc = iptr->sx.s23.s2.uc;
2236 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2238 #endif /* ENABLE_VERIFIER */
2240 disp = dseg_add_functionptr(cd, asm_handle_exception);
2241 M_ALD_DSEG(REG_ITMP1, disp);
2242 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2247 case ICMD_GOTO: /* ... ==> ... */
2248 case ICMD_RET: /* ... ==> ... */
2250 emit_br(cd, iptr->dst.block);
2254 case ICMD_JSR: /* ... ==> ... */
2256 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2260 case ICMD_IFNULL: /* ..., value ==> ... */
2261 case ICMD_IFNONNULL: /* ..., value ==> ... */
2262 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2264 switch (iptr->opc) {
2266 emit_beq(cd, iptr->dst.block);
2268 case ICMD_IFNONNULL:
2269 emit_bne(cd, iptr->dst.block);
2274 case ICMD_IFEQ: /* ..., value ==> ... */
2275 case ICMD_IFLT: /* ..., value ==> ... */
2276 case ICMD_IFLE: /* ..., value ==> ... */
2277 case ICMD_IFNE: /* ..., value ==> ... */
2278 case ICMD_IFGT: /* ..., value ==> ... */
2279 case ICMD_IFGE: /* ..., value ==> ... */
2281 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2283 if (N_VALID_IMM(iptr->sx.val.i))
2284 M_ICMP_IMM(s1, iptr->sx.val.i);
2286 disp = dseg_add_s4(cd, iptr->sx.val.i);
2287 if (N_VALID_DSEG_DISP(disp)) {
2288 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2290 ICONST(REG_ITMP2, disp);
2291 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2295 switch (iptr->opc) {
2297 emit_blt(cd, iptr->dst.block);
2300 emit_ble(cd, iptr->dst.block);
2303 emit_bne(cd, iptr->dst.block);
2306 emit_bgt(cd, iptr->dst.block);
2309 emit_bge(cd, iptr->dst.block);
2312 emit_beq(cd, iptr->dst.block);
2318 case ICMD_IF_LLT: /* ..., value ==> ... */
2319 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2325 /* ATTENTION: compare high words signed and low words unsigned */
2327 # define LABEL_OUT BRANCH_LABEL_1
2329 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2331 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2332 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2334 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2335 if (N_VALID_DSEG_DISP(disp)) {
2336 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2338 ICONST(REG_ITMP2, disp);
2339 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2346 emit_blt(cd, iptr->dst.block);
2347 /* EQ ... fall through */
2348 emit_label_bgt(cd, LABEL_OUT);
2352 emit_bgt(cd, iptr->dst.block);
2353 /* EQ ... fall through */
2354 emit_label_blt(cd, LABEL_OUT);
2357 /* EQ ... fall through */
2358 emit_label_bne(cd, LABEL_OUT);
2361 /* EQ ... fall through */
2362 emit_bne(cd, iptr->dst.block);
2368 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2370 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2371 if (N_VALID_DSEG_DISP(disp)) {
2372 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2374 ICONST(REG_ITMP2, disp);
2375 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2380 emit_blt(cd, iptr->dst.block);
2381 emit_label(cd, LABEL_OUT);
2384 emit_ble(cd, iptr->dst.block);
2385 emit_label(cd, LABEL_OUT);
2388 emit_bgt(cd, iptr->dst.block);
2389 emit_label(cd, LABEL_OUT);
2392 emit_bge(cd, iptr->dst.block);
2393 emit_label(cd, LABEL_OUT);
2396 emit_beq(cd, iptr->dst.block);
2397 emit_label(cd, LABEL_OUT);
2400 emit_bne(cd, iptr->dst.block);
2409 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2410 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2412 /* Compare addresses as 31 bit unsigned integers */
2414 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2415 M_LDA(REG_ITMP1, s1, 0);
2417 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2418 M_LDA(REG_ITMP2, s2, 0);
2420 M_CMP(REG_ITMP1, REG_ITMP2);
2422 switch (iptr->opc) {
2423 case ICMD_IF_ACMPEQ:
2424 emit_beq(cd, iptr->dst.block);
2426 case ICMD_IF_ACMPNE:
2427 emit_bne(cd, iptr->dst.block);
2433 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2434 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2435 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2436 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2437 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2438 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2440 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2441 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2443 switch (iptr->opc) {
2444 case ICMD_IF_ICMPEQ:
2445 emit_beq(cd, iptr->dst.block);
2447 case ICMD_IF_ICMPNE:
2448 emit_bne(cd, iptr->dst.block);
2450 case ICMD_IF_ICMPLT:
2451 emit_blt(cd, iptr->dst.block);
2453 case ICMD_IF_ICMPGT:
2454 emit_bgt(cd, iptr->dst.block);
2456 case ICMD_IF_ICMPLE:
2457 emit_ble(cd, iptr->dst.block);
2459 case ICMD_IF_ICMPGE:
2460 emit_bge(cd, iptr->dst.block);
2466 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2467 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2468 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2469 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2470 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2471 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2476 /* ATTENTION: compare high words signed and low words unsigned */
2478 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2479 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2484 case ICMD_IF_LCMPLT:
2485 case ICMD_IF_LCMPLE:
2486 emit_blt(cd, iptr->dst.block);
2487 /* EQ ... fall through */
2488 out_ref = cd->mcodeptr;
2491 case ICMD_IF_LCMPGT:
2492 case ICMD_IF_LCMPGE:
2493 emit_bgt(cd, iptr->dst.block);
2494 /* EQ ... fall through */
2495 out_ref = cd->mcodeptr;
2498 case ICMD_IF_LCMPEQ:
2499 /* EQ ... fall through */
2500 out_ref = cd->mcodeptr;
2503 case ICMD_IF_LCMPNE:
2504 /* EQ ... fall through */
2505 emit_bne(cd, iptr->dst.block);
2511 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2512 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2517 case ICMD_IF_LCMPLT:
2518 emit_blt(cd, iptr->dst.block);
2520 case ICMD_IF_LCMPLE:
2521 emit_ble(cd, iptr->dst.block);
2523 case ICMD_IF_LCMPGT:
2524 emit_bgt(cd, iptr->dst.block);
2526 case ICMD_IF_LCMPGE:
2527 emit_bge(cd, iptr->dst.block);
2529 case ICMD_IF_LCMPEQ:
2530 emit_beq(cd, iptr->dst.block);
2532 case ICMD_IF_LCMPNE:
2533 emit_bne(cd, iptr->dst.block);
2539 if (out_ref != NULL) {
2540 N_BRC_BACK_PATCH(out_ref);
2546 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2548 REPLACEMENT_POINT_RETURN(cd, iptr);
2549 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2550 M_INTMOVE(s1, REG_RESULT);
2551 goto nowperformreturn;
2553 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2555 REPLACEMENT_POINT_RETURN(cd, iptr);
2556 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2557 M_INTMOVE(s1, REG_RESULT);
2559 #ifdef ENABLE_VERIFIER
2560 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2561 unresolved_class *uc = iptr->sx.s23.s2.uc;
2564 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2565 PROFILE_CYCLE_START;
2567 #endif /* ENABLE_VERIFIER */
2568 goto nowperformreturn;
2570 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2572 REPLACEMENT_POINT_RETURN(cd, iptr);
2573 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2574 M_LNGMOVE(s1, REG_RESULT_PACKED);
2575 goto nowperformreturn;
2577 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2580 REPLACEMENT_POINT_RETURN(cd, iptr);
2581 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2582 M_FLTMOVE(s1, REG_FRESULT);
2583 goto nowperformreturn;
2585 case ICMD_RETURN: /* ... ==> ... */
2587 REPLACEMENT_POINT_RETURN(cd, iptr);
2593 p = cd->stackframesize;
2595 /* call trace function */
2597 #if !defined(NDEBUG)
2598 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2599 emit_verbosecall_exit(jd);
2600 #endif /* !defined(NDEBUG) */
2602 #if defined(ENABLE_THREADS)
2603 if (checksync && code_is_synchronized(code)) {
2604 /* we need to save the proper return value */
2606 switch (iptr->opc) {
2608 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2612 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2615 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2618 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2622 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2624 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2625 M_ALD_DSEG(REG_ITMP2, disp);
2627 M_ASUB_IMM(96, REG_SP);
2629 M_AADD_IMM(96, REG_SP);
2631 /* and now restore the proper return value */
2633 switch (iptr->opc) {
2635 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2639 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2642 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2645 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2651 /* restore return address */
2653 p--; M_ALD(REG_RA, REG_SP, p * 8);
2655 /* restore saved registers */
2657 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2658 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2660 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2661 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2664 /* deallocate stack */
2666 if (cd->stackframesize)
2667 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2669 /* generate method profiling code */
2677 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2680 branch_target_t *table;
2682 table = iptr->dst.table;
2684 l = iptr->sx.s23.s2.tablelow;
2685 i = iptr->sx.s23.s3.tablehigh;
2687 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2688 M_INTMOVE(s1, REG_ITMP1);
2692 } else if (N_VALID_IMM(-l)) {
2693 M_ISUB_IMM(l, REG_ITMP1);
2695 ICONST(REG_ITMP2, l);
2696 M_ISUB(REG_ITMP2, REG_ITMP1);
2699 /* number of targets */
2705 ICONST(REG_ITMP2, i);
2706 M_ICMPU(REG_ITMP1, REG_ITMP2);
2707 emit_bge(cd, table[0].block);
2709 /* build jump table top down and use address of lowest entry */
2714 dseg_add_target(cd, table->block);
2719 /* length of dataseg after last dseg_add_target is used by load */
2721 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2722 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2723 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2724 M_JMP(RN, REG_ITMP1);
2729 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2732 lookup_target_t *lookup;
2734 lookup = iptr->dst.lookup;
2736 i = iptr->sx.s23.s2.lookupcount;
2738 MCODECHECK(8 + ((7 + 6) * i) + 5);
2739 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2742 if (N_VALID_IMM(lookup->value)) {
2743 M_ICMP_IMM(s1, lookup->value);
2745 ICONST(REG_ITMP2, lookup->value);
2746 M_ICMP(REG_ITMP2, s1);
2748 emit_beq(cd, lookup->target.block);
2752 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2757 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2759 bte = iptr->sx.s23.s3.bte;
2763 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2764 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2765 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2766 case ICMD_INVOKEINTERFACE:
2768 REPLACEMENT_POINT_INVOKE(cd, iptr);
2770 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2772 um = iptr->sx.s23.s3.um;
2773 md = um->methodref->parseddesc.md;
2776 lm = iptr->sx.s23.s3.fmiref->p.method;
2778 md = lm->parseddesc;
2782 s3 = md->paramcount;
2784 MCODECHECK((s3 << 1) + 64);
2786 /* copy arguments to registers or stack location */
2788 for (s3 = s3 - 1; s3 >= 0; s3--) {
2789 var = VAR(iptr->sx.s23.s2.args[s3]);
2791 /* Already Preallocated? */
2792 if (var->flags & PREALLOC)
2795 if (IS_INT_LNG_TYPE(var->type)) {
2796 if (!md->params[s3].inmemory) {
2797 if (IS_2_WORD_TYPE(var->type)) {
2799 GET_LOW_REG(md->params[s3].regoff),
2800 GET_HIGH_REG(md->params[s3].regoff)
2802 d = emit_load(jd, iptr, var, s1);
2806 s1 = md->params[s3].regoff;
2807 d = emit_load(jd, iptr, var, s1);
2812 if (IS_2_WORD_TYPE(var->type)) {
2813 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2814 M_LST(d, REG_SP, md->params[s3].regoff);
2817 d = emit_load(jd, iptr, var, REG_ITMP1);
2818 M_IST(d, REG_SP, md->params[s3].regoff);
2823 if (!md->params[s3].inmemory) {
2824 s1 = md->params[s3].regoff;
2825 d = emit_load(jd, iptr, var, s1);
2829 d = emit_load(jd, iptr, var, REG_FTMP1);
2830 if (IS_2_WORD_TYPE(var->type))
2831 M_DST(d, REG_SP, md->params[s3].regoff);
2833 M_FST(d, REG_SP, md->params[s3].regoff);
2838 /* generate method profiling code */
2842 switch (iptr->opc) {
2844 if (bte->stub == NULL) {
2845 disp = dseg_add_functionptr(cd, bte->fp);
2846 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2848 disp = dseg_add_functionptr(cd, bte->stub);
2851 if (N_VALID_DSEG_DISP(disp)) {
2852 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2854 N_LHI(REG_ITMP1, disp);
2855 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2859 case ICMD_INVOKESPECIAL:
2861 /* Implicit NULL pointer check */
2862 M_ILD(REG_ITMP1, REG_A0, 0);
2866 case ICMD_INVOKESTATIC:
2868 disp = dseg_add_unique_address(cd, um);
2870 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2874 disp = dseg_add_address(cd, lm->stubroutine);
2876 if (N_VALID_DSEG_DISP(disp)) {
2877 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2879 N_LHI(REG_ITMP1, disp);
2880 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2884 case ICMD_INVOKEVIRTUAL:
2885 /* TODO softnull REG_A0 */
2888 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2893 s1 = OFFSET(vftbl_t, table[0]) +
2894 sizeof(methodptr) * lm->vftblindex;
2897 /* implicit null-pointer check */
2899 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2900 M_ALD(REG_PV, REG_METHODPTR, s1);
2903 case ICMD_INVOKEINTERFACE:
2904 /* TODO softnull REG_A0 */
2906 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2907 * and -0xFFF in index register (itmp1)
2911 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2917 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2918 sizeof(methodptr*) * lm->class->index;
2920 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2923 /* Implicit null-pointer check */
2924 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2925 N_LHI(REG_ITMP2, s1);
2926 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2927 M_ALD(REG_PV, REG_METHODPTR, s2);
2931 /* generate the actual call */
2934 emit_restore_pv(cd);
2936 /* post call finalization */
2938 switch (iptr->opc) {
2940 if (bte->stub == NULL) {
2941 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2946 /* generate method profiling code */
2948 PROFILE_CYCLE_START;
2950 /* store size of call code in replacement point */
2952 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2954 /* store return value */
2956 d = md->returntype.type;
2958 if (d != TYPE_VOID) {
2959 if (IS_INT_LNG_TYPE(d)) {
2960 if (IS_2_WORD_TYPE(d)) {
2961 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2962 M_LNGMOVE(REG_RESULT_PACKED, s1);
2965 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2966 M_INTMOVE(REG_RESULT, s1);
2970 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2971 M_FLTMOVE(REG_FRESULT, s1);
2973 emit_store_dst(jd, iptr, s1);
2979 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2981 /* val.a: (classinfo*) superclass */
2983 /* superclass is an interface:
2985 * OK if ((sub == NULL) ||
2986 * (sub->vftbl->interfacetablelength > super->index) &&
2987 * (sub->vftbl->interfacetable[-super->index] != NULL));
2989 * superclass is a class:
2991 * OK if ((sub == NULL) || (0
2992 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2993 * super->vftbl->diffval));
2996 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2997 /* object type cast-check */
3000 vftbl_t *supervftbl;
3003 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3004 # define LABEL_CLASS BRANCH_LABEL_2
3005 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3006 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
3007 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
3009 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3015 super = iptr->sx.s23.s3.c.cls;
3016 superindex = super->index;
3017 supervftbl = super->vftbl;
3020 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3021 CODEGEN_CRITICAL_SECTION_NEW;
3023 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3025 /* if class is not resolved, check which code to call */
3027 if (super == NULL) {
3029 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3031 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3033 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3034 iptr->sx.s23.s3.c.ref,
3037 ICONST(REG_ITMP3, ACC_INTERFACE);
3039 if (N_VALID_DSEG_DISP(disp)) {
3040 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3042 ICONST(REG_ITMP2, disp);
3043 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3045 emit_label_beq(cd, LABEL_CLASS);
3048 /* interface checkcast code */
3050 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3051 if (super == NULL) {
3052 patcher_add_patch_ref(jd,
3053 PATCHER_checkcast_instanceof_interface,
3054 iptr->sx.s23.s3.c.ref,
3058 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3061 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3062 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3063 M_ISUB_IMM(superindex, REG_ITMP3);
3064 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3067 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3068 superindex * sizeof(methodptr*))
3070 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3071 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3073 if (super == NULL) {
3074 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3078 /* class checkcast code */
3080 if (super == NULL) {
3081 emit_label(cd, LABEL_CLASS);
3084 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3085 if (super == NULL) {
3086 disp = dseg_add_unique_address(cd, NULL);
3088 patcher_add_patch_ref(jd,
3089 PATCHER_resolve_classref_to_vftbl,
3090 iptr->sx.s23.s3.c.ref,
3094 disp = dseg_add_address(cd, supervftbl);
3096 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3100 CODEGEN_CRITICAL_SECTION_START;
3102 /* REG_ITMP3 := baseval(s1) */
3103 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3104 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3106 /* REG_ITMP2 := baseval(class) */
3107 M_ALD_DSEG(REG_ITMP2, disp);
3108 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3110 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3111 M_ISUB(REG_ITMP2, REG_ITMP3);
3113 /* REG_ITMP2 := diffval(class) */
3114 M_ALD_DSEG(REG_ITMP2, disp);
3115 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3117 CODEGEN_CRITICAL_SECTION_END;
3119 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3121 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3122 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3123 /* Branch if greater then */
3125 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3126 M_ALD_DSEG(REG_ITMP3, disp);
3128 CODEGEN_CRITICAL_SECTION_START;
3130 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3131 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3132 M_ISUB(REG_ITMP3, REG_ITMP2);
3133 M_ALD_DSEG(REG_ITMP3, disp);
3134 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3136 CODEGEN_CRITICAL_SECTION_END;
3138 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3139 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3140 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3141 /* Branch if greater then */
3143 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3146 if (super == NULL) {
3147 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3148 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3149 } else if (super->flags & ACC_INTERFACE) {
3150 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3152 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3155 d = codegen_reg_of_dst(jd, iptr, s1);
3157 # undef LABEL_EXIT_CHECK_NULL
3159 # undef LABEL_EXIT_INTERFACE_NULL
3160 # undef LABEL_EXIT_INTERFACE_DONE
3161 # undef LABEL_EXIT_CLASS_NULL
3164 /* array type cast-check */
3166 s1 = emit_load_s1(jd, iptr, REG_A0);
3167 M_INTMOVE(s1, REG_A0);
3169 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3170 disp = dseg_add_unique_address(cd, NULL);
3172 patcher_add_patch_ref(jd,
3173 PATCHER_resolve_classref_to_classinfo,
3174 iptr->sx.s23.s3.c.ref,
3178 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3180 M_ALD_DSEG(REG_A1, disp);
3181 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3182 M_ALD_DSEG(REG_ITMP1, disp);
3183 M_ASUB_IMM(96, REG_SP);
3184 M_JSR(REG_RA, REG_ITMP1);
3185 M_AADD_IMM(96, REG_SP);
3187 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3188 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3190 d = codegen_reg_of_dst(jd, iptr, s1);
3194 emit_store_dst(jd, iptr, d);
3197 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3198 /* val.a: (classinfo*) superclass */
3200 /* superclass is an interface:
3202 * return (sub != NULL) &&
3203 * (sub->vftbl->interfacetablelength > super->index) &&
3204 * (sub->vftbl->interfacetable[-super->index] != NULL);
3206 * superclass is a class:
3208 * return ((sub != NULL) && (0
3209 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3210 * super->vftbl->diffvall));
3212 * If superclass is unresolved, we include both code snippets
3213 * above, a patcher resolves the class' flags and we select
3214 * the right code at runtime.
3219 vftbl_t *supervftbl;
3222 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3228 super = iptr->sx.s23.s3.c.cls;
3229 superindex = super->index;
3230 supervftbl = super->vftbl;
3233 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3234 # define LABEL_CLASS BRANCH_LABEL_2
3235 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3236 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3237 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3238 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3240 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3241 CODEGEN_CRITICAL_SECTION_NEW;
3243 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3244 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3246 M_MOV(s1, REG_ITMP1);
3250 /* if class is not resolved, check which code to call */
3252 if (super == NULL) {
3256 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3258 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3260 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3261 iptr->sx.s23.s3.c.ref, disp);
3263 ICONST(REG_ITMP3, ACC_INTERFACE);
3265 if (N_VALID_DSEG_DISP(disp)) {
3266 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3268 ICONST(REG_ITMP2, disp);
3269 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3272 emit_label_beq(cd, LABEL_CLASS);
3275 /* interface instanceof code */
3277 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3278 if (super == NULL) {
3279 /* If d == REG_ITMP2, then it's destroyed in check
3284 patcher_add_patch_ref(jd,
3285 PATCHER_checkcast_instanceof_interface,
3286 iptr->sx.s23.s3.c.ref, 0);
3291 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3294 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3295 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3296 M_ISUB_IMM(superindex, REG_ITMP3);
3298 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3302 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3303 superindex * sizeof(methodptr*))
3305 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3307 /* d := (REG_ITMP1 != 0) */
3309 N_LTR(d, REG_ITMP1);
3310 M_BEQ(SZ_BRC + SZ_LHI);
3313 if (super == NULL) {
3314 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3318 /* class instanceof code */
3320 if (super == NULL) {
3321 emit_label(cd, LABEL_CLASS);
3324 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3325 if (super == NULL) {
3326 disp = dseg_add_unique_address(cd, NULL);
3328 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3329 iptr->sx.s23.s3.c.ref,
3333 disp = dseg_add_address(cd, supervftbl);
3338 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3341 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3342 M_ALD_DSEG(REG_ITMP2, disp);
3344 CODEGEN_CRITICAL_SECTION_START;
3346 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3347 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3348 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3350 CODEGEN_CRITICAL_SECTION_END;
3352 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3354 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3356 M_BGT(SZ_BRC + SZ_LHI);
3360 if (super == NULL) {
3361 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3362 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3363 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3364 } else if (super->flags & ACC_INTERFACE) {
3365 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3366 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3368 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3371 # undef LABEL_EXIT_CHECK_NULL
3373 # undef LABEL_EXIT_INTERFACE_NULL
3374 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3375 # undef LABEL_EXIT_INTERFACE_DONE
3376 # undef LABEL_EXIT_CLASS_NULL
3378 emit_store_dst(jd, iptr, d);
3384 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3386 /* check for negative sizes and copy sizes to stack if necessary */
3388 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3391 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3393 /* copy SAVEDVAR sizes to stack */
3394 var = VAR(iptr->sx.s23.s2.args[s1]);
3396 /* Already Preallocated? */
3397 if (!(var->flags & PREALLOC)) {
3398 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3399 M_IST(s2, REG_SP, s1 * 4);
3403 /* is a patcher function set? */
3405 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3406 disp = dseg_add_unique_address(cd, 0);
3408 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3409 iptr->sx.s23.s3.c.ref,
3413 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3415 /* a0 = dimension count */
3417 ICONST(REG_A0, iptr->s1.argcount);
3419 /* a1 = classinfo */
3421 M_ALD_DSEG(REG_A1, disp);
3423 /* a2 = pointer to dimensions = stack pointer */
3425 M_MOV(REG_SP, REG_A2);
3427 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3428 M_ALD_DSEG(REG_ITMP1, disp);
3429 M_ASUB_IMM(96, REG_SP);
3430 M_JSR(REG_RA, REG_ITMP1);
3431 M_AADD_IMM(96, REG_SP);
3433 /* check for exception before result assignment */
3435 emit_exception_check(cd, iptr);
3437 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3438 M_INTMOVE(REG_RESULT, s1);
3439 emit_store_dst(jd, iptr, s1);
3444 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3448 } /* for instruction */
3450 MCODECHECK(512); /* XXX require a lower number? */
3452 /* At the end of a basic block we may have to append some nops,
3453 because the patcher stub calling code might be longer than the
3454 actual instruction. So codepatching does not change the
3455 following block unintentionally. */
3457 if (cd->mcodeptr < cd->lastmcodeptr) {
3458 while (cd->mcodeptr < cd->lastmcodeptr) {
3463 } /* if (bptr -> flags >= BBREACHED) */
3464 } /* for basic block */
3466 dseg_createlinenumbertable(cd);
3468 /* generate stubs */
3470 emit_patcher_traps(jd);
3472 /* everything's ok */
3478 /* codegen_emit_stub_compiler **************************************************
3480 Emits a stub routine which calls the compiler.
3482 *******************************************************************************/
3484 void codegen_emit_stub_compiler(jitdata *jd)
3489 /* get required compiler data */
3494 /* code for the stub */
3496 /* don't touch ITMP2 as it cointains the return address */
3498 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3500 /* REG_METHODPTR (REG_ITMP1) already used */
3501 M_ILD_DSEG(REG_ITMP3, -2 * SIZEOF_VOID_P); /* methodinfo */
3502 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3507 /* codegen_emit_stub_native ****************************************************
3509 Emits a stub routine which calls a native method.
3511 *******************************************************************************/
3514 arguments on stack \
3515 -------------------------------------------------| <- SP on nativestub entry
3517 callee saved int regs (none) |
3518 callee saved float regs (none) | stack frame like in cacao
3519 local variable slots (none) |
3520 arguments for calling methods (none) /
3521 ------------------------------------------------------------------ <- datasp
3526 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3527 0 - 96 register save area for callee /
3528 -------------------------------------------------------- <- SP native method
3530 SP after method entry
3533 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3539 s4 i, j; /* count variables */
3544 /* get required compiler data */
3550 /* set some variables */
3554 /* calculate stackframe size */
3556 cd->stackframesize =
3557 1 + /* return address */
3558 sizeof(stackframeinfo_t) / 8 +
3559 sizeof(localref_table) / 8 +
3562 (96 / 8); /* linkage area */
3564 /* keep stack 8-byte aligned */
3566 /*ALIGN_2(cd->stackframesize);*/
3568 /* create method header */
3570 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3571 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3572 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3573 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3574 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3575 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3576 (void) dseg_addlinenumbertablesize(cd);
3577 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3581 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3582 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3584 /* store return address */
3586 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3588 /* get function address (this must happen before the stackframeinfo) */
3590 funcdisp = dseg_add_functionptr(cd, f);
3593 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
3595 #if defined(ENABLE_GC_CACAO)
3596 /* Save callee saved integer registers in stackframeinfo (GC may
3597 need to recover them during a collection). */
3599 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3600 OFFSET(stackframeinfo_t, intregs);
3602 for (i = 0; i < INT_SAV_CNT; i++)
3603 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3606 /* save integer and float argument registers */
3608 for (i = 0; i < md->paramcount; i++) {
3609 if (!md->params[i].inmemory) {
3610 s1 = md->params[i].regoff;
3612 switch (md->paramtypes[i].type) {
3615 M_IST(s1, REG_SP, 96 + i * 8);
3618 M_LST(s1, REG_SP, 96 + i * 8);
3622 M_DST(s1, REG_SP, 96 + i * 8);
3628 /* create native stack info */
3630 M_MOV(REG_SP, REG_A0);
3631 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3632 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3633 M_ALD_DSEG(REG_ITMP2, disp);
3636 /* remember class argument */
3638 if (m->flags & ACC_STATIC)
3639 M_MOV(REG_RESULT, REG_ITMP3);
3641 /* restore integer and float argument registers */
3643 for (i = 0; i < md->paramcount; i++) {
3644 if (!md->params[i].inmemory) {
3645 s1 = md->params[i].regoff;
3647 switch (md->paramtypes[i].type) {
3650 M_ILD(s1, REG_SP, 96 + i * 8);
3653 M_LLD(s1, REG_SP, 96 + i * 8);
3657 M_DLD(s1, REG_SP, 96 + i * 8);
3663 /* copy or spill arguments to new locations */
3665 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3666 t = md->paramtypes[i].type;
3668 if (IS_INT_LNG_TYPE(t)) {
3669 if (!md->params[i].inmemory) {
3670 s1 = md->params[i].regoff;
3671 s2 = nmd->params[j].regoff;
3673 if (!nmd->params[j].inmemory) {
3674 if (IS_2_WORD_TYPE(t))
3680 if (IS_2_WORD_TYPE(t))
3681 M_LST(s1, REG_SP, s2);
3683 M_IST(s1, REG_SP, s2);
3687 s1 = md->params[i].regoff + cd->stackframesize * 8;
3688 s2 = nmd->params[j].regoff;
3690 if (IS_2_WORD_TYPE(t)) {
3691 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3693 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3698 /* We only copy spilled float arguments, as the float
3699 argument registers keep unchanged. */
3701 if (md->params[i].inmemory) {
3702 s1 = md->params[i].regoff + cd->stackframesize * 8;
3703 s2 = nmd->params[j].regoff;
3705 if (IS_2_WORD_TYPE(t)) {
3706 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3708 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3714 /* Handle native Java methods. */
3716 if (m->flags & ACC_NATIVE) {
3717 /* put class into second argument register */
3719 if (m->flags & ACC_STATIC)
3720 M_MOV(REG_ITMP3, REG_A1);
3722 /* put env into first argument register */
3724 disp = dseg_add_address(cd, _Jv_env);
3725 M_ALD_DSEG(REG_A0, disp);
3728 /* generate the actual native call */
3730 M_ALD_DSEG(REG_ITMP2, funcdisp);
3733 /* save return value */
3735 switch (md->returntype.type) {
3738 M_IST(REG_RESULT, REG_SP, 96);
3741 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3745 M_DST(REG_FRESULT, REG_SP, 96);
3751 /* remove native stackframe info */
3753 M_MOV(REG_SP, REG_A0);
3754 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3755 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3756 M_ALD_DSEG(REG_ITMP1, disp);
3759 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3761 /* restore return value */
3763 switch (md->returntype.type) {
3766 M_ILD(REG_RESULT, REG_SP, 96);
3769 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3773 M_DLD(REG_FRESULT, REG_SP, 96);
3779 #if defined(ENABLE_GC_CACAO)
3780 /* Restore callee saved integer registers from stackframeinfo (GC
3781 might have modified them during a collection). */
3783 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3784 OFFSET(stackframeinfo_t, intregs);
3786 for (i = 0; i < INT_SAV_CNT; i++)
3787 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3790 /* load return address */
3792 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3794 /* remove stackframe */
3796 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3798 /* check for exception */
3800 M_TEST(REG_ITMP3_XPTR);
3801 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3805 /* handle exception */
3807 M_MOV(REG_RA, REG_ITMP1_XPC);
3809 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3810 M_ALD_DSEG(REG_ITMP2, disp);
3811 M_JMP(RN, REG_ITMP2);
3813 /* generate patcher traps */
3815 emit_patcher_traps(jd);
3819 * These are local overrides for various environment variables in Emacs.
3820 * Please do not remove this and leave it at the end of the file, where
3821 * Emacs will automagically detect them.
3822 * ---------------------------------------------------------------------
3825 * indent-tabs-mode: t
3829 * vim:noexpandtab:sw=4:ts=4: