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
25 $Id: codegen.c 8318 2007-08-16 10:05:34Z michi $
36 #include "native/jni.h"
37 #include "native/localref.h"
38 #include "native/native.h"
40 #include "mm/memory.h"
42 #if defined(ENABLE_THREADS)
43 # include "threads/lock-common.h"
44 # include "threads/native/lock.h"
47 #include "vmcore/loader.h"
48 #include "vmcore/options.h"
49 #include "vmcore/statistics.h"
50 #include "vm/builtin.h"
51 #include "vm/exceptions.h"
52 #include "vm/global.h"
53 #include "vm/jit/abi.h"
54 #if defined(ENABLE_LSRA)
55 # include "vm/jit/allocator/lsra.h"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/codegen-common.h"
59 #include "vm/jit/dseg.h"
60 #include "vm/jit/emit-common.h"
61 #include "vm/jit/jit.h"
62 #include "vm/jit/methodheader.h"
63 #include "vm/jit/parse.h"
64 #include "vm/jit/patcher-common.h"
65 #include "vm/jit/reg.h"
66 #include "vm/jit/replace.h"
67 #include "vm/jit/s390/arch.h"
68 #include "vm/jit/s390/codegen.h"
69 #include "vm/jit/s390/emit.h"
70 #include "vm/jit/s390/md-abi.h"
71 #include "vm/jit/stacktrace.h"
73 #include "vm/stringlocal.h"
76 /* DO__LOG generates a call to do__log. No registers are destroyed,
77 * so you may use it anywhere. regs is an array containing all general
81 static void do__log(u4 *regs) {
82 /* insert stuff here */
86 N_AHI(REG_SP, -200); \
87 N_STM(R0, R15, 96, REG_SP); \
88 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
89 N_LA(R2, 96, RN, REG_SP); \
91 N_LM(R0, R15, 96, REG_SP); \
94 #define SUPPORT_HERCULES 1
96 /* codegen *********************************************************************
98 Generates machine code.
100 *******************************************************************************/
104 Layout of stackframe:
107 ===============================================================================
108 return_address (stackframesize - 1) * 8
109 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
111 saved_int_reg[rd->savintreguse]
112 saved_flt_reg[FLT_SAV_CNT - 1]
114 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
116 return_value_tmp (rd->memuse + 1) * 8
117 monitorenter_argument (rd->memuse) * 8
119 local[rd->memuse - 1] (rd->memuse - 1) * 8
127 bool codegen_emit(jitdata *jd)
133 s4 len, s1, s2, s3, d, dd, disp;
136 varinfo *var, *var1, *var2, *dst;
140 constant_classref *cr;
141 unresolved_class *uc;
142 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
143 unresolved_method *um;
144 builtintable_entry *bte;
147 unresolved_field *uf;
150 rplpoint *replacementpoint;
154 /* get required compiler data */
161 /* prevent compiler warnings */
174 /* space to save used callee saved registers */
176 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
177 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
179 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
182 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
185 #if defined(ENABLE_THREADS)
186 /* Space to save argument of monitor_enter and Return Values to
187 survive monitor_exit. The stack position for the argument can
188 not be shared with place to save the return register
189 since both values reside in R2. */
191 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
192 /* 1 slot space to save argument of monitor_enter */
193 /* 1 slot to temporary store return value before monitor_exit */
194 cd->stackframesize += 2;
198 /* Keep stack of non-leaf functions 16-byte aligned for calls into
199 native code e.g. libc or jni (alignment problems with
202 if (!jd->isleafmethod || opt_verbosecall )
203 /* TODO really 16 bytes ? */
204 cd->stackframesize = (cd->stackframesize + 2) & ~2;
206 /* create method header */
208 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
209 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
211 #if defined(ENABLE_THREADS)
212 /* IsSync contains the offset relative to the stack pointer for the
213 argument of monitor_exit used in the exception handler. Since the
214 offset could be zero and give a wrong meaning of the flag it is
218 if (checksync && (m->flags & ACC_SYNCHRONIZED))
219 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync */
222 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
224 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
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 /* generate method profiling code */
247 #if defined(ENABLE_PROFILING)
248 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
249 /* count frequency */
250 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
251 ICONST(REG_ITMP2, 1);
252 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
253 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
259 /* create stack frame (if necessary) */
261 if (cd->stackframesize)
262 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
264 /* save used callee saved registers and return address */
266 p = cd->stackframesize;
267 p--; M_AST(REG_RA, REG_SP, p * 8);
269 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
270 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
272 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
273 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
276 /* take arguments out of register or stack frame */
280 for (p = 0, l = 0; p < md->paramcount; p++) {
281 t = md->paramtypes[p].type;
282 varindex = jd->local_map[l * 5 + t];
286 if (IS_2_WORD_TYPE(t))
289 if (varindex == UNUSED)
294 s1 = md->params[p].regoff;
296 if (IS_INT_LNG_TYPE(t)) { /* integer args */
297 if (IS_2_WORD_TYPE(t)) {
305 if (!md->params[p].inmemory) { /* register arguments */
306 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
307 if (IS_2_WORD_TYPE(t)) {
308 M_LNGMOVE(s2, var->vv.regoff);
310 M_INTMOVE(s2, var->vv.regoff);
312 } else { /* reg arg -> spilled */
313 if (IS_2_WORD_TYPE(t)) {
314 M_LST(s2, REG_SP, var->vv.regoff);
316 M_IST(s2, REG_SP, var->vv.regoff);
320 } else { /* stack arguments */
321 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
322 if (IS_2_WORD_TYPE(t)) {
323 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
325 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
327 } else { /* stack arg -> spilled */
328 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
332 } else { /* floating args */
333 if (!md->params[p].inmemory) { /* register arguments */
335 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
336 M_FLTMOVE(s2, var->vv.regoff);
338 } else { /* reg arg -> spilled */
339 if (IS_2_WORD_TYPE(t))
340 M_DST(s2, REG_SP, var->vv.regoff);
342 M_FST(s2, REG_SP, var->vv.regoff);
345 } else { /* stack arguments */
346 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
347 if (IS_2_WORD_TYPE(t))
348 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
351 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
353 } else { /* stack-arg -> spilled */
354 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
355 var->vv.regoff = cd->stackframesize * 8 + s1;
361 /* save monitorenter argument */
363 #if defined(ENABLE_THREADS)
364 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
365 /* stack offset for monitor argument */
370 if (opt_verbosecall) {
371 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
373 for (p = 0; p < INT_ARG_CNT; p++)
374 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
376 for (p = 0; p < FLT_ARG_CNT; p++)
377 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
379 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
383 /* decide which monitor enter function to call */
385 if (m->flags & ACC_STATIC) {
386 disp = dseg_add_address(cd, &m->class->object.header);
387 M_ALD_DSEG(REG_A0, disp);
391 M_BNE(SZ_BRC + SZ_ILL);
392 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
395 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
396 M_ALD_DSEG(REG_ITMP3, disp);
398 M_AST(REG_A0, REG_SP, s1 * 8);
400 M_ASUB_IMM(96, REG_SP);
402 M_AADD_IMM(96, REG_SP);
405 if (opt_verbosecall) {
406 for (p = 0; p < INT_ARG_CNT; p++)
407 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
409 for (p = 0; p < FLT_ARG_CNT; p++)
410 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
412 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
419 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
420 emit_verbosecall_enter(jd);
421 #endif /* !defined(NDEBUG) */
425 /* end of header generation */
427 /* create replacement points */
429 REPLACEMENT_POINTS_INIT(cd, jd);
431 /* walk through all basic blocks */
433 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
435 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
437 if (bptr->flags >= BBREACHED) {
439 /* branch resolving */
441 codegen_resolve_branchrefs(cd, bptr);
443 /* handle replacement points */
445 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
447 /* copy interface registers to their destination */
452 #if defined(ENABLE_PROFILING)
453 /* generate basicblock profiling code */
455 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
456 /* count frequency */
458 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
459 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
460 ICONST(REG_ITMP2, 1);
461 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
462 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
464 /* if this is an exception handler, start profiling again */
466 if (bptr->type == BBTYPE_EXH)
471 #if defined(ENABLE_LSRA)
475 src = bptr->invars[len];
476 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
477 if (bptr->type == BBTYPE_EXH) {
478 /* d = reg_of_var(rd, src, REG_ITMP1); */
479 if (!IS_INMEMORY(src->flags))
483 M_INTMOVE(REG_ITMP1, d);
484 emit_store(jd, NULL, src, d);
494 var = VAR(bptr->invars[len]);
495 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
496 if (bptr->type == BBTYPE_EXH) {
497 d = codegen_reg_of_var(0, var, REG_ITMP1);
498 M_INTMOVE(REG_ITMP1, d);
499 emit_store(jd, NULL, var, d);
503 assert((var->flags & INOUT));
506 #if defined(ENABLE_LSRA)
509 /* walk through all instructions */
514 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
515 if (iptr->line != currentline) {
516 dseg_addlinenumber(cd, iptr->line);
517 currentline = iptr->line;
520 MCODECHECK(1024); /* 1KB should be enough */
523 case ICMD_NOP: /* ... ==> ... */
524 case ICMD_POP: /* ..., value ==> ... */
525 case ICMD_POP2: /* ..., value, value ==> ... */
528 case ICMD_INLINE_START:
530 REPLACEMENT_POINT_INLINE_START(cd, iptr);
533 case ICMD_INLINE_BODY:
535 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
536 dseg_addlinenumber_inline_start(cd, iptr);
537 dseg_addlinenumber(cd, iptr->line);
540 case ICMD_INLINE_END:
542 dseg_addlinenumber_inline_end(cd, iptr);
543 dseg_addlinenumber(cd, iptr->line);
546 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
547 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
548 emit_nullpointer_check(cd, iptr, s1);
551 /* constant operations ************************************************/
553 case ICMD_ICONST: /* ... ==> ..., constant */
554 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
555 ICONST(d, iptr->sx.val.i);
556 emit_store_dst(jd, iptr, d);
559 case ICMD_LCONST: /* ... ==> ..., constant */
561 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
562 LCONST(d, iptr->sx.val.l);
563 emit_store_dst(jd, iptr, d);
566 case ICMD_FCONST: /* ... ==> ..., constant */
567 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
568 disp = dseg_add_float(cd, iptr->sx.val.f);
569 M_FLD_DSEG(d, disp, REG_ITMP1);
570 emit_store_dst(jd, iptr, d);
573 case ICMD_DCONST: /* ... ==> ..., constant */
574 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
575 disp = dseg_add_double(cd, iptr->sx.val.d);
576 M_DLD_DSEG(d, disp, REG_ITMP1);
577 emit_store_dst(jd, iptr, d);
580 case ICMD_ACONST: /* ... ==> ..., constant */
581 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
583 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
584 cr = iptr->sx.val.c.ref;
585 disp = dseg_add_unique_address(cd, cr);
587 /* PROFILE_CYCLE_STOP; */
589 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
592 /* PROFILE_CYCLE_START; */
596 if (iptr->sx.val.anyptr == 0) {
599 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
603 emit_store_dst(jd, iptr, d);
607 /* load/store/copy/move operations ************************************/
609 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
610 case ICMD_ALOAD: /* s1 = local variable */
614 case ICMD_ISTORE: /* ..., value ==> ... */
625 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
629 /* integer operations *************************************************/
631 case ICMD_INEG: /* ..., value ==> ..., - value */
633 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
634 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
636 emit_store_dst(jd, iptr, d);
640 case ICMD_LNEG: /* ..., value ==> ..., - value */
642 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
643 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
644 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
645 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
646 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
647 N_AHI(GET_HIGH_REG(d), -1);
648 emit_store_dst(jd, iptr, d);
651 case ICMD_I2L: /* ..., value ==> ..., value */
653 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
654 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
656 M_INTMOVE(s1, GET_HIGH_REG(d));
657 ICONST(GET_LOW_REG(d), 0);
658 M_SRDA_IMM(32, GET_HIGH_REG(d));
660 emit_copy_dst(jd, iptr, d);
661 emit_store_dst(jd, iptr, d);
662 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
666 case ICMD_L2I: /* ..., value ==> ..., value */
667 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
668 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
669 M_INTMOVE(GET_LOW_REG(s1), d);
670 emit_store_dst(jd, iptr, d);
673 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
674 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
675 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
679 emit_store_dst(jd, iptr, d);
682 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
683 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
684 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
688 emit_store_dst(jd, iptr, d);
691 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
693 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
694 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
698 emit_store_dst(jd, iptr, d);
701 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
703 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
704 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
705 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
712 emit_store_dst(jd, iptr, d);
717 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
718 /* sx.val.i = constant */
719 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
720 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
723 if (N_VALID_IMM(iptr->sx.val.i)) {
724 M_IADD_IMM(iptr->sx.val.i, d);
726 ICONST(REG_ITMP2, iptr->sx.val.i);
727 M_IADD(REG_ITMP2, d);
729 emit_store_dst(jd, iptr, d);
732 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
734 /* M, (r, q) -> (r, q) */
736 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
738 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
739 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
740 dd = GET_HIGH_REG(d);
749 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
750 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
760 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
761 N_AHI(GET_HIGH_REG(d), 1);
763 emit_store_dst(jd, iptr, d);
766 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
767 /* sx.val.l = constant */
769 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
770 dd = GET_HIGH_REG(d);
772 s1 = emit_load_s1_high(jd, iptr, dd);
773 s3 = iptr->sx.val.l >> 32;
777 if (N_VALID_IMM(s3)) {
780 ICONST(REG_ITMP3, s3);
781 M_IADD(REG_ITMP3, dd);
785 s1 = emit_load_s1_low(jd, iptr, dd);
786 s3 = iptr->sx.val.l & 0xffffffff;
787 ICONST(REG_ITMP3, s3);
790 N_ALR(dd, REG_ITMP3);
792 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
793 N_AHI(GET_HIGH_REG(d), 1);
795 emit_store_dst(jd, iptr, d);
798 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
800 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
801 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
802 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
804 M_INTMOVE(s1, REG_ITMP1);
805 M_ISUB(s2, REG_ITMP1);
806 M_INTMOVE(REG_ITMP1, d);
811 emit_store_dst(jd, iptr, d);
815 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
816 /* sx.val.i = constant */
818 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
819 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
822 if (N_VALID_IMM(-iptr->sx.val.i)) {
823 M_ISUB_IMM(iptr->sx.val.i, d);
825 ICONST(REG_ITMP2, iptr->sx.val.i);
826 M_ISUB(REG_ITMP2, d);
828 emit_store_dst(jd, iptr, d);
832 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
834 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
836 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
837 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
838 dd = GET_HIGH_REG(d);
841 M_INTMOVE(s2, REG_ITMP3);
848 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
849 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
853 M_INTMOVE(s2, REG_ITMP3);
860 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
861 N_AHI(GET_HIGH_REG(d), -1);
863 emit_store_dst(jd, iptr, d);
866 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
867 /* sx.val.l = constant */
869 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
871 dd = GET_HIGH_REG(d);
872 s1 = emit_load_s1_high(jd, iptr, dd);
873 s3 = iptr->sx.val.l >> 32;
877 if (N_VALID_IMM(-s3)) {
880 ICONST(REG_ITMP3, s3);
881 M_ISUB(REG_ITMP3, dd);
885 s1 = emit_load_s1_low(jd, iptr, dd);
886 s3 = iptr->sx.val.l & 0xffffffff;
887 ICONST(REG_ITMP3, s3);
890 N_SLR(dd, REG_ITMP3);
892 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
893 N_AHI(GET_HIGH_REG(d), -1);
895 emit_store_dst(jd, iptr, d);
898 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
900 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
901 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
902 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
909 emit_store_dst(jd, iptr, d);
913 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
914 /* sx.val.i = constant */
915 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
916 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
918 if (iptr->sx.val.i == 2) {
920 } else if (N_VALID_IMM(iptr->sx.val.i)) {
921 M_IMUL_IMM(iptr->sx.val.i, d);
923 disp = dseg_add_s4(cd, iptr->sx.val.i);
924 M_ILD_DSEG(REG_ITMP2, disp);
925 M_IMUL(REG_ITMP2, d);
927 emit_store_dst(jd, iptr, d);
930 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
931 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
933 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
934 emit_arithmetic_check(cd, iptr, s2);
936 /* For this operation we need a register pair.
937 * We will use r0 and itmp1 and will backup r0.
940 M_INTMOVE(R0, REG_ITMP3);
942 /* We won't check for division by 0, we catch a SIGFPE instead
943 * Special case 0x80000000 / 0xffffffff handled by signal handler too.
946 s1 = emit_load_s1(jd, iptr, R0);
955 d = codegen_reg_of_dst(jd, iptr, R0);
959 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
960 M_INTMOVE(REG_ITMP1, d);
964 emit_store_dst(jd, iptr, d);
966 /* If destionation of operation was not register R0,
970 if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
971 M_INTMOVE(REG_ITMP3, R0);
976 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
977 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
979 bte = iptr->sx.s23.s3.bte;
982 /* test s2 for zero */
984 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
985 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
986 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
987 emit_arithmetic_check(cd, iptr, REG_ITMP3);
991 disp = dseg_add_functionptr(cd, bte->fp);
995 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
997 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
998 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
1002 M_ASUB_IMM(96, REG_SP);
1003 M_ALD_DSEG(REG_ITMP3, disp);
1004 M_JSR(REG_RA, REG_ITMP3);
1005 M_AADD_IMM(96, REG_SP);
1009 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1010 M_LNGMOVE(REG_RESULT_PACKED, d);
1011 emit_store_dst(jd, iptr, d);
1015 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1016 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1017 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1019 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1020 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1021 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1023 /* Use only 5 bits of sencond operand. */
1025 M_INTMOVE(s2, REG_ITMP2);
1027 ICONST(REG_ITMP3, 0x1F);
1028 M_IAND(REG_ITMP3, s2);
1032 switch (iptr->opc) {
1045 emit_store_dst(jd, iptr, d);
1048 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1049 /* sx.val.i = constant */
1053 assert(iptr->sx.val.i <= 32);
1055 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1056 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1063 s3 = (1 << iptr->sx.val.i) - 1;
1065 if (N_VALID_IMM(s3)) {
1068 ICONST(REG_ITMP1, -1);
1069 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1070 M_IADD(REG_ITMP1, d);
1073 N_BRC_BACK_PATCH(ref);
1075 M_SRA_IMM(iptr->sx.val.i, d);
1077 emit_store_dst(jd, iptr, d);
1082 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1083 /* sx.val.i = constant */
1085 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1086 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1089 M_MOV(s1, REG_ITMP1);
1093 ICONST(REG_ITMP3, iptr->sx.val.i);
1096 M_IAND(REG_ITMP3, d);
1099 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1105 emit_store_dst(jd, iptr, d);
1109 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1110 /* sx.val.i = constant */
1111 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1112 /* sx.val.i = constant */
1113 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1114 /* sx.val.i = constant */
1115 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1116 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1120 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1122 switch (iptr->opc) {
1123 case ICMD_ISHLCONST:
1126 case ICMD_ISHRCONST:
1129 case ICMD_IUSHRCONST:
1136 emit_store_dst(jd, iptr, d);
1139 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1141 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1143 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1145 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1147 /* Use only 6 bits of second operand */
1149 M_INTMOVE(s2, REG_ITMP3);
1151 ICONST(REG_ITMP2, 0x3F);
1152 M_IAND(REG_ITMP2, s2);
1154 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1156 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1157 M_INTMOVE(s2, REG_ITMP3);
1161 s1 = emit_load_s1(jd, iptr, d);
1165 switch (iptr->opc) {
1167 M_SLDL(s2, GET_HIGH_REG(d));
1170 M_SRDA(s2, GET_HIGH_REG(d));
1173 M_SRDL(s2, GET_HIGH_REG(d));
1179 emit_copy_dst(jd, iptr, d);
1180 emit_store_dst(jd, iptr, d);
1181 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
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 = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1194 s1 = emit_load_s1(jd, iptr, d);
1198 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1200 switch (iptr->opc) {
1201 case ICMD_LSHLCONST:
1202 N_SLDL(GET_HIGH_REG(d), disp, RN);
1204 case ICMD_LSHRCONST:
1205 N_SRDA(GET_HIGH_REG(d), disp, RN);
1207 case ICMD_LUSHRCONST:
1208 N_SRDL(GET_HIGH_REG(d), disp, RN);
1211 N_SLDL(GET_HIGH_REG(d), disp, RN);
1217 emit_copy_dst(jd, iptr, d);
1218 emit_store_dst(jd, iptr, d);
1219 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1223 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1225 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1226 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1227 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1234 emit_store_dst(jd, iptr, d);
1238 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1240 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1241 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1242 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1249 emit_store_dst(jd, iptr, d);
1253 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1255 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1256 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1257 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1264 emit_store_dst(jd, iptr, d);
1270 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1271 /* sx.val.i = constant */
1272 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1273 /* sx.val.i = constant */
1274 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1275 /* sx.val.i = constant */
1277 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1278 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1281 ICONST(REG_ITMP2, iptr->sx.val.i);
1283 switch (iptr->opc) {
1284 case ICMD_IANDCONST:
1285 M_IAND(REG_ITMP2, d);
1287 case ICMD_IXORCONST:
1288 M_IXOR(REG_ITMP2, d);
1291 M_IOR(REG_ITMP2, d);
1297 emit_store_dst(jd, iptr, d);
1301 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1302 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1303 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1305 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1307 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1308 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1309 dd = GET_LOW_REG(d);
1311 switch (iptr->opc) {
1340 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1341 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1342 dd = GET_HIGH_REG(d);
1344 switch (iptr->opc) {
1373 emit_store_dst(jd, iptr, d);
1376 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1377 /* sx.val.l = constant */
1378 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1379 /* sx.val.l = constant */
1380 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1381 /* sx.val.l = constant */
1383 /* TODO should use memory operand to access data segment, not load */
1385 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1387 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1388 s3 = iptr->sx.val.l & 0xffffffff;
1390 M_INTMOVE(s1, GET_LOW_REG(d));
1392 ICONST(REG_ITMP3, s3);
1394 switch (iptr->opc) {
1395 case ICMD_LANDCONST:
1396 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1398 case ICMD_LXORCONST:
1399 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1402 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1408 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1409 s3 = iptr->sx.val.l >> 32;
1411 M_INTMOVE(s1, GET_HIGH_REG(d));
1413 ICONST(REG_ITMP3, s3);
1415 switch (iptr->opc) {
1416 case ICMD_LANDCONST:
1417 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1419 case ICMD_LXORCONST:
1420 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1423 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1429 emit_store_dst(jd, iptr, d);
1433 /* floating operations ************************************************/
1435 case ICMD_FNEG: /* ..., value ==> ..., - value */
1436 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1437 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1439 emit_store_dst(jd, iptr, d);
1442 case ICMD_DNEG: /* ..., value ==> ..., - value */
1443 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1444 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1446 emit_store_dst(jd, iptr, d);
1449 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1450 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1451 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1452 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1459 emit_store_dst(jd, iptr, d);
1462 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1463 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1464 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1465 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1472 emit_store_dst(jd, iptr, d);
1475 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1476 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1477 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1478 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1482 emit_store_dst(jd, iptr, d);
1485 case ICMD_DSUB: /* ..., 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_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1496 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1497 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1498 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1505 emit_store_dst(jd, iptr, d);
1508 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1509 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1510 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1511 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1518 emit_store_dst(jd, iptr, d);
1521 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1522 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1523 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1524 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1528 emit_store_dst(jd, iptr, d);
1531 case ICMD_DDIV: /* ..., 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_I2F: /* ..., value ==> ..., (float) value */
1542 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1543 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1545 emit_store_dst(jd, iptr, d);
1548 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1549 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1550 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1552 emit_store_dst(jd, iptr, d);
1555 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1559 #ifdef SUPPORT_HERCULES
1563 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1564 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1568 switch (iptr->opc) {
1577 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1578 N_LHI(d, 0); /* Load 0 */
1579 ref1 = cd->mcodeptr;
1580 N_BRC(DD_ANY, 0); /* Exit */
1584 switch (iptr->opc) {
1593 #ifdef SUPPORT_HERCULES
1594 /* Hercules does the conversion using a plain C conversion.
1595 * According to manual, real hardware should *NOT* require this.
1597 * Corner case: Positive float leads to INT_MIN (overflow).
1600 switch (iptr->opc) {
1609 ref2 = cd->mcodeptr;
1610 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1614 ref3 = cd->mcodeptr;
1615 M_BGE(0); /* If integer result is negative, continue */
1617 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1618 M_ILD_DSEG(d, disp);
1620 N_BRC_BACK_PATCH(ref1);
1621 #ifdef SUPPORT_HERCULES
1622 N_BRC_BACK_PATCH(ref2);
1623 N_BRC_BACK_PATCH(ref3);
1625 emit_store_dst(jd, iptr, d);
1629 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1632 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1633 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1634 #ifdef SUPPORT_HERCULES
1637 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1638 disp = dseg_add_double(cd, 0.0 / 0.0);
1639 M_DLD_DSEG(d, disp, REG_ITMP1);
1640 emit_label_br(cd, BRANCH_LABEL_1);
1641 N_BRC_BACK_PATCH(ref);
1644 #ifdef SUPPORT_HERCULES
1645 emit_label(cd, BRANCH_LABEL_1);
1647 emit_store_dst(jd, iptr, d);
1651 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1652 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1653 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1655 emit_store_dst(jd, iptr, d);
1658 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1659 /* == => 0, < => 1, > => -1 */
1663 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1664 /* == => 0, < => 1, > => -1 */
1667 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1668 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1669 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1671 switch (iptr->opc) {
1683 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1684 SZ_BRC + SZ_BRC + SZ_BRC
1687 N_BRC( /* load -1 */
1688 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1689 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1694 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1697 N_LHI(d, 1); /* GT */
1698 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1699 N_LHI(d, -1); /* LT */
1700 M_BR(SZ_BRC + SZ_LHI);
1701 N_LHI(d, 0); /* EQ */
1703 emit_store_dst(jd, iptr, d);
1708 /* memory operations **************************************************/
1710 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1712 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1713 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1715 /* implicit null-pointer check */
1716 M_ILD(d, s1, OFFSET(java_array_t, size));
1717 emit_store_dst(jd, iptr, d);
1721 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1722 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1723 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1724 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1726 /* implicit null-pointer check */
1727 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1729 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1734 emit_store_dst(jd, iptr, d);
1737 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1739 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1740 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1741 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1743 /* implicit null-pointer check */
1744 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1746 M_INTMOVE(s2, REG_ITMP2);
1747 M_SLL_IMM(1, REG_ITMP2);
1749 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1751 /* N_LH does sign extends, undo ! */
1756 emit_store_dst(jd, iptr, d);
1759 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1760 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1761 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1762 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1764 /* implicit null-pointer check */
1765 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1767 M_INTMOVE(s2, REG_ITMP2);
1768 M_SLL_IMM(1, REG_ITMP2);
1770 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1771 emit_store_dst(jd, iptr, d);
1774 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1775 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1776 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1777 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1779 /* implicit null-pointer check */
1780 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1782 M_INTMOVE(s2, REG_ITMP2);
1783 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1784 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1785 emit_store_dst(jd, iptr, d);
1788 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1790 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1791 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1793 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1795 /* implicit null-pointer check */
1796 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1798 M_INTMOVE(s2, REG_ITMP2);
1799 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1801 /* We need to preserve the array address after the first load */
1803 if (GET_HIGH_REG(d) == s1) {
1804 M_INTMOVE(s1, REG_ITMP3);
1808 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1809 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1810 emit_store_dst(jd, iptr, d);
1814 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1816 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1817 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1818 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1820 /* implicit null-pointer check */
1821 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1823 M_INTMOVE(s2, REG_ITMP2);
1824 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1826 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1828 emit_store_dst(jd, iptr, d);
1831 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1832 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1833 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1834 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1836 /* implicit null-pointer check */
1837 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1839 M_INTMOVE(s2, REG_ITMP2);
1840 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1842 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1844 emit_store_dst(jd, iptr, d);
1847 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1848 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1849 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1850 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1852 /* implicit null-pointer check */
1853 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1855 M_INTMOVE(s2, REG_ITMP2);
1856 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1857 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1858 emit_store_dst(jd, iptr, d);
1861 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1862 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1863 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1864 /* implicit null-pointer check */
1865 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1866 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1868 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1871 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1873 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1874 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1875 /* implicit null-pointer check */
1876 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1877 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1879 M_INTMOVE(s2, REG_ITMP2);
1880 M_SLL_IMM(1, REG_ITMP2);
1882 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1886 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1887 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1888 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1889 /* implicit null-pointer check */
1890 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1891 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1893 M_INTMOVE(s2, REG_ITMP2);
1894 M_SLL_IMM(1, REG_ITMP2);
1896 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1899 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1901 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1902 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1903 /* implicit null-pointer check */
1904 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1906 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1908 M_INTMOVE(s2, REG_ITMP2);
1909 M_SLL_IMM(2, REG_ITMP2);
1911 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1914 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1916 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1917 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1918 /* implicit null-pointer check */
1919 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1921 M_INTMOVE(s2, REG_ITMP2);
1922 M_SLL_IMM(3, REG_ITMP2);
1924 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1925 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1926 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1927 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1930 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1931 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1932 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1933 /* implicit null-pointer check */
1934 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1935 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1937 M_INTMOVE(s2, REG_ITMP2);
1938 M_SLL_IMM(2, REG_ITMP2);
1940 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1943 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1944 s1 = emit_load_s1_notzero(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(3, REG_ITMP2);
1953 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1956 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1958 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1959 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1960 /* implicit null-pointer check */
1961 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1962 s3 = emit_load_s3(jd, iptr, REG_A1);
1964 M_INTMOVE(s1, REG_A0);
1965 M_INTMOVE(s3, REG_A1);
1967 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1968 M_ALD_DSEG(REG_ITMP3, disp);
1969 M_ASUB_IMM(96, REG_SP);
1970 M_JSR(REG_RA, REG_ITMP3);
1971 M_AADD_IMM(96, REG_SP);
1973 emit_exception_check(cd, iptr);
1975 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1976 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1977 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1979 M_INTMOVE(s2, REG_ITMP2);
1980 M_SLL_IMM(2, REG_ITMP2);
1981 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1984 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1985 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1990 case ICMD_GETSTATIC: /* ... ==> ..., value */
1992 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1993 uf = iptr->sx.s23.s3.uf;
1994 fieldtype = uf->fieldref->parseddesc.fd->type;
1995 disp = dseg_add_unique_address(cd, NULL);
1997 /* PROFILE_CYCLE_STOP; */
1999 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2001 /* PROFILE_CYCLE_START; */
2004 fi = iptr->sx.s23.s3.fmiref->p.field;
2005 fieldtype = fi->type;
2006 disp = dseg_add_address(cd, fi->value);
2008 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2011 patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, 0);
2013 PROFILE_CYCLE_START;
2017 M_ALD_DSEG(REG_ITMP1, disp);
2019 switch (fieldtype) {
2021 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2022 M_ILD(d, REG_ITMP1, 0);
2025 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2026 M_LLD(d, REG_ITMP1, 0);
2029 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2030 M_ALD(d, REG_ITMP1, 0);
2033 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2034 M_FLD(d, REG_ITMP1, 0);
2037 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2038 M_DLD(d, REG_ITMP1, 0);
2042 emit_store_dst(jd, iptr, d);
2046 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2048 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2049 uf = iptr->sx.s23.s3.uf;
2050 fieldtype = uf->fieldref->parseddesc.fd->type;
2051 disp = dseg_add_unique_address(cd, uf);
2053 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2056 fi = iptr->sx.s23.s3.fmiref->p.field;
2057 fieldtype = fi->type;
2058 disp = dseg_add_address(cd, fi->value);
2060 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2062 patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, disp);
2063 PROFILE_CYCLE_START;
2067 M_ALD_DSEG(REG_ITMP1, disp);
2068 switch (fieldtype) {
2070 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2071 M_IST(s1, REG_ITMP1, 0);
2074 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2075 M_LST(s1, REG_ITMP1, 0);
2078 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2079 M_AST(s1, REG_ITMP1, 0);
2082 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2083 M_FST(s1, REG_ITMP1, 0);
2086 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2087 M_DST(s1, REG_ITMP1, 0);
2092 case ICMD_GETFIELD: /* ... ==> ..., value */
2094 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2095 emit_nullpointer_check(cd, iptr, s1);
2097 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2098 uf = iptr->sx.s23.s3.uf;
2099 fieldtype = uf->fieldref->parseddesc.fd->type;
2102 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2105 fi = iptr->sx.s23.s3.fmiref->p.field;
2106 fieldtype = fi->type;
2110 switch (fieldtype) {
2112 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2116 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2117 if (GET_HIGH_REG(d) == s1) {
2118 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2119 M_ILD(GET_HIGH_REG(d), s1, disp);
2122 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2123 M_ILD(GET_HIGH_REG(d), s1, disp);
2127 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2131 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2135 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2139 emit_store_dst(jd, iptr, d);
2142 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2146 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2147 emit_nullpointer_check(cd, iptr, s1);
2149 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2150 uf = iptr->sx.s23.s3.uf;
2151 fieldtype = uf->fieldref->parseddesc.fd->type;
2155 fi = iptr->sx.s23.s3.fmiref->p.field;
2156 fieldtype = fi->type;
2160 /* We can't add a patcher ref behind this load,
2161 * because the patcher would destroy REG_ITMP3.
2163 * We pass in the disp parameter, how many bytes
2164 * to skip to the to the actual store.
2166 * XXX this relies on patcher_add_patch_ref internals
2169 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2170 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2175 if (IS_INT_LNG_TYPE(fieldtype)) {
2176 if (IS_2_WORD_TYPE(fieldtype))
2177 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2179 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2181 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2184 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2185 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2188 switch (fieldtype) {
2190 M_IST(s2, s1, disp);
2193 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2194 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2197 M_AST(s2, s1, disp);
2200 M_FST(s2, s1, disp);
2203 M_DST(s2, s1, disp);
2210 /* branch operations **************************************************/
2212 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2214 /* PROFILE_CYCLE_STOP; */
2216 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2217 M_INTMOVE(s1, REG_ITMP1_XPTR);
2219 #ifdef ENABLE_VERIFIER
2220 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2221 uc = iptr->sx.s23.s2.uc;
2223 patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
2225 #endif /* ENABLE_VERIFIER */
2227 disp = dseg_add_functionptr(cd, asm_handle_exception);
2228 M_ALD_DSEG(REG_ITMP2, disp);
2229 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2234 case ICMD_GOTO: /* ... ==> ... */
2235 case ICMD_RET: /* ... ==> ... */
2237 emit_br(cd, iptr->dst.block);
2241 case ICMD_JSR: /* ... ==> ... */
2243 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2247 case ICMD_IFNULL: /* ..., value ==> ... */
2248 case ICMD_IFNONNULL: /* ..., value ==> ... */
2249 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2251 switch (iptr->opc) {
2253 emit_beq(cd, iptr->dst.block);
2255 case ICMD_IFNONNULL:
2256 emit_bne(cd, iptr->dst.block);
2261 case ICMD_IFEQ: /* ..., value ==> ... */
2262 case ICMD_IFLT: /* ..., value ==> ... */
2263 case ICMD_IFLE: /* ..., value ==> ... */
2264 case ICMD_IFNE: /* ..., value ==> ... */
2265 case ICMD_IFGT: /* ..., value ==> ... */
2266 case ICMD_IFGE: /* ..., value ==> ... */
2268 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2270 if (N_VALID_IMM(iptr->sx.val.i))
2271 M_ICMP_IMM(s1, iptr->sx.val.i);
2273 disp = dseg_add_s4(cd, iptr->sx.val.i);
2274 if (N_VALID_DSEG_DISP(disp)) {
2275 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2277 ICONST(REG_ITMP2, disp);
2278 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2282 switch (iptr->opc) {
2284 emit_blt(cd, iptr->dst.block);
2287 emit_ble(cd, iptr->dst.block);
2290 emit_bne(cd, iptr->dst.block);
2293 emit_bgt(cd, iptr->dst.block);
2296 emit_bge(cd, iptr->dst.block);
2299 emit_beq(cd, iptr->dst.block);
2305 case ICMD_IF_LLT: /* ..., value ==> ... */
2306 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2312 /* ATTENTION: compare high words signed and low words unsigned */
2314 # define LABEL_OUT BRANCH_LABEL_1
2316 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2318 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2319 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2321 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2322 if (N_VALID_DSEG_DISP(disp)) {
2323 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2325 ICONST(REG_ITMP2, disp);
2326 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2333 emit_blt(cd, iptr->dst.block);
2334 /* EQ ... fall through */
2335 emit_label_bgt(cd, LABEL_OUT);
2339 emit_bgt(cd, iptr->dst.block);
2340 /* EQ ... fall through */
2341 emit_label_blt(cd, LABEL_OUT);
2344 /* EQ ... fall through */
2345 emit_label_bne(cd, LABEL_OUT);
2348 /* EQ ... fall through */
2349 emit_bne(cd, iptr->dst.block);
2355 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2357 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2358 if (N_VALID_DSEG_DISP(disp)) {
2359 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2361 ICONST(REG_ITMP2, disp);
2362 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2367 emit_blt(cd, iptr->dst.block);
2368 emit_label(cd, LABEL_OUT);
2371 emit_ble(cd, iptr->dst.block);
2372 emit_label(cd, LABEL_OUT);
2375 emit_bgt(cd, iptr->dst.block);
2376 emit_label(cd, LABEL_OUT);
2379 emit_bge(cd, iptr->dst.block);
2380 emit_label(cd, LABEL_OUT);
2383 emit_beq(cd, iptr->dst.block);
2384 emit_label(cd, LABEL_OUT);
2387 emit_bne(cd, iptr->dst.block);
2396 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2397 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2399 /* Compare addresses as 31 bit unsigned integers */
2401 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2402 M_LDA(REG_ITMP1, s1, 0);
2404 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2405 M_LDA(REG_ITMP2, s2, 0);
2407 M_CMP(REG_ITMP1, REG_ITMP2);
2409 switch (iptr->opc) {
2410 case ICMD_IF_ACMPEQ:
2411 emit_beq(cd, iptr->dst.block);
2413 case ICMD_IF_ACMPNE:
2414 emit_bne(cd, iptr->dst.block);
2420 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2421 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2422 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2423 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2424 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2425 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2427 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2428 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2430 switch (iptr->opc) {
2431 case ICMD_IF_ICMPEQ:
2432 emit_beq(cd, iptr->dst.block);
2434 case ICMD_IF_ICMPNE:
2435 emit_bne(cd, iptr->dst.block);
2437 case ICMD_IF_ICMPLT:
2438 emit_blt(cd, iptr->dst.block);
2440 case ICMD_IF_ICMPGT:
2441 emit_bgt(cd, iptr->dst.block);
2443 case ICMD_IF_ICMPLE:
2444 emit_ble(cd, iptr->dst.block);
2446 case ICMD_IF_ICMPGE:
2447 emit_bge(cd, iptr->dst.block);
2453 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2454 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2455 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2456 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2457 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2458 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2463 /* ATTENTION: compare high words signed and low words unsigned */
2465 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2466 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2471 case ICMD_IF_LCMPLT:
2472 case ICMD_IF_LCMPLE:
2473 emit_blt(cd, iptr->dst.block);
2474 /* EQ ... fall through */
2475 out_ref = cd->mcodeptr;
2478 case ICMD_IF_LCMPGT:
2479 case ICMD_IF_LCMPGE:
2480 emit_bgt(cd, iptr->dst.block);
2481 /* EQ ... fall through */
2482 out_ref = cd->mcodeptr;
2485 case ICMD_IF_LCMPEQ:
2486 /* EQ ... fall through */
2487 out_ref = cd->mcodeptr;
2490 case ICMD_IF_LCMPNE:
2491 /* EQ ... fall through */
2492 emit_bne(cd, iptr->dst.block);
2498 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2499 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2504 case ICMD_IF_LCMPLT:
2505 emit_blt(cd, iptr->dst.block);
2507 case ICMD_IF_LCMPLE:
2508 emit_ble(cd, iptr->dst.block);
2510 case ICMD_IF_LCMPGT:
2511 emit_bgt(cd, iptr->dst.block);
2513 case ICMD_IF_LCMPGE:
2514 emit_bge(cd, iptr->dst.block);
2516 case ICMD_IF_LCMPEQ:
2517 emit_beq(cd, iptr->dst.block);
2519 case ICMD_IF_LCMPNE:
2520 emit_bne(cd, iptr->dst.block);
2527 if (out_ref != NULL) {
2528 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2534 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2536 REPLACEMENT_POINT_RETURN(cd, iptr);
2537 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2538 M_INTMOVE(s1, REG_RESULT);
2539 goto nowperformreturn;
2541 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2543 REPLACEMENT_POINT_RETURN(cd, iptr);
2544 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2545 M_INTMOVE(s1, REG_RESULT);
2547 #ifdef ENABLE_VERIFIER
2548 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2549 unresolved_class *uc = iptr->sx.s23.s2.uc;
2552 patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
2553 PROFILE_CYCLE_START;
2555 #endif /* ENABLE_VERIFIER */
2556 goto nowperformreturn;
2558 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2560 REPLACEMENT_POINT_RETURN(cd, iptr);
2561 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2562 M_LNGMOVE(s1, REG_RESULT_PACKED);
2563 goto nowperformreturn;
2565 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2568 REPLACEMENT_POINT_RETURN(cd, iptr);
2569 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2570 M_FLTMOVE(s1, REG_FRESULT);
2571 goto nowperformreturn;
2573 case ICMD_RETURN: /* ... ==> ... */
2575 REPLACEMENT_POINT_RETURN(cd, iptr);
2581 p = cd->stackframesize;
2583 /* call trace function */
2585 #if !defined(NDEBUG)
2586 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2587 emit_verbosecall_exit(jd);
2588 #endif /* !defined(NDEBUG) */
2590 #if defined(ENABLE_THREADS)
2591 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2592 /* we need to save the proper return value */
2594 switch (iptr->opc) {
2596 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2600 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2603 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2606 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2610 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2612 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2613 M_ALD_DSEG(REG_ITMP3, disp);
2615 M_ASUB_IMM(96, REG_SP);
2617 M_AADD_IMM(96, REG_SP);
2619 /* and now restore the proper return value */
2621 switch (iptr->opc) {
2623 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2627 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2630 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2633 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2639 /* restore return address */
2641 p--; M_ALD(REG_RA, REG_SP, p * 8);
2643 /* restore saved registers */
2645 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2646 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2648 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2649 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2652 /* deallocate stack */
2654 if (cd->stackframesize)
2655 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2657 /* generate method profiling code */
2666 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2669 branch_target_t *table;
2671 table = iptr->dst.table;
2673 l = iptr->sx.s23.s2.tablelow;
2674 i = iptr->sx.s23.s3.tablehigh;
2676 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2677 M_INTMOVE(s1, REG_ITMP1);
2681 } else if (N_VALID_IMM(-l)) {
2682 M_ISUB_IMM(l, REG_ITMP1);
2684 ICONST(REG_ITMP2, l);
2685 M_ISUB(REG_ITMP2, REG_ITMP1);
2688 /* number of targets */
2694 ICONST(REG_ITMP2, i);
2695 M_ICMPU(REG_ITMP1, REG_ITMP2);
2696 emit_bge(cd, table[0].block);
2698 /* build jump table top down and use address of lowest entry */
2703 dseg_add_target(cd, table->block);
2708 /* length of dataseg after last dseg_add_target is used by load */
2710 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2711 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2712 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2713 M_JMP(RN, REG_ITMP1);
2718 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2721 lookup_target_t *lookup;
2723 lookup = iptr->dst.lookup;
2725 i = iptr->sx.s23.s2.lookupcount;
2727 MCODECHECK(8 + ((7 + 6) * i) + 5);
2728 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2731 if (N_VALID_IMM(lookup->value)) {
2732 M_ICMP_IMM(s1, lookup->value);
2734 ICONST(REG_ITMP2, lookup->value);
2735 M_ICMP(REG_ITMP2, s1);
2737 emit_beq(cd, lookup->target.block);
2741 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2746 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2748 bte = iptr->sx.s23.s3.bte;
2752 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2753 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2754 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2755 case ICMD_INVOKEINTERFACE:
2757 REPLACEMENT_POINT_INVOKE(cd, iptr);
2759 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2761 um = iptr->sx.s23.s3.um;
2762 md = um->methodref->parseddesc.md;
2765 lm = iptr->sx.s23.s3.fmiref->p.method;
2767 md = lm->parseddesc;
2771 s3 = md->paramcount;
2773 MCODECHECK((s3 << 1) + 64);
2775 /* copy arguments to registers or stack location */
2777 for (s3 = s3 - 1; s3 >= 0; s3--) {
2778 var = VAR(iptr->sx.s23.s2.args[s3]);
2780 /* Already Preallocated? */
2781 if (var->flags & PREALLOC)
2784 if (IS_INT_LNG_TYPE(var->type)) {
2785 if (!md->params[s3].inmemory) {
2786 if (IS_2_WORD_TYPE(var->type)) {
2788 GET_LOW_REG(md->params[s3].regoff),
2789 GET_HIGH_REG(md->params[s3].regoff)
2791 d = emit_load(jd, iptr, var, s1);
2795 s1 = md->params[s3].regoff;
2796 d = emit_load(jd, iptr, var, s1);
2801 if (IS_2_WORD_TYPE(var->type)) {
2802 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2803 M_LST(d, REG_SP, md->params[s3].regoff);
2806 d = emit_load(jd, iptr, var, REG_ITMP1);
2807 M_IST(d, REG_SP, md->params[s3].regoff);
2812 if (!md->params[s3].inmemory) {
2813 s1 = md->params[s3].regoff;
2814 d = emit_load(jd, iptr, var, s1);
2818 d = emit_load(jd, iptr, var, REG_FTMP1);
2819 if (IS_2_WORD_TYPE(var->type))
2820 M_DST(d, REG_SP, md->params[s3].regoff);
2822 M_FST(d, REG_SP, md->params[s3].regoff);
2827 /* generate method profiling code */
2831 switch (iptr->opc) {
2833 disp = dseg_add_functionptr(cd, bte->fp);
2835 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2836 if (N_VALID_DSEG_DISP(disp)) {
2837 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2839 N_LHI(REG_ITMP1, disp);
2840 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2844 case ICMD_INVOKESPECIAL:
2846 /* Implicit NULL pointer check */
2847 M_ILD(REG_ITMP1, REG_A0, 0);
2851 case ICMD_INVOKESTATIC:
2853 disp = dseg_add_unique_address(cd, um);
2855 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2859 disp = dseg_add_address(cd, lm->stubroutine);
2861 if (N_VALID_DSEG_DISP(disp)) {
2862 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2864 N_LHI(REG_ITMP1, disp);
2865 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2869 case ICMD_INVOKEVIRTUAL:
2870 /* TODO softnull REG_A0 */
2873 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2878 s1 = OFFSET(vftbl_t, table[0]) +
2879 sizeof(methodptr) * lm->vftblindex;
2882 /* implicit null-pointer check */
2884 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2885 M_ALD(REG_PV, REG_METHODPTR, s1);
2888 case ICMD_INVOKEINTERFACE:
2889 /* TODO softnull REG_A0 */
2891 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2892 * and -0xFFF in index register (itmp1)
2896 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2902 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2903 sizeof(methodptr*) * lm->class->index;
2905 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2908 /* Implicit null-pointer check */
2909 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2910 N_LHI(REG_ITMP1, s1);
2911 N_L(REG_METHODPTR, 0, REG_ITMP1, REG_METHODPTR);
2912 M_ALD(REG_PV, REG_METHODPTR, s2);
2916 /* generate the actual call */
2919 emit_restore_pv(cd);
2921 /* post call finalization */
2923 switch (iptr->opc) {
2925 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2926 emit_exception_check(cd, iptr); /* check for exception */
2930 /* generate method profiling code */
2932 PROFILE_CYCLE_START;
2934 /* store size of call code in replacement point */
2936 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2938 /* store return value */
2940 d = md->returntype.type;
2942 if (d != TYPE_VOID) {
2943 if (IS_INT_LNG_TYPE(d)) {
2944 if (IS_2_WORD_TYPE(d)) {
2945 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2946 M_LNGMOVE(REG_RESULT_PACKED, s1);
2949 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2950 M_INTMOVE(REG_RESULT, s1);
2954 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2955 M_FLTMOVE(REG_FRESULT, s1);
2957 emit_store_dst(jd, iptr, s1);
2963 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2965 /* val.a: (classinfo*) superclass */
2967 /* superclass is an interface:
2969 * OK if ((sub == NULL) ||
2970 * (sub->vftbl->interfacetablelength > super->index) &&
2971 * (sub->vftbl->interfacetable[-super->index] != NULL));
2973 * superclass is a class:
2975 * OK if ((sub == NULL) || (0
2976 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2977 * super->vftbl->diffval));
2980 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2981 /* object type cast-check */
2984 vftbl_t *supervftbl;
2987 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2988 # define LABEL_CLASS BRANCH_LABEL_2
2989 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2990 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2991 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2993 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2999 super = iptr->sx.s23.s3.c.cls;
3000 superindex = super->index;
3001 supervftbl = super->vftbl;
3004 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3005 CODEGEN_CRITICAL_SECTION_NEW;
3007 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3009 /* if class is not resolved, check which code to call */
3011 if (super == NULL) {
3013 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3015 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3017 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3018 iptr->sx.s23.s3.c.ref,
3021 ICONST(REG_ITMP2, ACC_INTERFACE);
3022 if (N_VALID_DSEG_DISP(disp)) {
3023 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3025 ICONST(REG_ITMP3, disp);
3026 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3028 emit_label_beq(cd, LABEL_CLASS);
3031 /* interface checkcast code */
3033 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3034 if (super == NULL) {
3035 patcher_add_patch_ref(jd,
3036 PATCHER_checkcast_instanceof_interface,
3037 iptr->sx.s23.s3.c.ref,
3041 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3044 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3045 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3046 M_ISUB_IMM(superindex, REG_ITMP3);
3047 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3050 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3051 superindex * sizeof(methodptr*))
3053 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3054 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3056 if (super == NULL) {
3057 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3061 /* class checkcast code */
3063 if (super == NULL) {
3064 emit_label(cd, LABEL_CLASS);
3067 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3068 if (super == NULL) {
3069 disp = dseg_add_unique_address(cd, NULL);
3071 patcher_add_patch_ref(jd,
3072 PATCHER_resolve_classref_to_vftbl,
3073 iptr->sx.s23.s3.c.ref,
3077 disp = dseg_add_address(cd, supervftbl);
3079 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3082 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3083 M_ALD_DSEG(REG_ITMP3, disp);
3085 CODEGEN_CRITICAL_SECTION_START;
3087 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3088 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3089 M_ISUB(REG_ITMP3, REG_ITMP2);
3090 M_ALD_DSEG(REG_ITMP3, disp);
3091 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3093 CODEGEN_CRITICAL_SECTION_END;
3095 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3096 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3097 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3098 /* Branch if greater then */
3099 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3102 if (super == NULL) {
3103 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3104 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3105 } else if (super->flags & ACC_INTERFACE) {
3106 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3108 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3111 d = codegen_reg_of_dst(jd, iptr, s1);
3113 # undef LABEL_EXIT_CHECK_NULL
3115 # undef LABEL_EXIT_INTERFACE_NULL
3116 # undef LABEL_EXIT_INTERFACE_DONE
3117 # undef LABEL_EXIT_CLASS_NULL
3120 /* array type cast-check */
3122 s1 = emit_load_s1(jd, iptr, REG_A0);
3123 M_INTMOVE(s1, REG_A0);
3125 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3126 disp = dseg_add_unique_address(cd, NULL);
3128 patcher_add_patch_ref(jd,
3129 PATCHER_resolve_classref_to_classinfo,
3130 iptr->sx.s23.s3.c.ref,
3134 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3136 M_ALD_DSEG(REG_A1, disp);
3137 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3138 M_ALD_DSEG(REG_ITMP1, disp);
3139 M_ASUB_IMM(96, REG_SP);
3140 M_JSR(REG_RA, REG_ITMP1);
3141 M_AADD_IMM(96, REG_SP);
3143 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3144 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3146 d = codegen_reg_of_dst(jd, iptr, s1);
3150 emit_store_dst(jd, iptr, d);
3153 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3154 /* val.a: (classinfo*) superclass */
3156 /* superclass is an interface:
3158 * return (sub != NULL) &&
3159 * (sub->vftbl->interfacetablelength > super->index) &&
3160 * (sub->vftbl->interfacetable[-super->index] != NULL);
3162 * superclass is a class:
3164 * return ((sub != NULL) && (0
3165 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3166 * super->vftbl->diffvall));
3168 * If superclass is unresolved, we include both code snippets
3169 * above, a patcher resolves the class' flags and we select
3170 * the right code at runtime.
3175 vftbl_t *supervftbl;
3178 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3184 super = iptr->sx.s23.s3.c.cls;
3185 superindex = super->index;
3186 supervftbl = super->vftbl;
3189 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3190 # define LABEL_CLASS BRANCH_LABEL_2
3191 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3192 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3193 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3194 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3196 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3197 CODEGEN_CRITICAL_SECTION_NEW;
3199 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3200 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3202 M_MOV(s1, REG_ITMP1);
3206 /* if class is not resolved, check which code to call */
3208 if (super == NULL) {
3212 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3214 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3216 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3217 iptr->sx.s23.s3.c.ref, disp);
3219 ICONST(REG_ITMP2, ACC_INTERFACE);
3221 if (N_VALID_DSEG_DISP(disp)) {
3222 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3224 ICONST(REG_ITMP3, disp);
3225 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3228 emit_label_beq(cd, LABEL_CLASS);
3231 /* interface instanceof code */
3233 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3234 if (super == NULL) {
3235 /* If d == REG_ITMP2, then it's destroyed in check
3240 patcher_add_patch_ref(jd,
3241 PATCHER_checkcast_instanceof_interface,
3242 iptr->sx.s23.s3.c.ref, 0);
3247 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3250 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3251 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3252 M_ISUB_IMM(superindex, REG_ITMP3);
3254 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3258 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3259 superindex * sizeof(methodptr*))
3261 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3263 /* d := (REG_ITMP1 != 0) */
3265 N_LTR(d, REG_ITMP1);
3266 M_BEQ(SZ_BRC + SZ_LHI);
3269 if (super == NULL) {
3270 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3274 /* class instanceof code */
3276 if (super == NULL) {
3277 emit_label(cd, LABEL_CLASS);
3280 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3281 if (super == NULL) {
3282 disp = dseg_add_unique_address(cd, NULL);
3284 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3285 iptr->sx.s23.s3.c.ref,
3289 disp = dseg_add_address(cd, supervftbl);
3294 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3297 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3298 M_ALD_DSEG(REG_ITMP2, disp);
3300 CODEGEN_CRITICAL_SECTION_START;
3302 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3303 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3304 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3306 CODEGEN_CRITICAL_SECTION_END;
3308 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3310 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3312 M_BGT(SZ_BRC + SZ_LHI);
3316 if (super == NULL) {
3317 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3318 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3319 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3320 } else if (super->flags & ACC_INTERFACE) {
3321 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3322 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3324 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3327 # undef LABEL_EXIT_CHECK_NULL
3329 # undef LABEL_EXIT_INTERFACE_NULL
3330 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3331 # undef LABEL_EXIT_INTERFACE_DONE
3332 # undef LABEL_EXIT_CLASS_NULL
3334 emit_store_dst(jd, iptr, d);
3340 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3342 /* check for negative sizes and copy sizes to stack if necessary */
3344 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3347 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3349 /* copy SAVEDVAR sizes to stack */
3350 var = VAR(iptr->sx.s23.s2.args[s1]);
3352 /* Already Preallocated? */
3353 if (!(var->flags & PREALLOC)) {
3354 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3355 M_IST(s2, REG_SP, s1 * 4);
3359 /* is a patcher function set? */
3361 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3362 disp = dseg_add_unique_address(cd, 0);
3364 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3365 iptr->sx.s23.s3.c.ref,
3369 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3371 /* a0 = dimension count */
3373 ICONST(REG_A0, iptr->s1.argcount);
3375 /* a1 = classinfo */
3377 M_ALD_DSEG(REG_A1, disp);
3379 /* a2 = pointer to dimensions = stack pointer */
3381 M_MOV(REG_SP, REG_A2);
3383 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3384 M_ALD_DSEG(REG_ITMP1, disp);
3385 M_ASUB_IMM(96, REG_SP);
3386 M_JSR(REG_RA, REG_ITMP1);
3387 M_AADD_IMM(96, REG_SP);
3389 /* check for exception before result assignment */
3391 emit_exception_check(cd, iptr);
3393 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3394 M_INTMOVE(REG_RESULT, s1);
3395 emit_store_dst(jd, iptr, s1);
3400 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3404 } /* for instruction */
3406 MCODECHECK(512); /* XXX require a lower number? */
3408 /* At the end of a basic block we may have to append some nops,
3409 because the patcher stub calling code might be longer than the
3410 actual instruction. So codepatching does not change the
3411 following block unintentionally. */
3413 if (cd->mcodeptr < cd->lastmcodeptr) {
3414 while (cd->mcodeptr < cd->lastmcodeptr) {
3419 } /* if (bptr -> flags >= BBREACHED) */
3420 } /* for basic block */
3422 dseg_createlinenumbertable(cd);
3424 /* generate stubs */
3426 emit_patcher_traps(jd);
3428 /* everything's ok */
3434 /* codegen_emit_stub_compiler **************************************************
3436 Emits a stub routine which calls the compiler.
3438 *******************************************************************************/
3440 void codegen_emit_stub_compiler(jitdata *jd)
3445 /* get required compiler data */
3450 /* code for the stub */
3452 /* don't touch ITMP3 as it cointains the return address */
3454 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3456 M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */
3457 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3458 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3463 /* codegen_emit_stub_native ****************************************************
3465 Emits a stub routine which calls a native method.
3467 *******************************************************************************/
3470 arguments on stack \
3471 -------------------------------------------------| <- SP on nativestub entry
3473 callee saved int regs (none) |
3474 callee saved float regs (none) | stack frame like in cacao
3475 local variable slots (none) |
3476 arguments for calling methods (none) /
3477 ------------------------------------------------------------------ <- datasp
3482 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3483 0 - 96 register save area for callee /
3484 -------------------------------------------------------- <- SP native method
3486 SP after method entry
3489 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3497 s4 i, j; /* count variables */
3502 /* get required compiler data */
3509 /* initialize variables */
3512 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3514 /* calculate stack frame size */
3516 cd->stackframesize =
3517 1 + /* r14 - return address */ +
3518 ((sizeof(stackframeinfo) + 7) / 8) +
3519 ((sizeof(localref_table) + 7) / 8) +
3521 (INT_ARG_CNT + FLT_ARG_CNT) +
3522 nmd->memuse + /* parameter passing */
3523 (96 / 8) /* required by ABI */;
3525 /* create method header */
3527 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3528 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3529 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3530 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3531 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3532 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3533 (void) dseg_addlinenumbertablesize(cd);
3534 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3536 /* generate stub code */
3538 N_AHI(REG_SP, -(cd->stackframesize * 8));
3539 N_AHI(REG_PV, N_PV_OFFSET);
3541 /* generate native method profiling code */
3543 #if defined(ENABLE_PROFILING)
3544 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3545 /* count frequency */
3546 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
3547 ICONST(REG_ITMP2, 1);
3548 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
3549 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
3553 /* save return address */
3555 N_ST(R14, (cd->stackframesize - 1) * 8, RN, REG_SP);
3557 #if !defined(NDEBUG)
3558 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3559 emit_verbosecall_enter(jd);
3562 /* get function address (this must happen before the stackframeinfo) */
3564 disp = dseg_add_functionptr(cd, f);
3566 #if !defined(WITH_STATIC_CLASSPATH)
3568 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, disp);
3571 M_ILD_DSEG(REG_ITMP1, disp);
3573 j = 96 + (nmd->memuse * 8);
3575 /* todo some arg registers are not volatile in C-abi terms */
3577 /* save integer and float argument registers */
3579 for (i = 0; i < md->paramcount; i++) {
3580 if (! md->params[i].inmemory) {
3581 s1 = md->params[i].regoff;
3582 t = md->paramtypes[i].type;
3584 if (IS_INT_LNG_TYPE(t)) {
3585 if (IS_2_WORD_TYPE(t)) {
3586 /* todo store multiple */
3587 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3588 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3590 N_ST(s1, j, RN, REG_SP);
3593 if (IS_2_WORD_TYPE(t)) {
3594 N_STD(s1, j, RN, REG_SP);
3596 N_STE(s1, j, RN, REG_SP);
3604 N_ST(REG_ITMP1, j, RN, REG_SP);
3606 /* create dynamic stack info */
3608 N_LAE(REG_A0, (cd->stackframesize - 1) * 8 , RN, REG_SP); /* datasp */
3609 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3610 N_LAE(REG_A2, cd->stackframesize * 8, RN, REG_SP); /* old SP */
3611 N_L(REG_A3, (cd->stackframesize - 1) * 8, RN, REG_SP); /* return address */
3613 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3614 M_ILD_DSEG(REG_ITMP1, disp);
3616 M_CALL(REG_ITMP1); /* call */
3618 /* restore integer and float argument registers */
3620 j = 96 + (nmd->memuse * 8);
3622 for (i = 0; i < md->paramcount; i++) {
3623 if (! md->params[i].inmemory) {
3624 s1 = md->params[i].regoff;
3625 t = md->paramtypes[i].type;
3627 if (IS_INT_LNG_TYPE(t)) {
3628 if (IS_2_WORD_TYPE(t)) {
3629 /* todo load multiple ! */
3630 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3631 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3633 N_L(s1, j, RN, REG_SP);
3636 if (IS_2_WORD_TYPE(t)) {
3637 N_LD(s1, j, RN, REG_SP);
3639 N_LE(s1, j, RN, REG_SP);
3647 N_L(REG_ITMP1, j, RN, REG_SP);
3649 /* copy or spill arguments to new locations */
3651 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3652 t = md->paramtypes[i].type;
3654 if (IS_INT_LNG_TYPE(t)) {
3656 if (!md->params[i].inmemory) {
3658 s1 = md->params[i].regoff;
3660 if (!nmd->params[j].inmemory) {
3661 s2 = nmd->params[j].regoff;
3662 if (IS_2_WORD_TYPE(t)) {
3678 s2 = nmd->params[j].regoff;
3679 if (IS_2_WORD_TYPE(t)) {
3694 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3695 s2 = nmd->params[j].regoff;
3697 if (IS_2_WORD_TYPE(t)) {
3698 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3700 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3705 /* We only copy spilled float arguments, as the float argument */
3706 /* registers keep unchanged. */
3708 if (md->params[i].inmemory) {
3709 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3710 s2 = nmd->params[j].regoff;
3712 if (IS_2_WORD_TYPE(t)) {
3713 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3715 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3721 /* put class into second argument register */
3723 if (m->flags & ACC_STATIC) {
3724 disp = dseg_add_address(cd, m->class);
3725 M_ILD_DSEG(REG_A1, disp);
3728 /* put env into first argument register */
3730 disp = dseg_add_address(cd, _Jv_env);
3731 M_ILD_DSEG(REG_A0, disp);
3733 /* do the native function call */
3735 M_CALL(REG_ITMP1); /* call */
3737 /* save return value */
3739 t = md->returntype.type;
3741 if (t != TYPE_VOID) {
3742 if (IS_INT_LNG_TYPE(t)) {
3743 if (IS_2_WORD_TYPE(t)) {
3744 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3746 N_ST(REG_RESULT, 96, RN, REG_SP);
3749 if (IS_2_WORD_TYPE(t)) {
3750 N_STD(REG_FRESULT, 96, RN, REG_SP);
3752 N_STE(REG_FRESULT, 96, RN, REG_SP);
3757 #if !defined(NDEBUG)
3758 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3759 emit_verbosecall_exit(jd);
3762 /* remove native stackframe info */
3764 N_LAE(REG_A0, (cd->stackframesize - 1) * 8, RN, REG_SP); /* datasp */
3765 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3766 M_ALD_DSEG(REG_ITMP1, disp);
3768 N_LR(REG_ITMP3, REG_RESULT);
3770 /* restore return value */
3772 if (t != TYPE_VOID) {
3773 if (IS_INT_LNG_TYPE(t)) {
3774 if (IS_2_WORD_TYPE(t)) {
3775 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3777 N_L(REG_RESULT, 96, RN, REG_SP);
3780 if (IS_2_WORD_TYPE(t)) {
3781 N_LD(REG_FRESULT, 96, RN, REG_SP);
3783 N_LE(REG_FRESULT, 96, RN, REG_SP);
3788 /* load return address */
3790 N_L(REG_ITMP2, (cd->stackframesize - 1) * 8, RN, REG_SP);
3792 /* remove stackframe */
3794 N_AHI(REG_SP, cd->stackframesize * 8);
3796 /* test for exception */
3798 N_LTR(REG_ITMP3, REG_ITMP3);
3799 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3803 N_BCR(DD_ANY, REG_ITMP2);
3805 /* handle exception */
3807 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3808 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3812 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3815 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3816 M_ALD_DSEG(REG_ITMP3, disp);
3817 M_JMP(RN, REG_ITMP3);
3819 /* generate patcher stubs */
3821 emit_patcher_traps(jd);
3824 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3825 codegendata *cd = jd->cd;
3826 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3828 M_MOV(reg, tempregnum);
3836 * These are local overrides for various environment variables in Emacs.
3837 * Please do not remove this and leave it at the end of the file, where
3838 * Emacs will automagically detect them.
3839 * ---------------------------------------------------------------------
3842 * indent-tabs-mode: t
3846 * vim:noexpandtab:sw=4:ts=4: