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 7848 2007-05-01 21:40:26Z pm $
39 #include "vm/jit/s390/arch.h"
40 #include "vm/jit/s390/codegen.h"
41 #include "vm/jit/s390/emit.h"
43 #include "mm/memory.h"
44 #include "native/jni.h"
45 #include "native/native.h"
47 #if defined(ENABLE_THREADS)
48 # include "threads/native/lock.h"
51 #include "vm/builtin.h"
52 #include "vm/exceptions.h"
53 #include "vm/global.h"
54 #include "vmcore/loader.h"
55 #include "vmcore/options.h"
56 #include "vmcore/statistics.h"
57 #include "vm/stringlocal.h"
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/codegen-common.h"
61 #include "vm/jit/dseg.h"
62 #include "vm/jit/emit-common.h"
63 #include "vm/jit/jit.h"
64 #include "vm/jit/methodheader.h"
65 #include "vm/jit/parse.h"
66 #include "vm/jit/patcher.h"
67 #include "vm/jit/reg.h"
68 #include "vm/jit/replace.h"
69 #include "vm/jit/stacktrace.h"
70 #include "vm/jit/abi.h"
71 #include "vm/jit/emit-common.h"
73 #if defined(ENABLE_LSRA)
74 # include "vm/jit/allocator/lsra.h"
77 #define OOPS() assert(0);
81 /* codegen *********************************************************************
83 Generates machine code.
85 *******************************************************************************/
88 bool codegen_emit(jitdata *jd)
94 s4 len, s1, s2, s3, d, dd, disp;
97 varinfo *var, *var1, *var2, *dst;
101 constant_classref *cr;
102 unresolved_class *uc;
103 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
104 unresolved_method *um;
105 builtintable_entry *bte;
108 unresolved_field *uf;
111 rplpoint *replacementpoint;
115 /* get required compiler data */
122 /* prevent compiler warnings */
135 /* space to save used callee saved registers */
137 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
138 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
140 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
143 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
146 #if defined(ENABLE_THREADS)
147 /* Space to save argument of monitor_enter and Return Values to
148 survive monitor_exit. The stack position for the argument can
149 not be shared with place to save the return register
150 since both values reside in R2. */
152 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
153 /* reserve 2 slots for long/double return values for monitorexit */
155 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
156 cd->stackframesize += 3;
158 cd->stackframesize += 2;
162 /* Keep stack of non-leaf functions 16-byte aligned for calls into
163 native code e.g. libc or jni (alignment problems with
166 if (!jd->isleafmethod || opt_verbosecall )
167 /* TODO really 16 bytes ? */
168 cd->stackframesize = (cd->stackframesize + 3) & ~3;
170 /* create method header */
172 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
173 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
175 #if defined(ENABLE_THREADS)
176 /* IsSync contains the offset relative to the stack pointer for the
177 argument of monitor_exit used in the exception handler. Since the
178 offset could be zero and give a wrong meaning of the flag it is
182 if (checksync && (m->flags & ACC_SYNCHRONIZED))
183 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
187 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
189 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
190 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
191 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
193 (void) dseg_addlinenumbertablesize(cd);
195 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
197 /* create exception table */
199 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
200 dseg_add_target(cd, ex->start);
201 dseg_add_target(cd, ex->end);
202 dseg_add_target(cd, ex->handler);
203 (void) dseg_add_unique_address(cd, ex->catchtype.any);
206 /* generate method profiling code */
208 #if defined(ENABLE_PROFILING)
209 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
210 /* count frequency */
212 M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
213 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
214 M_IADD_IMM(1, REG_ITMP2);
215 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
217 /* PROFILE_CYCLE_START; */
221 /* create stack frame (if necessary) */
223 if (cd->stackframesize)
224 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
226 /* save used callee saved registers and return address */
228 p = cd->stackframesize;
229 p--; M_AST(REG_RA, REG_SP, p * 4);
231 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
232 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
234 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
235 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
238 /* take arguments out of register or stack frame */
242 for (p = 0, l = 0; p < md->paramcount; p++) {
243 t = md->paramtypes[p].type;
244 varindex = jd->local_map[l * 5 + t];
247 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
250 if (varindex == UNUSED)
255 s1 = md->params[p].regoff;
256 if (IS_INT_LNG_TYPE(t)) { /* integer args */
257 if (IS_2_WORD_TYPE(t)) {
265 if (!md->params[p].inmemory) { /* register arguments */
266 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
267 if (IS_2_WORD_TYPE(t))
268 M_LNGMOVE(s2, var->vv.regoff);
270 M_INTMOVE(s2, var->vv.regoff);
272 } else { /* reg arg -> spilled */
273 if (IS_2_WORD_TYPE(t))
274 M_LST(s2, REG_SP, var->vv.regoff * 4);
276 M_IST(s2, REG_SP, var->vv.regoff * 4);
279 } else { /* stack arguments */
280 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
281 if (IS_2_WORD_TYPE(t))
282 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
284 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
286 } else { /* stack arg -> spilled */
287 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
288 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
289 if (IS_2_WORD_TYPE(t)) {
290 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4);
291 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
296 } else { /* floating args */
297 if (!md->params[p].inmemory) { /* register arguments */
299 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
300 M_FLTMOVE(s2, var->vv.regoff);
302 } else { /* reg arg -> spilled */
303 if (IS_2_WORD_TYPE(t))
304 M_DST(s2, REG_SP, var->vv.regoff * 4);
306 M_FST(s2, REG_SP, var->vv.regoff * 4);
309 } else { /* stack arguments */
310 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
311 if (IS_2_WORD_TYPE(t))
312 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
315 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
317 } else { /* stack-arg -> spilled */
318 if (IS_2_WORD_TYPE(t)) {
319 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
320 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
321 var->vv.regoff = cd->stackframesize + s1;
324 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
325 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
332 /* save monitorenter argument */
334 #if defined(ENABLE_THREADS)
335 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
336 /* stack offset for monitor argument */
341 if (opt_verbosecall) {
342 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
344 for (p = 0; p < INT_ARG_CNT; p++)
345 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
347 for (p = 0; p < FLT_ARG_CNT; p++)
348 M_FST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
350 s1 += ((INT_ARG_CNT + FLT_ARG_CNT) * 2);
354 /* decide which monitor enter function to call */
356 if (m->flags & ACC_STATIC) {
357 disp = dseg_add_address(cd, &m->class->object.header);
358 M_ALD(REG_A0, REG_PV, disp);
362 M_BNE(SZ_BRC + SZ_ILL);
363 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
366 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
367 M_ALD(REG_ITMP3, REG_PV, disp);
369 M_AST(REG_A0, REG_SP, s1 * 4);
371 M_ASUB_IMM(96, REG_SP);
373 M_AADD_IMM(96, REG_SP);
376 if (opt_verbosecall) {
377 for (p = 0; p < INT_ARG_CNT; p++)
378 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
380 for (p = 0; p < FLT_ARG_CNT; p++)
381 M_FLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
383 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
390 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
391 emit_verbosecall_enter(jd);
392 #endif /* !defined(NDEBUG) */
396 /* end of header generation */
398 replacementpoint = jd->code->rplpoints;
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 */
416 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
417 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
421 assert(cd->lastmcodeptr <= cd->mcodeptr);
422 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
426 /* copy interface registers to their destination */
431 /* generate basicblock profiling code */
433 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
434 /* count frequency */
436 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
437 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
439 /* if this is an exception handler, start profiling again */
441 if (bptr->type == BBTYPE_EXH)
445 #if defined(ENABLE_LSRA)
449 src = bptr->invars[len];
450 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
451 if (bptr->type == BBTYPE_EXH) {
452 /* d = reg_of_var(rd, src, REG_ITMP1); */
453 if (!IS_INMEMORY(src->flags))
457 M_INTMOVE(REG_ITMP1, d);
458 emit_store(jd, NULL, src, d);
468 var = VAR(bptr->invars[len]);
469 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
470 if (bptr->type == BBTYPE_EXH) {
471 d = codegen_reg_of_var(0, var, REG_ITMP1);
472 M_INTMOVE(REG_ITMP1, d);
473 emit_store(jd, NULL, var, d);
477 assert((var->flags & INOUT));
480 #if defined(ENABLE_LSRA)
483 /* walk through all instructions */
488 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
489 if (iptr->line != currentline) {
490 dseg_addlinenumber(cd, iptr->line);
491 currentline = iptr->line;
494 MCODECHECK(1024); /* 1KB should be enough */
497 case ICMD_NOP: /* ... ==> ... */
498 case ICMD_POP: /* ..., value ==> ... */
499 case ICMD_POP2: /* ..., value, value ==> ... */
500 case ICMD_INLINE_START: /* internal ICMDs */
501 case ICMD_INLINE_END:
504 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
505 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
506 emit_nullpointer_check(cd, iptr, s1);
509 /* constant operations ************************************************/
511 case ICMD_ICONST: /* ... ==> ..., constant */
512 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
513 ICONST(d, iptr->sx.val.i);
514 emit_store_dst(jd, iptr, d);
517 case ICMD_LCONST: /* ... ==> ..., constant */
519 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
520 LCONST(d, iptr->sx.val.l);
521 emit_store_dst(jd, iptr, d);
524 case ICMD_FCONST: /* ... ==> ..., constant */
525 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
526 disp = dseg_add_float(cd, iptr->sx.val.f);
527 M_FLDN(d, REG_PV, disp, REG_ITMP1);
528 emit_store_dst(jd, iptr, d);
531 case ICMD_DCONST: /* ... ==> ..., constant */
532 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
533 disp = dseg_add_double(cd, iptr->sx.val.d);
534 M_DLDN(d, REG_PV, disp, REG_ITMP1);
535 emit_store_dst(jd, iptr, d);
538 case ICMD_ACONST: /* ... ==> ..., constant */
539 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
541 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
542 cr = iptr->sx.val.c.ref;
543 disp = dseg_add_unique_address(cd, cr);
545 /* PROFILE_CYCLE_STOP; */
547 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
550 /* PROFILE_CYCLE_START; */
552 M_ALD(d, REG_PV, disp);
554 if (iptr->sx.val.anyptr == 0) {
557 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
558 M_ALD(d, REG_PV, disp);
561 emit_store_dst(jd, iptr, d);
565 /* load/store/copy/move operations ************************************/
567 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
568 case ICMD_ALOAD: /* s1 = local variable */
572 case ICMD_ISTORE: /* ..., value ==> ... */
583 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
587 /* integer operations *************************************************/
589 case ICMD_INEG: /* ..., value ==> ..., - value */
591 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
592 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
594 emit_store_dst(jd, iptr, d);
598 case ICMD_LNEG: /* ..., value ==> ..., - value */
600 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
601 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
602 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
603 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
604 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
605 N_AHI(GET_HIGH_REG(d), -1);
606 emit_store_dst(jd, iptr, d);
609 case ICMD_I2L: /* ..., value ==> ..., value */
611 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
612 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
614 M_INTMOVE(s1, GET_HIGH_REG(d));
615 ICONST(GET_LOW_REG(d), 0);
616 M_SRDA_IMM(32, GET_HIGH_REG(d));
618 emit_copy_dst(jd, iptr, d);
619 emit_store_dst(jd, iptr, d);
620 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
624 case ICMD_L2I: /* ..., value ==> ..., value */
625 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
626 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
627 M_INTMOVE(GET_LOW_REG(s1), d);
628 emit_store_dst(jd, iptr, d);
631 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
632 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
633 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
637 emit_store_dst(jd, iptr, d);
640 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
641 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
642 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
646 emit_store_dst(jd, iptr, d);
649 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
651 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
652 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
656 emit_store_dst(jd, iptr, d);
659 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
661 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
662 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
663 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
670 emit_store_dst(jd, iptr, d);
675 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
676 /* sx.val.i = constant */
677 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
678 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
681 if (N_VALID_IMM(iptr->sx.val.i)) {
682 M_IADD_IMM(iptr->sx.val.i, d);
684 ICONST(REG_ITMP2, iptr->sx.val.i);
685 M_IADD(REG_ITMP2, d);
687 emit_store_dst(jd, iptr, d);
690 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
692 /* M, (r, q) -> (r, q) */
694 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
696 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
697 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
698 dd = GET_HIGH_REG(d);
707 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
708 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
718 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
719 N_AHI(GET_HIGH_REG(d), 1);
721 emit_store_dst(jd, iptr, d);
724 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
725 /* sx.val.l = constant */
727 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
728 dd = GET_HIGH_REG(d);
730 s1 = emit_load_s1_high(jd, iptr, dd);
731 s3 = iptr->sx.val.l >> 32;
735 if (N_VALID_IMM(s3)) {
738 ICONST(REG_ITMP3, s3);
739 M_IADD(REG_ITMP3, dd);
743 s1 = emit_load_s1_low(jd, iptr, dd);
744 s3 = iptr->sx.val.l & 0xffffffff;
745 ICONST(REG_ITMP3, s3);
748 N_ALR(dd, REG_ITMP3);
750 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
751 N_AHI(GET_HIGH_REG(d), 1);
753 emit_store_dst(jd, iptr, d);
756 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
758 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
759 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
760 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
762 M_INTMOVE(s1, REG_ITMP1);
763 M_ISUB(s2, REG_ITMP1);
764 M_INTMOVE(REG_ITMP1, d);
769 emit_store_dst(jd, iptr, d);
773 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
774 /* sx.val.i = constant */
776 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
777 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
780 if (N_VALID_IMM(-iptr->sx.val.i)) {
781 M_ISUB_IMM(iptr->sx.val.i, d);
783 ICONST(REG_ITMP2, iptr->sx.val.i);
784 M_ISUB(REG_ITMP2, d);
786 emit_store_dst(jd, iptr, d);
790 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
792 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
794 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
795 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
796 dd = GET_HIGH_REG(d);
799 M_INTMOVE(s2, REG_ITMP3);
806 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
807 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
811 M_INTMOVE(s2, REG_ITMP3);
818 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
819 N_AHI(GET_HIGH_REG(d), -1);
821 emit_store_dst(jd, iptr, d);
824 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
825 /* sx.val.l = constant */
827 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
829 dd = GET_HIGH_REG(d);
830 s1 = emit_load_s1_high(jd, iptr, dd);
831 s3 = iptr->sx.val.l >> 32;
835 if (N_VALID_IMM(-s3)) {
838 ICONST(REG_ITMP3, s3);
839 M_ISUB(REG_ITMP3, dd);
843 s1 = emit_load_s1_low(jd, iptr, dd);
844 s3 = iptr->sx.val.l & 0xffffffff;
845 ICONST(REG_ITMP3, s3);
848 N_SLR(dd, REG_ITMP3);
850 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
851 N_AHI(GET_HIGH_REG(d), -1);
853 emit_store_dst(jd, iptr, d);
856 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
858 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
859 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
860 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
867 emit_store_dst(jd, iptr, d);
871 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
872 /* sx.val.i = constant */
873 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
874 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
876 if (iptr->sx.val.i == 2) {
878 } else if (N_VALID_IMM(iptr->sx.val.i)) {
879 M_IMUL_IMM(iptr->sx.val.i, d);
881 disp = dseg_add_s4(cd, iptr->sx.val.i);
882 M_ILD(REG_ITMP2, REG_PV, disp);
883 M_IMUL(REG_ITMP2, d);
885 emit_store_dst(jd, iptr, d);
888 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
889 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
891 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
892 emit_arithmetic_check(cd, iptr, s2);
894 /* For this operation we need a register pair.
895 * We will use r0 and itmp1 and will backup r0.
898 M_INTMOVE(R0, REG_ITMP3);
900 /* We won't check for division by 0, we catch a SIGFPE instead
901 * Special case 0x80000000 / 0xffffffff handled by signal handler too.
904 s1 = emit_load_s1(jd, iptr, R0);
913 d = codegen_reg_of_dst(jd, iptr, R0);
917 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
918 M_INTMOVE(REG_ITMP1, d);
922 emit_store_dst(jd, iptr, d);
924 /* If destionation of operation was not register R0,
928 if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
929 M_INTMOVE(REG_ITMP3, R0);
934 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
935 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
937 bte = iptr->sx.s23.s3.bte;
940 /* test s2 for zero */
942 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
943 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
944 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
945 emit_arithmetic_check(cd, iptr, REG_ITMP3);
949 disp = dseg_add_functionptr(cd, bte->fp);
953 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
955 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
956 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
960 M_ASUB_IMM(96, REG_SP);
961 M_ALD(REG_ITMP3, REG_PV, disp);
962 M_JSR(REG_RA, REG_ITMP3);
963 M_AADD_IMM(96, REG_SP);
967 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
968 M_LNGMOVE(REG_RESULT_PACKED, d);
969 emit_store_dst(jd, iptr, d);
973 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
974 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
975 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
977 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
978 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
979 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
981 /* Use only 5 bits of sencond operand. */
983 M_INTMOVE(s2, REG_ITMP2);
985 ICONST(REG_ITMP3, 0x1F);
986 M_IAND(REG_ITMP3, s2);
1003 emit_store_dst(jd, iptr, d);
1006 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1007 /* sx.val.i = constant */
1011 assert(iptr->sx.val.i <= 32);
1013 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1014 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1021 s3 = (1 << iptr->sx.val.i) - 1;
1023 if (N_VALID_IMM(s3)) {
1026 ICONST(REG_ITMP1, -1);
1027 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1028 M_IADD(REG_ITMP1, d);
1031 *(u4 *)ref |= (u4)(cd->mcodeptr - ref) / 2;
1033 M_SRA_IMM(iptr->sx.val.i, d);
1035 emit_store_dst(jd, iptr, d);
1040 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1041 /* sx.val.i = constant */
1043 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1044 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1047 M_MOV(s1, REG_ITMP1);
1051 ICONST(REG_ITMP3, iptr->sx.val.i);
1054 M_IAND(REG_ITMP3, d);
1057 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1063 emit_store_dst(jd, iptr, d);
1067 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1068 /* sx.val.i = constant */
1069 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1070 /* sx.val.i = constant */
1071 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1072 /* sx.val.i = constant */
1073 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1074 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1078 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1080 switch (iptr->opc) {
1081 case ICMD_ISHLCONST:
1084 case ICMD_ISHRCONST:
1087 case ICMD_IUSHRCONST:
1094 emit_store_dst(jd, iptr, d);
1097 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1099 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1101 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1103 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1105 /* Use only 6 bits of second operand */
1107 M_INTMOVE(s2, REG_ITMP3);
1109 ICONST(REG_ITMP2, 0x3F);
1110 M_IAND(REG_ITMP2, s2);
1112 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1114 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1115 M_INTMOVE(s2, REG_ITMP3);
1119 s1 = emit_load_s1(jd, iptr, d);
1123 switch (iptr->opc) {
1125 M_SLDL(s2, GET_HIGH_REG(d));
1128 M_SRDA(s2, GET_HIGH_REG(d));
1131 M_SRDL(s2, GET_HIGH_REG(d));
1137 emit_copy_dst(jd, iptr, d);
1138 emit_store_dst(jd, iptr, d);
1139 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1143 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1144 /* sx.val.i = constant */
1145 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1146 /* sx.val.i = constant */
1147 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1148 /* sx.val.l = constant */
1151 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1152 s1 = emit_load_s1(jd, iptr, d);
1156 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1158 switch (iptr->opc) {
1159 case ICMD_LSHLCONST:
1160 N_SLDL(GET_HIGH_REG(d), disp, RN);
1162 case ICMD_LSHRCONST:
1163 N_SRDA(GET_HIGH_REG(d), disp, RN);
1165 case ICMD_LUSHRCONST:
1166 N_SRDL(GET_HIGH_REG(d), disp, RN);
1169 N_SLDL(GET_HIGH_REG(d), disp, RN);
1175 emit_copy_dst(jd, iptr, d);
1176 emit_store_dst(jd, iptr, d);
1177 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1181 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1183 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1184 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1185 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1192 emit_store_dst(jd, iptr, d);
1196 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1198 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1199 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1200 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1207 emit_store_dst(jd, iptr, d);
1211 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1213 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1214 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1215 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1222 emit_store_dst(jd, iptr, d);
1228 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1229 /* sx.val.i = constant */
1230 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1231 /* sx.val.i = constant */
1232 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1233 /* sx.val.i = constant */
1235 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1236 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1239 ICONST(REG_ITMP2, iptr->sx.val.i);
1241 switch (iptr->opc) {
1242 case ICMD_IANDCONST:
1243 M_IAND(REG_ITMP2, d);
1245 case ICMD_IXORCONST:
1246 M_IXOR(REG_ITMP2, d);
1249 M_IOR(REG_ITMP2, d);
1255 emit_store_dst(jd, iptr, d);
1259 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1260 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1261 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1263 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1265 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1266 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1267 dd = GET_LOW_REG(d);
1269 switch (iptr->opc) {
1298 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1299 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1300 dd = GET_HIGH_REG(d);
1302 switch (iptr->opc) {
1331 emit_store_dst(jd, iptr, d);
1334 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1335 /* sx.val.l = constant */
1336 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1337 /* sx.val.l = constant */
1338 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1339 /* sx.val.l = constant */
1341 /* TODO should use memory operand to access data segment, not load */
1343 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1345 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1346 s3 = iptr->sx.val.l & 0xffffffff;
1348 M_INTMOVE(s1, GET_LOW_REG(d));
1350 ICONST(REG_ITMP3, s3);
1352 switch (iptr->opc) {
1353 case ICMD_LANDCONST:
1354 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1356 case ICMD_LXORCONST:
1357 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1360 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1366 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1367 s3 = iptr->sx.val.l >> 32;
1369 M_INTMOVE(s1, GET_HIGH_REG(d));
1371 ICONST(REG_ITMP3, s3);
1373 switch (iptr->opc) {
1374 case ICMD_LANDCONST:
1375 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1377 case ICMD_LXORCONST:
1378 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1381 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1387 emit_store_dst(jd, iptr, d);
1391 /* floating operations ************************************************/
1393 case ICMD_FNEG: /* ..., value ==> ..., - value */
1394 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1395 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1397 emit_store_dst(jd, iptr, d);
1400 case ICMD_DNEG: /* ..., value ==> ..., - value */
1401 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1402 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1404 emit_store_dst(jd, iptr, d);
1407 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1408 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1409 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1410 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1417 emit_store_dst(jd, iptr, d);
1420 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1421 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1422 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1423 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1430 emit_store_dst(jd, iptr, d);
1433 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1434 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1435 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1436 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1440 emit_store_dst(jd, iptr, d);
1443 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1444 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1445 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1446 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1450 emit_store_dst(jd, iptr, d);
1453 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1454 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1455 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1456 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1463 emit_store_dst(jd, iptr, d);
1466 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1467 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1468 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1469 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1476 emit_store_dst(jd, iptr, d);
1479 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1480 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1481 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1482 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1486 emit_store_dst(jd, iptr, d);
1489 case ICMD_DDIV: /* ..., 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_I2F: /* ..., value ==> ..., (float) value */
1500 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1501 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1503 emit_store_dst(jd, iptr, d);
1506 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1507 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1508 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1510 emit_store_dst(jd, iptr, d);
1513 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1514 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1515 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1517 emit_store_dst(jd, iptr, d);
1518 /* TODO: corner cases ? */
1521 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1522 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1523 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1525 emit_store_dst(jd, iptr, d);
1526 /* TODO: corner cases ? */
1531 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1532 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1533 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1535 emit_store_dst(jd, iptr, d);
1538 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1539 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1540 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1542 emit_store_dst(jd, iptr, d);
1545 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1546 /* == => 0, < => 1, > => -1 */
1550 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1551 /* == => 0, < => 1, > => -1 */
1554 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1555 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1556 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1558 switch (iptr->opc) {
1570 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1571 SZ_BRC + SZ_BRC + SZ_BRC
1574 N_BRC( /* load -1 */
1575 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1576 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1581 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1584 N_LHI(d, 1); /* GT */
1585 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1586 N_LHI(d, -1); /* LT */
1587 M_BR(SZ_BRC + SZ_LHI);
1588 N_LHI(d, 0); /* EQ */
1590 emit_store_dst(jd, iptr, d);
1595 /* memory operations **************************************************/
1597 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1599 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1600 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1602 /* implicit null-pointer check */
1603 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1604 emit_store_dst(jd, iptr, d);
1608 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1609 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1610 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1611 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1613 /* implicit null-pointer check */
1614 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1616 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1621 emit_store_dst(jd, iptr, d);
1624 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1626 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1627 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1628 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1630 /* implicit null-pointer check */
1631 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1633 M_INTMOVE(s2, REG_ITMP2);
1634 M_SLL_IMM(1, REG_ITMP2);
1636 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1638 /* N_LH does sign extends, undo ! */
1643 emit_store_dst(jd, iptr, d);
1646 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1647 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1648 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1649 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1651 /* implicit null-pointer check */
1652 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1654 M_INTMOVE(s2, REG_ITMP2);
1655 M_SLL_IMM(1, REG_ITMP2);
1657 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1658 emit_store_dst(jd, iptr, d);
1661 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1662 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1663 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1664 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1666 /* implicit null-pointer check */
1667 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1669 M_INTMOVE(s2, REG_ITMP2);
1670 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1671 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1672 emit_store_dst(jd, iptr, d);
1675 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1677 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1678 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1680 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1682 /* implicit null-pointer check */
1683 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1685 M_INTMOVE(s2, REG_ITMP2);
1686 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1688 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1689 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1690 emit_store_dst(jd, iptr, d);
1694 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1696 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1697 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1698 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1700 /* implicit null-pointer check */
1701 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1703 M_INTMOVE(s2, REG_ITMP2);
1704 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1706 N_LE(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1708 emit_store_dst(jd, iptr, d);
1711 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1712 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1713 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1714 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1716 /* implicit null-pointer check */
1717 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1719 M_INTMOVE(s2, REG_ITMP2);
1720 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1722 N_LD(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1724 emit_store_dst(jd, iptr, d);
1727 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1728 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1729 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1730 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1732 /* implicit null-pointer check */
1733 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1735 M_INTMOVE(s2, REG_ITMP2);
1736 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1737 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1738 emit_store_dst(jd, iptr, d);
1741 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1742 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1743 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1744 /* implicit null-pointer check */
1745 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1746 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1748 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1751 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1753 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1754 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1755 /* implicit null-pointer check */
1756 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1757 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1759 M_INTMOVE(s2, REG_ITMP2);
1760 M_SLL_IMM(1, REG_ITMP2);
1762 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1766 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1767 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1768 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1769 /* implicit null-pointer check */
1770 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1771 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1773 M_INTMOVE(s2, REG_ITMP2);
1774 M_SLL_IMM(1, REG_ITMP2);
1776 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1779 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1781 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1782 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1783 /* implicit null-pointer check */
1784 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1786 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1788 M_INTMOVE(s2, REG_ITMP2);
1789 M_SLL_IMM(2, REG_ITMP2);
1791 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1794 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1796 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1797 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1798 /* implicit null-pointer check */
1799 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1801 M_INTMOVE(s2, REG_ITMP2);
1802 M_SLL_IMM(3, REG_ITMP2);
1804 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1805 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1806 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1807 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1810 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1811 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1812 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1813 /* implicit null-pointer check */
1814 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1815 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1817 M_INTMOVE(s2, REG_ITMP2);
1818 M_SLL_IMM(2, REG_ITMP2);
1820 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1823 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1824 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1825 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1826 /* implicit null-pointer check */
1827 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1828 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1830 M_INTMOVE(s2, REG_ITMP2);
1831 M_SLL_IMM(3, REG_ITMP2);
1833 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1836 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1838 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1839 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1840 /* implicit null-pointer check */
1841 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1842 s3 = emit_load_s3(jd, iptr, REG_A1);
1844 M_INTMOVE(s1, REG_A0);
1845 M_INTMOVE(s3, REG_A1);
1847 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1848 M_ALD(REG_ITMP3, REG_PV, disp);
1849 M_ASUB_IMM(96, REG_SP);
1850 M_JSR(REG_RA, REG_ITMP3);
1851 M_AADD_IMM(96, REG_SP);
1853 emit_exception_check(cd, iptr);
1855 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1856 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1857 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1859 M_INTMOVE(s2, REG_ITMP2);
1860 M_SLL_IMM(2, REG_ITMP2);
1861 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1864 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1865 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1870 case ICMD_GETSTATIC: /* ... ==> ..., value */
1872 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1873 uf = iptr->sx.s23.s3.uf;
1874 fieldtype = uf->fieldref->parseddesc.fd->type;
1875 disp = dseg_add_unique_address(cd, NULL);
1877 /* PROFILE_CYCLE_STOP; */
1879 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1881 /* PROFILE_CYCLE_START; */
1884 fi = iptr->sx.s23.s3.fmiref->p.field;
1885 fieldtype = fi->type;
1886 disp = dseg_add_address(cd, &(fi->value));
1888 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1891 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
1893 PROFILE_CYCLE_START;
1897 M_ALD(REG_ITMP1, REG_PV, disp);
1899 switch (fieldtype) {
1901 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1902 M_ILD(d, REG_ITMP1, 0);
1905 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1906 M_LLD(d, REG_ITMP1, 0);
1909 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1910 M_ALD(d, REG_ITMP1, 0);
1913 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1914 M_FLD(d, REG_ITMP1, 0);
1917 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1918 M_DLD(d, REG_ITMP1, 0);
1922 emit_store_dst(jd, iptr, d);
1926 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1928 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1929 uf = iptr->sx.s23.s3.uf;
1930 fieldtype = uf->fieldref->parseddesc.fd->type;
1931 disp = dseg_add_unique_address(cd, uf);
1933 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
1936 fi = iptr->sx.s23.s3.fmiref->p.field;
1937 fieldtype = fi->type;
1938 disp = dseg_add_address(cd, &(fi->value));
1940 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1941 codegen_addpatchref(cd, PATCHER_clinit,
1945 M_ALD(REG_ITMP1, REG_PV, disp);
1946 switch (fieldtype) {
1948 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1949 M_IST(s1, REG_ITMP1, 0);
1952 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
1953 M_LST(s1, REG_ITMP1, 0);
1956 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1957 M_AST(s1, REG_ITMP1, 0);
1960 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1961 M_FST(s1, REG_ITMP1, 0);
1964 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1965 M_DST(s1, REG_ITMP1, 0);
1970 case ICMD_GETFIELD: /* ... ==> ..., value */
1972 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1973 emit_nullpointer_check(cd, iptr, s1);
1975 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1976 uf = iptr->sx.s23.s3.uf;
1977 fieldtype = uf->fieldref->parseddesc.fd->type;
1980 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1983 fi = iptr->sx.s23.s3.fmiref->p.field;
1984 fieldtype = fi->type;
1988 switch (fieldtype) {
1990 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1994 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1995 if (GET_HIGH_REG(d) == s1) {
1996 M_ILD(GET_LOW_REG(d), s1, disp + 4);
1997 M_ILD(GET_HIGH_REG(d), s1, disp);
2000 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2001 M_ILD(GET_HIGH_REG(d), s1, disp);
2005 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2009 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2013 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2017 emit_store_dst(jd, iptr, d);
2020 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2022 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2023 emit_nullpointer_check(cd, iptr, s1);
2025 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2026 uf = iptr->sx.s23.s3.uf;
2027 fieldtype = uf->fieldref->parseddesc.fd->type;
2031 fi = iptr->sx.s23.s3.fmiref->p.field;
2032 fieldtype = fi->type;
2036 if (IS_INT_LNG_TYPE(fieldtype)) {
2037 if (IS_2_WORD_TYPE(fieldtype))
2038 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2040 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2043 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2045 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2046 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2048 switch (fieldtype) {
2050 M_IST(s2, s1, disp);
2053 /* TODO really order */
2054 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2055 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2058 M_AST(s2, s1, disp);
2061 M_FST(s2, s1, disp);
2064 M_DST(s2, s1, disp);
2069 /* branch operations **************************************************/
2071 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2073 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2074 M_INTMOVE(s1, REG_ITMP1_XPTR);
2078 #ifdef ENABLE_VERIFIER
2079 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2080 uc = iptr->sx.s23.s2.uc;
2082 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2084 #endif /* ENABLE_VERIFIER */
2086 disp = dseg_add_functionptr(cd, asm_handle_exception);
2087 M_ALD(REG_ITMP2, REG_PV, disp);
2088 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2093 case ICMD_GOTO: /* ... ==> ... */
2094 case ICMD_RET: /* ... ==> ... */
2096 emit_br(cd, iptr->dst.block);
2100 case ICMD_JSR: /* ... ==> ... */
2102 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2106 case ICMD_IFNULL: /* ..., value ==> ... */
2107 case ICMD_IFNONNULL: /* ..., value ==> ... */
2108 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2110 switch (iptr->opc) {
2112 emit_beq(cd, iptr->dst.block);
2114 case ICMD_IFNONNULL:
2115 emit_bne(cd, iptr->dst.block);
2120 case ICMD_IFEQ: /* ..., value ==> ... */
2121 case ICMD_IFLT: /* ..., value ==> ... */
2122 case ICMD_IFLE: /* ..., value ==> ... */
2123 case ICMD_IFNE: /* ..., value ==> ... */
2124 case ICMD_IFGT: /* ..., value ==> ... */
2125 case ICMD_IFGE: /* ..., value ==> ... */
2127 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2129 if (N_VALID_IMM(iptr->sx.val.i))
2130 M_ICMP_IMM(s1, iptr->sx.val.i);
2132 disp = dseg_add_s4(cd, iptr->sx.val.i);
2133 ICONST(REG_ITMP2, disp);
2134 N_C(s1, 0, REG_ITMP2, REG_PV);
2137 switch (iptr->opc) {
2139 emit_blt(cd, iptr->dst.block);
2142 emit_ble(cd, iptr->dst.block);
2145 emit_bne(cd, iptr->dst.block);
2148 emit_bgt(cd, iptr->dst.block);
2151 emit_bge(cd, iptr->dst.block);
2154 emit_beq(cd, iptr->dst.block);
2160 case ICMD_IF_LLT: /* ..., value ==> ... */
2161 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2167 /* ATTENTION: compare high words signed and low words unsigned */
2169 # define LABEL_OUT BRANCH_LABEL_1
2171 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2173 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2174 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2176 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2177 ICONST(REG_ITMP2, disp);
2178 N_C(s1, 0, REG_ITMP2, REG_PV);
2184 emit_blt(cd, iptr->dst.block);
2185 /* EQ ... fall through */
2186 emit_label_bgt(cd, LABEL_OUT);
2190 emit_bgt(cd, iptr->dst.block);
2191 /* EQ ... fall through */
2192 emit_label_blt(cd, LABEL_OUT);
2195 /* EQ ... fall through */
2196 emit_label_bne(cd, LABEL_OUT);
2199 /* EQ ... fall through */
2200 emit_bne(cd, iptr->dst.block);
2206 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2208 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2209 ICONST(REG_ITMP2, disp);
2210 N_CL(s1, 0, REG_ITMP2, REG_PV);
2214 emit_blt(cd, iptr->dst.block);
2215 emit_label(cd, LABEL_OUT);
2218 emit_ble(cd, iptr->dst.block);
2219 emit_label(cd, LABEL_OUT);
2222 emit_bgt(cd, iptr->dst.block);
2223 emit_label(cd, LABEL_OUT);
2226 emit_bge(cd, iptr->dst.block);
2227 emit_label(cd, LABEL_OUT);
2230 emit_beq(cd, iptr->dst.block);
2231 emit_label(cd, LABEL_OUT);
2234 emit_bne(cd, iptr->dst.block);
2243 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2244 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2246 /* Compare addresses as 31 bit unsigned integers */
2248 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2249 M_LDA(REG_ITMP1, s1, 0);
2251 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2252 M_LDA(REG_ITMP2, s2, 0);
2254 M_CMP(REG_ITMP1, REG_ITMP2);
2256 switch (iptr->opc) {
2257 case ICMD_IF_ACMPEQ:
2258 emit_beq(cd, iptr->dst.block);
2260 case ICMD_IF_ACMPNE:
2261 emit_bne(cd, iptr->dst.block);
2267 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2268 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2269 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2270 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2271 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2272 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2274 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2275 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2277 switch (iptr->opc) {
2278 case ICMD_IF_ICMPEQ:
2279 emit_beq(cd, iptr->dst.block);
2281 case ICMD_IF_ICMPNE:
2282 emit_bne(cd, iptr->dst.block);
2284 case ICMD_IF_ICMPLT:
2285 emit_blt(cd, iptr->dst.block);
2287 case ICMD_IF_ICMPGT:
2288 emit_bgt(cd, iptr->dst.block);
2290 case ICMD_IF_ICMPLE:
2291 emit_ble(cd, iptr->dst.block);
2293 case ICMD_IF_ICMPGE:
2294 emit_bge(cd, iptr->dst.block);
2300 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2301 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2302 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2303 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2304 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2305 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2310 /* ATTENTION: compare high words signed and low words unsigned */
2312 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2313 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2318 case ICMD_IF_LCMPLT:
2319 case ICMD_IF_LCMPLE:
2320 emit_blt(cd, iptr->dst.block);
2321 /* EQ ... fall through */
2322 out_ref = cd->mcodeptr;
2325 case ICMD_IF_LCMPGT:
2326 case ICMD_IF_LCMPGE:
2327 emit_bgt(cd, iptr->dst.block);
2328 /* EQ ... fall through */
2329 out_ref = cd->mcodeptr;
2332 case ICMD_IF_LCMPEQ:
2333 /* EQ ... fall through */
2334 out_ref = cd->mcodeptr;
2337 case ICMD_IF_LCMPNE:
2338 /* EQ ... fall through */
2339 emit_bne(cd, iptr->dst.block);
2345 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2346 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2351 case ICMD_IF_LCMPLT:
2352 emit_blt(cd, iptr->dst.block);
2354 case ICMD_IF_LCMPLE:
2355 emit_ble(cd, iptr->dst.block);
2357 case ICMD_IF_LCMPGT:
2358 emit_bgt(cd, iptr->dst.block);
2360 case ICMD_IF_LCMPGE:
2361 emit_bge(cd, iptr->dst.block);
2363 case ICMD_IF_LCMPEQ:
2364 emit_beq(cd, iptr->dst.block);
2366 case ICMD_IF_LCMPNE:
2367 emit_bne(cd, iptr->dst.block);
2374 if (out_ref != NULL) {
2375 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2381 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2383 REPLACEMENT_POINT_RETURN(cd, iptr);
2384 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2385 M_INTMOVE(s1, REG_RESULT);
2386 goto nowperformreturn;
2388 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2390 REPLACEMENT_POINT_RETURN(cd, iptr);
2391 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2392 M_INTMOVE(s1, REG_RESULT);
2394 #ifdef ENABLE_VERIFIER
2395 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2396 unresolved_class *uc = iptr->sx.s23.s2.uc;
2398 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2400 #endif /* ENABLE_VERIFIER */
2401 goto nowperformreturn;
2403 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2405 REPLACEMENT_POINT_RETURN(cd, iptr);
2406 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2407 M_LNGMOVE(s1, REG_RESULT_PACKED);
2408 goto nowperformreturn;
2410 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2413 REPLACEMENT_POINT_RETURN(cd, iptr);
2414 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2415 M_FLTMOVE(s1, REG_FRESULT);
2416 goto nowperformreturn;
2418 case ICMD_RETURN: /* ... ==> ... */
2420 REPLACEMENT_POINT_RETURN(cd, iptr);
2426 p = cd->stackframesize;
2428 /* call trace function */
2430 #if !defined(NDEBUG)
2431 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2432 emit_verbosecall_exit(jd);
2433 #endif /* !defined(NDEBUG) */
2435 #if defined(ENABLE_THREADS)
2436 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2438 /* we need to save the proper return value */
2440 switch (iptr->opc) {
2442 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2446 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2449 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2452 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2456 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2458 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2459 M_ALD(REG_ITMP3, REG_PV, disp);
2461 M_ASUB_IMM(96, REG_SP);
2463 M_AADD_IMM(96, REG_SP);
2465 /* and now restore the proper return value */
2467 switch (iptr->opc) {
2469 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2473 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2476 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2479 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2485 /* restore return address */
2487 p--; M_ALD(REG_RA, REG_SP, p * 4);
2489 /* restore saved registers */
2491 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2492 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2494 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2495 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2498 /* deallocate stack */
2500 if (cd->stackframesize)
2501 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2508 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2511 branch_target_t *table;
2513 table = iptr->dst.table;
2515 l = iptr->sx.s23.s2.tablelow;
2516 i = iptr->sx.s23.s3.tablehigh;
2518 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2519 M_INTMOVE(s1, REG_ITMP1);
2523 } else if (N_VALID_IMM(-l)) {
2524 M_ISUB_IMM(l, REG_ITMP1);
2526 ICONST(REG_ITMP2, l);
2527 M_ISUB(REG_ITMP2, REG_ITMP1);
2530 /* number of targets */
2536 ICONST(REG_ITMP2, i);
2537 M_ICMPU(REG_ITMP1, REG_ITMP2);
2538 emit_bge(cd, table[0].block);
2540 /* build jump table top down and use address of lowest entry */
2545 dseg_add_target(cd, table->block);
2550 /* length of dataseg after last dseg_add_target is used by load */
2552 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2553 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2554 N_L(REG_ITMP1, 0, REG_ITMP1, REG_PV);
2555 M_JMP(RN, REG_ITMP1);
2560 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2563 lookup_target_t *lookup;
2565 lookup = iptr->dst.lookup;
2567 i = iptr->sx.s23.s2.lookupcount;
2569 MCODECHECK(8 + ((7 + 6) * i) + 5);
2570 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2573 if (N_VALID_IMM(lookup->value)) {
2574 M_ICMP_IMM(s1, lookup->value);
2576 ICONST(REG_ITMP2, lookup->value);
2577 M_ICMP(REG_ITMP2, s1);
2579 emit_beq(cd, lookup->target.block);
2583 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2588 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2590 bte = iptr->sx.s23.s3.bte;
2594 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2595 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2596 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2597 case ICMD_INVOKEINTERFACE:
2599 REPLACEMENT_POINT_INVOKE(cd, iptr);
2601 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2603 um = iptr->sx.s23.s3.um;
2604 md = um->methodref->parseddesc.md;
2607 lm = iptr->sx.s23.s3.fmiref->p.method;
2609 md = lm->parseddesc;
2613 s3 = md->paramcount;
2615 MCODECHECK((s3 << 1) + 64);
2617 /* copy arguments to registers or stack location */
2619 for (s3 = s3 - 1; s3 >= 0; s3--) {
2620 var = VAR(iptr->sx.s23.s2.args[s3]);
2622 /* Already Preallocated? */
2623 if (var->flags & PREALLOC)
2626 if (IS_INT_LNG_TYPE(var->type)) {
2627 if (!md->params[s3].inmemory) {
2628 if (IS_2_WORD_TYPE(var->type)) {
2630 GET_LOW_REG(md->params[s3].regoff),
2631 GET_HIGH_REG(md->params[s3].regoff)
2633 d = emit_load(jd, iptr, var, s1);
2637 s1 = md->params[s3].regoff;
2638 d = emit_load(jd, iptr, var, s1);
2643 if (IS_2_WORD_TYPE(var->type)) {
2644 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2645 M_LST(d, REG_SP, md->params[s3].regoff * 4);
2648 d = emit_load(jd, iptr, var, REG_ITMP1);
2649 M_IST(d, REG_SP, md->params[s3].regoff * 4);
2654 if (!md->params[s3].inmemory) {
2655 s1 = md->params[s3].regoff;
2656 d = emit_load(jd, iptr, var, s1);
2660 d = emit_load(jd, iptr, var, REG_FTMP1);
2661 if (IS_2_WORD_TYPE(var->type))
2662 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2664 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2669 switch (iptr->opc) {
2671 disp = dseg_add_functionptr(cd, bte->fp);
2673 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2674 N_LHI(REG_ITMP1, disp);
2675 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2678 case ICMD_INVOKESPECIAL:
2680 /* Implicit NULL pointer check */
2681 M_ILD(REG_ITMP1, REG_A0, 0);
2685 case ICMD_INVOKESTATIC:
2687 disp = dseg_add_unique_address(cd, um);
2689 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2693 disp = dseg_add_address(cd, lm->stubroutine);
2695 N_LHI(REG_ITMP1, disp);
2696 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2699 case ICMD_INVOKEVIRTUAL:
2700 /* TODO softnull REG_A0 */
2703 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2708 s1 = OFFSET(vftbl_t, table[0]) +
2709 sizeof(methodptr) * lm->vftblindex;
2712 /* implicit null-pointer check */
2714 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2715 M_ALD(REG_PV, REG_METHODPTR, s1);
2718 case ICMD_INVOKEINTERFACE:
2719 /* TODO softnull REG_A0 */
2721 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2722 * and -0xFFF in index register (itmp1)
2725 N_LHI(REG_ITMP1, -N_DISP_MAX);
2728 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2734 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2735 sizeof(methodptr*) * lm->class->index +
2738 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2741 /* Implicit null-pointer check */
2742 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2743 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
2744 M_ALD(REG_PV, REG_METHODPTR, s2);
2748 /* generate the actual call */
2751 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2752 emit_restore_pv(cd);
2754 /* post call finalization */
2756 switch (iptr->opc) {
2758 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2759 emit_exception_check(cd, iptr); /* check for exception */
2763 /* store return value */
2765 d = md->returntype.type;
2767 if (d != TYPE_VOID) {
2768 if (IS_INT_LNG_TYPE(d)) {
2769 if (IS_2_WORD_TYPE(d)) {
2770 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2771 M_LNGMOVE(REG_RESULT_PACKED, s1);
2774 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2775 M_INTMOVE(REG_RESULT, s1);
2779 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2780 M_FLTMOVE(REG_FRESULT, s1);
2782 emit_store_dst(jd, iptr, s1);
2788 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2790 /* val.a: (classinfo*) superclass */
2792 /* superclass is an interface:
2794 * OK if ((sub == NULL) ||
2795 * (sub->vftbl->interfacetablelength > super->index) &&
2796 * (sub->vftbl->interfacetable[-super->index] != NULL));
2798 * superclass is a class:
2800 * OK if ((sub == NULL) || (0
2801 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2802 * super->vftbl->diffval));
2805 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2806 /* object type cast-check */
2809 vftbl_t *supervftbl;
2812 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2813 # define LABEL_CLASS BRANCH_LABEL_2
2814 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2815 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2816 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2818 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2824 super = iptr->sx.s23.s3.c.cls;
2825 superindex = super->index;
2826 supervftbl = super->vftbl;
2829 #if defined(ENABLE_THREADS)
2830 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2832 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2834 /* if class is not resolved, check which code to call */
2836 if (super == NULL) {
2838 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2840 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2842 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
2843 iptr->sx.s23.s3.c.ref,
2846 ICONST(REG_ITMP2, ACC_INTERFACE);
2847 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
2848 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
2849 emit_label_beq(cd, LABEL_CLASS);
2852 /* interface checkcast code */
2854 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2855 if (super == NULL) {
2856 codegen_add_patch_ref(cd,
2857 PATCHER_checkcast_instanceof_interface,
2858 iptr->sx.s23.s3.c.ref,
2862 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
2865 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2866 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2867 M_ISUB_IMM(superindex, REG_ITMP3);
2868 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
2871 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2872 superindex * sizeof(methodptr*))
2874 M_ALD(REG_ITMP2, REG_ITMP2, 0);
2875 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
2877 if (super == NULL) {
2878 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
2882 /* class checkcast code */
2884 if (super == NULL) {
2885 emit_label(cd, LABEL_CLASS);
2888 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2889 if (super == NULL) {
2890 disp = dseg_add_unique_address(cd, NULL);
2892 codegen_add_patch_ref(cd,
2893 PATCHER_resolve_classref_to_vftbl,
2894 iptr->sx.s23.s3.c.ref,
2898 disp = dseg_add_address(cd, supervftbl);
2900 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
2903 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2904 M_ALD(REG_ITMP3, REG_PV, disp);
2905 #if defined(ENABLE_THREADS)
2906 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
2908 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2909 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2910 M_ISUB(REG_ITMP3, REG_ITMP2);
2911 M_ALD(REG_ITMP3, REG_PV, disp);
2912 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2913 #if defined(ENABLE_THREADS)
2914 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
2916 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
2917 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
2918 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
2919 /* Branch if greater then */
2920 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
2923 if (super == NULL) {
2924 emit_label(cd, LABEL_EXIT_CHECK_NULL);
2925 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
2926 } else if (super->flags & ACC_INTERFACE) {
2927 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
2929 emit_label(cd, LABEL_EXIT_CLASS_NULL);
2932 d = codegen_reg_of_dst(jd, iptr, s1);
2934 # undef LABEL_EXIT_CHECK_NULL
2936 # undef LABEL_EXIT_INTERFACE_NULL
2937 # undef LABEL_EXIT_INTERFACE_DONE
2938 # undef LABEL_EXIT_CLASS_NULL
2941 /* array type cast-check */
2943 s1 = emit_load_s1(jd, iptr, REG_A0);
2944 M_INTMOVE(s1, REG_A0);
2946 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2947 disp = dseg_add_unique_address(cd, NULL);
2949 codegen_add_patch_ref(cd,
2950 PATCHER_resolve_classref_to_classinfo,
2951 iptr->sx.s23.s3.c.ref,
2955 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2957 M_ALD(REG_A1, REG_PV, disp);
2958 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2959 M_ALD(REG_ITMP1, REG_PV, disp);
2960 M_ASUB_IMM(96, REG_SP);
2961 M_JSR(REG_RA, REG_ITMP1);
2962 M_AADD_IMM(96, REG_SP);
2964 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2965 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
2967 d = codegen_reg_of_dst(jd, iptr, s1);
2971 emit_store_dst(jd, iptr, d);
2974 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2975 /* val.a: (classinfo*) superclass */
2977 /* superclass is an interface:
2979 * return (sub != NULL) &&
2980 * (sub->vftbl->interfacetablelength > super->index) &&
2981 * (sub->vftbl->interfacetable[-super->index] != NULL);
2983 * superclass is a class:
2985 * return ((sub != NULL) && (0
2986 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2987 * super->vftbl->diffvall));
2989 * If superclass is unresolved, we include both code snippets
2990 * above, a patcher resolves the class' flags and we select
2991 * the right code at runtime.
2996 vftbl_t *supervftbl;
2999 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3005 super = iptr->sx.s23.s3.c.cls;
3006 superindex = super->index;
3007 supervftbl = super->vftbl;
3010 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3011 # define LABEL_CLASS BRANCH_LABEL_2
3012 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3013 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3014 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3015 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3017 #if defined(ENABLE_THREADS)
3018 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3020 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3021 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3023 M_MOV(s1, REG_ITMP1);
3027 /* if class is not resolved, check which code to call */
3029 if (super == NULL) {
3033 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3035 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3037 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3038 iptr->sx.s23.s3.c.ref, disp);
3040 ICONST(REG_ITMP2, ACC_INTERFACE);
3041 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3042 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3043 emit_label_beq(cd, LABEL_CLASS);
3046 /* interface instanceof code */
3048 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3049 if (super == NULL) {
3050 /* If d == REG_ITMP2, then it's destroyed in check
3055 codegen_add_patch_ref(cd,
3056 PATCHER_checkcast_instanceof_interface,
3057 iptr->sx.s23.s3.c.ref, 0);
3062 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3065 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3066 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3067 M_ISUB_IMM(superindex, REG_ITMP3);
3069 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3073 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3074 superindex * sizeof(methodptr*))
3076 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3078 /* d := (REG_ITMP1 != 0) */
3080 N_LTR(d, REG_ITMP1);
3081 M_BEQ(SZ_BRC + SZ_LHI);
3084 if (super == NULL) {
3085 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3089 /* class instanceof code */
3091 if (super == NULL) {
3092 emit_label(cd, LABEL_CLASS);
3095 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3096 if (super == NULL) {
3097 disp = dseg_add_unique_address(cd, NULL);
3099 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3100 iptr->sx.s23.s3.c.ref,
3104 disp = dseg_add_address(cd, supervftbl);
3109 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3112 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3113 M_ALD(REG_ITMP2, REG_PV, disp);
3114 #if defined(ENABLE_THREADS)
3115 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3117 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3118 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3119 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3120 #if defined(ENABLE_THREADS)
3121 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3123 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3125 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3127 M_BGT(SZ_BRC + SZ_LHI);
3131 if (super == NULL) {
3132 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3133 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3134 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3135 } else if (super->flags & ACC_INTERFACE) {
3136 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3137 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3139 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3142 # undef LABEL_EXIT_CHECK_NULL
3144 # undef LABEL_EXIT_INTERFACE_NULL
3145 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3146 # undef LABEL_EXIT_INTERFACE_DONE
3147 # undef LABEL_EXIT_CLASS_NULL
3149 emit_store_dst(jd, iptr, d);
3155 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3157 /* check for negative sizes and copy sizes to stack if necessary */
3159 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3162 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3164 /* copy SAVEDVAR sizes to stack */
3165 var = VAR(iptr->sx.s23.s2.args[s1]);
3167 /* Already Preallocated? */
3168 if (!(var->flags & PREALLOC)) {
3169 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3170 M_IST(s2, REG_SP, s1 * 4);
3174 /* is a patcher function set? */
3176 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3177 disp = dseg_add_unique_address(cd, 0);
3179 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
3180 iptr->sx.s23.s3.c.ref,
3184 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3186 /* a0 = dimension count */
3188 ICONST(REG_A0, iptr->s1.argcount);
3190 /* a1 = classinfo */
3192 M_ALD(REG_A1, REG_PV, disp);
3194 /* a2 = pointer to dimensions = stack pointer */
3196 M_MOV(REG_SP, REG_A2);
3198 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3199 M_ALD(REG_ITMP1, REG_PV, disp);
3200 M_ASUB_IMM(96, REG_SP);
3201 M_JSR(REG_RA, REG_ITMP1);
3202 M_AADD_IMM(96, REG_SP);
3204 /* check for exception before result assignment */
3206 emit_exception_check(cd, iptr);
3208 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3209 M_INTMOVE(REG_RESULT, s1);
3210 emit_store_dst(jd, iptr, s1);
3215 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3219 } /* for instruction */
3221 MCODECHECK(512); /* XXX require a lower number? */
3223 /* At the end of a basic block we may have to append some nops,
3224 because the patcher stub calling code might be longer than the
3225 actual instruction. So codepatching does not change the
3226 following block unintentionally. */
3228 if (cd->mcodeptr < cd->lastmcodeptr) {
3229 while (cd->mcodeptr < cd->lastmcodeptr) {
3234 } /* if (bptr -> flags >= BBREACHED) */
3235 } /* for basic block */
3237 dseg_createlinenumbertable(cd);
3239 /* generate stubs */
3241 emit_patcher_stubs(jd);
3243 emit_replacement_stubs(jd);
3246 /* everything's ok */
3252 /* codegen_emit_stub_compiler **************************************************
3254 Emits a stub routine which calls the compiler.
3256 *******************************************************************************/
3258 void codegen_emit_stub_compiler(jitdata *jd)
3263 /* get required compiler data */
3268 /* code for the stub */
3270 /* don't touch ITMP3 as it cointains the return address */
3272 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3274 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3275 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3276 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3281 /* codegen_emit_stub_native ****************************************************
3283 Emits a stub routine which calls a native method.
3285 *******************************************************************************/
3288 arguments on stack \
3289 -------------------------------------------------| <- SP on nativestub entry
3291 callee saved int regs (none) |
3292 callee saved float regs (none) | stack frame like in cacao
3293 local variable slots (none) |
3294 arguments for calling methods (none) /
3295 ------------------------------------------------------------------ <- datasp
3300 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3301 0 - 96 register save area for callee /
3302 -------------------------------------------------------- <- SP native method
3304 SP after method entry
3307 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3315 s4 i, j; /* count variables */
3320 /* get required compiler data */
3327 /* initialize variables */
3330 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3332 /* calculate stack frame size */
3334 cd->stackframesize =
3335 1 + /* r14 - return address */ +
3336 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3337 sizeof(localref_table) / SIZEOF_VOID_P +
3339 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3340 nmd->memuse + /* parameter passing */
3341 96 / SIZEOF_VOID_P /* required by ABI */;
3343 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3346 /* create method header */
3348 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3349 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3350 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3351 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3352 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3353 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3354 (void) dseg_addlinenumbertablesize(cd);
3355 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3357 /* generate native method profiling code */
3359 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3360 /* count frequency */
3362 M_MOV_IMM(code, REG_ITMP3);
3363 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3367 /* generate stub code */
3369 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3371 /* save return address */
3373 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3375 #if !defined(NDEBUG)
3376 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3377 emit_verbosecall_enter(jd);
3380 /* get function address (this must happen before the stackframeinfo) */
3382 disp = dseg_add_functionptr(cd, f);
3384 #if !defined(WITH_STATIC_CLASSPATH)
3386 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3389 M_ILD(REG_ITMP1, REG_PV, disp);
3391 j = 96 + (nmd->memuse * 4);
3393 /* todo some arg registers are not volatile in C-abi terms */
3395 /* save integer and float argument registers */
3397 for (i = 0; i < md->paramcount; i++) {
3398 if (! md->params[i].inmemory) {
3399 s1 = md->params[i].regoff;
3400 t = md->paramtypes[i].type;
3402 if (IS_INT_LNG_TYPE(t)) {
3403 if (IS_2_WORD_TYPE(t)) {
3404 /* todo store multiple */
3405 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3406 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3408 N_ST(s1, j, RN, REG_SP);
3411 if (IS_2_WORD_TYPE(t)) {
3412 N_STD(s1, j, RN, REG_SP);
3414 N_STE(s1, j, RN, REG_SP);
3422 N_ST(REG_ITMP1, j, RN, REG_SP);
3424 /* create dynamic stack info */
3426 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3427 N_LR(REG_A1, REG_PV); /* pv */
3428 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3429 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3431 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3432 M_ILD(REG_ITMP1, REG_PV, disp);
3434 M_CALL(REG_ITMP1); /* call */
3436 /* restore integer and float argument registers */
3438 j = 96 + (nmd->memuse * 4);
3440 for (i = 0; i < md->paramcount; i++) {
3441 if (! md->params[i].inmemory) {
3442 s1 = md->params[i].regoff;
3443 t = md->paramtypes[i].type;
3445 if (IS_INT_LNG_TYPE(t)) {
3446 if (IS_2_WORD_TYPE(t)) {
3447 /* todo load multiple ! */
3448 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3449 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3451 N_L(s1, j, RN, REG_SP);
3454 if (IS_2_WORD_TYPE(t)) {
3455 N_LD(s1, j, RN, REG_SP);
3457 N_LE(s1, j, RN, REG_SP);
3465 N_L(REG_ITMP1, j, RN, REG_SP);
3467 /* copy or spill arguments to new locations */
3469 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3470 t = md->paramtypes[i].type;
3472 if (IS_INT_LNG_TYPE(t)) {
3474 if (!md->params[i].inmemory) {
3476 s1 = md->params[i].regoff;
3478 if (!nmd->params[j].inmemory) {
3479 s2 = nmd->params[j].regoff;
3480 if (IS_2_WORD_TYPE(t)) {
3496 s2 = nmd->params[j].regoff;
3497 if (IS_2_WORD_TYPE(t)) {
3501 96 + (s2 * 4), REG_SP
3506 96 + (s2 * 4), RN, REG_SP
3512 s1 = cd->stackframesize + md->params[i].regoff;
3513 s2 = nmd->params[j].regoff;
3515 if (IS_2_WORD_TYPE(t)) {
3516 N_MVC(96 + (s2 * 4), 8, REG_SP, (s1 * 4), REG_SP);
3518 N_MVC(96 + (s2 * 4), 4, REG_SP, (s1 * 4), REG_SP);
3523 /* We only copy spilled float arguments, as the float argument */
3524 /* registers keep unchanged. */
3526 if (md->params[i].inmemory) {
3527 s1 = cd->stackframesize + md->params[i].regoff;
3528 s2 = nmd->params[j].regoff;
3530 if (IS_2_WORD_TYPE(t)) {
3531 N_MVC(96 + (s2 * 4), 8, REG_SP, (s1 * 4), REG_SP);
3533 N_MVC(96 + (s2 * 4), 4, REG_SP, (s1 * 4), REG_SP);
3539 /* put class into second argument register */
3541 if (m->flags & ACC_STATIC) {
3542 disp = dseg_add_address(cd, m->class);
3543 M_ILD(REG_A1, REG_PV, disp);
3546 /* put env into first argument register */
3548 disp = dseg_add_address(cd, _Jv_env);
3549 M_ILD(REG_A0, REG_PV, disp);
3551 /* do the native function call */
3553 M_CALL(REG_ITMP1); /* call */
3555 /* save return value */
3557 t = md->returntype.type;
3559 if (t != TYPE_VOID) {
3560 if (IS_INT_LNG_TYPE(t)) {
3561 if (IS_2_WORD_TYPE(t)) {
3562 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3564 N_ST(REG_RESULT, 96, RN, REG_SP);
3567 if (IS_2_WORD_TYPE(t)) {
3568 N_STD(REG_FRESULT, 96, RN, REG_SP);
3570 N_STE(REG_FRESULT, 96, RN, REG_SP);
3575 #if !defined(NDEBUG)
3576 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3577 emit_verbosecall_exit(jd);
3580 /* remove native stackframe info */
3582 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3583 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3584 M_ILD(REG_ITMP1, REG_PV, disp);
3586 N_LR(REG_ITMP3, REG_RESULT);
3588 /* restore return value */
3590 if (t != TYPE_VOID) {
3591 if (IS_INT_LNG_TYPE(t)) {
3592 if (IS_2_WORD_TYPE(t)) {
3593 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3595 N_L(REG_RESULT, 96, RN, REG_SP);
3598 if (IS_2_WORD_TYPE(t)) {
3599 N_LD(REG_FRESULT, 96, RN, REG_SP);
3601 N_LE(REG_FRESULT, 96, RN, REG_SP);
3606 /* load return address */
3608 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3610 /* remove stackframe */
3612 N_AHI(REG_SP, cd->stackframesize * 4);
3614 /* test for exception */
3616 N_LTR(REG_ITMP3, REG_ITMP3);
3617 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3621 N_BCR(DD_ANY, REG_ITMP2);
3623 /* handle exception */
3625 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3626 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3630 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3633 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3634 M_ALD(REG_ITMP3, REG_PV, disp);
3635 M_JMP(RN, REG_ITMP3);
3637 /* generate patcher stubs */
3639 emit_patcher_stubs(jd);
3642 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3643 codegendata *cd = jd->cd;
3644 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3646 M_MOV(reg, tempregnum);
3654 * These are local overrides for various environment variables in Emacs.
3655 * Please do not remove this and leave it at the end of the file, where
3656 * Emacs will automagically detect them.
3657 * ---------------------------------------------------------------------
3660 * indent-tabs-mode: t
3664 * vim:noexpandtab:sw=4:ts=4: