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 code->synchronizedoffset = rd->memuse * 8;
211 /* REMOVEME: We still need it for exception handling in assembler. */
213 if (code_is_leafmethod(code))
214 (void) dseg_add_unique_s4(cd, 1);
216 (void) dseg_add_unique_s4(cd, 0);
218 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
219 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
221 (void) dseg_addlinenumbertablesize(cd);
223 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
225 /* create exception table */
227 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
228 dseg_add_target(cd, ex->start);
229 dseg_add_target(cd, ex->end);
230 dseg_add_target(cd, ex->handler);
231 (void) dseg_add_unique_address(cd, ex->catchtype.any);
236 M_AADD_IMM(N_PV_OFFSET, REG_PV);
238 /* create stack frame (if necessary) */
240 if (cd->stackframesize) {
241 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
244 /* store return address */
246 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
248 /* generate method profiling code */
250 #if defined(ENABLE_PROFILING)
251 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
252 /* count frequency */
253 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
254 ICONST(REG_ITMP2, 1);
255 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
256 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
262 /* save used callee saved registers and return address */
264 p = cd->stackframesize - 1;
266 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
267 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
269 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
270 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
273 /* take arguments out of register or stack frame */
277 for (p = 0, l = 0; p < md->paramcount; p++) {
278 t = md->paramtypes[p].type;
279 varindex = jd->local_map[l * 5 + t];
283 if (IS_2_WORD_TYPE(t))
286 if (varindex == UNUSED)
291 s1 = md->params[p].regoff;
293 if (IS_INT_LNG_TYPE(t)) { /* integer args */
294 if (IS_2_WORD_TYPE(t)) {
302 if (!md->params[p].inmemory) { /* register arguments */
303 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
304 if (IS_2_WORD_TYPE(t)) {
305 M_LNGMOVE(s2, var->vv.regoff);
307 M_INTMOVE(s2, var->vv.regoff);
309 } else { /* reg arg -> spilled */
310 if (IS_2_WORD_TYPE(t)) {
311 M_LST(s2, REG_SP, var->vv.regoff);
313 M_IST(s2, REG_SP, var->vv.regoff);
317 } else { /* stack arguments */
318 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
319 if (IS_2_WORD_TYPE(t)) {
320 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
322 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
324 } else { /* stack arg -> spilled */
325 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
329 } else { /* floating args */
330 if (!md->params[p].inmemory) { /* register arguments */
332 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
333 M_FLTMOVE(s2, var->vv.regoff);
335 } else { /* reg arg -> spilled */
336 if (IS_2_WORD_TYPE(t))
337 M_DST(s2, REG_SP, var->vv.regoff);
339 M_FST(s2, REG_SP, var->vv.regoff);
342 } else { /* stack arguments */
343 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
344 if (IS_2_WORD_TYPE(t))
345 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
348 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
350 } else { /* stack-arg -> spilled */
351 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
352 var->vv.regoff = cd->stackframesize * 8 + s1;
358 /* save monitorenter argument */
360 #if defined(ENABLE_THREADS)
361 if (checksync && code_is_synchronized(code)) {
362 /* stack offset for monitor argument */
367 if (opt_verbosecall) {
368 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
370 for (p = 0; p < INT_ARG_CNT; p++)
371 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
373 for (p = 0; p < FLT_ARG_CNT; p++)
374 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
376 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
380 /* decide which monitor enter function to call */
382 if (m->flags & ACC_STATIC) {
383 disp = dseg_add_address(cd, &m->class->object.header);
384 M_ALD_DSEG(REG_A0, disp);
388 M_BNE(SZ_BRC + SZ_ILL);
389 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
392 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
393 M_ALD_DSEG(REG_ITMP2, disp);
395 M_AST(REG_A0, REG_SP, s1 * 8);
397 M_ASUB_IMM(96, REG_SP);
399 M_AADD_IMM(96, REG_SP);
402 if (opt_verbosecall) {
403 for (p = 0; p < INT_ARG_CNT; p++)
404 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
406 for (p = 0; p < FLT_ARG_CNT; p++)
407 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
409 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
416 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
417 emit_verbosecall_enter(jd);
418 #endif /* !defined(NDEBUG) */
422 /* end of header generation */
424 /* create replacement points */
426 REPLACEMENT_POINTS_INIT(cd, jd);
428 /* walk through all basic blocks */
430 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
432 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
434 if (bptr->flags >= BBREACHED) {
436 /* branch resolving */
438 codegen_resolve_branchrefs(cd, bptr);
440 /* handle replacement points */
442 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
444 /* copy interface registers to their destination */
449 #if defined(ENABLE_PROFILING)
450 /* generate basicblock profiling code */
452 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
453 /* count frequency */
455 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
456 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
457 ICONST(REG_ITMP2, 1);
458 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
459 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
461 /* if this is an exception handler, start profiling again */
463 if (bptr->type == BBTYPE_EXH)
468 #if defined(ENABLE_LSRA)
472 src = bptr->invars[len];
473 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
474 if (bptr->type == BBTYPE_EXH) {
475 /* d = reg_of_var(rd, src, REG_ITMP1); */
476 if (!IS_INMEMORY(src->flags))
480 M_INTMOVE(REG_ITMP3_XPTR, d);
481 emit_store(jd, NULL, src, d);
491 var = VAR(bptr->invars[len]);
492 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
493 if (bptr->type == BBTYPE_EXH) {
494 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
495 M_INTMOVE(REG_ITMP3_XPTR, d);
496 emit_store(jd, NULL, var, d);
500 assert((var->flags & INOUT));
503 #if defined(ENABLE_LSRA)
506 /* walk through all instructions */
511 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
512 if (iptr->line != currentline) {
513 dseg_addlinenumber(cd, iptr->line);
514 currentline = iptr->line;
517 MCODECHECK(1024); /* 1KB should be enough */
520 case ICMD_NOP: /* ... ==> ... */
521 case ICMD_POP: /* ..., value ==> ... */
522 case ICMD_POP2: /* ..., value, value ==> ... */
525 case ICMD_INLINE_START:
527 REPLACEMENT_POINT_INLINE_START(cd, iptr);
530 case ICMD_INLINE_BODY:
532 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
533 dseg_addlinenumber_inline_start(cd, iptr);
534 dseg_addlinenumber(cd, iptr->line);
537 case ICMD_INLINE_END:
539 dseg_addlinenumber_inline_end(cd, iptr);
540 dseg_addlinenumber(cd, iptr->line);
543 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
544 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
545 emit_nullpointer_check(cd, iptr, s1);
548 /* constant operations ************************************************/
550 case ICMD_ICONST: /* ... ==> ..., constant */
551 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
552 ICONST(d, iptr->sx.val.i);
553 emit_store_dst(jd, iptr, d);
556 case ICMD_LCONST: /* ... ==> ..., constant */
558 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
559 LCONST(d, iptr->sx.val.l);
560 emit_store_dst(jd, iptr, d);
563 case ICMD_FCONST: /* ... ==> ..., constant */
564 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
565 disp = dseg_add_float(cd, iptr->sx.val.f);
566 M_FLD_DSEG(d, disp, REG_ITMP1);
567 emit_store_dst(jd, iptr, d);
570 case ICMD_DCONST: /* ... ==> ..., constant */
571 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
572 disp = dseg_add_double(cd, iptr->sx.val.d);
573 M_DLD_DSEG(d, disp, REG_ITMP1);
574 emit_store_dst(jd, iptr, d);
577 case ICMD_ACONST: /* ... ==> ..., constant */
578 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
580 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
581 cr = iptr->sx.val.c.ref;
582 disp = dseg_add_unique_address(cd, cr);
584 /* PROFILE_CYCLE_STOP; */
586 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
589 /* PROFILE_CYCLE_START; */
593 if (iptr->sx.val.anyptr == 0) {
596 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
599 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
600 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
602 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
604 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
610 emit_store_dst(jd, iptr, d);
614 /* load/store/copy/move operations ************************************/
616 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
617 case ICMD_ALOAD: /* s1 = local variable */
621 case ICMD_ISTORE: /* ..., value ==> ... */
632 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
636 /* integer operations *************************************************/
638 case ICMD_INEG: /* ..., value ==> ..., - value */
640 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
641 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
643 emit_store_dst(jd, iptr, d);
647 case ICMD_LNEG: /* ..., value ==> ..., - value */
649 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
650 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
651 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
652 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
653 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
654 N_AHI(GET_HIGH_REG(d), -1);
655 emit_store_dst(jd, iptr, d);
658 case ICMD_I2L: /* ..., value ==> ..., value */
660 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
661 if (! N_IS_EVEN_ODD(d)) {
662 d = REG_ITMP31_PACKED;
664 assert(N_IS_EVEN_ODD(d));
666 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
668 M_INTMOVE(s1, GET_HIGH_REG(d));
669 M_SRDA_IMM(32, GET_HIGH_REG(d));
671 emit_copy_dst(jd, iptr, d);
672 emit_store_dst(jd, iptr, d);
675 case ICMD_L2I: /* ..., value ==> ..., value */
676 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
677 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
678 M_INTMOVE(GET_LOW_REG(s1), d);
679 emit_store_dst(jd, iptr, d);
682 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
683 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
684 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
688 emit_store_dst(jd, iptr, d);
691 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
692 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
693 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
697 emit_store_dst(jd, iptr, d);
700 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
702 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
703 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
707 emit_store_dst(jd, iptr, d);
710 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
712 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
713 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
714 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
721 emit_store_dst(jd, iptr, d);
726 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
727 /* sx.val.i = constant */
728 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
729 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
732 if (N_VALID_IMM(iptr->sx.val.i)) {
733 M_IADD_IMM(iptr->sx.val.i, d);
735 ICONST(REG_ITMP2, iptr->sx.val.i);
736 M_IADD(REG_ITMP2, d);
738 emit_store_dst(jd, iptr, d);
741 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
743 /* M, (r, q) -> (r, q) */
745 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
747 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
748 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
749 dd = GET_HIGH_REG(d);
758 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
759 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
769 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
770 N_AHI(GET_HIGH_REG(d), 1);
772 emit_store_dst(jd, iptr, d);
775 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
776 /* sx.val.l = constant */
778 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
779 dd = GET_HIGH_REG(d);
781 s1 = emit_load_s1_high(jd, iptr, dd);
782 s3 = iptr->sx.val.l >> 32;
786 if (N_VALID_IMM(s3)) {
789 ICONST(REG_ITMP3, s3);
790 M_IADD(REG_ITMP3, dd);
794 s1 = emit_load_s1_low(jd, iptr, dd);
795 s3 = iptr->sx.val.l & 0xffffffff;
796 ICONST(REG_ITMP3, s3);
799 N_ALR(dd, REG_ITMP3);
801 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
802 N_AHI(GET_HIGH_REG(d), 1);
804 emit_store_dst(jd, iptr, d);
807 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
809 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
810 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
811 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
813 M_INTMOVE(s1, REG_ITMP1);
814 M_ISUB(s2, REG_ITMP1);
815 M_INTMOVE(REG_ITMP1, d);
820 emit_store_dst(jd, iptr, d);
824 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
825 /* sx.val.i = constant */
827 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
828 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
831 if (N_VALID_IMM(-iptr->sx.val.i)) {
832 M_ISUB_IMM(iptr->sx.val.i, d);
834 ICONST(REG_ITMP2, iptr->sx.val.i);
835 M_ISUB(REG_ITMP2, d);
837 emit_store_dst(jd, iptr, d);
841 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
843 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
845 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
846 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
847 dd = GET_HIGH_REG(d);
850 M_INTMOVE(s2, REG_ITMP3);
857 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
858 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
862 M_INTMOVE(s2, REG_ITMP3);
869 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
870 N_AHI(GET_HIGH_REG(d), -1);
872 emit_store_dst(jd, iptr, d);
875 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
876 /* sx.val.l = constant */
878 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
880 dd = GET_HIGH_REG(d);
881 s1 = emit_load_s1_high(jd, iptr, dd);
882 s3 = iptr->sx.val.l >> 32;
886 if (N_VALID_IMM(-s3)) {
889 ICONST(REG_ITMP3, s3);
890 M_ISUB(REG_ITMP3, dd);
894 s1 = emit_load_s1_low(jd, iptr, dd);
895 s3 = iptr->sx.val.l & 0xffffffff;
896 ICONST(REG_ITMP3, s3);
899 N_SLR(dd, REG_ITMP3);
901 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
902 N_AHI(GET_HIGH_REG(d), -1);
904 emit_store_dst(jd, iptr, d);
907 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
909 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
910 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
911 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
918 emit_store_dst(jd, iptr, d);
922 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
923 /* sx.val.i = constant */
924 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
925 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
927 if (iptr->sx.val.i == 2) {
929 } else if (N_VALID_IMM(iptr->sx.val.i)) {
930 M_IMUL_IMM(iptr->sx.val.i, d);
932 disp = dseg_add_s4(cd, iptr->sx.val.i);
933 M_ILD_DSEG(REG_ITMP2, disp);
934 M_IMUL(REG_ITMP2, d);
936 emit_store_dst(jd, iptr, d);
939 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
940 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
942 /* load s1 into r0 */
944 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
945 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
946 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
948 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
950 /* extend s1 to long */
952 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
956 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
962 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
963 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
966 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
967 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
971 emit_store_dst(jd, iptr, d);
975 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
976 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
978 bte = iptr->sx.s23.s3.bte;
981 /* test s2 for zero */
983 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
984 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
985 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
986 emit_arithmetic_check(cd, iptr, REG_ITMP3);
990 disp = dseg_add_functionptr(cd, bte->fp);
994 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
996 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
997 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
1001 M_ASUB_IMM(96, REG_SP);
1002 M_ALD_DSEG(REG_ITMP2, disp);
1003 M_JSR(REG_RA, REG_ITMP2);
1004 M_AADD_IMM(96, REG_SP);
1008 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1009 M_LNGMOVE(REG_RESULT_PACKED, d);
1010 emit_store_dst(jd, iptr, d);
1014 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1015 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1016 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1018 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1019 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1020 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1022 /* Use only 5 bits of sencond operand. */
1024 M_INTMOVE(s2, REG_ITMP2);
1026 ICONST(REG_ITMP3, 0x1F);
1027 M_IAND(REG_ITMP3, s2);
1031 switch (iptr->opc) {
1044 emit_store_dst(jd, iptr, d);
1047 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1048 /* sx.val.i = constant */
1052 assert(iptr->sx.val.i <= 32);
1054 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1055 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1062 s3 = (1 << iptr->sx.val.i) - 1;
1064 if (N_VALID_IMM(s3)) {
1067 ICONST(REG_ITMP1, -1);
1068 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1069 M_IADD(REG_ITMP1, d);
1072 N_BRC_BACK_PATCH(ref);
1074 M_SRA_IMM(iptr->sx.val.i, d);
1076 emit_store_dst(jd, iptr, d);
1081 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1082 /* sx.val.i = constant */
1084 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1085 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1088 M_MOV(s1, REG_ITMP1);
1092 ICONST(REG_ITMP3, iptr->sx.val.i);
1095 M_IAND(REG_ITMP3, d);
1098 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1104 emit_store_dst(jd, iptr, d);
1108 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1109 /* sx.val.i = constant */
1110 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1111 /* sx.val.i = constant */
1112 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1113 /* sx.val.i = constant */
1114 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1115 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1119 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1121 switch (iptr->opc) {
1122 case ICMD_ISHLCONST:
1125 case ICMD_ISHRCONST:
1128 case ICMD_IUSHRCONST:
1135 emit_store_dst(jd, iptr, d);
1138 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1140 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1142 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1144 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1146 /* Use only 6 bits of second operand */
1148 M_INTMOVE(s2, REG_ITMP2);
1150 ICONST(REG_ITMP1, 0x3F);
1151 M_IAND(REG_ITMP1, s2);
1153 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1154 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1156 /* Destination must be even-odd pair */
1158 if (! N_IS_EVEN_ODD(d)) {
1159 d = REG_ITMP31_PACKED;
1162 assert(N_IS_EVEN_ODD(d));
1166 switch (iptr->opc) {
1168 M_SLDL(s2, GET_HIGH_REG(d));
1171 M_SRDA(s2, GET_HIGH_REG(d));
1174 M_SRDL(s2, GET_HIGH_REG(d));
1180 emit_copy_dst(jd, iptr, d);
1181 emit_store_dst(jd, iptr, d);
1185 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1186 /* sx.val.i = constant */
1187 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1188 /* sx.val.i = constant */
1189 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1190 /* sx.val.l = constant */
1193 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1194 if (! N_IS_EVEN_ODD(d)) {
1195 d = REG_ITMP31_PACKED;
1197 assert(N_IS_EVEN_ODD(d));
1199 s1 = emit_load_s1(jd, iptr, d);
1203 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1205 switch (iptr->opc) {
1206 case ICMD_LSHLCONST:
1207 N_SLDL(GET_HIGH_REG(d), disp, RN);
1209 case ICMD_LSHRCONST:
1210 N_SRDA(GET_HIGH_REG(d), disp, RN);
1212 case ICMD_LUSHRCONST:
1213 N_SRDL(GET_HIGH_REG(d), disp, RN);
1216 N_SLDL(GET_HIGH_REG(d), disp, RN);
1222 emit_copy_dst(jd, iptr, d);
1223 emit_store_dst(jd, iptr, d);
1226 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1228 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1229 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1230 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1237 emit_store_dst(jd, iptr, d);
1241 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1243 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1244 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1245 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1252 emit_store_dst(jd, iptr, d);
1256 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1258 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1259 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1260 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1267 emit_store_dst(jd, iptr, d);
1273 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1274 /* sx.val.i = constant */
1275 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1276 /* sx.val.i = constant */
1277 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1278 /* sx.val.i = constant */
1280 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1281 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1284 ICONST(REG_ITMP2, iptr->sx.val.i);
1286 switch (iptr->opc) {
1287 case ICMD_IANDCONST:
1288 M_IAND(REG_ITMP2, d);
1290 case ICMD_IXORCONST:
1291 M_IXOR(REG_ITMP2, d);
1294 M_IOR(REG_ITMP2, d);
1300 emit_store_dst(jd, iptr, d);
1304 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1305 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1306 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1308 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1310 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1311 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1312 dd = GET_LOW_REG(d);
1314 switch (iptr->opc) {
1343 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1344 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1345 dd = GET_HIGH_REG(d);
1347 switch (iptr->opc) {
1376 emit_store_dst(jd, iptr, d);
1379 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1380 /* sx.val.l = constant */
1381 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1382 /* sx.val.l = constant */
1383 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1384 /* sx.val.l = constant */
1386 /* TODO should use memory operand to access data segment, not load */
1388 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1390 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1391 s3 = iptr->sx.val.l & 0xffffffff;
1393 M_INTMOVE(s1, GET_LOW_REG(d));
1395 ICONST(REG_ITMP3, s3);
1397 switch (iptr->opc) {
1398 case ICMD_LANDCONST:
1399 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1401 case ICMD_LXORCONST:
1402 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1405 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1411 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1412 s3 = iptr->sx.val.l >> 32;
1414 M_INTMOVE(s1, GET_HIGH_REG(d));
1416 ICONST(REG_ITMP3, s3);
1418 switch (iptr->opc) {
1419 case ICMD_LANDCONST:
1420 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1422 case ICMD_LXORCONST:
1423 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1426 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1432 emit_store_dst(jd, iptr, d);
1436 /* floating operations ************************************************/
1438 case ICMD_FNEG: /* ..., value ==> ..., - value */
1439 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1440 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1442 emit_store_dst(jd, iptr, d);
1445 case ICMD_DNEG: /* ..., 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_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1453 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1454 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1455 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1462 emit_store_dst(jd, iptr, d);
1465 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1466 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1467 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1468 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1475 emit_store_dst(jd, iptr, d);
1478 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1479 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1480 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1481 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1485 emit_store_dst(jd, iptr, d);
1488 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1489 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1490 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1491 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1495 emit_store_dst(jd, iptr, d);
1498 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1499 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1500 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1501 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1508 emit_store_dst(jd, iptr, d);
1511 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1512 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1513 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1514 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1521 emit_store_dst(jd, iptr, d);
1524 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1525 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1526 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1527 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1531 emit_store_dst(jd, iptr, d);
1534 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1535 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1536 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1537 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1541 emit_store_dst(jd, iptr, d);
1544 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1545 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1546 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1548 emit_store_dst(jd, iptr, d);
1551 case ICMD_I2D: /* ..., value ==> ..., (double) 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_F2I: /* ..., value ==> ..., (int) value */
1562 #ifdef SUPPORT_HERCULES
1566 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1567 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1571 switch (iptr->opc) {
1580 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1581 N_LHI(d, 0); /* Load 0 */
1582 ref1 = cd->mcodeptr;
1583 N_BRC(DD_ANY, 0); /* Exit */
1587 switch (iptr->opc) {
1596 #ifdef SUPPORT_HERCULES
1597 /* Hercules does the conversion using a plain C conversion.
1598 * According to manual, real hardware should *NOT* require this.
1600 * Corner case: Positive float leads to INT_MIN (overflow).
1603 switch (iptr->opc) {
1612 ref2 = cd->mcodeptr;
1613 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1617 ref3 = cd->mcodeptr;
1618 M_BGE(0); /* If integer result is negative, continue */
1620 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1621 M_ILD_DSEG(d, disp);
1623 N_BRC_BACK_PATCH(ref1);
1624 #ifdef SUPPORT_HERCULES
1625 N_BRC_BACK_PATCH(ref2);
1626 N_BRC_BACK_PATCH(ref3);
1628 emit_store_dst(jd, iptr, d);
1632 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1635 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1636 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1637 #ifdef SUPPORT_HERCULES
1640 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1641 disp = dseg_add_double(cd, 0.0 / 0.0);
1642 M_DLD_DSEG(d, disp, REG_ITMP1);
1643 emit_label_br(cd, BRANCH_LABEL_1);
1644 N_BRC_BACK_PATCH(ref);
1647 #ifdef SUPPORT_HERCULES
1648 emit_label(cd, BRANCH_LABEL_1);
1650 emit_store_dst(jd, iptr, d);
1654 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1655 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1656 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1658 emit_store_dst(jd, iptr, d);
1661 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1662 /* == => 0, < => 1, > => -1 */
1666 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1667 /* == => 0, < => 1, > => -1 */
1670 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1671 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1672 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1674 switch (iptr->opc) {
1686 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1687 SZ_BRC + SZ_BRC + SZ_BRC
1690 N_BRC( /* load -1 */
1691 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1692 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1697 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1700 N_LHI(d, 1); /* GT */
1701 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1702 N_LHI(d, -1); /* LT */
1703 M_BR(SZ_BRC + SZ_LHI);
1704 N_LHI(d, 0); /* EQ */
1706 emit_store_dst(jd, iptr, d);
1711 /* memory operations **************************************************/
1713 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1715 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1716 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1718 /* implicit null-pointer check */
1719 M_ILD(d, s1, OFFSET(java_array_t, size));
1720 emit_store_dst(jd, iptr, d);
1724 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1725 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1726 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1727 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1729 /* implicit null-pointer check */
1730 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1732 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1737 emit_store_dst(jd, iptr, d);
1740 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1742 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1743 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1744 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1746 /* implicit null-pointer check */
1747 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1749 M_INTMOVE(s2, REG_ITMP2);
1750 M_SLL_IMM(1, REG_ITMP2);
1752 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1754 /* N_LH does sign extends, undo ! */
1759 emit_store_dst(jd, iptr, d);
1762 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1763 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1764 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1765 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1767 /* implicit null-pointer check */
1768 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1770 M_INTMOVE(s2, REG_ITMP2);
1771 M_SLL_IMM(1, REG_ITMP2);
1773 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1774 emit_store_dst(jd, iptr, d);
1777 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1778 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1779 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1780 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1782 /* implicit null-pointer check */
1783 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1785 M_INTMOVE(s2, REG_ITMP2);
1786 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1787 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1788 emit_store_dst(jd, iptr, d);
1791 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1793 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1794 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1796 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1798 /* implicit null-pointer check */
1799 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1801 M_INTMOVE(s2, REG_ITMP2);
1802 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1805 GET_LOW_REG(d) /* maybe itmp3 */,
1806 OFFSET(java_intarray_t, data[0]) + 4,
1807 REG_ITMP2, s1 /* maybe itmp1 */
1811 GET_HIGH_REG(d) /* maybe itmp1 */,
1812 OFFSET(java_intarray_t, data[0]),
1813 REG_ITMP2, s1 /* maybe itmp1 */
1816 emit_store_dst(jd, iptr, d);
1820 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1822 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1823 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1824 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1826 /* implicit null-pointer check */
1827 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1829 M_INTMOVE(s2, REG_ITMP2);
1830 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1832 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1834 emit_store_dst(jd, iptr, d);
1837 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1838 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1839 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1840 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1842 /* implicit null-pointer check */
1843 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1845 M_INTMOVE(s2, REG_ITMP2);
1846 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1848 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1850 emit_store_dst(jd, iptr, d);
1853 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1854 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1855 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1856 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1858 /* implicit null-pointer check */
1859 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1861 M_INTMOVE(s2, REG_ITMP2);
1862 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1863 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1864 emit_store_dst(jd, iptr, d);
1867 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1868 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1869 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1870 /* implicit null-pointer check */
1871 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1872 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1874 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1877 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1879 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1880 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1881 /* implicit null-pointer check */
1882 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1883 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1885 M_INTMOVE(s2, REG_ITMP2);
1886 M_SLL_IMM(1, REG_ITMP2);
1888 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1892 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1893 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1894 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1895 /* implicit null-pointer check */
1896 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1897 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1899 M_INTMOVE(s2, REG_ITMP2);
1900 M_SLL_IMM(1, REG_ITMP2);
1902 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1905 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1907 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1908 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1909 /* implicit null-pointer check */
1910 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1912 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1914 M_INTMOVE(s2, REG_ITMP2);
1915 M_SLL_IMM(2, REG_ITMP2);
1917 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1920 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1922 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1923 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1924 /* implicit null-pointer check */
1925 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1927 M_INTMOVE(s2, REG_ITMP2);
1928 M_SLL_IMM(3, REG_ITMP2);
1930 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1931 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1932 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1933 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1936 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1937 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1938 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1939 /* implicit null-pointer check */
1940 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1941 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1943 M_INTMOVE(s2, REG_ITMP2);
1944 M_SLL_IMM(2, REG_ITMP2);
1946 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1949 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1950 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1951 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1952 /* implicit null-pointer check */
1953 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1954 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1956 M_INTMOVE(s2, REG_ITMP2);
1957 M_SLL_IMM(3, REG_ITMP2);
1959 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1962 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1964 s1 = emit_load_s1(jd, iptr, REG_A0);
1965 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1966 /* implicit null-pointer check */
1967 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1968 s3 = emit_load_s3(jd, iptr, REG_A1);
1970 M_INTMOVE(s1, REG_A0);
1971 M_INTMOVE(s3, REG_A1);
1973 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1974 M_ALD_DSEG(REG_ITMP2, disp);
1975 M_ASUB_IMM(96, REG_SP);
1976 M_JSR(REG_RA, REG_ITMP2);
1977 M_AADD_IMM(96, REG_SP);
1979 emit_arraystore_check(cd, iptr);
1981 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1982 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1983 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1985 M_INTMOVE(s2, REG_ITMP2);
1986 M_SLL_IMM(2, REG_ITMP2);
1987 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1990 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1991 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1996 case ICMD_GETSTATIC: /* ... ==> ..., value */
1998 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1999 uf = iptr->sx.s23.s3.uf;
2000 fieldtype = uf->fieldref->parseddesc.fd->type;
2001 disp = dseg_add_unique_address(cd, NULL);
2003 /* PROFILE_CYCLE_STOP; */
2005 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2007 /* PROFILE_CYCLE_START; */
2010 fi = iptr->sx.s23.s3.fmiref->p.field;
2011 fieldtype = fi->type;
2012 disp = dseg_add_address(cd, fi->value);
2014 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2017 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
2019 PROFILE_CYCLE_START;
2023 M_ALD_DSEG(REG_ITMP1, disp);
2025 switch (fieldtype) {
2027 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2028 M_ILD(d, REG_ITMP1, 0);
2031 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2032 M_LLD(d, REG_ITMP1, 0);
2035 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2036 M_ALD(d, REG_ITMP1, 0);
2039 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2040 M_FLD(d, REG_ITMP1, 0);
2043 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2044 M_DLD(d, REG_ITMP1, 0);
2048 emit_store_dst(jd, iptr, d);
2052 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2054 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2055 uf = iptr->sx.s23.s3.uf;
2056 fieldtype = uf->fieldref->parseddesc.fd->type;
2057 disp = dseg_add_unique_address(cd, uf);
2059 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2062 fi = iptr->sx.s23.s3.fmiref->p.field;
2063 fieldtype = fi->type;
2064 disp = dseg_add_address(cd, fi->value);
2066 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2068 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
2069 PROFILE_CYCLE_START;
2073 M_ALD_DSEG(REG_ITMP1, disp);
2074 switch (fieldtype) {
2076 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2077 M_IST(s1, REG_ITMP1, 0);
2080 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2081 M_LST(s1, REG_ITMP1, 0);
2084 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2085 M_AST(s1, REG_ITMP1, 0);
2088 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2089 M_FST(s1, REG_ITMP1, 0);
2092 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2093 M_DST(s1, REG_ITMP1, 0);
2098 case ICMD_GETFIELD: /* ... ==> ..., value */
2100 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2101 emit_nullpointer_check(cd, iptr, s1);
2103 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2104 uf = iptr->sx.s23.s3.uf;
2105 fieldtype = uf->fieldref->parseddesc.fd->type;
2108 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2111 fi = iptr->sx.s23.s3.fmiref->p.field;
2112 fieldtype = fi->type;
2116 switch (fieldtype) {
2118 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2122 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2123 if (GET_HIGH_REG(d) == s1) {
2124 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2125 M_ILD(GET_HIGH_REG(d), s1, disp);
2128 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2129 M_ILD(GET_HIGH_REG(d), s1, disp);
2133 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2137 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2141 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2145 emit_store_dst(jd, iptr, d);
2148 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2152 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2153 emit_nullpointer_check(cd, iptr, s1);
2155 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2156 uf = iptr->sx.s23.s3.uf;
2157 fieldtype = uf->fieldref->parseddesc.fd->type;
2161 fi = iptr->sx.s23.s3.fmiref->p.field;
2162 fieldtype = fi->type;
2166 /* We can't add a patcher ref behind this load,
2167 * because the patcher would destroy REG_ITMP3.
2169 * We pass in the disp parameter, how many bytes
2170 * to skip to the to the actual store.
2172 * XXX this relies on patcher_add_patch_ref internals
2175 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2176 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2181 if (IS_INT_LNG_TYPE(fieldtype)) {
2182 if (IS_2_WORD_TYPE(fieldtype))
2183 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2185 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2187 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2190 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2191 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2194 switch (fieldtype) {
2196 M_IST(s2, s1, disp);
2199 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2200 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2203 M_AST(s2, s1, disp);
2206 M_FST(s2, s1, disp);
2209 M_DST(s2, s1, disp);
2216 /* branch operations **************************************************/
2218 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2220 /* PROFILE_CYCLE_STOP; */
2222 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2223 M_INTMOVE(s1, REG_ITMP3_XPTR);
2225 #ifdef ENABLE_VERIFIER
2226 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2227 uc = iptr->sx.s23.s2.uc;
2229 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2231 #endif /* ENABLE_VERIFIER */
2233 disp = dseg_add_functionptr(cd, asm_handle_exception);
2234 M_ALD_DSEG(REG_ITMP1, disp);
2235 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2240 case ICMD_GOTO: /* ... ==> ... */
2241 case ICMD_RET: /* ... ==> ... */
2243 emit_br(cd, iptr->dst.block);
2247 case ICMD_JSR: /* ... ==> ... */
2249 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2253 case ICMD_IFNULL: /* ..., value ==> ... */
2254 case ICMD_IFNONNULL: /* ..., value ==> ... */
2255 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2257 switch (iptr->opc) {
2259 emit_beq(cd, iptr->dst.block);
2261 case ICMD_IFNONNULL:
2262 emit_bne(cd, iptr->dst.block);
2267 case ICMD_IFEQ: /* ..., value ==> ... */
2268 case ICMD_IFLT: /* ..., value ==> ... */
2269 case ICMD_IFLE: /* ..., value ==> ... */
2270 case ICMD_IFNE: /* ..., value ==> ... */
2271 case ICMD_IFGT: /* ..., value ==> ... */
2272 case ICMD_IFGE: /* ..., value ==> ... */
2274 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2276 if (N_VALID_IMM(iptr->sx.val.i))
2277 M_ICMP_IMM(s1, iptr->sx.val.i);
2279 disp = dseg_add_s4(cd, iptr->sx.val.i);
2280 if (N_VALID_DSEG_DISP(disp)) {
2281 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2283 ICONST(REG_ITMP2, disp);
2284 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2288 switch (iptr->opc) {
2290 emit_blt(cd, iptr->dst.block);
2293 emit_ble(cd, iptr->dst.block);
2296 emit_bne(cd, iptr->dst.block);
2299 emit_bgt(cd, iptr->dst.block);
2302 emit_bge(cd, iptr->dst.block);
2305 emit_beq(cd, iptr->dst.block);
2311 case ICMD_IF_LLT: /* ..., value ==> ... */
2312 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2318 /* ATTENTION: compare high words signed and low words unsigned */
2320 # define LABEL_OUT BRANCH_LABEL_1
2322 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2324 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2325 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2327 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2328 if (N_VALID_DSEG_DISP(disp)) {
2329 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2331 ICONST(REG_ITMP2, disp);
2332 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2339 emit_blt(cd, iptr->dst.block);
2340 /* EQ ... fall through */
2341 emit_label_bgt(cd, LABEL_OUT);
2345 emit_bgt(cd, iptr->dst.block);
2346 /* EQ ... fall through */
2347 emit_label_blt(cd, LABEL_OUT);
2350 /* EQ ... fall through */
2351 emit_label_bne(cd, LABEL_OUT);
2354 /* EQ ... fall through */
2355 emit_bne(cd, iptr->dst.block);
2361 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2363 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2364 if (N_VALID_DSEG_DISP(disp)) {
2365 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2367 ICONST(REG_ITMP2, disp);
2368 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2373 emit_blt(cd, iptr->dst.block);
2374 emit_label(cd, LABEL_OUT);
2377 emit_ble(cd, iptr->dst.block);
2378 emit_label(cd, LABEL_OUT);
2381 emit_bgt(cd, iptr->dst.block);
2382 emit_label(cd, LABEL_OUT);
2385 emit_bge(cd, iptr->dst.block);
2386 emit_label(cd, LABEL_OUT);
2389 emit_beq(cd, iptr->dst.block);
2390 emit_label(cd, LABEL_OUT);
2393 emit_bne(cd, iptr->dst.block);
2402 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2403 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2405 /* Compare addresses as 31 bit unsigned integers */
2407 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2408 M_LDA(REG_ITMP1, s1, 0);
2410 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2411 M_LDA(REG_ITMP2, s2, 0);
2413 M_CMP(REG_ITMP1, REG_ITMP2);
2415 switch (iptr->opc) {
2416 case ICMD_IF_ACMPEQ:
2417 emit_beq(cd, iptr->dst.block);
2419 case ICMD_IF_ACMPNE:
2420 emit_bne(cd, iptr->dst.block);
2426 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2427 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2428 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2429 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2430 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2431 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2433 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2434 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2436 switch (iptr->opc) {
2437 case ICMD_IF_ICMPEQ:
2438 emit_beq(cd, iptr->dst.block);
2440 case ICMD_IF_ICMPNE:
2441 emit_bne(cd, iptr->dst.block);
2443 case ICMD_IF_ICMPLT:
2444 emit_blt(cd, iptr->dst.block);
2446 case ICMD_IF_ICMPGT:
2447 emit_bgt(cd, iptr->dst.block);
2449 case ICMD_IF_ICMPLE:
2450 emit_ble(cd, iptr->dst.block);
2452 case ICMD_IF_ICMPGE:
2453 emit_bge(cd, iptr->dst.block);
2459 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2460 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2461 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2462 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2463 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2464 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2469 /* ATTENTION: compare high words signed and low words unsigned */
2471 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2472 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2477 case ICMD_IF_LCMPLT:
2478 case ICMD_IF_LCMPLE:
2479 emit_blt(cd, iptr->dst.block);
2480 /* EQ ... fall through */
2481 out_ref = cd->mcodeptr;
2484 case ICMD_IF_LCMPGT:
2485 case ICMD_IF_LCMPGE:
2486 emit_bgt(cd, iptr->dst.block);
2487 /* EQ ... fall through */
2488 out_ref = cd->mcodeptr;
2491 case ICMD_IF_LCMPEQ:
2492 /* EQ ... fall through */
2493 out_ref = cd->mcodeptr;
2496 case ICMD_IF_LCMPNE:
2497 /* EQ ... fall through */
2498 emit_bne(cd, iptr->dst.block);
2504 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2505 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2510 case ICMD_IF_LCMPLT:
2511 emit_blt(cd, iptr->dst.block);
2513 case ICMD_IF_LCMPLE:
2514 emit_ble(cd, iptr->dst.block);
2516 case ICMD_IF_LCMPGT:
2517 emit_bgt(cd, iptr->dst.block);
2519 case ICMD_IF_LCMPGE:
2520 emit_bge(cd, iptr->dst.block);
2522 case ICMD_IF_LCMPEQ:
2523 emit_beq(cd, iptr->dst.block);
2525 case ICMD_IF_LCMPNE:
2526 emit_bne(cd, iptr->dst.block);
2532 if (out_ref != NULL) {
2533 N_BRC_BACK_PATCH(out_ref);
2539 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2541 REPLACEMENT_POINT_RETURN(cd, iptr);
2542 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2543 M_INTMOVE(s1, REG_RESULT);
2544 goto nowperformreturn;
2546 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2548 REPLACEMENT_POINT_RETURN(cd, iptr);
2549 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2550 M_INTMOVE(s1, REG_RESULT);
2552 #ifdef ENABLE_VERIFIER
2553 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2554 unresolved_class *uc = iptr->sx.s23.s2.uc;
2557 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2558 PROFILE_CYCLE_START;
2560 #endif /* ENABLE_VERIFIER */
2561 goto nowperformreturn;
2563 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2565 REPLACEMENT_POINT_RETURN(cd, iptr);
2566 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2567 M_LNGMOVE(s1, REG_RESULT_PACKED);
2568 goto nowperformreturn;
2570 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2573 REPLACEMENT_POINT_RETURN(cd, iptr);
2574 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2575 M_FLTMOVE(s1, REG_FRESULT);
2576 goto nowperformreturn;
2578 case ICMD_RETURN: /* ... ==> ... */
2580 REPLACEMENT_POINT_RETURN(cd, iptr);
2586 p = cd->stackframesize;
2588 /* call trace function */
2590 #if !defined(NDEBUG)
2591 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2592 emit_verbosecall_exit(jd);
2593 #endif /* !defined(NDEBUG) */
2595 #if defined(ENABLE_THREADS)
2596 if (checksync && code_is_synchronized(code)) {
2597 /* we need to save the proper return value */
2599 switch (iptr->opc) {
2601 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2605 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2608 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2611 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2615 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2617 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2618 M_ALD_DSEG(REG_ITMP2, disp);
2620 M_ASUB_IMM(96, REG_SP);
2622 M_AADD_IMM(96, REG_SP);
2624 /* and now restore the proper return value */
2626 switch (iptr->opc) {
2628 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2632 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2635 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2638 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2644 /* restore return address */
2646 p--; M_ALD(REG_RA, REG_SP, p * 8);
2648 /* restore saved registers */
2650 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2651 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2653 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2654 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2657 /* deallocate stack */
2659 if (cd->stackframesize)
2660 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2662 /* generate method profiling code */
2670 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2673 branch_target_t *table;
2675 table = iptr->dst.table;
2677 l = iptr->sx.s23.s2.tablelow;
2678 i = iptr->sx.s23.s3.tablehigh;
2680 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2681 M_INTMOVE(s1, REG_ITMP1);
2685 } else if (N_VALID_IMM(-l)) {
2686 M_ISUB_IMM(l, REG_ITMP1);
2688 ICONST(REG_ITMP2, l);
2689 M_ISUB(REG_ITMP2, REG_ITMP1);
2692 /* number of targets */
2698 ICONST(REG_ITMP2, i);
2699 M_ICMPU(REG_ITMP1, REG_ITMP2);
2700 emit_bge(cd, table[0].block);
2702 /* build jump table top down and use address of lowest entry */
2707 dseg_add_target(cd, table->block);
2712 /* length of dataseg after last dseg_add_target is used by load */
2714 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2715 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2716 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2717 M_JMP(RN, REG_ITMP1);
2722 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2725 lookup_target_t *lookup;
2727 lookup = iptr->dst.lookup;
2729 i = iptr->sx.s23.s2.lookupcount;
2731 MCODECHECK(8 + ((7 + 6) * i) + 5);
2732 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2735 if (N_VALID_IMM(lookup->value)) {
2736 M_ICMP_IMM(s1, lookup->value);
2738 ICONST(REG_ITMP2, lookup->value);
2739 M_ICMP(REG_ITMP2, s1);
2741 emit_beq(cd, lookup->target.block);
2745 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2750 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2752 bte = iptr->sx.s23.s3.bte;
2756 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2757 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2758 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2759 case ICMD_INVOKEINTERFACE:
2761 REPLACEMENT_POINT_INVOKE(cd, iptr);
2763 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2765 um = iptr->sx.s23.s3.um;
2766 md = um->methodref->parseddesc.md;
2769 lm = iptr->sx.s23.s3.fmiref->p.method;
2771 md = lm->parseddesc;
2775 s3 = md->paramcount;
2777 MCODECHECK((s3 << 1) + 64);
2779 /* copy arguments to registers or stack location */
2781 for (s3 = s3 - 1; s3 >= 0; s3--) {
2782 var = VAR(iptr->sx.s23.s2.args[s3]);
2784 /* Already Preallocated? */
2785 if (var->flags & PREALLOC)
2788 if (IS_INT_LNG_TYPE(var->type)) {
2789 if (!md->params[s3].inmemory) {
2790 if (IS_2_WORD_TYPE(var->type)) {
2792 GET_LOW_REG(md->params[s3].regoff),
2793 GET_HIGH_REG(md->params[s3].regoff)
2795 d = emit_load(jd, iptr, var, s1);
2799 s1 = md->params[s3].regoff;
2800 d = emit_load(jd, iptr, var, s1);
2805 if (IS_2_WORD_TYPE(var->type)) {
2806 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2807 M_LST(d, REG_SP, md->params[s3].regoff);
2810 d = emit_load(jd, iptr, var, REG_ITMP1);
2811 M_IST(d, REG_SP, md->params[s3].regoff);
2816 if (!md->params[s3].inmemory) {
2817 s1 = md->params[s3].regoff;
2818 d = emit_load(jd, iptr, var, s1);
2822 d = emit_load(jd, iptr, var, REG_FTMP1);
2823 if (IS_2_WORD_TYPE(var->type))
2824 M_DST(d, REG_SP, md->params[s3].regoff);
2826 M_FST(d, REG_SP, md->params[s3].regoff);
2831 /* generate method profiling code */
2835 switch (iptr->opc) {
2837 if (bte->stub == NULL) {
2838 disp = dseg_add_functionptr(cd, bte->fp);
2839 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2841 disp = dseg_add_functionptr(cd, bte->stub);
2844 if (N_VALID_DSEG_DISP(disp)) {
2845 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2847 N_LHI(REG_ITMP1, disp);
2848 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2852 case ICMD_INVOKESPECIAL:
2854 /* Implicit NULL pointer check */
2855 M_ILD(REG_ITMP1, REG_A0, 0);
2859 case ICMD_INVOKESTATIC:
2861 disp = dseg_add_unique_address(cd, um);
2863 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2867 disp = dseg_add_address(cd, lm->stubroutine);
2869 if (N_VALID_DSEG_DISP(disp)) {
2870 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2872 N_LHI(REG_ITMP1, disp);
2873 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2877 case ICMD_INVOKEVIRTUAL:
2878 /* TODO softnull REG_A0 */
2881 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2886 s1 = OFFSET(vftbl_t, table[0]) +
2887 sizeof(methodptr) * lm->vftblindex;
2890 /* implicit null-pointer check */
2892 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2893 M_ALD(REG_PV, REG_METHODPTR, s1);
2896 case ICMD_INVOKEINTERFACE:
2897 /* TODO softnull REG_A0 */
2899 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2900 * and -0xFFF in index register (itmp1)
2904 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2910 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2911 sizeof(methodptr*) * lm->class->index;
2913 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2916 /* Implicit null-pointer check */
2917 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2918 N_LHI(REG_ITMP2, s1);
2919 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2920 M_ALD(REG_PV, REG_METHODPTR, s2);
2924 /* generate the actual call */
2927 emit_restore_pv(cd);
2929 /* post call finalization */
2931 switch (iptr->opc) {
2933 if (bte->stub == NULL) {
2934 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2939 /* generate method profiling code */
2941 PROFILE_CYCLE_START;
2943 /* store size of call code in replacement point */
2945 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2947 /* store return value */
2949 d = md->returntype.type;
2951 if (d != TYPE_VOID) {
2952 if (IS_INT_LNG_TYPE(d)) {
2953 if (IS_2_WORD_TYPE(d)) {
2954 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2955 M_LNGMOVE(REG_RESULT_PACKED, s1);
2958 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2959 M_INTMOVE(REG_RESULT, s1);
2963 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2964 M_FLTMOVE(REG_FRESULT, s1);
2966 emit_store_dst(jd, iptr, s1);
2972 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2974 /* val.a: (classinfo*) superclass */
2976 /* superclass is an interface:
2978 * OK if ((sub == NULL) ||
2979 * (sub->vftbl->interfacetablelength > super->index) &&
2980 * (sub->vftbl->interfacetable[-super->index] != NULL));
2982 * superclass is a class:
2984 * OK if ((sub == NULL) || (0
2985 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2986 * super->vftbl->diffval));
2989 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2990 /* object type cast-check */
2993 vftbl_t *supervftbl;
2996 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2997 # define LABEL_CLASS BRANCH_LABEL_2
2998 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2999 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
3000 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
3002 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3008 super = iptr->sx.s23.s3.c.cls;
3009 superindex = super->index;
3010 supervftbl = super->vftbl;
3013 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3014 CODEGEN_CRITICAL_SECTION_NEW;
3016 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3018 /* if class is not resolved, check which code to call */
3020 if (super == NULL) {
3022 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3024 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3026 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3027 iptr->sx.s23.s3.c.ref,
3030 ICONST(REG_ITMP3, ACC_INTERFACE);
3032 if (N_VALID_DSEG_DISP(disp)) {
3033 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3035 ICONST(REG_ITMP2, disp);
3036 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3038 emit_label_beq(cd, LABEL_CLASS);
3041 /* interface checkcast code */
3043 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3044 if (super == NULL) {
3045 patcher_add_patch_ref(jd,
3046 PATCHER_checkcast_instanceof_interface,
3047 iptr->sx.s23.s3.c.ref,
3051 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3054 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3055 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3056 M_ISUB_IMM(superindex, REG_ITMP3);
3057 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3060 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3061 superindex * sizeof(methodptr*))
3063 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3064 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3066 if (super == NULL) {
3067 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3071 /* class checkcast code */
3073 if (super == NULL) {
3074 emit_label(cd, LABEL_CLASS);
3077 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3078 if (super == NULL) {
3079 disp = dseg_add_unique_address(cd, NULL);
3081 patcher_add_patch_ref(jd,
3082 PATCHER_resolve_classref_to_vftbl,
3083 iptr->sx.s23.s3.c.ref,
3087 disp = dseg_add_address(cd, supervftbl);
3089 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3093 CODEGEN_CRITICAL_SECTION_START;
3095 /* REG_ITMP3 := baseval(s1) */
3096 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3097 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3099 /* REG_ITMP2 := baseval(class) */
3100 M_ALD_DSEG(REG_ITMP2, disp);
3101 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3103 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3104 M_ISUB(REG_ITMP2, REG_ITMP3);
3106 /* REG_ITMP2 := diffval(class) */
3107 M_ALD_DSEG(REG_ITMP2, disp);
3108 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3110 CODEGEN_CRITICAL_SECTION_END;
3112 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3114 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3115 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3116 /* Branch if greater then */
3118 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3119 M_ALD_DSEG(REG_ITMP3, disp);
3121 CODEGEN_CRITICAL_SECTION_START;
3123 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3124 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3125 M_ISUB(REG_ITMP3, REG_ITMP2);
3126 M_ALD_DSEG(REG_ITMP3, disp);
3127 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3129 CODEGEN_CRITICAL_SECTION_END;
3131 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3132 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3133 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3134 /* Branch if greater then */
3136 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3139 if (super == NULL) {
3140 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3141 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3142 } else if (super->flags & ACC_INTERFACE) {
3143 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3145 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3148 d = codegen_reg_of_dst(jd, iptr, s1);
3150 # undef LABEL_EXIT_CHECK_NULL
3152 # undef LABEL_EXIT_INTERFACE_NULL
3153 # undef LABEL_EXIT_INTERFACE_DONE
3154 # undef LABEL_EXIT_CLASS_NULL
3157 /* array type cast-check */
3159 s1 = emit_load_s1(jd, iptr, REG_A0);
3160 M_INTMOVE(s1, REG_A0);
3162 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3163 disp = dseg_add_unique_address(cd, NULL);
3165 patcher_add_patch_ref(jd,
3166 PATCHER_resolve_classref_to_classinfo,
3167 iptr->sx.s23.s3.c.ref,
3171 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3173 M_ALD_DSEG(REG_A1, disp);
3174 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3175 M_ALD_DSEG(REG_ITMP1, disp);
3176 M_ASUB_IMM(96, REG_SP);
3177 M_JSR(REG_RA, REG_ITMP1);
3178 M_AADD_IMM(96, REG_SP);
3180 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3181 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3183 d = codegen_reg_of_dst(jd, iptr, s1);
3187 emit_store_dst(jd, iptr, d);
3190 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3191 /* val.a: (classinfo*) superclass */
3193 /* superclass is an interface:
3195 * return (sub != NULL) &&
3196 * (sub->vftbl->interfacetablelength > super->index) &&
3197 * (sub->vftbl->interfacetable[-super->index] != NULL);
3199 * superclass is a class:
3201 * return ((sub != NULL) && (0
3202 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3203 * super->vftbl->diffvall));
3205 * If superclass is unresolved, we include both code snippets
3206 * above, a patcher resolves the class' flags and we select
3207 * the right code at runtime.
3212 vftbl_t *supervftbl;
3215 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3221 super = iptr->sx.s23.s3.c.cls;
3222 superindex = super->index;
3223 supervftbl = super->vftbl;
3226 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3227 # define LABEL_CLASS BRANCH_LABEL_2
3228 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3229 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3230 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3231 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3233 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3234 CODEGEN_CRITICAL_SECTION_NEW;
3236 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3237 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3239 M_MOV(s1, REG_ITMP1);
3243 /* if class is not resolved, check which code to call */
3245 if (super == NULL) {
3249 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3251 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3253 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3254 iptr->sx.s23.s3.c.ref, disp);
3256 ICONST(REG_ITMP3, ACC_INTERFACE);
3258 if (N_VALID_DSEG_DISP(disp)) {
3259 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3261 ICONST(REG_ITMP2, disp);
3262 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3265 emit_label_beq(cd, LABEL_CLASS);
3268 /* interface instanceof code */
3270 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3271 if (super == NULL) {
3272 /* If d == REG_ITMP2, then it's destroyed in check
3277 patcher_add_patch_ref(jd,
3278 PATCHER_checkcast_instanceof_interface,
3279 iptr->sx.s23.s3.c.ref, 0);
3284 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3287 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3288 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3289 M_ISUB_IMM(superindex, REG_ITMP3);
3291 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3295 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3296 superindex * sizeof(methodptr*))
3298 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3300 /* d := (REG_ITMP1 != 0) */
3302 N_LTR(d, REG_ITMP1);
3303 M_BEQ(SZ_BRC + SZ_LHI);
3306 if (super == NULL) {
3307 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3311 /* class instanceof code */
3313 if (super == NULL) {
3314 emit_label(cd, LABEL_CLASS);
3317 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3318 if (super == NULL) {
3319 disp = dseg_add_unique_address(cd, NULL);
3321 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3322 iptr->sx.s23.s3.c.ref,
3326 disp = dseg_add_address(cd, supervftbl);
3331 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3334 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3335 M_ALD_DSEG(REG_ITMP2, disp);
3337 CODEGEN_CRITICAL_SECTION_START;
3339 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3340 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3341 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3343 CODEGEN_CRITICAL_SECTION_END;
3345 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3347 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3349 M_BGT(SZ_BRC + SZ_LHI);
3353 if (super == NULL) {
3354 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3355 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3356 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3357 } else if (super->flags & ACC_INTERFACE) {
3358 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3359 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3361 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3364 # undef LABEL_EXIT_CHECK_NULL
3366 # undef LABEL_EXIT_INTERFACE_NULL
3367 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3368 # undef LABEL_EXIT_INTERFACE_DONE
3369 # undef LABEL_EXIT_CLASS_NULL
3371 emit_store_dst(jd, iptr, d);
3377 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3379 /* check for negative sizes and copy sizes to stack if necessary */
3381 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3384 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3386 /* copy SAVEDVAR sizes to stack */
3387 var = VAR(iptr->sx.s23.s2.args[s1]);
3389 /* Already Preallocated? */
3390 if (!(var->flags & PREALLOC)) {
3391 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3392 M_IST(s2, REG_SP, s1 * 4);
3396 /* is a patcher function set? */
3398 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3399 disp = dseg_add_unique_address(cd, 0);
3401 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3402 iptr->sx.s23.s3.c.ref,
3406 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3408 /* a0 = dimension count */
3410 ICONST(REG_A0, iptr->s1.argcount);
3412 /* a1 = classinfo */
3414 M_ALD_DSEG(REG_A1, disp);
3416 /* a2 = pointer to dimensions = stack pointer */
3418 M_MOV(REG_SP, REG_A2);
3420 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3421 M_ALD_DSEG(REG_ITMP1, disp);
3422 M_ASUB_IMM(96, REG_SP);
3423 M_JSR(REG_RA, REG_ITMP1);
3424 M_AADD_IMM(96, REG_SP);
3426 /* check for exception before result assignment */
3428 emit_exception_check(cd, iptr);
3430 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3431 M_INTMOVE(REG_RESULT, s1);
3432 emit_store_dst(jd, iptr, s1);
3437 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3441 } /* for instruction */
3443 MCODECHECK(512); /* XXX require a lower number? */
3445 /* At the end of a basic block we may have to append some nops,
3446 because the patcher stub calling code might be longer than the
3447 actual instruction. So codepatching does not change the
3448 following block unintentionally. */
3450 if (cd->mcodeptr < cd->lastmcodeptr) {
3451 while (cd->mcodeptr < cd->lastmcodeptr) {
3456 } /* if (bptr -> flags >= BBREACHED) */
3457 } /* for basic block */
3459 dseg_createlinenumbertable(cd);
3461 /* generate stubs */
3463 emit_patcher_traps(jd);
3465 /* everything's ok */
3471 /* codegen_emit_stub_compiler **************************************************
3473 Emits a stub routine which calls the compiler.
3475 *******************************************************************************/
3477 void codegen_emit_stub_compiler(jitdata *jd)
3482 /* get required compiler data */
3487 /* code for the stub */
3489 /* don't touch ITMP2 as it cointains the return address */
3491 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3493 /* REG_METHODPTR (REG_ITMP1) already used */
3494 M_ILD_DSEG(REG_ITMP3, -2 * SIZEOF_VOID_P); /* methodinfo */
3495 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3500 /* codegen_emit_stub_native ****************************************************
3502 Emits a stub routine which calls a native method.
3504 *******************************************************************************/
3507 arguments on stack \
3508 -------------------------------------------------| <- SP on nativestub entry
3510 callee saved int regs (none) |
3511 callee saved float regs (none) | stack frame like in cacao
3512 local variable slots (none) |
3513 arguments for calling methods (none) /
3514 ------------------------------------------------------------------ <- datasp
3519 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3520 0 - 96 register save area for callee /
3521 -------------------------------------------------------- <- SP native method
3523 SP after method entry
3526 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3532 s4 i, j; /* count variables */
3537 /* get required compiler data */
3543 /* set some variables */
3547 /* calculate stackframe size */
3549 cd->stackframesize =
3550 1 + /* return address */
3551 sizeof(stackframeinfo_t) / 8 +
3552 sizeof(localref_table) / 8 +
3555 (96 / 8); /* linkage area */
3557 /* keep stack 8-byte aligned */
3559 /*ALIGN_2(cd->stackframesize);*/
3561 /* create method header */
3563 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3564 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3565 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3566 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3567 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3568 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3569 (void) dseg_addlinenumbertablesize(cd);
3570 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3574 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3575 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3577 /* store return address */
3579 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3581 /* get function address (this must happen before the stackframeinfo) */
3583 funcdisp = dseg_add_functionptr(cd, f);
3586 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
3588 #if defined(ENABLE_GC_CACAO)
3589 /* Save callee saved integer registers in stackframeinfo (GC may
3590 need to recover them during a collection). */
3592 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3593 OFFSET(stackframeinfo_t, intregs);
3595 for (i = 0; i < INT_SAV_CNT; i++)
3596 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3599 /* save integer and float argument registers */
3601 for (i = 0; i < md->paramcount; i++) {
3602 if (!md->params[i].inmemory) {
3603 s1 = md->params[i].regoff;
3605 switch (md->paramtypes[i].type) {
3608 M_IST(s1, REG_SP, 96 + i * 8);
3611 M_LST(s1, REG_SP, 96 + i * 8);
3615 M_DST(s1, REG_SP, 96 + i * 8);
3621 /* create native stack info */
3623 M_MOV(REG_SP, REG_A0);
3624 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3625 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3626 M_ALD_DSEG(REG_ITMP2, disp);
3629 /* remember class argument */
3631 if (m->flags & ACC_STATIC)
3632 M_MOV(REG_RESULT, REG_ITMP3);
3634 /* restore integer and float argument registers */
3636 for (i = 0; i < md->paramcount; i++) {
3637 if (!md->params[i].inmemory) {
3638 s1 = md->params[i].regoff;
3640 switch (md->paramtypes[i].type) {
3643 M_ILD(s1, REG_SP, 96 + i * 8);
3646 M_LLD(s1, REG_SP, 96 + i * 8);
3650 M_DLD(s1, REG_SP, 96 + i * 8);
3656 /* copy or spill arguments to new locations */
3658 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3659 t = md->paramtypes[i].type;
3661 if (IS_INT_LNG_TYPE(t)) {
3662 if (!md->params[i].inmemory) {
3663 s1 = md->params[i].regoff;
3664 s2 = nmd->params[j].regoff;
3666 if (!nmd->params[j].inmemory) {
3667 if (IS_2_WORD_TYPE(t))
3673 if (IS_2_WORD_TYPE(t))
3674 M_LST(s1, REG_SP, s2);
3676 M_IST(s1, REG_SP, s2);
3680 s1 = md->params[i].regoff + cd->stackframesize * 8;
3681 s2 = nmd->params[j].regoff;
3683 if (IS_2_WORD_TYPE(t)) {
3684 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3686 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3691 /* We only copy spilled float arguments, as the float
3692 argument registers keep unchanged. */
3694 if (md->params[i].inmemory) {
3695 s1 = md->params[i].regoff + cd->stackframesize * 8;
3696 s2 = nmd->params[j].regoff;
3698 if (IS_2_WORD_TYPE(t)) {
3699 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3701 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3707 /* Handle native Java methods. */
3709 if (m->flags & ACC_NATIVE) {
3710 /* put class into second argument register */
3712 if (m->flags & ACC_STATIC)
3713 M_MOV(REG_ITMP3, REG_A1);
3715 /* put env into first argument register */
3717 disp = dseg_add_address(cd, _Jv_env);
3718 M_ALD_DSEG(REG_A0, disp);
3721 /* generate the actual native call */
3723 M_ALD_DSEG(REG_ITMP2, funcdisp);
3726 /* save return value */
3728 switch (md->returntype.type) {
3731 M_IST(REG_RESULT, REG_SP, 96);
3734 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3738 M_DST(REG_FRESULT, REG_SP, 96);
3744 /* remove native stackframe info */
3746 M_MOV(REG_SP, REG_A0);
3747 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3748 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3749 M_ALD_DSEG(REG_ITMP1, disp);
3752 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3754 /* restore return value */
3756 switch (md->returntype.type) {
3759 M_ILD(REG_RESULT, REG_SP, 96);
3762 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3766 M_DLD(REG_FRESULT, REG_SP, 96);
3772 #if defined(ENABLE_GC_CACAO)
3773 /* Restore callee saved integer registers from stackframeinfo (GC
3774 might have modified them during a collection). */
3776 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3777 OFFSET(stackframeinfo_t, intregs);
3779 for (i = 0; i < INT_SAV_CNT; i++)
3780 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3783 /* load return address */
3785 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3787 /* remove stackframe */
3789 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3791 /* check for exception */
3793 M_TEST(REG_ITMP3_XPTR);
3794 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3798 /* handle exception */
3800 M_MOV(REG_RA, REG_ITMP1_XPC);
3802 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3803 M_ALD_DSEG(REG_ITMP2, disp);
3804 M_JMP(RN, REG_ITMP2);
3806 /* generate patcher traps */
3808 emit_patcher_traps(jd);
3812 * These are local overrides for various environment variables in Emacs.
3813 * Please do not remove this and leave it at the end of the file, where
3814 * Emacs will automagically detect them.
3815 * ---------------------------------------------------------------------
3818 * indent-tabs-mode: t
3822 * vim:noexpandtab:sw=4:ts=4: