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 8240 2007-07-29 20:36:47Z 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);
78 #define SUPPORT_HERCULES 1
82 /* codegen *********************************************************************
84 Generates machine code.
86 *******************************************************************************/
89 bool codegen_emit(jitdata *jd)
95 s4 len, s1, s2, s3, d, dd, disp;
98 varinfo *var, *var1, *var2, *dst;
102 constant_classref *cr;
103 unresolved_class *uc;
104 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
105 unresolved_method *um;
106 builtintable_entry *bte;
109 unresolved_field *uf;
112 rplpoint *replacementpoint;
116 /* get required compiler data */
123 /* prevent compiler warnings */
136 /* space to save used callee saved registers */
138 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
139 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
141 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
144 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
147 #if defined(ENABLE_THREADS)
148 /* Space to save argument of monitor_enter and Return Values to
149 survive monitor_exit. The stack position for the argument can
150 not be shared with place to save the return register
151 since both values reside in R2. */
153 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
154 /* reserve 2 slots for long/double return values for monitorexit */
156 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
157 cd->stackframesize += 3;
159 cd->stackframesize += 2;
163 /* Keep stack of non-leaf functions 16-byte aligned for calls into
164 native code e.g. libc or jni (alignment problems with
167 if (!jd->isleafmethod || opt_verbosecall )
168 /* TODO really 16 bytes ? */
169 cd->stackframesize = (cd->stackframesize + 3) & ~3;
171 /* create method header */
173 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
174 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
176 #if defined(ENABLE_THREADS)
177 /* IsSync contains the offset relative to the stack pointer for the
178 argument of monitor_exit used in the exception handler. Since the
179 offset could be zero and give a wrong meaning of the flag it is
183 if (checksync && (m->flags & ACC_SYNCHRONIZED))
184 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
188 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
190 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
191 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
192 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
194 (void) dseg_addlinenumbertablesize(cd);
196 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
198 /* create exception table */
200 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
201 dseg_add_target(cd, ex->start);
202 dseg_add_target(cd, ex->end);
203 dseg_add_target(cd, ex->handler);
204 (void) dseg_add_unique_address(cd, ex->catchtype.any);
209 M_AADD_IMM(N_PV_OFFSET, REG_PV);
211 /* generate method profiling code */
213 #if defined(ENABLE_PROFILING)
214 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
215 /* count frequency */
216 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
217 ICONST(REG_ITMP2, 1);
218 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
219 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
225 /* create stack frame (if necessary) */
227 if (cd->stackframesize)
228 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
230 /* save used callee saved registers and return address */
232 p = cd->stackframesize;
233 p--; M_AST(REG_RA, REG_SP, p * 4);
235 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
236 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
238 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
239 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
242 /* take arguments out of register or stack frame */
246 for (p = 0, l = 0; p < md->paramcount; p++) {
247 t = md->paramtypes[p].type;
248 varindex = jd->local_map[l * 5 + t];
251 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
254 if (varindex == UNUSED)
259 s1 = md->params[p].regoff;
260 if (IS_INT_LNG_TYPE(t)) { /* integer args */
261 if (IS_2_WORD_TYPE(t)) {
269 if (!md->params[p].inmemory) { /* register arguments */
270 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
271 if (IS_2_WORD_TYPE(t))
272 M_LNGMOVE(s2, var->vv.regoff);
274 M_INTMOVE(s2, var->vv.regoff);
276 } else { /* reg arg -> spilled */
277 if (IS_2_WORD_TYPE(t))
278 M_LST(s2, REG_SP, var->vv.regoff);
280 M_IST(s2, REG_SP, var->vv.regoff);
283 } else { /* stack arguments */
284 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
285 if (IS_2_WORD_TYPE(t))
286 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
288 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
290 } else { /* stack arg -> spilled */
291 if (IS_2_WORD_TYPE(t)) {
292 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
294 N_MVC(var->vv.regoff, 4, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
299 } else { /* floating args */
300 if (!md->params[p].inmemory) { /* register arguments */
302 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
303 M_FLTMOVE(s2, var->vv.regoff);
305 } else { /* reg arg -> spilled */
306 if (IS_2_WORD_TYPE(t))
307 M_DST(s2, REG_SP, var->vv.regoff);
309 M_FST(s2, REG_SP, var->vv.regoff);
312 } else { /* stack arguments */
313 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
314 if (IS_2_WORD_TYPE(t))
315 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
318 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
320 } else { /* stack-arg -> spilled */
321 if (IS_2_WORD_TYPE(t)) {
322 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
323 var->vv.regoff = cd->stackframesize * 4 + s1;
326 N_MVC(var->vv.regoff, 4, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
333 /* save monitorenter argument */
335 #if defined(ENABLE_THREADS)
336 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
337 /* stack offset for monitor argument */
342 if (opt_verbosecall) {
343 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
345 for (p = 0; p < INT_ARG_CNT; p++)
346 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
348 for (p = 0; p < FLT_ARG_CNT; p++)
349 M_FST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
351 s1 += ((INT_ARG_CNT + FLT_ARG_CNT) * 2);
355 /* decide which monitor enter function to call */
357 if (m->flags & ACC_STATIC) {
358 disp = dseg_add_address(cd, &m->class->object.header);
359 M_ALD_DSEG(REG_A0, disp);
363 M_BNE(SZ_BRC + SZ_ILL);
364 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
367 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
368 M_ALD_DSEG(REG_ITMP3, disp);
370 M_AST(REG_A0, REG_SP, s1 * 4);
372 M_ASUB_IMM(96, REG_SP);
374 M_AADD_IMM(96, REG_SP);
377 if (opt_verbosecall) {
378 for (p = 0; p < INT_ARG_CNT; p++)
379 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
381 for (p = 0; p < FLT_ARG_CNT; p++)
382 M_FLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
384 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
391 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
392 emit_verbosecall_enter(jd);
393 #endif /* !defined(NDEBUG) */
397 /* end of header generation */
399 /* create replacement points */
401 REPLACEMENT_POINTS_INIT(cd, jd);
403 /* walk through all basic blocks */
405 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
407 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
409 if (bptr->flags >= BBREACHED) {
411 /* branch resolving */
413 codegen_resolve_branchrefs(cd, bptr);
415 /* handle replacement points */
417 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
419 /* copy interface registers to their destination */
424 #if defined(ENABLE_PROFILING)
425 /* generate basicblock profiling code */
427 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
428 /* count frequency */
430 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
431 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
432 ICONST(REG_ITMP2, 1);
433 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
434 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
436 /* if this is an exception handler, start profiling again */
438 if (bptr->type == BBTYPE_EXH)
443 #if defined(ENABLE_LSRA)
447 src = bptr->invars[len];
448 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
449 if (bptr->type == BBTYPE_EXH) {
450 /* d = reg_of_var(rd, src, REG_ITMP1); */
451 if (!IS_INMEMORY(src->flags))
455 M_INTMOVE(REG_ITMP1, d);
456 emit_store(jd, NULL, src, d);
466 var = VAR(bptr->invars[len]);
467 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
468 if (bptr->type == BBTYPE_EXH) {
469 d = codegen_reg_of_var(0, var, REG_ITMP1);
470 M_INTMOVE(REG_ITMP1, d);
471 emit_store(jd, NULL, var, d);
475 assert((var->flags & INOUT));
478 #if defined(ENABLE_LSRA)
481 /* walk through all instructions */
486 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
487 if (iptr->line != currentline) {
488 dseg_addlinenumber(cd, iptr->line);
489 currentline = iptr->line;
492 MCODECHECK(1024); /* 1KB should be enough */
495 case ICMD_NOP: /* ... ==> ... */
496 case ICMD_POP: /* ..., value ==> ... */
497 case ICMD_POP2: /* ..., value, value ==> ... */
500 case ICMD_INLINE_START:
502 REPLACEMENT_POINT_INLINE_START(cd, iptr);
505 case ICMD_INLINE_BODY:
507 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
508 dseg_addlinenumber_inline_start(cd, iptr);
509 dseg_addlinenumber(cd, iptr->line);
512 case ICMD_INLINE_END:
514 dseg_addlinenumber_inline_end(cd, iptr);
515 dseg_addlinenumber(cd, iptr->line);
518 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
519 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
520 emit_nullpointer_check(cd, iptr, s1);
523 /* constant operations ************************************************/
525 case ICMD_ICONST: /* ... ==> ..., constant */
526 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
527 ICONST(d, iptr->sx.val.i);
528 emit_store_dst(jd, iptr, d);
531 case ICMD_LCONST: /* ... ==> ..., constant */
533 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
534 LCONST(d, iptr->sx.val.l);
535 emit_store_dst(jd, iptr, d);
538 case ICMD_FCONST: /* ... ==> ..., constant */
539 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
540 disp = dseg_add_float(cd, iptr->sx.val.f);
541 M_FLD_DSEG(d, disp, REG_ITMP1);
542 emit_store_dst(jd, iptr, d);
545 case ICMD_DCONST: /* ... ==> ..., constant */
546 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
547 disp = dseg_add_double(cd, iptr->sx.val.d);
548 M_DLD_DSEG(d, disp, REG_ITMP1);
549 emit_store_dst(jd, iptr, d);
552 case ICMD_ACONST: /* ... ==> ..., constant */
553 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
555 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
556 cr = iptr->sx.val.c.ref;
557 disp = dseg_add_unique_address(cd, cr);
559 /* PROFILE_CYCLE_STOP; */
561 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
564 /* PROFILE_CYCLE_START; */
568 if (iptr->sx.val.anyptr == 0) {
571 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
575 emit_store_dst(jd, iptr, d);
579 /* load/store/copy/move operations ************************************/
581 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
582 case ICMD_ALOAD: /* s1 = local variable */
586 case ICMD_ISTORE: /* ..., value ==> ... */
597 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
601 /* integer operations *************************************************/
603 case ICMD_INEG: /* ..., value ==> ..., - value */
605 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
606 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
608 emit_store_dst(jd, iptr, d);
612 case ICMD_LNEG: /* ..., value ==> ..., - value */
614 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
615 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
616 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
617 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
618 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
619 N_AHI(GET_HIGH_REG(d), -1);
620 emit_store_dst(jd, iptr, d);
623 case ICMD_I2L: /* ..., value ==> ..., value */
625 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
626 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
628 M_INTMOVE(s1, GET_HIGH_REG(d));
629 ICONST(GET_LOW_REG(d), 0);
630 M_SRDA_IMM(32, GET_HIGH_REG(d));
632 emit_copy_dst(jd, iptr, d);
633 emit_store_dst(jd, iptr, d);
634 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
638 case ICMD_L2I: /* ..., value ==> ..., value */
639 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
640 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
641 M_INTMOVE(GET_LOW_REG(s1), d);
642 emit_store_dst(jd, iptr, d);
645 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
646 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
647 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
651 emit_store_dst(jd, iptr, d);
654 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
655 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
656 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
660 emit_store_dst(jd, iptr, d);
663 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
665 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
666 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
670 emit_store_dst(jd, iptr, d);
673 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
675 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
676 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
677 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
684 emit_store_dst(jd, iptr, d);
689 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
690 /* sx.val.i = constant */
691 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
692 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
695 if (N_VALID_IMM(iptr->sx.val.i)) {
696 M_IADD_IMM(iptr->sx.val.i, d);
698 ICONST(REG_ITMP2, iptr->sx.val.i);
699 M_IADD(REG_ITMP2, d);
701 emit_store_dst(jd, iptr, d);
704 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
706 /* M, (r, q) -> (r, q) */
708 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
710 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
711 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
712 dd = GET_HIGH_REG(d);
721 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
722 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
732 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
733 N_AHI(GET_HIGH_REG(d), 1);
735 emit_store_dst(jd, iptr, d);
738 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
739 /* sx.val.l = constant */
741 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
742 dd = GET_HIGH_REG(d);
744 s1 = emit_load_s1_high(jd, iptr, dd);
745 s3 = iptr->sx.val.l >> 32;
749 if (N_VALID_IMM(s3)) {
752 ICONST(REG_ITMP3, s3);
753 M_IADD(REG_ITMP3, dd);
757 s1 = emit_load_s1_low(jd, iptr, dd);
758 s3 = iptr->sx.val.l & 0xffffffff;
759 ICONST(REG_ITMP3, s3);
762 N_ALR(dd, REG_ITMP3);
764 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
765 N_AHI(GET_HIGH_REG(d), 1);
767 emit_store_dst(jd, iptr, d);
770 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
772 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
773 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
774 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
776 M_INTMOVE(s1, REG_ITMP1);
777 M_ISUB(s2, REG_ITMP1);
778 M_INTMOVE(REG_ITMP1, d);
783 emit_store_dst(jd, iptr, d);
787 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
788 /* sx.val.i = constant */
790 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
791 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
794 if (N_VALID_IMM(-iptr->sx.val.i)) {
795 M_ISUB_IMM(iptr->sx.val.i, d);
797 ICONST(REG_ITMP2, iptr->sx.val.i);
798 M_ISUB(REG_ITMP2, d);
800 emit_store_dst(jd, iptr, d);
804 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
806 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
808 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
809 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
810 dd = GET_HIGH_REG(d);
813 M_INTMOVE(s2, REG_ITMP3);
820 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
821 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
825 M_INTMOVE(s2, REG_ITMP3);
832 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
833 N_AHI(GET_HIGH_REG(d), -1);
835 emit_store_dst(jd, iptr, d);
838 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
839 /* sx.val.l = constant */
841 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
843 dd = GET_HIGH_REG(d);
844 s1 = emit_load_s1_high(jd, iptr, dd);
845 s3 = iptr->sx.val.l >> 32;
849 if (N_VALID_IMM(-s3)) {
852 ICONST(REG_ITMP3, s3);
853 M_ISUB(REG_ITMP3, dd);
857 s1 = emit_load_s1_low(jd, iptr, dd);
858 s3 = iptr->sx.val.l & 0xffffffff;
859 ICONST(REG_ITMP3, s3);
862 N_SLR(dd, REG_ITMP3);
864 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
865 N_AHI(GET_HIGH_REG(d), -1);
867 emit_store_dst(jd, iptr, d);
870 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
872 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
873 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
874 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
881 emit_store_dst(jd, iptr, d);
885 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
886 /* sx.val.i = constant */
887 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
888 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
890 if (iptr->sx.val.i == 2) {
892 } else if (N_VALID_IMM(iptr->sx.val.i)) {
893 M_IMUL_IMM(iptr->sx.val.i, d);
895 disp = dseg_add_s4(cd, iptr->sx.val.i);
896 M_ILD_DSEG(REG_ITMP2, disp);
897 M_IMUL(REG_ITMP2, d);
899 emit_store_dst(jd, iptr, d);
902 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
903 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
905 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
906 emit_arithmetic_check(cd, iptr, s2);
908 /* For this operation we need a register pair.
909 * We will use r0 and itmp1 and will backup r0.
912 M_INTMOVE(R0, REG_ITMP3);
914 /* We won't check for division by 0, we catch a SIGFPE instead
915 * Special case 0x80000000 / 0xffffffff handled by signal handler too.
918 s1 = emit_load_s1(jd, iptr, R0);
927 d = codegen_reg_of_dst(jd, iptr, R0);
931 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
932 M_INTMOVE(REG_ITMP1, d);
936 emit_store_dst(jd, iptr, d);
938 /* If destionation of operation was not register R0,
942 if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
943 M_INTMOVE(REG_ITMP3, R0);
948 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
949 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
951 bte = iptr->sx.s23.s3.bte;
954 /* test s2 for zero */
956 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
957 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
958 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
959 emit_arithmetic_check(cd, iptr, REG_ITMP3);
963 disp = dseg_add_functionptr(cd, bte->fp);
967 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
969 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
970 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
974 M_ASUB_IMM(96, REG_SP);
975 M_ALD_DSEG(REG_ITMP3, disp);
976 M_JSR(REG_RA, REG_ITMP3);
977 M_AADD_IMM(96, REG_SP);
981 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
982 M_LNGMOVE(REG_RESULT_PACKED, d);
983 emit_store_dst(jd, iptr, d);
987 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
988 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
989 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
991 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
992 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
993 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
995 /* Use only 5 bits of sencond operand. */
997 M_INTMOVE(s2, REG_ITMP2);
999 ICONST(REG_ITMP3, 0x1F);
1000 M_IAND(REG_ITMP3, s2);
1004 switch (iptr->opc) {
1017 emit_store_dst(jd, iptr, d);
1020 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1021 /* sx.val.i = constant */
1025 assert(iptr->sx.val.i <= 32);
1027 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1028 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1035 s3 = (1 << iptr->sx.val.i) - 1;
1037 if (N_VALID_IMM(s3)) {
1040 ICONST(REG_ITMP1, -1);
1041 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1042 M_IADD(REG_ITMP1, d);
1045 N_BRC_BACK_PATCH(ref);
1047 M_SRA_IMM(iptr->sx.val.i, d);
1049 emit_store_dst(jd, iptr, d);
1054 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1055 /* sx.val.i = constant */
1057 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1058 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1061 M_MOV(s1, REG_ITMP1);
1065 ICONST(REG_ITMP3, iptr->sx.val.i);
1068 M_IAND(REG_ITMP3, d);
1071 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1077 emit_store_dst(jd, iptr, d);
1081 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1082 /* sx.val.i = constant */
1083 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1084 /* sx.val.i = constant */
1085 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1086 /* sx.val.i = constant */
1087 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1088 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1092 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1094 switch (iptr->opc) {
1095 case ICMD_ISHLCONST:
1098 case ICMD_ISHRCONST:
1101 case ICMD_IUSHRCONST:
1108 emit_store_dst(jd, iptr, d);
1111 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1113 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1115 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1117 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1119 /* Use only 6 bits of second operand */
1121 M_INTMOVE(s2, REG_ITMP3);
1123 ICONST(REG_ITMP2, 0x3F);
1124 M_IAND(REG_ITMP2, s2);
1126 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1128 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1129 M_INTMOVE(s2, REG_ITMP3);
1133 s1 = emit_load_s1(jd, iptr, d);
1137 switch (iptr->opc) {
1139 M_SLDL(s2, GET_HIGH_REG(d));
1142 M_SRDA(s2, GET_HIGH_REG(d));
1145 M_SRDL(s2, GET_HIGH_REG(d));
1151 emit_copy_dst(jd, iptr, d);
1152 emit_store_dst(jd, iptr, d);
1153 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1157 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1158 /* sx.val.i = constant */
1159 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1160 /* sx.val.i = constant */
1161 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1162 /* sx.val.l = constant */
1165 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1166 s1 = emit_load_s1(jd, iptr, d);
1170 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1172 switch (iptr->opc) {
1173 case ICMD_LSHLCONST:
1174 N_SLDL(GET_HIGH_REG(d), disp, RN);
1176 case ICMD_LSHRCONST:
1177 N_SRDA(GET_HIGH_REG(d), disp, RN);
1179 case ICMD_LUSHRCONST:
1180 N_SRDL(GET_HIGH_REG(d), disp, RN);
1183 N_SLDL(GET_HIGH_REG(d), disp, RN);
1189 emit_copy_dst(jd, iptr, d);
1190 emit_store_dst(jd, iptr, d);
1191 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1195 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1197 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1198 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1199 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1206 emit_store_dst(jd, iptr, d);
1210 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1212 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1213 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1214 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1221 emit_store_dst(jd, iptr, d);
1225 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1227 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1228 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1229 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1236 emit_store_dst(jd, iptr, d);
1242 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1243 /* sx.val.i = constant */
1244 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1245 /* sx.val.i = constant */
1246 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1247 /* sx.val.i = constant */
1249 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1250 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1253 ICONST(REG_ITMP2, iptr->sx.val.i);
1255 switch (iptr->opc) {
1256 case ICMD_IANDCONST:
1257 M_IAND(REG_ITMP2, d);
1259 case ICMD_IXORCONST:
1260 M_IXOR(REG_ITMP2, d);
1263 M_IOR(REG_ITMP2, d);
1269 emit_store_dst(jd, iptr, d);
1273 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1274 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1275 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1277 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1279 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1280 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1281 dd = GET_LOW_REG(d);
1283 switch (iptr->opc) {
1312 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1313 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1314 dd = GET_HIGH_REG(d);
1316 switch (iptr->opc) {
1345 emit_store_dst(jd, iptr, d);
1348 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1349 /* sx.val.l = constant */
1350 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1351 /* sx.val.l = constant */
1352 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1353 /* sx.val.l = constant */
1355 /* TODO should use memory operand to access data segment, not load */
1357 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1359 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1360 s3 = iptr->sx.val.l & 0xffffffff;
1362 M_INTMOVE(s1, GET_LOW_REG(d));
1364 ICONST(REG_ITMP3, s3);
1366 switch (iptr->opc) {
1367 case ICMD_LANDCONST:
1368 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1370 case ICMD_LXORCONST:
1371 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1374 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1380 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1381 s3 = iptr->sx.val.l >> 32;
1383 M_INTMOVE(s1, GET_HIGH_REG(d));
1385 ICONST(REG_ITMP3, s3);
1387 switch (iptr->opc) {
1388 case ICMD_LANDCONST:
1389 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1391 case ICMD_LXORCONST:
1392 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1395 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1401 emit_store_dst(jd, iptr, d);
1405 /* floating operations ************************************************/
1407 case ICMD_FNEG: /* ..., value ==> ..., - value */
1408 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1409 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1411 emit_store_dst(jd, iptr, d);
1414 case ICMD_DNEG: /* ..., value ==> ..., - value */
1415 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1416 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1418 emit_store_dst(jd, iptr, d);
1421 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1422 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1423 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1424 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1431 emit_store_dst(jd, iptr, d);
1434 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1435 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1436 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1437 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1444 emit_store_dst(jd, iptr, d);
1447 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1448 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1449 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1450 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1454 emit_store_dst(jd, iptr, d);
1457 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1458 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1459 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1460 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1464 emit_store_dst(jd, iptr, d);
1467 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1468 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1469 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1470 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1477 emit_store_dst(jd, iptr, d);
1480 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1481 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1482 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1483 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1490 emit_store_dst(jd, iptr, d);
1493 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1494 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1495 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1496 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1500 emit_store_dst(jd, iptr, d);
1503 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1504 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1505 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1506 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1510 emit_store_dst(jd, iptr, d);
1513 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1514 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1515 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1517 emit_store_dst(jd, iptr, d);
1520 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1521 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1522 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1524 emit_store_dst(jd, iptr, d);
1527 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1531 #ifdef SUPPORT_HERCULES
1535 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1536 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1540 switch (iptr->opc) {
1549 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1550 N_LHI(d, 0); /* Load 0 */
1551 ref1 = cd->mcodeptr;
1552 N_BRC(DD_ANY, 0); /* Exit */
1556 switch (iptr->opc) {
1565 #ifdef SUPPORT_HERCULES
1566 /* Hercules does the conversion using a plain C conversion.
1567 * According to manual, real hardware should *NOT* require this.
1569 * Corner case: Positive float leads to INT_MIN (overflow).
1572 switch (iptr->opc) {
1581 ref2 = cd->mcodeptr;
1582 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1586 ref3 = cd->mcodeptr;
1587 M_BGE(0); /* If integer result is negative, continue */
1589 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1590 M_ILD_DSEG(d, disp);
1592 N_BRC_BACK_PATCH(ref1);
1593 #ifdef SUPPORT_HERCULES
1594 N_BRC_BACK_PATCH(ref2);
1595 N_BRC_BACK_PATCH(ref3);
1597 emit_store_dst(jd, iptr, d);
1601 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1604 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1605 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1606 #ifdef SUPPORT_HERCULES
1609 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1610 disp = dseg_add_double(cd, 0.0 / 0.0);
1611 M_DLD_DSEG(d, disp, REG_ITMP1);
1612 emit_label_br(cd, BRANCH_LABEL_1);
1613 N_BRC_BACK_PATCH(ref);
1616 #ifdef SUPPORT_HERCULES
1617 emit_label(cd, BRANCH_LABEL_1);
1619 emit_store_dst(jd, iptr, d);
1623 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1624 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1625 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1627 emit_store_dst(jd, iptr, d);
1630 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1631 /* == => 0, < => 1, > => -1 */
1635 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1636 /* == => 0, < => 1, > => -1 */
1639 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1640 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1641 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1643 switch (iptr->opc) {
1655 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1656 SZ_BRC + SZ_BRC + SZ_BRC
1659 N_BRC( /* load -1 */
1660 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1661 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1666 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1669 N_LHI(d, 1); /* GT */
1670 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1671 N_LHI(d, -1); /* LT */
1672 M_BR(SZ_BRC + SZ_LHI);
1673 N_LHI(d, 0); /* EQ */
1675 emit_store_dst(jd, iptr, d);
1680 /* memory operations **************************************************/
1682 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1684 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1685 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1687 /* implicit null-pointer check */
1688 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1689 emit_store_dst(jd, iptr, d);
1693 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1694 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1695 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1696 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1698 /* implicit null-pointer check */
1699 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1701 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1706 emit_store_dst(jd, iptr, d);
1709 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1711 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1712 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1713 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1715 /* implicit null-pointer check */
1716 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1718 M_INTMOVE(s2, REG_ITMP2);
1719 M_SLL_IMM(1, REG_ITMP2);
1721 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1723 /* N_LH does sign extends, undo ! */
1728 emit_store_dst(jd, iptr, d);
1731 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1732 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1733 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1734 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1736 /* implicit null-pointer check */
1737 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1739 M_INTMOVE(s2, REG_ITMP2);
1740 M_SLL_IMM(1, REG_ITMP2);
1742 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1743 emit_store_dst(jd, iptr, d);
1746 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1747 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1748 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1749 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1751 /* implicit null-pointer check */
1752 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1754 M_INTMOVE(s2, REG_ITMP2);
1755 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1756 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1757 emit_store_dst(jd, iptr, d);
1760 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1762 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1763 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1765 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1767 /* implicit null-pointer check */
1768 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1770 M_INTMOVE(s2, REG_ITMP2);
1771 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1773 /* We need to preserve the array address after the first load */
1775 if (GET_HIGH_REG(d) == s1) {
1776 M_INTMOVE(s1, REG_ITMP3);
1780 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1781 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1782 emit_store_dst(jd, iptr, d);
1786 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1788 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1789 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1790 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1792 /* implicit null-pointer check */
1793 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1795 M_INTMOVE(s2, REG_ITMP2);
1796 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1798 N_LE(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1800 emit_store_dst(jd, iptr, d);
1803 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1804 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1805 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1806 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1808 /* implicit null-pointer check */
1809 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1811 M_INTMOVE(s2, REG_ITMP2);
1812 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1814 N_LD(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1816 emit_store_dst(jd, iptr, d);
1819 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1820 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1821 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1822 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1824 /* implicit null-pointer check */
1825 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1827 M_INTMOVE(s2, REG_ITMP2);
1828 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1829 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1830 emit_store_dst(jd, iptr, d);
1833 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1834 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1835 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1836 /* implicit null-pointer check */
1837 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1838 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1840 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1843 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1845 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1846 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1847 /* implicit null-pointer check */
1848 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1849 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1851 M_INTMOVE(s2, REG_ITMP2);
1852 M_SLL_IMM(1, REG_ITMP2);
1854 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1858 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1859 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1860 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1861 /* implicit null-pointer check */
1862 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1863 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1865 M_INTMOVE(s2, REG_ITMP2);
1866 M_SLL_IMM(1, REG_ITMP2);
1868 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1871 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1873 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1874 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1875 /* implicit null-pointer check */
1876 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1878 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1880 M_INTMOVE(s2, REG_ITMP2);
1881 M_SLL_IMM(2, REG_ITMP2);
1883 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1886 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1888 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1889 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1890 /* implicit null-pointer check */
1891 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1893 M_INTMOVE(s2, REG_ITMP2);
1894 M_SLL_IMM(3, REG_ITMP2);
1896 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1897 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1898 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1899 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1902 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1903 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1904 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1905 /* implicit null-pointer check */
1906 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1907 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1909 M_INTMOVE(s2, REG_ITMP2);
1910 M_SLL_IMM(2, REG_ITMP2);
1912 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1915 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1916 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1917 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1918 /* implicit null-pointer check */
1919 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1920 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1922 M_INTMOVE(s2, REG_ITMP2);
1923 M_SLL_IMM(3, REG_ITMP2);
1925 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1928 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1930 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1931 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1932 /* implicit null-pointer check */
1933 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1934 s3 = emit_load_s3(jd, iptr, REG_A1);
1936 M_INTMOVE(s1, REG_A0);
1937 M_INTMOVE(s3, REG_A1);
1939 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1940 M_ALD_DSEG(REG_ITMP3, disp);
1941 M_ASUB_IMM(96, REG_SP);
1942 M_JSR(REG_RA, REG_ITMP3);
1943 M_AADD_IMM(96, REG_SP);
1945 emit_exception_check(cd, iptr);
1947 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1948 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1949 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1951 M_INTMOVE(s2, REG_ITMP2);
1952 M_SLL_IMM(2, REG_ITMP2);
1953 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1956 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1957 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1962 case ICMD_GETSTATIC: /* ... ==> ..., value */
1964 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1965 uf = iptr->sx.s23.s3.uf;
1966 fieldtype = uf->fieldref->parseddesc.fd->type;
1967 disp = dseg_add_unique_address(cd, NULL);
1969 /* PROFILE_CYCLE_STOP; */
1971 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1973 /* PROFILE_CYCLE_START; */
1976 fi = iptr->sx.s23.s3.fmiref->p.field;
1977 fieldtype = fi->type;
1978 disp = dseg_add_address(cd, &(fi->value));
1980 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1983 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
1985 PROFILE_CYCLE_START;
1989 M_ALD_DSEG(REG_ITMP1, disp);
1991 switch (fieldtype) {
1993 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1994 M_ILD(d, REG_ITMP1, 0);
1997 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1998 M_LLD(d, REG_ITMP1, 0);
2001 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2002 M_ALD(d, REG_ITMP1, 0);
2005 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2006 M_FLD(d, REG_ITMP1, 0);
2009 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2010 M_DLD(d, REG_ITMP1, 0);
2014 emit_store_dst(jd, iptr, d);
2018 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2020 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2021 uf = iptr->sx.s23.s3.uf;
2022 fieldtype = uf->fieldref->parseddesc.fd->type;
2023 disp = dseg_add_unique_address(cd, uf);
2025 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2028 fi = iptr->sx.s23.s3.fmiref->p.field;
2029 fieldtype = fi->type;
2030 disp = dseg_add_address(cd, &(fi->value));
2032 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2034 codegen_addpatchref(cd, PATCHER_clinit, fi->class, disp);
2035 PROFILE_CYCLE_START;
2039 M_ALD_DSEG(REG_ITMP1, disp);
2040 switch (fieldtype) {
2042 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2043 M_IST(s1, REG_ITMP1, 0);
2046 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2047 M_LST(s1, REG_ITMP1, 0);
2050 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2051 M_AST(s1, REG_ITMP1, 0);
2054 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2055 M_FST(s1, REG_ITMP1, 0);
2058 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2059 M_DST(s1, REG_ITMP1, 0);
2064 case ICMD_GETFIELD: /* ... ==> ..., value */
2066 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2067 emit_nullpointer_check(cd, iptr, s1);
2069 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2070 uf = iptr->sx.s23.s3.uf;
2071 fieldtype = uf->fieldref->parseddesc.fd->type;
2074 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2077 fi = iptr->sx.s23.s3.fmiref->p.field;
2078 fieldtype = fi->type;
2082 switch (fieldtype) {
2084 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2088 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2089 if (GET_HIGH_REG(d) == s1) {
2090 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2091 M_ILD(GET_HIGH_REG(d), s1, disp);
2094 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2095 M_ILD(GET_HIGH_REG(d), s1, disp);
2099 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2103 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2107 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2111 emit_store_dst(jd, iptr, d);
2114 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2118 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2119 emit_nullpointer_check(cd, iptr, s1);
2121 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2122 uf = iptr->sx.s23.s3.uf;
2123 fieldtype = uf->fieldref->parseddesc.fd->type;
2127 fi = iptr->sx.s23.s3.fmiref->p.field;
2128 fieldtype = fi->type;
2132 /* We can't add a patcher ref behind this load,
2133 * because the patcher would destroy REG_ITMP3.
2135 * We pass in the disp parameter, how many bytes
2136 * to skip to the to the actual store.
2138 * XXX this relies on codegen_add_patch_ref internals
2141 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2142 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2147 if (IS_INT_LNG_TYPE(fieldtype)) {
2148 if (IS_2_WORD_TYPE(fieldtype))
2149 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2151 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2153 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2156 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2157 cd->patchrefs->disp = (cd->mcodeptr - ref);
2160 switch (fieldtype) {
2162 M_IST(s2, s1, disp);
2165 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2166 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2169 M_AST(s2, s1, disp);
2172 M_FST(s2, s1, disp);
2175 M_DST(s2, s1, disp);
2182 /* branch operations **************************************************/
2184 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2186 /* PROFILE_CYCLE_STOP; */
2188 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2189 M_INTMOVE(s1, REG_ITMP1_XPTR);
2191 #ifdef ENABLE_VERIFIER
2192 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2193 uc = iptr->sx.s23.s2.uc;
2195 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2197 #endif /* ENABLE_VERIFIER */
2199 disp = dseg_add_functionptr(cd, asm_handle_exception);
2200 M_ALD_DSEG(REG_ITMP2, disp);
2201 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2206 case ICMD_GOTO: /* ... ==> ... */
2207 case ICMD_RET: /* ... ==> ... */
2209 emit_br(cd, iptr->dst.block);
2213 case ICMD_JSR: /* ... ==> ... */
2215 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2219 case ICMD_IFNULL: /* ..., value ==> ... */
2220 case ICMD_IFNONNULL: /* ..., value ==> ... */
2221 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2223 switch (iptr->opc) {
2225 emit_beq(cd, iptr->dst.block);
2227 case ICMD_IFNONNULL:
2228 emit_bne(cd, iptr->dst.block);
2233 case ICMD_IFEQ: /* ..., value ==> ... */
2234 case ICMD_IFLT: /* ..., value ==> ... */
2235 case ICMD_IFLE: /* ..., value ==> ... */
2236 case ICMD_IFNE: /* ..., value ==> ... */
2237 case ICMD_IFGT: /* ..., value ==> ... */
2238 case ICMD_IFGE: /* ..., value ==> ... */
2240 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2242 if (N_VALID_IMM(iptr->sx.val.i))
2243 M_ICMP_IMM(s1, iptr->sx.val.i);
2245 disp = dseg_add_s4(cd, iptr->sx.val.i);
2246 if (N_VALID_DSEG_DISP(disp)) {
2247 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2249 ICONST(REG_ITMP2, disp);
2250 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2254 switch (iptr->opc) {
2256 emit_blt(cd, iptr->dst.block);
2259 emit_ble(cd, iptr->dst.block);
2262 emit_bne(cd, iptr->dst.block);
2265 emit_bgt(cd, iptr->dst.block);
2268 emit_bge(cd, iptr->dst.block);
2271 emit_beq(cd, iptr->dst.block);
2277 case ICMD_IF_LLT: /* ..., value ==> ... */
2278 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2284 /* ATTENTION: compare high words signed and low words unsigned */
2286 # define LABEL_OUT BRANCH_LABEL_1
2288 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2290 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2291 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2293 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2294 if (N_VALID_DSEG_DISP(disp)) {
2295 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2297 ICONST(REG_ITMP2, disp);
2298 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2305 emit_blt(cd, iptr->dst.block);
2306 /* EQ ... fall through */
2307 emit_label_bgt(cd, LABEL_OUT);
2311 emit_bgt(cd, iptr->dst.block);
2312 /* EQ ... fall through */
2313 emit_label_blt(cd, LABEL_OUT);
2316 /* EQ ... fall through */
2317 emit_label_bne(cd, LABEL_OUT);
2320 /* EQ ... fall through */
2321 emit_bne(cd, iptr->dst.block);
2327 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2329 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2330 if (N_VALID_DSEG_DISP(disp)) {
2331 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2333 ICONST(REG_ITMP2, disp);
2334 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2339 emit_blt(cd, iptr->dst.block);
2340 emit_label(cd, LABEL_OUT);
2343 emit_ble(cd, iptr->dst.block);
2344 emit_label(cd, LABEL_OUT);
2347 emit_bgt(cd, iptr->dst.block);
2348 emit_label(cd, LABEL_OUT);
2351 emit_bge(cd, iptr->dst.block);
2352 emit_label(cd, LABEL_OUT);
2355 emit_beq(cd, iptr->dst.block);
2356 emit_label(cd, LABEL_OUT);
2359 emit_bne(cd, iptr->dst.block);
2368 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2369 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2371 /* Compare addresses as 31 bit unsigned integers */
2373 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2374 M_LDA(REG_ITMP1, s1, 0);
2376 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2377 M_LDA(REG_ITMP2, s2, 0);
2379 M_CMP(REG_ITMP1, REG_ITMP2);
2381 switch (iptr->opc) {
2382 case ICMD_IF_ACMPEQ:
2383 emit_beq(cd, iptr->dst.block);
2385 case ICMD_IF_ACMPNE:
2386 emit_bne(cd, iptr->dst.block);
2392 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2393 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2394 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2395 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2396 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2397 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2399 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2400 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2402 switch (iptr->opc) {
2403 case ICMD_IF_ICMPEQ:
2404 emit_beq(cd, iptr->dst.block);
2406 case ICMD_IF_ICMPNE:
2407 emit_bne(cd, iptr->dst.block);
2409 case ICMD_IF_ICMPLT:
2410 emit_blt(cd, iptr->dst.block);
2412 case ICMD_IF_ICMPGT:
2413 emit_bgt(cd, iptr->dst.block);
2415 case ICMD_IF_ICMPLE:
2416 emit_ble(cd, iptr->dst.block);
2418 case ICMD_IF_ICMPGE:
2419 emit_bge(cd, iptr->dst.block);
2425 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2426 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2427 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2428 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2429 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2430 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2435 /* ATTENTION: compare high words signed and low words unsigned */
2437 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2438 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2443 case ICMD_IF_LCMPLT:
2444 case ICMD_IF_LCMPLE:
2445 emit_blt(cd, iptr->dst.block);
2446 /* EQ ... fall through */
2447 out_ref = cd->mcodeptr;
2450 case ICMD_IF_LCMPGT:
2451 case ICMD_IF_LCMPGE:
2452 emit_bgt(cd, iptr->dst.block);
2453 /* EQ ... fall through */
2454 out_ref = cd->mcodeptr;
2457 case ICMD_IF_LCMPEQ:
2458 /* EQ ... fall through */
2459 out_ref = cd->mcodeptr;
2462 case ICMD_IF_LCMPNE:
2463 /* EQ ... fall through */
2464 emit_bne(cd, iptr->dst.block);
2470 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2471 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2476 case ICMD_IF_LCMPLT:
2477 emit_blt(cd, iptr->dst.block);
2479 case ICMD_IF_LCMPLE:
2480 emit_ble(cd, iptr->dst.block);
2482 case ICMD_IF_LCMPGT:
2483 emit_bgt(cd, iptr->dst.block);
2485 case ICMD_IF_LCMPGE:
2486 emit_bge(cd, iptr->dst.block);
2488 case ICMD_IF_LCMPEQ:
2489 emit_beq(cd, iptr->dst.block);
2491 case ICMD_IF_LCMPNE:
2492 emit_bne(cd, iptr->dst.block);
2499 if (out_ref != NULL) {
2500 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2506 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2508 REPLACEMENT_POINT_RETURN(cd, iptr);
2509 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2510 M_INTMOVE(s1, REG_RESULT);
2511 goto nowperformreturn;
2513 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2515 REPLACEMENT_POINT_RETURN(cd, iptr);
2516 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2517 M_INTMOVE(s1, REG_RESULT);
2519 #ifdef ENABLE_VERIFIER
2520 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2521 unresolved_class *uc = iptr->sx.s23.s2.uc;
2524 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2525 PROFILE_CYCLE_START;
2527 #endif /* ENABLE_VERIFIER */
2528 goto nowperformreturn;
2530 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2532 REPLACEMENT_POINT_RETURN(cd, iptr);
2533 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2534 M_LNGMOVE(s1, REG_RESULT_PACKED);
2535 goto nowperformreturn;
2537 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2540 REPLACEMENT_POINT_RETURN(cd, iptr);
2541 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2542 M_FLTMOVE(s1, REG_FRESULT);
2543 goto nowperformreturn;
2545 case ICMD_RETURN: /* ... ==> ... */
2547 REPLACEMENT_POINT_RETURN(cd, iptr);
2553 p = cd->stackframesize;
2555 /* call trace function */
2557 #if !defined(NDEBUG)
2558 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2559 emit_verbosecall_exit(jd);
2560 #endif /* !defined(NDEBUG) */
2562 #if defined(ENABLE_THREADS)
2563 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2565 /* we need to save the proper return value */
2567 switch (iptr->opc) {
2569 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2573 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2576 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2579 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2583 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2585 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2586 M_ALD_DSEG(REG_ITMP3, disp);
2588 M_ASUB_IMM(96, REG_SP);
2590 M_AADD_IMM(96, REG_SP);
2592 /* and now restore the proper return value */
2594 switch (iptr->opc) {
2596 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2600 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2603 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2606 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2612 /* restore return address */
2614 p--; M_ALD(REG_RA, REG_SP, p * 4);
2616 /* restore saved registers */
2618 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2619 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2621 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2622 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2625 /* deallocate stack */
2627 if (cd->stackframesize)
2628 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2630 /* generate method profiling code */
2638 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2641 branch_target_t *table;
2643 table = iptr->dst.table;
2645 l = iptr->sx.s23.s2.tablelow;
2646 i = iptr->sx.s23.s3.tablehigh;
2648 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2649 M_INTMOVE(s1, REG_ITMP1);
2653 } else if (N_VALID_IMM(-l)) {
2654 M_ISUB_IMM(l, REG_ITMP1);
2656 ICONST(REG_ITMP2, l);
2657 M_ISUB(REG_ITMP2, REG_ITMP1);
2660 /* number of targets */
2666 ICONST(REG_ITMP2, i);
2667 M_ICMPU(REG_ITMP1, REG_ITMP2);
2668 emit_bge(cd, table[0].block);
2670 /* build jump table top down and use address of lowest entry */
2675 dseg_add_target(cd, table->block);
2680 /* length of dataseg after last dseg_add_target is used by load */
2682 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2683 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2684 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2685 M_JMP(RN, REG_ITMP1);
2690 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2693 lookup_target_t *lookup;
2695 lookup = iptr->dst.lookup;
2697 i = iptr->sx.s23.s2.lookupcount;
2699 MCODECHECK(8 + ((7 + 6) * i) + 5);
2700 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2703 if (N_VALID_IMM(lookup->value)) {
2704 M_ICMP_IMM(s1, lookup->value);
2706 ICONST(REG_ITMP2, lookup->value);
2707 M_ICMP(REG_ITMP2, s1);
2709 emit_beq(cd, lookup->target.block);
2713 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2718 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2720 bte = iptr->sx.s23.s3.bte;
2724 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2725 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2726 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2727 case ICMD_INVOKEINTERFACE:
2729 REPLACEMENT_POINT_INVOKE(cd, iptr);
2731 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2733 um = iptr->sx.s23.s3.um;
2734 md = um->methodref->parseddesc.md;
2737 lm = iptr->sx.s23.s3.fmiref->p.method;
2739 md = lm->parseddesc;
2743 s3 = md->paramcount;
2745 MCODECHECK((s3 << 1) + 64);
2747 /* copy arguments to registers or stack location */
2749 for (s3 = s3 - 1; s3 >= 0; s3--) {
2750 var = VAR(iptr->sx.s23.s2.args[s3]);
2752 /* Already Preallocated? */
2753 if (var->flags & PREALLOC)
2756 if (IS_INT_LNG_TYPE(var->type)) {
2757 if (!md->params[s3].inmemory) {
2758 if (IS_2_WORD_TYPE(var->type)) {
2760 GET_LOW_REG(md->params[s3].regoff),
2761 GET_HIGH_REG(md->params[s3].regoff)
2763 d = emit_load(jd, iptr, var, s1);
2767 s1 = md->params[s3].regoff;
2768 d = emit_load(jd, iptr, var, s1);
2773 if (IS_2_WORD_TYPE(var->type)) {
2774 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2775 M_LST(d, REG_SP, md->params[s3].regoff);
2778 d = emit_load(jd, iptr, var, REG_ITMP1);
2779 M_IST(d, REG_SP, md->params[s3].regoff);
2784 if (!md->params[s3].inmemory) {
2785 s1 = md->params[s3].regoff;
2786 d = emit_load(jd, iptr, var, s1);
2790 d = emit_load(jd, iptr, var, REG_FTMP1);
2791 if (IS_2_WORD_TYPE(var->type))
2792 M_DST(d, REG_SP, md->params[s3].regoff);
2794 M_FST(d, REG_SP, md->params[s3].regoff);
2799 /* generate method profiling code */
2803 switch (iptr->opc) {
2805 disp = dseg_add_functionptr(cd, bte->fp);
2807 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2808 if (N_VALID_DSEG_DISP(disp)) {
2809 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2811 N_LHI(REG_ITMP1, disp);
2812 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2816 case ICMD_INVOKESPECIAL:
2818 /* Implicit NULL pointer check */
2819 M_ILD(REG_ITMP1, REG_A0, 0);
2823 case ICMD_INVOKESTATIC:
2825 disp = dseg_add_unique_address(cd, um);
2827 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2831 disp = dseg_add_address(cd, lm->stubroutine);
2833 if (N_VALID_DSEG_DISP(disp)) {
2834 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2836 N_LHI(REG_ITMP1, disp);
2837 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2841 case ICMD_INVOKEVIRTUAL:
2842 /* TODO softnull REG_A0 */
2845 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2850 s1 = OFFSET(vftbl_t, table[0]) +
2851 sizeof(methodptr) * lm->vftblindex;
2854 /* implicit null-pointer check */
2856 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2857 M_ALD(REG_PV, REG_METHODPTR, s1);
2860 case ICMD_INVOKEINTERFACE:
2861 /* TODO softnull REG_A0 */
2863 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2864 * and -0xFFF in index register (itmp1)
2868 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2874 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2875 sizeof(methodptr*) * lm->class->index;
2877 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2880 /* Implicit null-pointer check */
2881 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2882 N_LHI(REG_ITMP1, s1);
2883 N_L(REG_METHODPTR, 0, REG_ITMP1, REG_METHODPTR);
2884 M_ALD(REG_PV, REG_METHODPTR, s2);
2888 /* generate the actual call */
2891 emit_restore_pv(cd);
2893 /* post call finalization */
2895 switch (iptr->opc) {
2897 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2898 emit_exception_check(cd, iptr); /* check for exception */
2902 /* generate method profiling code */
2904 PROFILE_CYCLE_START;
2906 /* store size of call code in replacement point */
2908 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2910 /* store return value */
2912 d = md->returntype.type;
2914 if (d != TYPE_VOID) {
2915 if (IS_INT_LNG_TYPE(d)) {
2916 if (IS_2_WORD_TYPE(d)) {
2917 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2918 M_LNGMOVE(REG_RESULT_PACKED, s1);
2921 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2922 M_INTMOVE(REG_RESULT, s1);
2926 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2927 M_FLTMOVE(REG_FRESULT, s1);
2929 emit_store_dst(jd, iptr, s1);
2935 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2937 /* val.a: (classinfo*) superclass */
2939 /* superclass is an interface:
2941 * OK if ((sub == NULL) ||
2942 * (sub->vftbl->interfacetablelength > super->index) &&
2943 * (sub->vftbl->interfacetable[-super->index] != NULL));
2945 * superclass is a class:
2947 * OK if ((sub == NULL) || (0
2948 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2949 * super->vftbl->diffval));
2952 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2953 /* object type cast-check */
2956 vftbl_t *supervftbl;
2959 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2960 # define LABEL_CLASS BRANCH_LABEL_2
2961 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2962 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2963 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2965 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2971 super = iptr->sx.s23.s3.c.cls;
2972 superindex = super->index;
2973 supervftbl = super->vftbl;
2976 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2977 CODEGEN_CRITICAL_SECTION_NEW;
2979 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2981 /* if class is not resolved, check which code to call */
2983 if (super == NULL) {
2985 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2987 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2989 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
2990 iptr->sx.s23.s3.c.ref,
2993 ICONST(REG_ITMP2, ACC_INTERFACE);
2994 if (N_VALID_DSEG_DISP(disp)) {
2995 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
2997 ICONST(REG_ITMP3, disp);
2998 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3000 emit_label_beq(cd, LABEL_CLASS);
3003 /* interface checkcast code */
3005 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3006 if (super == NULL) {
3007 codegen_add_patch_ref(cd,
3008 PATCHER_checkcast_instanceof_interface,
3009 iptr->sx.s23.s3.c.ref,
3013 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3016 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3017 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3018 M_ISUB_IMM(superindex, REG_ITMP3);
3019 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3022 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3023 superindex * sizeof(methodptr*))
3025 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3026 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3028 if (super == NULL) {
3029 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3033 /* class checkcast code */
3035 if (super == NULL) {
3036 emit_label(cd, LABEL_CLASS);
3039 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3040 if (super == NULL) {
3041 disp = dseg_add_unique_address(cd, NULL);
3043 codegen_add_patch_ref(cd,
3044 PATCHER_resolve_classref_to_vftbl,
3045 iptr->sx.s23.s3.c.ref,
3049 disp = dseg_add_address(cd, supervftbl);
3051 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3054 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3055 M_ALD_DSEG(REG_ITMP3, disp);
3057 CODEGEN_CRITICAL_SECTION_START;
3059 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3060 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3061 M_ISUB(REG_ITMP3, REG_ITMP2);
3062 M_ALD_DSEG(REG_ITMP3, disp);
3063 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3065 CODEGEN_CRITICAL_SECTION_END;
3067 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3068 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3069 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3070 /* Branch if greater then */
3071 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3074 if (super == NULL) {
3075 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3076 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3077 } else if (super->flags & ACC_INTERFACE) {
3078 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3080 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3083 d = codegen_reg_of_dst(jd, iptr, s1);
3085 # undef LABEL_EXIT_CHECK_NULL
3087 # undef LABEL_EXIT_INTERFACE_NULL
3088 # undef LABEL_EXIT_INTERFACE_DONE
3089 # undef LABEL_EXIT_CLASS_NULL
3092 /* array type cast-check */
3094 s1 = emit_load_s1(jd, iptr, REG_A0);
3095 M_INTMOVE(s1, REG_A0);
3097 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3098 disp = dseg_add_unique_address(cd, NULL);
3100 codegen_add_patch_ref(cd,
3101 PATCHER_resolve_classref_to_classinfo,
3102 iptr->sx.s23.s3.c.ref,
3106 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3108 M_ALD_DSEG(REG_A1, disp);
3109 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3110 M_ALD_DSEG(REG_ITMP1, disp);
3111 M_ASUB_IMM(96, REG_SP);
3112 M_JSR(REG_RA, REG_ITMP1);
3113 M_AADD_IMM(96, REG_SP);
3115 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3116 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3118 d = codegen_reg_of_dst(jd, iptr, s1);
3122 emit_store_dst(jd, iptr, d);
3125 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3126 /* val.a: (classinfo*) superclass */
3128 /* superclass is an interface:
3130 * return (sub != NULL) &&
3131 * (sub->vftbl->interfacetablelength > super->index) &&
3132 * (sub->vftbl->interfacetable[-super->index] != NULL);
3134 * superclass is a class:
3136 * return ((sub != NULL) && (0
3137 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3138 * super->vftbl->diffvall));
3140 * If superclass is unresolved, we include both code snippets
3141 * above, a patcher resolves the class' flags and we select
3142 * the right code at runtime.
3147 vftbl_t *supervftbl;
3150 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3156 super = iptr->sx.s23.s3.c.cls;
3157 superindex = super->index;
3158 supervftbl = super->vftbl;
3161 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3162 # define LABEL_CLASS BRANCH_LABEL_2
3163 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3164 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3165 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3166 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3168 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3169 CODEGEN_CRITICAL_SECTION_NEW;
3171 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3172 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3174 M_MOV(s1, REG_ITMP1);
3178 /* if class is not resolved, check which code to call */
3180 if (super == NULL) {
3184 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3186 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3188 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3189 iptr->sx.s23.s3.c.ref, disp);
3191 ICONST(REG_ITMP2, ACC_INTERFACE);
3193 if (N_VALID_DSEG_DISP(disp)) {
3194 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3196 ICONST(REG_ITMP3, disp);
3197 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3200 emit_label_beq(cd, LABEL_CLASS);
3203 /* interface instanceof code */
3205 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3206 if (super == NULL) {
3207 /* If d == REG_ITMP2, then it's destroyed in check
3212 codegen_add_patch_ref(cd,
3213 PATCHER_checkcast_instanceof_interface,
3214 iptr->sx.s23.s3.c.ref, 0);
3219 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3222 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3223 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3224 M_ISUB_IMM(superindex, REG_ITMP3);
3226 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3230 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3231 superindex * sizeof(methodptr*))
3233 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3235 /* d := (REG_ITMP1 != 0) */
3237 N_LTR(d, REG_ITMP1);
3238 M_BEQ(SZ_BRC + SZ_LHI);
3241 if (super == NULL) {
3242 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3246 /* class instanceof code */
3248 if (super == NULL) {
3249 emit_label(cd, LABEL_CLASS);
3252 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3253 if (super == NULL) {
3254 disp = dseg_add_unique_address(cd, NULL);
3256 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3257 iptr->sx.s23.s3.c.ref,
3261 disp = dseg_add_address(cd, supervftbl);
3266 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3269 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3270 M_ALD_DSEG(REG_ITMP2, disp);
3272 CODEGEN_CRITICAL_SECTION_START;
3274 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3275 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3276 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3278 CODEGEN_CRITICAL_SECTION_END;
3280 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3282 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3284 M_BGT(SZ_BRC + SZ_LHI);
3288 if (super == NULL) {
3289 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3290 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3291 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3292 } else if (super->flags & ACC_INTERFACE) {
3293 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3294 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3296 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3299 # undef LABEL_EXIT_CHECK_NULL
3301 # undef LABEL_EXIT_INTERFACE_NULL
3302 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3303 # undef LABEL_EXIT_INTERFACE_DONE
3304 # undef LABEL_EXIT_CLASS_NULL
3306 emit_store_dst(jd, iptr, d);
3312 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3314 /* check for negative sizes and copy sizes to stack if necessary */
3316 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3319 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3321 /* copy SAVEDVAR sizes to stack */
3322 var = VAR(iptr->sx.s23.s2.args[s1]);
3324 /* Already Preallocated? */
3325 if (!(var->flags & PREALLOC)) {
3326 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3327 M_IST(s2, REG_SP, s1 * 4);
3331 /* is a patcher function set? */
3333 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3334 disp = dseg_add_unique_address(cd, 0);
3336 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
3337 iptr->sx.s23.s3.c.ref,
3341 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3343 /* a0 = dimension count */
3345 ICONST(REG_A0, iptr->s1.argcount);
3347 /* a1 = classinfo */
3349 M_ALD_DSEG(REG_A1, disp);
3351 /* a2 = pointer to dimensions = stack pointer */
3353 M_MOV(REG_SP, REG_A2);
3355 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3356 M_ALD_DSEG(REG_ITMP1, disp);
3357 M_ASUB_IMM(96, REG_SP);
3358 M_JSR(REG_RA, REG_ITMP1);
3359 M_AADD_IMM(96, REG_SP);
3361 /* check for exception before result assignment */
3363 emit_exception_check(cd, iptr);
3365 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3366 M_INTMOVE(REG_RESULT, s1);
3367 emit_store_dst(jd, iptr, s1);
3372 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3376 } /* for instruction */
3378 MCODECHECK(512); /* XXX require a lower number? */
3380 /* At the end of a basic block we may have to append some nops,
3381 because the patcher stub calling code might be longer than the
3382 actual instruction. So codepatching does not change the
3383 following block unintentionally. */
3385 if (cd->mcodeptr < cd->lastmcodeptr) {
3386 while (cd->mcodeptr < cd->lastmcodeptr) {
3391 } /* if (bptr -> flags >= BBREACHED) */
3392 } /* for basic block */
3394 dseg_createlinenumbertable(cd);
3396 /* generate stubs */
3398 emit_patcher_stubs(jd);
3399 #if defined(ENABLE_REPLACEMENT)
3400 REPLACEMENT_EMIT_STUBS(jd);
3403 /* everything's ok */
3409 /* codegen_emit_stub_compiler **************************************************
3411 Emits a stub routine which calls the compiler.
3413 *******************************************************************************/
3415 void codegen_emit_stub_compiler(jitdata *jd)
3420 /* get required compiler data */
3425 /* code for the stub */
3427 /* don't touch ITMP3 as it cointains the return address */
3429 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3431 M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */
3432 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3433 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3438 /* codegen_emit_stub_native ****************************************************
3440 Emits a stub routine which calls a native method.
3442 *******************************************************************************/
3445 arguments on stack \
3446 -------------------------------------------------| <- SP on nativestub entry
3448 callee saved int regs (none) |
3449 callee saved float regs (none) | stack frame like in cacao
3450 local variable slots (none) |
3451 arguments for calling methods (none) /
3452 ------------------------------------------------------------------ <- datasp
3457 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3458 0 - 96 register save area for callee /
3459 -------------------------------------------------------- <- SP native method
3461 SP after method entry
3464 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3472 s4 i, j; /* count variables */
3477 /* get required compiler data */
3484 /* initialize variables */
3487 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3489 /* calculate stack frame size */
3491 cd->stackframesize =
3492 1 + /* r14 - return address */ +
3493 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3494 sizeof(localref_table) / SIZEOF_VOID_P +
3496 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3497 nmd->memuse + /* parameter passing */
3498 96 / SIZEOF_VOID_P /* required by ABI */;
3500 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3503 /* create method header */
3505 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3506 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3507 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3508 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3509 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3510 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3511 (void) dseg_addlinenumbertablesize(cd);
3512 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3514 /* generate stub code */
3516 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3517 N_AHI(REG_PV, N_PV_OFFSET);
3519 /* generate native method profiling code */
3521 #if defined(ENABLE_PROFILING)
3522 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3523 /* count frequency */
3524 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
3525 ICONST(REG_ITMP2, 1);
3526 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
3527 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
3531 /* save return address */
3533 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3535 #if !defined(NDEBUG)
3536 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3537 emit_verbosecall_enter(jd);
3540 /* get function address (this must happen before the stackframeinfo) */
3542 disp = dseg_add_functionptr(cd, f);
3544 #if !defined(WITH_STATIC_CLASSPATH)
3546 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3549 M_ILD_DSEG(REG_ITMP1, disp);
3551 j = 96 + (nmd->memuse * 4);
3553 /* todo some arg registers are not volatile in C-abi terms */
3555 /* save integer and float argument registers */
3557 for (i = 0; i < md->paramcount; i++) {
3558 if (! md->params[i].inmemory) {
3559 s1 = md->params[i].regoff;
3560 t = md->paramtypes[i].type;
3562 if (IS_INT_LNG_TYPE(t)) {
3563 if (IS_2_WORD_TYPE(t)) {
3564 /* todo store multiple */
3565 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3566 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3568 N_ST(s1, j, RN, REG_SP);
3571 if (IS_2_WORD_TYPE(t)) {
3572 N_STD(s1, j, RN, REG_SP);
3574 N_STE(s1, j, RN, REG_SP);
3582 N_ST(REG_ITMP1, j, RN, REG_SP);
3584 /* create dynamic stack info */
3586 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3587 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3588 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3589 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3591 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3592 M_ILD_DSEG(REG_ITMP1, disp);
3594 M_CALL(REG_ITMP1); /* call */
3596 /* restore integer and float argument registers */
3598 j = 96 + (nmd->memuse * 4);
3600 for (i = 0; i < md->paramcount; i++) {
3601 if (! md->params[i].inmemory) {
3602 s1 = md->params[i].regoff;
3603 t = md->paramtypes[i].type;
3605 if (IS_INT_LNG_TYPE(t)) {
3606 if (IS_2_WORD_TYPE(t)) {
3607 /* todo load multiple ! */
3608 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3609 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3611 N_L(s1, j, RN, REG_SP);
3614 if (IS_2_WORD_TYPE(t)) {
3615 N_LD(s1, j, RN, REG_SP);
3617 N_LE(s1, j, RN, REG_SP);
3625 N_L(REG_ITMP1, j, RN, REG_SP);
3627 /* copy or spill arguments to new locations */
3629 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3630 t = md->paramtypes[i].type;
3632 if (IS_INT_LNG_TYPE(t)) {
3634 if (!md->params[i].inmemory) {
3636 s1 = md->params[i].regoff;
3638 if (!nmd->params[j].inmemory) {
3639 s2 = nmd->params[j].regoff;
3640 if (IS_2_WORD_TYPE(t)) {
3656 s2 = nmd->params[j].regoff;
3657 if (IS_2_WORD_TYPE(t)) {
3672 s1 = cd->stackframesize * 4 + md->params[i].regoff;
3673 s2 = nmd->params[j].regoff;
3675 if (IS_2_WORD_TYPE(t)) {
3676 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3678 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3683 /* We only copy spilled float arguments, as the float argument */
3684 /* registers keep unchanged. */
3686 if (md->params[i].inmemory) {
3687 s1 = cd->stackframesize * 4 + md->params[i].regoff;
3688 s2 = nmd->params[j].regoff;
3690 if (IS_2_WORD_TYPE(t)) {
3691 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3693 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3699 /* put class into second argument register */
3701 if (m->flags & ACC_STATIC) {
3702 disp = dseg_add_address(cd, m->class);
3703 M_ILD_DSEG(REG_A1, disp);
3706 /* put env into first argument register */
3708 disp = dseg_add_address(cd, _Jv_env);
3709 M_ILD_DSEG(REG_A0, disp);
3711 /* do the native function call */
3713 M_CALL(REG_ITMP1); /* call */
3715 /* save return value */
3717 t = md->returntype.type;
3719 if (t != TYPE_VOID) {
3720 if (IS_INT_LNG_TYPE(t)) {
3721 if (IS_2_WORD_TYPE(t)) {
3722 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3724 N_ST(REG_RESULT, 96, RN, REG_SP);
3727 if (IS_2_WORD_TYPE(t)) {
3728 N_STD(REG_FRESULT, 96, RN, REG_SP);
3730 N_STE(REG_FRESULT, 96, RN, REG_SP);
3735 #if !defined(NDEBUG)
3736 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3737 emit_verbosecall_exit(jd);
3740 /* remove native stackframe info */
3742 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3743 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3744 M_ALD_DSEG(REG_ITMP1, disp);
3746 N_LR(REG_ITMP3, REG_RESULT);
3748 /* restore return value */
3750 if (t != TYPE_VOID) {
3751 if (IS_INT_LNG_TYPE(t)) {
3752 if (IS_2_WORD_TYPE(t)) {
3753 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3755 N_L(REG_RESULT, 96, RN, REG_SP);
3758 if (IS_2_WORD_TYPE(t)) {
3759 N_LD(REG_FRESULT, 96, RN, REG_SP);
3761 N_LE(REG_FRESULT, 96, RN, REG_SP);
3766 /* load return address */
3768 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3770 /* remove stackframe */
3772 N_AHI(REG_SP, cd->stackframesize * 4);
3774 /* test for exception */
3776 N_LTR(REG_ITMP3, REG_ITMP3);
3777 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3781 N_BCR(DD_ANY, REG_ITMP2);
3783 /* handle exception */
3785 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3786 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3790 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3793 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3794 M_ALD_DSEG(REG_ITMP3, disp);
3795 M_JMP(RN, REG_ITMP3);
3797 /* generate patcher stubs */
3799 emit_patcher_stubs(jd);
3802 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3803 codegendata *cd = jd->cd;
3804 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3806 M_MOV(reg, tempregnum);
3814 * These are local overrides for various environment variables in Emacs.
3815 * Please do not remove this and leave it at the end of the file, where
3816 * Emacs will automagically detect them.
3817 * ---------------------------------------------------------------------
3820 * indent-tabs-mode: t
3824 * vim:noexpandtab:sw=4:ts=4: