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 8278 2007-08-08 17:10:18Z michi $
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 #define OOPS() assert(0);
76 #define SUPPORT_HERCULES 1
80 /* codegen *********************************************************************
82 Generates machine code.
84 *******************************************************************************/
87 bool codegen_emit(jitdata *jd)
93 s4 len, s1, s2, s3, d, dd, disp;
96 varinfo *var, *var1, *var2, *dst;
100 constant_classref *cr;
101 unresolved_class *uc;
102 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
103 unresolved_method *um;
104 builtintable_entry *bte;
107 unresolved_field *uf;
110 rplpoint *replacementpoint;
114 /* get required compiler data */
121 /* prevent compiler warnings */
134 /* space to save used callee saved registers */
136 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
137 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
139 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
142 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
145 #if defined(ENABLE_THREADS)
146 /* Space to save argument of monitor_enter and Return Values to
147 survive monitor_exit. The stack position for the argument can
148 not be shared with place to save the return register
149 since both values reside in R2. */
151 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
152 /* reserve 2 slots for long/double return values for monitorexit */
154 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
155 cd->stackframesize += 3;
157 cd->stackframesize += 2;
161 /* Keep stack of non-leaf functions 16-byte aligned for calls into
162 native code e.g. libc or jni (alignment problems with
165 if (!jd->isleafmethod || opt_verbosecall )
166 /* TODO really 16 bytes ? */
167 cd->stackframesize = (cd->stackframesize + 3) & ~3;
169 /* create method header */
171 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
172 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
174 #if defined(ENABLE_THREADS)
175 /* IsSync contains the offset relative to the stack pointer for the
176 argument of monitor_exit used in the exception handler. Since the
177 offset could be zero and give a wrong meaning of the flag it is
181 if (checksync && (m->flags & ACC_SYNCHRONIZED))
182 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
186 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
188 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
189 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
190 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
192 (void) dseg_addlinenumbertablesize(cd);
194 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
196 /* create exception table */
198 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
199 dseg_add_target(cd, ex->start);
200 dseg_add_target(cd, ex->end);
201 dseg_add_target(cd, ex->handler);
202 (void) dseg_add_unique_address(cd, ex->catchtype.any);
207 M_AADD_IMM(N_PV_OFFSET, REG_PV);
209 /* generate method profiling code */
211 #if defined(ENABLE_PROFILING)
212 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
213 /* count frequency */
214 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
215 ICONST(REG_ITMP2, 1);
216 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
217 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
223 /* create stack frame (if necessary) */
225 if (cd->stackframesize)
226 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
228 /* save used callee saved registers and return address */
230 p = cd->stackframesize;
231 p--; M_AST(REG_RA, REG_SP, p * 4);
233 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
234 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
236 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
237 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
240 /* take arguments out of register or stack frame */
244 for (p = 0, l = 0; p < md->paramcount; p++) {
245 t = md->paramtypes[p].type;
246 varindex = jd->local_map[l * 5 + t];
249 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
252 if (varindex == UNUSED)
257 s1 = md->params[p].regoff;
258 if (IS_INT_LNG_TYPE(t)) { /* integer args */
259 if (IS_2_WORD_TYPE(t)) {
267 if (!md->params[p].inmemory) { /* register arguments */
268 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
269 if (IS_2_WORD_TYPE(t))
270 M_LNGMOVE(s2, var->vv.regoff);
272 M_INTMOVE(s2, var->vv.regoff);
274 } else { /* reg arg -> spilled */
275 if (IS_2_WORD_TYPE(t))
276 M_LST(s2, REG_SP, var->vv.regoff);
278 M_IST(s2, REG_SP, var->vv.regoff);
281 } else { /* stack arguments */
282 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
283 if (IS_2_WORD_TYPE(t))
284 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
286 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
288 } else { /* stack arg -> spilled */
289 if (IS_2_WORD_TYPE(t)) {
290 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
292 N_MVC(var->vv.regoff, 4, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
297 } else { /* floating args */
298 if (!md->params[p].inmemory) { /* register arguments */
300 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
301 M_FLTMOVE(s2, var->vv.regoff);
303 } else { /* reg arg -> spilled */
304 if (IS_2_WORD_TYPE(t))
305 M_DST(s2, REG_SP, var->vv.regoff);
307 M_FST(s2, REG_SP, var->vv.regoff);
310 } else { /* stack arguments */
311 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
312 if (IS_2_WORD_TYPE(t))
313 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
316 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
318 } else { /* stack-arg -> spilled */
319 if (IS_2_WORD_TYPE(t)) {
320 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
321 var->vv.regoff = cd->stackframesize * 4 + s1;
324 N_MVC(var->vv.regoff, 4, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
331 /* save monitorenter argument */
333 #if defined(ENABLE_THREADS)
334 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
335 /* stack offset for monitor argument */
340 if (opt_verbosecall) {
341 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
343 for (p = 0; p < INT_ARG_CNT; p++)
344 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
346 for (p = 0; p < FLT_ARG_CNT; p++)
347 M_FST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
349 s1 += ((INT_ARG_CNT + FLT_ARG_CNT) * 2);
353 /* decide which monitor enter function to call */
355 if (m->flags & ACC_STATIC) {
356 disp = dseg_add_address(cd, &m->class->object.header);
357 M_ALD_DSEG(REG_A0, disp);
361 M_BNE(SZ_BRC + SZ_ILL);
362 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
365 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
366 M_ALD_DSEG(REG_ITMP3, disp);
368 M_AST(REG_A0, REG_SP, s1 * 4);
370 M_ASUB_IMM(96, REG_SP);
372 M_AADD_IMM(96, REG_SP);
375 if (opt_verbosecall) {
376 for (p = 0; p < INT_ARG_CNT; p++)
377 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
379 for (p = 0; p < FLT_ARG_CNT; p++)
380 M_FLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
382 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
389 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
390 emit_verbosecall_enter(jd);
391 #endif /* !defined(NDEBUG) */
395 /* end of header generation */
397 /* create replacement points */
399 REPLACEMENT_POINTS_INIT(cd, jd);
401 /* walk through all basic blocks */
403 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
405 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
407 if (bptr->flags >= BBREACHED) {
409 /* branch resolving */
411 codegen_resolve_branchrefs(cd, bptr);
413 /* handle replacement points */
415 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
417 /* copy interface registers to their destination */
422 #if defined(ENABLE_PROFILING)
423 /* generate basicblock profiling code */
425 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
426 /* count frequency */
428 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
429 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
430 ICONST(REG_ITMP2, 1);
431 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
432 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
434 /* if this is an exception handler, start profiling again */
436 if (bptr->type == BBTYPE_EXH)
441 #if defined(ENABLE_LSRA)
445 src = bptr->invars[len];
446 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
447 if (bptr->type == BBTYPE_EXH) {
448 /* d = reg_of_var(rd, src, REG_ITMP1); */
449 if (!IS_INMEMORY(src->flags))
453 M_INTMOVE(REG_ITMP1, d);
454 emit_store(jd, NULL, src, d);
464 var = VAR(bptr->invars[len]);
465 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
466 if (bptr->type == BBTYPE_EXH) {
467 d = codegen_reg_of_var(0, var, REG_ITMP1);
468 M_INTMOVE(REG_ITMP1, d);
469 emit_store(jd, NULL, var, d);
473 assert((var->flags & INOUT));
476 #if defined(ENABLE_LSRA)
479 /* walk through all instructions */
484 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
485 if (iptr->line != currentline) {
486 dseg_addlinenumber(cd, iptr->line);
487 currentline = iptr->line;
490 MCODECHECK(1024); /* 1KB should be enough */
493 case ICMD_NOP: /* ... ==> ... */
494 case ICMD_POP: /* ..., value ==> ... */
495 case ICMD_POP2: /* ..., value, value ==> ... */
498 case ICMD_INLINE_START:
500 REPLACEMENT_POINT_INLINE_START(cd, iptr);
503 case ICMD_INLINE_BODY:
505 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
506 dseg_addlinenumber_inline_start(cd, iptr);
507 dseg_addlinenumber(cd, iptr->line);
510 case ICMD_INLINE_END:
512 dseg_addlinenumber_inline_end(cd, iptr);
513 dseg_addlinenumber(cd, iptr->line);
516 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
517 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
518 emit_nullpointer_check(cd, iptr, s1);
521 /* constant operations ************************************************/
523 case ICMD_ICONST: /* ... ==> ..., constant */
524 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
525 ICONST(d, iptr->sx.val.i);
526 emit_store_dst(jd, iptr, d);
529 case ICMD_LCONST: /* ... ==> ..., constant */
531 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
532 LCONST(d, iptr->sx.val.l);
533 emit_store_dst(jd, iptr, d);
536 case ICMD_FCONST: /* ... ==> ..., constant */
537 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
538 disp = dseg_add_float(cd, iptr->sx.val.f);
539 M_FLD_DSEG(d, disp, REG_ITMP1);
540 emit_store_dst(jd, iptr, d);
543 case ICMD_DCONST: /* ... ==> ..., constant */
544 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
545 disp = dseg_add_double(cd, iptr->sx.val.d);
546 M_DLD_DSEG(d, disp, REG_ITMP1);
547 emit_store_dst(jd, iptr, d);
550 case ICMD_ACONST: /* ... ==> ..., constant */
551 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
553 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
554 cr = iptr->sx.val.c.ref;
555 disp = dseg_add_unique_address(cd, cr);
557 /* PROFILE_CYCLE_STOP; */
559 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
562 /* PROFILE_CYCLE_START; */
566 if (iptr->sx.val.anyptr == 0) {
569 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
573 emit_store_dst(jd, iptr, d);
577 /* load/store/copy/move operations ************************************/
579 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
580 case ICMD_ALOAD: /* s1 = local variable */
584 case ICMD_ISTORE: /* ..., value ==> ... */
595 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
599 /* integer operations *************************************************/
601 case ICMD_INEG: /* ..., value ==> ..., - value */
603 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
604 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
606 emit_store_dst(jd, iptr, d);
610 case ICMD_LNEG: /* ..., value ==> ..., - value */
612 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
613 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
614 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
615 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
616 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
617 N_AHI(GET_HIGH_REG(d), -1);
618 emit_store_dst(jd, iptr, d);
621 case ICMD_I2L: /* ..., value ==> ..., value */
623 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
624 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
626 M_INTMOVE(s1, GET_HIGH_REG(d));
627 ICONST(GET_LOW_REG(d), 0);
628 M_SRDA_IMM(32, GET_HIGH_REG(d));
630 emit_copy_dst(jd, iptr, d);
631 emit_store_dst(jd, iptr, d);
632 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
636 case ICMD_L2I: /* ..., value ==> ..., value */
637 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
638 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
639 M_INTMOVE(GET_LOW_REG(s1), d);
640 emit_store_dst(jd, iptr, d);
643 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
644 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
645 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
649 emit_store_dst(jd, iptr, d);
652 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
653 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
654 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
658 emit_store_dst(jd, iptr, d);
661 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
663 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
664 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
668 emit_store_dst(jd, iptr, d);
671 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
673 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
674 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
675 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
682 emit_store_dst(jd, iptr, d);
687 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
688 /* sx.val.i = constant */
689 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
690 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
693 if (N_VALID_IMM(iptr->sx.val.i)) {
694 M_IADD_IMM(iptr->sx.val.i, d);
696 ICONST(REG_ITMP2, iptr->sx.val.i);
697 M_IADD(REG_ITMP2, d);
699 emit_store_dst(jd, iptr, d);
702 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
704 /* M, (r, q) -> (r, q) */
706 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
708 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
709 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
710 dd = GET_HIGH_REG(d);
719 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
720 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
730 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
731 N_AHI(GET_HIGH_REG(d), 1);
733 emit_store_dst(jd, iptr, d);
736 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
737 /* sx.val.l = constant */
739 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
740 dd = GET_HIGH_REG(d);
742 s1 = emit_load_s1_high(jd, iptr, dd);
743 s3 = iptr->sx.val.l >> 32;
747 if (N_VALID_IMM(s3)) {
750 ICONST(REG_ITMP3, s3);
751 M_IADD(REG_ITMP3, dd);
755 s1 = emit_load_s1_low(jd, iptr, dd);
756 s3 = iptr->sx.val.l & 0xffffffff;
757 ICONST(REG_ITMP3, s3);
760 N_ALR(dd, REG_ITMP3);
762 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
763 N_AHI(GET_HIGH_REG(d), 1);
765 emit_store_dst(jd, iptr, d);
768 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
770 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
771 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
772 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
774 M_INTMOVE(s1, REG_ITMP1);
775 M_ISUB(s2, REG_ITMP1);
776 M_INTMOVE(REG_ITMP1, d);
781 emit_store_dst(jd, iptr, d);
785 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
786 /* sx.val.i = constant */
788 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
789 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
792 if (N_VALID_IMM(-iptr->sx.val.i)) {
793 M_ISUB_IMM(iptr->sx.val.i, d);
795 ICONST(REG_ITMP2, iptr->sx.val.i);
796 M_ISUB(REG_ITMP2, d);
798 emit_store_dst(jd, iptr, d);
802 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
804 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
806 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
807 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
808 dd = GET_HIGH_REG(d);
811 M_INTMOVE(s2, REG_ITMP3);
818 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
819 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
823 M_INTMOVE(s2, REG_ITMP3);
830 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
831 N_AHI(GET_HIGH_REG(d), -1);
833 emit_store_dst(jd, iptr, d);
836 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
837 /* sx.val.l = constant */
839 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
841 dd = GET_HIGH_REG(d);
842 s1 = emit_load_s1_high(jd, iptr, dd);
843 s3 = iptr->sx.val.l >> 32;
847 if (N_VALID_IMM(-s3)) {
850 ICONST(REG_ITMP3, s3);
851 M_ISUB(REG_ITMP3, dd);
855 s1 = emit_load_s1_low(jd, iptr, dd);
856 s3 = iptr->sx.val.l & 0xffffffff;
857 ICONST(REG_ITMP3, s3);
860 N_SLR(dd, REG_ITMP3);
862 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
863 N_AHI(GET_HIGH_REG(d), -1);
865 emit_store_dst(jd, iptr, d);
868 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
870 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
871 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
872 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
879 emit_store_dst(jd, iptr, d);
883 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
884 /* sx.val.i = constant */
885 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
886 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
888 if (iptr->sx.val.i == 2) {
890 } else if (N_VALID_IMM(iptr->sx.val.i)) {
891 M_IMUL_IMM(iptr->sx.val.i, d);
893 disp = dseg_add_s4(cd, iptr->sx.val.i);
894 M_ILD_DSEG(REG_ITMP2, disp);
895 M_IMUL(REG_ITMP2, d);
897 emit_store_dst(jd, iptr, d);
900 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
901 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
903 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
904 emit_arithmetic_check(cd, iptr, s2);
906 /* For this operation we need a register pair.
907 * We will use r0 and itmp1 and will backup r0.
910 M_INTMOVE(R0, REG_ITMP3);
912 /* We won't check for division by 0, we catch a SIGFPE instead
913 * Special case 0x80000000 / 0xffffffff handled by signal handler too.
916 s1 = emit_load_s1(jd, iptr, R0);
925 d = codegen_reg_of_dst(jd, iptr, R0);
929 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
930 M_INTMOVE(REG_ITMP1, d);
934 emit_store_dst(jd, iptr, d);
936 /* If destionation of operation was not register R0,
940 if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
941 M_INTMOVE(REG_ITMP3, R0);
946 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
947 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
949 bte = iptr->sx.s23.s3.bte;
952 /* test s2 for zero */
954 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
955 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
956 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
957 emit_arithmetic_check(cd, iptr, REG_ITMP3);
961 disp = dseg_add_functionptr(cd, bte->fp);
965 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
967 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
968 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
972 M_ASUB_IMM(96, REG_SP);
973 M_ALD_DSEG(REG_ITMP3, disp);
974 M_JSR(REG_RA, REG_ITMP3);
975 M_AADD_IMM(96, REG_SP);
979 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
980 M_LNGMOVE(REG_RESULT_PACKED, d);
981 emit_store_dst(jd, iptr, d);
985 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
986 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
987 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
989 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
990 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
991 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
993 /* Use only 5 bits of sencond operand. */
995 M_INTMOVE(s2, REG_ITMP2);
997 ICONST(REG_ITMP3, 0x1F);
998 M_IAND(REG_ITMP3, s2);
1002 switch (iptr->opc) {
1015 emit_store_dst(jd, iptr, d);
1018 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1019 /* sx.val.i = constant */
1023 assert(iptr->sx.val.i <= 32);
1025 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1026 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1033 s3 = (1 << iptr->sx.val.i) - 1;
1035 if (N_VALID_IMM(s3)) {
1038 ICONST(REG_ITMP1, -1);
1039 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1040 M_IADD(REG_ITMP1, d);
1043 N_BRC_BACK_PATCH(ref);
1045 M_SRA_IMM(iptr->sx.val.i, d);
1047 emit_store_dst(jd, iptr, d);
1052 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1053 /* sx.val.i = constant */
1055 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1056 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1059 M_MOV(s1, REG_ITMP1);
1063 ICONST(REG_ITMP3, iptr->sx.val.i);
1066 M_IAND(REG_ITMP3, d);
1069 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1075 emit_store_dst(jd, iptr, d);
1079 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1080 /* sx.val.i = constant */
1081 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1082 /* sx.val.i = constant */
1083 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1084 /* sx.val.i = constant */
1085 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1086 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1090 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1092 switch (iptr->opc) {
1093 case ICMD_ISHLCONST:
1096 case ICMD_ISHRCONST:
1099 case ICMD_IUSHRCONST:
1106 emit_store_dst(jd, iptr, d);
1109 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1111 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1113 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1115 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1117 /* Use only 6 bits of second operand */
1119 M_INTMOVE(s2, REG_ITMP3);
1121 ICONST(REG_ITMP2, 0x3F);
1122 M_IAND(REG_ITMP2, s2);
1124 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1126 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1127 M_INTMOVE(s2, REG_ITMP3);
1131 s1 = emit_load_s1(jd, iptr, d);
1135 switch (iptr->opc) {
1137 M_SLDL(s2, GET_HIGH_REG(d));
1140 M_SRDA(s2, GET_HIGH_REG(d));
1143 M_SRDL(s2, GET_HIGH_REG(d));
1149 emit_copy_dst(jd, iptr, d);
1150 emit_store_dst(jd, iptr, d);
1151 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1155 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1156 /* sx.val.i = constant */
1157 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1158 /* sx.val.i = constant */
1159 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1160 /* sx.val.l = constant */
1163 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1164 s1 = emit_load_s1(jd, iptr, d);
1168 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1170 switch (iptr->opc) {
1171 case ICMD_LSHLCONST:
1172 N_SLDL(GET_HIGH_REG(d), disp, RN);
1174 case ICMD_LSHRCONST:
1175 N_SRDA(GET_HIGH_REG(d), disp, RN);
1177 case ICMD_LUSHRCONST:
1178 N_SRDL(GET_HIGH_REG(d), disp, RN);
1181 N_SLDL(GET_HIGH_REG(d), disp, RN);
1187 emit_copy_dst(jd, iptr, d);
1188 emit_store_dst(jd, iptr, d);
1189 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1193 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1195 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1196 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1197 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1204 emit_store_dst(jd, iptr, d);
1208 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1210 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1211 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1212 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1219 emit_store_dst(jd, iptr, d);
1223 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1225 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1226 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1227 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1234 emit_store_dst(jd, iptr, d);
1240 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1241 /* sx.val.i = constant */
1242 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1243 /* sx.val.i = constant */
1244 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1245 /* sx.val.i = constant */
1247 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1248 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1251 ICONST(REG_ITMP2, iptr->sx.val.i);
1253 switch (iptr->opc) {
1254 case ICMD_IANDCONST:
1255 M_IAND(REG_ITMP2, d);
1257 case ICMD_IXORCONST:
1258 M_IXOR(REG_ITMP2, d);
1261 M_IOR(REG_ITMP2, d);
1267 emit_store_dst(jd, iptr, d);
1271 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1272 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1273 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1275 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1277 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1278 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1279 dd = GET_LOW_REG(d);
1281 switch (iptr->opc) {
1310 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1311 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1312 dd = GET_HIGH_REG(d);
1314 switch (iptr->opc) {
1343 emit_store_dst(jd, iptr, d);
1346 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1347 /* sx.val.l = constant */
1348 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1349 /* sx.val.l = constant */
1350 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1351 /* sx.val.l = constant */
1353 /* TODO should use memory operand to access data segment, not load */
1355 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1357 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1358 s3 = iptr->sx.val.l & 0xffffffff;
1360 M_INTMOVE(s1, GET_LOW_REG(d));
1362 ICONST(REG_ITMP3, s3);
1364 switch (iptr->opc) {
1365 case ICMD_LANDCONST:
1366 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1368 case ICMD_LXORCONST:
1369 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1372 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1378 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1379 s3 = iptr->sx.val.l >> 32;
1381 M_INTMOVE(s1, GET_HIGH_REG(d));
1383 ICONST(REG_ITMP3, s3);
1385 switch (iptr->opc) {
1386 case ICMD_LANDCONST:
1387 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1389 case ICMD_LXORCONST:
1390 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1393 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1399 emit_store_dst(jd, iptr, d);
1403 /* floating operations ************************************************/
1405 case ICMD_FNEG: /* ..., value ==> ..., - value */
1406 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1407 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1409 emit_store_dst(jd, iptr, d);
1412 case ICMD_DNEG: /* ..., value ==> ..., - value */
1413 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1414 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1416 emit_store_dst(jd, iptr, d);
1419 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1420 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1421 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1422 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1429 emit_store_dst(jd, iptr, d);
1432 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1433 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1434 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1435 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1442 emit_store_dst(jd, iptr, d);
1445 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1446 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1447 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1448 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1452 emit_store_dst(jd, iptr, d);
1455 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1456 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1457 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1458 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1462 emit_store_dst(jd, iptr, d);
1465 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1466 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1467 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1468 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1475 emit_store_dst(jd, iptr, d);
1478 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1479 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1480 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1481 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1488 emit_store_dst(jd, iptr, d);
1491 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1492 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1493 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1494 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1498 emit_store_dst(jd, iptr, d);
1501 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1502 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1503 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1504 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1508 emit_store_dst(jd, iptr, d);
1511 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1512 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1513 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1515 emit_store_dst(jd, iptr, d);
1518 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1519 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1520 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1522 emit_store_dst(jd, iptr, d);
1525 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1529 #ifdef SUPPORT_HERCULES
1533 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1534 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1538 switch (iptr->opc) {
1547 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1548 N_LHI(d, 0); /* Load 0 */
1549 ref1 = cd->mcodeptr;
1550 N_BRC(DD_ANY, 0); /* Exit */
1554 switch (iptr->opc) {
1563 #ifdef SUPPORT_HERCULES
1564 /* Hercules does the conversion using a plain C conversion.
1565 * According to manual, real hardware should *NOT* require this.
1567 * Corner case: Positive float leads to INT_MIN (overflow).
1570 switch (iptr->opc) {
1579 ref2 = cd->mcodeptr;
1580 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1584 ref3 = cd->mcodeptr;
1585 M_BGE(0); /* If integer result is negative, continue */
1587 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1588 M_ILD_DSEG(d, disp);
1590 N_BRC_BACK_PATCH(ref1);
1591 #ifdef SUPPORT_HERCULES
1592 N_BRC_BACK_PATCH(ref2);
1593 N_BRC_BACK_PATCH(ref3);
1595 emit_store_dst(jd, iptr, d);
1599 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1602 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1603 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1604 #ifdef SUPPORT_HERCULES
1607 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1608 disp = dseg_add_double(cd, 0.0 / 0.0);
1609 M_DLD_DSEG(d, disp, REG_ITMP1);
1610 emit_label_br(cd, BRANCH_LABEL_1);
1611 N_BRC_BACK_PATCH(ref);
1614 #ifdef SUPPORT_HERCULES
1615 emit_label(cd, BRANCH_LABEL_1);
1617 emit_store_dst(jd, iptr, d);
1621 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1622 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1623 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1625 emit_store_dst(jd, iptr, d);
1628 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1629 /* == => 0, < => 1, > => -1 */
1633 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1634 /* == => 0, < => 1, > => -1 */
1637 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1638 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1639 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1641 switch (iptr->opc) {
1653 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1654 SZ_BRC + SZ_BRC + SZ_BRC
1657 N_BRC( /* load -1 */
1658 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1659 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1664 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1667 N_LHI(d, 1); /* GT */
1668 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1669 N_LHI(d, -1); /* LT */
1670 M_BR(SZ_BRC + SZ_LHI);
1671 N_LHI(d, 0); /* EQ */
1673 emit_store_dst(jd, iptr, d);
1678 /* memory operations **************************************************/
1680 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1682 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1683 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1685 /* implicit null-pointer check */
1686 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1687 emit_store_dst(jd, iptr, d);
1691 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1692 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1693 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1694 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1696 /* implicit null-pointer check */
1697 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1699 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1704 emit_store_dst(jd, iptr, d);
1707 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1709 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1710 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1711 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1713 /* implicit null-pointer check */
1714 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1716 M_INTMOVE(s2, REG_ITMP2);
1717 M_SLL_IMM(1, REG_ITMP2);
1719 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1721 /* N_LH does sign extends, undo ! */
1726 emit_store_dst(jd, iptr, d);
1729 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1730 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1731 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1732 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1734 /* implicit null-pointer check */
1735 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1737 M_INTMOVE(s2, REG_ITMP2);
1738 M_SLL_IMM(1, REG_ITMP2);
1740 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1741 emit_store_dst(jd, iptr, d);
1744 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1745 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1746 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1747 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1749 /* implicit null-pointer check */
1750 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1752 M_INTMOVE(s2, REG_ITMP2);
1753 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1754 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1755 emit_store_dst(jd, iptr, d);
1758 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1760 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1761 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1763 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1765 /* implicit null-pointer check */
1766 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1768 M_INTMOVE(s2, REG_ITMP2);
1769 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1771 /* We need to preserve the array address after the first load */
1773 if (GET_HIGH_REG(d) == s1) {
1774 M_INTMOVE(s1, REG_ITMP3);
1778 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1779 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1780 emit_store_dst(jd, iptr, d);
1784 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1786 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1787 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1788 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1790 /* implicit null-pointer check */
1791 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1793 M_INTMOVE(s2, REG_ITMP2);
1794 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1796 N_LE(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1798 emit_store_dst(jd, iptr, d);
1801 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1802 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1803 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1804 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1806 /* implicit null-pointer check */
1807 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1809 M_INTMOVE(s2, REG_ITMP2);
1810 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1812 N_LD(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1814 emit_store_dst(jd, iptr, d);
1817 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1818 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1819 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1820 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1822 /* implicit null-pointer check */
1823 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1825 M_INTMOVE(s2, REG_ITMP2);
1826 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1827 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1828 emit_store_dst(jd, iptr, d);
1831 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1832 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1833 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1834 /* implicit null-pointer check */
1835 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1836 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1838 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1841 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1843 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1844 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1845 /* implicit null-pointer check */
1846 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1847 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1849 M_INTMOVE(s2, REG_ITMP2);
1850 M_SLL_IMM(1, REG_ITMP2);
1852 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1856 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1857 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1858 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1859 /* implicit null-pointer check */
1860 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1861 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1863 M_INTMOVE(s2, REG_ITMP2);
1864 M_SLL_IMM(1, REG_ITMP2);
1866 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1869 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1871 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1872 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1873 /* implicit null-pointer check */
1874 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(2, REG_ITMP2);
1881 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1884 case ICMD_LASTORE: /* ..., 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);
1891 M_INTMOVE(s2, REG_ITMP2);
1892 M_SLL_IMM(3, REG_ITMP2);
1894 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1895 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1896 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1897 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1900 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1901 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1902 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1903 /* implicit null-pointer check */
1904 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1905 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1907 M_INTMOVE(s2, REG_ITMP2);
1908 M_SLL_IMM(2, REG_ITMP2);
1910 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1913 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1914 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1915 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1916 /* implicit null-pointer check */
1917 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1918 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1920 M_INTMOVE(s2, REG_ITMP2);
1921 M_SLL_IMM(3, REG_ITMP2);
1923 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1926 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1928 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1929 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1930 /* implicit null-pointer check */
1931 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1932 s3 = emit_load_s3(jd, iptr, REG_A1);
1934 M_INTMOVE(s1, REG_A0);
1935 M_INTMOVE(s3, REG_A1);
1937 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1938 M_ALD_DSEG(REG_ITMP3, disp);
1939 M_ASUB_IMM(96, REG_SP);
1940 M_JSR(REG_RA, REG_ITMP3);
1941 M_AADD_IMM(96, REG_SP);
1943 emit_exception_check(cd, iptr);
1945 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1946 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1947 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1949 M_INTMOVE(s2, REG_ITMP2);
1950 M_SLL_IMM(2, REG_ITMP2);
1951 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1954 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1955 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1960 case ICMD_GETSTATIC: /* ... ==> ..., value */
1962 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1963 uf = iptr->sx.s23.s3.uf;
1964 fieldtype = uf->fieldref->parseddesc.fd->type;
1965 disp = dseg_add_unique_address(cd, NULL);
1967 /* PROFILE_CYCLE_STOP; */
1969 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1971 /* PROFILE_CYCLE_START; */
1974 fi = iptr->sx.s23.s3.fmiref->p.field;
1975 fieldtype = fi->type;
1976 disp = dseg_add_address(cd, fi->value);
1978 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1981 patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, 0);
1983 PROFILE_CYCLE_START;
1987 M_ALD_DSEG(REG_ITMP1, disp);
1989 switch (fieldtype) {
1991 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1992 M_ILD(d, REG_ITMP1, 0);
1995 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1996 M_LLD(d, REG_ITMP1, 0);
1999 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2000 M_ALD(d, REG_ITMP1, 0);
2003 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2004 M_FLD(d, REG_ITMP1, 0);
2007 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2008 M_DLD(d, REG_ITMP1, 0);
2012 emit_store_dst(jd, iptr, d);
2016 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2018 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2019 uf = iptr->sx.s23.s3.uf;
2020 fieldtype = uf->fieldref->parseddesc.fd->type;
2021 disp = dseg_add_unique_address(cd, uf);
2023 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2026 fi = iptr->sx.s23.s3.fmiref->p.field;
2027 fieldtype = fi->type;
2028 disp = dseg_add_address(cd, fi->value);
2030 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2032 patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, disp);
2033 PROFILE_CYCLE_START;
2037 M_ALD_DSEG(REG_ITMP1, disp);
2038 switch (fieldtype) {
2040 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2041 M_IST(s1, REG_ITMP1, 0);
2044 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2045 M_LST(s1, REG_ITMP1, 0);
2048 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2049 M_AST(s1, REG_ITMP1, 0);
2052 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2053 M_FST(s1, REG_ITMP1, 0);
2056 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2057 M_DST(s1, REG_ITMP1, 0);
2062 case ICMD_GETFIELD: /* ... ==> ..., value */
2064 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2065 emit_nullpointer_check(cd, iptr, s1);
2067 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2068 uf = iptr->sx.s23.s3.uf;
2069 fieldtype = uf->fieldref->parseddesc.fd->type;
2072 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2075 fi = iptr->sx.s23.s3.fmiref->p.field;
2076 fieldtype = fi->type;
2080 switch (fieldtype) {
2082 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2086 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2087 if (GET_HIGH_REG(d) == s1) {
2088 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2089 M_ILD(GET_HIGH_REG(d), s1, disp);
2092 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2093 M_ILD(GET_HIGH_REG(d), s1, disp);
2097 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2101 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2105 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2109 emit_store_dst(jd, iptr, d);
2112 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2116 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2117 emit_nullpointer_check(cd, iptr, s1);
2119 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2120 uf = iptr->sx.s23.s3.uf;
2121 fieldtype = uf->fieldref->parseddesc.fd->type;
2125 fi = iptr->sx.s23.s3.fmiref->p.field;
2126 fieldtype = fi->type;
2130 /* We can't add a patcher ref behind this load,
2131 * because the patcher would destroy REG_ITMP3.
2133 * We pass in the disp parameter, how many bytes
2134 * to skip to the to the actual store.
2136 * XXX this relies on patcher_add_patch_ref internals
2139 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2140 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2145 if (IS_INT_LNG_TYPE(fieldtype)) {
2146 if (IS_2_WORD_TYPE(fieldtype))
2147 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2149 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2151 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2154 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2155 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2158 switch (fieldtype) {
2160 M_IST(s2, s1, disp);
2163 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2164 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2167 M_AST(s2, s1, disp);
2170 M_FST(s2, s1, disp);
2173 M_DST(s2, s1, disp);
2180 /* branch operations **************************************************/
2182 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2184 /* PROFILE_CYCLE_STOP; */
2186 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2187 M_INTMOVE(s1, REG_ITMP1_XPTR);
2189 #ifdef ENABLE_VERIFIER
2190 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2191 uc = iptr->sx.s23.s2.uc;
2193 patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
2195 #endif /* ENABLE_VERIFIER */
2197 disp = dseg_add_functionptr(cd, asm_handle_exception);
2198 M_ALD_DSEG(REG_ITMP2, disp);
2199 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2204 case ICMD_GOTO: /* ... ==> ... */
2205 case ICMD_RET: /* ... ==> ... */
2207 emit_br(cd, iptr->dst.block);
2211 case ICMD_JSR: /* ... ==> ... */
2213 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2217 case ICMD_IFNULL: /* ..., value ==> ... */
2218 case ICMD_IFNONNULL: /* ..., value ==> ... */
2219 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2221 switch (iptr->opc) {
2223 emit_beq(cd, iptr->dst.block);
2225 case ICMD_IFNONNULL:
2226 emit_bne(cd, iptr->dst.block);
2231 case ICMD_IFEQ: /* ..., value ==> ... */
2232 case ICMD_IFLT: /* ..., value ==> ... */
2233 case ICMD_IFLE: /* ..., value ==> ... */
2234 case ICMD_IFNE: /* ..., value ==> ... */
2235 case ICMD_IFGT: /* ..., value ==> ... */
2236 case ICMD_IFGE: /* ..., value ==> ... */
2238 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2240 if (N_VALID_IMM(iptr->sx.val.i))
2241 M_ICMP_IMM(s1, iptr->sx.val.i);
2243 disp = dseg_add_s4(cd, iptr->sx.val.i);
2244 if (N_VALID_DSEG_DISP(disp)) {
2245 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2247 ICONST(REG_ITMP2, disp);
2248 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2252 switch (iptr->opc) {
2254 emit_blt(cd, iptr->dst.block);
2257 emit_ble(cd, iptr->dst.block);
2260 emit_bne(cd, iptr->dst.block);
2263 emit_bgt(cd, iptr->dst.block);
2266 emit_bge(cd, iptr->dst.block);
2269 emit_beq(cd, iptr->dst.block);
2275 case ICMD_IF_LLT: /* ..., value ==> ... */
2276 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2282 /* ATTENTION: compare high words signed and low words unsigned */
2284 # define LABEL_OUT BRANCH_LABEL_1
2286 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2288 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2289 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2291 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2292 if (N_VALID_DSEG_DISP(disp)) {
2293 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2295 ICONST(REG_ITMP2, disp);
2296 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2303 emit_blt(cd, iptr->dst.block);
2304 /* EQ ... fall through */
2305 emit_label_bgt(cd, LABEL_OUT);
2309 emit_bgt(cd, iptr->dst.block);
2310 /* EQ ... fall through */
2311 emit_label_blt(cd, LABEL_OUT);
2314 /* EQ ... fall through */
2315 emit_label_bne(cd, LABEL_OUT);
2318 /* EQ ... fall through */
2319 emit_bne(cd, iptr->dst.block);
2325 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2327 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2328 if (N_VALID_DSEG_DISP(disp)) {
2329 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2331 ICONST(REG_ITMP2, disp);
2332 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2337 emit_blt(cd, iptr->dst.block);
2338 emit_label(cd, LABEL_OUT);
2341 emit_ble(cd, iptr->dst.block);
2342 emit_label(cd, LABEL_OUT);
2345 emit_bgt(cd, iptr->dst.block);
2346 emit_label(cd, LABEL_OUT);
2349 emit_bge(cd, iptr->dst.block);
2350 emit_label(cd, LABEL_OUT);
2353 emit_beq(cd, iptr->dst.block);
2354 emit_label(cd, LABEL_OUT);
2357 emit_bne(cd, iptr->dst.block);
2366 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2367 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2369 /* Compare addresses as 31 bit unsigned integers */
2371 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2372 M_LDA(REG_ITMP1, s1, 0);
2374 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2375 M_LDA(REG_ITMP2, s2, 0);
2377 M_CMP(REG_ITMP1, REG_ITMP2);
2379 switch (iptr->opc) {
2380 case ICMD_IF_ACMPEQ:
2381 emit_beq(cd, iptr->dst.block);
2383 case ICMD_IF_ACMPNE:
2384 emit_bne(cd, iptr->dst.block);
2390 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2391 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2392 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2393 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2394 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2395 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2397 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2398 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2400 switch (iptr->opc) {
2401 case ICMD_IF_ICMPEQ:
2402 emit_beq(cd, iptr->dst.block);
2404 case ICMD_IF_ICMPNE:
2405 emit_bne(cd, iptr->dst.block);
2407 case ICMD_IF_ICMPLT:
2408 emit_blt(cd, iptr->dst.block);
2410 case ICMD_IF_ICMPGT:
2411 emit_bgt(cd, iptr->dst.block);
2413 case ICMD_IF_ICMPLE:
2414 emit_ble(cd, iptr->dst.block);
2416 case ICMD_IF_ICMPGE:
2417 emit_bge(cd, iptr->dst.block);
2423 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2424 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2425 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2426 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2427 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2428 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2433 /* ATTENTION: compare high words signed and low words unsigned */
2435 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2436 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2441 case ICMD_IF_LCMPLT:
2442 case ICMD_IF_LCMPLE:
2443 emit_blt(cd, iptr->dst.block);
2444 /* EQ ... fall through */
2445 out_ref = cd->mcodeptr;
2448 case ICMD_IF_LCMPGT:
2449 case ICMD_IF_LCMPGE:
2450 emit_bgt(cd, iptr->dst.block);
2451 /* EQ ... fall through */
2452 out_ref = cd->mcodeptr;
2455 case ICMD_IF_LCMPEQ:
2456 /* EQ ... fall through */
2457 out_ref = cd->mcodeptr;
2460 case ICMD_IF_LCMPNE:
2461 /* EQ ... fall through */
2462 emit_bne(cd, iptr->dst.block);
2468 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2469 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2474 case ICMD_IF_LCMPLT:
2475 emit_blt(cd, iptr->dst.block);
2477 case ICMD_IF_LCMPLE:
2478 emit_ble(cd, iptr->dst.block);
2480 case ICMD_IF_LCMPGT:
2481 emit_bgt(cd, iptr->dst.block);
2483 case ICMD_IF_LCMPGE:
2484 emit_bge(cd, iptr->dst.block);
2486 case ICMD_IF_LCMPEQ:
2487 emit_beq(cd, iptr->dst.block);
2489 case ICMD_IF_LCMPNE:
2490 emit_bne(cd, iptr->dst.block);
2497 if (out_ref != NULL) {
2498 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2504 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2506 REPLACEMENT_POINT_RETURN(cd, iptr);
2507 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2508 M_INTMOVE(s1, REG_RESULT);
2509 goto nowperformreturn;
2511 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2513 REPLACEMENT_POINT_RETURN(cd, iptr);
2514 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2515 M_INTMOVE(s1, REG_RESULT);
2517 #ifdef ENABLE_VERIFIER
2518 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2519 unresolved_class *uc = iptr->sx.s23.s2.uc;
2522 patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
2523 PROFILE_CYCLE_START;
2525 #endif /* ENABLE_VERIFIER */
2526 goto nowperformreturn;
2528 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2530 REPLACEMENT_POINT_RETURN(cd, iptr);
2531 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2532 M_LNGMOVE(s1, REG_RESULT_PACKED);
2533 goto nowperformreturn;
2535 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2538 REPLACEMENT_POINT_RETURN(cd, iptr);
2539 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2540 M_FLTMOVE(s1, REG_FRESULT);
2541 goto nowperformreturn;
2543 case ICMD_RETURN: /* ... ==> ... */
2545 REPLACEMENT_POINT_RETURN(cd, iptr);
2551 p = cd->stackframesize;
2553 /* call trace function */
2555 #if !defined(NDEBUG)
2556 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2557 emit_verbosecall_exit(jd);
2558 #endif /* !defined(NDEBUG) */
2560 #if defined(ENABLE_THREADS)
2561 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2563 /* we need to save the proper return value */
2565 switch (iptr->opc) {
2567 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2571 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2574 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2577 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2581 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2583 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2584 M_ALD_DSEG(REG_ITMP3, disp);
2586 M_ASUB_IMM(96, REG_SP);
2588 M_AADD_IMM(96, REG_SP);
2590 /* and now restore the proper return value */
2592 switch (iptr->opc) {
2594 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2598 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2601 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2604 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2610 /* restore return address */
2612 p--; M_ALD(REG_RA, REG_SP, p * 4);
2614 /* restore saved registers */
2616 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2617 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2619 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2620 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2623 /* deallocate stack */
2625 if (cd->stackframesize)
2626 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2628 /* generate method profiling code */
2636 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2639 branch_target_t *table;
2641 table = iptr->dst.table;
2643 l = iptr->sx.s23.s2.tablelow;
2644 i = iptr->sx.s23.s3.tablehigh;
2646 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2647 M_INTMOVE(s1, REG_ITMP1);
2651 } else if (N_VALID_IMM(-l)) {
2652 M_ISUB_IMM(l, REG_ITMP1);
2654 ICONST(REG_ITMP2, l);
2655 M_ISUB(REG_ITMP2, REG_ITMP1);
2658 /* number of targets */
2664 ICONST(REG_ITMP2, i);
2665 M_ICMPU(REG_ITMP1, REG_ITMP2);
2666 emit_bge(cd, table[0].block);
2668 /* build jump table top down and use address of lowest entry */
2673 dseg_add_target(cd, table->block);
2678 /* length of dataseg after last dseg_add_target is used by load */
2680 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2681 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2682 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2683 M_JMP(RN, REG_ITMP1);
2688 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2691 lookup_target_t *lookup;
2693 lookup = iptr->dst.lookup;
2695 i = iptr->sx.s23.s2.lookupcount;
2697 MCODECHECK(8 + ((7 + 6) * i) + 5);
2698 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2701 if (N_VALID_IMM(lookup->value)) {
2702 M_ICMP_IMM(s1, lookup->value);
2704 ICONST(REG_ITMP2, lookup->value);
2705 M_ICMP(REG_ITMP2, s1);
2707 emit_beq(cd, lookup->target.block);
2711 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2716 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2718 bte = iptr->sx.s23.s3.bte;
2722 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2723 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2724 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2725 case ICMD_INVOKEINTERFACE:
2727 REPLACEMENT_POINT_INVOKE(cd, iptr);
2729 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2731 um = iptr->sx.s23.s3.um;
2732 md = um->methodref->parseddesc.md;
2735 lm = iptr->sx.s23.s3.fmiref->p.method;
2737 md = lm->parseddesc;
2741 s3 = md->paramcount;
2743 MCODECHECK((s3 << 1) + 64);
2745 /* copy arguments to registers or stack location */
2747 for (s3 = s3 - 1; s3 >= 0; s3--) {
2748 var = VAR(iptr->sx.s23.s2.args[s3]);
2750 /* Already Preallocated? */
2751 if (var->flags & PREALLOC)
2754 if (IS_INT_LNG_TYPE(var->type)) {
2755 if (!md->params[s3].inmemory) {
2756 if (IS_2_WORD_TYPE(var->type)) {
2758 GET_LOW_REG(md->params[s3].regoff),
2759 GET_HIGH_REG(md->params[s3].regoff)
2761 d = emit_load(jd, iptr, var, s1);
2765 s1 = md->params[s3].regoff;
2766 d = emit_load(jd, iptr, var, s1);
2771 if (IS_2_WORD_TYPE(var->type)) {
2772 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2773 M_LST(d, REG_SP, md->params[s3].regoff);
2776 d = emit_load(jd, iptr, var, REG_ITMP1);
2777 M_IST(d, REG_SP, md->params[s3].regoff);
2782 if (!md->params[s3].inmemory) {
2783 s1 = md->params[s3].regoff;
2784 d = emit_load(jd, iptr, var, s1);
2788 d = emit_load(jd, iptr, var, REG_FTMP1);
2789 if (IS_2_WORD_TYPE(var->type))
2790 M_DST(d, REG_SP, md->params[s3].regoff);
2792 M_FST(d, REG_SP, md->params[s3].regoff);
2797 /* generate method profiling code */
2801 switch (iptr->opc) {
2803 disp = dseg_add_functionptr(cd, bte->fp);
2805 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2806 if (N_VALID_DSEG_DISP(disp)) {
2807 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2809 N_LHI(REG_ITMP1, disp);
2810 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2814 case ICMD_INVOKESPECIAL:
2816 /* Implicit NULL pointer check */
2817 M_ILD(REG_ITMP1, REG_A0, 0);
2821 case ICMD_INVOKESTATIC:
2823 disp = dseg_add_unique_address(cd, um);
2825 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2829 disp = dseg_add_address(cd, lm->stubroutine);
2831 if (N_VALID_DSEG_DISP(disp)) {
2832 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2834 N_LHI(REG_ITMP1, disp);
2835 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2839 case ICMD_INVOKEVIRTUAL:
2840 /* TODO softnull REG_A0 */
2843 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2848 s1 = OFFSET(vftbl_t, table[0]) +
2849 sizeof(methodptr) * lm->vftblindex;
2852 /* implicit null-pointer check */
2854 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2855 M_ALD(REG_PV, REG_METHODPTR, s1);
2858 case ICMD_INVOKEINTERFACE:
2859 /* TODO softnull REG_A0 */
2861 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2862 * and -0xFFF in index register (itmp1)
2866 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2872 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2873 sizeof(methodptr*) * lm->class->index;
2875 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2878 /* Implicit null-pointer check */
2879 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2880 N_LHI(REG_ITMP1, s1);
2881 N_L(REG_METHODPTR, 0, REG_ITMP1, REG_METHODPTR);
2882 M_ALD(REG_PV, REG_METHODPTR, s2);
2886 /* generate the actual call */
2889 emit_restore_pv(cd);
2891 /* post call finalization */
2893 switch (iptr->opc) {
2895 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2896 emit_exception_check(cd, iptr); /* check for exception */
2900 /* generate method profiling code */
2902 PROFILE_CYCLE_START;
2904 /* store size of call code in replacement point */
2906 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2908 /* store return value */
2910 d = md->returntype.type;
2912 if (d != TYPE_VOID) {
2913 if (IS_INT_LNG_TYPE(d)) {
2914 if (IS_2_WORD_TYPE(d)) {
2915 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2916 M_LNGMOVE(REG_RESULT_PACKED, s1);
2919 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2920 M_INTMOVE(REG_RESULT, s1);
2924 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2925 M_FLTMOVE(REG_FRESULT, s1);
2927 emit_store_dst(jd, iptr, s1);
2933 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2935 /* val.a: (classinfo*) superclass */
2937 /* superclass is an interface:
2939 * OK if ((sub == NULL) ||
2940 * (sub->vftbl->interfacetablelength > super->index) &&
2941 * (sub->vftbl->interfacetable[-super->index] != NULL));
2943 * superclass is a class:
2945 * OK if ((sub == NULL) || (0
2946 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2947 * super->vftbl->diffval));
2950 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2951 /* object type cast-check */
2954 vftbl_t *supervftbl;
2957 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2958 # define LABEL_CLASS BRANCH_LABEL_2
2959 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2960 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2961 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2963 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2969 super = iptr->sx.s23.s3.c.cls;
2970 superindex = super->index;
2971 supervftbl = super->vftbl;
2974 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2975 CODEGEN_CRITICAL_SECTION_NEW;
2977 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2979 /* if class is not resolved, check which code to call */
2981 if (super == NULL) {
2983 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2985 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2987 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
2988 iptr->sx.s23.s3.c.ref,
2991 ICONST(REG_ITMP2, ACC_INTERFACE);
2992 if (N_VALID_DSEG_DISP(disp)) {
2993 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
2995 ICONST(REG_ITMP3, disp);
2996 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
2998 emit_label_beq(cd, LABEL_CLASS);
3001 /* interface checkcast code */
3003 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3004 if (super == NULL) {
3005 patcher_add_patch_ref(jd,
3006 PATCHER_checkcast_instanceof_interface,
3007 iptr->sx.s23.s3.c.ref,
3011 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3014 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3015 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3016 M_ISUB_IMM(superindex, REG_ITMP3);
3017 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3020 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3021 superindex * sizeof(methodptr*))
3023 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3024 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3026 if (super == NULL) {
3027 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3031 /* class checkcast code */
3033 if (super == NULL) {
3034 emit_label(cd, LABEL_CLASS);
3037 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3038 if (super == NULL) {
3039 disp = dseg_add_unique_address(cd, NULL);
3041 patcher_add_patch_ref(jd,
3042 PATCHER_resolve_classref_to_vftbl,
3043 iptr->sx.s23.s3.c.ref,
3047 disp = dseg_add_address(cd, supervftbl);
3049 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3052 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3053 M_ALD_DSEG(REG_ITMP3, disp);
3055 CODEGEN_CRITICAL_SECTION_START;
3057 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3058 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3059 M_ISUB(REG_ITMP3, REG_ITMP2);
3060 M_ALD_DSEG(REG_ITMP3, disp);
3061 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3063 CODEGEN_CRITICAL_SECTION_END;
3065 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3066 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3067 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3068 /* Branch if greater then */
3069 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3072 if (super == NULL) {
3073 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3074 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3075 } else if (super->flags & ACC_INTERFACE) {
3076 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3078 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3081 d = codegen_reg_of_dst(jd, iptr, s1);
3083 # undef LABEL_EXIT_CHECK_NULL
3085 # undef LABEL_EXIT_INTERFACE_NULL
3086 # undef LABEL_EXIT_INTERFACE_DONE
3087 # undef LABEL_EXIT_CLASS_NULL
3090 /* array type cast-check */
3092 s1 = emit_load_s1(jd, iptr, REG_A0);
3093 M_INTMOVE(s1, REG_A0);
3095 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3096 disp = dseg_add_unique_address(cd, NULL);
3098 patcher_add_patch_ref(jd,
3099 PATCHER_resolve_classref_to_classinfo,
3100 iptr->sx.s23.s3.c.ref,
3104 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3106 M_ALD_DSEG(REG_A1, disp);
3107 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3108 M_ALD_DSEG(REG_ITMP1, disp);
3109 M_ASUB_IMM(96, REG_SP);
3110 M_JSR(REG_RA, REG_ITMP1);
3111 M_AADD_IMM(96, REG_SP);
3113 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3114 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3116 d = codegen_reg_of_dst(jd, iptr, s1);
3120 emit_store_dst(jd, iptr, d);
3123 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3124 /* val.a: (classinfo*) superclass */
3126 /* superclass is an interface:
3128 * return (sub != NULL) &&
3129 * (sub->vftbl->interfacetablelength > super->index) &&
3130 * (sub->vftbl->interfacetable[-super->index] != NULL);
3132 * superclass is a class:
3134 * return ((sub != NULL) && (0
3135 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3136 * super->vftbl->diffvall));
3138 * If superclass is unresolved, we include both code snippets
3139 * above, a patcher resolves the class' flags and we select
3140 * the right code at runtime.
3145 vftbl_t *supervftbl;
3148 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3154 super = iptr->sx.s23.s3.c.cls;
3155 superindex = super->index;
3156 supervftbl = super->vftbl;
3159 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3160 # define LABEL_CLASS BRANCH_LABEL_2
3161 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3162 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3163 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3164 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3166 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3167 CODEGEN_CRITICAL_SECTION_NEW;
3169 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3170 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3172 M_MOV(s1, REG_ITMP1);
3176 /* if class is not resolved, check which code to call */
3178 if (super == NULL) {
3182 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3184 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3186 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3187 iptr->sx.s23.s3.c.ref, disp);
3189 ICONST(REG_ITMP2, ACC_INTERFACE);
3191 if (N_VALID_DSEG_DISP(disp)) {
3192 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3194 ICONST(REG_ITMP3, disp);
3195 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3198 emit_label_beq(cd, LABEL_CLASS);
3201 /* interface instanceof code */
3203 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3204 if (super == NULL) {
3205 /* If d == REG_ITMP2, then it's destroyed in check
3210 patcher_add_patch_ref(jd,
3211 PATCHER_checkcast_instanceof_interface,
3212 iptr->sx.s23.s3.c.ref, 0);
3217 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3220 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3221 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3222 M_ISUB_IMM(superindex, REG_ITMP3);
3224 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3228 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3229 superindex * sizeof(methodptr*))
3231 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3233 /* d := (REG_ITMP1 != 0) */
3235 N_LTR(d, REG_ITMP1);
3236 M_BEQ(SZ_BRC + SZ_LHI);
3239 if (super == NULL) {
3240 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3244 /* class instanceof code */
3246 if (super == NULL) {
3247 emit_label(cd, LABEL_CLASS);
3250 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3251 if (super == NULL) {
3252 disp = dseg_add_unique_address(cd, NULL);
3254 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3255 iptr->sx.s23.s3.c.ref,
3259 disp = dseg_add_address(cd, supervftbl);
3264 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3267 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3268 M_ALD_DSEG(REG_ITMP2, disp);
3270 CODEGEN_CRITICAL_SECTION_START;
3272 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3273 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3274 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3276 CODEGEN_CRITICAL_SECTION_END;
3278 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3280 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3282 M_BGT(SZ_BRC + SZ_LHI);
3286 if (super == NULL) {
3287 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3288 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3289 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3290 } else if (super->flags & ACC_INTERFACE) {
3291 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3292 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3294 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3297 # undef LABEL_EXIT_CHECK_NULL
3299 # undef LABEL_EXIT_INTERFACE_NULL
3300 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3301 # undef LABEL_EXIT_INTERFACE_DONE
3302 # undef LABEL_EXIT_CLASS_NULL
3304 emit_store_dst(jd, iptr, d);
3310 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3312 /* check for negative sizes and copy sizes to stack if necessary */
3314 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3317 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3319 /* copy SAVEDVAR sizes to stack */
3320 var = VAR(iptr->sx.s23.s2.args[s1]);
3322 /* Already Preallocated? */
3323 if (!(var->flags & PREALLOC)) {
3324 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3325 M_IST(s2, REG_SP, s1 * 4);
3329 /* is a patcher function set? */
3331 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3332 disp = dseg_add_unique_address(cd, 0);
3334 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3335 iptr->sx.s23.s3.c.ref,
3339 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3341 /* a0 = dimension count */
3343 ICONST(REG_A0, iptr->s1.argcount);
3345 /* a1 = classinfo */
3347 M_ALD_DSEG(REG_A1, disp);
3349 /* a2 = pointer to dimensions = stack pointer */
3351 M_MOV(REG_SP, REG_A2);
3353 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3354 M_ALD_DSEG(REG_ITMP1, disp);
3355 M_ASUB_IMM(96, REG_SP);
3356 M_JSR(REG_RA, REG_ITMP1);
3357 M_AADD_IMM(96, REG_SP);
3359 /* check for exception before result assignment */
3361 emit_exception_check(cd, iptr);
3363 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3364 M_INTMOVE(REG_RESULT, s1);
3365 emit_store_dst(jd, iptr, s1);
3370 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3374 } /* for instruction */
3376 MCODECHECK(512); /* XXX require a lower number? */
3378 /* At the end of a basic block we may have to append some nops,
3379 because the patcher stub calling code might be longer than the
3380 actual instruction. So codepatching does not change the
3381 following block unintentionally. */
3383 if (cd->mcodeptr < cd->lastmcodeptr) {
3384 while (cd->mcodeptr < cd->lastmcodeptr) {
3389 } /* if (bptr -> flags >= BBREACHED) */
3390 } /* for basic block */
3392 dseg_createlinenumbertable(cd);
3394 /* generate stubs */
3396 emit_patcher_traps(jd);
3398 /* everything's ok */
3404 /* codegen_emit_stub_compiler **************************************************
3406 Emits a stub routine which calls the compiler.
3408 *******************************************************************************/
3410 void codegen_emit_stub_compiler(jitdata *jd)
3415 /* get required compiler data */
3420 /* code for the stub */
3422 /* don't touch ITMP3 as it cointains the return address */
3424 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3426 M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */
3427 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3428 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3433 /* codegen_emit_stub_native ****************************************************
3435 Emits a stub routine which calls a native method.
3437 *******************************************************************************/
3440 arguments on stack \
3441 -------------------------------------------------| <- SP on nativestub entry
3443 callee saved int regs (none) |
3444 callee saved float regs (none) | stack frame like in cacao
3445 local variable slots (none) |
3446 arguments for calling methods (none) /
3447 ------------------------------------------------------------------ <- datasp
3452 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3453 0 - 96 register save area for callee /
3454 -------------------------------------------------------- <- SP native method
3456 SP after method entry
3459 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3467 s4 i, j; /* count variables */
3472 /* get required compiler data */
3479 /* initialize variables */
3482 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3484 /* calculate stack frame size */
3486 cd->stackframesize =
3487 1 + /* r14 - return address */ +
3488 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3489 sizeof(localref_table) / SIZEOF_VOID_P +
3491 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3492 nmd->memuse + /* parameter passing */
3493 96 / SIZEOF_VOID_P /* required by ABI */;
3495 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3498 /* create method header */
3500 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3501 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3502 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3503 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3504 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3505 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3506 (void) dseg_addlinenumbertablesize(cd);
3507 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3509 /* generate stub code */
3511 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3512 N_AHI(REG_PV, N_PV_OFFSET);
3514 /* generate native method profiling code */
3516 #if defined(ENABLE_PROFILING)
3517 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3518 /* count frequency */
3519 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
3520 ICONST(REG_ITMP2, 1);
3521 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
3522 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
3526 /* save return address */
3528 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3530 #if !defined(NDEBUG)
3531 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3532 emit_verbosecall_enter(jd);
3535 /* get function address (this must happen before the stackframeinfo) */
3537 disp = dseg_add_functionptr(cd, f);
3539 #if !defined(WITH_STATIC_CLASSPATH)
3541 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, disp);
3544 M_ILD_DSEG(REG_ITMP1, disp);
3546 j = 96 + (nmd->memuse * 4);
3548 /* todo some arg registers are not volatile in C-abi terms */
3550 /* save integer and float argument registers */
3552 for (i = 0; i < md->paramcount; i++) {
3553 if (! md->params[i].inmemory) {
3554 s1 = md->params[i].regoff;
3555 t = md->paramtypes[i].type;
3557 if (IS_INT_LNG_TYPE(t)) {
3558 if (IS_2_WORD_TYPE(t)) {
3559 /* todo store multiple */
3560 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3561 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3563 N_ST(s1, j, RN, REG_SP);
3566 if (IS_2_WORD_TYPE(t)) {
3567 N_STD(s1, j, RN, REG_SP);
3569 N_STE(s1, j, RN, REG_SP);
3577 N_ST(REG_ITMP1, j, RN, REG_SP);
3579 /* create dynamic stack info */
3581 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3582 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3583 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3584 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3586 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3587 M_ILD_DSEG(REG_ITMP1, disp);
3589 M_CALL(REG_ITMP1); /* call */
3591 /* restore integer and float argument registers */
3593 j = 96 + (nmd->memuse * 4);
3595 for (i = 0; i < md->paramcount; i++) {
3596 if (! md->params[i].inmemory) {
3597 s1 = md->params[i].regoff;
3598 t = md->paramtypes[i].type;
3600 if (IS_INT_LNG_TYPE(t)) {
3601 if (IS_2_WORD_TYPE(t)) {
3602 /* todo load multiple ! */
3603 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3604 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3606 N_L(s1, j, RN, REG_SP);
3609 if (IS_2_WORD_TYPE(t)) {
3610 N_LD(s1, j, RN, REG_SP);
3612 N_LE(s1, j, RN, REG_SP);
3620 N_L(REG_ITMP1, j, RN, REG_SP);
3622 /* copy or spill arguments to new locations */
3624 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3625 t = md->paramtypes[i].type;
3627 if (IS_INT_LNG_TYPE(t)) {
3629 if (!md->params[i].inmemory) {
3631 s1 = md->params[i].regoff;
3633 if (!nmd->params[j].inmemory) {
3634 s2 = nmd->params[j].regoff;
3635 if (IS_2_WORD_TYPE(t)) {
3651 s2 = nmd->params[j].regoff;
3652 if (IS_2_WORD_TYPE(t)) {
3667 s1 = cd->stackframesize * 4 + md->params[i].regoff;
3668 s2 = nmd->params[j].regoff;
3670 if (IS_2_WORD_TYPE(t)) {
3671 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3673 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3678 /* We only copy spilled float arguments, as the float argument */
3679 /* registers keep unchanged. */
3681 if (md->params[i].inmemory) {
3682 s1 = cd->stackframesize * 4 + md->params[i].regoff;
3683 s2 = nmd->params[j].regoff;
3685 if (IS_2_WORD_TYPE(t)) {
3686 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3688 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3694 /* put class into second argument register */
3696 if (m->flags & ACC_STATIC) {
3697 disp = dseg_add_address(cd, m->class);
3698 M_ILD_DSEG(REG_A1, disp);
3701 /* put env into first argument register */
3703 disp = dseg_add_address(cd, _Jv_env);
3704 M_ILD_DSEG(REG_A0, disp);
3706 /* do the native function call */
3708 M_CALL(REG_ITMP1); /* call */
3710 /* save return value */
3712 t = md->returntype.type;
3714 if (t != TYPE_VOID) {
3715 if (IS_INT_LNG_TYPE(t)) {
3716 if (IS_2_WORD_TYPE(t)) {
3717 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3719 N_ST(REG_RESULT, 96, RN, REG_SP);
3722 if (IS_2_WORD_TYPE(t)) {
3723 N_STD(REG_FRESULT, 96, RN, REG_SP);
3725 N_STE(REG_FRESULT, 96, RN, REG_SP);
3730 #if !defined(NDEBUG)
3731 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3732 emit_verbosecall_exit(jd);
3735 /* remove native stackframe info */
3737 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3738 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3739 M_ALD_DSEG(REG_ITMP1, disp);
3741 N_LR(REG_ITMP3, REG_RESULT);
3743 /* restore return value */
3745 if (t != TYPE_VOID) {
3746 if (IS_INT_LNG_TYPE(t)) {
3747 if (IS_2_WORD_TYPE(t)) {
3748 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3750 N_L(REG_RESULT, 96, RN, REG_SP);
3753 if (IS_2_WORD_TYPE(t)) {
3754 N_LD(REG_FRESULT, 96, RN, REG_SP);
3756 N_LE(REG_FRESULT, 96, RN, REG_SP);
3761 /* load return address */
3763 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3765 /* remove stackframe */
3767 N_AHI(REG_SP, cd->stackframesize * 4);
3769 /* test for exception */
3771 N_LTR(REG_ITMP3, REG_ITMP3);
3772 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3776 N_BCR(DD_ANY, REG_ITMP2);
3778 /* handle exception */
3780 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3781 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3785 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3788 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3789 M_ALD_DSEG(REG_ITMP3, disp);
3790 M_JMP(RN, REG_ITMP3);
3792 /* generate patcher stubs */
3794 emit_patcher_traps(jd);
3797 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3798 codegendata *cd = jd->cd;
3799 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3801 M_MOV(reg, tempregnum);
3809 * These are local overrides for various environment variables in Emacs.
3810 * Please do not remove this and leave it at the end of the file, where
3811 * Emacs will automagically detect them.
3812 * ---------------------------------------------------------------------
3815 * indent-tabs-mode: t
3819 * vim:noexpandtab:sw=4:ts=4: