1 /* src/vm/jit/s390/codegen.c - machine code generator for s390
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "native/jni.h"
35 #include "native/localref.h"
36 #include "native/native.h"
38 #include "mm/memory.h"
40 #if defined(ENABLE_THREADS)
41 # include "threads/lock-common.h"
42 # include "threads/native/lock.h"
45 #include "vmcore/loader.h"
46 #include "vmcore/options.h"
47 #include "vmcore/statistics.h"
48 #include "vm/builtin.h"
49 #include "vm/exceptions.h"
50 #include "vm/global.h"
51 #include "vm/jit/abi.h"
52 #if defined(ENABLE_LSRA)
53 # include "vm/jit/allocator/lsra.h"
55 #include "vm/jit/asmpart.h"
56 #include "vm/jit/codegen-common.h"
57 #include "vm/jit/dseg.h"
58 #include "vm/jit/emit-common.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/methodheader.h"
61 #include "vm/jit/parse.h"
62 #include "vm/jit/patcher-common.h"
63 #include "vm/jit/reg.h"
64 #include "vm/jit/replace.h"
65 #include "vm/jit/s390/arch.h"
66 #include "vm/jit/s390/codegen.h"
67 #include "vm/jit/s390/emit.h"
68 #include "vm/jit/s390/md-abi.h"
69 #include "vm/jit/stacktrace.h"
71 #include "vm/stringlocal.h"
74 /* DO__LOG generates a call to do__log. No registers are destroyed,
75 * so you may use it anywhere. regs is an array containing all general
79 static void do__log(u4 *regs) {
80 /* insert stuff here */
84 N_AHI(REG_SP, -200); \
85 N_STM(R0, R15, 96, REG_SP); \
86 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
87 N_LA(R2, 96, RN, REG_SP); \
89 N_LM(R0, R15, 96, REG_SP); \
92 #define SUPPORT_HERCULES 1
94 /* codegen *********************************************************************
96 Generates machine code.
98 *******************************************************************************/
102 Layout of stackframe:
105 ===============================================================================
106 return_address (stackframesize - 1) * 8
107 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
109 saved_int_reg[rd->savintreguse]
110 saved_flt_reg[FLT_SAV_CNT - 1]
112 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
114 return_value_tmp (rd->memuse + 1) * 8
115 monitorenter_argument (rd->memuse) * 8
117 local[rd->memuse - 1] (rd->memuse - 1) * 8
125 bool codegen_emit(jitdata *jd)
131 s4 len, s1, s2, s3, d, dd, disp;
134 varinfo *var, *var1, *var2, *dst;
138 constant_classref *cr;
139 unresolved_class *uc;
140 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
141 unresolved_method *um;
142 builtintable_entry *bte;
145 unresolved_field *uf;
148 rplpoint *replacementpoint;
152 /* get required compiler data */
159 /* prevent compiler warnings */
172 /* space to save used callee saved registers */
174 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
175 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
177 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
180 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
183 #if defined(ENABLE_THREADS)
184 /* Space to save argument of monitor_enter and Return Values to
185 survive monitor_exit. The stack position for the argument can
186 not be shared with place to save the return register
187 since both values reside in R2. */
189 if (checksync && (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 (!code_is_leafmethod(code) || opt_verbosecall )
201 /* TODO really 16 bytes ? */
202 cd->stackframesize = (cd->stackframesize + 2) & ~2;
204 /* create method header */
206 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
207 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
209 #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 /* REMOVEME: We still need it for exception handling in assembler. */
224 if (code_is_leafmethod(code))
225 (void) dseg_add_unique_s4(cd, 1);
227 (void) dseg_add_unique_s4(cd, 0);
229 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
230 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
232 (void) dseg_addlinenumbertablesize(cd);
234 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
236 /* create exception table */
238 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
239 dseg_add_target(cd, ex->start);
240 dseg_add_target(cd, ex->end);
241 dseg_add_target(cd, ex->handler);
242 (void) dseg_add_unique_address(cd, ex->catchtype.any);
247 M_AADD_IMM(N_PV_OFFSET, REG_PV);
249 /* create stack frame (if necessary) */
251 if (cd->stackframesize) {
252 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
255 /* store return address */
257 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
259 /* generate method profiling code */
261 #if defined(ENABLE_PROFILING)
262 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
263 /* count frequency */
264 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
265 ICONST(REG_ITMP2, 1);
266 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
267 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
273 /* save used callee saved registers and return address */
275 p = cd->stackframesize - 1;
277 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
278 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
280 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
281 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
284 /* take arguments out of register or stack frame */
288 for (p = 0, l = 0; p < md->paramcount; p++) {
289 t = md->paramtypes[p].type;
290 varindex = jd->local_map[l * 5 + t];
294 if (IS_2_WORD_TYPE(t))
297 if (varindex == UNUSED)
302 s1 = md->params[p].regoff;
304 if (IS_INT_LNG_TYPE(t)) { /* integer args */
305 if (IS_2_WORD_TYPE(t)) {
313 if (!md->params[p].inmemory) { /* register arguments */
314 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
315 if (IS_2_WORD_TYPE(t)) {
316 M_LNGMOVE(s2, var->vv.regoff);
318 M_INTMOVE(s2, var->vv.regoff);
320 } else { /* reg arg -> spilled */
321 if (IS_2_WORD_TYPE(t)) {
322 M_LST(s2, REG_SP, var->vv.regoff);
324 M_IST(s2, REG_SP, var->vv.regoff);
328 } else { /* stack arguments */
329 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
330 if (IS_2_WORD_TYPE(t)) {
331 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
333 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
335 } else { /* stack arg -> spilled */
336 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
340 } else { /* floating args */
341 if (!md->params[p].inmemory) { /* register arguments */
343 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
344 M_FLTMOVE(s2, var->vv.regoff);
346 } else { /* reg arg -> spilled */
347 if (IS_2_WORD_TYPE(t))
348 M_DST(s2, REG_SP, var->vv.regoff);
350 M_FST(s2, REG_SP, var->vv.regoff);
353 } else { /* stack arguments */
354 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
355 if (IS_2_WORD_TYPE(t))
356 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
359 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
361 } else { /* stack-arg -> spilled */
362 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
363 var->vv.regoff = cd->stackframesize * 8 + s1;
369 /* save monitorenter argument */
371 #if defined(ENABLE_THREADS)
372 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
373 /* stack offset for monitor argument */
378 if (opt_verbosecall) {
379 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
381 for (p = 0; p < INT_ARG_CNT; p++)
382 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
384 for (p = 0; p < FLT_ARG_CNT; p++)
385 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
387 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
391 /* decide which monitor enter function to call */
393 if (m->flags & ACC_STATIC) {
394 disp = dseg_add_address(cd, &m->class->object.header);
395 M_ALD_DSEG(REG_A0, disp);
399 M_BNE(SZ_BRC + SZ_ILL);
400 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
403 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
404 M_ALD_DSEG(REG_ITMP2, disp);
406 M_AST(REG_A0, REG_SP, s1 * 8);
408 M_ASUB_IMM(96, REG_SP);
410 M_AADD_IMM(96, REG_SP);
413 if (opt_verbosecall) {
414 for (p = 0; p < INT_ARG_CNT; p++)
415 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
417 for (p = 0; p < FLT_ARG_CNT; p++)
418 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
420 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
427 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
428 emit_verbosecall_enter(jd);
429 #endif /* !defined(NDEBUG) */
433 /* end of header generation */
435 /* create replacement points */
437 REPLACEMENT_POINTS_INIT(cd, jd);
439 /* walk through all basic blocks */
441 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
443 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
445 if (bptr->flags >= BBREACHED) {
447 /* branch resolving */
449 codegen_resolve_branchrefs(cd, bptr);
451 /* handle replacement points */
453 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
455 /* copy interface registers to their destination */
460 #if defined(ENABLE_PROFILING)
461 /* generate basicblock profiling code */
463 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
464 /* count frequency */
466 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
467 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
468 ICONST(REG_ITMP2, 1);
469 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
470 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
472 /* if this is an exception handler, start profiling again */
474 if (bptr->type == BBTYPE_EXH)
479 #if defined(ENABLE_LSRA)
483 src = bptr->invars[len];
484 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
485 if (bptr->type == BBTYPE_EXH) {
486 /* d = reg_of_var(rd, src, REG_ITMP1); */
487 if (!IS_INMEMORY(src->flags))
491 M_INTMOVE(REG_ITMP3_XPTR, d);
492 emit_store(jd, NULL, src, d);
502 var = VAR(bptr->invars[len]);
503 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
504 if (bptr->type == BBTYPE_EXH) {
505 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
506 M_INTMOVE(REG_ITMP3_XPTR, d);
507 emit_store(jd, NULL, var, d);
511 assert((var->flags & INOUT));
514 #if defined(ENABLE_LSRA)
517 /* walk through all instructions */
522 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
523 if (iptr->line != currentline) {
524 dseg_addlinenumber(cd, iptr->line);
525 currentline = iptr->line;
528 MCODECHECK(1024); /* 1KB should be enough */
531 case ICMD_NOP: /* ... ==> ... */
532 case ICMD_POP: /* ..., value ==> ... */
533 case ICMD_POP2: /* ..., value, value ==> ... */
536 case ICMD_INLINE_START:
538 REPLACEMENT_POINT_INLINE_START(cd, iptr);
541 case ICMD_INLINE_BODY:
543 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
544 dseg_addlinenumber_inline_start(cd, iptr);
545 dseg_addlinenumber(cd, iptr->line);
548 case ICMD_INLINE_END:
550 dseg_addlinenumber_inline_end(cd, iptr);
551 dseg_addlinenumber(cd, iptr->line);
554 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
555 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
556 emit_nullpointer_check(cd, iptr, s1);
559 /* constant operations ************************************************/
561 case ICMD_ICONST: /* ... ==> ..., constant */
562 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
563 ICONST(d, iptr->sx.val.i);
564 emit_store_dst(jd, iptr, d);
567 case ICMD_LCONST: /* ... ==> ..., constant */
569 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
570 LCONST(d, iptr->sx.val.l);
571 emit_store_dst(jd, iptr, d);
574 case ICMD_FCONST: /* ... ==> ..., constant */
575 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
576 disp = dseg_add_float(cd, iptr->sx.val.f);
577 M_FLD_DSEG(d, disp, REG_ITMP1);
578 emit_store_dst(jd, iptr, d);
581 case ICMD_DCONST: /* ... ==> ..., constant */
582 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
583 disp = dseg_add_double(cd, iptr->sx.val.d);
584 M_DLD_DSEG(d, disp, REG_ITMP1);
585 emit_store_dst(jd, iptr, d);
588 case ICMD_ACONST: /* ... ==> ..., constant */
589 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
591 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
592 cr = iptr->sx.val.c.ref;
593 disp = dseg_add_unique_address(cd, cr);
595 /* PROFILE_CYCLE_STOP; */
597 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
600 /* PROFILE_CYCLE_START; */
604 if (iptr->sx.val.anyptr == 0) {
607 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
610 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
611 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
613 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
615 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
621 emit_store_dst(jd, iptr, d);
625 /* load/store/copy/move operations ************************************/
627 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
628 case ICMD_ALOAD: /* s1 = local variable */
632 case ICMD_ISTORE: /* ..., value ==> ... */
643 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
647 /* integer operations *************************************************/
649 case ICMD_INEG: /* ..., value ==> ..., - value */
651 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
652 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
654 emit_store_dst(jd, iptr, d);
658 case ICMD_LNEG: /* ..., value ==> ..., - value */
660 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
661 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
662 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
663 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
664 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
665 N_AHI(GET_HIGH_REG(d), -1);
666 emit_store_dst(jd, iptr, d);
669 case ICMD_I2L: /* ..., value ==> ..., value */
671 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
672 if (! N_IS_EVEN_ODD(d)) {
673 d = REG_ITMP31_PACKED;
675 assert(N_IS_EVEN_ODD(d));
677 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
679 M_INTMOVE(s1, GET_HIGH_REG(d));
680 M_SRDA_IMM(32, GET_HIGH_REG(d));
682 emit_copy_dst(jd, iptr, d);
683 emit_store_dst(jd, iptr, d);
686 case ICMD_L2I: /* ..., value ==> ..., value */
687 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
688 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
689 M_INTMOVE(GET_LOW_REG(s1), d);
690 emit_store_dst(jd, iptr, d);
693 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
694 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
695 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
699 emit_store_dst(jd, iptr, d);
702 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
703 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
704 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
708 emit_store_dst(jd, iptr, d);
711 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
713 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
714 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
718 emit_store_dst(jd, iptr, d);
721 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
723 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
724 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
725 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
732 emit_store_dst(jd, iptr, d);
737 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
738 /* sx.val.i = constant */
739 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
740 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
743 if (N_VALID_IMM(iptr->sx.val.i)) {
744 M_IADD_IMM(iptr->sx.val.i, d);
746 ICONST(REG_ITMP2, iptr->sx.val.i);
747 M_IADD(REG_ITMP2, d);
749 emit_store_dst(jd, iptr, d);
752 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
754 /* M, (r, q) -> (r, q) */
756 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
758 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
759 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
760 dd = GET_HIGH_REG(d);
769 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
770 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
780 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
781 N_AHI(GET_HIGH_REG(d), 1);
783 emit_store_dst(jd, iptr, d);
786 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
787 /* sx.val.l = constant */
789 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
790 dd = GET_HIGH_REG(d);
792 s1 = emit_load_s1_high(jd, iptr, dd);
793 s3 = iptr->sx.val.l >> 32;
797 if (N_VALID_IMM(s3)) {
800 ICONST(REG_ITMP3, s3);
801 M_IADD(REG_ITMP3, dd);
805 s1 = emit_load_s1_low(jd, iptr, dd);
806 s3 = iptr->sx.val.l & 0xffffffff;
807 ICONST(REG_ITMP3, s3);
810 N_ALR(dd, REG_ITMP3);
812 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
813 N_AHI(GET_HIGH_REG(d), 1);
815 emit_store_dst(jd, iptr, d);
818 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
820 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
821 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
822 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
824 M_INTMOVE(s1, REG_ITMP1);
825 M_ISUB(s2, REG_ITMP1);
826 M_INTMOVE(REG_ITMP1, d);
831 emit_store_dst(jd, iptr, d);
835 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
836 /* sx.val.i = constant */
838 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
839 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
842 if (N_VALID_IMM(-iptr->sx.val.i)) {
843 M_ISUB_IMM(iptr->sx.val.i, d);
845 ICONST(REG_ITMP2, iptr->sx.val.i);
846 M_ISUB(REG_ITMP2, d);
848 emit_store_dst(jd, iptr, d);
852 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
854 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
856 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
857 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
858 dd = GET_HIGH_REG(d);
861 M_INTMOVE(s2, REG_ITMP3);
868 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
869 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
873 M_INTMOVE(s2, REG_ITMP3);
880 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
881 N_AHI(GET_HIGH_REG(d), -1);
883 emit_store_dst(jd, iptr, d);
886 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
887 /* sx.val.l = constant */
889 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
891 dd = GET_HIGH_REG(d);
892 s1 = emit_load_s1_high(jd, iptr, dd);
893 s3 = iptr->sx.val.l >> 32;
897 if (N_VALID_IMM(-s3)) {
900 ICONST(REG_ITMP3, s3);
901 M_ISUB(REG_ITMP3, dd);
905 s1 = emit_load_s1_low(jd, iptr, dd);
906 s3 = iptr->sx.val.l & 0xffffffff;
907 ICONST(REG_ITMP3, s3);
910 N_SLR(dd, REG_ITMP3);
912 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
913 N_AHI(GET_HIGH_REG(d), -1);
915 emit_store_dst(jd, iptr, d);
918 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
920 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
921 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
922 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
929 emit_store_dst(jd, iptr, d);
933 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
934 /* sx.val.i = constant */
935 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
936 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
938 if (iptr->sx.val.i == 2) {
940 } else if (N_VALID_IMM(iptr->sx.val.i)) {
941 M_IMUL_IMM(iptr->sx.val.i, d);
943 disp = dseg_add_s4(cd, iptr->sx.val.i);
944 M_ILD_DSEG(REG_ITMP2, disp);
945 M_IMUL(REG_ITMP2, d);
947 emit_store_dst(jd, iptr, d);
950 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
951 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
953 /* load s1 into r0 */
955 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
956 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
957 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
959 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
961 /* extend s1 to long */
963 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
967 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
973 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
974 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
977 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
978 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
982 emit_store_dst(jd, iptr, d);
986 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
987 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
989 bte = iptr->sx.s23.s3.bte;
992 /* test s2 for zero */
994 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
995 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
996 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
997 emit_arithmetic_check(cd, iptr, REG_ITMP3);
1001 disp = dseg_add_functionptr(cd, bte->fp);
1003 /* load arguments */
1005 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
1007 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
1008 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
1012 M_ASUB_IMM(96, REG_SP);
1013 M_ALD_DSEG(REG_ITMP2, disp);
1014 M_JSR(REG_RA, REG_ITMP2);
1015 M_AADD_IMM(96, REG_SP);
1019 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1020 M_LNGMOVE(REG_RESULT_PACKED, d);
1021 emit_store_dst(jd, iptr, d);
1025 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1026 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1027 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1029 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1030 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1031 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1033 /* Use only 5 bits of sencond operand. */
1035 M_INTMOVE(s2, REG_ITMP2);
1037 ICONST(REG_ITMP3, 0x1F);
1038 M_IAND(REG_ITMP3, s2);
1042 switch (iptr->opc) {
1055 emit_store_dst(jd, iptr, d);
1058 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1059 /* sx.val.i = constant */
1063 assert(iptr->sx.val.i <= 32);
1065 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1066 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1073 s3 = (1 << iptr->sx.val.i) - 1;
1075 if (N_VALID_IMM(s3)) {
1078 ICONST(REG_ITMP1, -1);
1079 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1080 M_IADD(REG_ITMP1, d);
1083 N_BRC_BACK_PATCH(ref);
1085 M_SRA_IMM(iptr->sx.val.i, d);
1087 emit_store_dst(jd, iptr, d);
1092 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1093 /* sx.val.i = constant */
1095 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1096 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1099 M_MOV(s1, REG_ITMP1);
1103 ICONST(REG_ITMP3, iptr->sx.val.i);
1106 M_IAND(REG_ITMP3, d);
1109 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1115 emit_store_dst(jd, iptr, d);
1119 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1120 /* sx.val.i = constant */
1121 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1122 /* sx.val.i = constant */
1123 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1124 /* sx.val.i = constant */
1125 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1126 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1130 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1132 switch (iptr->opc) {
1133 case ICMD_ISHLCONST:
1136 case ICMD_ISHRCONST:
1139 case ICMD_IUSHRCONST:
1146 emit_store_dst(jd, iptr, d);
1149 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1151 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1153 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1155 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1157 /* Use only 6 bits of second operand */
1159 M_INTMOVE(s2, REG_ITMP2);
1161 ICONST(REG_ITMP1, 0x3F);
1162 M_IAND(REG_ITMP1, s2);
1164 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1165 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1167 /* Destination must be even-odd pair */
1169 if (! N_IS_EVEN_ODD(d)) {
1170 d = REG_ITMP31_PACKED;
1173 assert(N_IS_EVEN_ODD(d));
1177 switch (iptr->opc) {
1179 M_SLDL(s2, GET_HIGH_REG(d));
1182 M_SRDA(s2, GET_HIGH_REG(d));
1185 M_SRDL(s2, GET_HIGH_REG(d));
1191 emit_copy_dst(jd, iptr, d);
1192 emit_store_dst(jd, iptr, d);
1196 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1197 /* sx.val.i = constant */
1198 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1199 /* sx.val.i = constant */
1200 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1201 /* sx.val.l = constant */
1204 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1205 if (! N_IS_EVEN_ODD(d)) {
1206 d = REG_ITMP31_PACKED;
1208 assert(N_IS_EVEN_ODD(d));
1210 s1 = emit_load_s1(jd, iptr, d);
1214 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1216 switch (iptr->opc) {
1217 case ICMD_LSHLCONST:
1218 N_SLDL(GET_HIGH_REG(d), disp, RN);
1220 case ICMD_LSHRCONST:
1221 N_SRDA(GET_HIGH_REG(d), disp, RN);
1223 case ICMD_LUSHRCONST:
1224 N_SRDL(GET_HIGH_REG(d), disp, RN);
1227 N_SLDL(GET_HIGH_REG(d), disp, RN);
1233 emit_copy_dst(jd, iptr, d);
1234 emit_store_dst(jd, iptr, d);
1237 case ICMD_IAND: /* ..., 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_IOR: /* ..., 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);
1267 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1269 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1270 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1271 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1278 emit_store_dst(jd, iptr, d);
1284 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1285 /* sx.val.i = constant */
1286 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1287 /* sx.val.i = constant */
1288 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1289 /* sx.val.i = constant */
1291 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1292 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1295 ICONST(REG_ITMP2, iptr->sx.val.i);
1297 switch (iptr->opc) {
1298 case ICMD_IANDCONST:
1299 M_IAND(REG_ITMP2, d);
1301 case ICMD_IXORCONST:
1302 M_IXOR(REG_ITMP2, d);
1305 M_IOR(REG_ITMP2, d);
1311 emit_store_dst(jd, iptr, d);
1315 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1316 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1317 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1319 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1321 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1322 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1323 dd = GET_LOW_REG(d);
1325 switch (iptr->opc) {
1354 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1355 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1356 dd = GET_HIGH_REG(d);
1358 switch (iptr->opc) {
1387 emit_store_dst(jd, iptr, d);
1390 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1391 /* sx.val.l = constant */
1392 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1393 /* sx.val.l = constant */
1394 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1395 /* sx.val.l = constant */
1397 /* TODO should use memory operand to access data segment, not load */
1399 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1401 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1402 s3 = iptr->sx.val.l & 0xffffffff;
1404 M_INTMOVE(s1, GET_LOW_REG(d));
1406 ICONST(REG_ITMP3, s3);
1408 switch (iptr->opc) {
1409 case ICMD_LANDCONST:
1410 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1412 case ICMD_LXORCONST:
1413 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1416 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1422 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1423 s3 = iptr->sx.val.l >> 32;
1425 M_INTMOVE(s1, GET_HIGH_REG(d));
1427 ICONST(REG_ITMP3, s3);
1429 switch (iptr->opc) {
1430 case ICMD_LANDCONST:
1431 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1433 case ICMD_LXORCONST:
1434 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1437 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1443 emit_store_dst(jd, iptr, d);
1447 /* floating operations ************************************************/
1449 case ICMD_FNEG: /* ..., value ==> ..., - value */
1450 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1451 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1453 emit_store_dst(jd, iptr, d);
1456 case ICMD_DNEG: /* ..., value ==> ..., - value */
1457 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1458 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1460 emit_store_dst(jd, iptr, d);
1463 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1464 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1465 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1466 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1473 emit_store_dst(jd, iptr, d);
1476 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1477 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1478 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1479 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1486 emit_store_dst(jd, iptr, d);
1489 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1490 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1491 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1492 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1496 emit_store_dst(jd, iptr, d);
1499 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1500 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1501 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1502 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1506 emit_store_dst(jd, iptr, d);
1509 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1510 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1511 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1512 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1519 emit_store_dst(jd, iptr, d);
1522 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1523 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1524 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1525 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1532 emit_store_dst(jd, iptr, d);
1535 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1536 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1537 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1538 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1542 emit_store_dst(jd, iptr, d);
1545 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1546 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1547 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1548 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1552 emit_store_dst(jd, iptr, d);
1555 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1556 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1557 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1559 emit_store_dst(jd, iptr, d);
1562 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1563 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1564 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1566 emit_store_dst(jd, iptr, d);
1569 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1573 #ifdef SUPPORT_HERCULES
1577 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1578 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1582 switch (iptr->opc) {
1591 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1592 N_LHI(d, 0); /* Load 0 */
1593 ref1 = cd->mcodeptr;
1594 N_BRC(DD_ANY, 0); /* Exit */
1598 switch (iptr->opc) {
1607 #ifdef SUPPORT_HERCULES
1608 /* Hercules does the conversion using a plain C conversion.
1609 * According to manual, real hardware should *NOT* require this.
1611 * Corner case: Positive float leads to INT_MIN (overflow).
1614 switch (iptr->opc) {
1623 ref2 = cd->mcodeptr;
1624 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1628 ref3 = cd->mcodeptr;
1629 M_BGE(0); /* If integer result is negative, continue */
1631 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1632 M_ILD_DSEG(d, disp);
1634 N_BRC_BACK_PATCH(ref1);
1635 #ifdef SUPPORT_HERCULES
1636 N_BRC_BACK_PATCH(ref2);
1637 N_BRC_BACK_PATCH(ref3);
1639 emit_store_dst(jd, iptr, d);
1643 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1646 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1647 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1648 #ifdef SUPPORT_HERCULES
1651 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1652 disp = dseg_add_double(cd, 0.0 / 0.0);
1653 M_DLD_DSEG(d, disp, REG_ITMP1);
1654 emit_label_br(cd, BRANCH_LABEL_1);
1655 N_BRC_BACK_PATCH(ref);
1658 #ifdef SUPPORT_HERCULES
1659 emit_label(cd, BRANCH_LABEL_1);
1661 emit_store_dst(jd, iptr, d);
1665 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1666 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1667 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1669 emit_store_dst(jd, iptr, d);
1672 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1673 /* == => 0, < => 1, > => -1 */
1677 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1678 /* == => 0, < => 1, > => -1 */
1681 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1682 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1683 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1685 switch (iptr->opc) {
1697 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1698 SZ_BRC + SZ_BRC + SZ_BRC
1701 N_BRC( /* load -1 */
1702 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1703 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1708 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1711 N_LHI(d, 1); /* GT */
1712 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1713 N_LHI(d, -1); /* LT */
1714 M_BR(SZ_BRC + SZ_LHI);
1715 N_LHI(d, 0); /* EQ */
1717 emit_store_dst(jd, iptr, d);
1722 /* memory operations **************************************************/
1724 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1726 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1727 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1729 /* implicit null-pointer check */
1730 M_ILD(d, s1, OFFSET(java_array_t, size));
1731 emit_store_dst(jd, iptr, d);
1735 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1736 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1737 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1738 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1740 /* implicit null-pointer check */
1741 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1743 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1748 emit_store_dst(jd, iptr, d);
1751 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1753 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1754 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1755 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1757 /* implicit null-pointer check */
1758 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1760 M_INTMOVE(s2, REG_ITMP2);
1761 M_SLL_IMM(1, REG_ITMP2);
1763 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1765 /* N_LH does sign extends, undo ! */
1770 emit_store_dst(jd, iptr, d);
1773 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1774 s1 = emit_load_s1(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(1, REG_ITMP2);
1784 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1785 emit_store_dst(jd, iptr, d);
1788 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1789 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1790 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1791 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1793 /* implicit null-pointer check */
1794 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1796 M_INTMOVE(s2, REG_ITMP2);
1797 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1798 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1799 emit_store_dst(jd, iptr, d);
1802 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1804 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1805 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1807 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1809 /* implicit null-pointer check */
1810 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1812 M_INTMOVE(s2, REG_ITMP2);
1813 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1816 GET_LOW_REG(d) /* maybe itmp3 */,
1817 OFFSET(java_intarray_t, data[0]) + 4,
1818 REG_ITMP2, s1 /* maybe itmp1 */
1822 GET_HIGH_REG(d) /* maybe itmp1 */,
1823 OFFSET(java_intarray_t, data[0]),
1824 REG_ITMP2, s1 /* maybe itmp1 */
1827 emit_store_dst(jd, iptr, d);
1831 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1833 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1834 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1835 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1837 /* implicit null-pointer check */
1838 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1840 M_INTMOVE(s2, REG_ITMP2);
1841 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1843 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1845 emit_store_dst(jd, iptr, d);
1848 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1849 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1850 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1851 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1853 /* implicit null-pointer check */
1854 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1856 M_INTMOVE(s2, REG_ITMP2);
1857 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1859 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1861 emit_store_dst(jd, iptr, d);
1864 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1865 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1866 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1867 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1869 /* implicit null-pointer check */
1870 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1872 M_INTMOVE(s2, REG_ITMP2);
1873 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1874 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1875 emit_store_dst(jd, iptr, d);
1878 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1879 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1880 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1881 /* implicit null-pointer check */
1882 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1883 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1885 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1888 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1890 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1891 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1892 /* implicit null-pointer check */
1893 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1894 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1896 M_INTMOVE(s2, REG_ITMP2);
1897 M_SLL_IMM(1, REG_ITMP2);
1899 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1903 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1904 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1905 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1906 /* implicit null-pointer check */
1907 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1908 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1910 M_INTMOVE(s2, REG_ITMP2);
1911 M_SLL_IMM(1, REG_ITMP2);
1913 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1916 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1918 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1919 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1920 /* implicit null-pointer check */
1921 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1923 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1925 M_INTMOVE(s2, REG_ITMP2);
1926 M_SLL_IMM(2, REG_ITMP2);
1928 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1931 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1933 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1934 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1935 /* implicit null-pointer check */
1936 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1938 M_INTMOVE(s2, REG_ITMP2);
1939 M_SLL_IMM(3, REG_ITMP2);
1941 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1942 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1943 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1944 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1947 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1948 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1949 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1950 /* implicit null-pointer check */
1951 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1952 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1954 M_INTMOVE(s2, REG_ITMP2);
1955 M_SLL_IMM(2, REG_ITMP2);
1957 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1960 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1961 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1962 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1963 /* implicit null-pointer check */
1964 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1965 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1967 M_INTMOVE(s2, REG_ITMP2);
1968 M_SLL_IMM(3, REG_ITMP2);
1970 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1973 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1975 s1 = emit_load_s1(jd, iptr, REG_A0);
1976 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1977 /* implicit null-pointer check */
1978 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1979 s3 = emit_load_s3(jd, iptr, REG_A1);
1981 M_INTMOVE(s1, REG_A0);
1982 M_INTMOVE(s3, REG_A1);
1984 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1985 M_ALD_DSEG(REG_ITMP2, disp);
1986 M_ASUB_IMM(96, REG_SP);
1987 M_JSR(REG_RA, REG_ITMP2);
1988 M_AADD_IMM(96, REG_SP);
1990 emit_arraystore_check(cd, iptr);
1992 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1993 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1994 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1996 M_INTMOVE(s2, REG_ITMP2);
1997 M_SLL_IMM(2, REG_ITMP2);
1998 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
2001 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
2002 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2007 case ICMD_GETSTATIC: /* ... ==> ..., value */
2009 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2010 uf = iptr->sx.s23.s3.uf;
2011 fieldtype = uf->fieldref->parseddesc.fd->type;
2012 disp = dseg_add_unique_address(cd, NULL);
2014 /* PROFILE_CYCLE_STOP; */
2016 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2018 /* PROFILE_CYCLE_START; */
2021 fi = iptr->sx.s23.s3.fmiref->p.field;
2022 fieldtype = fi->type;
2023 disp = dseg_add_address(cd, fi->value);
2025 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2028 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
2030 PROFILE_CYCLE_START;
2034 M_ALD_DSEG(REG_ITMP1, disp);
2036 switch (fieldtype) {
2038 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2039 M_ILD(d, REG_ITMP1, 0);
2042 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2043 M_LLD(d, REG_ITMP1, 0);
2046 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2047 M_ALD(d, REG_ITMP1, 0);
2050 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2051 M_FLD(d, REG_ITMP1, 0);
2054 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2055 M_DLD(d, REG_ITMP1, 0);
2059 emit_store_dst(jd, iptr, d);
2063 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2065 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2066 uf = iptr->sx.s23.s3.uf;
2067 fieldtype = uf->fieldref->parseddesc.fd->type;
2068 disp = dseg_add_unique_address(cd, uf);
2070 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2073 fi = iptr->sx.s23.s3.fmiref->p.field;
2074 fieldtype = fi->type;
2075 disp = dseg_add_address(cd, fi->value);
2077 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2079 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
2080 PROFILE_CYCLE_START;
2084 M_ALD_DSEG(REG_ITMP1, disp);
2085 switch (fieldtype) {
2087 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2088 M_IST(s1, REG_ITMP1, 0);
2091 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2092 M_LST(s1, REG_ITMP1, 0);
2095 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2096 M_AST(s1, REG_ITMP1, 0);
2099 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2100 M_FST(s1, REG_ITMP1, 0);
2103 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2104 M_DST(s1, REG_ITMP1, 0);
2109 case ICMD_GETFIELD: /* ... ==> ..., value */
2111 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2112 emit_nullpointer_check(cd, iptr, s1);
2114 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2115 uf = iptr->sx.s23.s3.uf;
2116 fieldtype = uf->fieldref->parseddesc.fd->type;
2119 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2122 fi = iptr->sx.s23.s3.fmiref->p.field;
2123 fieldtype = fi->type;
2127 switch (fieldtype) {
2129 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2133 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2134 if (GET_HIGH_REG(d) == s1) {
2135 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2136 M_ILD(GET_HIGH_REG(d), s1, disp);
2139 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2140 M_ILD(GET_HIGH_REG(d), s1, disp);
2144 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2148 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2152 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2156 emit_store_dst(jd, iptr, d);
2159 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2163 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2164 emit_nullpointer_check(cd, iptr, s1);
2166 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2167 uf = iptr->sx.s23.s3.uf;
2168 fieldtype = uf->fieldref->parseddesc.fd->type;
2172 fi = iptr->sx.s23.s3.fmiref->p.field;
2173 fieldtype = fi->type;
2177 /* We can't add a patcher ref behind this load,
2178 * because the patcher would destroy REG_ITMP3.
2180 * We pass in the disp parameter, how many bytes
2181 * to skip to the to the actual store.
2183 * XXX this relies on patcher_add_patch_ref internals
2186 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2187 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2192 if (IS_INT_LNG_TYPE(fieldtype)) {
2193 if (IS_2_WORD_TYPE(fieldtype))
2194 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2196 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2198 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2201 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2202 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2205 switch (fieldtype) {
2207 M_IST(s2, s1, disp);
2210 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2211 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2214 M_AST(s2, s1, disp);
2217 M_FST(s2, s1, disp);
2220 M_DST(s2, s1, disp);
2227 /* branch operations **************************************************/
2229 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2231 /* PROFILE_CYCLE_STOP; */
2233 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2234 M_INTMOVE(s1, REG_ITMP3_XPTR);
2236 #ifdef ENABLE_VERIFIER
2237 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2238 uc = iptr->sx.s23.s2.uc;
2240 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2242 #endif /* ENABLE_VERIFIER */
2244 disp = dseg_add_functionptr(cd, asm_handle_exception);
2245 M_ALD_DSEG(REG_ITMP1, disp);
2246 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2251 case ICMD_GOTO: /* ... ==> ... */
2252 case ICMD_RET: /* ... ==> ... */
2254 emit_br(cd, iptr->dst.block);
2258 case ICMD_JSR: /* ... ==> ... */
2260 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2264 case ICMD_IFNULL: /* ..., value ==> ... */
2265 case ICMD_IFNONNULL: /* ..., value ==> ... */
2266 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2268 switch (iptr->opc) {
2270 emit_beq(cd, iptr->dst.block);
2272 case ICMD_IFNONNULL:
2273 emit_bne(cd, iptr->dst.block);
2278 case ICMD_IFEQ: /* ..., value ==> ... */
2279 case ICMD_IFLT: /* ..., value ==> ... */
2280 case ICMD_IFLE: /* ..., value ==> ... */
2281 case ICMD_IFNE: /* ..., value ==> ... */
2282 case ICMD_IFGT: /* ..., value ==> ... */
2283 case ICMD_IFGE: /* ..., value ==> ... */
2285 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2287 if (N_VALID_IMM(iptr->sx.val.i))
2288 M_ICMP_IMM(s1, iptr->sx.val.i);
2290 disp = dseg_add_s4(cd, iptr->sx.val.i);
2291 if (N_VALID_DSEG_DISP(disp)) {
2292 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2294 ICONST(REG_ITMP2, disp);
2295 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2299 switch (iptr->opc) {
2301 emit_blt(cd, iptr->dst.block);
2304 emit_ble(cd, iptr->dst.block);
2307 emit_bne(cd, iptr->dst.block);
2310 emit_bgt(cd, iptr->dst.block);
2313 emit_bge(cd, iptr->dst.block);
2316 emit_beq(cd, iptr->dst.block);
2322 case ICMD_IF_LLT: /* ..., value ==> ... */
2323 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2329 /* ATTENTION: compare high words signed and low words unsigned */
2331 # define LABEL_OUT BRANCH_LABEL_1
2333 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2335 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2336 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2338 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2339 if (N_VALID_DSEG_DISP(disp)) {
2340 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2342 ICONST(REG_ITMP2, disp);
2343 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2350 emit_blt(cd, iptr->dst.block);
2351 /* EQ ... fall through */
2352 emit_label_bgt(cd, LABEL_OUT);
2356 emit_bgt(cd, iptr->dst.block);
2357 /* EQ ... fall through */
2358 emit_label_blt(cd, LABEL_OUT);
2361 /* EQ ... fall through */
2362 emit_label_bne(cd, LABEL_OUT);
2365 /* EQ ... fall through */
2366 emit_bne(cd, iptr->dst.block);
2372 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2374 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2375 if (N_VALID_DSEG_DISP(disp)) {
2376 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2378 ICONST(REG_ITMP2, disp);
2379 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2384 emit_blt(cd, iptr->dst.block);
2385 emit_label(cd, LABEL_OUT);
2388 emit_ble(cd, iptr->dst.block);
2389 emit_label(cd, LABEL_OUT);
2392 emit_bgt(cd, iptr->dst.block);
2393 emit_label(cd, LABEL_OUT);
2396 emit_bge(cd, iptr->dst.block);
2397 emit_label(cd, LABEL_OUT);
2400 emit_beq(cd, iptr->dst.block);
2401 emit_label(cd, LABEL_OUT);
2404 emit_bne(cd, iptr->dst.block);
2413 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2414 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2416 /* Compare addresses as 31 bit unsigned integers */
2418 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2419 M_LDA(REG_ITMP1, s1, 0);
2421 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2422 M_LDA(REG_ITMP2, s2, 0);
2424 M_CMP(REG_ITMP1, REG_ITMP2);
2426 switch (iptr->opc) {
2427 case ICMD_IF_ACMPEQ:
2428 emit_beq(cd, iptr->dst.block);
2430 case ICMD_IF_ACMPNE:
2431 emit_bne(cd, iptr->dst.block);
2437 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2438 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2439 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2440 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2441 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2442 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2444 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2445 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2447 switch (iptr->opc) {
2448 case ICMD_IF_ICMPEQ:
2449 emit_beq(cd, iptr->dst.block);
2451 case ICMD_IF_ICMPNE:
2452 emit_bne(cd, iptr->dst.block);
2454 case ICMD_IF_ICMPLT:
2455 emit_blt(cd, iptr->dst.block);
2457 case ICMD_IF_ICMPGT:
2458 emit_bgt(cd, iptr->dst.block);
2460 case ICMD_IF_ICMPLE:
2461 emit_ble(cd, iptr->dst.block);
2463 case ICMD_IF_ICMPGE:
2464 emit_bge(cd, iptr->dst.block);
2470 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2471 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2472 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2473 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2474 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2475 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2480 /* ATTENTION: compare high words signed and low words unsigned */
2482 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2483 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2488 case ICMD_IF_LCMPLT:
2489 case ICMD_IF_LCMPLE:
2490 emit_blt(cd, iptr->dst.block);
2491 /* EQ ... fall through */
2492 out_ref = cd->mcodeptr;
2495 case ICMD_IF_LCMPGT:
2496 case ICMD_IF_LCMPGE:
2497 emit_bgt(cd, iptr->dst.block);
2498 /* EQ ... fall through */
2499 out_ref = cd->mcodeptr;
2502 case ICMD_IF_LCMPEQ:
2503 /* EQ ... fall through */
2504 out_ref = cd->mcodeptr;
2507 case ICMD_IF_LCMPNE:
2508 /* EQ ... fall through */
2509 emit_bne(cd, iptr->dst.block);
2515 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2516 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2521 case ICMD_IF_LCMPLT:
2522 emit_blt(cd, iptr->dst.block);
2524 case ICMD_IF_LCMPLE:
2525 emit_ble(cd, iptr->dst.block);
2527 case ICMD_IF_LCMPGT:
2528 emit_bgt(cd, iptr->dst.block);
2530 case ICMD_IF_LCMPGE:
2531 emit_bge(cd, iptr->dst.block);
2533 case ICMD_IF_LCMPEQ:
2534 emit_beq(cd, iptr->dst.block);
2536 case ICMD_IF_LCMPNE:
2537 emit_bne(cd, iptr->dst.block);
2543 if (out_ref != NULL) {
2544 N_BRC_BACK_PATCH(out_ref);
2550 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2552 REPLACEMENT_POINT_RETURN(cd, iptr);
2553 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2554 M_INTMOVE(s1, REG_RESULT);
2555 goto nowperformreturn;
2557 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2559 REPLACEMENT_POINT_RETURN(cd, iptr);
2560 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2561 M_INTMOVE(s1, REG_RESULT);
2563 #ifdef ENABLE_VERIFIER
2564 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2565 unresolved_class *uc = iptr->sx.s23.s2.uc;
2568 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2569 PROFILE_CYCLE_START;
2571 #endif /* ENABLE_VERIFIER */
2572 goto nowperformreturn;
2574 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2576 REPLACEMENT_POINT_RETURN(cd, iptr);
2577 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2578 M_LNGMOVE(s1, REG_RESULT_PACKED);
2579 goto nowperformreturn;
2581 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2584 REPLACEMENT_POINT_RETURN(cd, iptr);
2585 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2586 M_FLTMOVE(s1, REG_FRESULT);
2587 goto nowperformreturn;
2589 case ICMD_RETURN: /* ... ==> ... */
2591 REPLACEMENT_POINT_RETURN(cd, iptr);
2597 p = cd->stackframesize;
2599 /* call trace function */
2601 #if !defined(NDEBUG)
2602 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2603 emit_verbosecall_exit(jd);
2604 #endif /* !defined(NDEBUG) */
2606 #if defined(ENABLE_THREADS)
2607 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2608 /* we need to save the proper return value */
2610 switch (iptr->opc) {
2612 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2616 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2619 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2622 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2626 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2628 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2629 M_ALD_DSEG(REG_ITMP2, disp);
2631 M_ASUB_IMM(96, REG_SP);
2633 M_AADD_IMM(96, REG_SP);
2635 /* and now restore the proper return value */
2637 switch (iptr->opc) {
2639 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2643 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2646 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2649 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2655 /* restore return address */
2657 p--; M_ALD(REG_RA, REG_SP, p * 8);
2659 /* restore saved registers */
2661 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2662 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2664 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2665 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2668 /* deallocate stack */
2670 if (cd->stackframesize)
2671 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2673 /* generate method profiling code */
2681 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2684 branch_target_t *table;
2686 table = iptr->dst.table;
2688 l = iptr->sx.s23.s2.tablelow;
2689 i = iptr->sx.s23.s3.tablehigh;
2691 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2692 M_INTMOVE(s1, REG_ITMP1);
2696 } else if (N_VALID_IMM(-l)) {
2697 M_ISUB_IMM(l, REG_ITMP1);
2699 ICONST(REG_ITMP2, l);
2700 M_ISUB(REG_ITMP2, REG_ITMP1);
2703 /* number of targets */
2709 ICONST(REG_ITMP2, i);
2710 M_ICMPU(REG_ITMP1, REG_ITMP2);
2711 emit_bge(cd, table[0].block);
2713 /* build jump table top down and use address of lowest entry */
2718 dseg_add_target(cd, table->block);
2723 /* length of dataseg after last dseg_add_target is used by load */
2725 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2726 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2727 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2728 M_JMP(RN, REG_ITMP1);
2733 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2736 lookup_target_t *lookup;
2738 lookup = iptr->dst.lookup;
2740 i = iptr->sx.s23.s2.lookupcount;
2742 MCODECHECK(8 + ((7 + 6) * i) + 5);
2743 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2746 if (N_VALID_IMM(lookup->value)) {
2747 M_ICMP_IMM(s1, lookup->value);
2749 ICONST(REG_ITMP2, lookup->value);
2750 M_ICMP(REG_ITMP2, s1);
2752 emit_beq(cd, lookup->target.block);
2756 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2761 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2763 bte = iptr->sx.s23.s3.bte;
2767 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2768 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2769 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2770 case ICMD_INVOKEINTERFACE:
2772 REPLACEMENT_POINT_INVOKE(cd, iptr);
2774 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2776 um = iptr->sx.s23.s3.um;
2777 md = um->methodref->parseddesc.md;
2780 lm = iptr->sx.s23.s3.fmiref->p.method;
2782 md = lm->parseddesc;
2786 s3 = md->paramcount;
2788 MCODECHECK((s3 << 1) + 64);
2790 /* copy arguments to registers or stack location */
2792 for (s3 = s3 - 1; s3 >= 0; s3--) {
2793 var = VAR(iptr->sx.s23.s2.args[s3]);
2795 /* Already Preallocated? */
2796 if (var->flags & PREALLOC)
2799 if (IS_INT_LNG_TYPE(var->type)) {
2800 if (!md->params[s3].inmemory) {
2801 if (IS_2_WORD_TYPE(var->type)) {
2803 GET_LOW_REG(md->params[s3].regoff),
2804 GET_HIGH_REG(md->params[s3].regoff)
2806 d = emit_load(jd, iptr, var, s1);
2810 s1 = md->params[s3].regoff;
2811 d = emit_load(jd, iptr, var, s1);
2816 if (IS_2_WORD_TYPE(var->type)) {
2817 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2818 M_LST(d, REG_SP, md->params[s3].regoff);
2821 d = emit_load(jd, iptr, var, REG_ITMP1);
2822 M_IST(d, REG_SP, md->params[s3].regoff);
2827 if (!md->params[s3].inmemory) {
2828 s1 = md->params[s3].regoff;
2829 d = emit_load(jd, iptr, var, s1);
2833 d = emit_load(jd, iptr, var, REG_FTMP1);
2834 if (IS_2_WORD_TYPE(var->type))
2835 M_DST(d, REG_SP, md->params[s3].regoff);
2837 M_FST(d, REG_SP, md->params[s3].regoff);
2842 /* generate method profiling code */
2846 switch (iptr->opc) {
2848 if (bte->stub == NULL) {
2849 disp = dseg_add_functionptr(cd, bte->fp);
2850 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2852 disp = dseg_add_functionptr(cd, bte->stub);
2855 if (N_VALID_DSEG_DISP(disp)) {
2856 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2858 N_LHI(REG_ITMP1, disp);
2859 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2863 case ICMD_INVOKESPECIAL:
2865 /* Implicit NULL pointer check */
2866 M_ILD(REG_ITMP1, REG_A0, 0);
2870 case ICMD_INVOKESTATIC:
2872 disp = dseg_add_unique_address(cd, um);
2874 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2878 disp = dseg_add_address(cd, lm->stubroutine);
2880 if (N_VALID_DSEG_DISP(disp)) {
2881 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2883 N_LHI(REG_ITMP1, disp);
2884 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2888 case ICMD_INVOKEVIRTUAL:
2889 /* TODO softnull REG_A0 */
2892 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2897 s1 = OFFSET(vftbl_t, table[0]) +
2898 sizeof(methodptr) * lm->vftblindex;
2901 /* implicit null-pointer check */
2903 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2904 M_ALD(REG_PV, REG_METHODPTR, s1);
2907 case ICMD_INVOKEINTERFACE:
2908 /* TODO softnull REG_A0 */
2910 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2911 * and -0xFFF in index register (itmp1)
2915 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2921 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2922 sizeof(methodptr*) * lm->class->index;
2924 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2927 /* Implicit null-pointer check */
2928 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2929 N_LHI(REG_ITMP2, s1);
2930 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2931 M_ALD(REG_PV, REG_METHODPTR, s2);
2935 /* generate the actual call */
2938 emit_restore_pv(cd);
2940 /* post call finalization */
2942 switch (iptr->opc) {
2944 if (bte->stub == NULL) {
2945 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2950 /* generate method profiling code */
2952 PROFILE_CYCLE_START;
2954 /* store size of call code in replacement point */
2956 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2958 /* store return value */
2960 d = md->returntype.type;
2962 if (d != TYPE_VOID) {
2963 if (IS_INT_LNG_TYPE(d)) {
2964 if (IS_2_WORD_TYPE(d)) {
2965 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2966 M_LNGMOVE(REG_RESULT_PACKED, s1);
2969 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2970 M_INTMOVE(REG_RESULT, s1);
2974 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2975 M_FLTMOVE(REG_FRESULT, s1);
2977 emit_store_dst(jd, iptr, s1);
2983 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2985 /* val.a: (classinfo*) superclass */
2987 /* superclass is an interface:
2989 * OK if ((sub == NULL) ||
2990 * (sub->vftbl->interfacetablelength > super->index) &&
2991 * (sub->vftbl->interfacetable[-super->index] != NULL));
2993 * superclass is a class:
2995 * OK if ((sub == NULL) || (0
2996 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2997 * super->vftbl->diffval));
3000 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
3001 /* object type cast-check */
3004 vftbl_t *supervftbl;
3007 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3008 # define LABEL_CLASS BRANCH_LABEL_2
3009 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3010 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
3011 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
3013 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3019 super = iptr->sx.s23.s3.c.cls;
3020 superindex = super->index;
3021 supervftbl = super->vftbl;
3024 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3025 CODEGEN_CRITICAL_SECTION_NEW;
3027 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3029 /* if class is not resolved, check which code to call */
3031 if (super == NULL) {
3033 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3035 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3037 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3038 iptr->sx.s23.s3.c.ref,
3041 ICONST(REG_ITMP3, ACC_INTERFACE);
3043 if (N_VALID_DSEG_DISP(disp)) {
3044 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3046 ICONST(REG_ITMP2, disp);
3047 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3049 emit_label_beq(cd, LABEL_CLASS);
3052 /* interface checkcast code */
3054 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3055 if (super == NULL) {
3056 patcher_add_patch_ref(jd,
3057 PATCHER_checkcast_instanceof_interface,
3058 iptr->sx.s23.s3.c.ref,
3062 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3065 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3066 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3067 M_ISUB_IMM(superindex, REG_ITMP3);
3068 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3071 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3072 superindex * sizeof(methodptr*))
3074 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3075 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3077 if (super == NULL) {
3078 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3082 /* class checkcast code */
3084 if (super == NULL) {
3085 emit_label(cd, LABEL_CLASS);
3088 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3089 if (super == NULL) {
3090 disp = dseg_add_unique_address(cd, NULL);
3092 patcher_add_patch_ref(jd,
3093 PATCHER_resolve_classref_to_vftbl,
3094 iptr->sx.s23.s3.c.ref,
3098 disp = dseg_add_address(cd, supervftbl);
3100 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3104 CODEGEN_CRITICAL_SECTION_START;
3106 /* REG_ITMP3 := baseval(s1) */
3107 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3108 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3110 /* REG_ITMP2 := baseval(class) */
3111 M_ALD_DSEG(REG_ITMP2, disp);
3112 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3114 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3115 M_ISUB(REG_ITMP2, REG_ITMP3);
3117 /* REG_ITMP2 := diffval(class) */
3118 M_ALD_DSEG(REG_ITMP2, disp);
3119 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3121 CODEGEN_CRITICAL_SECTION_END;
3123 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3125 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3126 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3127 /* Branch if greater then */
3129 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3130 M_ALD_DSEG(REG_ITMP3, disp);
3132 CODEGEN_CRITICAL_SECTION_START;
3134 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3135 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3136 M_ISUB(REG_ITMP3, REG_ITMP2);
3137 M_ALD_DSEG(REG_ITMP3, disp);
3138 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3140 CODEGEN_CRITICAL_SECTION_END;
3142 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3143 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3144 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3145 /* Branch if greater then */
3147 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3150 if (super == NULL) {
3151 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3152 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3153 } else if (super->flags & ACC_INTERFACE) {
3154 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3156 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3159 d = codegen_reg_of_dst(jd, iptr, s1);
3161 # undef LABEL_EXIT_CHECK_NULL
3163 # undef LABEL_EXIT_INTERFACE_NULL
3164 # undef LABEL_EXIT_INTERFACE_DONE
3165 # undef LABEL_EXIT_CLASS_NULL
3168 /* array type cast-check */
3170 s1 = emit_load_s1(jd, iptr, REG_A0);
3171 M_INTMOVE(s1, REG_A0);
3173 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3174 disp = dseg_add_unique_address(cd, NULL);
3176 patcher_add_patch_ref(jd,
3177 PATCHER_resolve_classref_to_classinfo,
3178 iptr->sx.s23.s3.c.ref,
3182 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3184 M_ALD_DSEG(REG_A1, disp);
3185 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3186 M_ALD_DSEG(REG_ITMP1, disp);
3187 M_ASUB_IMM(96, REG_SP);
3188 M_JSR(REG_RA, REG_ITMP1);
3189 M_AADD_IMM(96, REG_SP);
3191 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3192 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3194 d = codegen_reg_of_dst(jd, iptr, s1);
3198 emit_store_dst(jd, iptr, d);
3201 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3202 /* val.a: (classinfo*) superclass */
3204 /* superclass is an interface:
3206 * return (sub != NULL) &&
3207 * (sub->vftbl->interfacetablelength > super->index) &&
3208 * (sub->vftbl->interfacetable[-super->index] != NULL);
3210 * superclass is a class:
3212 * return ((sub != NULL) && (0
3213 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3214 * super->vftbl->diffvall));
3216 * If superclass is unresolved, we include both code snippets
3217 * above, a patcher resolves the class' flags and we select
3218 * the right code at runtime.
3223 vftbl_t *supervftbl;
3226 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3232 super = iptr->sx.s23.s3.c.cls;
3233 superindex = super->index;
3234 supervftbl = super->vftbl;
3237 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3238 # define LABEL_CLASS BRANCH_LABEL_2
3239 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3240 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3241 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3242 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3244 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3245 CODEGEN_CRITICAL_SECTION_NEW;
3247 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3248 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3250 M_MOV(s1, REG_ITMP1);
3254 /* if class is not resolved, check which code to call */
3256 if (super == NULL) {
3260 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3262 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3264 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3265 iptr->sx.s23.s3.c.ref, disp);
3267 ICONST(REG_ITMP3, ACC_INTERFACE);
3269 if (N_VALID_DSEG_DISP(disp)) {
3270 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3272 ICONST(REG_ITMP2, disp);
3273 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3276 emit_label_beq(cd, LABEL_CLASS);
3279 /* interface instanceof code */
3281 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3282 if (super == NULL) {
3283 /* If d == REG_ITMP2, then it's destroyed in check
3288 patcher_add_patch_ref(jd,
3289 PATCHER_checkcast_instanceof_interface,
3290 iptr->sx.s23.s3.c.ref, 0);
3295 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3298 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3299 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3300 M_ISUB_IMM(superindex, REG_ITMP3);
3302 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3306 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3307 superindex * sizeof(methodptr*))
3309 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3311 /* d := (REG_ITMP1 != 0) */
3313 N_LTR(d, REG_ITMP1);
3314 M_BEQ(SZ_BRC + SZ_LHI);
3317 if (super == NULL) {
3318 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3322 /* class instanceof code */
3324 if (super == NULL) {
3325 emit_label(cd, LABEL_CLASS);
3328 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3329 if (super == NULL) {
3330 disp = dseg_add_unique_address(cd, NULL);
3332 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3333 iptr->sx.s23.s3.c.ref,
3337 disp = dseg_add_address(cd, supervftbl);
3342 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3345 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3346 M_ALD_DSEG(REG_ITMP2, disp);
3348 CODEGEN_CRITICAL_SECTION_START;
3350 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3351 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3352 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3354 CODEGEN_CRITICAL_SECTION_END;
3356 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3358 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3360 M_BGT(SZ_BRC + SZ_LHI);
3364 if (super == NULL) {
3365 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3366 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3367 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3368 } else if (super->flags & ACC_INTERFACE) {
3369 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3370 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3372 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3375 # undef LABEL_EXIT_CHECK_NULL
3377 # undef LABEL_EXIT_INTERFACE_NULL
3378 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3379 # undef LABEL_EXIT_INTERFACE_DONE
3380 # undef LABEL_EXIT_CLASS_NULL
3382 emit_store_dst(jd, iptr, d);
3388 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3390 /* check for negative sizes and copy sizes to stack if necessary */
3392 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3395 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3397 /* copy SAVEDVAR sizes to stack */
3398 var = VAR(iptr->sx.s23.s2.args[s1]);
3400 /* Already Preallocated? */
3401 if (!(var->flags & PREALLOC)) {
3402 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3403 M_IST(s2, REG_SP, s1 * 4);
3407 /* is a patcher function set? */
3409 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3410 disp = dseg_add_unique_address(cd, 0);
3412 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3413 iptr->sx.s23.s3.c.ref,
3417 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3419 /* a0 = dimension count */
3421 ICONST(REG_A0, iptr->s1.argcount);
3423 /* a1 = classinfo */
3425 M_ALD_DSEG(REG_A1, disp);
3427 /* a2 = pointer to dimensions = stack pointer */
3429 M_MOV(REG_SP, REG_A2);
3431 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3432 M_ALD_DSEG(REG_ITMP1, disp);
3433 M_ASUB_IMM(96, REG_SP);
3434 M_JSR(REG_RA, REG_ITMP1);
3435 M_AADD_IMM(96, REG_SP);
3437 /* check for exception before result assignment */
3439 emit_exception_check(cd, iptr);
3441 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3442 M_INTMOVE(REG_RESULT, s1);
3443 emit_store_dst(jd, iptr, s1);
3448 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3452 } /* for instruction */
3454 MCODECHECK(512); /* XXX require a lower number? */
3456 /* At the end of a basic block we may have to append some nops,
3457 because the patcher stub calling code might be longer than the
3458 actual instruction. So codepatching does not change the
3459 following block unintentionally. */
3461 if (cd->mcodeptr < cd->lastmcodeptr) {
3462 while (cd->mcodeptr < cd->lastmcodeptr) {
3467 } /* if (bptr -> flags >= BBREACHED) */
3468 } /* for basic block */
3470 dseg_createlinenumbertable(cd);
3472 /* generate stubs */
3474 emit_patcher_traps(jd);
3476 /* everything's ok */
3482 /* codegen_emit_stub_compiler **************************************************
3484 Emits a stub routine which calls the compiler.
3486 *******************************************************************************/
3488 void codegen_emit_stub_compiler(jitdata *jd)
3493 /* get required compiler data */
3498 /* code for the stub */
3500 /* don't touch ITMP2 as it cointains the return address */
3502 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3504 /* REG_METHODPTR (REG_ITMP1) already used */
3505 M_ILD_DSEG(REG_ITMP3, -2 * SIZEOF_VOID_P); /* methodinfo */
3506 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3511 /* codegen_emit_stub_native ****************************************************
3513 Emits a stub routine which calls a native method.
3515 *******************************************************************************/
3518 arguments on stack \
3519 -------------------------------------------------| <- SP on nativestub entry
3521 callee saved int regs (none) |
3522 callee saved float regs (none) | stack frame like in cacao
3523 local variable slots (none) |
3524 arguments for calling methods (none) /
3525 ------------------------------------------------------------------ <- datasp
3530 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3531 0 - 96 register save area for callee /
3532 -------------------------------------------------------- <- SP native method
3534 SP after method entry
3537 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3543 s4 i, j; /* count variables */
3548 /* get required compiler data */
3554 /* set some variables */
3558 /* calculate stackframe size */
3560 cd->stackframesize =
3561 1 + /* return address */
3562 sizeof(stackframeinfo_t) / 8 +
3563 sizeof(localref_table) / 8 +
3566 (96 / 8); /* linkage area */
3568 /* keep stack 8-byte aligned */
3570 /*ALIGN_2(cd->stackframesize);*/
3572 /* create method header */
3574 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3575 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3576 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3577 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3578 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3579 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3580 (void) dseg_addlinenumbertablesize(cd);
3581 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3585 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3586 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3588 /* store return address */
3590 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3592 /* get function address (this must happen before the stackframeinfo) */
3594 funcdisp = dseg_add_functionptr(cd, f);
3597 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
3599 #if defined(ENABLE_GC_CACAO)
3600 /* Save callee saved integer registers in stackframeinfo (GC may
3601 need to recover them during a collection). */
3603 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3604 OFFSET(stackframeinfo_t, intregs);
3606 for (i = 0; i < INT_SAV_CNT; i++)
3607 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3610 /* save integer and float argument registers */
3612 for (i = 0; i < md->paramcount; i++) {
3613 if (!md->params[i].inmemory) {
3614 s1 = md->params[i].regoff;
3616 switch (md->paramtypes[i].type) {
3619 M_IST(s1, REG_SP, 96 + i * 8);
3622 M_LST(s1, REG_SP, 96 + i * 8);
3626 M_DST(s1, REG_SP, 96 + i * 8);
3632 /* create native stack info */
3634 M_MOV(REG_SP, REG_A0);
3635 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3636 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3637 M_ALD_DSEG(REG_ITMP2, disp);
3640 /* remember class argument */
3642 if (m->flags & ACC_STATIC)
3643 M_MOV(REG_RESULT, REG_ITMP3);
3645 /* restore integer and float argument registers */
3647 for (i = 0; i < md->paramcount; i++) {
3648 if (!md->params[i].inmemory) {
3649 s1 = md->params[i].regoff;
3651 switch (md->paramtypes[i].type) {
3654 M_ILD(s1, REG_SP, 96 + i * 8);
3657 M_LLD(s1, REG_SP, 96 + i * 8);
3661 M_DLD(s1, REG_SP, 96 + i * 8);
3667 /* copy or spill arguments to new locations */
3669 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3670 t = md->paramtypes[i].type;
3672 if (IS_INT_LNG_TYPE(t)) {
3673 if (!md->params[i].inmemory) {
3674 s1 = md->params[i].regoff;
3675 s2 = nmd->params[j].regoff;
3677 if (!nmd->params[j].inmemory) {
3678 if (IS_2_WORD_TYPE(t))
3684 if (IS_2_WORD_TYPE(t))
3685 M_LST(s1, REG_SP, s2);
3687 M_IST(s1, REG_SP, s2);
3691 s1 = md->params[i].regoff + cd->stackframesize * 8;
3692 s2 = nmd->params[j].regoff;
3694 if (IS_2_WORD_TYPE(t)) {
3695 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3697 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3702 /* We only copy spilled float arguments, as the float
3703 argument registers keep unchanged. */
3705 if (md->params[i].inmemory) {
3706 s1 = md->params[i].regoff + cd->stackframesize * 8;
3707 s2 = nmd->params[j].regoff;
3709 if (IS_2_WORD_TYPE(t)) {
3710 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3712 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3718 /* Handle native Java methods. */
3720 if (m->flags & ACC_NATIVE) {
3721 /* put class into second argument register */
3723 if (m->flags & ACC_STATIC)
3724 M_MOV(REG_ITMP3, REG_A1);
3726 /* put env into first argument register */
3728 disp = dseg_add_address(cd, _Jv_env);
3729 M_ALD_DSEG(REG_A0, disp);
3732 /* generate the actual native call */
3734 M_ALD_DSEG(REG_ITMP2, funcdisp);
3737 /* save return value */
3739 switch (md->returntype.type) {
3742 M_IST(REG_RESULT, REG_SP, 96);
3745 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3749 M_DST(REG_FRESULT, REG_SP, 96);
3755 /* remove native stackframe info */
3757 M_MOV(REG_SP, REG_A0);
3758 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3759 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3760 M_ALD_DSEG(REG_ITMP1, disp);
3763 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3765 /* restore return value */
3767 switch (md->returntype.type) {
3770 M_ILD(REG_RESULT, REG_SP, 96);
3773 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3777 M_DLD(REG_FRESULT, REG_SP, 96);
3783 #if defined(ENABLE_GC_CACAO)
3784 /* Restore callee saved integer registers from stackframeinfo (GC
3785 might have modified them during a collection). */
3787 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3788 OFFSET(stackframeinfo_t, intregs);
3790 for (i = 0; i < INT_SAV_CNT; i++)
3791 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3794 /* load return address */
3796 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3798 /* remove stackframe */
3800 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3802 /* check for exception */
3804 M_TEST(REG_ITMP3_XPTR);
3805 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3809 /* handle exception */
3811 M_MOV(REG_RA, REG_ITMP1_XPC);
3813 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3814 M_ALD_DSEG(REG_ITMP2, disp);
3815 M_JMP(RN, REG_ITMP2);
3817 /* generate patcher traps */
3819 emit_patcher_traps(jd);
3823 * These are local overrides for various environment variables in Emacs.
3824 * Please do not remove this and leave it at the end of the file, where
3825 * Emacs will automagically detect them.
3826 * ---------------------------------------------------------------------
3829 * indent-tabs-mode: t
3833 * vim:noexpandtab:sw=4:ts=4: