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_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
183 #if defined(ENABLE_THREADS)
184 /* Space to save argument of monitor_enter and Return Values to
185 survive monitor_exit. The stack position for the argument can
186 not be shared with place to save the return register
187 since both values reside in R2. */
189 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
190 /* 1 slot space to save argument of monitor_enter */
191 /* 1 slot to temporary store return value before monitor_exit */
192 cd->stackframesize += 2;
196 /* Keep stack of non-leaf functions 16-byte aligned for calls into
197 native code e.g. libc or jni (alignment problems with
200 if (!jd->isleafmethod || opt_verbosecall )
201 /* TODO really 16 bytes ? */
202 cd->stackframesize = (cd->stackframesize + 2) & ~2;
204 /* create method header */
206 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
207 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
209 #if defined(ENABLE_THREADS)
210 /* IsSync contains the offset relative to the stack pointer for the
211 argument of monitor_exit used in the exception handler. Since the
212 offset could be zero and give a wrong meaning of the flag it is
216 if (checksync && (m->flags & ACC_SYNCHRONIZED))
217 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync */
220 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
222 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
223 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
224 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
226 (void) dseg_addlinenumbertablesize(cd);
228 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
230 /* create exception table */
232 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
233 dseg_add_target(cd, ex->start);
234 dseg_add_target(cd, ex->end);
235 dseg_add_target(cd, ex->handler);
236 (void) dseg_add_unique_address(cd, ex->catchtype.any);
241 M_AADD_IMM(N_PV_OFFSET, REG_PV);
243 /* generate method profiling code */
245 #if defined(ENABLE_PROFILING)
246 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
247 /* count frequency */
248 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
249 ICONST(REG_ITMP2, 1);
250 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
251 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
257 /* create stack frame (if necessary) */
259 if (cd->stackframesize)
260 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
262 /* save used callee saved registers and return address */
264 p = cd->stackframesize;
265 p--; M_AST(REG_RA, REG_SP, p * 8);
267 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
268 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
270 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
271 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
274 /* take arguments out of register or stack frame */
278 for (p = 0, l = 0; p < md->paramcount; p++) {
279 t = md->paramtypes[p].type;
280 varindex = jd->local_map[l * 5 + t];
284 if (IS_2_WORD_TYPE(t))
287 if (varindex == UNUSED)
292 s1 = md->params[p].regoff;
294 if (IS_INT_LNG_TYPE(t)) { /* integer args */
295 if (IS_2_WORD_TYPE(t)) {
303 if (!md->params[p].inmemory) { /* register arguments */
304 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
305 if (IS_2_WORD_TYPE(t)) {
306 M_LNGMOVE(s2, var->vv.regoff);
308 M_INTMOVE(s2, var->vv.regoff);
310 } else { /* reg arg -> spilled */
311 if (IS_2_WORD_TYPE(t)) {
312 M_LST(s2, REG_SP, var->vv.regoff);
314 M_IST(s2, REG_SP, var->vv.regoff);
318 } else { /* stack arguments */
319 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
320 if (IS_2_WORD_TYPE(t)) {
321 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
323 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
325 } else { /* stack arg -> spilled */
326 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
330 } else { /* floating args */
331 if (!md->params[p].inmemory) { /* register arguments */
333 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
334 M_FLTMOVE(s2, var->vv.regoff);
336 } else { /* reg arg -> spilled */
337 if (IS_2_WORD_TYPE(t))
338 M_DST(s2, REG_SP, var->vv.regoff);
340 M_FST(s2, REG_SP, var->vv.regoff);
343 } else { /* stack arguments */
344 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
345 if (IS_2_WORD_TYPE(t))
346 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
349 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
351 } else { /* stack-arg -> spilled */
352 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
353 var->vv.regoff = cd->stackframesize * 8 + s1;
359 /* save monitorenter argument */
361 #if defined(ENABLE_THREADS)
362 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
363 /* stack offset for monitor argument */
368 if (opt_verbosecall) {
369 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
371 for (p = 0; p < INT_ARG_CNT; p++)
372 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
374 for (p = 0; p < FLT_ARG_CNT; p++)
375 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
377 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
381 /* decide which monitor enter function to call */
383 if (m->flags & ACC_STATIC) {
384 disp = dseg_add_address(cd, &m->class->object.header);
385 M_ALD_DSEG(REG_A0, disp);
389 M_BNE(SZ_BRC + SZ_ILL);
390 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
393 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
394 M_ALD_DSEG(REG_ITMP3, disp);
396 M_AST(REG_A0, REG_SP, s1 * 8);
398 M_ASUB_IMM(96, REG_SP);
400 M_AADD_IMM(96, REG_SP);
403 if (opt_verbosecall) {
404 for (p = 0; p < INT_ARG_CNT; p++)
405 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
407 for (p = 0; p < FLT_ARG_CNT; p++)
408 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
410 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
417 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
418 emit_verbosecall_enter(jd);
419 #endif /* !defined(NDEBUG) */
423 /* end of header generation */
425 /* create replacement points */
427 REPLACEMENT_POINTS_INIT(cd, jd);
429 /* walk through all basic blocks */
431 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
433 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
435 if (bptr->flags >= BBREACHED) {
437 /* branch resolving */
439 codegen_resolve_branchrefs(cd, bptr);
441 /* handle replacement points */
443 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
445 /* copy interface registers to their destination */
450 #if defined(ENABLE_PROFILING)
451 /* generate basicblock profiling code */
453 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
454 /* count frequency */
456 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
457 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
458 ICONST(REG_ITMP2, 1);
459 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
460 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
462 /* if this is an exception handler, start profiling again */
464 if (bptr->type == BBTYPE_EXH)
469 #if defined(ENABLE_LSRA)
473 src = bptr->invars[len];
474 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
475 if (bptr->type == BBTYPE_EXH) {
476 /* d = reg_of_var(rd, src, REG_ITMP1); */
477 if (!IS_INMEMORY(src->flags))
481 M_INTMOVE(REG_ITMP1, d);
482 emit_store(jd, NULL, src, d);
492 var = VAR(bptr->invars[len]);
493 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
494 if (bptr->type == BBTYPE_EXH) {
495 d = codegen_reg_of_var(0, var, REG_ITMP1);
496 M_INTMOVE(REG_ITMP1, d);
497 emit_store(jd, NULL, var, d);
501 assert((var->flags & INOUT));
504 #if defined(ENABLE_LSRA)
507 /* walk through all instructions */
512 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
513 if (iptr->line != currentline) {
514 dseg_addlinenumber(cd, iptr->line);
515 currentline = iptr->line;
518 MCODECHECK(1024); /* 1KB should be enough */
521 case ICMD_NOP: /* ... ==> ... */
522 case ICMD_POP: /* ..., value ==> ... */
523 case ICMD_POP2: /* ..., value, value ==> ... */
526 case ICMD_INLINE_START:
528 REPLACEMENT_POINT_INLINE_START(cd, iptr);
531 case ICMD_INLINE_BODY:
533 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
534 dseg_addlinenumber_inline_start(cd, iptr);
535 dseg_addlinenumber(cd, iptr->line);
538 case ICMD_INLINE_END:
540 dseg_addlinenumber_inline_end(cd, iptr);
541 dseg_addlinenumber(cd, iptr->line);
544 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
545 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
546 emit_nullpointer_check(cd, iptr, s1);
549 /* constant operations ************************************************/
551 case ICMD_ICONST: /* ... ==> ..., constant */
552 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
553 ICONST(d, iptr->sx.val.i);
554 emit_store_dst(jd, iptr, d);
557 case ICMD_LCONST: /* ... ==> ..., constant */
559 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
560 LCONST(d, iptr->sx.val.l);
561 emit_store_dst(jd, iptr, d);
564 case ICMD_FCONST: /* ... ==> ..., constant */
565 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
566 disp = dseg_add_float(cd, iptr->sx.val.f);
567 M_FLD_DSEG(d, disp, REG_ITMP1);
568 emit_store_dst(jd, iptr, d);
571 case ICMD_DCONST: /* ... ==> ..., constant */
572 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
573 disp = dseg_add_double(cd, iptr->sx.val.d);
574 M_DLD_DSEG(d, disp, REG_ITMP1);
575 emit_store_dst(jd, iptr, d);
578 case ICMD_ACONST: /* ... ==> ..., constant */
579 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
581 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
582 cr = iptr->sx.val.c.ref;
583 disp = dseg_add_unique_address(cd, cr);
585 /* PROFILE_CYCLE_STOP; */
587 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
590 /* PROFILE_CYCLE_START; */
594 if (iptr->sx.val.anyptr == 0) {
597 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
600 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
601 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
603 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
605 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
611 emit_store_dst(jd, iptr, d);
615 /* load/store/copy/move operations ************************************/
617 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
618 case ICMD_ALOAD: /* s1 = local variable */
622 case ICMD_ISTORE: /* ..., value ==> ... */
633 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
637 /* integer operations *************************************************/
639 case ICMD_INEG: /* ..., value ==> ..., - value */
641 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
642 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
644 emit_store_dst(jd, iptr, d);
648 case ICMD_LNEG: /* ..., value ==> ..., - value */
650 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
651 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
652 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
653 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
654 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
655 N_AHI(GET_HIGH_REG(d), -1);
656 emit_store_dst(jd, iptr, d);
659 case ICMD_I2L: /* ..., value ==> ..., value */
661 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
662 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
664 M_INTMOVE(s1, GET_HIGH_REG(d));
665 ICONST(GET_LOW_REG(d), 0);
666 M_SRDA_IMM(32, GET_HIGH_REG(d));
668 emit_copy_dst(jd, iptr, d);
669 emit_store_dst(jd, iptr, d);
670 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
674 case ICMD_L2I: /* ..., value ==> ..., value */
675 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
676 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
677 M_INTMOVE(GET_LOW_REG(s1), d);
678 emit_store_dst(jd, iptr, d);
681 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
682 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
683 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
687 emit_store_dst(jd, iptr, d);
690 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
691 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
692 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
696 emit_store_dst(jd, iptr, d);
699 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
701 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
702 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
706 emit_store_dst(jd, iptr, d);
709 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
711 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
712 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
713 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
720 emit_store_dst(jd, iptr, d);
725 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
726 /* sx.val.i = constant */
727 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
728 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
731 if (N_VALID_IMM(iptr->sx.val.i)) {
732 M_IADD_IMM(iptr->sx.val.i, d);
734 ICONST(REG_ITMP2, iptr->sx.val.i);
735 M_IADD(REG_ITMP2, d);
737 emit_store_dst(jd, iptr, d);
740 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
742 /* M, (r, q) -> (r, q) */
744 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
746 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
747 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
748 dd = GET_HIGH_REG(d);
757 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
758 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
768 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
769 N_AHI(GET_HIGH_REG(d), 1);
771 emit_store_dst(jd, iptr, d);
774 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
775 /* sx.val.l = constant */
777 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
778 dd = GET_HIGH_REG(d);
780 s1 = emit_load_s1_high(jd, iptr, dd);
781 s3 = iptr->sx.val.l >> 32;
785 if (N_VALID_IMM(s3)) {
788 ICONST(REG_ITMP3, s3);
789 M_IADD(REG_ITMP3, dd);
793 s1 = emit_load_s1_low(jd, iptr, dd);
794 s3 = iptr->sx.val.l & 0xffffffff;
795 ICONST(REG_ITMP3, s3);
798 N_ALR(dd, REG_ITMP3);
800 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
801 N_AHI(GET_HIGH_REG(d), 1);
803 emit_store_dst(jd, iptr, d);
806 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
808 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
809 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
810 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
812 M_INTMOVE(s1, REG_ITMP1);
813 M_ISUB(s2, REG_ITMP1);
814 M_INTMOVE(REG_ITMP1, d);
819 emit_store_dst(jd, iptr, d);
823 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
824 /* sx.val.i = constant */
826 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
827 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
830 if (N_VALID_IMM(-iptr->sx.val.i)) {
831 M_ISUB_IMM(iptr->sx.val.i, d);
833 ICONST(REG_ITMP2, iptr->sx.val.i);
834 M_ISUB(REG_ITMP2, d);
836 emit_store_dst(jd, iptr, d);
840 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
842 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
844 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
845 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
846 dd = GET_HIGH_REG(d);
849 M_INTMOVE(s2, REG_ITMP3);
856 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
857 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
861 M_INTMOVE(s2, REG_ITMP3);
868 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
869 N_AHI(GET_HIGH_REG(d), -1);
871 emit_store_dst(jd, iptr, d);
874 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
875 /* sx.val.l = constant */
877 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
879 dd = GET_HIGH_REG(d);
880 s1 = emit_load_s1_high(jd, iptr, dd);
881 s3 = iptr->sx.val.l >> 32;
885 if (N_VALID_IMM(-s3)) {
888 ICONST(REG_ITMP3, s3);
889 M_ISUB(REG_ITMP3, dd);
893 s1 = emit_load_s1_low(jd, iptr, dd);
894 s3 = iptr->sx.val.l & 0xffffffff;
895 ICONST(REG_ITMP3, s3);
898 N_SLR(dd, REG_ITMP3);
900 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
901 N_AHI(GET_HIGH_REG(d), -1);
903 emit_store_dst(jd, iptr, d);
906 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
908 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
909 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
910 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
917 emit_store_dst(jd, iptr, d);
921 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
922 /* sx.val.i = constant */
923 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
924 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
926 if (iptr->sx.val.i == 2) {
928 } else if (N_VALID_IMM(iptr->sx.val.i)) {
929 M_IMUL_IMM(iptr->sx.val.i, d);
931 disp = dseg_add_s4(cd, iptr->sx.val.i);
932 M_ILD_DSEG(REG_ITMP2, disp);
933 M_IMUL(REG_ITMP2, d);
935 emit_store_dst(jd, iptr, d);
938 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
939 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
941 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
942 emit_arithmetic_check(cd, iptr, s2);
944 /* For this operation we need a register pair.
945 * We will use r0 and itmp1 and will backup r0.
948 M_INTMOVE(R0, REG_ITMP3);
950 /* We won't check for division by 0, we catch a SIGFPE instead
951 * Special case 0x80000000 / 0xffffffff handled by signal handler too.
954 s1 = emit_load_s1(jd, iptr, R0);
963 d = codegen_reg_of_dst(jd, iptr, R0);
967 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
968 M_INTMOVE(REG_ITMP1, d);
972 emit_store_dst(jd, iptr, d);
974 /* If destionation of operation was not register R0,
978 if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
979 M_INTMOVE(REG_ITMP3, R0);
984 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
985 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
987 bte = iptr->sx.s23.s3.bte;
990 /* test s2 for zero */
992 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
993 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
994 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
995 emit_arithmetic_check(cd, iptr, REG_ITMP3);
999 disp = dseg_add_functionptr(cd, bte->fp);
1001 /* load arguments */
1003 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
1005 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
1006 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
1010 M_ASUB_IMM(96, REG_SP);
1011 M_ALD_DSEG(REG_ITMP3, disp);
1012 M_JSR(REG_RA, REG_ITMP3);
1013 M_AADD_IMM(96, REG_SP);
1017 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1018 M_LNGMOVE(REG_RESULT_PACKED, d);
1019 emit_store_dst(jd, iptr, d);
1023 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1024 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1025 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1027 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1028 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1029 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1031 /* Use only 5 bits of sencond operand. */
1033 M_INTMOVE(s2, REG_ITMP2);
1035 ICONST(REG_ITMP3, 0x1F);
1036 M_IAND(REG_ITMP3, s2);
1040 switch (iptr->opc) {
1053 emit_store_dst(jd, iptr, d);
1056 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1057 /* sx.val.i = constant */
1061 assert(iptr->sx.val.i <= 32);
1063 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1064 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1071 s3 = (1 << iptr->sx.val.i) - 1;
1073 if (N_VALID_IMM(s3)) {
1076 ICONST(REG_ITMP1, -1);
1077 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1078 M_IADD(REG_ITMP1, d);
1081 N_BRC_BACK_PATCH(ref);
1083 M_SRA_IMM(iptr->sx.val.i, d);
1085 emit_store_dst(jd, iptr, d);
1090 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1091 /* sx.val.i = constant */
1093 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1094 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1097 M_MOV(s1, REG_ITMP1);
1101 ICONST(REG_ITMP3, iptr->sx.val.i);
1104 M_IAND(REG_ITMP3, d);
1107 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1113 emit_store_dst(jd, iptr, d);
1117 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1118 /* sx.val.i = constant */
1119 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1120 /* sx.val.i = constant */
1121 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1122 /* sx.val.i = constant */
1123 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1124 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1128 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1130 switch (iptr->opc) {
1131 case ICMD_ISHLCONST:
1134 case ICMD_ISHRCONST:
1137 case ICMD_IUSHRCONST:
1144 emit_store_dst(jd, iptr, d);
1147 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1149 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1151 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1153 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1155 /* Use only 6 bits of second operand */
1157 M_INTMOVE(s2, REG_ITMP3);
1159 ICONST(REG_ITMP2, 0x3F);
1160 M_IAND(REG_ITMP2, s2);
1162 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1164 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1165 M_INTMOVE(s2, REG_ITMP3);
1169 s1 = emit_load_s1(jd, iptr, d);
1173 switch (iptr->opc) {
1175 M_SLDL(s2, GET_HIGH_REG(d));
1178 M_SRDA(s2, GET_HIGH_REG(d));
1181 M_SRDL(s2, GET_HIGH_REG(d));
1187 emit_copy_dst(jd, iptr, d);
1188 emit_store_dst(jd, iptr, d);
1189 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1193 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1194 /* sx.val.i = constant */
1195 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1196 /* sx.val.i = constant */
1197 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1198 /* sx.val.l = constant */
1201 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1202 s1 = emit_load_s1(jd, iptr, d);
1206 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1208 switch (iptr->opc) {
1209 case ICMD_LSHLCONST:
1210 N_SLDL(GET_HIGH_REG(d), disp, RN);
1212 case ICMD_LSHRCONST:
1213 N_SRDA(GET_HIGH_REG(d), disp, RN);
1215 case ICMD_LUSHRCONST:
1216 N_SRDL(GET_HIGH_REG(d), disp, RN);
1219 N_SLDL(GET_HIGH_REG(d), disp, RN);
1225 emit_copy_dst(jd, iptr, d);
1226 emit_store_dst(jd, iptr, d);
1227 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1231 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1233 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1234 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1235 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1242 emit_store_dst(jd, iptr, d);
1246 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1248 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1249 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1250 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1257 emit_store_dst(jd, iptr, d);
1261 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1263 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1264 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1265 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1272 emit_store_dst(jd, iptr, d);
1278 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1279 /* sx.val.i = constant */
1280 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1281 /* sx.val.i = constant */
1282 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1283 /* sx.val.i = constant */
1285 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1286 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1289 ICONST(REG_ITMP2, iptr->sx.val.i);
1291 switch (iptr->opc) {
1292 case ICMD_IANDCONST:
1293 M_IAND(REG_ITMP2, d);
1295 case ICMD_IXORCONST:
1296 M_IXOR(REG_ITMP2, d);
1299 M_IOR(REG_ITMP2, d);
1305 emit_store_dst(jd, iptr, d);
1309 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1310 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1311 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1313 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1315 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1316 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1317 dd = GET_LOW_REG(d);
1319 switch (iptr->opc) {
1348 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1349 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1350 dd = GET_HIGH_REG(d);
1352 switch (iptr->opc) {
1381 emit_store_dst(jd, iptr, d);
1384 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1385 /* sx.val.l = constant */
1386 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1387 /* sx.val.l = constant */
1388 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1389 /* sx.val.l = constant */
1391 /* TODO should use memory operand to access data segment, not load */
1393 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1395 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1396 s3 = iptr->sx.val.l & 0xffffffff;
1398 M_INTMOVE(s1, GET_LOW_REG(d));
1400 ICONST(REG_ITMP3, s3);
1402 switch (iptr->opc) {
1403 case ICMD_LANDCONST:
1404 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1406 case ICMD_LXORCONST:
1407 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1410 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1416 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1417 s3 = iptr->sx.val.l >> 32;
1419 M_INTMOVE(s1, GET_HIGH_REG(d));
1421 ICONST(REG_ITMP3, s3);
1423 switch (iptr->opc) {
1424 case ICMD_LANDCONST:
1425 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1427 case ICMD_LXORCONST:
1428 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1431 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1437 emit_store_dst(jd, iptr, d);
1441 /* floating operations ************************************************/
1443 case ICMD_FNEG: /* ..., value ==> ..., - value */
1444 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1445 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1447 emit_store_dst(jd, iptr, d);
1450 case ICMD_DNEG: /* ..., value ==> ..., - value */
1451 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1452 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1454 emit_store_dst(jd, iptr, d);
1457 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1458 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1459 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1460 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1467 emit_store_dst(jd, iptr, d);
1470 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1471 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1472 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1473 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1480 emit_store_dst(jd, iptr, d);
1483 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1484 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1485 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1486 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1490 emit_store_dst(jd, iptr, d);
1493 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1494 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1495 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1496 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1500 emit_store_dst(jd, iptr, d);
1503 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1504 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1505 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1506 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1513 emit_store_dst(jd, iptr, d);
1516 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1517 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1518 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1519 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1526 emit_store_dst(jd, iptr, d);
1529 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1530 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1531 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1532 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1536 emit_store_dst(jd, iptr, d);
1539 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1540 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1541 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1542 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1546 emit_store_dst(jd, iptr, d);
1549 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1550 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1551 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1553 emit_store_dst(jd, iptr, d);
1556 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1557 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1558 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1560 emit_store_dst(jd, iptr, d);
1563 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1567 #ifdef SUPPORT_HERCULES
1571 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1572 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1576 switch (iptr->opc) {
1585 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1586 N_LHI(d, 0); /* Load 0 */
1587 ref1 = cd->mcodeptr;
1588 N_BRC(DD_ANY, 0); /* Exit */
1592 switch (iptr->opc) {
1601 #ifdef SUPPORT_HERCULES
1602 /* Hercules does the conversion using a plain C conversion.
1603 * According to manual, real hardware should *NOT* require this.
1605 * Corner case: Positive float leads to INT_MIN (overflow).
1608 switch (iptr->opc) {
1617 ref2 = cd->mcodeptr;
1618 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1622 ref3 = cd->mcodeptr;
1623 M_BGE(0); /* If integer result is negative, continue */
1625 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1626 M_ILD_DSEG(d, disp);
1628 N_BRC_BACK_PATCH(ref1);
1629 #ifdef SUPPORT_HERCULES
1630 N_BRC_BACK_PATCH(ref2);
1631 N_BRC_BACK_PATCH(ref3);
1633 emit_store_dst(jd, iptr, d);
1637 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1640 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1641 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1642 #ifdef SUPPORT_HERCULES
1645 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1646 disp = dseg_add_double(cd, 0.0 / 0.0);
1647 M_DLD_DSEG(d, disp, REG_ITMP1);
1648 emit_label_br(cd, BRANCH_LABEL_1);
1649 N_BRC_BACK_PATCH(ref);
1652 #ifdef SUPPORT_HERCULES
1653 emit_label(cd, BRANCH_LABEL_1);
1655 emit_store_dst(jd, iptr, d);
1659 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1660 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1661 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1663 emit_store_dst(jd, iptr, d);
1666 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1667 /* == => 0, < => 1, > => -1 */
1671 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1672 /* == => 0, < => 1, > => -1 */
1675 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1676 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1677 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1679 switch (iptr->opc) {
1691 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1692 SZ_BRC + SZ_BRC + SZ_BRC
1695 N_BRC( /* load -1 */
1696 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1697 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1702 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1705 N_LHI(d, 1); /* GT */
1706 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1707 N_LHI(d, -1); /* LT */
1708 M_BR(SZ_BRC + SZ_LHI);
1709 N_LHI(d, 0); /* EQ */
1711 emit_store_dst(jd, iptr, d);
1716 /* memory operations **************************************************/
1718 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1720 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1721 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1723 /* implicit null-pointer check */
1724 M_ILD(d, s1, OFFSET(java_array_t, size));
1725 emit_store_dst(jd, iptr, d);
1729 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1730 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1731 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1732 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1734 /* implicit null-pointer check */
1735 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1737 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1742 emit_store_dst(jd, iptr, d);
1745 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1747 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1748 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1749 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1751 /* implicit null-pointer check */
1752 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1754 M_INTMOVE(s2, REG_ITMP2);
1755 M_SLL_IMM(1, REG_ITMP2);
1757 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1759 /* N_LH does sign extends, undo ! */
1764 emit_store_dst(jd, iptr, d);
1767 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1768 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1769 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1770 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1772 /* implicit null-pointer check */
1773 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1775 M_INTMOVE(s2, REG_ITMP2);
1776 M_SLL_IMM(1, REG_ITMP2);
1778 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1779 emit_store_dst(jd, iptr, d);
1782 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1783 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1784 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1785 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1787 /* implicit null-pointer check */
1788 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1790 M_INTMOVE(s2, REG_ITMP2);
1791 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1792 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1793 emit_store_dst(jd, iptr, d);
1796 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1798 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1799 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1801 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1803 /* implicit null-pointer check */
1804 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1806 M_INTMOVE(s2, REG_ITMP2);
1807 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1809 /* We need to preserve the array address after the first load */
1811 if (GET_HIGH_REG(d) == s1) {
1812 M_INTMOVE(s1, REG_ITMP3);
1816 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1817 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1818 emit_store_dst(jd, iptr, d);
1822 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1824 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1825 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1826 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1828 /* implicit null-pointer check */
1829 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1831 M_INTMOVE(s2, REG_ITMP2);
1832 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1834 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1836 emit_store_dst(jd, iptr, d);
1839 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1840 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1841 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1842 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1844 /* implicit null-pointer check */
1845 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1847 M_INTMOVE(s2, REG_ITMP2);
1848 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1850 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1852 emit_store_dst(jd, iptr, d);
1855 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1856 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1857 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1858 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1860 /* implicit null-pointer check */
1861 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1863 M_INTMOVE(s2, REG_ITMP2);
1864 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1865 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1866 emit_store_dst(jd, iptr, d);
1869 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1870 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1871 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1872 /* implicit null-pointer check */
1873 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1874 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1876 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1879 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1881 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1882 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1883 /* implicit null-pointer check */
1884 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1885 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1887 M_INTMOVE(s2, REG_ITMP2);
1888 M_SLL_IMM(1, REG_ITMP2);
1890 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1894 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1895 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1896 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1897 /* implicit null-pointer check */
1898 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1899 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1901 M_INTMOVE(s2, REG_ITMP2);
1902 M_SLL_IMM(1, REG_ITMP2);
1904 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1907 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1909 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1910 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1911 /* implicit null-pointer check */
1912 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1914 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1916 M_INTMOVE(s2, REG_ITMP2);
1917 M_SLL_IMM(2, REG_ITMP2);
1919 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1922 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1924 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1925 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1926 /* implicit null-pointer check */
1927 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1929 M_INTMOVE(s2, REG_ITMP2);
1930 M_SLL_IMM(3, REG_ITMP2);
1932 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1933 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1934 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1935 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1938 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1939 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1940 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1941 /* implicit null-pointer check */
1942 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1943 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1945 M_INTMOVE(s2, REG_ITMP2);
1946 M_SLL_IMM(2, REG_ITMP2);
1948 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1951 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1952 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1953 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1954 /* implicit null-pointer check */
1955 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1956 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1958 M_INTMOVE(s2, REG_ITMP2);
1959 M_SLL_IMM(3, REG_ITMP2);
1961 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1964 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1966 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1967 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1968 /* implicit null-pointer check */
1969 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1970 s3 = emit_load_s3(jd, iptr, REG_A1);
1972 M_INTMOVE(s1, REG_A0);
1973 M_INTMOVE(s3, REG_A1);
1975 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1976 M_ALD_DSEG(REG_ITMP3, disp);
1977 M_ASUB_IMM(96, REG_SP);
1978 M_JSR(REG_RA, REG_ITMP3);
1979 M_AADD_IMM(96, REG_SP);
1981 emit_arraystore_check(cd, iptr);
1983 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1984 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1985 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1987 M_INTMOVE(s2, REG_ITMP2);
1988 M_SLL_IMM(2, REG_ITMP2);
1989 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1992 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1993 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1998 case ICMD_GETSTATIC: /* ... ==> ..., value */
2000 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2001 uf = iptr->sx.s23.s3.uf;
2002 fieldtype = uf->fieldref->parseddesc.fd->type;
2003 disp = dseg_add_unique_address(cd, NULL);
2005 /* PROFILE_CYCLE_STOP; */
2007 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2009 /* PROFILE_CYCLE_START; */
2012 fi = iptr->sx.s23.s3.fmiref->p.field;
2013 fieldtype = fi->type;
2014 disp = dseg_add_address(cd, fi->value);
2016 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2019 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
2021 PROFILE_CYCLE_START;
2025 M_ALD_DSEG(REG_ITMP1, disp);
2027 switch (fieldtype) {
2029 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2030 M_ILD(d, REG_ITMP1, 0);
2033 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2034 M_LLD(d, REG_ITMP1, 0);
2037 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2038 M_ALD(d, REG_ITMP1, 0);
2041 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2042 M_FLD(d, REG_ITMP1, 0);
2045 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2046 M_DLD(d, REG_ITMP1, 0);
2050 emit_store_dst(jd, iptr, d);
2054 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2056 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2057 uf = iptr->sx.s23.s3.uf;
2058 fieldtype = uf->fieldref->parseddesc.fd->type;
2059 disp = dseg_add_unique_address(cd, uf);
2061 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2064 fi = iptr->sx.s23.s3.fmiref->p.field;
2065 fieldtype = fi->type;
2066 disp = dseg_add_address(cd, fi->value);
2068 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2070 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
2071 PROFILE_CYCLE_START;
2075 M_ALD_DSEG(REG_ITMP1, disp);
2076 switch (fieldtype) {
2078 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2079 M_IST(s1, REG_ITMP1, 0);
2082 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2083 M_LST(s1, REG_ITMP1, 0);
2086 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2087 M_AST(s1, REG_ITMP1, 0);
2090 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2091 M_FST(s1, REG_ITMP1, 0);
2094 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2095 M_DST(s1, REG_ITMP1, 0);
2100 case ICMD_GETFIELD: /* ... ==> ..., value */
2102 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2103 emit_nullpointer_check(cd, iptr, s1);
2105 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2106 uf = iptr->sx.s23.s3.uf;
2107 fieldtype = uf->fieldref->parseddesc.fd->type;
2110 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2113 fi = iptr->sx.s23.s3.fmiref->p.field;
2114 fieldtype = fi->type;
2118 switch (fieldtype) {
2120 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2124 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2125 if (GET_HIGH_REG(d) == s1) {
2126 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2127 M_ILD(GET_HIGH_REG(d), s1, disp);
2130 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2131 M_ILD(GET_HIGH_REG(d), s1, disp);
2135 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2139 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2143 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2147 emit_store_dst(jd, iptr, d);
2150 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2154 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2155 emit_nullpointer_check(cd, iptr, s1);
2157 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2158 uf = iptr->sx.s23.s3.uf;
2159 fieldtype = uf->fieldref->parseddesc.fd->type;
2163 fi = iptr->sx.s23.s3.fmiref->p.field;
2164 fieldtype = fi->type;
2168 /* We can't add a patcher ref behind this load,
2169 * because the patcher would destroy REG_ITMP3.
2171 * We pass in the disp parameter, how many bytes
2172 * to skip to the to the actual store.
2174 * XXX this relies on patcher_add_patch_ref internals
2177 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2178 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2183 if (IS_INT_LNG_TYPE(fieldtype)) {
2184 if (IS_2_WORD_TYPE(fieldtype))
2185 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2187 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2189 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2192 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2193 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2196 switch (fieldtype) {
2198 M_IST(s2, s1, disp);
2201 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2202 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2205 M_AST(s2, s1, disp);
2208 M_FST(s2, s1, disp);
2211 M_DST(s2, s1, disp);
2218 /* branch operations **************************************************/
2220 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2222 /* PROFILE_CYCLE_STOP; */
2224 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2225 M_INTMOVE(s1, REG_ITMP1_XPTR);
2227 #ifdef ENABLE_VERIFIER
2228 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2229 uc = iptr->sx.s23.s2.uc;
2231 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2233 #endif /* ENABLE_VERIFIER */
2235 disp = dseg_add_functionptr(cd, asm_handle_exception);
2236 M_ALD_DSEG(REG_ITMP2, disp);
2237 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2242 case ICMD_GOTO: /* ... ==> ... */
2243 case ICMD_RET: /* ... ==> ... */
2245 emit_br(cd, iptr->dst.block);
2249 case ICMD_JSR: /* ... ==> ... */
2251 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2255 case ICMD_IFNULL: /* ..., value ==> ... */
2256 case ICMD_IFNONNULL: /* ..., value ==> ... */
2257 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2259 switch (iptr->opc) {
2261 emit_beq(cd, iptr->dst.block);
2263 case ICMD_IFNONNULL:
2264 emit_bne(cd, iptr->dst.block);
2269 case ICMD_IFEQ: /* ..., value ==> ... */
2270 case ICMD_IFLT: /* ..., value ==> ... */
2271 case ICMD_IFLE: /* ..., value ==> ... */
2272 case ICMD_IFNE: /* ..., value ==> ... */
2273 case ICMD_IFGT: /* ..., value ==> ... */
2274 case ICMD_IFGE: /* ..., value ==> ... */
2276 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2278 if (N_VALID_IMM(iptr->sx.val.i))
2279 M_ICMP_IMM(s1, iptr->sx.val.i);
2281 disp = dseg_add_s4(cd, iptr->sx.val.i);
2282 if (N_VALID_DSEG_DISP(disp)) {
2283 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2285 ICONST(REG_ITMP2, disp);
2286 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2290 switch (iptr->opc) {
2292 emit_blt(cd, iptr->dst.block);
2295 emit_ble(cd, iptr->dst.block);
2298 emit_bne(cd, iptr->dst.block);
2301 emit_bgt(cd, iptr->dst.block);
2304 emit_bge(cd, iptr->dst.block);
2307 emit_beq(cd, iptr->dst.block);
2313 case ICMD_IF_LLT: /* ..., value ==> ... */
2314 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2320 /* ATTENTION: compare high words signed and low words unsigned */
2322 # define LABEL_OUT BRANCH_LABEL_1
2324 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2326 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2327 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2329 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2330 if (N_VALID_DSEG_DISP(disp)) {
2331 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2333 ICONST(REG_ITMP2, disp);
2334 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2341 emit_blt(cd, iptr->dst.block);
2342 /* EQ ... fall through */
2343 emit_label_bgt(cd, LABEL_OUT);
2347 emit_bgt(cd, iptr->dst.block);
2348 /* EQ ... fall through */
2349 emit_label_blt(cd, LABEL_OUT);
2352 /* EQ ... fall through */
2353 emit_label_bne(cd, LABEL_OUT);
2356 /* EQ ... fall through */
2357 emit_bne(cd, iptr->dst.block);
2363 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2365 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2366 if (N_VALID_DSEG_DISP(disp)) {
2367 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2369 ICONST(REG_ITMP2, disp);
2370 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2375 emit_blt(cd, iptr->dst.block);
2376 emit_label(cd, LABEL_OUT);
2379 emit_ble(cd, iptr->dst.block);
2380 emit_label(cd, LABEL_OUT);
2383 emit_bgt(cd, iptr->dst.block);
2384 emit_label(cd, LABEL_OUT);
2387 emit_bge(cd, iptr->dst.block);
2388 emit_label(cd, LABEL_OUT);
2391 emit_beq(cd, iptr->dst.block);
2392 emit_label(cd, LABEL_OUT);
2395 emit_bne(cd, iptr->dst.block);
2404 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2405 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2407 /* Compare addresses as 31 bit unsigned integers */
2409 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2410 M_LDA(REG_ITMP1, s1, 0);
2412 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2413 M_LDA(REG_ITMP2, s2, 0);
2415 M_CMP(REG_ITMP1, REG_ITMP2);
2417 switch (iptr->opc) {
2418 case ICMD_IF_ACMPEQ:
2419 emit_beq(cd, iptr->dst.block);
2421 case ICMD_IF_ACMPNE:
2422 emit_bne(cd, iptr->dst.block);
2428 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2429 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2430 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2431 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2432 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2433 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2435 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2436 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2438 switch (iptr->opc) {
2439 case ICMD_IF_ICMPEQ:
2440 emit_beq(cd, iptr->dst.block);
2442 case ICMD_IF_ICMPNE:
2443 emit_bne(cd, iptr->dst.block);
2445 case ICMD_IF_ICMPLT:
2446 emit_blt(cd, iptr->dst.block);
2448 case ICMD_IF_ICMPGT:
2449 emit_bgt(cd, iptr->dst.block);
2451 case ICMD_IF_ICMPLE:
2452 emit_ble(cd, iptr->dst.block);
2454 case ICMD_IF_ICMPGE:
2455 emit_bge(cd, iptr->dst.block);
2461 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2462 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2463 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2464 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2465 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2466 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2471 /* ATTENTION: compare high words signed and low words unsigned */
2473 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2474 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2479 case ICMD_IF_LCMPLT:
2480 case ICMD_IF_LCMPLE:
2481 emit_blt(cd, iptr->dst.block);
2482 /* EQ ... fall through */
2483 out_ref = cd->mcodeptr;
2486 case ICMD_IF_LCMPGT:
2487 case ICMD_IF_LCMPGE:
2488 emit_bgt(cd, iptr->dst.block);
2489 /* EQ ... fall through */
2490 out_ref = cd->mcodeptr;
2493 case ICMD_IF_LCMPEQ:
2494 /* EQ ... fall through */
2495 out_ref = cd->mcodeptr;
2498 case ICMD_IF_LCMPNE:
2499 /* EQ ... fall through */
2500 emit_bne(cd, iptr->dst.block);
2506 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2507 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2512 case ICMD_IF_LCMPLT:
2513 emit_blt(cd, iptr->dst.block);
2515 case ICMD_IF_LCMPLE:
2516 emit_ble(cd, iptr->dst.block);
2518 case ICMD_IF_LCMPGT:
2519 emit_bgt(cd, iptr->dst.block);
2521 case ICMD_IF_LCMPGE:
2522 emit_bge(cd, iptr->dst.block);
2524 case ICMD_IF_LCMPEQ:
2525 emit_beq(cd, iptr->dst.block);
2527 case ICMD_IF_LCMPNE:
2528 emit_bne(cd, iptr->dst.block);
2535 if (out_ref != NULL) {
2536 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2542 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2544 REPLACEMENT_POINT_RETURN(cd, iptr);
2545 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2546 M_INTMOVE(s1, REG_RESULT);
2547 goto nowperformreturn;
2549 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2551 REPLACEMENT_POINT_RETURN(cd, iptr);
2552 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2553 M_INTMOVE(s1, REG_RESULT);
2555 #ifdef ENABLE_VERIFIER
2556 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2557 unresolved_class *uc = iptr->sx.s23.s2.uc;
2560 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2561 PROFILE_CYCLE_START;
2563 #endif /* ENABLE_VERIFIER */
2564 goto nowperformreturn;
2566 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2568 REPLACEMENT_POINT_RETURN(cd, iptr);
2569 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2570 M_LNGMOVE(s1, REG_RESULT_PACKED);
2571 goto nowperformreturn;
2573 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2576 REPLACEMENT_POINT_RETURN(cd, iptr);
2577 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2578 M_FLTMOVE(s1, REG_FRESULT);
2579 goto nowperformreturn;
2581 case ICMD_RETURN: /* ... ==> ... */
2583 REPLACEMENT_POINT_RETURN(cd, iptr);
2589 p = cd->stackframesize;
2591 /* call trace function */
2593 #if !defined(NDEBUG)
2594 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2595 emit_verbosecall_exit(jd);
2596 #endif /* !defined(NDEBUG) */
2598 #if defined(ENABLE_THREADS)
2599 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2600 /* we need to save the proper return value */
2602 switch (iptr->opc) {
2604 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2608 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2611 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2614 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2618 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2620 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2621 M_ALD_DSEG(REG_ITMP3, disp);
2623 M_ASUB_IMM(96, REG_SP);
2625 M_AADD_IMM(96, REG_SP);
2627 /* and now restore the proper return value */
2629 switch (iptr->opc) {
2631 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2635 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2638 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2641 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2647 /* restore return address */
2649 p--; M_ALD(REG_RA, REG_SP, p * 8);
2651 /* restore saved registers */
2653 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2654 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2656 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2657 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2660 /* deallocate stack */
2662 if (cd->stackframesize)
2663 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2665 /* generate method profiling code */
2673 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2676 branch_target_t *table;
2678 table = iptr->dst.table;
2680 l = iptr->sx.s23.s2.tablelow;
2681 i = iptr->sx.s23.s3.tablehigh;
2683 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2684 M_INTMOVE(s1, REG_ITMP1);
2688 } else if (N_VALID_IMM(-l)) {
2689 M_ISUB_IMM(l, REG_ITMP1);
2691 ICONST(REG_ITMP2, l);
2692 M_ISUB(REG_ITMP2, REG_ITMP1);
2695 /* number of targets */
2701 ICONST(REG_ITMP2, i);
2702 M_ICMPU(REG_ITMP1, REG_ITMP2);
2703 emit_bge(cd, table[0].block);
2705 /* build jump table top down and use address of lowest entry */
2710 dseg_add_target(cd, table->block);
2715 /* length of dataseg after last dseg_add_target is used by load */
2717 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2718 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2719 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2720 M_JMP(RN, REG_ITMP1);
2725 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2728 lookup_target_t *lookup;
2730 lookup = iptr->dst.lookup;
2732 i = iptr->sx.s23.s2.lookupcount;
2734 MCODECHECK(8 + ((7 + 6) * i) + 5);
2735 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2738 if (N_VALID_IMM(lookup->value)) {
2739 M_ICMP_IMM(s1, lookup->value);
2741 ICONST(REG_ITMP2, lookup->value);
2742 M_ICMP(REG_ITMP2, s1);
2744 emit_beq(cd, lookup->target.block);
2748 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2753 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2755 bte = iptr->sx.s23.s3.bte;
2759 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2760 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2761 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2762 case ICMD_INVOKEINTERFACE:
2764 REPLACEMENT_POINT_INVOKE(cd, iptr);
2766 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2768 um = iptr->sx.s23.s3.um;
2769 md = um->methodref->parseddesc.md;
2772 lm = iptr->sx.s23.s3.fmiref->p.method;
2774 md = lm->parseddesc;
2778 s3 = md->paramcount;
2780 MCODECHECK((s3 << 1) + 64);
2782 /* copy arguments to registers or stack location */
2784 for (s3 = s3 - 1; s3 >= 0; s3--) {
2785 var = VAR(iptr->sx.s23.s2.args[s3]);
2787 /* Already Preallocated? */
2788 if (var->flags & PREALLOC)
2791 if (IS_INT_LNG_TYPE(var->type)) {
2792 if (!md->params[s3].inmemory) {
2793 if (IS_2_WORD_TYPE(var->type)) {
2795 GET_LOW_REG(md->params[s3].regoff),
2796 GET_HIGH_REG(md->params[s3].regoff)
2798 d = emit_load(jd, iptr, var, s1);
2802 s1 = md->params[s3].regoff;
2803 d = emit_load(jd, iptr, var, s1);
2808 if (IS_2_WORD_TYPE(var->type)) {
2809 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2810 M_LST(d, REG_SP, md->params[s3].regoff);
2813 d = emit_load(jd, iptr, var, REG_ITMP1);
2814 M_IST(d, REG_SP, md->params[s3].regoff);
2819 if (!md->params[s3].inmemory) {
2820 s1 = md->params[s3].regoff;
2821 d = emit_load(jd, iptr, var, s1);
2825 d = emit_load(jd, iptr, var, REG_FTMP1);
2826 if (IS_2_WORD_TYPE(var->type))
2827 M_DST(d, REG_SP, md->params[s3].regoff);
2829 M_FST(d, REG_SP, md->params[s3].regoff);
2834 /* generate method profiling code */
2838 switch (iptr->opc) {
2840 if (bte->stub == NULL)
2841 disp = dseg_add_functionptr(cd, bte->fp);
2843 disp = dseg_add_functionptr(cd, bte->stub);
2845 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2846 if (N_VALID_DSEG_DISP(disp)) {
2847 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2849 N_LHI(REG_ITMP1, disp);
2850 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2854 case ICMD_INVOKESPECIAL:
2856 /* Implicit NULL pointer check */
2857 M_ILD(REG_ITMP1, REG_A0, 0);
2861 case ICMD_INVOKESTATIC:
2863 disp = dseg_add_unique_address(cd, um);
2865 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2869 disp = dseg_add_address(cd, lm->stubroutine);
2871 if (N_VALID_DSEG_DISP(disp)) {
2872 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2874 N_LHI(REG_ITMP1, disp);
2875 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2879 case ICMD_INVOKEVIRTUAL:
2880 /* TODO softnull REG_A0 */
2883 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2888 s1 = OFFSET(vftbl_t, table[0]) +
2889 sizeof(methodptr) * lm->vftblindex;
2892 /* implicit null-pointer check */
2894 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2895 M_ALD(REG_PV, REG_METHODPTR, s1);
2898 case ICMD_INVOKEINTERFACE:
2899 /* TODO softnull REG_A0 */
2901 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2902 * and -0xFFF in index register (itmp1)
2906 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2912 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2913 sizeof(methodptr*) * lm->class->index;
2915 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2918 /* Implicit null-pointer check */
2919 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2920 N_LHI(REG_ITMP1, s1);
2921 N_L(REG_METHODPTR, 0, REG_ITMP1, REG_METHODPTR);
2922 M_ALD(REG_PV, REG_METHODPTR, s2);
2926 /* generate the actual call */
2929 emit_restore_pv(cd);
2931 /* post call finalization */
2933 switch (iptr->opc) {
2935 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
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_notzero(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_ITMP2, ACC_INTERFACE);
3031 if (N_VALID_DSEG_DISP(disp)) {
3032 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3034 ICONST(REG_ITMP3, disp);
3035 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3037 emit_label_beq(cd, LABEL_CLASS);
3040 /* interface checkcast code */
3042 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3043 if (super == NULL) {
3044 patcher_add_patch_ref(jd,
3045 PATCHER_checkcast_instanceof_interface,
3046 iptr->sx.s23.s3.c.ref,
3050 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3053 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3054 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3055 M_ISUB_IMM(superindex, REG_ITMP3);
3056 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3059 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3060 superindex * sizeof(methodptr*))
3062 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3063 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3065 if (super == NULL) {
3066 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3070 /* class checkcast code */
3072 if (super == NULL) {
3073 emit_label(cd, LABEL_CLASS);
3076 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3077 if (super == NULL) {
3078 disp = dseg_add_unique_address(cd, NULL);
3080 patcher_add_patch_ref(jd,
3081 PATCHER_resolve_classref_to_vftbl,
3082 iptr->sx.s23.s3.c.ref,
3086 disp = dseg_add_address(cd, supervftbl);
3088 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3091 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3092 M_ALD_DSEG(REG_ITMP3, disp);
3094 CODEGEN_CRITICAL_SECTION_START;
3096 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3097 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3098 M_ISUB(REG_ITMP3, REG_ITMP2);
3099 M_ALD_DSEG(REG_ITMP3, disp);
3100 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3102 CODEGEN_CRITICAL_SECTION_END;
3104 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3105 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3106 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3107 /* Branch if greater then */
3108 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3111 if (super == NULL) {
3112 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3113 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3114 } else if (super->flags & ACC_INTERFACE) {
3115 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3117 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3120 d = codegen_reg_of_dst(jd, iptr, s1);
3122 # undef LABEL_EXIT_CHECK_NULL
3124 # undef LABEL_EXIT_INTERFACE_NULL
3125 # undef LABEL_EXIT_INTERFACE_DONE
3126 # undef LABEL_EXIT_CLASS_NULL
3129 /* array type cast-check */
3131 s1 = emit_load_s1(jd, iptr, REG_A0);
3132 M_INTMOVE(s1, REG_A0);
3134 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3135 disp = dseg_add_unique_address(cd, NULL);
3137 patcher_add_patch_ref(jd,
3138 PATCHER_resolve_classref_to_classinfo,
3139 iptr->sx.s23.s3.c.ref,
3143 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3145 M_ALD_DSEG(REG_A1, disp);
3146 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3147 M_ALD_DSEG(REG_ITMP1, disp);
3148 M_ASUB_IMM(96, REG_SP);
3149 M_JSR(REG_RA, REG_ITMP1);
3150 M_AADD_IMM(96, REG_SP);
3152 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3153 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3155 d = codegen_reg_of_dst(jd, iptr, s1);
3159 emit_store_dst(jd, iptr, d);
3162 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3163 /* val.a: (classinfo*) superclass */
3165 /* superclass is an interface:
3167 * return (sub != NULL) &&
3168 * (sub->vftbl->interfacetablelength > super->index) &&
3169 * (sub->vftbl->interfacetable[-super->index] != NULL);
3171 * superclass is a class:
3173 * return ((sub != NULL) && (0
3174 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3175 * super->vftbl->diffvall));
3177 * If superclass is unresolved, we include both code snippets
3178 * above, a patcher resolves the class' flags and we select
3179 * the right code at runtime.
3184 vftbl_t *supervftbl;
3187 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3193 super = iptr->sx.s23.s3.c.cls;
3194 superindex = super->index;
3195 supervftbl = super->vftbl;
3198 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3199 # define LABEL_CLASS BRANCH_LABEL_2
3200 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3201 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3202 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3203 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3205 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3206 CODEGEN_CRITICAL_SECTION_NEW;
3208 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3209 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3211 M_MOV(s1, REG_ITMP1);
3215 /* if class is not resolved, check which code to call */
3217 if (super == NULL) {
3221 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3223 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3225 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3226 iptr->sx.s23.s3.c.ref, disp);
3228 ICONST(REG_ITMP2, ACC_INTERFACE);
3230 if (N_VALID_DSEG_DISP(disp)) {
3231 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3233 ICONST(REG_ITMP3, disp);
3234 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3237 emit_label_beq(cd, LABEL_CLASS);
3240 /* interface instanceof code */
3242 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3243 if (super == NULL) {
3244 /* If d == REG_ITMP2, then it's destroyed in check
3249 patcher_add_patch_ref(jd,
3250 PATCHER_checkcast_instanceof_interface,
3251 iptr->sx.s23.s3.c.ref, 0);
3256 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3259 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3260 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3261 M_ISUB_IMM(superindex, REG_ITMP3);
3263 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3267 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3268 superindex * sizeof(methodptr*))
3270 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3272 /* d := (REG_ITMP1 != 0) */
3274 N_LTR(d, REG_ITMP1);
3275 M_BEQ(SZ_BRC + SZ_LHI);
3278 if (super == NULL) {
3279 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3283 /* class instanceof code */
3285 if (super == NULL) {
3286 emit_label(cd, LABEL_CLASS);
3289 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3290 if (super == NULL) {
3291 disp = dseg_add_unique_address(cd, NULL);
3293 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3294 iptr->sx.s23.s3.c.ref,
3298 disp = dseg_add_address(cd, supervftbl);
3303 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3306 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3307 M_ALD_DSEG(REG_ITMP2, disp);
3309 CODEGEN_CRITICAL_SECTION_START;
3311 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3312 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3313 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3315 CODEGEN_CRITICAL_SECTION_END;
3317 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3319 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3321 M_BGT(SZ_BRC + SZ_LHI);
3325 if (super == NULL) {
3326 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3327 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3328 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3329 } else if (super->flags & ACC_INTERFACE) {
3330 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3331 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3333 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3336 # undef LABEL_EXIT_CHECK_NULL
3338 # undef LABEL_EXIT_INTERFACE_NULL
3339 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3340 # undef LABEL_EXIT_INTERFACE_DONE
3341 # undef LABEL_EXIT_CLASS_NULL
3343 emit_store_dst(jd, iptr, d);
3349 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3351 /* check for negative sizes and copy sizes to stack if necessary */
3353 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3356 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3358 /* copy SAVEDVAR sizes to stack */
3359 var = VAR(iptr->sx.s23.s2.args[s1]);
3361 /* Already Preallocated? */
3362 if (!(var->flags & PREALLOC)) {
3363 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3364 M_IST(s2, REG_SP, s1 * 4);
3368 /* is a patcher function set? */
3370 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3371 disp = dseg_add_unique_address(cd, 0);
3373 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3374 iptr->sx.s23.s3.c.ref,
3378 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3380 /* a0 = dimension count */
3382 ICONST(REG_A0, iptr->s1.argcount);
3384 /* a1 = classinfo */
3386 M_ALD_DSEG(REG_A1, disp);
3388 /* a2 = pointer to dimensions = stack pointer */
3390 M_MOV(REG_SP, REG_A2);
3392 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3393 M_ALD_DSEG(REG_ITMP1, disp);
3394 M_ASUB_IMM(96, REG_SP);
3395 M_JSR(REG_RA, REG_ITMP1);
3396 M_AADD_IMM(96, REG_SP);
3398 /* check for exception before result assignment */
3400 emit_exception_check(cd, iptr);
3402 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3403 M_INTMOVE(REG_RESULT, s1);
3404 emit_store_dst(jd, iptr, s1);
3409 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3413 } /* for instruction */
3415 MCODECHECK(512); /* XXX require a lower number? */
3417 /* At the end of a basic block we may have to append some nops,
3418 because the patcher stub calling code might be longer than the
3419 actual instruction. So codepatching does not change the
3420 following block unintentionally. */
3422 if (cd->mcodeptr < cd->lastmcodeptr) {
3423 while (cd->mcodeptr < cd->lastmcodeptr) {
3428 } /* if (bptr -> flags >= BBREACHED) */
3429 } /* for basic block */
3431 dseg_createlinenumbertable(cd);
3433 /* generate stubs */
3435 emit_patcher_traps(jd);
3437 /* everything's ok */
3443 /* codegen_emit_stub_compiler **************************************************
3445 Emits a stub routine which calls the compiler.
3447 *******************************************************************************/
3449 void codegen_emit_stub_compiler(jitdata *jd)
3454 /* get required compiler data */
3459 /* code for the stub */
3461 /* don't touch ITMP3 as it cointains the return address */
3463 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3465 M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */
3466 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3467 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3472 /* codegen_emit_stub_native ****************************************************
3474 Emits a stub routine which calls a native method.
3476 *******************************************************************************/
3479 arguments on stack \
3480 -------------------------------------------------| <- SP on nativestub entry
3482 callee saved int regs (none) |
3483 callee saved float regs (none) | stack frame like in cacao
3484 local variable slots (none) |
3485 arguments for calling methods (none) /
3486 ------------------------------------------------------------------ <- datasp
3491 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3492 0 - 96 register save area for callee /
3493 -------------------------------------------------------- <- SP native method
3495 SP after method entry
3498 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3506 s4 i, j; /* count variables */
3511 /* get required compiler data */
3518 /* initialize variables */
3521 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3523 /* calculate stack frame size */
3525 cd->stackframesize =
3526 1 + /* r14 - return address */ +
3527 ((sizeof(stackframeinfo) + 7) / 8) +
3528 ((sizeof(localref_table) + 7) / 8) +
3530 (INT_ARG_CNT + FLT_ARG_CNT) +
3531 nmd->memuse + /* parameter passing */
3532 (96 / 8) /* required by ABI */;
3534 /* create method header */
3536 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3537 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3538 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3539 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3540 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3541 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3542 (void) dseg_addlinenumbertablesize(cd);
3543 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3545 /* generate stub code */
3547 N_AHI(REG_SP, -(cd->stackframesize * 8));
3548 N_AHI(REG_PV, N_PV_OFFSET);
3550 /* generate native method profiling code */
3552 #if defined(ENABLE_PROFILING)
3553 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3554 /* count frequency */
3555 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
3556 ICONST(REG_ITMP2, 1);
3557 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
3558 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
3562 /* save return address */
3564 N_ST(R14, (cd->stackframesize - 1) * 8, RN, REG_SP);
3566 #if !defined(NDEBUG)
3567 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3568 emit_verbosecall_enter(jd);
3571 /* get function address (this must happen before the stackframeinfo) */
3573 disp = dseg_add_functionptr(cd, f);
3576 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, disp);
3578 M_ILD_DSEG(REG_ITMP1, disp);
3580 j = 96 + (nmd->memuse * 8);
3582 /* todo some arg registers are not volatile in C-abi terms */
3584 /* save integer and float argument registers */
3586 for (i = 0; i < md->paramcount; i++) {
3587 if (! md->params[i].inmemory) {
3588 s1 = md->params[i].regoff;
3589 t = md->paramtypes[i].type;
3591 if (IS_INT_LNG_TYPE(t)) {
3592 if (IS_2_WORD_TYPE(t)) {
3593 /* todo store multiple */
3594 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3595 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3597 N_ST(s1, j, RN, REG_SP);
3600 if (IS_2_WORD_TYPE(t)) {
3601 N_STD(s1, j, RN, REG_SP);
3603 N_STE(s1, j, RN, REG_SP);
3611 N_ST(REG_ITMP1, j, RN, REG_SP);
3613 /* create dynamic stack info */
3615 N_MOV(REG_SP, REG_A0); /* currentsp */
3616 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3618 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3619 M_ILD_DSEG(REG_ITMP1, disp);
3621 M_CALL(REG_ITMP1); /* call */
3623 /* remember class argument */
3625 if (m->flags & ACC_STATIC)
3626 N_LR(REG_ITMP3, REG_RESULT);
3628 /* restore integer and float argument registers */
3630 j = 96 + (nmd->memuse * 8);
3632 for (i = 0; i < md->paramcount; i++) {
3633 if (! md->params[i].inmemory) {
3634 s1 = md->params[i].regoff;
3635 t = md->paramtypes[i].type;
3637 if (IS_INT_LNG_TYPE(t)) {
3638 if (IS_2_WORD_TYPE(t)) {
3639 /* todo load multiple ! */
3640 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3641 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3643 N_L(s1, j, RN, REG_SP);
3646 if (IS_2_WORD_TYPE(t)) {
3647 N_LD(s1, j, RN, REG_SP);
3649 N_LE(s1, j, RN, REG_SP);
3657 N_L(REG_ITMP1, j, RN, REG_SP);
3659 /* copy or spill arguments to new locations */
3661 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3662 t = md->paramtypes[i].type;
3664 if (IS_INT_LNG_TYPE(t)) {
3666 if (!md->params[i].inmemory) {
3668 s1 = md->params[i].regoff;
3670 if (!nmd->params[j].inmemory) {
3671 s2 = nmd->params[j].regoff;
3672 if (IS_2_WORD_TYPE(t)) {
3688 s2 = nmd->params[j].regoff;
3689 if (IS_2_WORD_TYPE(t)) {
3704 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3705 s2 = nmd->params[j].regoff;
3707 if (IS_2_WORD_TYPE(t)) {
3708 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3710 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3715 /* We only copy spilled float arguments, as the float argument */
3716 /* registers keep unchanged. */
3718 if (md->params[i].inmemory) {
3719 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3720 s2 = nmd->params[j].regoff;
3722 if (IS_2_WORD_TYPE(t)) {
3723 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3725 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3731 /* put class into second argument register */
3733 if (m->flags & ACC_STATIC)
3734 M_MOV(REG_ITMP3, REG_A1);
3736 /* put env into first argument register */
3738 disp = dseg_add_address(cd, _Jv_env);
3739 M_ILD_DSEG(REG_A0, disp);
3741 /* do the native function call */
3743 M_CALL(REG_ITMP1); /* call */
3745 /* save return value */
3747 t = md->returntype.type;
3749 if (t != TYPE_VOID) {
3750 if (IS_INT_LNG_TYPE(t)) {
3751 if (IS_2_WORD_TYPE(t)) {
3752 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3754 N_ST(REG_RESULT, 96, RN, REG_SP);
3757 if (IS_2_WORD_TYPE(t)) {
3758 N_STD(REG_FRESULT, 96, RN, REG_SP);
3760 N_STE(REG_FRESULT, 96, RN, REG_SP);
3765 #if !defined(NDEBUG)
3766 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3767 emit_verbosecall_exit(jd);
3770 /* remove native stackframe info */
3772 N_MOV(REG_SP, REG_A0); /* currentsp */
3773 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3774 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3775 M_ALD_DSEG(REG_ITMP1, disp);
3777 N_LR(REG_ITMP3, REG_RESULT);
3779 /* restore return value */
3781 if (t != TYPE_VOID) {
3782 if (IS_INT_LNG_TYPE(t)) {
3783 if (IS_2_WORD_TYPE(t)) {
3784 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3786 N_L(REG_RESULT, 96, RN, REG_SP);
3789 if (IS_2_WORD_TYPE(t)) {
3790 N_LD(REG_FRESULT, 96, RN, REG_SP);
3792 N_LE(REG_FRESULT, 96, RN, REG_SP);
3797 /* load return address */
3799 N_L(REG_ITMP2, (cd->stackframesize - 1) * 8, RN, REG_SP);
3801 /* remove stackframe */
3803 N_AHI(REG_SP, cd->stackframesize * 8);
3805 /* test for exception */
3807 N_LTR(REG_ITMP3, REG_ITMP3);
3808 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3812 N_BCR(DD_ANY, REG_ITMP2);
3814 /* handle exception */
3816 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3817 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3821 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3824 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3825 M_ALD_DSEG(REG_ITMP3, disp);
3826 M_JMP(RN, REG_ITMP3);
3828 /* generate patcher stubs */
3830 emit_patcher_traps(jd);
3833 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3834 codegendata *cd = jd->cd;
3835 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3837 M_MOV(reg, tempregnum);
3845 * These are local overrides for various environment variables in Emacs.
3846 * Please do not remove this and leave it at the end of the file, where
3847 * Emacs will automagically detect them.
3848 * ---------------------------------------------------------------------
3851 * indent-tabs-mode: t
3855 * vim:noexpandtab:sw=4:ts=4: