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 disp = dseg_add_functionptr(cd, bte->fp);
2842 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2843 if (N_VALID_DSEG_DISP(disp)) {
2844 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2846 N_LHI(REG_ITMP1, disp);
2847 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2851 case ICMD_INVOKESPECIAL:
2853 /* Implicit NULL pointer check */
2854 M_ILD(REG_ITMP1, REG_A0, 0);
2858 case ICMD_INVOKESTATIC:
2860 disp = dseg_add_unique_address(cd, um);
2862 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2866 disp = dseg_add_address(cd, lm->stubroutine);
2868 if (N_VALID_DSEG_DISP(disp)) {
2869 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2871 N_LHI(REG_ITMP1, disp);
2872 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2876 case ICMD_INVOKEVIRTUAL:
2877 /* TODO softnull REG_A0 */
2880 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2885 s1 = OFFSET(vftbl_t, table[0]) +
2886 sizeof(methodptr) * lm->vftblindex;
2889 /* implicit null-pointer check */
2891 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2892 M_ALD(REG_PV, REG_METHODPTR, s1);
2895 case ICMD_INVOKEINTERFACE:
2896 /* TODO softnull REG_A0 */
2898 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2899 * and -0xFFF in index register (itmp1)
2903 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2909 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2910 sizeof(methodptr*) * lm->class->index;
2912 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2915 /* Implicit null-pointer check */
2916 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2917 N_LHI(REG_ITMP1, s1);
2918 N_L(REG_METHODPTR, 0, REG_ITMP1, REG_METHODPTR);
2919 M_ALD(REG_PV, REG_METHODPTR, s2);
2923 /* generate the actual call */
2926 emit_restore_pv(cd);
2928 /* post call finalization */
2930 switch (iptr->opc) {
2932 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2933 emit_exception_check(cd, iptr); /* check for exception */
2937 /* generate method profiling code */
2939 PROFILE_CYCLE_START;
2941 /* store size of call code in replacement point */
2943 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2945 /* store return value */
2947 d = md->returntype.type;
2949 if (d != TYPE_VOID) {
2950 if (IS_INT_LNG_TYPE(d)) {
2951 if (IS_2_WORD_TYPE(d)) {
2952 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2953 M_LNGMOVE(REG_RESULT_PACKED, s1);
2956 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2957 M_INTMOVE(REG_RESULT, s1);
2961 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2962 M_FLTMOVE(REG_FRESULT, s1);
2964 emit_store_dst(jd, iptr, s1);
2970 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2972 /* val.a: (classinfo*) superclass */
2974 /* superclass is an interface:
2976 * OK if ((sub == NULL) ||
2977 * (sub->vftbl->interfacetablelength > super->index) &&
2978 * (sub->vftbl->interfacetable[-super->index] != NULL));
2980 * superclass is a class:
2982 * OK if ((sub == NULL) || (0
2983 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2984 * super->vftbl->diffval));
2987 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2988 /* object type cast-check */
2991 vftbl_t *supervftbl;
2994 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2995 # define LABEL_CLASS BRANCH_LABEL_2
2996 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2997 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2998 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
3000 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3006 super = iptr->sx.s23.s3.c.cls;
3007 superindex = super->index;
3008 supervftbl = super->vftbl;
3011 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3012 CODEGEN_CRITICAL_SECTION_NEW;
3014 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3016 /* if class is not resolved, check which code to call */
3018 if (super == NULL) {
3020 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3022 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3024 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3025 iptr->sx.s23.s3.c.ref,
3028 ICONST(REG_ITMP2, ACC_INTERFACE);
3029 if (N_VALID_DSEG_DISP(disp)) {
3030 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3032 ICONST(REG_ITMP3, disp);
3033 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3035 emit_label_beq(cd, LABEL_CLASS);
3038 /* interface checkcast code */
3040 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3041 if (super == NULL) {
3042 patcher_add_patch_ref(jd,
3043 PATCHER_checkcast_instanceof_interface,
3044 iptr->sx.s23.s3.c.ref,
3048 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3051 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3052 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3053 M_ISUB_IMM(superindex, REG_ITMP3);
3054 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3057 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3058 superindex * sizeof(methodptr*))
3060 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3061 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3063 if (super == NULL) {
3064 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3068 /* class checkcast code */
3070 if (super == NULL) {
3071 emit_label(cd, LABEL_CLASS);
3074 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3075 if (super == NULL) {
3076 disp = dseg_add_unique_address(cd, NULL);
3078 patcher_add_patch_ref(jd,
3079 PATCHER_resolve_classref_to_vftbl,
3080 iptr->sx.s23.s3.c.ref,
3084 disp = dseg_add_address(cd, supervftbl);
3086 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3089 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3090 M_ALD_DSEG(REG_ITMP3, disp);
3092 CODEGEN_CRITICAL_SECTION_START;
3094 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3095 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3096 M_ISUB(REG_ITMP3, REG_ITMP2);
3097 M_ALD_DSEG(REG_ITMP3, disp);
3098 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3100 CODEGEN_CRITICAL_SECTION_END;
3102 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3103 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3104 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3105 /* Branch if greater then */
3106 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3109 if (super == NULL) {
3110 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3111 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3112 } else if (super->flags & ACC_INTERFACE) {
3113 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3115 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3118 d = codegen_reg_of_dst(jd, iptr, s1);
3120 # undef LABEL_EXIT_CHECK_NULL
3122 # undef LABEL_EXIT_INTERFACE_NULL
3123 # undef LABEL_EXIT_INTERFACE_DONE
3124 # undef LABEL_EXIT_CLASS_NULL
3127 /* array type cast-check */
3129 s1 = emit_load_s1(jd, iptr, REG_A0);
3130 M_INTMOVE(s1, REG_A0);
3132 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3133 disp = dseg_add_unique_address(cd, NULL);
3135 patcher_add_patch_ref(jd,
3136 PATCHER_resolve_classref_to_classinfo,
3137 iptr->sx.s23.s3.c.ref,
3141 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3143 M_ALD_DSEG(REG_A1, disp);
3144 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3145 M_ALD_DSEG(REG_ITMP1, disp);
3146 M_ASUB_IMM(96, REG_SP);
3147 M_JSR(REG_RA, REG_ITMP1);
3148 M_AADD_IMM(96, REG_SP);
3150 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3151 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3153 d = codegen_reg_of_dst(jd, iptr, s1);
3157 emit_store_dst(jd, iptr, d);
3160 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3161 /* val.a: (classinfo*) superclass */
3163 /* superclass is an interface:
3165 * return (sub != NULL) &&
3166 * (sub->vftbl->interfacetablelength > super->index) &&
3167 * (sub->vftbl->interfacetable[-super->index] != NULL);
3169 * superclass is a class:
3171 * return ((sub != NULL) && (0
3172 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3173 * super->vftbl->diffvall));
3175 * If superclass is unresolved, we include both code snippets
3176 * above, a patcher resolves the class' flags and we select
3177 * the right code at runtime.
3182 vftbl_t *supervftbl;
3185 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3191 super = iptr->sx.s23.s3.c.cls;
3192 superindex = super->index;
3193 supervftbl = super->vftbl;
3196 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3197 # define LABEL_CLASS BRANCH_LABEL_2
3198 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3199 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3200 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3201 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3203 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3204 CODEGEN_CRITICAL_SECTION_NEW;
3206 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3207 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3209 M_MOV(s1, REG_ITMP1);
3213 /* if class is not resolved, check which code to call */
3215 if (super == NULL) {
3219 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3221 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3223 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3224 iptr->sx.s23.s3.c.ref, disp);
3226 ICONST(REG_ITMP2, ACC_INTERFACE);
3228 if (N_VALID_DSEG_DISP(disp)) {
3229 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3231 ICONST(REG_ITMP3, disp);
3232 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3235 emit_label_beq(cd, LABEL_CLASS);
3238 /* interface instanceof code */
3240 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3241 if (super == NULL) {
3242 /* If d == REG_ITMP2, then it's destroyed in check
3247 patcher_add_patch_ref(jd,
3248 PATCHER_checkcast_instanceof_interface,
3249 iptr->sx.s23.s3.c.ref, 0);
3254 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3257 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3258 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3259 M_ISUB_IMM(superindex, REG_ITMP3);
3261 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3265 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3266 superindex * sizeof(methodptr*))
3268 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3270 /* d := (REG_ITMP1 != 0) */
3272 N_LTR(d, REG_ITMP1);
3273 M_BEQ(SZ_BRC + SZ_LHI);
3276 if (super == NULL) {
3277 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3281 /* class instanceof code */
3283 if (super == NULL) {
3284 emit_label(cd, LABEL_CLASS);
3287 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3288 if (super == NULL) {
3289 disp = dseg_add_unique_address(cd, NULL);
3291 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3292 iptr->sx.s23.s3.c.ref,
3296 disp = dseg_add_address(cd, supervftbl);
3301 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3304 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3305 M_ALD_DSEG(REG_ITMP2, disp);
3307 CODEGEN_CRITICAL_SECTION_START;
3309 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3310 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3311 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3313 CODEGEN_CRITICAL_SECTION_END;
3315 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3317 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3319 M_BGT(SZ_BRC + SZ_LHI);
3323 if (super == NULL) {
3324 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3325 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3326 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3327 } else if (super->flags & ACC_INTERFACE) {
3328 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3329 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3331 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3334 # undef LABEL_EXIT_CHECK_NULL
3336 # undef LABEL_EXIT_INTERFACE_NULL
3337 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3338 # undef LABEL_EXIT_INTERFACE_DONE
3339 # undef LABEL_EXIT_CLASS_NULL
3341 emit_store_dst(jd, iptr, d);
3347 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3349 /* check for negative sizes and copy sizes to stack if necessary */
3351 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3354 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3356 /* copy SAVEDVAR sizes to stack */
3357 var = VAR(iptr->sx.s23.s2.args[s1]);
3359 /* Already Preallocated? */
3360 if (!(var->flags & PREALLOC)) {
3361 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3362 M_IST(s2, REG_SP, s1 * 4);
3366 /* is a patcher function set? */
3368 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3369 disp = dseg_add_unique_address(cd, 0);
3371 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3372 iptr->sx.s23.s3.c.ref,
3376 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3378 /* a0 = dimension count */
3380 ICONST(REG_A0, iptr->s1.argcount);
3382 /* a1 = classinfo */
3384 M_ALD_DSEG(REG_A1, disp);
3386 /* a2 = pointer to dimensions = stack pointer */
3388 M_MOV(REG_SP, REG_A2);
3390 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3391 M_ALD_DSEG(REG_ITMP1, disp);
3392 M_ASUB_IMM(96, REG_SP);
3393 M_JSR(REG_RA, REG_ITMP1);
3394 M_AADD_IMM(96, REG_SP);
3396 /* check for exception before result assignment */
3398 emit_exception_check(cd, iptr);
3400 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3401 M_INTMOVE(REG_RESULT, s1);
3402 emit_store_dst(jd, iptr, s1);
3407 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3411 } /* for instruction */
3413 MCODECHECK(512); /* XXX require a lower number? */
3415 /* At the end of a basic block we may have to append some nops,
3416 because the patcher stub calling code might be longer than the
3417 actual instruction. So codepatching does not change the
3418 following block unintentionally. */
3420 if (cd->mcodeptr < cd->lastmcodeptr) {
3421 while (cd->mcodeptr < cd->lastmcodeptr) {
3426 } /* if (bptr -> flags >= BBREACHED) */
3427 } /* for basic block */
3429 dseg_createlinenumbertable(cd);
3431 /* generate stubs */
3433 emit_patcher_traps(jd);
3435 /* everything's ok */
3441 /* codegen_emit_stub_compiler **************************************************
3443 Emits a stub routine which calls the compiler.
3445 *******************************************************************************/
3447 void codegen_emit_stub_compiler(jitdata *jd)
3452 /* get required compiler data */
3457 /* code for the stub */
3459 /* don't touch ITMP3 as it cointains the return address */
3461 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3463 M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */
3464 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3465 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3470 /* codegen_emit_stub_native ****************************************************
3472 Emits a stub routine which calls a native method.
3474 *******************************************************************************/
3477 arguments on stack \
3478 -------------------------------------------------| <- SP on nativestub entry
3480 callee saved int regs (none) |
3481 callee saved float regs (none) | stack frame like in cacao
3482 local variable slots (none) |
3483 arguments for calling methods (none) /
3484 ------------------------------------------------------------------ <- datasp
3489 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3490 0 - 96 register save area for callee /
3491 -------------------------------------------------------- <- SP native method
3493 SP after method entry
3496 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3504 s4 i, j; /* count variables */
3509 /* get required compiler data */
3516 /* initialize variables */
3519 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3521 /* calculate stack frame size */
3523 cd->stackframesize =
3524 1 + /* r14 - return address */ +
3525 ((sizeof(stackframeinfo) + 7) / 8) +
3526 ((sizeof(localref_table) + 7) / 8) +
3528 (INT_ARG_CNT + FLT_ARG_CNT) +
3529 nmd->memuse + /* parameter passing */
3530 (96 / 8) /* required by ABI */;
3532 /* create method header */
3534 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3535 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3536 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3537 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3538 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3539 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3540 (void) dseg_addlinenumbertablesize(cd);
3541 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3543 /* generate stub code */
3545 N_AHI(REG_SP, -(cd->stackframesize * 8));
3546 N_AHI(REG_PV, N_PV_OFFSET);
3548 /* generate native method profiling code */
3550 #if defined(ENABLE_PROFILING)
3551 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3552 /* count frequency */
3553 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
3554 ICONST(REG_ITMP2, 1);
3555 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
3556 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
3560 /* save return address */
3562 N_ST(R14, (cd->stackframesize - 1) * 8, RN, REG_SP);
3564 #if !defined(NDEBUG)
3565 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3566 emit_verbosecall_enter(jd);
3569 /* get function address (this must happen before the stackframeinfo) */
3571 disp = dseg_add_functionptr(cd, f);
3574 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, disp);
3576 M_ILD_DSEG(REG_ITMP1, disp);
3578 j = 96 + (nmd->memuse * 8);
3580 /* todo some arg registers are not volatile in C-abi terms */
3582 /* save integer and float argument registers */
3584 for (i = 0; i < md->paramcount; i++) {
3585 if (! md->params[i].inmemory) {
3586 s1 = md->params[i].regoff;
3587 t = md->paramtypes[i].type;
3589 if (IS_INT_LNG_TYPE(t)) {
3590 if (IS_2_WORD_TYPE(t)) {
3591 /* todo store multiple */
3592 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3593 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3595 N_ST(s1, j, RN, REG_SP);
3598 if (IS_2_WORD_TYPE(t)) {
3599 N_STD(s1, j, RN, REG_SP);
3601 N_STE(s1, j, RN, REG_SP);
3609 N_ST(REG_ITMP1, j, RN, REG_SP);
3611 /* create dynamic stack info */
3613 N_MOV(REG_SP, REG_A0); /* currentsp */
3614 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3616 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3617 M_ILD_DSEG(REG_ITMP1, disp);
3619 M_CALL(REG_ITMP1); /* call */
3621 /* remember class argument */
3623 if (m->flags & ACC_STATIC)
3624 N_LR(REG_ITMP3, REG_RESULT);
3626 /* restore integer and float argument registers */
3628 j = 96 + (nmd->memuse * 8);
3630 for (i = 0; i < md->paramcount; i++) {
3631 if (! md->params[i].inmemory) {
3632 s1 = md->params[i].regoff;
3633 t = md->paramtypes[i].type;
3635 if (IS_INT_LNG_TYPE(t)) {
3636 if (IS_2_WORD_TYPE(t)) {
3637 /* todo load multiple ! */
3638 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3639 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3641 N_L(s1, j, RN, REG_SP);
3644 if (IS_2_WORD_TYPE(t)) {
3645 N_LD(s1, j, RN, REG_SP);
3647 N_LE(s1, j, RN, REG_SP);
3655 N_L(REG_ITMP1, j, RN, REG_SP);
3657 /* copy or spill arguments to new locations */
3659 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3660 t = md->paramtypes[i].type;
3662 if (IS_INT_LNG_TYPE(t)) {
3664 if (!md->params[i].inmemory) {
3666 s1 = md->params[i].regoff;
3668 if (!nmd->params[j].inmemory) {
3669 s2 = nmd->params[j].regoff;
3670 if (IS_2_WORD_TYPE(t)) {
3686 s2 = nmd->params[j].regoff;
3687 if (IS_2_WORD_TYPE(t)) {
3702 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3703 s2 = nmd->params[j].regoff;
3705 if (IS_2_WORD_TYPE(t)) {
3706 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3708 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3713 /* We only copy spilled float arguments, as the float argument */
3714 /* registers keep unchanged. */
3716 if (md->params[i].inmemory) {
3717 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3718 s2 = nmd->params[j].regoff;
3720 if (IS_2_WORD_TYPE(t)) {
3721 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3723 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3729 /* put class into second argument register */
3731 if (m->flags & ACC_STATIC)
3732 M_MOV(REG_ITMP3, REG_A1);
3734 /* put env into first argument register */
3736 disp = dseg_add_address(cd, _Jv_env);
3737 M_ILD_DSEG(REG_A0, disp);
3739 /* do the native function call */
3741 M_CALL(REG_ITMP1); /* call */
3743 /* save return value */
3745 t = md->returntype.type;
3747 if (t != TYPE_VOID) {
3748 if (IS_INT_LNG_TYPE(t)) {
3749 if (IS_2_WORD_TYPE(t)) {
3750 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3752 N_ST(REG_RESULT, 96, RN, REG_SP);
3755 if (IS_2_WORD_TYPE(t)) {
3756 N_STD(REG_FRESULT, 96, RN, REG_SP);
3758 N_STE(REG_FRESULT, 96, RN, REG_SP);
3763 #if !defined(NDEBUG)
3764 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3765 emit_verbosecall_exit(jd);
3768 /* remove native stackframe info */
3770 N_MOV(REG_SP, REG_A0); /* currentsp */
3771 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3772 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3773 M_ALD_DSEG(REG_ITMP1, disp);
3775 N_LR(REG_ITMP3, REG_RESULT);
3777 /* restore return value */
3779 if (t != TYPE_VOID) {
3780 if (IS_INT_LNG_TYPE(t)) {
3781 if (IS_2_WORD_TYPE(t)) {
3782 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3784 N_L(REG_RESULT, 96, RN, REG_SP);
3787 if (IS_2_WORD_TYPE(t)) {
3788 N_LD(REG_FRESULT, 96, RN, REG_SP);
3790 N_LE(REG_FRESULT, 96, RN, REG_SP);
3795 /* load return address */
3797 N_L(REG_ITMP2, (cd->stackframesize - 1) * 8, RN, REG_SP);
3799 /* remove stackframe */
3801 N_AHI(REG_SP, cd->stackframesize * 8);
3803 /* test for exception */
3805 N_LTR(REG_ITMP3, REG_ITMP3);
3806 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3810 N_BCR(DD_ANY, REG_ITMP2);
3812 /* handle exception */
3814 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3815 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3819 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3822 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3823 M_ALD_DSEG(REG_ITMP3, disp);
3824 M_JMP(RN, REG_ITMP3);
3826 /* generate patcher stubs */
3828 emit_patcher_traps(jd);
3831 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3832 codegendata *cd = jd->cd;
3833 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3835 M_MOV(reg, tempregnum);
3843 * These are local overrides for various environment variables in Emacs.
3844 * Please do not remove this and leave it at the end of the file, where
3845 * Emacs will automagically detect them.
3846 * ---------------------------------------------------------------------
3849 * indent-tabs-mode: t
3853 * vim:noexpandtab:sw=4:ts=4: