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 8400 2007-08-22 18:28:22Z pm $
36 #include "native/jni.h"
37 #include "native/localref.h"
38 #include "native/native.h"
40 #include "mm/memory.h"
42 #if defined(ENABLE_THREADS)
43 # include "threads/lock-common.h"
44 # include "threads/native/lock.h"
47 #include "vmcore/loader.h"
48 #include "vmcore/options.h"
49 #include "vmcore/statistics.h"
50 #include "vm/builtin.h"
51 #include "vm/exceptions.h"
52 #include "vm/global.h"
53 #include "vm/jit/abi.h"
54 #if defined(ENABLE_LSRA)
55 # include "vm/jit/allocator/lsra.h"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/codegen-common.h"
59 #include "vm/jit/dseg.h"
60 #include "vm/jit/emit-common.h"
61 #include "vm/jit/jit.h"
62 #include "vm/jit/methodheader.h"
63 #include "vm/jit/parse.h"
64 #include "vm/jit/patcher-common.h"
65 #include "vm/jit/reg.h"
66 #include "vm/jit/replace.h"
67 #include "vm/jit/s390/arch.h"
68 #include "vm/jit/s390/codegen.h"
69 #include "vm/jit/s390/emit.h"
70 #include "vm/jit/s390/md-abi.h"
71 #include "vm/jit/stacktrace.h"
73 #include "vm/stringlocal.h"
76 /* DO__LOG generates a call to do__log. No registers are destroyed,
77 * so you may use it anywhere. regs is an array containing all general
81 static void do__log(u4 *regs) {
82 /* insert stuff here */
86 N_AHI(REG_SP, -200); \
87 N_STM(R0, R15, 96, REG_SP); \
88 M_ALD_DSEG(R14, dseg_add_address(cd, &do__log)); \
89 N_LA(R2, 96, RN, REG_SP); \
91 N_LM(R0, R15, 96, REG_SP); \
94 #define SUPPORT_HERCULES 1
96 /* codegen *********************************************************************
98 Generates machine code.
100 *******************************************************************************/
104 Layout of stackframe:
107 ===============================================================================
108 return_address (stackframesize - 1) * 8
109 saved_int_reg[INT_SAV_CNT - 1] (stackframseize - 2) * 8
111 saved_int_reg[rd->savintreguse]
112 saved_flt_reg[FLT_SAV_CNT - 1]
114 saved_flt_reg[rd->savfltreguse] (stackframesize - 1 - savedregs_num) * 8
116 return_value_tmp (rd->memuse + 1) * 8
117 monitorenter_argument (rd->memuse) * 8
119 local[rd->memuse - 1] (rd->memuse - 1) * 8
127 bool codegen_emit(jitdata *jd)
133 s4 len, s1, s2, s3, d, dd, disp;
136 varinfo *var, *var1, *var2, *dst;
140 constant_classref *cr;
141 unresolved_class *uc;
142 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
143 unresolved_method *um;
144 builtintable_entry *bte;
147 unresolved_field *uf;
150 rplpoint *replacementpoint;
154 /* get required compiler data */
161 /* prevent compiler warnings */
174 /* space to save used callee saved registers */
176 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
177 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
179 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
182 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
185 #if defined(ENABLE_THREADS)
186 /* Space to save argument of monitor_enter and Return Values to
187 survive monitor_exit. The stack position for the argument can
188 not be shared with place to save the return register
189 since both values reside in R2. */
191 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
192 /* 1 slot space to save argument of monitor_enter */
193 /* 1 slot to temporary store return value before monitor_exit */
194 cd->stackframesize += 2;
198 /* Keep stack of non-leaf functions 16-byte aligned for calls into
199 native code e.g. libc or jni (alignment problems with
202 if (!jd->isleafmethod || opt_verbosecall )
203 /* TODO really 16 bytes ? */
204 cd->stackframesize = (cd->stackframesize + 2) & ~2;
206 /* create method header */
208 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
209 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
211 #if defined(ENABLE_THREADS)
212 /* IsSync contains the offset relative to the stack pointer for the
213 argument of monitor_exit used in the exception handler. Since the
214 offset could be zero and give a wrong meaning of the flag it is
218 if (checksync && (m->flags & ACC_SYNCHRONIZED))
219 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 8); /* IsSync */
222 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
224 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
225 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
226 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
228 (void) dseg_addlinenumbertablesize(cd);
230 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
232 /* create exception table */
234 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
235 dseg_add_target(cd, ex->start);
236 dseg_add_target(cd, ex->end);
237 dseg_add_target(cd, ex->handler);
238 (void) dseg_add_unique_address(cd, ex->catchtype.any);
243 M_AADD_IMM(N_PV_OFFSET, REG_PV);
245 /* generate method profiling code */
247 #if defined(ENABLE_PROFILING)
248 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
249 /* count frequency */
250 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
251 ICONST(REG_ITMP2, 1);
252 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
253 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
259 /* create stack frame (if necessary) */
261 if (cd->stackframesize)
262 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
264 /* save used callee saved registers and return address */
266 p = cd->stackframesize;
267 p--; M_AST(REG_RA, REG_SP, p * 8);
269 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
270 p--; M_IST(rd->savintregs[i], REG_SP, p * 8);
272 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
273 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
276 /* take arguments out of register or stack frame */
280 for (p = 0, l = 0; p < md->paramcount; p++) {
281 t = md->paramtypes[p].type;
282 varindex = jd->local_map[l * 5 + t];
286 if (IS_2_WORD_TYPE(t))
289 if (varindex == UNUSED)
294 s1 = md->params[p].regoff;
296 if (IS_INT_LNG_TYPE(t)) { /* integer args */
297 if (IS_2_WORD_TYPE(t)) {
305 if (!md->params[p].inmemory) { /* register arguments */
306 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
307 if (IS_2_WORD_TYPE(t)) {
308 M_LNGMOVE(s2, var->vv.regoff);
310 M_INTMOVE(s2, var->vv.regoff);
312 } else { /* reg arg -> spilled */
313 if (IS_2_WORD_TYPE(t)) {
314 M_LST(s2, REG_SP, var->vv.regoff);
316 M_IST(s2, REG_SP, var->vv.regoff);
320 } else { /* stack arguments */
321 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
322 if (IS_2_WORD_TYPE(t)) {
323 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
325 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
327 } else { /* stack arg -> spilled */
328 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
332 } else { /* floating args */
333 if (!md->params[p].inmemory) { /* register arguments */
335 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
336 M_FLTMOVE(s2, var->vv.regoff);
338 } else { /* reg arg -> spilled */
339 if (IS_2_WORD_TYPE(t))
340 M_DST(s2, REG_SP, var->vv.regoff);
342 M_FST(s2, REG_SP, var->vv.regoff);
345 } else { /* stack arguments */
346 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
347 if (IS_2_WORD_TYPE(t))
348 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
351 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 8 + s1);
353 } else { /* stack-arg -> spilled */
354 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 8 + s1, REG_SP);
355 var->vv.regoff = cd->stackframesize * 8 + s1;
361 /* save monitorenter argument */
363 #if defined(ENABLE_THREADS)
364 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
365 /* stack offset for monitor argument */
370 if (opt_verbosecall) {
371 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
373 for (p = 0; p < INT_ARG_CNT; p++)
374 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
376 for (p = 0; p < FLT_ARG_CNT; p++)
377 M_DST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
379 s1 += ((INT_ARG_CNT + FLT_ARG_CNT));
383 /* decide which monitor enter function to call */
385 if (m->flags & ACC_STATIC) {
386 disp = dseg_add_address(cd, &m->class->object.header);
387 M_ALD_DSEG(REG_A0, disp);
391 M_BNE(SZ_BRC + SZ_ILL);
392 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
395 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
396 M_ALD_DSEG(REG_ITMP3, disp);
398 M_AST(REG_A0, REG_SP, s1 * 8);
400 M_ASUB_IMM(96, REG_SP);
402 M_AADD_IMM(96, REG_SP);
405 if (opt_verbosecall) {
406 for (p = 0; p < INT_ARG_CNT; p++)
407 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
409 for (p = 0; p < FLT_ARG_CNT; p++)
410 M_DLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
412 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
419 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
420 emit_verbosecall_enter(jd);
421 #endif /* !defined(NDEBUG) */
425 /* end of header generation */
427 /* create replacement points */
429 REPLACEMENT_POINTS_INIT(cd, jd);
431 /* walk through all basic blocks */
433 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
435 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
437 if (bptr->flags >= BBREACHED) {
439 /* branch resolving */
441 codegen_resolve_branchrefs(cd, bptr);
443 /* handle replacement points */
445 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
447 /* copy interface registers to their destination */
452 #if defined(ENABLE_PROFILING)
453 /* generate basicblock profiling code */
455 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
456 /* count frequency */
458 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
459 M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(codeinfo, bbfrequency));
460 ICONST(REG_ITMP2, 1);
461 N_AL(REG_ITMP2, bptr->nr * 4, RN, REG_ITMP1);
462 M_IST(REG_ITMP2, REG_ITMP1, bptr->nr * 4);
464 /* if this is an exception handler, start profiling again */
466 if (bptr->type == BBTYPE_EXH)
471 #if defined(ENABLE_LSRA)
475 src = bptr->invars[len];
476 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
477 if (bptr->type == BBTYPE_EXH) {
478 /* d = reg_of_var(rd, src, REG_ITMP1); */
479 if (!IS_INMEMORY(src->flags))
483 M_INTMOVE(REG_ITMP1, d);
484 emit_store(jd, NULL, src, d);
494 var = VAR(bptr->invars[len]);
495 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
496 if (bptr->type == BBTYPE_EXH) {
497 d = codegen_reg_of_var(0, var, REG_ITMP1);
498 M_INTMOVE(REG_ITMP1, d);
499 emit_store(jd, NULL, var, d);
503 assert((var->flags & INOUT));
506 #if defined(ENABLE_LSRA)
509 /* walk through all instructions */
514 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
515 if (iptr->line != currentline) {
516 dseg_addlinenumber(cd, iptr->line);
517 currentline = iptr->line;
520 MCODECHECK(1024); /* 1KB should be enough */
523 case ICMD_NOP: /* ... ==> ... */
524 case ICMD_POP: /* ..., value ==> ... */
525 case ICMD_POP2: /* ..., value, value ==> ... */
528 case ICMD_INLINE_START:
530 REPLACEMENT_POINT_INLINE_START(cd, iptr);
533 case ICMD_INLINE_BODY:
535 REPLACEMENT_POINT_INLINE_BODY(cd, iptr);
536 dseg_addlinenumber_inline_start(cd, iptr);
537 dseg_addlinenumber(cd, iptr->line);
540 case ICMD_INLINE_END:
542 dseg_addlinenumber_inline_end(cd, iptr);
543 dseg_addlinenumber(cd, iptr->line);
546 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
547 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
548 emit_nullpointer_check(cd, iptr, s1);
551 /* constant operations ************************************************/
553 case ICMD_ICONST: /* ... ==> ..., constant */
554 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
555 ICONST(d, iptr->sx.val.i);
556 emit_store_dst(jd, iptr, d);
559 case ICMD_LCONST: /* ... ==> ..., constant */
561 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
562 LCONST(d, iptr->sx.val.l);
563 emit_store_dst(jd, iptr, d);
566 case ICMD_FCONST: /* ... ==> ..., constant */
567 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
568 disp = dseg_add_float(cd, iptr->sx.val.f);
569 M_FLD_DSEG(d, disp, REG_ITMP1);
570 emit_store_dst(jd, iptr, d);
573 case ICMD_DCONST: /* ... ==> ..., constant */
574 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
575 disp = dseg_add_double(cd, iptr->sx.val.d);
576 M_DLD_DSEG(d, disp, REG_ITMP1);
577 emit_store_dst(jd, iptr, d);
580 case ICMD_ACONST: /* ... ==> ..., constant */
581 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
583 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
584 cr = iptr->sx.val.c.ref;
585 disp = dseg_add_unique_address(cd, cr);
587 /* PROFILE_CYCLE_STOP; */
589 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
592 /* PROFILE_CYCLE_START; */
596 if (iptr->sx.val.anyptr == 0) {
599 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
602 if (((u4)(iptr->sx.val.anyptr) & 0x00008000) == 0) {
603 N_LHI(d, ((u4)(iptr->sx.val.anyptr) >> 16) & 0xFFFF);
605 N_AHI(d, (u4)(iptr->sx.val.anyptr) & 0xFFFF);
607 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
613 emit_store_dst(jd, iptr, d);
617 /* load/store/copy/move operations ************************************/
619 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
620 case ICMD_ALOAD: /* s1 = local variable */
624 case ICMD_ISTORE: /* ..., value ==> ... */
635 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
639 /* integer operations *************************************************/
641 case ICMD_INEG: /* ..., value ==> ..., - value */
643 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
644 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
646 emit_store_dst(jd, iptr, d);
650 case ICMD_LNEG: /* ..., value ==> ..., - value */
652 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
653 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
654 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
655 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
656 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
657 N_AHI(GET_HIGH_REG(d), -1);
658 emit_store_dst(jd, iptr, d);
661 case ICMD_I2L: /* ..., value ==> ..., value */
663 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
664 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
666 M_INTMOVE(s1, GET_HIGH_REG(d));
667 ICONST(GET_LOW_REG(d), 0);
668 M_SRDA_IMM(32, GET_HIGH_REG(d));
670 emit_copy_dst(jd, iptr, d);
671 emit_store_dst(jd, iptr, d);
672 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
676 case ICMD_L2I: /* ..., value ==> ..., value */
677 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
678 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
679 M_INTMOVE(GET_LOW_REG(s1), d);
680 emit_store_dst(jd, iptr, d);
683 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
684 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
685 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
689 emit_store_dst(jd, iptr, d);
692 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
693 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
694 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
698 emit_store_dst(jd, iptr, d);
701 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
703 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
704 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
708 emit_store_dst(jd, iptr, d);
711 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
713 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
714 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
715 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
722 emit_store_dst(jd, iptr, d);
727 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
728 /* sx.val.i = constant */
729 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
730 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
733 if (N_VALID_IMM(iptr->sx.val.i)) {
734 M_IADD_IMM(iptr->sx.val.i, d);
736 ICONST(REG_ITMP2, iptr->sx.val.i);
737 M_IADD(REG_ITMP2, d);
739 emit_store_dst(jd, iptr, d);
742 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
744 /* M, (r, q) -> (r, q) */
746 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
748 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
749 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
750 dd = GET_HIGH_REG(d);
759 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
760 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
770 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
771 N_AHI(GET_HIGH_REG(d), 1);
773 emit_store_dst(jd, iptr, d);
776 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
777 /* sx.val.l = constant */
779 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
780 dd = GET_HIGH_REG(d);
782 s1 = emit_load_s1_high(jd, iptr, dd);
783 s3 = iptr->sx.val.l >> 32;
787 if (N_VALID_IMM(s3)) {
790 ICONST(REG_ITMP3, s3);
791 M_IADD(REG_ITMP3, dd);
795 s1 = emit_load_s1_low(jd, iptr, dd);
796 s3 = iptr->sx.val.l & 0xffffffff;
797 ICONST(REG_ITMP3, s3);
800 N_ALR(dd, REG_ITMP3);
802 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
803 N_AHI(GET_HIGH_REG(d), 1);
805 emit_store_dst(jd, iptr, d);
808 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
810 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
811 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
812 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
814 M_INTMOVE(s1, REG_ITMP1);
815 M_ISUB(s2, REG_ITMP1);
816 M_INTMOVE(REG_ITMP1, d);
821 emit_store_dst(jd, iptr, d);
825 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
826 /* sx.val.i = constant */
828 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
829 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
832 if (N_VALID_IMM(-iptr->sx.val.i)) {
833 M_ISUB_IMM(iptr->sx.val.i, d);
835 ICONST(REG_ITMP2, iptr->sx.val.i);
836 M_ISUB(REG_ITMP2, d);
838 emit_store_dst(jd, iptr, d);
842 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
844 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
846 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
847 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
848 dd = GET_HIGH_REG(d);
851 M_INTMOVE(s2, REG_ITMP3);
858 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
859 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
863 M_INTMOVE(s2, REG_ITMP3);
870 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
871 N_AHI(GET_HIGH_REG(d), -1);
873 emit_store_dst(jd, iptr, d);
876 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
877 /* sx.val.l = constant */
879 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
881 dd = GET_HIGH_REG(d);
882 s1 = emit_load_s1_high(jd, iptr, dd);
883 s3 = iptr->sx.val.l >> 32;
887 if (N_VALID_IMM(-s3)) {
890 ICONST(REG_ITMP3, s3);
891 M_ISUB(REG_ITMP3, dd);
895 s1 = emit_load_s1_low(jd, iptr, dd);
896 s3 = iptr->sx.val.l & 0xffffffff;
897 ICONST(REG_ITMP3, s3);
900 N_SLR(dd, REG_ITMP3);
902 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
903 N_AHI(GET_HIGH_REG(d), -1);
905 emit_store_dst(jd, iptr, d);
908 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
910 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
911 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
912 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
919 emit_store_dst(jd, iptr, d);
923 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
924 /* sx.val.i = constant */
925 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
926 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
928 if (iptr->sx.val.i == 2) {
930 } else if (N_VALID_IMM(iptr->sx.val.i)) {
931 M_IMUL_IMM(iptr->sx.val.i, d);
933 disp = dseg_add_s4(cd, iptr->sx.val.i);
934 M_ILD_DSEG(REG_ITMP2, disp);
935 M_IMUL(REG_ITMP2, d);
937 emit_store_dst(jd, iptr, d);
940 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
941 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
943 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
944 emit_arithmetic_check(cd, iptr, s2);
946 /* For this operation we need a register pair.
947 * We will use r0 and itmp1 and will backup r0.
950 M_INTMOVE(R0, REG_ITMP3);
952 /* We won't check for division by 0, we catch a SIGFPE instead
953 * Special case 0x80000000 / 0xffffffff handled by signal handler too.
956 s1 = emit_load_s1(jd, iptr, R0);
965 d = codegen_reg_of_dst(jd, iptr, R0);
969 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
970 M_INTMOVE(REG_ITMP1, d);
974 emit_store_dst(jd, iptr, d);
976 /* If destionation of operation was not register R0,
980 if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
981 M_INTMOVE(REG_ITMP3, R0);
986 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
987 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
989 bte = iptr->sx.s23.s3.bte;
992 /* test s2 for zero */
994 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
995 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
996 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
997 emit_arithmetic_check(cd, iptr, REG_ITMP3);
1001 disp = dseg_add_functionptr(cd, bte->fp);
1003 /* load arguments */
1005 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
1007 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
1008 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
1012 M_ASUB_IMM(96, REG_SP);
1013 M_ALD_DSEG(REG_ITMP3, disp);
1014 M_JSR(REG_RA, REG_ITMP3);
1015 M_AADD_IMM(96, REG_SP);
1019 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
1020 M_LNGMOVE(REG_RESULT_PACKED, d);
1021 emit_store_dst(jd, iptr, d);
1025 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1026 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1027 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1029 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1030 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1031 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1033 /* Use only 5 bits of sencond operand. */
1035 M_INTMOVE(s2, REG_ITMP2);
1037 ICONST(REG_ITMP3, 0x1F);
1038 M_IAND(REG_ITMP3, s2);
1042 switch (iptr->opc) {
1055 emit_store_dst(jd, iptr, d);
1058 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1059 /* sx.val.i = constant */
1063 assert(iptr->sx.val.i <= 32);
1065 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1066 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1073 s3 = (1 << iptr->sx.val.i) - 1;
1075 if (N_VALID_IMM(s3)) {
1078 ICONST(REG_ITMP1, -1);
1079 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1080 M_IADD(REG_ITMP1, d);
1083 N_BRC_BACK_PATCH(ref);
1085 M_SRA_IMM(iptr->sx.val.i, d);
1087 emit_store_dst(jd, iptr, d);
1092 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1093 /* sx.val.i = constant */
1095 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1096 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1099 M_MOV(s1, REG_ITMP1);
1103 ICONST(REG_ITMP3, iptr->sx.val.i);
1106 M_IAND(REG_ITMP3, d);
1109 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1115 emit_store_dst(jd, iptr, d);
1119 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1120 /* sx.val.i = constant */
1121 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1122 /* sx.val.i = constant */
1123 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1124 /* sx.val.i = constant */
1125 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1126 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1130 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1132 switch (iptr->opc) {
1133 case ICMD_ISHLCONST:
1136 case ICMD_ISHRCONST:
1139 case ICMD_IUSHRCONST:
1146 emit_store_dst(jd, iptr, d);
1149 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1151 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1153 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1155 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1157 /* Use only 6 bits of second operand */
1159 M_INTMOVE(s2, REG_ITMP3);
1161 ICONST(REG_ITMP2, 0x3F);
1162 M_IAND(REG_ITMP2, s2);
1164 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1166 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1167 M_INTMOVE(s2, REG_ITMP3);
1171 s1 = emit_load_s1(jd, iptr, d);
1175 switch (iptr->opc) {
1177 M_SLDL(s2, GET_HIGH_REG(d));
1180 M_SRDA(s2, GET_HIGH_REG(d));
1183 M_SRDL(s2, GET_HIGH_REG(d));
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_LSHLCONST: /* ..., value ==> ..., value << constant */
1196 /* sx.val.i = constant */
1197 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1198 /* sx.val.i = constant */
1199 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1200 /* sx.val.l = constant */
1203 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1204 s1 = emit_load_s1(jd, iptr, d);
1208 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1210 switch (iptr->opc) {
1211 case ICMD_LSHLCONST:
1212 N_SLDL(GET_HIGH_REG(d), disp, RN);
1214 case ICMD_LSHRCONST:
1215 N_SRDA(GET_HIGH_REG(d), disp, RN);
1217 case ICMD_LUSHRCONST:
1218 N_SRDL(GET_HIGH_REG(d), disp, RN);
1221 N_SLDL(GET_HIGH_REG(d), disp, RN);
1227 emit_copy_dst(jd, iptr, d);
1228 emit_store_dst(jd, iptr, d);
1229 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1233 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1235 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1236 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1237 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1244 emit_store_dst(jd, iptr, d);
1248 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1250 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1251 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1252 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1259 emit_store_dst(jd, iptr, d);
1263 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1265 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1266 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1267 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1274 emit_store_dst(jd, iptr, d);
1280 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1281 /* sx.val.i = constant */
1282 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1283 /* sx.val.i = constant */
1284 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1285 /* sx.val.i = constant */
1287 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1288 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1291 ICONST(REG_ITMP2, iptr->sx.val.i);
1293 switch (iptr->opc) {
1294 case ICMD_IANDCONST:
1295 M_IAND(REG_ITMP2, d);
1297 case ICMD_IXORCONST:
1298 M_IXOR(REG_ITMP2, d);
1301 M_IOR(REG_ITMP2, d);
1307 emit_store_dst(jd, iptr, d);
1311 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1312 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1313 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1315 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1317 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1318 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1319 dd = GET_LOW_REG(d);
1321 switch (iptr->opc) {
1350 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1351 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1352 dd = GET_HIGH_REG(d);
1354 switch (iptr->opc) {
1383 emit_store_dst(jd, iptr, d);
1386 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1387 /* sx.val.l = constant */
1388 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1389 /* sx.val.l = constant */
1390 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1391 /* sx.val.l = constant */
1393 /* TODO should use memory operand to access data segment, not load */
1395 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1397 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1398 s3 = iptr->sx.val.l & 0xffffffff;
1400 M_INTMOVE(s1, GET_LOW_REG(d));
1402 ICONST(REG_ITMP3, s3);
1404 switch (iptr->opc) {
1405 case ICMD_LANDCONST:
1406 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1408 case ICMD_LXORCONST:
1409 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1412 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1418 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1419 s3 = iptr->sx.val.l >> 32;
1421 M_INTMOVE(s1, GET_HIGH_REG(d));
1423 ICONST(REG_ITMP3, s3);
1425 switch (iptr->opc) {
1426 case ICMD_LANDCONST:
1427 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1429 case ICMD_LXORCONST:
1430 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1433 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1439 emit_store_dst(jd, iptr, d);
1443 /* floating operations ************************************************/
1445 case ICMD_FNEG: /* ..., value ==> ..., - value */
1446 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1447 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1449 emit_store_dst(jd, iptr, d);
1452 case ICMD_DNEG: /* ..., value ==> ..., - value */
1453 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1454 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1456 emit_store_dst(jd, iptr, d);
1459 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1460 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1461 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1462 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1469 emit_store_dst(jd, iptr, d);
1472 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1473 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1474 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1475 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1482 emit_store_dst(jd, iptr, d);
1485 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1486 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1487 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1488 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1492 emit_store_dst(jd, iptr, d);
1495 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1496 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1497 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1498 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1502 emit_store_dst(jd, iptr, d);
1505 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1506 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1507 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1508 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1515 emit_store_dst(jd, iptr, d);
1518 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1519 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1520 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1521 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1528 emit_store_dst(jd, iptr, d);
1531 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1532 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1533 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1534 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1538 emit_store_dst(jd, iptr, d);
1541 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1542 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1543 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1544 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1548 emit_store_dst(jd, iptr, d);
1551 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1552 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1553 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1555 emit_store_dst(jd, iptr, d);
1558 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1559 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1560 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1562 emit_store_dst(jd, iptr, d);
1565 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1569 #ifdef SUPPORT_HERCULES
1573 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1574 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1578 switch (iptr->opc) {
1587 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1588 N_LHI(d, 0); /* Load 0 */
1589 ref1 = cd->mcodeptr;
1590 N_BRC(DD_ANY, 0); /* Exit */
1594 switch (iptr->opc) {
1603 #ifdef SUPPORT_HERCULES
1604 /* Hercules does the conversion using a plain C conversion.
1605 * According to manual, real hardware should *NOT* require this.
1607 * Corner case: Positive float leads to INT_MIN (overflow).
1610 switch (iptr->opc) {
1619 ref2 = cd->mcodeptr;
1620 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1624 ref3 = cd->mcodeptr;
1625 M_BGE(0); /* If integer result is negative, continue */
1627 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1628 M_ILD_DSEG(d, disp);
1630 N_BRC_BACK_PATCH(ref1);
1631 #ifdef SUPPORT_HERCULES
1632 N_BRC_BACK_PATCH(ref2);
1633 N_BRC_BACK_PATCH(ref3);
1635 emit_store_dst(jd, iptr, d);
1639 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1642 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1643 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1644 #ifdef SUPPORT_HERCULES
1647 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1648 disp = dseg_add_double(cd, 0.0 / 0.0);
1649 M_DLD_DSEG(d, disp, REG_ITMP1);
1650 emit_label_br(cd, BRANCH_LABEL_1);
1651 N_BRC_BACK_PATCH(ref);
1654 #ifdef SUPPORT_HERCULES
1655 emit_label(cd, BRANCH_LABEL_1);
1657 emit_store_dst(jd, iptr, d);
1661 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1662 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1663 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1665 emit_store_dst(jd, iptr, d);
1668 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1669 /* == => 0, < => 1, > => -1 */
1673 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1674 /* == => 0, < => 1, > => -1 */
1677 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1678 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1679 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1681 switch (iptr->opc) {
1693 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1694 SZ_BRC + SZ_BRC + SZ_BRC
1697 N_BRC( /* load -1 */
1698 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1699 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1704 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1707 N_LHI(d, 1); /* GT */
1708 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1709 N_LHI(d, -1); /* LT */
1710 M_BR(SZ_BRC + SZ_LHI);
1711 N_LHI(d, 0); /* EQ */
1713 emit_store_dst(jd, iptr, d);
1718 /* memory operations **************************************************/
1720 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1722 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1723 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1725 /* implicit null-pointer check */
1726 M_ILD(d, s1, OFFSET(java_array_t, size));
1727 emit_store_dst(jd, iptr, d);
1731 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1732 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1733 s2 = emit_load_s2_notzero(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 N_IC(d, OFFSET(java_bytearray_t, data[0]), s2, s1);
1744 emit_store_dst(jd, iptr, d);
1747 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1749 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1750 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1751 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1753 /* implicit null-pointer check */
1754 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1756 M_INTMOVE(s2, REG_ITMP2);
1757 M_SLL_IMM(1, REG_ITMP2);
1759 N_LH(d, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1761 /* N_LH does sign extends, undo ! */
1766 emit_store_dst(jd, iptr, d);
1769 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1770 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1771 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1772 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1774 /* implicit null-pointer check */
1775 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1777 M_INTMOVE(s2, REG_ITMP2);
1778 M_SLL_IMM(1, REG_ITMP2);
1780 N_LH(d, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1781 emit_store_dst(jd, iptr, d);
1784 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1785 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1786 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1787 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1789 /* implicit null-pointer check */
1790 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1792 M_INTMOVE(s2, REG_ITMP2);
1793 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1794 N_L(d, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1795 emit_store_dst(jd, iptr, d);
1798 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1800 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1801 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1803 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1805 /* implicit null-pointer check */
1806 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1808 M_INTMOVE(s2, REG_ITMP2);
1809 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1811 /* We need to preserve the array address after the first load */
1813 if (GET_HIGH_REG(d) == s1) {
1814 M_INTMOVE(s1, REG_ITMP3);
1818 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1819 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1820 emit_store_dst(jd, iptr, d);
1824 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1826 s1 = emit_load_s1_notzero(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(2, REG_ITMP2); /* scale index by 4 */
1836 N_LE(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1838 emit_store_dst(jd, iptr, d);
1841 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1842 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1843 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1844 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1846 /* implicit null-pointer check */
1847 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1849 M_INTMOVE(s2, REG_ITMP2);
1850 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1852 N_LD(d, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1854 emit_store_dst(jd, iptr, d);
1857 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1858 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1859 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1860 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1862 /* implicit null-pointer check */
1863 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1865 M_INTMOVE(s2, REG_ITMP2);
1866 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1867 N_L(d, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1868 emit_store_dst(jd, iptr, d);
1871 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1872 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1873 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1874 /* implicit null-pointer check */
1875 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1876 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1878 N_STC(s3, OFFSET(java_bytearray_t, data[0]), s2, s1);
1881 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1883 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1884 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1885 /* implicit null-pointer check */
1886 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1887 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1889 M_INTMOVE(s2, REG_ITMP2);
1890 M_SLL_IMM(1, REG_ITMP2);
1892 N_STH(s3, OFFSET(java_chararray_t, data[0]), REG_ITMP2, s1);
1896 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1897 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1898 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1899 /* implicit null-pointer check */
1900 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1901 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1903 M_INTMOVE(s2, REG_ITMP2);
1904 M_SLL_IMM(1, REG_ITMP2);
1906 N_STH(s3, OFFSET(java_shortarray_t, data[0]), REG_ITMP2, s1);
1909 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1911 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1912 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1913 /* implicit null-pointer check */
1914 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1916 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1918 M_INTMOVE(s2, REG_ITMP2);
1919 M_SLL_IMM(2, REG_ITMP2);
1921 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1924 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1926 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1927 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1928 /* implicit null-pointer check */
1929 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1931 M_INTMOVE(s2, REG_ITMP2);
1932 M_SLL_IMM(3, REG_ITMP2);
1934 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1935 N_ST(s3, OFFSET(java_intarray_t, data[0]), REG_ITMP2, s1);
1936 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1937 N_ST(s3, OFFSET(java_intarray_t, data[0]) + 4, REG_ITMP2, s1);
1940 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1941 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1942 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1943 /* implicit null-pointer check */
1944 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1945 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1947 M_INTMOVE(s2, REG_ITMP2);
1948 M_SLL_IMM(2, REG_ITMP2);
1950 N_STE(s3, OFFSET(java_floatarray_t, data[0]), REG_ITMP2, s1);
1953 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1954 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1955 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1956 /* implicit null-pointer check */
1957 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1958 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1960 M_INTMOVE(s2, REG_ITMP2);
1961 M_SLL_IMM(3, REG_ITMP2);
1963 N_STD(s3, OFFSET(java_doublearray_t, data[0]), REG_ITMP2, s1);
1966 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1968 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1969 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1970 /* implicit null-pointer check */
1971 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1972 s3 = emit_load_s3(jd, iptr, REG_A1);
1974 M_INTMOVE(s1, REG_A0);
1975 M_INTMOVE(s3, REG_A1);
1977 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1978 M_ALD_DSEG(REG_ITMP3, disp);
1979 M_ASUB_IMM(96, REG_SP);
1980 M_JSR(REG_RA, REG_ITMP3);
1981 M_AADD_IMM(96, REG_SP);
1983 emit_exception_check(cd, iptr);
1985 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1986 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1987 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1989 M_INTMOVE(s2, REG_ITMP2);
1990 M_SLL_IMM(2, REG_ITMP2);
1991 N_ST(s3, OFFSET(java_objectarray_t, data[0]), REG_ITMP2, s1);
1994 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1995 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2000 case ICMD_GETSTATIC: /* ... ==> ..., value */
2002 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2003 uf = iptr->sx.s23.s3.uf;
2004 fieldtype = uf->fieldref->parseddesc.fd->type;
2005 disp = dseg_add_unique_address(cd, NULL);
2007 /* PROFILE_CYCLE_STOP; */
2009 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2011 /* PROFILE_CYCLE_START; */
2014 fi = iptr->sx.s23.s3.fmiref->p.field;
2015 fieldtype = fi->type;
2016 disp = dseg_add_address(cd, fi->value);
2018 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2021 patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, 0);
2023 PROFILE_CYCLE_START;
2027 M_ALD_DSEG(REG_ITMP1, disp);
2029 switch (fieldtype) {
2031 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2032 M_ILD(d, REG_ITMP1, 0);
2035 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2036 M_LLD(d, REG_ITMP1, 0);
2039 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2040 M_ALD(d, REG_ITMP1, 0);
2043 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2044 M_FLD(d, REG_ITMP1, 0);
2047 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2048 M_DLD(d, REG_ITMP1, 0);
2052 emit_store_dst(jd, iptr, d);
2056 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2058 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2059 uf = iptr->sx.s23.s3.uf;
2060 fieldtype = uf->fieldref->parseddesc.fd->type;
2061 disp = dseg_add_unique_address(cd, uf);
2063 patcher_add_patch_ref(jd, PATCHER_get_putstatic, uf, disp);
2066 fi = iptr->sx.s23.s3.fmiref->p.field;
2067 fieldtype = fi->type;
2068 disp = dseg_add_address(cd, fi->value);
2070 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2072 patcher_add_patch_ref(jd, PATCHER_clinit, fi->class, disp);
2073 PROFILE_CYCLE_START;
2077 M_ALD_DSEG(REG_ITMP1, disp);
2078 switch (fieldtype) {
2080 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2081 M_IST(s1, REG_ITMP1, 0);
2084 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2085 M_LST(s1, REG_ITMP1, 0);
2088 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2089 M_AST(s1, REG_ITMP1, 0);
2092 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2093 M_FST(s1, REG_ITMP1, 0);
2096 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2097 M_DST(s1, REG_ITMP1, 0);
2102 case ICMD_GETFIELD: /* ... ==> ..., value */
2104 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2105 emit_nullpointer_check(cd, iptr, s1);
2107 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2108 uf = iptr->sx.s23.s3.uf;
2109 fieldtype = uf->fieldref->parseddesc.fd->type;
2112 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2115 fi = iptr->sx.s23.s3.fmiref->p.field;
2116 fieldtype = fi->type;
2120 switch (fieldtype) {
2122 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2126 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2127 if (GET_HIGH_REG(d) == s1) {
2128 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2129 M_ILD(GET_HIGH_REG(d), s1, disp);
2132 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2133 M_ILD(GET_HIGH_REG(d), s1, disp);
2137 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2141 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2145 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2149 emit_store_dst(jd, iptr, d);
2152 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2156 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2157 emit_nullpointer_check(cd, iptr, s1);
2159 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2160 uf = iptr->sx.s23.s3.uf;
2161 fieldtype = uf->fieldref->parseddesc.fd->type;
2165 fi = iptr->sx.s23.s3.fmiref->p.field;
2166 fieldtype = fi->type;
2170 /* We can't add a patcher ref behind this load,
2171 * because the patcher would destroy REG_ITMP3.
2173 * We pass in the disp parameter, how many bytes
2174 * to skip to the to the actual store.
2176 * XXX this relies on patcher_add_patch_ref internals
2179 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2180 patcher_add_patch_ref(jd, PATCHER_get_putfield, uf, 0);
2185 if (IS_INT_LNG_TYPE(fieldtype)) {
2186 if (IS_2_WORD_TYPE(fieldtype))
2187 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2189 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2191 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2194 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2195 ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
2198 switch (fieldtype) {
2200 M_IST(s2, s1, disp);
2203 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2204 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2207 M_AST(s2, s1, disp);
2210 M_FST(s2, s1, disp);
2213 M_DST(s2, s1, disp);
2220 /* branch operations **************************************************/
2222 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2224 /* PROFILE_CYCLE_STOP; */
2226 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2227 M_INTMOVE(s1, REG_ITMP1_XPTR);
2229 #ifdef ENABLE_VERIFIER
2230 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2231 uc = iptr->sx.s23.s2.uc;
2233 patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
2235 #endif /* ENABLE_VERIFIER */
2237 disp = dseg_add_functionptr(cd, asm_handle_exception);
2238 M_ALD_DSEG(REG_ITMP2, disp);
2239 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2244 case ICMD_GOTO: /* ... ==> ... */
2245 case ICMD_RET: /* ... ==> ... */
2247 emit_br(cd, iptr->dst.block);
2251 case ICMD_JSR: /* ... ==> ... */
2253 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2257 case ICMD_IFNULL: /* ..., value ==> ... */
2258 case ICMD_IFNONNULL: /* ..., value ==> ... */
2259 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2261 switch (iptr->opc) {
2263 emit_beq(cd, iptr->dst.block);
2265 case ICMD_IFNONNULL:
2266 emit_bne(cd, iptr->dst.block);
2271 case ICMD_IFEQ: /* ..., value ==> ... */
2272 case ICMD_IFLT: /* ..., value ==> ... */
2273 case ICMD_IFLE: /* ..., value ==> ... */
2274 case ICMD_IFNE: /* ..., value ==> ... */
2275 case ICMD_IFGT: /* ..., value ==> ... */
2276 case ICMD_IFGE: /* ..., value ==> ... */
2278 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2280 if (N_VALID_IMM(iptr->sx.val.i))
2281 M_ICMP_IMM(s1, iptr->sx.val.i);
2283 disp = dseg_add_s4(cd, iptr->sx.val.i);
2284 if (N_VALID_DSEG_DISP(disp)) {
2285 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2287 ICONST(REG_ITMP2, disp);
2288 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2292 switch (iptr->opc) {
2294 emit_blt(cd, iptr->dst.block);
2297 emit_ble(cd, iptr->dst.block);
2300 emit_bne(cd, iptr->dst.block);
2303 emit_bgt(cd, iptr->dst.block);
2306 emit_bge(cd, iptr->dst.block);
2309 emit_beq(cd, iptr->dst.block);
2315 case ICMD_IF_LLT: /* ..., value ==> ... */
2316 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2322 /* ATTENTION: compare high words signed and low words unsigned */
2324 # define LABEL_OUT BRANCH_LABEL_1
2326 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2328 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2329 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2331 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2332 if (N_VALID_DSEG_DISP(disp)) {
2333 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2335 ICONST(REG_ITMP2, disp);
2336 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2343 emit_blt(cd, iptr->dst.block);
2344 /* EQ ... fall through */
2345 emit_label_bgt(cd, LABEL_OUT);
2349 emit_bgt(cd, iptr->dst.block);
2350 /* EQ ... fall through */
2351 emit_label_blt(cd, LABEL_OUT);
2354 /* EQ ... fall through */
2355 emit_label_bne(cd, LABEL_OUT);
2358 /* EQ ... fall through */
2359 emit_bne(cd, iptr->dst.block);
2365 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2367 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2368 if (N_VALID_DSEG_DISP(disp)) {
2369 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2371 ICONST(REG_ITMP2, disp);
2372 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2377 emit_blt(cd, iptr->dst.block);
2378 emit_label(cd, LABEL_OUT);
2381 emit_ble(cd, iptr->dst.block);
2382 emit_label(cd, LABEL_OUT);
2385 emit_bgt(cd, iptr->dst.block);
2386 emit_label(cd, LABEL_OUT);
2389 emit_bge(cd, iptr->dst.block);
2390 emit_label(cd, LABEL_OUT);
2393 emit_beq(cd, iptr->dst.block);
2394 emit_label(cd, LABEL_OUT);
2397 emit_bne(cd, iptr->dst.block);
2406 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2407 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2409 /* Compare addresses as 31 bit unsigned integers */
2411 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2412 M_LDA(REG_ITMP1, s1, 0);
2414 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2415 M_LDA(REG_ITMP2, s2, 0);
2417 M_CMP(REG_ITMP1, REG_ITMP2);
2419 switch (iptr->opc) {
2420 case ICMD_IF_ACMPEQ:
2421 emit_beq(cd, iptr->dst.block);
2423 case ICMD_IF_ACMPNE:
2424 emit_bne(cd, iptr->dst.block);
2430 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2431 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2432 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2433 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2434 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2435 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2437 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2438 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2440 switch (iptr->opc) {
2441 case ICMD_IF_ICMPEQ:
2442 emit_beq(cd, iptr->dst.block);
2444 case ICMD_IF_ICMPNE:
2445 emit_bne(cd, iptr->dst.block);
2447 case ICMD_IF_ICMPLT:
2448 emit_blt(cd, iptr->dst.block);
2450 case ICMD_IF_ICMPGT:
2451 emit_bgt(cd, iptr->dst.block);
2453 case ICMD_IF_ICMPLE:
2454 emit_ble(cd, iptr->dst.block);
2456 case ICMD_IF_ICMPGE:
2457 emit_bge(cd, iptr->dst.block);
2463 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2464 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2465 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2466 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2467 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2468 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2473 /* ATTENTION: compare high words signed and low words unsigned */
2475 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2476 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2481 case ICMD_IF_LCMPLT:
2482 case ICMD_IF_LCMPLE:
2483 emit_blt(cd, iptr->dst.block);
2484 /* EQ ... fall through */
2485 out_ref = cd->mcodeptr;
2488 case ICMD_IF_LCMPGT:
2489 case ICMD_IF_LCMPGE:
2490 emit_bgt(cd, iptr->dst.block);
2491 /* EQ ... fall through */
2492 out_ref = cd->mcodeptr;
2495 case ICMD_IF_LCMPEQ:
2496 /* EQ ... fall through */
2497 out_ref = cd->mcodeptr;
2500 case ICMD_IF_LCMPNE:
2501 /* EQ ... fall through */
2502 emit_bne(cd, iptr->dst.block);
2508 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2509 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2514 case ICMD_IF_LCMPLT:
2515 emit_blt(cd, iptr->dst.block);
2517 case ICMD_IF_LCMPLE:
2518 emit_ble(cd, iptr->dst.block);
2520 case ICMD_IF_LCMPGT:
2521 emit_bgt(cd, iptr->dst.block);
2523 case ICMD_IF_LCMPGE:
2524 emit_bge(cd, iptr->dst.block);
2526 case ICMD_IF_LCMPEQ:
2527 emit_beq(cd, iptr->dst.block);
2529 case ICMD_IF_LCMPNE:
2530 emit_bne(cd, iptr->dst.block);
2537 if (out_ref != NULL) {
2538 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2544 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2546 REPLACEMENT_POINT_RETURN(cd, iptr);
2547 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2548 M_INTMOVE(s1, REG_RESULT);
2549 goto nowperformreturn;
2551 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2553 REPLACEMENT_POINT_RETURN(cd, iptr);
2554 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2555 M_INTMOVE(s1, REG_RESULT);
2557 #ifdef ENABLE_VERIFIER
2558 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2559 unresolved_class *uc = iptr->sx.s23.s2.uc;
2562 patcher_add_patch_ref(jd, PATCHER_athrow_areturn, uc, 0);
2563 PROFILE_CYCLE_START;
2565 #endif /* ENABLE_VERIFIER */
2566 goto nowperformreturn;
2568 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2570 REPLACEMENT_POINT_RETURN(cd, iptr);
2571 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2572 M_LNGMOVE(s1, REG_RESULT_PACKED);
2573 goto nowperformreturn;
2575 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2578 REPLACEMENT_POINT_RETURN(cd, iptr);
2579 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2580 M_FLTMOVE(s1, REG_FRESULT);
2581 goto nowperformreturn;
2583 case ICMD_RETURN: /* ... ==> ... */
2585 REPLACEMENT_POINT_RETURN(cd, iptr);
2591 p = cd->stackframesize;
2593 /* call trace function */
2595 #if !defined(NDEBUG)
2596 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2597 emit_verbosecall_exit(jd);
2598 #endif /* !defined(NDEBUG) */
2600 #if defined(ENABLE_THREADS)
2601 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2602 /* we need to save the proper return value */
2604 switch (iptr->opc) {
2606 M_IST(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2610 M_IST(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2613 M_FST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2616 M_DST(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2620 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2622 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2623 M_ALD_DSEG(REG_ITMP3, disp);
2625 M_ASUB_IMM(96, REG_SP);
2627 M_AADD_IMM(96, REG_SP);
2629 /* and now restore the proper return value */
2631 switch (iptr->opc) {
2633 M_ILD(REG_RESULT2, REG_SP, ((rd->memuse + 1) * 8) + 4);
2637 M_ILD(REG_RESULT , REG_SP, (rd->memuse + 1) * 8);
2640 M_FLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2643 M_DLD(REG_FRESULT, REG_SP, (rd->memuse + 1) * 8);
2649 /* restore return address */
2651 p--; M_ALD(REG_RA, REG_SP, p * 8);
2653 /* restore saved registers */
2655 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2656 p--; M_ILD(rd->savintregs[i], REG_SP, p * 8);
2658 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2659 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2662 /* deallocate stack */
2664 if (cd->stackframesize)
2665 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2667 /* generate method profiling code */
2675 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2678 branch_target_t *table;
2680 table = iptr->dst.table;
2682 l = iptr->sx.s23.s2.tablelow;
2683 i = iptr->sx.s23.s3.tablehigh;
2685 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2686 M_INTMOVE(s1, REG_ITMP1);
2690 } else if (N_VALID_IMM(-l)) {
2691 M_ISUB_IMM(l, REG_ITMP1);
2693 ICONST(REG_ITMP2, l);
2694 M_ISUB(REG_ITMP2, REG_ITMP1);
2697 /* number of targets */
2703 ICONST(REG_ITMP2, i);
2704 M_ICMPU(REG_ITMP1, REG_ITMP2);
2705 emit_bge(cd, table[0].block);
2707 /* build jump table top down and use address of lowest entry */
2712 dseg_add_target(cd, table->block);
2717 /* length of dataseg after last dseg_add_target is used by load */
2719 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2720 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2721 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2722 M_JMP(RN, REG_ITMP1);
2727 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2730 lookup_target_t *lookup;
2732 lookup = iptr->dst.lookup;
2734 i = iptr->sx.s23.s2.lookupcount;
2736 MCODECHECK(8 + ((7 + 6) * i) + 5);
2737 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2740 if (N_VALID_IMM(lookup->value)) {
2741 M_ICMP_IMM(s1, lookup->value);
2743 ICONST(REG_ITMP2, lookup->value);
2744 M_ICMP(REG_ITMP2, s1);
2746 emit_beq(cd, lookup->target.block);
2750 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2755 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2757 bte = iptr->sx.s23.s3.bte;
2761 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2762 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2763 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2764 case ICMD_INVOKEINTERFACE:
2766 REPLACEMENT_POINT_INVOKE(cd, iptr);
2768 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2770 um = iptr->sx.s23.s3.um;
2771 md = um->methodref->parseddesc.md;
2774 lm = iptr->sx.s23.s3.fmiref->p.method;
2776 md = lm->parseddesc;
2780 s3 = md->paramcount;
2782 MCODECHECK((s3 << 1) + 64);
2784 /* copy arguments to registers or stack location */
2786 for (s3 = s3 - 1; s3 >= 0; s3--) {
2787 var = VAR(iptr->sx.s23.s2.args[s3]);
2789 /* Already Preallocated? */
2790 if (var->flags & PREALLOC)
2793 if (IS_INT_LNG_TYPE(var->type)) {
2794 if (!md->params[s3].inmemory) {
2795 if (IS_2_WORD_TYPE(var->type)) {
2797 GET_LOW_REG(md->params[s3].regoff),
2798 GET_HIGH_REG(md->params[s3].regoff)
2800 d = emit_load(jd, iptr, var, s1);
2804 s1 = md->params[s3].regoff;
2805 d = emit_load(jd, iptr, var, s1);
2810 if (IS_2_WORD_TYPE(var->type)) {
2811 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2812 M_LST(d, REG_SP, md->params[s3].regoff);
2815 d = emit_load(jd, iptr, var, REG_ITMP1);
2816 M_IST(d, REG_SP, md->params[s3].regoff);
2821 if (!md->params[s3].inmemory) {
2822 s1 = md->params[s3].regoff;
2823 d = emit_load(jd, iptr, var, s1);
2827 d = emit_load(jd, iptr, var, REG_FTMP1);
2828 if (IS_2_WORD_TYPE(var->type))
2829 M_DST(d, REG_SP, md->params[s3].regoff);
2831 M_FST(d, REG_SP, md->params[s3].regoff);
2836 /* generate method profiling code */
2840 switch (iptr->opc) {
2842 disp = dseg_add_functionptr(cd, bte->fp);
2844 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2845 if (N_VALID_DSEG_DISP(disp)) {
2846 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2848 N_LHI(REG_ITMP1, disp);
2849 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2853 case ICMD_INVOKESPECIAL:
2855 /* Implicit NULL pointer check */
2856 M_ILD(REG_ITMP1, REG_A0, 0);
2860 case ICMD_INVOKESTATIC:
2862 disp = dseg_add_unique_address(cd, um);
2864 patcher_add_patch_ref(jd, PATCHER_invokestatic_special,
2868 disp = dseg_add_address(cd, lm->stubroutine);
2870 if (N_VALID_DSEG_DISP(disp)) {
2871 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2873 N_LHI(REG_ITMP1, disp);
2874 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2878 case ICMD_INVOKEVIRTUAL:
2879 /* TODO softnull REG_A0 */
2882 patcher_add_patch_ref(jd, PATCHER_invokevirtual, um, 0);
2887 s1 = OFFSET(vftbl_t, table[0]) +
2888 sizeof(methodptr) * lm->vftblindex;
2891 /* implicit null-pointer check */
2893 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2894 M_ALD(REG_PV, REG_METHODPTR, s1);
2897 case ICMD_INVOKEINTERFACE:
2898 /* TODO softnull REG_A0 */
2900 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2901 * and -0xFFF in index register (itmp1)
2905 patcher_add_patch_ref(jd, PATCHER_invokeinterface, um, 0);
2911 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2912 sizeof(methodptr*) * lm->class->index;
2914 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2917 /* Implicit null-pointer check */
2918 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_object_t, vftbl));
2919 N_LHI(REG_ITMP1, s1);
2920 N_L(REG_METHODPTR, 0, REG_ITMP1, REG_METHODPTR);
2921 M_ALD(REG_PV, REG_METHODPTR, s2);
2925 /* generate the actual call */
2928 emit_restore_pv(cd);
2930 /* post call finalization */
2932 switch (iptr->opc) {
2934 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2935 emit_exception_check(cd, iptr); /* check for exception */
2939 /* generate method profiling code */
2941 PROFILE_CYCLE_START;
2943 /* store size of call code in replacement point */
2945 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2947 /* store return value */
2949 d = md->returntype.type;
2951 if (d != TYPE_VOID) {
2952 if (IS_INT_LNG_TYPE(d)) {
2953 if (IS_2_WORD_TYPE(d)) {
2954 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2955 M_LNGMOVE(REG_RESULT_PACKED, s1);
2958 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2959 M_INTMOVE(REG_RESULT, s1);
2963 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2964 M_FLTMOVE(REG_FRESULT, s1);
2966 emit_store_dst(jd, iptr, s1);
2972 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2974 /* val.a: (classinfo*) superclass */
2976 /* superclass is an interface:
2978 * OK if ((sub == NULL) ||
2979 * (sub->vftbl->interfacetablelength > super->index) &&
2980 * (sub->vftbl->interfacetable[-super->index] != NULL));
2982 * superclass is a class:
2984 * OK if ((sub == NULL) || (0
2985 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2986 * super->vftbl->diffval));
2989 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2990 /* object type cast-check */
2993 vftbl_t *supervftbl;
2996 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2997 # define LABEL_CLASS BRANCH_LABEL_2
2998 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2999 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
3000 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
3002 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3008 super = iptr->sx.s23.s3.c.cls;
3009 superindex = super->index;
3010 supervftbl = super->vftbl;
3013 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3014 CODEGEN_CRITICAL_SECTION_NEW;
3016 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3018 /* if class is not resolved, check which code to call */
3020 if (super == NULL) {
3022 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3024 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3026 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3027 iptr->sx.s23.s3.c.ref,
3030 ICONST(REG_ITMP2, ACC_INTERFACE);
3031 if (N_VALID_DSEG_DISP(disp)) {
3032 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3034 ICONST(REG_ITMP3, disp);
3035 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3037 emit_label_beq(cd, LABEL_CLASS);
3040 /* interface checkcast code */
3042 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3043 if (super == NULL) {
3044 patcher_add_patch_ref(jd,
3045 PATCHER_checkcast_instanceof_interface,
3046 iptr->sx.s23.s3.c.ref,
3050 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3053 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3054 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3055 M_ISUB_IMM(superindex, REG_ITMP3);
3056 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
3059 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3060 superindex * sizeof(methodptr*))
3062 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3063 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3065 if (super == NULL) {
3066 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3070 /* class checkcast code */
3072 if (super == NULL) {
3073 emit_label(cd, LABEL_CLASS);
3076 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3077 if (super == NULL) {
3078 disp = dseg_add_unique_address(cd, NULL);
3080 patcher_add_patch_ref(jd,
3081 PATCHER_resolve_classref_to_vftbl,
3082 iptr->sx.s23.s3.c.ref,
3086 disp = dseg_add_address(cd, supervftbl);
3088 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3091 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
3092 M_ALD_DSEG(REG_ITMP3, disp);
3094 CODEGEN_CRITICAL_SECTION_START;
3096 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3097 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3098 M_ISUB(REG_ITMP3, REG_ITMP2);
3099 M_ALD_DSEG(REG_ITMP3, disp);
3100 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3102 CODEGEN_CRITICAL_SECTION_END;
3104 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3105 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3106 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3107 /* Branch if greater then */
3108 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3111 if (super == NULL) {
3112 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3113 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3114 } else if (super->flags & ACC_INTERFACE) {
3115 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3117 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3120 d = codegen_reg_of_dst(jd, iptr, s1);
3122 # undef LABEL_EXIT_CHECK_NULL
3124 # undef LABEL_EXIT_INTERFACE_NULL
3125 # undef LABEL_EXIT_INTERFACE_DONE
3126 # undef LABEL_EXIT_CLASS_NULL
3129 /* array type cast-check */
3131 s1 = emit_load_s1(jd, iptr, REG_A0);
3132 M_INTMOVE(s1, REG_A0);
3134 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3135 disp = dseg_add_unique_address(cd, NULL);
3137 patcher_add_patch_ref(jd,
3138 PATCHER_resolve_classref_to_classinfo,
3139 iptr->sx.s23.s3.c.ref,
3143 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3145 M_ALD_DSEG(REG_A1, disp);
3146 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3147 M_ALD_DSEG(REG_ITMP1, disp);
3148 M_ASUB_IMM(96, REG_SP);
3149 M_JSR(REG_RA, REG_ITMP1);
3150 M_AADD_IMM(96, REG_SP);
3152 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3153 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3155 d = codegen_reg_of_dst(jd, iptr, s1);
3159 emit_store_dst(jd, iptr, d);
3162 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3163 /* val.a: (classinfo*) superclass */
3165 /* superclass is an interface:
3167 * return (sub != NULL) &&
3168 * (sub->vftbl->interfacetablelength > super->index) &&
3169 * (sub->vftbl->interfacetable[-super->index] != NULL);
3171 * superclass is a class:
3173 * return ((sub != NULL) && (0
3174 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3175 * super->vftbl->diffvall));
3177 * If superclass is unresolved, we include both code snippets
3178 * above, a patcher resolves the class' flags and we select
3179 * the right code at runtime.
3184 vftbl_t *supervftbl;
3187 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3193 super = iptr->sx.s23.s3.c.cls;
3194 superindex = super->index;
3195 supervftbl = super->vftbl;
3198 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3199 # define LABEL_CLASS BRANCH_LABEL_2
3200 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3201 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3202 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3203 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3205 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3206 CODEGEN_CRITICAL_SECTION_NEW;
3208 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3209 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3211 M_MOV(s1, REG_ITMP1);
3215 /* if class is not resolved, check which code to call */
3217 if (super == NULL) {
3221 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3223 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3225 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_flags,
3226 iptr->sx.s23.s3.c.ref, disp);
3228 ICONST(REG_ITMP2, ACC_INTERFACE);
3230 if (N_VALID_DSEG_DISP(disp)) {
3231 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3233 ICONST(REG_ITMP3, disp);
3234 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3237 emit_label_beq(cd, LABEL_CLASS);
3240 /* interface instanceof code */
3242 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3243 if (super == NULL) {
3244 /* If d == REG_ITMP2, then it's destroyed in check
3249 patcher_add_patch_ref(jd,
3250 PATCHER_checkcast_instanceof_interface,
3251 iptr->sx.s23.s3.c.ref, 0);
3256 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3259 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3260 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3261 M_ISUB_IMM(superindex, REG_ITMP3);
3263 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3267 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3268 superindex * sizeof(methodptr*))
3270 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3272 /* d := (REG_ITMP1 != 0) */
3274 N_LTR(d, REG_ITMP1);
3275 M_BEQ(SZ_BRC + SZ_LHI);
3278 if (super == NULL) {
3279 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3283 /* class instanceof code */
3285 if (super == NULL) {
3286 emit_label(cd, LABEL_CLASS);
3289 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3290 if (super == NULL) {
3291 disp = dseg_add_unique_address(cd, NULL);
3293 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_vftbl,
3294 iptr->sx.s23.s3.c.ref,
3298 disp = dseg_add_address(cd, supervftbl);
3303 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3306 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
3307 M_ALD_DSEG(REG_ITMP2, disp);
3309 CODEGEN_CRITICAL_SECTION_START;
3311 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3312 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3313 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3315 CODEGEN_CRITICAL_SECTION_END;
3317 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3319 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3321 M_BGT(SZ_BRC + SZ_LHI);
3325 if (super == NULL) {
3326 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3327 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3328 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3329 } else if (super->flags & ACC_INTERFACE) {
3330 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3331 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3333 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3336 # undef LABEL_EXIT_CHECK_NULL
3338 # undef LABEL_EXIT_INTERFACE_NULL
3339 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3340 # undef LABEL_EXIT_INTERFACE_DONE
3341 # undef LABEL_EXIT_CLASS_NULL
3343 emit_store_dst(jd, iptr, d);
3349 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3351 /* check for negative sizes and copy sizes to stack if necessary */
3353 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3356 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3358 /* copy SAVEDVAR sizes to stack */
3359 var = VAR(iptr->sx.s23.s2.args[s1]);
3361 /* Already Preallocated? */
3362 if (!(var->flags & PREALLOC)) {
3363 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3364 M_IST(s2, REG_SP, s1 * 4);
3368 /* is a patcher function set? */
3370 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3371 disp = dseg_add_unique_address(cd, 0);
3373 patcher_add_patch_ref(jd, PATCHER_resolve_classref_to_classinfo,
3374 iptr->sx.s23.s3.c.ref,
3378 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3380 /* a0 = dimension count */
3382 ICONST(REG_A0, iptr->s1.argcount);
3384 /* a1 = classinfo */
3386 M_ALD_DSEG(REG_A1, disp);
3388 /* a2 = pointer to dimensions = stack pointer */
3390 M_MOV(REG_SP, REG_A2);
3392 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3393 M_ALD_DSEG(REG_ITMP1, disp);
3394 M_ASUB_IMM(96, REG_SP);
3395 M_JSR(REG_RA, REG_ITMP1);
3396 M_AADD_IMM(96, REG_SP);
3398 /* check for exception before result assignment */
3400 emit_exception_check(cd, iptr);
3402 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3403 M_INTMOVE(REG_RESULT, s1);
3404 emit_store_dst(jd, iptr, s1);
3409 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3413 } /* for instruction */
3415 MCODECHECK(512); /* XXX require a lower number? */
3417 /* At the end of a basic block we may have to append some nops,
3418 because the patcher stub calling code might be longer than the
3419 actual instruction. So codepatching does not change the
3420 following block unintentionally. */
3422 if (cd->mcodeptr < cd->lastmcodeptr) {
3423 while (cd->mcodeptr < cd->lastmcodeptr) {
3428 } /* if (bptr -> flags >= BBREACHED) */
3429 } /* for basic block */
3431 dseg_createlinenumbertable(cd);
3433 /* generate stubs */
3435 emit_patcher_traps(jd);
3437 /* everything's ok */
3443 /* codegen_emit_stub_compiler **************************************************
3445 Emits a stub routine which calls the compiler.
3447 *******************************************************************************/
3449 void codegen_emit_stub_compiler(jitdata *jd)
3454 /* get required compiler data */
3459 /* code for the stub */
3461 /* don't touch ITMP3 as it cointains the return address */
3463 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3465 M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */
3466 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3467 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3472 /* codegen_emit_stub_native ****************************************************
3474 Emits a stub routine which calls a native method.
3476 *******************************************************************************/
3479 arguments on stack \
3480 -------------------------------------------------| <- SP on nativestub entry
3482 callee saved int regs (none) |
3483 callee saved float regs (none) | stack frame like in cacao
3484 local variable slots (none) |
3485 arguments for calling methods (none) /
3486 ------------------------------------------------------------------ <- datasp
3491 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3492 0 - 96 register save area for callee /
3493 -------------------------------------------------------- <- SP native method
3495 SP after method entry
3498 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3506 s4 i, j; /* count variables */
3511 /* get required compiler data */
3518 /* initialize variables */
3521 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3523 /* calculate stack frame size */
3525 cd->stackframesize =
3526 1 + /* r14 - return address */ +
3527 ((sizeof(stackframeinfo) + 7) / 8) +
3528 ((sizeof(localref_table) + 7) / 8) +
3530 (INT_ARG_CNT + FLT_ARG_CNT) +
3531 nmd->memuse + /* parameter passing */
3532 (96 / 8) /* required by ABI */;
3534 /* create method header */
3536 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3537 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3538 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3539 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3540 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3541 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3542 (void) dseg_addlinenumbertablesize(cd);
3543 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3545 /* generate stub code */
3547 N_AHI(REG_SP, -(cd->stackframesize * 8));
3548 N_AHI(REG_PV, N_PV_OFFSET);
3550 /* generate native method profiling code */
3552 #if defined(ENABLE_PROFILING)
3553 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3554 /* count frequency */
3555 M_ALD_DSEG(REG_ITMP1, CodeinfoPointer);
3556 ICONST(REG_ITMP2, 1);
3557 N_AL(REG_ITMP2, OFFSET(codeinfo, frequency), RN, REG_ITMP1);
3558 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
3562 /* save return address */
3564 N_ST(R14, (cd->stackframesize - 1) * 8, RN, REG_SP);
3566 #if !defined(NDEBUG)
3567 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3568 emit_verbosecall_enter(jd);
3571 /* get function address (this must happen before the stackframeinfo) */
3573 disp = dseg_add_functionptr(cd, f);
3575 #if !defined(WITH_STATIC_CLASSPATH)
3577 patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, disp);
3580 M_ILD_DSEG(REG_ITMP1, disp);
3582 j = 96 + (nmd->memuse * 8);
3584 /* todo some arg registers are not volatile in C-abi terms */
3586 /* save integer and float argument registers */
3588 for (i = 0; i < md->paramcount; i++) {
3589 if (! md->params[i].inmemory) {
3590 s1 = md->params[i].regoff;
3591 t = md->paramtypes[i].type;
3593 if (IS_INT_LNG_TYPE(t)) {
3594 if (IS_2_WORD_TYPE(t)) {
3595 /* todo store multiple */
3596 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3597 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3599 N_ST(s1, j, RN, REG_SP);
3602 if (IS_2_WORD_TYPE(t)) {
3603 N_STD(s1, j, RN, REG_SP);
3605 N_STE(s1, j, RN, REG_SP);
3613 N_ST(REG_ITMP1, j, RN, REG_SP);
3615 /* create dynamic stack info */
3617 N_LAE(REG_A0, (cd->stackframesize - 1) * 8 , RN, REG_SP); /* datasp */
3618 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3619 N_LAE(REG_A2, cd->stackframesize * 8, RN, REG_SP); /* old SP */
3620 N_L(REG_A3, (cd->stackframesize - 1) * 8, RN, REG_SP); /* return address */
3622 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3623 M_ILD_DSEG(REG_ITMP1, disp);
3625 M_CALL(REG_ITMP1); /* call */
3627 /* restore integer and float argument registers */
3629 j = 96 + (nmd->memuse * 8);
3631 for (i = 0; i < md->paramcount; i++) {
3632 if (! md->params[i].inmemory) {
3633 s1 = md->params[i].regoff;
3634 t = md->paramtypes[i].type;
3636 if (IS_INT_LNG_TYPE(t)) {
3637 if (IS_2_WORD_TYPE(t)) {
3638 /* todo load multiple ! */
3639 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3640 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3642 N_L(s1, j, RN, REG_SP);
3645 if (IS_2_WORD_TYPE(t)) {
3646 N_LD(s1, j, RN, REG_SP);
3648 N_LE(s1, j, RN, REG_SP);
3656 N_L(REG_ITMP1, j, RN, REG_SP);
3658 /* copy or spill arguments to new locations */
3660 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3661 t = md->paramtypes[i].type;
3663 if (IS_INT_LNG_TYPE(t)) {
3665 if (!md->params[i].inmemory) {
3667 s1 = md->params[i].regoff;
3669 if (!nmd->params[j].inmemory) {
3670 s2 = nmd->params[j].regoff;
3671 if (IS_2_WORD_TYPE(t)) {
3687 s2 = nmd->params[j].regoff;
3688 if (IS_2_WORD_TYPE(t)) {
3703 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3704 s2 = nmd->params[j].regoff;
3706 if (IS_2_WORD_TYPE(t)) {
3707 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3709 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3714 /* We only copy spilled float arguments, as the float argument */
3715 /* registers keep unchanged. */
3717 if (md->params[i].inmemory) {
3718 s1 = cd->stackframesize * 8 + md->params[i].regoff;
3719 s2 = nmd->params[j].regoff;
3721 if (IS_2_WORD_TYPE(t)) {
3722 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3724 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3730 /* put class into second argument register */
3732 if (m->flags & ACC_STATIC) {
3733 disp = dseg_add_address(cd, m->class);
3734 M_ILD_DSEG(REG_A1, disp);
3737 /* put env into first argument register */
3739 disp = dseg_add_address(cd, _Jv_env);
3740 M_ILD_DSEG(REG_A0, disp);
3742 /* do the native function call */
3744 M_CALL(REG_ITMP1); /* call */
3746 /* save return value */
3748 t = md->returntype.type;
3750 if (t != TYPE_VOID) {
3751 if (IS_INT_LNG_TYPE(t)) {
3752 if (IS_2_WORD_TYPE(t)) {
3753 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3755 N_ST(REG_RESULT, 96, RN, REG_SP);
3758 if (IS_2_WORD_TYPE(t)) {
3759 N_STD(REG_FRESULT, 96, RN, REG_SP);
3761 N_STE(REG_FRESULT, 96, RN, REG_SP);
3766 #if !defined(NDEBUG)
3767 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3768 emit_verbosecall_exit(jd);
3771 /* remove native stackframe info */
3773 N_LAE(REG_A0, (cd->stackframesize - 1) * 8, RN, REG_SP); /* datasp */
3774 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3775 M_ALD_DSEG(REG_ITMP1, disp);
3777 N_LR(REG_ITMP3, REG_RESULT);
3779 /* restore return value */
3781 if (t != TYPE_VOID) {
3782 if (IS_INT_LNG_TYPE(t)) {
3783 if (IS_2_WORD_TYPE(t)) {
3784 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3786 N_L(REG_RESULT, 96, RN, REG_SP);
3789 if (IS_2_WORD_TYPE(t)) {
3790 N_LD(REG_FRESULT, 96, RN, REG_SP);
3792 N_LE(REG_FRESULT, 96, RN, REG_SP);
3797 /* load return address */
3799 N_L(REG_ITMP2, (cd->stackframesize - 1) * 8, RN, REG_SP);
3801 /* remove stackframe */
3803 N_AHI(REG_SP, cd->stackframesize * 8);
3805 /* test for exception */
3807 N_LTR(REG_ITMP3, REG_ITMP3);
3808 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3812 N_BCR(DD_ANY, REG_ITMP2);
3814 /* handle exception */
3816 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3817 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3821 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3824 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3825 M_ALD_DSEG(REG_ITMP3, disp);
3826 M_JMP(RN, REG_ITMP3);
3828 /* generate patcher stubs */
3830 emit_patcher_traps(jd);
3833 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3834 codegendata *cd = jd->cd;
3835 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3837 M_MOV(reg, tempregnum);
3845 * These are local overrides for various environment variables in Emacs.
3846 * Please do not remove this and leave it at the end of the file, where
3847 * Emacs will automagically detect them.
3848 * ---------------------------------------------------------------------
3851 * indent-tabs-mode: t
3855 * vim:noexpandtab:sw=4:ts=4: