1 /* src/vm/jit/s390/codegen.c - machine code generator for s390
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: codegen.c 8296 2007-08-11 22:38:38Z pm $
36 #include "native/jni.h"
37 #include "native/native.h"
39 #include "mm/memory.h"
41 #if defined(ENABLE_THREADS)
42 # include "threads/lock-common.h"
43 # include "threads/native/lock.h"
46 #include "vmcore/loader.h"
47 #include "vmcore/options.h"
48 #include "vmcore/statistics.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
52 #include "vm/jit/abi.h"
53 #if defined(ENABLE_LSRA)
54 # include "vm/jit/allocator/lsra.h"
56 #include "vm/jit/asmpart.h"
57 #include "vm/jit/codegen-common.h"
58 #include "vm/jit/dseg.h"
59 #include "vm/jit/emit-common.h"
60 #include "vm/jit/jit.h"
61 #include "vm/jit/methodheader.h"
62 #include "vm/jit/parse.h"
63 #include "vm/jit/patcher-common.h"
64 #include "vm/jit/reg.h"
65 #include "vm/jit/replace.h"
66 #include "vm/jit/s390/arch.h"
67 #include "vm/jit/s390/codegen.h"
68 #include "vm/jit/s390/emit.h"
69 #include "vm/jit/s390/md-abi.h"
70 #include "vm/jit/stacktrace.h"
72 #include "vm/stringlocal.h"
75 /* DO__LOG generates a call to do__log. No registers are destroyed,
76 * so you may use it anywhere. regs is an array containing all general
80 static void do__log(u4 *regs) {
81 /* insert stuff here */
85 N_AHI(REG_SP, -200); \
86 N_STM(R0, R15, 96, REG_SP); \
87 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
88 N_LA(R2, 96, RN, REG_SP); \
90 N_LM(R0, R15, 96, REG_SP); \
93 #define SUPPORT_HERCULES 1
95 /* codegen *********************************************************************
97 Generates machine code.
99 *******************************************************************************/
103 Layout of stackframe:
106 ===============================================================================
107 return_address (stackframesize - 1) * 8
108 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
110 saved_int_reg[rd->savintreguse]
111 saved_flt_reg[FLT_SAV_CNT - 1]
113 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
115 return_value_tmp (rd->memuse + 1) * 8
116 monitorenter_argument (rd->memuse) * 8
118 local[rd->memuse - 1] (rd->memuse - 1) * 8
126 bool codegen_emit(jitdata *jd)
132 s4 len, s1, s2, s3, d, dd, disp;
135 varinfo *var, *var1, *var2, *dst;
139 constant_classref *cr;
140 unresolved_class *uc;
141 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
142 unresolved_method *um;
143 builtintable_entry *bte;
146 unresolved_field *uf;
149 rplpoint *replacementpoint;
153 /* get required compiler data */
160 /* prevent compiler warnings */
173 /* space to save used callee saved registers */
175 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
176 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
178 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
181 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
184 #if defined(ENABLE_THREADS)
185 /* Space to save argument of monitor_enter and Return Values to
186 survive monitor_exit. The stack position for the argument can
187 not be shared with place to save the return register
188 since both values reside in R2. */
190 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
191 /* 1 slot space to save argument of monitor_enter */
192 /* 1 slot to temporary store return value before monitor_exit */
193 cd->stackframesize += 2;
197 /* Keep stack of non-leaf functions 16-byte aligned for calls into
198 native code e.g. libc or jni (alignment problems with
201 if (!jd->isleafmethod || opt_verbosecall )
202 /* TODO really 16 bytes ? */
203 cd->stackframesize = (cd->stackframesize + 2) & ~2;
205 /* create method header */
207 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
208 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
210 #if defined(ENABLE_THREADS)
211 /* IsSync contains the offset relative to the stack pointer for the
212 argument of monitor_exit used in the exception handler. Since the
213 offset could be zero and give a wrong meaning of the flag it is
217 if (checksync && (m->flags & ACC_SYNCHRONIZED))
218 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync */
221 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
223 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
224 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
225 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
227 (void) dseg_addlinenumbertablesize(cd);
229 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
231 /* create exception table */
233 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
234 dseg_add_target(cd, ex->start);
235 dseg_add_target(cd, ex->end);
236 dseg_add_target(cd, ex->handler);
237 (void) dseg_add_unique_address(cd, ex->catchtype.any);
242 M_AADD_IMM(N_PV_OFFSET, REG_PV);
244 /* generate method profiling code */
246 #if defined(ENABLE_PROFILING)
247 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
248 /* count frequency */
249 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
250 ICONST(REG_ITMP2, 1);
251 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
252 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
258 /* create stack frame (if necessary) */
260 if (cd->stackframesize)
261 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
263 /* save used callee saved registers and return address */
265 p = cd->stackframesize;
266 p--; M_AST(REG_RA, REG_SP, p * 8);
268 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
269 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
271 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
272 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
275 /* take arguments out of register or stack frame */
279 for (p = 0, l = 0; p < md->paramcount; p++) {
280 t = md->paramtypes[p].type;
281 varindex = jd->local_map[l * 5 + t];
285 if (IS_2_WORD_TYPE(t))
288 if (varindex == UNUSED)
293 s1 = md->params[p].regoff;
295 if (IS_INT_LNG_TYPE(t)) { /* integer args */
296 if (IS_2_WORD_TYPE(t)) {
304 if (!md->params[p].inmemory) { /* register arguments */
305 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
306 if (IS_2_WORD_TYPE(t)) {
307 M_LNGMOVE(s2, var->vv.regoff);
309 M_INTMOVE(s2, var->vv.regoff);
311 } else { /* reg arg -> spilled */
312 if (IS_2_WORD_TYPE(t)) {
313 M_LST(s2, REG_SP, var->vv.regoff);
315 M_IST(s2, REG_SP, var->vv.regoff);
319 } else { /* stack arguments */
320 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
321 if (IS_2_WORD_TYPE(t)) {
322 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
324 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
326 } else { /* stack arg -> spilled */
327 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
331 } else { /* floating args */
332 if (!md->params[p].inmemory) { /* register arguments */
334 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
335 M_FLTMOVE(s2, var->vv.regoff);
337 } else { /* reg arg -> spilled */
338 if (IS_2_WORD_TYPE(t))
339 M_DST(s2, REG_SP, var->vv.regoff);
341 M_FST(s2, REG_SP, var->vv.regoff);
344 } else { /* stack arguments */
345 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
346 if (IS_2_WORD_TYPE(t))
347 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
350 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
352 } else { /* stack-arg -> spilled */
353 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
354 var->vv.regoff = cd->stackframesize * 8 + s1;
360 /* save monitorenter argument */
362 #if defined(ENABLE_THREADS)
363 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
364 /* stack offset for monitor argument */
369 if (opt_verbosecall) {
370 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
372 for (p = 0; p < INT_ARG_CNT; p++)
373 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
375 for (p = 0; p < FLT_ARG_CNT; p++)
376 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
378 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
382 /* decide which monitor enter function to call */
384 if (m->flags & ACC_STATIC) {
385 disp = dseg_add_address(cd, &m->class->object.header);
386 M_ALD_DSEG(REG_A0, disp);
390 M_BNE(SZ_BRC + SZ_ILL);
391 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
394 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
395 M_ALD_DSEG(REG_ITMP3, disp);
397 M_AST(REG_A0, REG_SP, s1 * 8);
399 M_ASUB_IMM(96, REG_SP);
401 M_AADD_IMM(96, REG_SP);
404 if (opt_verbosecall) {
405 for (p = 0; p < INT_ARG_CNT; p++)
406 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
408 for (p = 0; p < FLT_ARG_CNT; p++)
409 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
411 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
418 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
419 emit_verbosecall_enter(jd);
420 #endif /* !defined(NDEBUG) */
424 /* end of header generation */
426 /* create replacement points */
428 REPLACEMENT_POINTS_INIT(cd, jd);
430 /* walk through all basic blocks */
432 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
434 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
436 if (bptr->flags >= BBREACHED) {
438 /* branch resolving */
440 codegen_resolve_branchrefs(cd, bptr);
442 /* handle replacement points */
444 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
446 /* copy interface registers to their destination */
451 #if defined(ENABLE_PROFILING)
452 /* generate basicblock profiling code */
454 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
455 /* count frequency */
457 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
458 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
459 ICONST(REG_ITMP2, 1);
460 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
461 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
463 /* if this is an exception handler, start profiling again */
465 if (bptr->type == BBTYPE_EXH)
470 #if defined(ENABLE_LSRA)
474 src = bptr->invars[len];
475 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
476 if (bptr->type == BBTYPE_EXH) {
477 /* d = reg_of_var(rd, src, REG_ITMP1); */
478 if (!IS_INMEMORY(src->flags))
482 M_INTMOVE(REG_ITMP1, d);
483 emit_store(jd, NULL, src, d);
493 var = VAR(bptr->invars[len]);
494 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
495 if (bptr->type == BBTYPE_EXH) {
496 d = codegen_reg_of_var(0, var, REG_ITMP1);
497 M_INTMOVE(REG_ITMP1, d);
498 emit_store(jd, NULL, var, d);
502 assert((var->flags & INOUT));
505 #if defined(ENABLE_LSRA)
508 /* walk through all instructions */
513 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
514 if (iptr->line != currentline) {
515 dseg_addlinenumber(cd, iptr->line);
516 currentline = iptr->line;
519 MCODECHECK(1024); /* 1KB should be enough */
522 case ICMD_NOP: /* ... ==> ... */
523 case ICMD_POP: /* ..., value ==> ... */
524 case ICMD_POP2: /* ..., value, value ==> ... */
527 case ICMD_INLINE_START:
529 REPLACEMENT_POINT_INLINE_START(cd, iptr);
532 case ICMD_INLINE_BODY:
534 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
535 dseg_addlinenumber_inline_start(cd, iptr);
536 dseg_addlinenumber(cd, iptr->line);
539 case ICMD_INLINE_END:
541 dseg_addlinenumber_inline_end(cd, iptr);
542 dseg_addlinenumber(cd, iptr->line);
545 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
546 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
547 emit_nullpointer_check(cd, iptr, s1);
550 /* constant operations ************************************************/
552 case ICMD_ICONST: /* ... ==> ..., constant */
553 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
554 ICONST(d, iptr->sx.val.i);
555 emit_store_dst(jd, iptr, d);
558 case ICMD_LCONST: /* ... ==> ..., constant */
560 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
561 LCONST(d, iptr->sx.val.l);
562 emit_store_dst(jd, iptr, d);
565 case ICMD_FCONST: /* ... ==> ..., constant */
566 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
567 disp = dseg_add_float(cd, iptr->sx.val.f);
568 M_FLD_DSEG(d, disp, REG_ITMP1);
569 emit_store_dst(jd, iptr, d);
572 case ICMD_DCONST: /* ... ==> ..., constant */
573 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
574 disp = dseg_add_double(cd, iptr->sx.val.d);
575 M_DLD_DSEG(d, disp, REG_ITMP1);
576 emit_store_dst(jd, iptr, d);
579 case ICMD_ACONST: /* ... ==> ..., constant */
580 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
582 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
583 cr = iptr->sx.val.c.ref;
584 disp = dseg_add_unique_address(cd, cr);
586 /* PROFILE_CYCLE_STOP; */
588 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
591 /* PROFILE_CYCLE_START; */
595 if (iptr->sx.val.anyptr == 0) {
598 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
602 emit_store_dst(jd, iptr, d);
606 /* load/store/copy/move operations ************************************/
608 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
609 case ICMD_ALOAD: /* s1 = local variable */
613 case ICMD_ISTORE: /* ..., value ==> ... */
624 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
628 /* integer operations *************************************************/
630 case ICMD_INEG: /* ..., value ==> ..., - value */
632 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
633 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
635 emit_store_dst(jd, iptr, d);
639 case ICMD_LNEG: /* ..., value ==> ..., - value */
641 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
642 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
643 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
644 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
645 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
646 N_AHI(GET_HIGH_REG(d), -1);
647 emit_store_dst(jd, iptr, d);
650 case ICMD_I2L: /* ..., value ==> ..., value */
652 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
653 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
655 M_INTMOVE(s1, GET_HIGH_REG(d));
656 ICONST(GET_LOW_REG(d), 0);
657 M_SRDA_IMM(32, GET_HIGH_REG(d));
659 emit_copy_dst(jd, iptr, d);
660 emit_store_dst(jd, iptr, d);
661 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
665 case ICMD_L2I: /* ..., value ==> ..., value */
666 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
667 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
668 M_INTMOVE(GET_LOW_REG(s1), d);
669 emit_store_dst(jd, iptr, d);
672 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
673 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
674 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
678 emit_store_dst(jd, iptr, d);
681 case ICMD_INT2CHAR: /* ..., 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_INT2SHORT: /* ..., value ==> ..., value */
692 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
693 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
697 emit_store_dst(jd, iptr, d);
700 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
702 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
703 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
704 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
711 emit_store_dst(jd, iptr, d);
716 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
717 /* sx.val.i = constant */
718 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
719 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
722 if (N_VALID_IMM(iptr->sx.val.i)) {
723 M_IADD_IMM(iptr->sx.val.i, d);
725 ICONST(REG_ITMP2, iptr->sx.val.i);
726 M_IADD(REG_ITMP2, d);
728 emit_store_dst(jd, iptr, d);
731 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
733 /* M, (r, q) -> (r, q) */
735 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
737 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
738 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
739 dd = GET_HIGH_REG(d);
748 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
749 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
759 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
760 N_AHI(GET_HIGH_REG(d), 1);
762 emit_store_dst(jd, iptr, d);
765 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
766 /* sx.val.l = constant */
768 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
769 dd = GET_HIGH_REG(d);
771 s1 = emit_load_s1_high(jd, iptr, dd);
772 s3 = iptr->sx.val.l >> 32;
776 if (N_VALID_IMM(s3)) {
779 ICONST(REG_ITMP3, s3);
780 M_IADD(REG_ITMP3, dd);
784 s1 = emit_load_s1_low(jd, iptr, dd);
785 s3 = iptr->sx.val.l & 0xffffffff;
786 ICONST(REG_ITMP3, s3);
789 N_ALR(dd, REG_ITMP3);
791 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
792 N_AHI(GET_HIGH_REG(d), 1);
794 emit_store_dst(jd, iptr, d);
797 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
799 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
800 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
801 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
803 M_INTMOVE(s1, REG_ITMP1);
804 M_ISUB(s2, REG_ITMP1);
805 M_INTMOVE(REG_ITMP1, d);
810 emit_store_dst(jd, iptr, d);
814 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
815 /* sx.val.i = constant */
817 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
818 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
821 if (N_VALID_IMM(-iptr->sx.val.i)) {
822 M_ISUB_IMM(iptr->sx.val.i, d);
824 ICONST(REG_ITMP2, iptr->sx.val.i);
825 M_ISUB(REG_ITMP2, d);
827 emit_store_dst(jd, iptr, d);
831 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
833 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
835 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
836 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
837 dd = GET_HIGH_REG(d);
840 M_INTMOVE(s2, REG_ITMP3);
847 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
848 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
852 M_INTMOVE(s2, REG_ITMP3);
859 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
860 N_AHI(GET_HIGH_REG(d), -1);
862 emit_store_dst(jd, iptr, d);
865 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
866 /* sx.val.l = constant */
868 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
870 dd = GET_HIGH_REG(d);
871 s1 = emit_load_s1_high(jd, iptr, dd);
872 s3 = iptr->sx.val.l >> 32;
876 if (N_VALID_IMM(-s3)) {
879 ICONST(REG_ITMP3, s3);
880 M_ISUB(REG_ITMP3, dd);
884 s1 = emit_load_s1_low(jd, iptr, dd);
885 s3 = iptr->sx.val.l & 0xffffffff;
886 ICONST(REG_ITMP3, s3);
889 N_SLR(dd, REG_ITMP3);
891 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
892 N_AHI(GET_HIGH_REG(d), -1);
894 emit_store_dst(jd, iptr, d);
897 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
899 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
900 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
901 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
908 emit_store_dst(jd, iptr, d);
912 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
913 /* sx.val.i = constant */
914 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
915 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
917 if (iptr->sx.val.i == 2) {
919 } else if (N_VALID_IMM(iptr->sx.val.i)) {
920 M_IMUL_IMM(iptr->sx.val.i, d);
922 disp = dseg_add_s4(cd, iptr->sx.val.i);
923 M_ILD_DSEG(REG_ITMP2, disp);
924 M_IMUL(REG_ITMP2, d);
926 emit_store_dst(jd, iptr, d);
929 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
930 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
932 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
933 emit_arithmetic_check(cd, iptr, s2);
935 /* For this operation we need a register pair.
936 * We will use r0 and itmp1 and will backup r0.
939 M_INTMOVE(R0, REG_ITMP3);
941 /* We won't check for division by 0, we catch a SIGFPE instead
942 * Special case 0x80000000 / 0xffffffff handled by signal handler too.
945 s1 = emit_load_s1(jd, iptr, R0);
954 d = codegen_reg_of_dst(jd, iptr, R0);
958 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
959 M_INTMOVE(REG_ITMP1, d);
963 emit_store_dst(jd, iptr, d);
965 /* If destionation of operation was not register R0,
969 if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
970 M_INTMOVE(REG_ITMP3, R0);
975 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
976 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
978 bte = iptr->sx.s23.s3.bte;
981 /* test s2 for zero */
983 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
984 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
985 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
986 emit_arithmetic_check(cd, iptr, REG_ITMP3);
990 disp = dseg_add_functionptr(cd, bte->fp);
994 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
996 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
997 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
1001 M_ASUB_IMM(96, REG_SP);
1002 M_ALD_DSEG(REG_ITMP3, disp);
1003 M_JSR(REG_RA, REG_ITMP3);
1004 M_AADD_IMM(96, REG_SP);
1008 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1009 M_LNGMOVE(REG_RESULT_PACKED, d);
1010 emit_store_dst(jd, iptr, d);
1014 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1015 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1016 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1018 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1019 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1020 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1022 /* Use only 5 bits of sencond operand. */
1024 M_INTMOVE(s2, REG_ITMP2);
1026 ICONST(REG_ITMP3, 0x1F);
1027 M_IAND(REG_ITMP3, s2);
1031 switch (iptr->opc) {
1044 emit_store_dst(jd, iptr, d);
1047 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1048 /* sx.val.i = constant */
1052 assert(iptr->sx.val.i <= 32);
1054 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1055 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1062 s3 = (1 << iptr->sx.val.i) - 1;
1064 if (N_VALID_IMM(s3)) {
1067 ICONST(REG_ITMP1, -1);
1068 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1069 M_IADD(REG_ITMP1, d);
1072 N_BRC_BACK_PATCH(ref);
1074 M_SRA_IMM(iptr->sx.val.i, d);
1076 emit_store_dst(jd, iptr, d);
1081 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1082 /* sx.val.i = constant */
1084 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1085 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1088 M_MOV(s1, REG_ITMP1);
1092 ICONST(REG_ITMP3, iptr->sx.val.i);
1095 M_IAND(REG_ITMP3, d);
1098 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1104 emit_store_dst(jd, iptr, d);
1108 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1109 /* sx.val.i = constant */
1110 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1111 /* sx.val.i = constant */
1112 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1113 /* sx.val.i = constant */
1114 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1115 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1119 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1121 switch (iptr->opc) {
1122 case ICMD_ISHLCONST:
1125 case ICMD_ISHRCONST:
1128 case ICMD_IUSHRCONST:
1135 emit_store_dst(jd, iptr, d);
1138 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1140 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1142 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1144 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1146 /* Use only 6 bits of second operand */
1148 M_INTMOVE(s2, REG_ITMP3);
1150 ICONST(REG_ITMP2, 0x3F);
1151 M_IAND(REG_ITMP2, s2);
1153 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1155 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1156 M_INTMOVE(s2, REG_ITMP3);
1160 s1 = emit_load_s1(jd, iptr, d);
1164 switch (iptr->opc) {
1166 M_SLDL(s2, GET_HIGH_REG(d));
1169 M_SRDA(s2, GET_HIGH_REG(d));
1172 M_SRDL(s2, GET_HIGH_REG(d));
1178 emit_copy_dst(jd, iptr, d);
1179 emit_store_dst(jd, iptr, d);
1180 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1184 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1185 /* sx.val.i = constant */
1186 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1187 /* sx.val.i = constant */
1188 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1189 /* sx.val.l = constant */
1192 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1193 s1 = emit_load_s1(jd, iptr, d);
1197 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1199 switch (iptr->opc) {
1200 case ICMD_LSHLCONST:
1201 N_SLDL(GET_HIGH_REG(d), disp, RN);
1203 case ICMD_LSHRCONST:
1204 N_SRDA(GET_HIGH_REG(d), disp, RN);
1206 case ICMD_LUSHRCONST:
1207 N_SRDL(GET_HIGH_REG(d), disp, RN);
1210 N_SLDL(GET_HIGH_REG(d), disp, RN);
1216 emit_copy_dst(jd, iptr, d);
1217 emit_store_dst(jd, iptr, d);
1218 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1222 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1224 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1225 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1226 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1233 emit_store_dst(jd, iptr, d);
1237 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1239 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1240 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1241 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1248 emit_store_dst(jd, iptr, d);
1252 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1254 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1255 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1256 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1263 emit_store_dst(jd, iptr, d);
1269 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1270 /* sx.val.i = constant */
1271 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1272 /* sx.val.i = constant */
1273 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1274 /* sx.val.i = constant */
1276 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1277 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1280 ICONST(REG_ITMP2, iptr->sx.val.i);
1282 switch (iptr->opc) {
1283 case ICMD_IANDCONST:
1284 M_IAND(REG_ITMP2, d);
1286 case ICMD_IXORCONST:
1287 M_IXOR(REG_ITMP2, d);
1290 M_IOR(REG_ITMP2, d);
1296 emit_store_dst(jd, iptr, d);
1300 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1301 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1302 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1304 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1306 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1307 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1308 dd = GET_LOW_REG(d);
1310 switch (iptr->opc) {
1339 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1340 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1341 dd = GET_HIGH_REG(d);
1343 switch (iptr->opc) {
1372 emit_store_dst(jd, iptr, d);
1375 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1376 /* sx.val.l = constant */
1377 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1378 /* sx.val.l = constant */
1379 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1380 /* sx.val.l = constant */
1382 /* TODO should use memory operand to access data segment, not load */
1384 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1386 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1387 s3 = iptr->sx.val.l & 0xffffffff;
1389 M_INTMOVE(s1, GET_LOW_REG(d));
1391 ICONST(REG_ITMP3, s3);
1393 switch (iptr->opc) {
1394 case ICMD_LANDCONST:
1395 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1397 case ICMD_LXORCONST:
1398 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1401 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1407 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1408 s3 = iptr->sx.val.l >> 32;
1410 M_INTMOVE(s1, GET_HIGH_REG(d));
1412 ICONST(REG_ITMP3, s3);
1414 switch (iptr->opc) {
1415 case ICMD_LANDCONST:
1416 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1418 case ICMD_LXORCONST:
1419 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1422 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1428 emit_store_dst(jd, iptr, d);
1432 /* floating operations ************************************************/
1434 case ICMD_FNEG: /* ..., value ==> ..., - value */
1435 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1436 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1438 emit_store_dst(jd, iptr, d);
1441 case ICMD_DNEG: /* ..., value ==> ..., - value */
1442 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1443 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1445 emit_store_dst(jd, iptr, d);
1448 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1449 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1450 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1451 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1458 emit_store_dst(jd, iptr, d);
1461 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1462 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1463 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1464 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1471 emit_store_dst(jd, iptr, d);
1474 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1475 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1476 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1477 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1481 emit_store_dst(jd, iptr, d);
1484 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1485 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1486 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1487 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1491 emit_store_dst(jd, iptr, d);
1494 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1495 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1496 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1497 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1504 emit_store_dst(jd, iptr, d);
1507 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1508 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1509 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1510 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1517 emit_store_dst(jd, iptr, d);
1520 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1521 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1522 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1523 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1527 emit_store_dst(jd, iptr, d);
1530 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1531 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1532 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1533 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1537 emit_store_dst(jd, iptr, d);
1540 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1541 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1542 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1544 emit_store_dst(jd, iptr, d);
1547 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1548 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1549 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1551 emit_store_dst(jd, iptr, d);
1554 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1558 #ifdef SUPPORT_HERCULES
1562 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1563 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1567 switch (iptr->opc) {
1576 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1577 N_LHI(d, 0); /* Load 0 */
1578 ref1 = cd->mcodeptr;
1579 N_BRC(DD_ANY, 0); /* Exit */
1583 switch (iptr->opc) {
1592 #ifdef SUPPORT_HERCULES
1593 /* Hercules does the conversion using a plain C conversion.
1594 * According to manual, real hardware should *NOT* require this.
1596 * Corner case: Positive float leads to INT_MIN (overflow).
1599 switch (iptr->opc) {
1608 ref2 = cd->mcodeptr;
1609 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1613 ref3 = cd->mcodeptr;
1614 M_BGE(0); /* If integer result is negative, continue */
1616 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1617 M_ILD_DSEG(d, disp);
1619 N_BRC_BACK_PATCH(ref1);
1620 #ifdef SUPPORT_HERCULES
1621 N_BRC_BACK_PATCH(ref2);
1622 N_BRC_BACK_PATCH(ref3);
1624 emit_store_dst(jd, iptr, d);
1628 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1631 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1632 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1633 #ifdef SUPPORT_HERCULES
1636 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1637 disp = dseg_add_double(cd, 0.0 / 0.0);
1638 M_DLD_DSEG(d, disp, REG_ITMP1);
1639 emit_label_br(cd, BRANCH_LABEL_1);
1640 N_BRC_BACK_PATCH(ref);
1643 #ifdef SUPPORT_HERCULES
1644 emit_label(cd, BRANCH_LABEL_1);
1646 emit_store_dst(jd, iptr, d);
1650 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1651 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1652 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1654 emit_store_dst(jd, iptr, d);
1657 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1658 /* == => 0, < => 1, > => -1 */
1662 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1663 /* == => 0, < => 1, > => -1 */
1666 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1667 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1668 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1670 switch (iptr->opc) {
1682 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1683 SZ_BRC + SZ_BRC + SZ_BRC
1686 N_BRC( /* load -1 */
1687 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1688 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1693 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1696 N_LHI(d, 1); /* GT */
1697 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1698 N_LHI(d, -1); /* LT */
1699 M_BR(SZ_BRC + SZ_LHI);
1700 N_LHI(d, 0); /* EQ */
1702 emit_store_dst(jd, iptr, d);
1707 /* memory operations **************************************************/
1709 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1711 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1712 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1714 /* implicit null-pointer check */
1715 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1716 emit_store_dst(jd, iptr, d);
1720 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1721 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1722 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1723 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1725 /* implicit null-pointer check */
1726 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1728 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1733 emit_store_dst(jd, iptr, d);
1736 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1738 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1739 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1740 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1742 /* implicit null-pointer check */
1743 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1745 M_INTMOVE(s2, REG_ITMP2);
1746 M_SLL_IMM(1, REG_ITMP2);
1748 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1750 /* N_LH does sign extends, undo ! */
1755 emit_store_dst(jd, iptr, d);
1758 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1759 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1760 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1761 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1763 /* implicit null-pointer check */
1764 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1766 M_INTMOVE(s2, REG_ITMP2);
1767 M_SLL_IMM(1, REG_ITMP2);
1769 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1770 emit_store_dst(jd, iptr, d);
1773 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1774 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1775 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1776 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1778 /* implicit null-pointer check */
1779 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1781 M_INTMOVE(s2, REG_ITMP2);
1782 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1783 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1784 emit_store_dst(jd, iptr, d);
1787 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1789 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1790 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1792 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1794 /* implicit null-pointer check */
1795 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1797 M_INTMOVE(s2, REG_ITMP2);
1798 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1800 /* We need to preserve the array address after the first load */
1802 if (GET_HIGH_REG(d) == s1) {
1803 M_INTMOVE(s1, REG_ITMP3);
1807 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1808 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1809 emit_store_dst(jd, iptr, d);
1813 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1815 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1816 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1817 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1819 /* implicit null-pointer check */
1820 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1822 M_INTMOVE(s2, REG_ITMP2);
1823 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1825 N_LE(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1827 emit_store_dst(jd, iptr, d);
1830 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1831 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1832 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1833 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1835 /* implicit null-pointer check */
1836 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1838 M_INTMOVE(s2, REG_ITMP2);
1839 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1841 N_LD(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1843 emit_store_dst(jd, iptr, d);
1846 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1847 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1848 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1849 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1851 /* implicit null-pointer check */
1852 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1854 M_INTMOVE(s2, REG_ITMP2);
1855 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1856 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1857 emit_store_dst(jd, iptr, d);
1860 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1861 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1862 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1863 /* implicit null-pointer check */
1864 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1865 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1867 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1870 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1872 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1873 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1874 /* implicit null-pointer check */
1875 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1876 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1878 M_INTMOVE(s2, REG_ITMP2);
1879 M_SLL_IMM(1, REG_ITMP2);
1881 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1885 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1886 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1887 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1888 /* implicit null-pointer check */
1889 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1890 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1892 M_INTMOVE(s2, REG_ITMP2);
1893 M_SLL_IMM(1, REG_ITMP2);
1895 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1898 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1900 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1901 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1902 /* implicit null-pointer check */
1903 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1905 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1907 M_INTMOVE(s2, REG_ITMP2);
1908 M_SLL_IMM(2, REG_ITMP2);
1910 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1913 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1915 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1916 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1917 /* implicit null-pointer check */
1918 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1920 M_INTMOVE(s2, REG_ITMP2);
1921 M_SLL_IMM(3, REG_ITMP2);
1923 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1924 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1925 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1926 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1929 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1930 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1931 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1932 /* implicit null-pointer check */
1933 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1934 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1936 M_INTMOVE(s2, REG_ITMP2);
1937 M_SLL_IMM(2, REG_ITMP2);
1939 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1942 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1943 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1944 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1945 /* implicit null-pointer check */
1946 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1947 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1949 M_INTMOVE(s2, REG_ITMP2);
1950 M_SLL_IMM(3, REG_ITMP2);
1952 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1955 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1957 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1958 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1959 /* implicit null-pointer check */
1960 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1961 s3 = emit_load_s3(jd, iptr, REG_A1);
1963 M_INTMOVE(s1, REG_A0);
1964 M_INTMOVE(s3, REG_A1);
1966 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1967 M_ALD_DSEG(REG_ITMP3, disp);
1968 M_ASUB_IMM(96, REG_SP);
1969 M_JSR(REG_RA, REG_ITMP3);
1970 M_AADD_IMM(96, REG_SP);
1972 emit_exception_check(cd, iptr);
1974 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1975 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1976 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1978 M_INTMOVE(s2, REG_ITMP2);
1979 M_SLL_IMM(2, REG_ITMP2);
1980 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1983 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1984 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1989 case ICMD_GETSTATIC: /* ... ==> ..., value */
1991 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1992 uf = iptr->sx.s23.s3.uf;
1993 fieldtype = uf->fieldref->parseddesc.fd->type;
1994 disp = dseg_add_unique_address(cd, NULL);
1996 /* PROFILE_CYCLE_STOP; */
1998 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2000 /* PROFILE_CYCLE_START; */
2003 fi = iptr->sx.s23.s3.fmiref->p.field;
2004 fieldtype = fi->type;
2005 disp = dseg_add_address(cd, fi->value);
2007 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2010 patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, 0);
2012 PROFILE_CYCLE_START;
2016 M_ALD_DSEG(REG_ITMP1, disp);
2018 switch (fieldtype) {
2020 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2021 M_ILD(d, REG_ITMP1, 0);
2024 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2025 M_LLD(d, REG_ITMP1, 0);
2028 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2029 M_ALD(d, REG_ITMP1, 0);
2032 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2033 M_FLD(d, REG_ITMP1, 0);
2036 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2037 M_DLD(d, REG_ITMP1, 0);
2041 emit_store_dst(jd, iptr, d);
2045 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2047 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2048 uf = iptr->sx.s23.s3.uf;
2049 fieldtype = uf->fieldref->parseddesc.fd->type;
2050 disp = dseg_add_unique_address(cd, uf);
2052 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2055 fi = iptr->sx.s23.s3.fmiref->p.field;
2056 fieldtype = fi->type;
2057 disp = dseg_add_address(cd, fi->value);
2059 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2061 patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, disp);
2062 PROFILE_CYCLE_START;
2066 M_ALD_DSEG(REG_ITMP1, disp);
2067 switch (fieldtype) {
2069 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2070 M_IST(s1, REG_ITMP1, 0);
2073 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2074 M_LST(s1, REG_ITMP1, 0);
2077 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2078 M_AST(s1, REG_ITMP1, 0);
2081 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2082 M_FST(s1, REG_ITMP1, 0);
2085 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2086 M_DST(s1, REG_ITMP1, 0);
2091 case ICMD_GETFIELD: /* ... ==> ..., value */
2093 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2094 emit_nullpointer_check(cd, iptr, s1);
2096 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2097 uf = iptr->sx.s23.s3.uf;
2098 fieldtype = uf->fieldref->parseddesc.fd->type;
2101 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2104 fi = iptr->sx.s23.s3.fmiref->p.field;
2105 fieldtype = fi->type;
2109 switch (fieldtype) {
2111 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2115 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2116 if (GET_HIGH_REG(d) == s1) {
2117 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2118 M_ILD(GET_HIGH_REG(d), s1, disp);
2121 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2122 M_ILD(GET_HIGH_REG(d), s1, disp);
2126 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2130 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2134 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2138 emit_store_dst(jd, iptr, d);
2141 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2145 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2146 emit_nullpointer_check(cd, iptr, s1);
2148 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2149 uf = iptr->sx.s23.s3.uf;
2150 fieldtype = uf->fieldref->parseddesc.fd->type;
2154 fi = iptr->sx.s23.s3.fmiref->p.field;
2155 fieldtype = fi->type;
2159 /* We can't add a patcher ref behind this load,
2160 * because the patcher would destroy REG_ITMP3.
2162 * We pass in the disp parameter, how many bytes
2163 * to skip to the to the actual store.
2165 * XXX this relies on patcher_add_patch_ref internals
2168 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2169 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2174 if (IS_INT_LNG_TYPE(fieldtype)) {
2175 if (IS_2_WORD_TYPE(fieldtype))
2176 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2178 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2180 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2183 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2184 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2187 switch (fieldtype) {
2189 M_IST(s2, s1, disp);
2192 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2193 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2196 M_AST(s2, s1, disp);
2199 M_FST(s2, s1, disp);
2202 M_DST(s2, s1, disp);
2209 /* branch operations **************************************************/
2211 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2213 /* PROFILE_CYCLE_STOP; */
2215 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2216 M_INTMOVE(s1, REG_ITMP1_XPTR);
2218 #ifdef ENABLE_VERIFIER
2219 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2220 uc = iptr->sx.s23.s2.uc;
2222 patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
2224 #endif /* ENABLE_VERIFIER */
2226 disp = dseg_add_functionptr(cd, asm_handle_exception);
2227 M_ALD_DSEG(REG_ITMP2, disp);
2228 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2233 case ICMD_GOTO: /* ... ==> ... */
2234 case ICMD_RET: /* ... ==> ... */
2236 emit_br(cd, iptr->dst.block);
2240 case ICMD_JSR: /* ... ==> ... */
2242 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2246 case ICMD_IFNULL: /* ..., value ==> ... */
2247 case ICMD_IFNONNULL: /* ..., value ==> ... */
2248 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2250 switch (iptr->opc) {
2252 emit_beq(cd, iptr->dst.block);
2254 case ICMD_IFNONNULL:
2255 emit_bne(cd, iptr->dst.block);
2260 case ICMD_IFEQ: /* ..., value ==> ... */
2261 case ICMD_IFLT: /* ..., value ==> ... */
2262 case ICMD_IFLE: /* ..., value ==> ... */
2263 case ICMD_IFNE: /* ..., value ==> ... */
2264 case ICMD_IFGT: /* ..., value ==> ... */
2265 case ICMD_IFGE: /* ..., value ==> ... */
2267 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2269 if (N_VALID_IMM(iptr->sx.val.i))
2270 M_ICMP_IMM(s1, iptr->sx.val.i);
2272 disp = dseg_add_s4(cd, iptr->sx.val.i);
2273 if (N_VALID_DSEG_DISP(disp)) {
2274 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2276 ICONST(REG_ITMP2, disp);
2277 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2281 switch (iptr->opc) {
2283 emit_blt(cd, iptr->dst.block);
2286 emit_ble(cd, iptr->dst.block);
2289 emit_bne(cd, iptr->dst.block);
2292 emit_bgt(cd, iptr->dst.block);
2295 emit_bge(cd, iptr->dst.block);
2298 emit_beq(cd, iptr->dst.block);
2304 case ICMD_IF_LLT: /* ..., value ==> ... */
2305 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2311 /* ATTENTION: compare high words signed and low words unsigned */
2313 # define LABEL_OUT BRANCH_LABEL_1
2315 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2317 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2318 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2320 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2321 if (N_VALID_DSEG_DISP(disp)) {
2322 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2324 ICONST(REG_ITMP2, disp);
2325 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2332 emit_blt(cd, iptr->dst.block);
2333 /* EQ ... fall through */
2334 emit_label_bgt(cd, LABEL_OUT);
2338 emit_bgt(cd, iptr->dst.block);
2339 /* EQ ... fall through */
2340 emit_label_blt(cd, LABEL_OUT);
2343 /* EQ ... fall through */
2344 emit_label_bne(cd, LABEL_OUT);
2347 /* EQ ... fall through */
2348 emit_bne(cd, iptr->dst.block);
2354 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2356 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2357 if (N_VALID_DSEG_DISP(disp)) {
2358 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2360 ICONST(REG_ITMP2, disp);
2361 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2366 emit_blt(cd, iptr->dst.block);
2367 emit_label(cd, LABEL_OUT);
2370 emit_ble(cd, iptr->dst.block);
2371 emit_label(cd, LABEL_OUT);
2374 emit_bgt(cd, iptr->dst.block);
2375 emit_label(cd, LABEL_OUT);
2378 emit_bge(cd, iptr->dst.block);
2379 emit_label(cd, LABEL_OUT);
2382 emit_beq(cd, iptr->dst.block);
2383 emit_label(cd, LABEL_OUT);
2386 emit_bne(cd, iptr->dst.block);
2395 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2396 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2398 /* Compare addresses as 31 bit unsigned integers */
2400 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2401 M_LDA(REG_ITMP1, s1, 0);
2403 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2404 M_LDA(REG_ITMP2, s2, 0);
2406 M_CMP(REG_ITMP1, REG_ITMP2);
2408 switch (iptr->opc) {
2409 case ICMD_IF_ACMPEQ:
2410 emit_beq(cd, iptr->dst.block);
2412 case ICMD_IF_ACMPNE:
2413 emit_bne(cd, iptr->dst.block);
2419 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2420 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2421 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2422 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2423 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2424 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2426 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2427 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2429 switch (iptr->opc) {
2430 case ICMD_IF_ICMPEQ:
2431 emit_beq(cd, iptr->dst.block);
2433 case ICMD_IF_ICMPNE:
2434 emit_bne(cd, iptr->dst.block);
2436 case ICMD_IF_ICMPLT:
2437 emit_blt(cd, iptr->dst.block);
2439 case ICMD_IF_ICMPGT:
2440 emit_bgt(cd, iptr->dst.block);
2442 case ICMD_IF_ICMPLE:
2443 emit_ble(cd, iptr->dst.block);
2445 case ICMD_IF_ICMPGE:
2446 emit_bge(cd, iptr->dst.block);
2452 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2453 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2454 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2455 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2456 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2457 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2462 /* ATTENTION: compare high words signed and low words unsigned */
2464 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2465 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2470 case ICMD_IF_LCMPLT:
2471 case ICMD_IF_LCMPLE:
2472 emit_blt(cd, iptr->dst.block);
2473 /* EQ ... fall through */
2474 out_ref = cd->mcodeptr;
2477 case ICMD_IF_LCMPGT:
2478 case ICMD_IF_LCMPGE:
2479 emit_bgt(cd, iptr->dst.block);
2480 /* EQ ... fall through */
2481 out_ref = cd->mcodeptr;
2484 case ICMD_IF_LCMPEQ:
2485 /* EQ ... fall through */
2486 out_ref = cd->mcodeptr;
2489 case ICMD_IF_LCMPNE:
2490 /* EQ ... fall through */
2491 emit_bne(cd, iptr->dst.block);
2497 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2498 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2503 case ICMD_IF_LCMPLT:
2504 emit_blt(cd, iptr->dst.block);
2506 case ICMD_IF_LCMPLE:
2507 emit_ble(cd, iptr->dst.block);
2509 case ICMD_IF_LCMPGT:
2510 emit_bgt(cd, iptr->dst.block);
2512 case ICMD_IF_LCMPGE:
2513 emit_bge(cd, iptr->dst.block);
2515 case ICMD_IF_LCMPEQ:
2516 emit_beq(cd, iptr->dst.block);
2518 case ICMD_IF_LCMPNE:
2519 emit_bne(cd, iptr->dst.block);
2526 if (out_ref != NULL) {
2527 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2533 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2535 REPLACEMENT_POINT_RETURN(cd, iptr);
2536 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2537 M_INTMOVE(s1, REG_RESULT);
2538 goto nowperformreturn;
2540 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2542 REPLACEMENT_POINT_RETURN(cd, iptr);
2543 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2544 M_INTMOVE(s1, REG_RESULT);
2546 #ifdef ENABLE_VERIFIER
2547 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2548 unresolved_class *uc = iptr->sx.s23.s2.uc;
2551 patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
2552 PROFILE_CYCLE_START;
2554 #endif /* ENABLE_VERIFIER */
2555 goto nowperformreturn;
2557 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2559 REPLACEMENT_POINT_RETURN(cd, iptr);
2560 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2561 M_LNGMOVE(s1, REG_RESULT_PACKED);
2562 goto nowperformreturn;
2564 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2567 REPLACEMENT_POINT_RETURN(cd, iptr);
2568 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2569 M_FLTMOVE(s1, REG_FRESULT);
2570 goto nowperformreturn;
2572 case ICMD_RETURN: /* ... ==> ... */
2574 REPLACEMENT_POINT_RETURN(cd, iptr);
2580 p = cd->stackframesize;
2582 /* call trace function */
2584 #if !defined(NDEBUG)
2585 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2586 emit_verbosecall_exit(jd);
2587 #endif /* !defined(NDEBUG) */
2589 #if defined(ENABLE_THREADS)
2590 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2591 /* we need to save the proper return value */
2593 switch (iptr->opc) {
2595 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2599 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2602 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2605 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2609 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2611 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2612 M_ALD_DSEG(REG_ITMP3, disp);
2614 M_ASUB_IMM(96, REG_SP);
2616 M_AADD_IMM(96, REG_SP);
2618 /* and now restore the proper return value */
2620 switch (iptr->opc) {
2622 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2626 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2629 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2632 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2638 /* restore return address */
2640 p--; M_ALD(REG_RA, REG_SP, p * 8);
2642 /* restore saved registers */
2644 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2645 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2647 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2648 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2651 /* deallocate stack */
2653 if (cd->stackframesize)
2654 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2656 /* generate method profiling code */
2665 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2668 branch_target_t *table;
2670 table = iptr->dst.table;
2672 l = iptr->sx.s23.s2.tablelow;
2673 i = iptr->sx.s23.s3.tablehigh;
2675 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2676 M_INTMOVE(s1, REG_ITMP1);
2680 } else if (N_VALID_IMM(-l)) {
2681 M_ISUB_IMM(l, REG_ITMP1);
2683 ICONST(REG_ITMP2, l);
2684 M_ISUB(REG_ITMP2, REG_ITMP1);
2687 /* number of targets */
2693 ICONST(REG_ITMP2, i);
2694 M_ICMPU(REG_ITMP1, REG_ITMP2);
2695 emit_bge(cd, table[0].block);
2697 /* build jump table top down and use address of lowest entry */
2702 dseg_add_target(cd, table->block);
2707 /* length of dataseg after last dseg_add_target is used by load */
2709 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2710 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2711 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2712 M_JMP(RN, REG_ITMP1);
2717 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2720 lookup_target_t *lookup;
2722 lookup = iptr->dst.lookup;
2724 i = iptr->sx.s23.s2.lookupcount;
2726 MCODECHECK(8 + ((7 + 6) * i) + 5);
2727 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2730 if (N_VALID_IMM(lookup->value)) {
2731 M_ICMP_IMM(s1, lookup->value);
2733 ICONST(REG_ITMP2, lookup->value);
2734 M_ICMP(REG_ITMP2, s1);
2736 emit_beq(cd, lookup->target.block);
2740 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2745 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2747 bte = iptr->sx.s23.s3.bte;
2751 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2752 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2753 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2754 case ICMD_INVOKEINTERFACE:
2756 REPLACEMENT_POINT_INVOKE(cd, iptr);
2758 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2760 um = iptr->sx.s23.s3.um;
2761 md = um->methodref->parseddesc.md;
2764 lm = iptr->sx.s23.s3.fmiref->p.method;
2766 md = lm->parseddesc;
2770 s3 = md->paramcount;
2772 MCODECHECK((s3 << 1) + 64);
2774 /* copy arguments to registers or stack location */
2776 for (s3 = s3 - 1; s3 >= 0; s3--) {
2777 var = VAR(iptr->sx.s23.s2.args[s3]);
2779 /* Already Preallocated? */
2780 if (var->flags & PREALLOC)
2783 if (IS_INT_LNG_TYPE(var->type)) {
2784 if (!md->params[s3].inmemory) {
2785 if (IS_2_WORD_TYPE(var->type)) {
2787 GET_LOW_REG(md->params[s3].regoff),
2788 GET_HIGH_REG(md->params[s3].regoff)
2790 d = emit_load(jd, iptr, var, s1);
2794 s1 = md->params[s3].regoff;
2795 d = emit_load(jd, iptr, var, s1);
2800 if (IS_2_WORD_TYPE(var->type)) {
2801 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2802 M_LST(d, REG_SP, md->params[s3].regoff);
2805 d = emit_load(jd, iptr, var, REG_ITMP1);
2806 M_IST(d, REG_SP, md->params[s3].regoff);
2811 if (!md->params[s3].inmemory) {
2812 s1 = md->params[s3].regoff;
2813 d = emit_load(jd, iptr, var, s1);
2817 d = emit_load(jd, iptr, var, REG_FTMP1);
2818 if (IS_2_WORD_TYPE(var->type))
2819 M_DST(d, REG_SP, md->params[s3].regoff);
2821 M_FST(d, REG_SP, md->params[s3].regoff);
2826 /* generate method profiling code */
2830 switch (iptr->opc) {
2832 disp = dseg_add_functionptr(cd, bte->fp);
2834 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2835 if (N_VALID_DSEG_DISP(disp)) {
2836 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2838 N_LHI(REG_ITMP1, disp);
2839 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2843 case ICMD_INVOKESPECIAL:
2845 /* Implicit NULL pointer check */
2846 M_ILD(REG_ITMP1, REG_A0, 0);
2850 case ICMD_INVOKESTATIC:
2852 disp = dseg_add_unique_address(cd, um);
2854 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2858 disp = dseg_add_address(cd, lm->stubroutine);
2860 if (N_VALID_DSEG_DISP(disp)) {
2861 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2863 N_LHI(REG_ITMP1, disp);
2864 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2868 case ICMD_INVOKEVIRTUAL:
2869 /* TODO softnull REG_A0 */
2872 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2877 s1 = OFFSET(vftbl_t, table[0]) +
2878 sizeof(methodptr) * lm->vftblindex;
2881 /* implicit null-pointer check */
2883 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2884 M_ALD(REG_PV, REG_METHODPTR, s1);
2887 case ICMD_INVOKEINTERFACE:
2888 /* TODO softnull REG_A0 */
2890 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2891 * and -0xFFF in index register (itmp1)
2895 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2901 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2902 sizeof(methodptr*) * lm->class->index;
2904 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2907 /* Implicit null-pointer check */
2908 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2909 N_LHI(REG_ITMP1, s1);
2910 N_L(REG_METHODPTR, 0, REG_ITMP1, REG_METHODPTR);
2911 M_ALD(REG_PV, REG_METHODPTR, s2);
2915 /* generate the actual call */
2918 emit_restore_pv(cd);
2920 /* post call finalization */
2922 switch (iptr->opc) {
2924 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2925 emit_exception_check(cd, iptr); /* check for exception */
2929 /* generate method profiling code */
2931 PROFILE_CYCLE_START;
2933 /* store size of call code in replacement point */
2935 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2937 /* store return value */
2939 d = md->returntype.type;
2941 if (d != TYPE_VOID) {
2942 if (IS_INT_LNG_TYPE(d)) {
2943 if (IS_2_WORD_TYPE(d)) {
2944 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2945 M_LNGMOVE(REG_RESULT_PACKED, s1);
2948 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2949 M_INTMOVE(REG_RESULT, s1);
2953 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2954 M_FLTMOVE(REG_FRESULT, s1);
2956 emit_store_dst(jd, iptr, s1);
2962 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2964 /* val.a: (classinfo*) superclass */
2966 /* superclass is an interface:
2968 * OK if ((sub == NULL) ||
2969 * (sub->vftbl->interfacetablelength > super->index) &&
2970 * (sub->vftbl->interfacetable[-super->index] != NULL));
2972 * superclass is a class:
2974 * OK if ((sub == NULL) || (0
2975 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2976 * super->vftbl->diffval));
2979 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2980 /* object type cast-check */
2983 vftbl_t *supervftbl;
2986 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2987 # define LABEL_CLASS BRANCH_LABEL_2
2988 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2989 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2990 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2992 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2998 super = iptr->sx.s23.s3.c.cls;
2999 superindex = super->index;
3000 supervftbl = super->vftbl;
3003 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3004 CODEGEN_CRITICAL_SECTION_NEW;
3006 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3008 /* if class is not resolved, check which code to call */
3010 if (super == NULL) {
3012 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3014 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3016 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3017 iptr->sx.s23.s3.c.ref,
3020 ICONST(REG_ITMP2, ACC_INTERFACE);
3021 if (N_VALID_DSEG_DISP(disp)) {
3022 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3024 ICONST(REG_ITMP3, disp);
3025 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3027 emit_label_beq(cd, LABEL_CLASS);
3030 /* interface checkcast code */
3032 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3033 if (super == NULL) {
3034 patcher_add_patch_ref(jd,
3035 PATCHER_checkcast_instanceof_interface,
3036 iptr->sx.s23.s3.c.ref,
3040 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3043 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3044 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3045 M_ISUB_IMM(superindex, REG_ITMP3);
3046 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3049 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3050 superindex * sizeof(methodptr*))
3052 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3053 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3055 if (super == NULL) {
3056 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3060 /* class checkcast code */
3062 if (super == NULL) {
3063 emit_label(cd, LABEL_CLASS);
3066 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3067 if (super == NULL) {
3068 disp = dseg_add_unique_address(cd, NULL);
3070 patcher_add_patch_ref(jd,
3071 PATCHER_resolve_classref_to_vftbl,
3072 iptr->sx.s23.s3.c.ref,
3076 disp = dseg_add_address(cd, supervftbl);
3078 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3081 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3082 M_ALD_DSEG(REG_ITMP3, disp);
3084 CODEGEN_CRITICAL_SECTION_START;
3086 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3087 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3088 M_ISUB(REG_ITMP3, REG_ITMP2);
3089 M_ALD_DSEG(REG_ITMP3, disp);
3090 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3092 CODEGEN_CRITICAL_SECTION_END;
3094 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3095 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3096 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3097 /* Branch if greater then */
3098 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3101 if (super == NULL) {
3102 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3103 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3104 } else if (super->flags & ACC_INTERFACE) {
3105 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3107 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3110 d = codegen_reg_of_dst(jd, iptr, s1);
3112 # undef LABEL_EXIT_CHECK_NULL
3114 # undef LABEL_EXIT_INTERFACE_NULL
3115 # undef LABEL_EXIT_INTERFACE_DONE
3116 # undef LABEL_EXIT_CLASS_NULL
3119 /* array type cast-check */
3121 s1 = emit_load_s1(jd, iptr, REG_A0);
3122 M_INTMOVE(s1, REG_A0);
3124 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3125 disp = dseg_add_unique_address(cd, NULL);
3127 patcher_add_patch_ref(jd,
3128 PATCHER_resolve_classref_to_classinfo,
3129 iptr->sx.s23.s3.c.ref,
3133 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3135 M_ALD_DSEG(REG_A1, disp);
3136 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3137 M_ALD_DSEG(REG_ITMP1, disp);
3138 M_ASUB_IMM(96, REG_SP);
3139 M_JSR(REG_RA, REG_ITMP1);
3140 M_AADD_IMM(96, REG_SP);
3142 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3143 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3145 d = codegen_reg_of_dst(jd, iptr, s1);
3149 emit_store_dst(jd, iptr, d);
3152 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3153 /* val.a: (classinfo*) superclass */
3155 /* superclass is an interface:
3157 * return (sub != NULL) &&
3158 * (sub->vftbl->interfacetablelength > super->index) &&
3159 * (sub->vftbl->interfacetable[-super->index] != NULL);
3161 * superclass is a class:
3163 * return ((sub != NULL) && (0
3164 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3165 * super->vftbl->diffvall));
3167 * If superclass is unresolved, we include both code snippets
3168 * above, a patcher resolves the class' flags and we select
3169 * the right code at runtime.
3174 vftbl_t *supervftbl;
3177 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3183 super = iptr->sx.s23.s3.c.cls;
3184 superindex = super->index;
3185 supervftbl = super->vftbl;
3188 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3189 # define LABEL_CLASS BRANCH_LABEL_2
3190 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3191 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3192 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3193 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3195 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3196 CODEGEN_CRITICAL_SECTION_NEW;
3198 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3199 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3201 M_MOV(s1, REG_ITMP1);
3205 /* if class is not resolved, check which code to call */
3207 if (super == NULL) {
3211 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3213 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3215 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3216 iptr->sx.s23.s3.c.ref, disp);
3218 ICONST(REG_ITMP2, ACC_INTERFACE);
3220 if (N_VALID_DSEG_DISP(disp)) {
3221 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3223 ICONST(REG_ITMP3, disp);
3224 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3227 emit_label_beq(cd, LABEL_CLASS);
3230 /* interface instanceof code */
3232 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3233 if (super == NULL) {
3234 /* If d == REG_ITMP2, then it's destroyed in check
3239 patcher_add_patch_ref(jd,
3240 PATCHER_checkcast_instanceof_interface,
3241 iptr->sx.s23.s3.c.ref, 0);
3246 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3249 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3250 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3251 M_ISUB_IMM(superindex, REG_ITMP3);
3253 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3257 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3258 superindex * sizeof(methodptr*))
3260 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3262 /* d := (REG_ITMP1 != 0) */
3264 N_LTR(d, REG_ITMP1);
3265 M_BEQ(SZ_BRC + SZ_LHI);
3268 if (super == NULL) {
3269 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3273 /* class instanceof code */
3275 if (super == NULL) {
3276 emit_label(cd, LABEL_CLASS);
3279 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3280 if (super == NULL) {
3281 disp = dseg_add_unique_address(cd, NULL);
3283 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3284 iptr->sx.s23.s3.c.ref,
3288 disp = dseg_add_address(cd, supervftbl);
3293 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3296 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3297 M_ALD_DSEG(REG_ITMP2, disp);
3299 CODEGEN_CRITICAL_SECTION_START;
3301 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3302 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3303 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3305 CODEGEN_CRITICAL_SECTION_END;
3307 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3309 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3311 M_BGT(SZ_BRC + SZ_LHI);
3315 if (super == NULL) {
3316 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3317 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3318 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3319 } else if (super->flags & ACC_INTERFACE) {
3320 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3321 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3323 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3326 # undef LABEL_EXIT_CHECK_NULL
3328 # undef LABEL_EXIT_INTERFACE_NULL
3329 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3330 # undef LABEL_EXIT_INTERFACE_DONE
3331 # undef LABEL_EXIT_CLASS_NULL
3333 emit_store_dst(jd, iptr, d);
3339 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3341 /* check for negative sizes and copy sizes to stack if necessary */
3343 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3346 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3348 /* copy SAVEDVAR sizes to stack */
3349 var = VAR(iptr->sx.s23.s2.args[s1]);
3351 /* Already Preallocated? */
3352 if (!(var->flags & PREALLOC)) {
3353 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3354 M_IST(s2, REG_SP, s1 * 4);
3358 /* is a patcher function set? */
3360 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3361 disp = dseg_add_unique_address(cd, 0);
3363 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3364 iptr->sx.s23.s3.c.ref,
3368 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3370 /* a0 = dimension count */
3372 ICONST(REG_A0, iptr->s1.argcount);
3374 /* a1 = classinfo */
3376 M_ALD_DSEG(REG_A1, disp);
3378 /* a2 = pointer to dimensions = stack pointer */
3380 M_MOV(REG_SP, REG_A2);
3382 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3383 M_ALD_DSEG(REG_ITMP1, disp);
3384 M_ASUB_IMM(96, REG_SP);
3385 M_JSR(REG_RA, REG_ITMP1);
3386 M_AADD_IMM(96, REG_SP);
3388 /* check for exception before result assignment */
3390 emit_exception_check(cd, iptr);
3392 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3393 M_INTMOVE(REG_RESULT, s1);
3394 emit_store_dst(jd, iptr, s1);
3399 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3403 } /* for instruction */
3405 MCODECHECK(512); /* XXX require a lower number? */
3407 /* At the end of a basic block we may have to append some nops,
3408 because the patcher stub calling code might be longer than the
3409 actual instruction. So codepatching does not change the
3410 following block unintentionally. */
3412 if (cd->mcodeptr < cd->lastmcodeptr) {
3413 while (cd->mcodeptr < cd->lastmcodeptr) {
3418 } /* if (bptr -> flags >= BBREACHED) */
3419 } /* for basic block */
3421 dseg_createlinenumbertable(cd);
3423 /* generate stubs */
3425 emit_patcher_traps(jd);
3427 /* everything's ok */
3433 /* codegen_emit_stub_compiler **************************************************
3435 Emits a stub routine which calls the compiler.
3437 *******************************************************************************/
3439 void codegen_emit_stub_compiler(jitdata *jd)
3444 /* get required compiler data */
3449 /* code for the stub */
3451 /* don't touch ITMP3 as it cointains the return address */
3453 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3455 M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */
3456 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3457 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3462 /* codegen_emit_stub_native ****************************************************
3464 Emits a stub routine which calls a native method.
3466 *******************************************************************************/
3469 arguments on stack \
3470 -------------------------------------------------| <- SP on nativestub entry
3472 callee saved int regs (none) |
3473 callee saved float regs (none) | stack frame like in cacao
3474 local variable slots (none) |
3475 arguments for calling methods (none) /
3476 ------------------------------------------------------------------ <- datasp
3481 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3482 0 - 96 register save area for callee /
3483 -------------------------------------------------------- <- SP native method
3485 SP after method entry
3488 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3496 s4 i, j; /* count variables */
3501 /* get required compiler data */
3508 /* initialize variables */
3511 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3513 /* calculate stack frame size */
3515 cd->stackframesize =
3516 1 + /* r14 - return address */ +
3517 ((sizeof(stackframeinfo) + 7) / 8) +
3518 ((sizeof(localref_table) + 7) / 8) +
3520 (INT_ARG_CNT + FLT_ARG_CNT) +
3521 nmd->memuse + /* parameter passing */
3522 (96 / 8) /* required by ABI */;
3524 /* create method header */
3526 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3527 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3528 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3529 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3530 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3531 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3532 (void) dseg_addlinenumbertablesize(cd);
3533 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3535 /* generate stub code */
3537 N_AHI(REG_SP, -(cd->stackframesize * 8));
3538 N_AHI(REG_PV, N_PV_OFFSET);
3540 /* generate native method profiling code */
3542 #if defined(ENABLE_PROFILING)
3543 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3544 /* count frequency */
3545 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
3546 ICONST(REG_ITMP2, 1);
3547 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
3548 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
3552 /* save return address */
3554 N_ST(R14, (cd->stackframesize - 1) * 8, RN, REG_SP);
3556 #if !defined(NDEBUG)
3557 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3558 emit_verbosecall_enter(jd);
3561 /* get function address (this must happen before the stackframeinfo) */
3563 disp = dseg_add_functionptr(cd, f);
3565 #if !defined(WITH_STATIC_CLASSPATH)
3567 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, disp);
3570 M_ILD_DSEG(REG_ITMP1, disp);
3572 j = 96 + (nmd->memuse * 8);
3574 /* todo some arg registers are not volatile in C-abi terms */
3576 /* save integer and float argument registers */
3578 for (i = 0; i < md->paramcount; i++) {
3579 if (! md->params[i].inmemory) {
3580 s1 = md->params[i].regoff;
3581 t = md->paramtypes[i].type;
3583 if (IS_INT_LNG_TYPE(t)) {
3584 if (IS_2_WORD_TYPE(t)) {
3585 /* todo store multiple */
3586 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3587 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3589 N_ST(s1, j, RN, REG_SP);
3592 if (IS_2_WORD_TYPE(t)) {
3593 N_STD(s1, j, RN, REG_SP);
3595 N_STE(s1, j, RN, REG_SP);
3603 N_ST(REG_ITMP1, j, RN, REG_SP);
3605 /* create dynamic stack info */
3607 N_LAE(REG_A0, (cd->stackframesize - 1) * 8 , RN, REG_SP); /* datasp */
3608 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3609 N_LAE(REG_A2, cd->stackframesize * 8, RN, REG_SP); /* old SP */
3610 N_L(REG_A3, (cd->stackframesize - 1) * 8, RN, REG_SP); /* return address */
3612 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3613 M_ILD_DSEG(REG_ITMP1, disp);
3615 M_CALL(REG_ITMP1); /* call */
3617 /* restore integer and float argument registers */
3619 j = 96 + (nmd->memuse * 8);
3621 for (i = 0; i < md->paramcount; i++) {
3622 if (! md->params[i].inmemory) {
3623 s1 = md->params[i].regoff;
3624 t = md->paramtypes[i].type;
3626 if (IS_INT_LNG_TYPE(t)) {
3627 if (IS_2_WORD_TYPE(t)) {
3628 /* todo load multiple ! */
3629 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3630 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3632 N_L(s1, j, RN, REG_SP);
3635 if (IS_2_WORD_TYPE(t)) {
3636 N_LD(s1, j, RN, REG_SP);
3638 N_LE(s1, j, RN, REG_SP);
3646 N_L(REG_ITMP1, j, RN, REG_SP);
3648 /* copy or spill arguments to new locations */
3650 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3651 t = md->paramtypes[i].type;
3653 if (IS_INT_LNG_TYPE(t)) {
3655 if (!md->params[i].inmemory) {
3657 s1 = md->params[i].regoff;
3659 if (!nmd->params[j].inmemory) {
3660 s2 = nmd->params[j].regoff;
3661 if (IS_2_WORD_TYPE(t)) {
3677 s2 = nmd->params[j].regoff;
3678 if (IS_2_WORD_TYPE(t)) {
3693 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3694 s2 = nmd->params[j].regoff;
3696 if (IS_2_WORD_TYPE(t)) {
3697 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3699 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3704 /* We only copy spilled float arguments, as the float argument */
3705 /* registers keep unchanged. */
3707 if (md->params[i].inmemory) {
3708 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3709 s2 = nmd->params[j].regoff;
3711 if (IS_2_WORD_TYPE(t)) {
3712 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3714 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3720 /* put class into second argument register */
3722 if (m->flags & ACC_STATIC) {
3723 disp = dseg_add_address(cd, m->class);
3724 M_ILD_DSEG(REG_A1, disp);
3727 /* put env into first argument register */
3729 disp = dseg_add_address(cd, _Jv_env);
3730 M_ILD_DSEG(REG_A0, disp);
3732 /* do the native function call */
3734 M_CALL(REG_ITMP1); /* call */
3736 /* save return value */
3738 t = md->returntype.type;
3740 if (t != TYPE_VOID) {
3741 if (IS_INT_LNG_TYPE(t)) {
3742 if (IS_2_WORD_TYPE(t)) {
3743 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3745 N_ST(REG_RESULT, 96, RN, REG_SP);
3748 if (IS_2_WORD_TYPE(t)) {
3749 N_STD(REG_FRESULT, 96, RN, REG_SP);
3751 N_STE(REG_FRESULT, 96, RN, REG_SP);
3756 #if !defined(NDEBUG)
3757 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3758 emit_verbosecall_exit(jd);
3761 /* remove native stackframe info */
3763 N_LAE(REG_A0, (cd->stackframesize - 1) * 8, RN, REG_SP); /* datasp */
3764 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3765 M_ALD_DSEG(REG_ITMP1, disp);
3767 N_LR(REG_ITMP3, REG_RESULT);
3769 /* restore return value */
3771 if (t != TYPE_VOID) {
3772 if (IS_INT_LNG_TYPE(t)) {
3773 if (IS_2_WORD_TYPE(t)) {
3774 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3776 N_L(REG_RESULT, 96, RN, REG_SP);
3779 if (IS_2_WORD_TYPE(t)) {
3780 N_LD(REG_FRESULT, 96, RN, REG_SP);
3782 N_LE(REG_FRESULT, 96, RN, REG_SP);
3787 /* load return address */
3789 N_L(REG_ITMP2, (cd->stackframesize - 1) * 8, RN, REG_SP);
3791 /* remove stackframe */
3793 N_AHI(REG_SP, cd->stackframesize * 8);
3795 /* test for exception */
3797 N_LTR(REG_ITMP3, REG_ITMP3);
3798 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3802 N_BCR(DD_ANY, REG_ITMP2);
3804 /* handle exception */
3806 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3807 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3811 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3814 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3815 M_ALD_DSEG(REG_ITMP3, disp);
3816 M_JMP(RN, REG_ITMP3);
3818 /* generate patcher stubs */
3820 emit_patcher_traps(jd);
3823 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3824 codegendata *cd = jd->cd;
3825 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3827 M_MOV(reg, tempregnum);
3835 * These are local overrides for various environment variables in Emacs.
3836 * Please do not remove this and leave it at the end of the file, where
3837 * Emacs will automagically detect them.
3838 * ---------------------------------------------------------------------
3841 * indent-tabs-mode: t
3845 * vim:noexpandtab:sw=4:ts=4: