1 /* src/vm/jit/s390/codegen.c - machine code generator for s390
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
34 #include "native/jni.h"
35 #include "native/localref.h"
36 #include "native/native.h"
38 #include "mm/memory.h"
40 #if defined(ENABLE_THREADS)
41 # include "threads/lock-common.h"
42 # include "threads/native/lock.h"
45 #include "vmcore/loader.h"
46 #include "vmcore/options.h"
47 #include "vmcore/statistics.h"
48 #include "vm/builtin.h"
49 #include "vm/exceptions.h"
50 #include "vm/global.h"
51 #include "vm/jit/abi.h"
52 #if defined(ENABLE_LSRA)
53 # include "vm/jit/allocator/lsra.h"
55 #include "vm/jit/asmpart.h"
56 #include "vm/jit/codegen-common.h"
57 #include "vm/jit/dseg.h"
58 #include "vm/jit/emit-common.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/methodheader.h"
61 #include "vm/jit/parse.h"
62 #include "vm/jit/patcher-common.h"
63 #include "vm/jit/reg.h"
64 #include "vm/jit/replace.h"
65 #include "vm/jit/s390/arch.h"
66 #include "vm/jit/s390/codegen.h"
67 #include "vm/jit/s390/emit.h"
68 #include "vm/jit/s390/md-abi.h"
69 #include "vm/jit/stacktrace.h"
71 #include "vm/stringlocal.h"
74 /* DO__LOG generates a call to do__log. No registers are destroyed,
75 * so you may use it anywhere. regs is an array containing all general
79 static void do__log(u4 *regs) {
80 /* insert stuff here */
84 N_AHI(REG_SP, -200); \
85 N_STM(R0, R15, 96, REG_SP); \
86 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
87 N_LA(R2, 96, RN, REG_SP); \
89 N_LM(R0, R15, 96, REG_SP); \
92 #define SUPPORT_HERCULES 1
94 /* codegen *********************************************************************
96 Generates machine code.
98 *******************************************************************************/
102 Layout of stackframe:
105 ===============================================================================
106 return_address (stackframesize - 1) * 8
107 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
109 saved_int_reg[rd->savintreguse]
110 saved_flt_reg[FLT_SAV_CNT - 1]
112 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
114 return_value_tmp (rd->memuse + 1) * 8
115 monitorenter_argument (rd->memuse) * 8
117 local[rd->memuse - 1] (rd->memuse - 1) * 8
125 bool codegen_emit(jitdata *jd)
131 s4 len, s1, s2, s3, d, dd, disp;
134 varinfo *var, *var1, *var2, *dst;
137 constant_classref *cr;
138 unresolved_class *uc;
139 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
140 unresolved_method *um;
141 builtintable_entry *bte;
144 unresolved_field *uf;
147 rplpoint *replacementpoint;
151 /* get required compiler data */
158 /* prevent compiler warnings */
171 /* space to save used callee saved registers */
173 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
174 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
176 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
179 * As REG_ITMP2 == REG_RA, do not touch REG_ITMP2, until it has been saved.
182 #if defined(ENABLE_THREADS)
183 /* Space to save argument of monitor_enter and Return Values to
184 survive monitor_exit. The stack position for the argument can
185 not be shared with place to save the return register
186 since both values reside in R2. */
188 if (checksync && code_is_synchronized(code)) {
189 /* 1 slot space to save argument of monitor_enter */
190 /* 1 slot to temporary store return value before monitor_exit */
191 cd->stackframesize += 2;
195 /* Keep stack of non-leaf functions 16-byte aligned for calls into
196 native code e.g. libc or jni (alignment problems with
199 if (!code_is_leafmethod(code) || opt_verbosecall )
200 /* TODO really 16 bytes ? */
201 cd->stackframesize = (cd->stackframesize + 2) & ~2;
203 /* create method header */
205 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
206 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
208 code->synchronizedoffset = rd->memuse * 8;
210 /* REMOVEME: We still need it for exception handling in assembler. */
212 if (code_is_leafmethod(code))
213 (void) dseg_add_unique_s4(cd, 1);
215 (void) dseg_add_unique_s4(cd, 0);
217 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
218 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
220 (void) dseg_addlinenumbertablesize(cd);
224 M_AADD_IMM(N_PV_OFFSET, REG_PV);
226 /* create stack frame (if necessary) */
228 if (cd->stackframesize) {
229 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
232 /* store return address */
234 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
236 /* generate method profiling code */
238 #if defined(ENABLE_PROFILING)
239 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
240 /* count frequency */
241 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
242 ICONST(REG_ITMP2, 1);
243 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
244 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
250 /* save used callee saved registers and return address */
252 p = cd->stackframesize - 1;
254 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
255 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
257 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
258 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
261 /* take arguments out of register or stack frame */
265 for (p = 0, l = 0; p < md->paramcount; p++) {
266 t = md->paramtypes[p].type;
267 varindex = jd->local_map[l * 5 + t];
271 if (IS_2_WORD_TYPE(t))
274 if (varindex == UNUSED)
279 s1 = md->params[p].regoff;
281 if (IS_INT_LNG_TYPE(t)) { /* integer args */
282 if (IS_2_WORD_TYPE(t)) {
290 if (!md->params[p].inmemory) { /* register arguments */
291 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
292 if (IS_2_WORD_TYPE(t)) {
293 M_LNGMOVE(s2, var->vv.regoff);
295 M_INTMOVE(s2, var->vv.regoff);
297 } else { /* reg arg -> spilled */
298 if (IS_2_WORD_TYPE(t)) {
299 M_LST(s2, REG_SP, var->vv.regoff);
301 M_IST(s2, REG_SP, var->vv.regoff);
305 } else { /* stack arguments */
306 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
307 if (IS_2_WORD_TYPE(t)) {
308 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
310 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
312 } else { /* stack arg -> spilled */
313 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
317 } else { /* floating args */
318 if (!md->params[p].inmemory) { /* register arguments */
320 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
321 M_FLTMOVE(s2, var->vv.regoff);
323 } else { /* reg arg -> spilled */
324 if (IS_2_WORD_TYPE(t))
325 M_DST(s2, REG_SP, var->vv.regoff);
327 M_FST(s2, REG_SP, var->vv.regoff);
330 } else { /* stack arguments */
331 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
332 if (IS_2_WORD_TYPE(t))
333 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
336 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
338 } else { /* stack-arg -> spilled */
339 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
340 var->vv.regoff = cd->stackframesize * 8 + s1;
346 /* save monitorenter argument */
348 #if defined(ENABLE_THREADS)
349 if (checksync && code_is_synchronized(code)) {
350 /* stack offset for monitor argument */
355 if (opt_verbosecall) {
356 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
358 for (p = 0; p < INT_ARG_CNT; p++)
359 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
361 for (p = 0; p < FLT_ARG_CNT; p++)
362 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
364 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
368 /* decide which monitor enter function to call */
370 if (m->flags & ACC_STATIC) {
371 disp = dseg_add_address(cd, &m->class->object.header);
372 M_ALD_DSEG(REG_A0, disp);
376 M_BNE(SZ_BRC + SZ_ILL);
377 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
380 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
381 M_ALD_DSEG(REG_ITMP2, disp);
383 M_AST(REG_A0, REG_SP, s1 * 8);
385 M_ASUB_IMM(96, REG_SP);
387 M_AADD_IMM(96, REG_SP);
390 if (opt_verbosecall) {
391 for (p = 0; p < INT_ARG_CNT; p++)
392 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
394 for (p = 0; p < FLT_ARG_CNT; p++)
395 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
397 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
404 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
405 emit_verbosecall_enter(jd);
406 #endif /* !defined(NDEBUG) */
410 /* end of header generation */
412 /* create replacement points */
414 REPLACEMENT_POINTS_INIT(cd, jd);
416 /* walk through all basic blocks */
418 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
420 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
422 if (bptr->flags >= BBREACHED) {
424 /* branch resolving */
426 codegen_resolve_branchrefs(cd, bptr);
428 /* handle replacement points */
430 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
432 /* copy interface registers to their destination */
437 #if defined(ENABLE_PROFILING)
438 /* generate basicblock profiling code */
440 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
441 /* count frequency */
443 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
444 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
445 ICONST(REG_ITMP2, 1);
446 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
447 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
449 /* if this is an exception handler, start profiling again */
451 if (bptr->type == BBTYPE_EXH)
456 #if defined(ENABLE_LSRA)
460 src = bptr->invars[len];
461 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
462 if (bptr->type == BBTYPE_EXH) {
463 /* d = reg_of_var(rd, src, REG_ITMP1); */
464 if (!IS_INMEMORY(src->flags))
468 M_INTMOVE(REG_ITMP3_XPTR, d);
469 emit_store(jd, NULL, src, d);
479 var = VAR(bptr->invars[len]);
480 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
481 if (bptr->type == BBTYPE_EXH) {
482 d = codegen_reg_of_var(0, var, REG_ITMP3_XPTR);
483 M_INTMOVE(REG_ITMP3_XPTR, d);
484 emit_store(jd, NULL, var, d);
488 assert((var->flags & INOUT));
491 #if defined(ENABLE_LSRA)
494 /* walk through all instructions */
499 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
500 if (iptr->line != currentline) {
501 dseg_addlinenumber(cd, iptr->line);
502 currentline = iptr->line;
505 MCODECHECK(1024); /* 1KB should be enough */
508 case ICMD_NOP: /* ... ==> ... */
509 case ICMD_POP: /* ..., value ==> ... */
510 case ICMD_POP2: /* ..., value, value ==> ... */
513 case ICMD_INLINE_START:
515 REPLACEMENT_POINT_INLINE_START(cd, iptr);
518 case ICMD_INLINE_BODY:
520 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
521 dseg_addlinenumber_inline_start(cd, iptr);
522 dseg_addlinenumber(cd, iptr->line);
525 case ICMD_INLINE_END:
527 dseg_addlinenumber_inline_end(cd, iptr);
528 dseg_addlinenumber(cd, iptr->line);
531 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
532 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
533 emit_nullpointer_check(cd, iptr, s1);
536 /* constant operations ************************************************/
538 case ICMD_ICONST: /* ... ==> ..., constant */
539 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
540 ICONST(d, iptr->sx.val.i);
541 emit_store_dst(jd, iptr, d);
544 case ICMD_LCONST: /* ... ==> ..., constant */
546 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
547 LCONST(d, iptr->sx.val.l);
548 emit_store_dst(jd, iptr, d);
551 case ICMD_FCONST: /* ... ==> ..., constant */
552 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
553 disp = dseg_add_float(cd, iptr->sx.val.f);
554 M_FLD_DSEG(d, disp, REG_ITMP1);
555 emit_store_dst(jd, iptr, d);
558 case ICMD_DCONST: /* ... ==> ..., constant */
559 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
560 disp = dseg_add_double(cd, iptr->sx.val.d);
561 M_DLD_DSEG(d, disp, REG_ITMP1);
562 emit_store_dst(jd, iptr, d);
565 case ICMD_ACONST: /* ... ==> ..., constant */
566 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
568 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
569 cr = iptr->sx.val.c.ref;
570 disp = dseg_add_unique_address(cd, cr);
572 /* PROFILE_CYCLE_STOP; */
574 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
577 /* PROFILE_CYCLE_START; */
581 if (iptr->sx.val.anyptr == 0) {
584 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
587 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
588 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
590 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
592 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
598 emit_store_dst(jd, iptr, d);
602 /* load/store/copy/move operations ************************************/
604 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
605 case ICMD_ALOAD: /* s1 = local variable */
609 case ICMD_ISTORE: /* ..., value ==> ... */
620 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
624 /* integer operations *************************************************/
626 case ICMD_INEG: /* ..., value ==> ..., - value */
628 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
629 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
631 emit_store_dst(jd, iptr, d);
635 case ICMD_LNEG: /* ..., value ==> ..., - value */
637 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
638 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
639 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
640 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
641 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
642 N_AHI(GET_HIGH_REG(d), -1);
643 emit_store_dst(jd, iptr, d);
646 case ICMD_I2L: /* ..., value ==> ..., value */
648 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
649 if (! N_IS_EVEN_ODD(d)) {
650 d = REG_ITMP31_PACKED;
652 assert(N_IS_EVEN_ODD(d));
654 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
656 M_INTMOVE(s1, GET_HIGH_REG(d));
657 M_SRDA_IMM(32, GET_HIGH_REG(d));
659 emit_copy_dst(jd, iptr, d);
660 emit_store_dst(jd, iptr, d);
663 case ICMD_L2I: /* ..., value ==> ..., value */
664 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
665 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
666 M_INTMOVE(GET_LOW_REG(s1), d);
667 emit_store_dst(jd, iptr, d);
670 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
671 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
672 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
676 emit_store_dst(jd, iptr, d);
679 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
680 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
681 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
685 emit_store_dst(jd, iptr, d);
688 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
690 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
691 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
695 emit_store_dst(jd, iptr, d);
698 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
700 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
701 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
702 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
709 emit_store_dst(jd, iptr, d);
714 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
715 /* sx.val.i = constant */
716 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
717 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
720 if (N_VALID_IMM(iptr->sx.val.i)) {
721 M_IADD_IMM(iptr->sx.val.i, d);
723 ICONST(REG_ITMP2, iptr->sx.val.i);
724 M_IADD(REG_ITMP2, d);
726 emit_store_dst(jd, iptr, d);
729 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
731 /* M, (r, q) -> (r, q) */
733 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
735 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
736 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
737 dd = GET_HIGH_REG(d);
746 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
747 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
757 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
758 N_AHI(GET_HIGH_REG(d), 1);
760 emit_store_dst(jd, iptr, d);
763 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
764 /* sx.val.l = constant */
766 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
767 dd = GET_HIGH_REG(d);
769 s1 = emit_load_s1_high(jd, iptr, dd);
770 s3 = iptr->sx.val.l >> 32;
774 if (N_VALID_IMM(s3)) {
777 ICONST(REG_ITMP3, s3);
778 M_IADD(REG_ITMP3, dd);
782 s1 = emit_load_s1_low(jd, iptr, dd);
783 s3 = iptr->sx.val.l & 0xffffffff;
784 ICONST(REG_ITMP3, s3);
787 N_ALR(dd, REG_ITMP3);
789 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
790 N_AHI(GET_HIGH_REG(d), 1);
792 emit_store_dst(jd, iptr, d);
795 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
797 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
798 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
799 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
801 M_INTMOVE(s1, REG_ITMP1);
802 M_ISUB(s2, REG_ITMP1);
803 M_INTMOVE(REG_ITMP1, d);
808 emit_store_dst(jd, iptr, d);
812 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
813 /* sx.val.i = constant */
815 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
816 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
819 if (N_VALID_IMM(-iptr->sx.val.i)) {
820 M_ISUB_IMM(iptr->sx.val.i, d);
822 ICONST(REG_ITMP2, iptr->sx.val.i);
823 M_ISUB(REG_ITMP2, d);
825 emit_store_dst(jd, iptr, d);
829 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
831 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
833 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
834 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
835 dd = GET_HIGH_REG(d);
838 M_INTMOVE(s2, REG_ITMP3);
845 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
846 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
850 M_INTMOVE(s2, REG_ITMP3);
857 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
858 N_AHI(GET_HIGH_REG(d), -1);
860 emit_store_dst(jd, iptr, d);
863 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
864 /* sx.val.l = constant */
866 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
868 dd = GET_HIGH_REG(d);
869 s1 = emit_load_s1_high(jd, iptr, dd);
870 s3 = iptr->sx.val.l >> 32;
874 if (N_VALID_IMM(-s3)) {
877 ICONST(REG_ITMP3, s3);
878 M_ISUB(REG_ITMP3, dd);
882 s1 = emit_load_s1_low(jd, iptr, dd);
883 s3 = iptr->sx.val.l & 0xffffffff;
884 ICONST(REG_ITMP3, s3);
887 N_SLR(dd, REG_ITMP3);
889 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
890 N_AHI(GET_HIGH_REG(d), -1);
892 emit_store_dst(jd, iptr, d);
895 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
897 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
898 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
899 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
906 emit_store_dst(jd, iptr, d);
910 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
911 /* sx.val.i = constant */
912 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
913 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
915 if (iptr->sx.val.i == 2) {
917 } else if (N_VALID_IMM(iptr->sx.val.i)) {
918 M_IMUL_IMM(iptr->sx.val.i, d);
920 disp = dseg_add_s4(cd, iptr->sx.val.i);
921 M_ILD_DSEG(REG_ITMP2, disp);
922 M_IMUL(REG_ITMP2, d);
924 emit_store_dst(jd, iptr, d);
927 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
928 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
930 /* load s1 into r0 */
932 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
933 M_INTMOVE(s1, GET_HIGH_REG(REG_ITMP31_PACKED));
934 s1 = GET_HIGH_REG(REG_ITMP31_PACKED);
936 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
938 /* extend s1 to long */
940 M_SRDA_IMM(32, GET_HIGH_REG(REG_ITMP31_PACKED));
944 N_DR(GET_HIGH_REG(REG_ITMP31_PACKED), s2);
950 d = codegen_reg_of_dst(jd, iptr, GET_HIGH_REG(REG_ITMP31_PACKED));
951 M_INTMOVE(GET_HIGH_REG(REG_ITMP31_PACKED), d);
954 d = codegen_reg_of_dst(jd, iptr, GET_LOW_REG(REG_ITMP31_PACKED));
955 M_INTMOVE(GET_LOW_REG(REG_ITMP31_PACKED), d);
959 emit_store_dst(jd, iptr, d);
963 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
964 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
966 bte = iptr->sx.s23.s3.bte;
969 /* test s2 for zero */
971 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
972 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
973 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
974 emit_arithmetic_check(cd, iptr, REG_ITMP3);
978 disp = dseg_add_functionptr(cd, bte->fp);
982 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
984 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
985 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
989 M_ASUB_IMM(96, REG_SP);
990 M_ALD_DSEG(REG_ITMP2, disp);
991 M_JSR(REG_RA, REG_ITMP2);
992 M_AADD_IMM(96, REG_SP);
996 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
997 M_LNGMOVE(REG_RESULT_PACKED, d);
998 emit_store_dst(jd, iptr, d);
1002 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1003 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1004 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1006 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1007 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1008 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1010 /* Use only 5 bits of sencond operand. */
1012 M_INTMOVE(s2, REG_ITMP2);
1014 ICONST(REG_ITMP3, 0x1F);
1015 M_IAND(REG_ITMP3, s2);
1019 switch (iptr->opc) {
1032 emit_store_dst(jd, iptr, d);
1035 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1036 /* sx.val.i = constant */
1040 assert(iptr->sx.val.i <= 32);
1042 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1043 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1050 s3 = (1 << iptr->sx.val.i) - 1;
1052 if (N_VALID_IMM(s3)) {
1055 ICONST(REG_ITMP1, -1);
1056 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1057 M_IADD(REG_ITMP1, d);
1060 N_BRC_BACK_PATCH(ref);
1062 M_SRA_IMM(iptr->sx.val.i, d);
1064 emit_store_dst(jd, iptr, d);
1069 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1070 /* sx.val.i = constant */
1072 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1073 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1076 M_MOV(s1, REG_ITMP1);
1080 ICONST(REG_ITMP3, iptr->sx.val.i);
1083 M_IAND(REG_ITMP3, d);
1086 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1092 emit_store_dst(jd, iptr, d);
1096 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1097 /* sx.val.i = constant */
1098 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1099 /* sx.val.i = constant */
1100 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1101 /* sx.val.i = constant */
1102 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1103 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1107 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1109 switch (iptr->opc) {
1110 case ICMD_ISHLCONST:
1113 case ICMD_ISHRCONST:
1116 case ICMD_IUSHRCONST:
1123 emit_store_dst(jd, iptr, d);
1126 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1128 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1130 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1132 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1134 /* Use only 6 bits of second operand */
1136 M_INTMOVE(s2, REG_ITMP2);
1138 ICONST(REG_ITMP1, 0x3F);
1139 M_IAND(REG_ITMP1, s2);
1141 s1 = emit_load_s1(jd, iptr, REG_ITMP31_PACKED); /* even-odd pair */
1142 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED);
1144 /* Destination must be even-odd pair */
1146 if (! N_IS_EVEN_ODD(d)) {
1147 d = REG_ITMP31_PACKED;
1150 assert(N_IS_EVEN_ODD(d));
1154 switch (iptr->opc) {
1156 M_SLDL(s2, GET_HIGH_REG(d));
1159 M_SRDA(s2, GET_HIGH_REG(d));
1162 M_SRDL(s2, GET_HIGH_REG(d));
1168 emit_copy_dst(jd, iptr, d);
1169 emit_store_dst(jd, iptr, d);
1173 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1174 /* sx.val.i = constant */
1175 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1176 /* sx.val.i = constant */
1177 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1178 /* sx.val.l = constant */
1181 d = codegen_reg_of_dst(jd, iptr, REG_ITMP31_PACKED); /* even-odd */
1182 if (! N_IS_EVEN_ODD(d)) {
1183 d = REG_ITMP31_PACKED;
1185 assert(N_IS_EVEN_ODD(d));
1187 s1 = emit_load_s1(jd, iptr, d);
1191 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1193 switch (iptr->opc) {
1194 case ICMD_LSHLCONST:
1195 N_SLDL(GET_HIGH_REG(d), disp, RN);
1197 case ICMD_LSHRCONST:
1198 N_SRDA(GET_HIGH_REG(d), disp, RN);
1200 case ICMD_LUSHRCONST:
1201 N_SRDL(GET_HIGH_REG(d), disp, RN);
1204 N_SLDL(GET_HIGH_REG(d), disp, RN);
1210 emit_copy_dst(jd, iptr, d);
1211 emit_store_dst(jd, iptr, d);
1214 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1216 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1217 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1218 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1225 emit_store_dst(jd, iptr, d);
1229 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1231 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1232 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1233 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1240 emit_store_dst(jd, iptr, d);
1244 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1246 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1247 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1248 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1255 emit_store_dst(jd, iptr, d);
1261 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1262 /* sx.val.i = constant */
1263 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1264 /* sx.val.i = constant */
1265 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1266 /* sx.val.i = constant */
1268 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1269 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1272 ICONST(REG_ITMP2, iptr->sx.val.i);
1274 switch (iptr->opc) {
1275 case ICMD_IANDCONST:
1276 M_IAND(REG_ITMP2, d);
1278 case ICMD_IXORCONST:
1279 M_IXOR(REG_ITMP2, d);
1282 M_IOR(REG_ITMP2, d);
1288 emit_store_dst(jd, iptr, d);
1292 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1293 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1294 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1296 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1298 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1299 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1300 dd = GET_LOW_REG(d);
1302 switch (iptr->opc) {
1331 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1332 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1333 dd = GET_HIGH_REG(d);
1335 switch (iptr->opc) {
1364 emit_store_dst(jd, iptr, d);
1367 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1368 /* sx.val.l = constant */
1369 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1370 /* sx.val.l = constant */
1371 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1372 /* sx.val.l = constant */
1374 /* TODO should use memory operand to access data segment, not load */
1376 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1378 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1379 s3 = iptr->sx.val.l & 0xffffffff;
1381 M_INTMOVE(s1, GET_LOW_REG(d));
1383 ICONST(REG_ITMP3, s3);
1385 switch (iptr->opc) {
1386 case ICMD_LANDCONST:
1387 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1389 case ICMD_LXORCONST:
1390 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1393 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1399 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1400 s3 = iptr->sx.val.l >> 32;
1402 M_INTMOVE(s1, GET_HIGH_REG(d));
1404 ICONST(REG_ITMP3, s3);
1406 switch (iptr->opc) {
1407 case ICMD_LANDCONST:
1408 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1410 case ICMD_LXORCONST:
1411 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1414 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1420 emit_store_dst(jd, iptr, d);
1424 /* floating operations ************************************************/
1426 case ICMD_FNEG: /* ..., value ==> ..., - value */
1427 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1428 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1430 emit_store_dst(jd, iptr, d);
1433 case ICMD_DNEG: /* ..., value ==> ..., - value */
1434 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1435 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1437 emit_store_dst(jd, iptr, d);
1440 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1441 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1442 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1443 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1450 emit_store_dst(jd, iptr, d);
1453 case ICMD_DADD: /* ..., 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_FTMP1);
1463 emit_store_dst(jd, iptr, d);
1466 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1467 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1468 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1469 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1473 emit_store_dst(jd, iptr, d);
1476 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1477 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1478 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1479 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1483 emit_store_dst(jd, iptr, d);
1486 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1487 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1488 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1489 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1496 emit_store_dst(jd, iptr, d);
1499 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1500 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1501 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1502 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1509 emit_store_dst(jd, iptr, d);
1512 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1513 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1514 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1515 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1519 emit_store_dst(jd, iptr, d);
1522 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1523 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1524 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1525 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1529 emit_store_dst(jd, iptr, d);
1532 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1533 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1534 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1536 emit_store_dst(jd, iptr, d);
1539 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1540 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1541 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1543 emit_store_dst(jd, iptr, d);
1546 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1550 #ifdef SUPPORT_HERCULES
1554 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1555 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1559 switch (iptr->opc) {
1568 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1569 N_LHI(d, 0); /* Load 0 */
1570 ref1 = cd->mcodeptr;
1571 N_BRC(DD_ANY, 0); /* Exit */
1575 switch (iptr->opc) {
1584 #ifdef SUPPORT_HERCULES
1585 /* Hercules does the conversion using a plain C conversion.
1586 * According to manual, real hardware should *NOT* require this.
1588 * Corner case: Positive float leads to INT_MIN (overflow).
1591 switch (iptr->opc) {
1600 ref2 = cd->mcodeptr;
1601 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1605 ref3 = cd->mcodeptr;
1606 M_BGE(0); /* If integer result is negative, continue */
1608 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1609 M_ILD_DSEG(d, disp);
1611 N_BRC_BACK_PATCH(ref1);
1612 #ifdef SUPPORT_HERCULES
1613 N_BRC_BACK_PATCH(ref2);
1614 N_BRC_BACK_PATCH(ref3);
1616 emit_store_dst(jd, iptr, d);
1620 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1623 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1624 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1625 #ifdef SUPPORT_HERCULES
1628 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1629 disp = dseg_add_double(cd, 0.0 / 0.0);
1630 M_DLD_DSEG(d, disp, REG_ITMP1);
1631 emit_label_br(cd, BRANCH_LABEL_1);
1632 N_BRC_BACK_PATCH(ref);
1635 #ifdef SUPPORT_HERCULES
1636 emit_label(cd, BRANCH_LABEL_1);
1638 emit_store_dst(jd, iptr, d);
1642 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1643 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1644 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1646 emit_store_dst(jd, iptr, d);
1649 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1650 /* == => 0, < => 1, > => -1 */
1654 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1655 /* == => 0, < => 1, > => -1 */
1658 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1659 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1660 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1662 switch (iptr->opc) {
1674 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1675 SZ_BRC + SZ_BRC + SZ_BRC
1678 N_BRC( /* load -1 */
1679 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1680 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1685 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1688 N_LHI(d, 1); /* GT */
1689 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1690 N_LHI(d, -1); /* LT */
1691 M_BR(SZ_BRC + SZ_LHI);
1692 N_LHI(d, 0); /* EQ */
1694 emit_store_dst(jd, iptr, d);
1699 /* memory operations **************************************************/
1701 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1703 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1704 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1706 /* implicit null-pointer check */
1707 M_ILD(d, s1, OFFSET(java_array_t, size));
1708 emit_store_dst(jd, iptr, d);
1712 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1713 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1714 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1715 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1717 /* implicit null-pointer check */
1718 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1720 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1725 emit_store_dst(jd, iptr, d);
1728 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1730 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1731 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1732 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1734 /* implicit null-pointer check */
1735 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1737 M_INTMOVE(s2, REG_ITMP2);
1738 M_SLL_IMM(1, REG_ITMP2);
1740 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1742 /* N_LH does sign extends, undo ! */
1747 emit_store_dst(jd, iptr, d);
1750 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1751 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1752 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1753 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1755 /* implicit null-pointer check */
1756 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1758 M_INTMOVE(s2, REG_ITMP2);
1759 M_SLL_IMM(1, REG_ITMP2);
1761 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1762 emit_store_dst(jd, iptr, d);
1765 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1766 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1767 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1768 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1770 /* implicit null-pointer check */
1771 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1773 M_INTMOVE(s2, REG_ITMP2);
1774 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1775 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1776 emit_store_dst(jd, iptr, d);
1779 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1781 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1782 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1784 d = codegen_reg_of_dst(jd, iptr, REG_ITMP13_PACKED);
1786 /* implicit null-pointer check */
1787 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1789 M_INTMOVE(s2, REG_ITMP2);
1790 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1793 GET_LOW_REG(d) /* maybe itmp3 */,
1794 OFFSET(java_intarray_t, data[0]) + 4,
1795 REG_ITMP2, s1 /* maybe itmp1 */
1799 GET_HIGH_REG(d) /* maybe itmp1 */,
1800 OFFSET(java_intarray_t, data[0]),
1801 REG_ITMP2, s1 /* maybe itmp1 */
1804 emit_store_dst(jd, iptr, d);
1808 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1810 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1811 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1812 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1814 /* implicit null-pointer check */
1815 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1817 M_INTMOVE(s2, REG_ITMP2);
1818 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1820 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1822 emit_store_dst(jd, iptr, d);
1825 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1826 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1827 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1828 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1830 /* implicit null-pointer check */
1831 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1833 M_INTMOVE(s2, REG_ITMP2);
1834 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1836 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1838 emit_store_dst(jd, iptr, d);
1841 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1842 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1843 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1844 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1846 /* implicit null-pointer check */
1847 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1849 M_INTMOVE(s2, REG_ITMP2);
1850 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1851 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1852 emit_store_dst(jd, iptr, d);
1855 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1856 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1857 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1858 /* implicit null-pointer check */
1859 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1860 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1862 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1865 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1867 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1868 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1869 /* implicit null-pointer check */
1870 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1871 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1873 M_INTMOVE(s2, REG_ITMP2);
1874 M_SLL_IMM(1, REG_ITMP2);
1876 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1880 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1881 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1882 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1883 /* implicit null-pointer check */
1884 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1885 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1887 M_INTMOVE(s2, REG_ITMP2);
1888 M_SLL_IMM(1, REG_ITMP2);
1890 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1893 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1895 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1896 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1897 /* implicit null-pointer check */
1898 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1900 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1902 M_INTMOVE(s2, REG_ITMP2);
1903 M_SLL_IMM(2, REG_ITMP2);
1905 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1908 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1910 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1911 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1912 /* implicit null-pointer check */
1913 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1915 M_INTMOVE(s2, REG_ITMP2);
1916 M_SLL_IMM(3, REG_ITMP2);
1918 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1919 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1920 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1921 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1924 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1925 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1926 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1927 /* implicit null-pointer check */
1928 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1929 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1931 M_INTMOVE(s2, REG_ITMP2);
1932 M_SLL_IMM(2, REG_ITMP2);
1934 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1937 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1938 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1939 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1940 /* implicit null-pointer check */
1941 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1942 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1944 M_INTMOVE(s2, REG_ITMP2);
1945 M_SLL_IMM(3, REG_ITMP2);
1947 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1950 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1952 s1 = emit_load_s1(jd, iptr, REG_A0);
1953 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1954 /* implicit null-pointer check */
1955 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1956 s3 = emit_load_s3(jd, iptr, REG_A1);
1958 M_INTMOVE(s1, REG_A0);
1959 M_INTMOVE(s3, REG_A1);
1961 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1962 M_ALD_DSEG(REG_ITMP2, disp);
1963 M_ASUB_IMM(96, REG_SP);
1964 M_JSR(REG_RA, REG_ITMP2);
1965 M_AADD_IMM(96, REG_SP);
1967 emit_arraystore_check(cd, iptr);
1969 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1970 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1971 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1973 M_INTMOVE(s2, REG_ITMP2);
1974 M_SLL_IMM(2, REG_ITMP2);
1975 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1978 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1979 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1984 case ICMD_GETSTATIC: /* ... ==> ..., value */
1986 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1987 uf = iptr->sx.s23.s3.uf;
1988 fieldtype = uf->fieldref->parseddesc.fd->type;
1989 disp = dseg_add_unique_address(cd, NULL);
1991 /* PROFILE_CYCLE_STOP; */
1993 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
1995 /* PROFILE_CYCLE_START; */
1998 fi = iptr->sx.s23.s3.fmiref->p.field;
1999 fieldtype = fi->type;
2000 disp = dseg_add_address(cd, fi->value);
2002 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2005 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
2007 PROFILE_CYCLE_START;
2011 M_ALD_DSEG(REG_ITMP1, disp);
2013 switch (fieldtype) {
2015 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2016 M_ILD(d, REG_ITMP1, 0);
2019 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2020 M_LLD(d, REG_ITMP1, 0);
2023 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2024 M_ALD(d, REG_ITMP1, 0);
2027 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2028 M_FLD(d, REG_ITMP1, 0);
2031 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2032 M_DLD(d, REG_ITMP1, 0);
2036 emit_store_dst(jd, iptr, d);
2040 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2042 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2043 uf = iptr->sx.s23.s3.uf;
2044 fieldtype = uf->fieldref->parseddesc.fd->type;
2045 disp = dseg_add_unique_address(cd, uf);
2047 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2050 fi = iptr->sx.s23.s3.fmiref->p.field;
2051 fieldtype = fi->type;
2052 disp = dseg_add_address(cd, fi->value);
2054 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2056 patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
2057 PROFILE_CYCLE_START;
2061 M_ALD_DSEG(REG_ITMP1, disp);
2062 switch (fieldtype) {
2064 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2065 M_IST(s1, REG_ITMP1, 0);
2068 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2069 M_LST(s1, REG_ITMP1, 0);
2072 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2073 M_AST(s1, REG_ITMP1, 0);
2076 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2077 M_FST(s1, REG_ITMP1, 0);
2080 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2081 M_DST(s1, REG_ITMP1, 0);
2086 case ICMD_GETFIELD: /* ... ==> ..., value */
2088 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2089 emit_nullpointer_check(cd, iptr, s1);
2091 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2092 uf = iptr->sx.s23.s3.uf;
2093 fieldtype = uf->fieldref->parseddesc.fd->type;
2096 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2099 fi = iptr->sx.s23.s3.fmiref->p.field;
2100 fieldtype = fi->type;
2104 switch (fieldtype) {
2106 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2110 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2111 if (GET_HIGH_REG(d) == s1) {
2112 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2113 M_ILD(GET_HIGH_REG(d), s1, disp);
2116 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2117 M_ILD(GET_HIGH_REG(d), s1, disp);
2121 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2125 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2129 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2133 emit_store_dst(jd, iptr, d);
2136 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2140 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2141 emit_nullpointer_check(cd, iptr, s1);
2143 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2144 uf = iptr->sx.s23.s3.uf;
2145 fieldtype = uf->fieldref->parseddesc.fd->type;
2149 fi = iptr->sx.s23.s3.fmiref->p.field;
2150 fieldtype = fi->type;
2154 /* We can't add a patcher ref behind this load,
2155 * because the patcher would destroy REG_ITMP3.
2157 * We pass in the disp parameter, how many bytes
2158 * to skip to the to the actual store.
2160 * XXX this relies on patcher_add_patch_ref internals
2163 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2164 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2169 if (IS_INT_LNG_TYPE(fieldtype)) {
2170 if (IS_2_WORD_TYPE(fieldtype))
2171 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2173 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2175 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2178 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2179 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2182 switch (fieldtype) {
2184 M_IST(s2, s1, disp);
2187 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2188 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2191 M_AST(s2, s1, disp);
2194 M_FST(s2, s1, disp);
2197 M_DST(s2, s1, disp);
2204 /* branch operations **************************************************/
2206 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2208 /* PROFILE_CYCLE_STOP; */
2210 s1 = emit_load_s1(jd, iptr, REG_ITMP3);
2211 M_INTMOVE(s1, REG_ITMP3_XPTR);
2213 #ifdef ENABLE_VERIFIER
2214 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2215 uc = iptr->sx.s23.s2.uc;
2217 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2219 #endif /* ENABLE_VERIFIER */
2221 disp = dseg_add_functionptr(cd, asm_handle_exception);
2222 M_ALD_DSEG(REG_ITMP1, disp);
2223 M_JMP(REG_ITMP1_XPC, REG_ITMP1);
2228 case ICMD_GOTO: /* ... ==> ... */
2229 case ICMD_RET: /* ... ==> ... */
2231 emit_br(cd, iptr->dst.block);
2235 case ICMD_JSR: /* ... ==> ... */
2237 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2241 case ICMD_IFNULL: /* ..., value ==> ... */
2242 case ICMD_IFNONNULL: /* ..., value ==> ... */
2243 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2245 switch (iptr->opc) {
2247 emit_beq(cd, iptr->dst.block);
2249 case ICMD_IFNONNULL:
2250 emit_bne(cd, iptr->dst.block);
2255 case ICMD_IFEQ: /* ..., value ==> ... */
2256 case ICMD_IFLT: /* ..., value ==> ... */
2257 case ICMD_IFLE: /* ..., value ==> ... */
2258 case ICMD_IFNE: /* ..., value ==> ... */
2259 case ICMD_IFGT: /* ..., value ==> ... */
2260 case ICMD_IFGE: /* ..., value ==> ... */
2262 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2264 if (N_VALID_IMM(iptr->sx.val.i))
2265 M_ICMP_IMM(s1, iptr->sx.val.i);
2267 disp = dseg_add_s4(cd, iptr->sx.val.i);
2268 if (N_VALID_DSEG_DISP(disp)) {
2269 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2271 ICONST(REG_ITMP2, disp);
2272 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2276 switch (iptr->opc) {
2278 emit_blt(cd, iptr->dst.block);
2281 emit_ble(cd, iptr->dst.block);
2284 emit_bne(cd, iptr->dst.block);
2287 emit_bgt(cd, iptr->dst.block);
2290 emit_bge(cd, iptr->dst.block);
2293 emit_beq(cd, iptr->dst.block);
2299 case ICMD_IF_LLT: /* ..., value ==> ... */
2300 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2306 /* ATTENTION: compare high words signed and low words unsigned */
2308 # define LABEL_OUT BRANCH_LABEL_1
2310 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2312 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2313 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2315 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2316 if (N_VALID_DSEG_DISP(disp)) {
2317 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2319 ICONST(REG_ITMP2, disp);
2320 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2327 emit_blt(cd, iptr->dst.block);
2328 /* EQ ... fall through */
2329 emit_label_bgt(cd, LABEL_OUT);
2333 emit_bgt(cd, iptr->dst.block);
2334 /* EQ ... fall through */
2335 emit_label_blt(cd, LABEL_OUT);
2338 /* EQ ... fall through */
2339 emit_label_bne(cd, LABEL_OUT);
2342 /* EQ ... fall through */
2343 emit_bne(cd, iptr->dst.block);
2349 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2351 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2352 if (N_VALID_DSEG_DISP(disp)) {
2353 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2355 ICONST(REG_ITMP2, disp);
2356 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2361 emit_blt(cd, iptr->dst.block);
2362 emit_label(cd, LABEL_OUT);
2365 emit_ble(cd, iptr->dst.block);
2366 emit_label(cd, LABEL_OUT);
2369 emit_bgt(cd, iptr->dst.block);
2370 emit_label(cd, LABEL_OUT);
2373 emit_bge(cd, iptr->dst.block);
2374 emit_label(cd, LABEL_OUT);
2377 emit_beq(cd, iptr->dst.block);
2378 emit_label(cd, LABEL_OUT);
2381 emit_bne(cd, iptr->dst.block);
2390 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2391 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2393 /* Compare addresses as 31 bit unsigned integers */
2395 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2396 M_LDA(REG_ITMP1, s1, 0);
2398 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2399 M_LDA(REG_ITMP2, s2, 0);
2401 M_CMP(REG_ITMP1, REG_ITMP2);
2403 switch (iptr->opc) {
2404 case ICMD_IF_ACMPEQ:
2405 emit_beq(cd, iptr->dst.block);
2407 case ICMD_IF_ACMPNE:
2408 emit_bne(cd, iptr->dst.block);
2414 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2415 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2416 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2417 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2418 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2419 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2421 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2422 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2424 switch (iptr->opc) {
2425 case ICMD_IF_ICMPEQ:
2426 emit_beq(cd, iptr->dst.block);
2428 case ICMD_IF_ICMPNE:
2429 emit_bne(cd, iptr->dst.block);
2431 case ICMD_IF_ICMPLT:
2432 emit_blt(cd, iptr->dst.block);
2434 case ICMD_IF_ICMPGT:
2435 emit_bgt(cd, iptr->dst.block);
2437 case ICMD_IF_ICMPLE:
2438 emit_ble(cd, iptr->dst.block);
2440 case ICMD_IF_ICMPGE:
2441 emit_bge(cd, iptr->dst.block);
2447 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2448 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2449 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2450 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2451 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2452 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2457 /* ATTENTION: compare high words signed and low words unsigned */
2459 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2460 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2465 case ICMD_IF_LCMPLT:
2466 case ICMD_IF_LCMPLE:
2467 emit_blt(cd, iptr->dst.block);
2468 /* EQ ... fall through */
2469 out_ref = cd->mcodeptr;
2472 case ICMD_IF_LCMPGT:
2473 case ICMD_IF_LCMPGE:
2474 emit_bgt(cd, iptr->dst.block);
2475 /* EQ ... fall through */
2476 out_ref = cd->mcodeptr;
2479 case ICMD_IF_LCMPEQ:
2480 /* EQ ... fall through */
2481 out_ref = cd->mcodeptr;
2484 case ICMD_IF_LCMPNE:
2485 /* EQ ... fall through */
2486 emit_bne(cd, iptr->dst.block);
2492 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2493 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2498 case ICMD_IF_LCMPLT:
2499 emit_blt(cd, iptr->dst.block);
2501 case ICMD_IF_LCMPLE:
2502 emit_ble(cd, iptr->dst.block);
2504 case ICMD_IF_LCMPGT:
2505 emit_bgt(cd, iptr->dst.block);
2507 case ICMD_IF_LCMPGE:
2508 emit_bge(cd, iptr->dst.block);
2510 case ICMD_IF_LCMPEQ:
2511 emit_beq(cd, iptr->dst.block);
2513 case ICMD_IF_LCMPNE:
2514 emit_bne(cd, iptr->dst.block);
2520 if (out_ref != NULL) {
2521 N_BRC_BACK_PATCH(out_ref);
2527 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2529 REPLACEMENT_POINT_RETURN(cd, iptr);
2530 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2531 M_INTMOVE(s1, REG_RESULT);
2532 goto nowperformreturn;
2534 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2536 REPLACEMENT_POINT_RETURN(cd, iptr);
2537 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2538 M_INTMOVE(s1, REG_RESULT);
2540 #ifdef ENABLE_VERIFIER
2541 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2542 unresolved_class *uc = iptr->sx.s23.s2.uc;
2545 patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
2546 PROFILE_CYCLE_START;
2548 #endif /* ENABLE_VERIFIER */
2549 goto nowperformreturn;
2551 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2553 REPLACEMENT_POINT_RETURN(cd, iptr);
2554 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2555 M_LNGMOVE(s1, REG_RESULT_PACKED);
2556 goto nowperformreturn;
2558 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2561 REPLACEMENT_POINT_RETURN(cd, iptr);
2562 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2563 M_FLTMOVE(s1, REG_FRESULT);
2564 goto nowperformreturn;
2566 case ICMD_RETURN: /* ... ==> ... */
2568 REPLACEMENT_POINT_RETURN(cd, iptr);
2574 p = cd->stackframesize;
2576 /* call trace function */
2578 #if !defined(NDEBUG)
2579 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2580 emit_verbosecall_exit(jd);
2581 #endif /* !defined(NDEBUG) */
2583 #if defined(ENABLE_THREADS)
2584 if (checksync && code_is_synchronized(code)) {
2585 /* we need to save the proper return value */
2587 switch (iptr->opc) {
2589 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2593 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2596 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2599 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2603 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2605 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2606 M_ALD_DSEG(REG_ITMP2, disp);
2608 M_ASUB_IMM(96, REG_SP);
2610 M_AADD_IMM(96, REG_SP);
2612 /* and now restore the proper return value */
2614 switch (iptr->opc) {
2616 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2620 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2623 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2626 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2632 /* restore return address */
2634 p--; M_ALD(REG_RA, REG_SP, p * 8);
2636 /* restore saved registers */
2638 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2639 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2641 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2642 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2645 /* deallocate stack */
2647 if (cd->stackframesize)
2648 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2650 /* generate method profiling code */
2658 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2661 branch_target_t *table;
2663 table = iptr->dst.table;
2665 l = iptr->sx.s23.s2.tablelow;
2666 i = iptr->sx.s23.s3.tablehigh;
2668 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2669 M_INTMOVE(s1, REG_ITMP1);
2673 } else if (N_VALID_IMM(-l)) {
2674 M_ISUB_IMM(l, REG_ITMP1);
2676 ICONST(REG_ITMP2, l);
2677 M_ISUB(REG_ITMP2, REG_ITMP1);
2680 /* number of targets */
2686 ICONST(REG_ITMP2, i);
2687 M_ICMPU(REG_ITMP1, REG_ITMP2);
2688 emit_bge(cd, table[0].block);
2690 /* build jump table top down and use address of lowest entry */
2695 dseg_add_target(cd, table->block);
2700 /* length of dataseg after last dseg_add_target is used by load */
2702 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2703 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2704 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2705 M_JMP(RN, REG_ITMP1);
2710 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2713 lookup_target_t *lookup;
2715 lookup = iptr->dst.lookup;
2717 i = iptr->sx.s23.s2.lookupcount;
2719 MCODECHECK(8 + ((7 + 6) * i) + 5);
2720 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2723 if (N_VALID_IMM(lookup->value)) {
2724 M_ICMP_IMM(s1, lookup->value);
2726 ICONST(REG_ITMP2, lookup->value);
2727 M_ICMP(REG_ITMP2, s1);
2729 emit_beq(cd, lookup->target.block);
2733 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2738 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2740 bte = iptr->sx.s23.s3.bte;
2744 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2745 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2746 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2747 case ICMD_INVOKEINTERFACE:
2749 REPLACEMENT_POINT_INVOKE(cd, iptr);
2751 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2753 um = iptr->sx.s23.s3.um;
2754 md = um->methodref->parseddesc.md;
2757 lm = iptr->sx.s23.s3.fmiref->p.method;
2759 md = lm->parseddesc;
2763 s3 = md->paramcount;
2765 MCODECHECK((s3 << 1) + 64);
2767 /* copy arguments to registers or stack location */
2769 for (s3 = s3 - 1; s3 >= 0; s3--) {
2770 var = VAR(iptr->sx.s23.s2.args[s3]);
2772 /* Already Preallocated? */
2773 if (var->flags & PREALLOC)
2776 if (IS_INT_LNG_TYPE(var->type)) {
2777 if (!md->params[s3].inmemory) {
2778 if (IS_2_WORD_TYPE(var->type)) {
2780 GET_LOW_REG(md->params[s3].regoff),
2781 GET_HIGH_REG(md->params[s3].regoff)
2783 d = emit_load(jd, iptr, var, s1);
2787 s1 = md->params[s3].regoff;
2788 d = emit_load(jd, iptr, var, s1);
2793 if (IS_2_WORD_TYPE(var->type)) {
2794 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2795 M_LST(d, REG_SP, md->params[s3].regoff);
2798 d = emit_load(jd, iptr, var, REG_ITMP1);
2799 M_IST(d, REG_SP, md->params[s3].regoff);
2804 if (!md->params[s3].inmemory) {
2805 s1 = md->params[s3].regoff;
2806 d = emit_load(jd, iptr, var, s1);
2810 d = emit_load(jd, iptr, var, REG_FTMP1);
2811 if (IS_2_WORD_TYPE(var->type))
2812 M_DST(d, REG_SP, md->params[s3].regoff);
2814 M_FST(d, REG_SP, md->params[s3].regoff);
2819 /* generate method profiling code */
2823 switch (iptr->opc) {
2825 if (bte->stub == NULL) {
2826 disp = dseg_add_functionptr(cd, bte->fp);
2827 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2829 disp = dseg_add_functionptr(cd, bte->stub);
2832 if (N_VALID_DSEG_DISP(disp)) {
2833 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2835 N_LHI(REG_ITMP1, disp);
2836 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2840 case ICMD_INVOKESPECIAL:
2842 /* Implicit NULL pointer check */
2843 M_ILD(REG_ITMP1, REG_A0, 0);
2847 case ICMD_INVOKESTATIC:
2849 disp = dseg_add_unique_address(cd, um);
2851 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2855 disp = dseg_add_address(cd, lm->stubroutine);
2857 if (N_VALID_DSEG_DISP(disp)) {
2858 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2860 N_LHI(REG_ITMP1, disp);
2861 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2865 case ICMD_INVOKEVIRTUAL:
2866 /* TODO softnull REG_A0 */
2869 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2874 s1 = OFFSET(vftbl_t, table[0]) +
2875 sizeof(methodptr) * lm->vftblindex;
2878 /* implicit null-pointer check */
2880 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2881 M_ALD(REG_PV, REG_METHODPTR, s1);
2884 case ICMD_INVOKEINTERFACE:
2885 /* TODO softnull REG_A0 */
2887 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2888 * and -0xFFF in index register (itmp1)
2892 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2898 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2899 sizeof(methodptr*) * lm->class->index;
2901 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2904 /* Implicit null-pointer check */
2905 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2906 N_LHI(REG_ITMP2, s1);
2907 N_L(REG_METHODPTR, 0, REG_ITMP2, REG_METHODPTR);
2908 M_ALD(REG_PV, REG_METHODPTR, s2);
2912 /* generate the actual call */
2915 emit_restore_pv(cd);
2917 /* post call finalization */
2919 switch (iptr->opc) {
2921 if (bte->stub == NULL) {
2922 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2927 /* generate method profiling code */
2929 PROFILE_CYCLE_START;
2931 /* store size of call code in replacement point */
2933 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2935 /* store return value */
2937 d = md->returntype.type;
2939 if (d != TYPE_VOID) {
2940 if (IS_INT_LNG_TYPE(d)) {
2941 if (IS_2_WORD_TYPE(d)) {
2942 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2943 M_LNGMOVE(REG_RESULT_PACKED, s1);
2946 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2947 M_INTMOVE(REG_RESULT, s1);
2951 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2952 M_FLTMOVE(REG_FRESULT, s1);
2954 emit_store_dst(jd, iptr, s1);
2960 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2962 /* val.a: (classinfo*) superclass */
2964 /* superclass is an interface:
2966 * OK if ((sub == NULL) ||
2967 * (sub->vftbl->interfacetablelength > super->index) &&
2968 * (sub->vftbl->interfacetable[-super->index] != NULL));
2970 * superclass is a class:
2972 * OK if ((sub == NULL) || (0
2973 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2974 * super->vftbl->diffval));
2977 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2978 /* object type cast-check */
2981 vftbl_t *supervftbl;
2984 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2985 # define LABEL_CLASS BRANCH_LABEL_2
2986 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2987 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2988 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2990 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2996 super = iptr->sx.s23.s3.c.cls;
2997 superindex = super->index;
2998 supervftbl = super->vftbl;
3001 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3002 CODEGEN_CRITICAL_SECTION_NEW;
3004 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3006 /* if class is not resolved, check which code to call */
3008 if (super == NULL) {
3010 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3012 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3014 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3015 iptr->sx.s23.s3.c.ref,
3018 ICONST(REG_ITMP3, ACC_INTERFACE);
3020 if (N_VALID_DSEG_DISP(disp)) {
3021 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3023 ICONST(REG_ITMP2, disp);
3024 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3026 emit_label_beq(cd, LABEL_CLASS);
3029 /* interface checkcast code */
3031 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3032 if (super == NULL) {
3033 patcher_add_patch_ref(jd,
3034 PATCHER_checkcast_instanceof_interface,
3035 iptr->sx.s23.s3.c.ref,
3039 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3042 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3043 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3044 M_ISUB_IMM(superindex, REG_ITMP3);
3045 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3048 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3049 superindex * sizeof(methodptr*))
3051 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3052 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3054 if (super == NULL) {
3055 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3059 /* class checkcast code */
3061 if (super == NULL) {
3062 emit_label(cd, LABEL_CLASS);
3065 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3066 if (super == NULL) {
3067 disp = dseg_add_unique_address(cd, NULL);
3069 patcher_add_patch_ref(jd,
3070 PATCHER_resolve_classref_to_vftbl,
3071 iptr->sx.s23.s3.c.ref,
3075 disp = dseg_add_address(cd, supervftbl);
3077 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3081 CODEGEN_CRITICAL_SECTION_START;
3083 /* REG_ITMP3 := baseval(s1) */
3084 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3085 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3087 /* REG_ITMP2 := baseval(class) */
3088 M_ALD_DSEG(REG_ITMP2, disp);
3089 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3091 /* REG_ITMP3 := REG_ITMP3 - REG_ITMP2 */
3092 M_ISUB(REG_ITMP2, REG_ITMP3);
3094 /* REG_ITMP2 := diffval(class) */
3095 M_ALD_DSEG(REG_ITMP2, disp);
3096 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3098 CODEGEN_CRITICAL_SECTION_END;
3100 M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
3102 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3103 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3104 /* Branch if greater then */
3106 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3107 M_ALD_DSEG(REG_ITMP3, disp);
3109 CODEGEN_CRITICAL_SECTION_START;
3111 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3112 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3113 M_ISUB(REG_ITMP3, REG_ITMP2);
3114 M_ALD_DSEG(REG_ITMP3, disp);
3115 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3117 CODEGEN_CRITICAL_SECTION_END;
3119 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3120 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3121 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3122 /* Branch if greater then */
3124 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3127 if (super == NULL) {
3128 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3129 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3130 } else if (super->flags & ACC_INTERFACE) {
3131 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3133 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3136 d = codegen_reg_of_dst(jd, iptr, s1);
3138 # undef LABEL_EXIT_CHECK_NULL
3140 # undef LABEL_EXIT_INTERFACE_NULL
3141 # undef LABEL_EXIT_INTERFACE_DONE
3142 # undef LABEL_EXIT_CLASS_NULL
3145 /* array type cast-check */
3147 s1 = emit_load_s1(jd, iptr, REG_A0);
3148 M_INTMOVE(s1, REG_A0);
3150 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3151 disp = dseg_add_unique_address(cd, NULL);
3153 patcher_add_patch_ref(jd,
3154 PATCHER_resolve_classref_to_classinfo,
3155 iptr->sx.s23.s3.c.ref,
3159 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3161 M_ALD_DSEG(REG_A1, disp);
3162 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3163 M_ALD_DSEG(REG_ITMP1, disp);
3164 M_ASUB_IMM(96, REG_SP);
3165 M_JSR(REG_RA, REG_ITMP1);
3166 M_AADD_IMM(96, REG_SP);
3168 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3169 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3171 d = codegen_reg_of_dst(jd, iptr, s1);
3175 emit_store_dst(jd, iptr, d);
3178 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3179 /* val.a: (classinfo*) superclass */
3181 /* superclass is an interface:
3183 * return (sub != NULL) &&
3184 * (sub->vftbl->interfacetablelength > super->index) &&
3185 * (sub->vftbl->interfacetable[-super->index] != NULL);
3187 * superclass is a class:
3189 * return ((sub != NULL) && (0
3190 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3191 * super->vftbl->diffvall));
3193 * If superclass is unresolved, we include both code snippets
3194 * above, a patcher resolves the class' flags and we select
3195 * the right code at runtime.
3200 vftbl_t *supervftbl;
3203 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3209 super = iptr->sx.s23.s3.c.cls;
3210 superindex = super->index;
3211 supervftbl = super->vftbl;
3214 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3215 # define LABEL_CLASS BRANCH_LABEL_2
3216 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3217 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3218 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3219 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3221 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3222 CODEGEN_CRITICAL_SECTION_NEW;
3224 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3225 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3227 M_MOV(s1, REG_ITMP1);
3231 /* if class is not resolved, check which code to call */
3233 if (super == NULL) {
3237 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3239 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3241 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3242 iptr->sx.s23.s3.c.ref, disp);
3244 ICONST(REG_ITMP3, ACC_INTERFACE);
3246 if (N_VALID_DSEG_DISP(disp)) {
3247 N_N(REG_ITMP3, N_DSEG_DISP(disp), RN, REG_PV);
3249 ICONST(REG_ITMP2, disp);
3250 N_N(REG_ITMP3, -N_PV_OFFSET, REG_ITMP2, REG_PV);
3253 emit_label_beq(cd, LABEL_CLASS);
3256 /* interface instanceof code */
3258 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3259 if (super == NULL) {
3260 /* If d == REG_ITMP2, then it's destroyed in check
3265 patcher_add_patch_ref(jd,
3266 PATCHER_checkcast_instanceof_interface,
3267 iptr->sx.s23.s3.c.ref, 0);
3272 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3275 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3276 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3277 M_ISUB_IMM(superindex, REG_ITMP3);
3279 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3283 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3284 superindex * sizeof(methodptr*))
3286 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3288 /* d := (REG_ITMP1 != 0) */
3290 N_LTR(d, REG_ITMP1);
3291 M_BEQ(SZ_BRC + SZ_LHI);
3294 if (super == NULL) {
3295 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3299 /* class instanceof code */
3301 if (super == NULL) {
3302 emit_label(cd, LABEL_CLASS);
3305 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3306 if (super == NULL) {
3307 disp = dseg_add_unique_address(cd, NULL);
3309 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3310 iptr->sx.s23.s3.c.ref,
3314 disp = dseg_add_address(cd, supervftbl);
3319 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3322 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3323 M_ALD_DSEG(REG_ITMP2, disp);
3325 CODEGEN_CRITICAL_SECTION_START;
3327 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3328 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3329 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3331 CODEGEN_CRITICAL_SECTION_END;
3333 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3335 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3337 M_BGT(SZ_BRC + SZ_LHI);
3341 if (super == NULL) {
3342 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3343 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3344 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3345 } else if (super->flags & ACC_INTERFACE) {
3346 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3347 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3349 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3352 # undef LABEL_EXIT_CHECK_NULL
3354 # undef LABEL_EXIT_INTERFACE_NULL
3355 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3356 # undef LABEL_EXIT_INTERFACE_DONE
3357 # undef LABEL_EXIT_CLASS_NULL
3359 emit_store_dst(jd, iptr, d);
3365 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3367 /* check for negative sizes and copy sizes to stack if necessary */
3369 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3372 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3374 /* copy SAVEDVAR sizes to stack */
3375 var = VAR(iptr->sx.s23.s2.args[s1]);
3377 /* Already Preallocated? */
3378 if (!(var->flags & PREALLOC)) {
3379 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3380 M_IST(s2, REG_SP, s1 * 4);
3384 /* is a patcher function set? */
3386 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3387 disp = dseg_add_unique_address(cd, 0);
3389 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3390 iptr->sx.s23.s3.c.ref,
3394 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3396 /* a0 = dimension count */
3398 ICONST(REG_A0, iptr->s1.argcount);
3400 /* a1 = classinfo */
3402 M_ALD_DSEG(REG_A1, disp);
3404 /* a2 = pointer to dimensions = stack pointer */
3406 M_MOV(REG_SP, REG_A2);
3408 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3409 M_ALD_DSEG(REG_ITMP1, disp);
3410 M_ASUB_IMM(96, REG_SP);
3411 M_JSR(REG_RA, REG_ITMP1);
3412 M_AADD_IMM(96, REG_SP);
3414 /* check for exception before result assignment */
3416 emit_exception_check(cd, iptr);
3418 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3419 M_INTMOVE(REG_RESULT, s1);
3420 emit_store_dst(jd, iptr, s1);
3425 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3429 } /* for instruction */
3431 MCODECHECK(512); /* XXX require a lower number? */
3433 /* At the end of a basic block we may have to append some nops,
3434 because the patcher stub calling code might be longer than the
3435 actual instruction. So codepatching does not change the
3436 following block unintentionally. */
3438 if (cd->mcodeptr < cd->lastmcodeptr) {
3439 while (cd->mcodeptr < cd->lastmcodeptr) {
3444 } /* if (bptr -> flags >= BBREACHED) */
3445 } /* for basic block */
3447 dseg_createlinenumbertable(cd);
3449 /* generate stubs */
3451 emit_patcher_traps(jd);
3453 /* everything's ok */
3459 /* codegen_emit_stub_compiler **************************************************
3461 Emits a stub routine which calls the compiler.
3463 *******************************************************************************/
3465 void codegen_emit_stub_compiler(jitdata *jd)
3470 /* get required compiler data */
3475 /* code for the stub */
3477 /* don't touch ITMP2 as it cointains the return address */
3479 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3481 /* REG_METHODPTR (REG_ITMP1) already used */
3482 M_ILD_DSEG(REG_ITMP3, -2 * SIZEOF_VOID_P); /* methodinfo */
3483 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3488 /* codegen_emit_stub_native ****************************************************
3490 Emits a stub routine which calls a native method.
3492 *******************************************************************************/
3495 arguments on stack \
3496 -------------------------------------------------| <- SP on nativestub entry
3498 callee saved int regs (none) |
3499 callee saved float regs (none) | stack frame like in cacao
3500 local variable slots (none) |
3501 arguments for calling methods (none) /
3502 ------------------------------------------------------------------ <- datasp
3507 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3508 0 - 96 register save area for callee /
3509 -------------------------------------------------------- <- SP native method
3511 SP after method entry
3514 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams)
3520 s4 i, j; /* count variables */
3525 /* get required compiler data */
3531 /* set some variables */
3535 /* calculate stackframe size */
3537 cd->stackframesize =
3538 1 + /* return address */
3539 sizeof(stackframeinfo_t) / 8 +
3540 sizeof(localref_table) / 8 +
3543 (96 / 8); /* linkage area */
3545 /* keep stack 8-byte aligned */
3547 /*ALIGN_2(cd->stackframesize);*/
3549 /* create method header */
3551 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3552 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3553 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3554 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3555 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3556 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3557 (void) dseg_addlinenumbertablesize(cd);
3558 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3562 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3563 M_AADD_IMM(N_PV_OFFSET, REG_PV);
3565 /* store return address */
3567 M_AST(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3569 /* get function address (this must happen before the stackframeinfo) */
3571 funcdisp = dseg_add_functionptr(cd, f);
3574 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, funcdisp);
3576 #if defined(ENABLE_GC_CACAO)
3577 /* Save callee saved integer registers in stackframeinfo (GC may
3578 need to recover them during a collection). */
3580 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3581 OFFSET(stackframeinfo_t, intregs);
3583 for (i = 0; i < INT_SAV_CNT; i++)
3584 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3587 /* save integer and float argument registers */
3589 for (i = 0; i < md->paramcount; i++) {
3590 if (!md->params[i].inmemory) {
3591 s1 = md->params[i].regoff;
3593 switch (md->paramtypes[i].type) {
3596 M_IST(s1, REG_SP, 96 + i * 8);
3599 M_LST(s1, REG_SP, 96 + i * 8);
3603 M_DST(s1, REG_SP, 96 + i * 8);
3609 /* create native stack info */
3611 M_MOV(REG_SP, REG_A0);
3612 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3613 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3614 M_ALD_DSEG(REG_ITMP2, disp);
3617 /* remember class argument */
3619 if (m->flags & ACC_STATIC)
3620 M_MOV(REG_RESULT, REG_ITMP3);
3622 /* restore integer and float argument registers */
3624 for (i = 0; i < md->paramcount; i++) {
3625 if (!md->params[i].inmemory) {
3626 s1 = md->params[i].regoff;
3628 switch (md->paramtypes[i].type) {
3631 M_ILD(s1, REG_SP, 96 + i * 8);
3634 M_LLD(s1, REG_SP, 96 + i * 8);
3638 M_DLD(s1, REG_SP, 96 + i * 8);
3644 /* copy or spill arguments to new locations */
3646 for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
3647 t = md->paramtypes[i].type;
3649 if (IS_INT_LNG_TYPE(t)) {
3650 if (!md->params[i].inmemory) {
3651 s1 = md->params[i].regoff;
3652 s2 = nmd->params[j].regoff;
3654 if (!nmd->params[j].inmemory) {
3655 if (IS_2_WORD_TYPE(t))
3661 if (IS_2_WORD_TYPE(t))
3662 M_LST(s1, REG_SP, s2);
3664 M_IST(s1, REG_SP, s2);
3668 s1 = md->params[i].regoff + cd->stackframesize * 8;
3669 s2 = nmd->params[j].regoff;
3671 if (IS_2_WORD_TYPE(t)) {
3672 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3674 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3679 /* We only copy spilled float arguments, as the float
3680 argument registers keep unchanged. */
3682 if (md->params[i].inmemory) {
3683 s1 = md->params[i].regoff + cd->stackframesize * 8;
3684 s2 = nmd->params[j].regoff;
3686 if (IS_2_WORD_TYPE(t)) {
3687 N_MVC(s2, 8, REG_SP, s1, REG_SP);
3689 N_MVC(s2, 4, REG_SP, s1, REG_SP);
3695 /* Handle native Java methods. */
3697 if (m->flags & ACC_NATIVE) {
3698 /* put class into second argument register */
3700 if (m->flags & ACC_STATIC)
3701 M_MOV(REG_ITMP3, REG_A1);
3703 /* put env into first argument register */
3705 disp = dseg_add_address(cd, _Jv_env);
3706 M_ALD_DSEG(REG_A0, disp);
3709 /* generate the actual native call */
3711 M_ALD_DSEG(REG_ITMP2, funcdisp);
3714 /* save return value */
3716 switch (md->returntype.type) {
3719 M_IST(REG_RESULT, REG_SP, 96);
3722 M_LST(REG_RESULT_PACKED, REG_SP, 96);
3726 M_DST(REG_FRESULT, REG_SP, 96);
3732 /* remove native stackframe info */
3734 M_MOV(REG_SP, REG_A0);
3735 M_LDA(REG_A1, REG_PV, -N_PV_OFFSET);
3736 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3737 M_ALD_DSEG(REG_ITMP1, disp);
3740 M_MOV(REG_RESULT, REG_ITMP3_XPTR);
3742 /* restore return value */
3744 switch (md->returntype.type) {
3747 M_ILD(REG_RESULT, REG_SP, 96);
3750 M_LLD(REG_RESULT_PACKED, REG_SP, 96);
3754 M_DLD(REG_FRESULT, REG_SP, 96);
3760 #if defined(ENABLE_GC_CACAO)
3761 /* Restore callee saved integer registers from stackframeinfo (GC
3762 might have modified them during a collection). */
3764 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3765 OFFSET(stackframeinfo_t, intregs);
3767 for (i = 0; i < INT_SAV_CNT; i++)
3768 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
3771 /* load return address */
3773 M_ALD(REG_RA, REG_SP, (cd->stackframesize - 1) * 8);
3775 /* remove stackframe */
3777 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3779 /* check for exception */
3781 M_TEST(REG_ITMP3_XPTR);
3782 M_BNE(SZ_BRC + SZ_BCR); /* if no exception then return */
3786 /* handle exception */
3788 M_MOV(REG_RA, REG_ITMP1_XPC);
3790 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3791 M_ALD_DSEG(REG_ITMP2, disp);
3792 M_JMP(RN, REG_ITMP2);
3794 /* generate patcher traps */
3796 emit_patcher_traps(jd);
3800 * These are local overrides for various environment variables in Emacs.
3801 * Please do not remove this and leave it at the end of the file, where
3802 * Emacs will automagically detect them.
3803 * ---------------------------------------------------------------------
3806 * indent-tabs-mode: t
3810 * vim:noexpandtab:sw=4:ts=4: