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 8068 2007-06-12 15:50:35Z pm $
39 #include "vm/jit/s390/arch.h"
40 #include "vm/jit/s390/codegen.h"
41 #include "vm/jit/s390/emit.h"
43 #include "mm/memory.h"
44 #include "native/jni.h"
45 #include "native/native.h"
47 #if defined(ENABLE_THREADS)
48 # include "threads/native/lock.h"
51 #include "vm/builtin.h"
52 #include "vm/exceptions.h"
53 #include "vm/global.h"
54 #include "vmcore/loader.h"
55 #include "vmcore/options.h"
56 #include "vmcore/statistics.h"
57 #include "vm/stringlocal.h"
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/codegen-common.h"
61 #include "vm/jit/dseg.h"
62 #include "vm/jit/emit-common.h"
63 #include "vm/jit/jit.h"
64 #include "vm/jit/methodheader.h"
65 #include "vm/jit/parse.h"
66 #include "vm/jit/patcher.h"
67 #include "vm/jit/reg.h"
68 #include "vm/jit/replace.h"
69 #include "vm/jit/stacktrace.h"
70 #include "vm/jit/abi.h"
71 #include "vm/jit/emit-common.h"
73 #if defined(ENABLE_LSRA)
74 # include "vm/jit/allocator/lsra.h"
77 #define OOPS() assert(0);
78 #define SUPPORT_HERCULES 1
82 /* codegen *********************************************************************
84 Generates machine code.
86 *******************************************************************************/
89 bool codegen_emit(jitdata *jd)
95 s4 len, s1, s2, s3, d, dd, disp;
98 varinfo *var, *var1, *var2, *dst;
102 constant_classref *cr;
103 unresolved_class *uc;
104 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
105 unresolved_method *um;
106 builtintable_entry *bte;
109 unresolved_field *uf;
112 rplpoint *replacementpoint;
116 /* get required compiler data */
123 /* prevent compiler warnings */
136 /* space to save used callee saved registers */
138 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
139 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
141 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
144 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
147 #if defined(ENABLE_THREADS)
148 /* Space to save argument of monitor_enter and Return Values to
149 survive monitor_exit. The stack position for the argument can
150 not be shared with place to save the return register
151 since both values reside in R2. */
153 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
154 /* reserve 2 slots for long/double return values for monitorexit */
156 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
157 cd->stackframesize += 3;
159 cd->stackframesize += 2;
163 /* Keep stack of non-leaf functions 16-byte aligned for calls into
164 native code e.g. libc or jni (alignment problems with
167 if (!jd->isleafmethod || opt_verbosecall )
168 /* TODO really 16 bytes ? */
169 cd->stackframesize = (cd->stackframesize + 3) & ~3;
171 /* create method header */
173 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
174 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
176 #if defined(ENABLE_THREADS)
177 /* IsSync contains the offset relative to the stack pointer for the
178 argument of monitor_exit used in the exception handler. Since the
179 offset could be zero and give a wrong meaning of the flag it is
183 if (checksync && (m->flags & ACC_SYNCHRONIZED))
184 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
188 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
190 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
191 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
192 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
194 (void) dseg_addlinenumbertablesize(cd);
196 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
198 /* create exception table */
200 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
201 dseg_add_target(cd, ex->start);
202 dseg_add_target(cd, ex->end);
203 dseg_add_target(cd, ex->handler);
204 (void) dseg_add_unique_address(cd, ex->catchtype.any);
207 /* generate method profiling code */
209 #if defined(ENABLE_PROFILING)
210 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
211 /* count frequency */
213 M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
214 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
215 M_IADD_IMM(1, REG_ITMP2);
216 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
218 /* PROFILE_CYCLE_START; */
222 /* create stack frame (if necessary) */
224 if (cd->stackframesize)
225 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
227 /* save used callee saved registers and return address */
229 p = cd->stackframesize;
230 p--; M_AST(REG_RA, REG_SP, p * 4);
232 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
233 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
235 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
236 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
239 /* take arguments out of register or stack frame */
243 for (p = 0, l = 0; p < md->paramcount; p++) {
244 t = md->paramtypes[p].type;
245 varindex = jd->local_map[l * 5 + t];
248 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
251 if (varindex == UNUSED)
256 s1 = md->params[p].regoff;
257 if (IS_INT_LNG_TYPE(t)) { /* integer args */
258 if (IS_2_WORD_TYPE(t)) {
266 if (!md->params[p].inmemory) { /* register arguments */
267 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
268 if (IS_2_WORD_TYPE(t))
269 M_LNGMOVE(s2, var->vv.regoff);
271 M_INTMOVE(s2, var->vv.regoff);
273 } else { /* reg arg -> spilled */
274 if (IS_2_WORD_TYPE(t))
275 M_LST(s2, REG_SP, var->vv.regoff * 4);
277 M_IST(s2, REG_SP, var->vv.regoff * 4);
280 } else { /* stack arguments */
281 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
282 if (IS_2_WORD_TYPE(t))
283 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
285 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
287 } else { /* stack arg -> spilled */
288 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
289 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
290 if (IS_2_WORD_TYPE(t)) {
291 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4);
292 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
297 } else { /* floating args */
298 if (!md->params[p].inmemory) { /* register arguments */
300 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
301 M_FLTMOVE(s2, var->vv.regoff);
303 } else { /* reg arg -> spilled */
304 if (IS_2_WORD_TYPE(t))
305 M_DST(s2, REG_SP, var->vv.regoff * 4);
307 M_FST(s2, REG_SP, var->vv.regoff * 4);
310 } else { /* stack arguments */
311 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
312 if (IS_2_WORD_TYPE(t))
313 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
316 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
318 } else { /* stack-arg -> spilled */
319 if (IS_2_WORD_TYPE(t)) {
320 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
321 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
322 var->vv.regoff = cd->stackframesize + s1;
325 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
326 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
333 /* save monitorenter argument */
335 #if defined(ENABLE_THREADS)
336 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
337 /* stack offset for monitor argument */
342 if (opt_verbosecall) {
343 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
345 for (p = 0; p < INT_ARG_CNT; p++)
346 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
348 for (p = 0; p < FLT_ARG_CNT; p++)
349 M_FST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
351 s1 += ((INT_ARG_CNT + FLT_ARG_CNT) * 2);
355 /* decide which monitor enter function to call */
357 if (m->flags & ACC_STATIC) {
358 disp = dseg_add_address(cd, &m->class->object.header);
359 M_ALD(REG_A0, REG_PV, disp);
363 M_BNE(SZ_BRC + SZ_ILL);
364 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
367 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
368 M_ALD(REG_ITMP3, REG_PV, disp);
370 M_AST(REG_A0, REG_SP, s1 * 4);
372 M_ASUB_IMM(96, REG_SP);
374 M_AADD_IMM(96, REG_SP);
377 if (opt_verbosecall) {
378 for (p = 0; p < INT_ARG_CNT; p++)
379 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
381 for (p = 0; p < FLT_ARG_CNT; p++)
382 M_FLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
384 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
391 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
392 emit_verbosecall_enter(jd);
393 #endif /* !defined(NDEBUG) */
397 /* end of header generation */
399 replacementpoint = jd->code->rplpoints;
402 /* walk through all basic blocks */
404 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
406 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
408 if (bptr->flags >= BBREACHED) {
410 /* branch resolving */
412 codegen_resolve_branchrefs(cd, bptr);
414 /* handle replacement points */
417 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
418 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
422 assert(cd->lastmcodeptr <= cd->mcodeptr);
423 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
427 /* copy interface registers to their destination */
432 /* generate basicblock profiling code */
434 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
435 /* count frequency */
437 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
438 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
440 /* if this is an exception handler, start profiling again */
442 if (bptr->type == BBTYPE_EXH)
446 #if defined(ENABLE_LSRA)
450 src = bptr->invars[len];
451 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
452 if (bptr->type == BBTYPE_EXH) {
453 /* d = reg_of_var(rd, src, REG_ITMP1); */
454 if (!IS_INMEMORY(src->flags))
458 M_INTMOVE(REG_ITMP1, d);
459 emit_store(jd, NULL, src, d);
469 var = VAR(bptr->invars[len]);
470 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
471 if (bptr->type == BBTYPE_EXH) {
472 d = codegen_reg_of_var(0, var, REG_ITMP1);
473 M_INTMOVE(REG_ITMP1, d);
474 emit_store(jd, NULL, var, d);
478 assert((var->flags & INOUT));
481 #if defined(ENABLE_LSRA)
484 /* walk through all instructions */
489 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
490 if (iptr->line != currentline) {
491 dseg_addlinenumber(cd, iptr->line);
492 currentline = iptr->line;
495 MCODECHECK(1024); /* 1KB should be enough */
498 case ICMD_NOP: /* ... ==> ... */
499 case ICMD_POP: /* ..., value ==> ... */
500 case ICMD_POP2: /* ..., value, value ==> ... */
501 case ICMD_INLINE_START: /* internal ICMDs */
502 case ICMD_INLINE_END:
505 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
506 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
507 emit_nullpointer_check(cd, iptr, s1);
510 /* constant operations ************************************************/
512 case ICMD_ICONST: /* ... ==> ..., constant */
513 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
514 ICONST(d, iptr->sx.val.i);
515 emit_store_dst(jd, iptr, d);
518 case ICMD_LCONST: /* ... ==> ..., constant */
520 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
521 LCONST(d, iptr->sx.val.l);
522 emit_store_dst(jd, iptr, d);
525 case ICMD_FCONST: /* ... ==> ..., constant */
526 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
527 disp = dseg_add_float(cd, iptr->sx.val.f);
528 M_FLDN(d, REG_PV, disp, REG_ITMP1);
529 emit_store_dst(jd, iptr, d);
532 case ICMD_DCONST: /* ... ==> ..., constant */
533 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
534 disp = dseg_add_double(cd, iptr->sx.val.d);
535 M_DLDN(d, REG_PV, disp, REG_ITMP1);
536 emit_store_dst(jd, iptr, d);
539 case ICMD_ACONST: /* ... ==> ..., constant */
540 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
542 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
543 cr = iptr->sx.val.c.ref;
544 disp = dseg_add_unique_address(cd, cr);
546 /* PROFILE_CYCLE_STOP; */
548 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
551 /* PROFILE_CYCLE_START; */
553 M_ALD(d, REG_PV, disp);
555 if (iptr->sx.val.anyptr == 0) {
558 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
559 M_ALD(d, REG_PV, disp);
562 emit_store_dst(jd, iptr, d);
566 /* load/store/copy/move operations ************************************/
568 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
569 case ICMD_ALOAD: /* s1 = local variable */
573 case ICMD_ISTORE: /* ..., value ==> ... */
584 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
588 /* integer operations *************************************************/
590 case ICMD_INEG: /* ..., value ==> ..., - value */
592 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
593 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
595 emit_store_dst(jd, iptr, d);
599 case ICMD_LNEG: /* ..., value ==> ..., - value */
601 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
602 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
603 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
604 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
605 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
606 N_AHI(GET_HIGH_REG(d), -1);
607 emit_store_dst(jd, iptr, d);
610 case ICMD_I2L: /* ..., value ==> ..., value */
612 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
613 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
615 M_INTMOVE(s1, GET_HIGH_REG(d));
616 ICONST(GET_LOW_REG(d), 0);
617 M_SRDA_IMM(32, GET_HIGH_REG(d));
619 emit_copy_dst(jd, iptr, d);
620 emit_store_dst(jd, iptr, d);
621 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
625 case ICMD_L2I: /* ..., value ==> ..., value */
626 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
627 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
628 M_INTMOVE(GET_LOW_REG(s1), d);
629 emit_store_dst(jd, iptr, d);
632 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
633 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
634 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
638 emit_store_dst(jd, iptr, d);
641 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
642 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
643 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
647 emit_store_dst(jd, iptr, d);
650 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
652 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
653 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
657 emit_store_dst(jd, iptr, d);
660 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
662 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
663 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
664 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
671 emit_store_dst(jd, iptr, d);
676 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
677 /* sx.val.i = constant */
678 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
679 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
682 if (N_VALID_IMM(iptr->sx.val.i)) {
683 M_IADD_IMM(iptr->sx.val.i, d);
685 ICONST(REG_ITMP2, iptr->sx.val.i);
686 M_IADD(REG_ITMP2, d);
688 emit_store_dst(jd, iptr, d);
691 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
693 /* M, (r, q) -> (r, q) */
695 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
697 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
698 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
699 dd = GET_HIGH_REG(d);
708 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
709 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
719 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
720 N_AHI(GET_HIGH_REG(d), 1);
722 emit_store_dst(jd, iptr, d);
725 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
726 /* sx.val.l = constant */
728 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
729 dd = GET_HIGH_REG(d);
731 s1 = emit_load_s1_high(jd, iptr, dd);
732 s3 = iptr->sx.val.l >> 32;
736 if (N_VALID_IMM(s3)) {
739 ICONST(REG_ITMP3, s3);
740 M_IADD(REG_ITMP3, dd);
744 s1 = emit_load_s1_low(jd, iptr, dd);
745 s3 = iptr->sx.val.l & 0xffffffff;
746 ICONST(REG_ITMP3, s3);
749 N_ALR(dd, REG_ITMP3);
751 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
752 N_AHI(GET_HIGH_REG(d), 1);
754 emit_store_dst(jd, iptr, d);
757 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
759 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
760 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
761 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
763 M_INTMOVE(s1, REG_ITMP1);
764 M_ISUB(s2, REG_ITMP1);
765 M_INTMOVE(REG_ITMP1, d);
770 emit_store_dst(jd, iptr, d);
774 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
775 /* sx.val.i = constant */
777 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
778 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
781 if (N_VALID_IMM(-iptr->sx.val.i)) {
782 M_ISUB_IMM(iptr->sx.val.i, d);
784 ICONST(REG_ITMP2, iptr->sx.val.i);
785 M_ISUB(REG_ITMP2, d);
787 emit_store_dst(jd, iptr, d);
791 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
793 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
795 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
796 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
797 dd = GET_HIGH_REG(d);
800 M_INTMOVE(s2, REG_ITMP3);
807 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
808 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
812 M_INTMOVE(s2, REG_ITMP3);
819 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
820 N_AHI(GET_HIGH_REG(d), -1);
822 emit_store_dst(jd, iptr, d);
825 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
826 /* sx.val.l = constant */
828 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
830 dd = GET_HIGH_REG(d);
831 s1 = emit_load_s1_high(jd, iptr, dd);
832 s3 = iptr->sx.val.l >> 32;
836 if (N_VALID_IMM(-s3)) {
839 ICONST(REG_ITMP3, s3);
840 M_ISUB(REG_ITMP3, dd);
844 s1 = emit_load_s1_low(jd, iptr, dd);
845 s3 = iptr->sx.val.l & 0xffffffff;
846 ICONST(REG_ITMP3, s3);
849 N_SLR(dd, REG_ITMP3);
851 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
852 N_AHI(GET_HIGH_REG(d), -1);
854 emit_store_dst(jd, iptr, d);
857 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
859 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
860 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
861 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
868 emit_store_dst(jd, iptr, d);
872 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
873 /* sx.val.i = constant */
874 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
875 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
877 if (iptr->sx.val.i == 2) {
879 } else if (N_VALID_IMM(iptr->sx.val.i)) {
880 M_IMUL_IMM(iptr->sx.val.i, d);
882 disp = dseg_add_s4(cd, iptr->sx.val.i);
883 M_ILD(REG_ITMP2, REG_PV, disp);
884 M_IMUL(REG_ITMP2, d);
886 emit_store_dst(jd, iptr, d);
889 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
890 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
892 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
893 emit_arithmetic_check(cd, iptr, s2);
895 /* For this operation we need a register pair.
896 * We will use r0 and itmp1 and will backup r0.
899 M_INTMOVE(R0, REG_ITMP3);
901 /* We won't check for division by 0, we catch a SIGFPE instead
902 * Special case 0x80000000 / 0xffffffff handled by signal handler too.
905 s1 = emit_load_s1(jd, iptr, R0);
914 d = codegen_reg_of_dst(jd, iptr, R0);
918 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
919 M_INTMOVE(REG_ITMP1, d);
923 emit_store_dst(jd, iptr, d);
925 /* If destionation of operation was not register R0,
929 if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
930 M_INTMOVE(REG_ITMP3, R0);
935 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
936 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
938 bte = iptr->sx.s23.s3.bte;
941 /* test s2 for zero */
943 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
944 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
945 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
946 emit_arithmetic_check(cd, iptr, REG_ITMP3);
950 disp = dseg_add_functionptr(cd, bte->fp);
954 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
956 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
957 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
961 M_ASUB_IMM(96, REG_SP);
962 M_ALD(REG_ITMP3, REG_PV, disp);
963 M_JSR(REG_RA, REG_ITMP3);
964 M_AADD_IMM(96, REG_SP);
968 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
969 M_LNGMOVE(REG_RESULT_PACKED, d);
970 emit_store_dst(jd, iptr, d);
974 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
975 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
976 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
978 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
979 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
980 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
982 /* Use only 5 bits of sencond operand. */
984 M_INTMOVE(s2, REG_ITMP2);
986 ICONST(REG_ITMP3, 0x1F);
987 M_IAND(REG_ITMP3, s2);
1004 emit_store_dst(jd, iptr, d);
1007 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1008 /* sx.val.i = constant */
1012 assert(iptr->sx.val.i <= 32);
1014 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1015 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1022 s3 = (1 << iptr->sx.val.i) - 1;
1024 if (N_VALID_IMM(s3)) {
1027 ICONST(REG_ITMP1, -1);
1028 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1029 M_IADD(REG_ITMP1, d);
1032 N_BRC_BACK_PATCH(ref);
1034 M_SRA_IMM(iptr->sx.val.i, d);
1036 emit_store_dst(jd, iptr, d);
1041 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1042 /* sx.val.i = constant */
1044 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1045 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1048 M_MOV(s1, REG_ITMP1);
1052 ICONST(REG_ITMP3, iptr->sx.val.i);
1055 M_IAND(REG_ITMP3, d);
1058 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1064 emit_store_dst(jd, iptr, d);
1068 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1069 /* sx.val.i = constant */
1070 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1071 /* sx.val.i = constant */
1072 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1073 /* sx.val.i = constant */
1074 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1075 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1079 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1081 switch (iptr->opc) {
1082 case ICMD_ISHLCONST:
1085 case ICMD_ISHRCONST:
1088 case ICMD_IUSHRCONST:
1095 emit_store_dst(jd, iptr, d);
1098 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1100 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1102 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1104 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1106 /* Use only 6 bits of second operand */
1108 M_INTMOVE(s2, REG_ITMP3);
1110 ICONST(REG_ITMP2, 0x3F);
1111 M_IAND(REG_ITMP2, s2);
1113 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1115 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1116 M_INTMOVE(s2, REG_ITMP3);
1120 s1 = emit_load_s1(jd, iptr, d);
1124 switch (iptr->opc) {
1126 M_SLDL(s2, GET_HIGH_REG(d));
1129 M_SRDA(s2, GET_HIGH_REG(d));
1132 M_SRDL(s2, GET_HIGH_REG(d));
1138 emit_copy_dst(jd, iptr, d);
1139 emit_store_dst(jd, iptr, d);
1140 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1144 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1145 /* sx.val.i = constant */
1146 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1147 /* sx.val.i = constant */
1148 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1149 /* sx.val.l = constant */
1152 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1153 s1 = emit_load_s1(jd, iptr, d);
1157 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1159 switch (iptr->opc) {
1160 case ICMD_LSHLCONST:
1161 N_SLDL(GET_HIGH_REG(d), disp, RN);
1163 case ICMD_LSHRCONST:
1164 N_SRDA(GET_HIGH_REG(d), disp, RN);
1166 case ICMD_LUSHRCONST:
1167 N_SRDL(GET_HIGH_REG(d), disp, RN);
1170 N_SLDL(GET_HIGH_REG(d), disp, RN);
1176 emit_copy_dst(jd, iptr, d);
1177 emit_store_dst(jd, iptr, d);
1178 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1182 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1184 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1185 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1186 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1193 emit_store_dst(jd, iptr, d);
1197 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1199 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1200 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1201 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1208 emit_store_dst(jd, iptr, d);
1212 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1214 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1215 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1216 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1223 emit_store_dst(jd, iptr, d);
1229 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1230 /* sx.val.i = constant */
1231 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1232 /* sx.val.i = constant */
1233 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1234 /* sx.val.i = constant */
1236 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1237 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1240 ICONST(REG_ITMP2, iptr->sx.val.i);
1242 switch (iptr->opc) {
1243 case ICMD_IANDCONST:
1244 M_IAND(REG_ITMP2, d);
1246 case ICMD_IXORCONST:
1247 M_IXOR(REG_ITMP2, d);
1250 M_IOR(REG_ITMP2, d);
1256 emit_store_dst(jd, iptr, d);
1260 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1261 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1262 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1264 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1266 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1267 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1268 dd = GET_LOW_REG(d);
1270 switch (iptr->opc) {
1299 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1300 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1301 dd = GET_HIGH_REG(d);
1303 switch (iptr->opc) {
1332 emit_store_dst(jd, iptr, d);
1335 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1336 /* sx.val.l = constant */
1337 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1338 /* sx.val.l = constant */
1339 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1340 /* sx.val.l = constant */
1342 /* TODO should use memory operand to access data segment, not load */
1344 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1346 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1347 s3 = iptr->sx.val.l & 0xffffffff;
1349 M_INTMOVE(s1, GET_LOW_REG(d));
1351 ICONST(REG_ITMP3, s3);
1353 switch (iptr->opc) {
1354 case ICMD_LANDCONST:
1355 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1357 case ICMD_LXORCONST:
1358 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1361 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1367 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1368 s3 = iptr->sx.val.l >> 32;
1370 M_INTMOVE(s1, GET_HIGH_REG(d));
1372 ICONST(REG_ITMP3, s3);
1374 switch (iptr->opc) {
1375 case ICMD_LANDCONST:
1376 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1378 case ICMD_LXORCONST:
1379 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1382 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1388 emit_store_dst(jd, iptr, d);
1392 /* floating operations ************************************************/
1394 case ICMD_FNEG: /* ..., value ==> ..., - value */
1395 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1396 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1398 emit_store_dst(jd, iptr, d);
1401 case ICMD_DNEG: /* ..., value ==> ..., - value */
1402 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1403 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1405 emit_store_dst(jd, iptr, d);
1408 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1409 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1410 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1411 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1418 emit_store_dst(jd, iptr, d);
1421 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1422 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1423 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1424 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1431 emit_store_dst(jd, iptr, d);
1434 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1435 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1436 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1437 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1441 emit_store_dst(jd, iptr, d);
1444 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1445 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1446 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1447 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1451 emit_store_dst(jd, iptr, d);
1454 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1455 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1456 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1457 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1464 emit_store_dst(jd, iptr, d);
1467 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1468 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1469 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1470 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1477 emit_store_dst(jd, iptr, d);
1480 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1481 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1482 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1483 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1487 emit_store_dst(jd, iptr, d);
1490 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1491 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1492 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1493 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1497 emit_store_dst(jd, iptr, d);
1500 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1501 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1502 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1504 emit_store_dst(jd, iptr, d);
1507 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1508 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1509 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1511 emit_store_dst(jd, iptr, d);
1514 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1518 #ifdef SUPPORT_HERCULES
1522 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1523 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1527 switch (iptr->opc) {
1536 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1537 N_LHI(d, 0); /* Load 0 */
1538 ref1 = cd->mcodeptr;
1539 N_BRC(DD_ANY, 0); /* Exit */
1543 switch (iptr->opc) {
1552 #ifdef SUPPORT_HERCULES
1553 /* Hercules does the conversion using a plain C conversion.
1554 * According to manual, real hardware should *NOT* require this.
1556 * Corner case: Positive float leads to INT_MIN (overflow).
1559 switch (iptr->opc) {
1568 ref2 = cd->mcodeptr;
1569 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1573 ref3 = cd->mcodeptr;
1574 M_BGE(0); /* If integer result is negative, continue */
1576 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1577 M_ILD(d, REG_PV, disp);
1579 N_BRC_BACK_PATCH(ref1);
1580 #ifdef SUPPORT_HERCULES
1581 N_BRC_BACK_PATCH(ref2);
1582 N_BRC_BACK_PATCH(ref3);
1584 emit_store_dst(jd, iptr, d);
1588 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1589 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1590 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1592 emit_store_dst(jd, iptr, d);
1595 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1596 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1597 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1599 emit_store_dst(jd, iptr, d);
1602 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1603 /* == => 0, < => 1, > => -1 */
1607 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1608 /* == => 0, < => 1, > => -1 */
1611 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1612 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1613 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1615 switch (iptr->opc) {
1627 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1628 SZ_BRC + SZ_BRC + SZ_BRC
1631 N_BRC( /* load -1 */
1632 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1633 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1638 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1641 N_LHI(d, 1); /* GT */
1642 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1643 N_LHI(d, -1); /* LT */
1644 M_BR(SZ_BRC + SZ_LHI);
1645 N_LHI(d, 0); /* EQ */
1647 emit_store_dst(jd, iptr, d);
1652 /* memory operations **************************************************/
1654 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1656 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1657 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1659 /* implicit null-pointer check */
1660 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1661 emit_store_dst(jd, iptr, d);
1665 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1666 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1667 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1668 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1670 /* implicit null-pointer check */
1671 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1673 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1678 emit_store_dst(jd, iptr, d);
1681 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1683 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1684 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1685 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1687 /* implicit null-pointer check */
1688 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1690 M_INTMOVE(s2, REG_ITMP2);
1691 M_SLL_IMM(1, REG_ITMP2);
1693 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1695 /* N_LH does sign extends, undo ! */
1700 emit_store_dst(jd, iptr, d);
1703 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1704 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1705 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1706 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1708 /* implicit null-pointer check */
1709 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1711 M_INTMOVE(s2, REG_ITMP2);
1712 M_SLL_IMM(1, REG_ITMP2);
1714 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1715 emit_store_dst(jd, iptr, d);
1718 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1719 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1720 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1721 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1723 /* implicit null-pointer check */
1724 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1726 M_INTMOVE(s2, REG_ITMP2);
1727 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1728 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1729 emit_store_dst(jd, iptr, d);
1732 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1734 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1735 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1737 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1739 /* implicit null-pointer check */
1740 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1742 M_INTMOVE(s2, REG_ITMP2);
1743 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1745 /* We need to preserve the array address after the first load */
1747 if (GET_HIGH_REG(d) == s1) {
1748 M_INTMOVE(s1, REG_ITMP3);
1752 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1753 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1754 emit_store_dst(jd, iptr, d);
1758 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1760 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1761 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1762 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1764 /* implicit null-pointer check */
1765 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1767 M_INTMOVE(s2, REG_ITMP2);
1768 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1770 N_LE(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1772 emit_store_dst(jd, iptr, d);
1775 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1776 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1777 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1778 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1780 /* implicit null-pointer check */
1781 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1783 M_INTMOVE(s2, REG_ITMP2);
1784 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1786 N_LD(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1788 emit_store_dst(jd, iptr, d);
1791 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1792 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1793 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1794 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1796 /* implicit null-pointer check */
1797 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1799 M_INTMOVE(s2, REG_ITMP2);
1800 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1801 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1802 emit_store_dst(jd, iptr, d);
1805 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1806 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1807 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1808 /* implicit null-pointer check */
1809 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1810 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1812 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1815 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1817 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1818 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1819 /* implicit null-pointer check */
1820 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1821 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1823 M_INTMOVE(s2, REG_ITMP2);
1824 M_SLL_IMM(1, REG_ITMP2);
1826 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1830 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1831 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1832 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1833 /* implicit null-pointer check */
1834 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1835 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1837 M_INTMOVE(s2, REG_ITMP2);
1838 M_SLL_IMM(1, REG_ITMP2);
1840 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1843 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1845 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1846 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1847 /* implicit null-pointer check */
1848 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1850 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1852 M_INTMOVE(s2, REG_ITMP2);
1853 M_SLL_IMM(2, REG_ITMP2);
1855 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1858 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1860 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1861 s2 = emit_load_s2(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(3, REG_ITMP2);
1868 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1869 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1870 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1871 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1874 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1875 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1876 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1877 /* implicit null-pointer check */
1878 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1879 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1881 M_INTMOVE(s2, REG_ITMP2);
1882 M_SLL_IMM(2, REG_ITMP2);
1884 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1887 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1888 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1889 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1890 /* implicit null-pointer check */
1891 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1892 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1894 M_INTMOVE(s2, REG_ITMP2);
1895 M_SLL_IMM(3, REG_ITMP2);
1897 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1900 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1902 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1903 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1904 /* implicit null-pointer check */
1905 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1906 s3 = emit_load_s3(jd, iptr, REG_A1);
1908 M_INTMOVE(s1, REG_A0);
1909 M_INTMOVE(s3, REG_A1);
1911 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1912 M_ALD(REG_ITMP3, REG_PV, disp);
1913 M_ASUB_IMM(96, REG_SP);
1914 M_JSR(REG_RA, REG_ITMP3);
1915 M_AADD_IMM(96, REG_SP);
1917 emit_exception_check(cd, iptr);
1919 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1920 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1921 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1923 M_INTMOVE(s2, REG_ITMP2);
1924 M_SLL_IMM(2, REG_ITMP2);
1925 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1928 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1929 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1934 case ICMD_GETSTATIC: /* ... ==> ..., value */
1936 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1937 uf = iptr->sx.s23.s3.uf;
1938 fieldtype = uf->fieldref->parseddesc.fd->type;
1939 disp = dseg_add_unique_address(cd, NULL);
1941 /* PROFILE_CYCLE_STOP; */
1943 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1945 /* PROFILE_CYCLE_START; */
1948 fi = iptr->sx.s23.s3.fmiref->p.field;
1949 fieldtype = fi->type;
1950 disp = dseg_add_address(cd, &(fi->value));
1952 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1955 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
1957 PROFILE_CYCLE_START;
1961 M_ALD(REG_ITMP1, REG_PV, disp);
1963 switch (fieldtype) {
1965 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1966 M_ILD(d, REG_ITMP1, 0);
1969 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1970 M_LLD(d, REG_ITMP1, 0);
1973 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1974 M_ALD(d, REG_ITMP1, 0);
1977 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1978 M_FLD(d, REG_ITMP1, 0);
1981 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1982 M_DLD(d, REG_ITMP1, 0);
1986 emit_store_dst(jd, iptr, d);
1990 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1992 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1993 uf = iptr->sx.s23.s3.uf;
1994 fieldtype = uf->fieldref->parseddesc.fd->type;
1995 disp = dseg_add_unique_address(cd, uf);
1997 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2000 fi = iptr->sx.s23.s3.fmiref->p.field;
2001 fieldtype = fi->type;
2002 disp = dseg_add_address(cd, &(fi->value));
2004 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2005 codegen_addpatchref(cd, PATCHER_clinit,
2009 M_ALD(REG_ITMP1, REG_PV, disp);
2010 switch (fieldtype) {
2012 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2013 M_IST(s1, REG_ITMP1, 0);
2016 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2017 M_LST(s1, REG_ITMP1, 0);
2020 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2021 M_AST(s1, REG_ITMP1, 0);
2024 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2025 M_FST(s1, REG_ITMP1, 0);
2028 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2029 M_DST(s1, REG_ITMP1, 0);
2034 case ICMD_GETFIELD: /* ... ==> ..., value */
2036 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2037 emit_nullpointer_check(cd, iptr, s1);
2039 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2040 uf = iptr->sx.s23.s3.uf;
2041 fieldtype = uf->fieldref->parseddesc.fd->type;
2044 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2047 fi = iptr->sx.s23.s3.fmiref->p.field;
2048 fieldtype = fi->type;
2052 switch (fieldtype) {
2054 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2058 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2059 if (GET_HIGH_REG(d) == s1) {
2060 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2061 M_ILD(GET_HIGH_REG(d), s1, disp);
2064 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2065 M_ILD(GET_HIGH_REG(d), s1, disp);
2069 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2073 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2077 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2081 emit_store_dst(jd, iptr, d);
2084 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2088 s1 = emit_load_s1_notzero(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;
2097 fi = iptr->sx.s23.s3.fmiref->p.field;
2098 fieldtype = fi->type;
2102 /* We can't add a patcher ref behind this load,
2103 * because the patcher would destroy REG_ITMP3.
2105 * We pass in the disp parameter, how many bytes
2106 * to skip to the to the actual store.
2108 * XXX this relies on codegen_add_patch_ref internals
2111 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2112 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2117 if (IS_INT_LNG_TYPE(fieldtype)) {
2118 if (IS_2_WORD_TYPE(fieldtype))
2119 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2121 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2123 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2126 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2127 cd->patchrefs->disp = (cd->mcodeptr - ref);
2130 switch (fieldtype) {
2132 M_IST(s2, s1, disp);
2135 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2136 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2139 M_AST(s2, s1, disp);
2142 M_FST(s2, s1, disp);
2145 M_DST(s2, s1, disp);
2152 /* branch operations **************************************************/
2154 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2156 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2157 M_INTMOVE(s1, REG_ITMP1_XPTR);
2161 #ifdef ENABLE_VERIFIER
2162 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2163 uc = iptr->sx.s23.s2.uc;
2165 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2167 #endif /* ENABLE_VERIFIER */
2169 disp = dseg_add_functionptr(cd, asm_handle_exception);
2170 M_ALD(REG_ITMP2, REG_PV, disp);
2171 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2176 case ICMD_GOTO: /* ... ==> ... */
2177 case ICMD_RET: /* ... ==> ... */
2179 emit_br(cd, iptr->dst.block);
2183 case ICMD_JSR: /* ... ==> ... */
2185 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2189 case ICMD_IFNULL: /* ..., value ==> ... */
2190 case ICMD_IFNONNULL: /* ..., value ==> ... */
2191 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2193 switch (iptr->opc) {
2195 emit_beq(cd, iptr->dst.block);
2197 case ICMD_IFNONNULL:
2198 emit_bne(cd, iptr->dst.block);
2203 case ICMD_IFEQ: /* ..., value ==> ... */
2204 case ICMD_IFLT: /* ..., value ==> ... */
2205 case ICMD_IFLE: /* ..., value ==> ... */
2206 case ICMD_IFNE: /* ..., value ==> ... */
2207 case ICMD_IFGT: /* ..., value ==> ... */
2208 case ICMD_IFGE: /* ..., value ==> ... */
2210 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2212 if (N_VALID_IMM(iptr->sx.val.i))
2213 M_ICMP_IMM(s1, iptr->sx.val.i);
2215 disp = dseg_add_s4(cd, iptr->sx.val.i);
2216 ICONST(REG_ITMP2, disp);
2217 N_C(s1, 0, REG_ITMP2, REG_PV);
2220 switch (iptr->opc) {
2222 emit_blt(cd, iptr->dst.block);
2225 emit_ble(cd, iptr->dst.block);
2228 emit_bne(cd, iptr->dst.block);
2231 emit_bgt(cd, iptr->dst.block);
2234 emit_bge(cd, iptr->dst.block);
2237 emit_beq(cd, iptr->dst.block);
2243 case ICMD_IF_LLT: /* ..., value ==> ... */
2244 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2250 /* ATTENTION: compare high words signed and low words unsigned */
2252 # define LABEL_OUT BRANCH_LABEL_1
2254 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2256 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2257 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2259 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2260 ICONST(REG_ITMP2, disp);
2261 N_C(s1, 0, REG_ITMP2, REG_PV);
2267 emit_blt(cd, iptr->dst.block);
2268 /* EQ ... fall through */
2269 emit_label_bgt(cd, LABEL_OUT);
2273 emit_bgt(cd, iptr->dst.block);
2274 /* EQ ... fall through */
2275 emit_label_blt(cd, LABEL_OUT);
2278 /* EQ ... fall through */
2279 emit_label_bne(cd, LABEL_OUT);
2282 /* EQ ... fall through */
2283 emit_bne(cd, iptr->dst.block);
2289 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2291 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2292 ICONST(REG_ITMP2, disp);
2293 N_CL(s1, 0, REG_ITMP2, REG_PV);
2297 emit_blt(cd, iptr->dst.block);
2298 emit_label(cd, LABEL_OUT);
2301 emit_ble(cd, iptr->dst.block);
2302 emit_label(cd, LABEL_OUT);
2305 emit_bgt(cd, iptr->dst.block);
2306 emit_label(cd, LABEL_OUT);
2309 emit_bge(cd, iptr->dst.block);
2310 emit_label(cd, LABEL_OUT);
2313 emit_beq(cd, iptr->dst.block);
2314 emit_label(cd, LABEL_OUT);
2317 emit_bne(cd, iptr->dst.block);
2326 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2327 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2329 /* Compare addresses as 31 bit unsigned integers */
2331 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2332 M_LDA(REG_ITMP1, s1, 0);
2334 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2335 M_LDA(REG_ITMP2, s2, 0);
2337 M_CMP(REG_ITMP1, REG_ITMP2);
2339 switch (iptr->opc) {
2340 case ICMD_IF_ACMPEQ:
2341 emit_beq(cd, iptr->dst.block);
2343 case ICMD_IF_ACMPNE:
2344 emit_bne(cd, iptr->dst.block);
2350 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2351 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2352 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2353 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2354 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2355 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2357 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2358 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2360 switch (iptr->opc) {
2361 case ICMD_IF_ICMPEQ:
2362 emit_beq(cd, iptr->dst.block);
2364 case ICMD_IF_ICMPNE:
2365 emit_bne(cd, iptr->dst.block);
2367 case ICMD_IF_ICMPLT:
2368 emit_blt(cd, iptr->dst.block);
2370 case ICMD_IF_ICMPGT:
2371 emit_bgt(cd, iptr->dst.block);
2373 case ICMD_IF_ICMPLE:
2374 emit_ble(cd, iptr->dst.block);
2376 case ICMD_IF_ICMPGE:
2377 emit_bge(cd, iptr->dst.block);
2383 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2384 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2385 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2386 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2387 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2388 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2393 /* ATTENTION: compare high words signed and low words unsigned */
2395 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2396 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2401 case ICMD_IF_LCMPLT:
2402 case ICMD_IF_LCMPLE:
2403 emit_blt(cd, iptr->dst.block);
2404 /* EQ ... fall through */
2405 out_ref = cd->mcodeptr;
2408 case ICMD_IF_LCMPGT:
2409 case ICMD_IF_LCMPGE:
2410 emit_bgt(cd, iptr->dst.block);
2411 /* EQ ... fall through */
2412 out_ref = cd->mcodeptr;
2415 case ICMD_IF_LCMPEQ:
2416 /* EQ ... fall through */
2417 out_ref = cd->mcodeptr;
2420 case ICMD_IF_LCMPNE:
2421 /* EQ ... fall through */
2422 emit_bne(cd, iptr->dst.block);
2428 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2429 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2434 case ICMD_IF_LCMPLT:
2435 emit_blt(cd, iptr->dst.block);
2437 case ICMD_IF_LCMPLE:
2438 emit_ble(cd, iptr->dst.block);
2440 case ICMD_IF_LCMPGT:
2441 emit_bgt(cd, iptr->dst.block);
2443 case ICMD_IF_LCMPGE:
2444 emit_bge(cd, iptr->dst.block);
2446 case ICMD_IF_LCMPEQ:
2447 emit_beq(cd, iptr->dst.block);
2449 case ICMD_IF_LCMPNE:
2450 emit_bne(cd, iptr->dst.block);
2457 if (out_ref != NULL) {
2458 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2464 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2466 REPLACEMENT_POINT_RETURN(cd, iptr);
2467 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2468 M_INTMOVE(s1, REG_RESULT);
2469 goto nowperformreturn;
2471 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2473 REPLACEMENT_POINT_RETURN(cd, iptr);
2474 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2475 M_INTMOVE(s1, REG_RESULT);
2477 #ifdef ENABLE_VERIFIER
2478 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2479 unresolved_class *uc = iptr->sx.s23.s2.uc;
2481 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2483 #endif /* ENABLE_VERIFIER */
2484 goto nowperformreturn;
2486 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2488 REPLACEMENT_POINT_RETURN(cd, iptr);
2489 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2490 M_LNGMOVE(s1, REG_RESULT_PACKED);
2491 goto nowperformreturn;
2493 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2496 REPLACEMENT_POINT_RETURN(cd, iptr);
2497 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2498 M_FLTMOVE(s1, REG_FRESULT);
2499 goto nowperformreturn;
2501 case ICMD_RETURN: /* ... ==> ... */
2503 REPLACEMENT_POINT_RETURN(cd, iptr);
2509 p = cd->stackframesize;
2511 /* call trace function */
2513 #if !defined(NDEBUG)
2514 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2515 emit_verbosecall_exit(jd);
2516 #endif /* !defined(NDEBUG) */
2518 #if defined(ENABLE_THREADS)
2519 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2521 /* we need to save the proper return value */
2523 switch (iptr->opc) {
2525 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2529 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2532 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2535 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2539 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2541 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2542 M_ALD(REG_ITMP3, REG_PV, disp);
2544 M_ASUB_IMM(96, REG_SP);
2546 M_AADD_IMM(96, REG_SP);
2548 /* and now restore the proper return value */
2550 switch (iptr->opc) {
2552 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2556 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2559 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2562 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2568 /* restore return address */
2570 p--; M_ALD(REG_RA, REG_SP, p * 4);
2572 /* restore saved registers */
2574 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2575 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2577 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2578 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2581 /* deallocate stack */
2583 if (cd->stackframesize)
2584 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2591 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2594 branch_target_t *table;
2596 table = iptr->dst.table;
2598 l = iptr->sx.s23.s2.tablelow;
2599 i = iptr->sx.s23.s3.tablehigh;
2601 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2602 M_INTMOVE(s1, REG_ITMP1);
2606 } else if (N_VALID_IMM(-l)) {
2607 M_ISUB_IMM(l, REG_ITMP1);
2609 ICONST(REG_ITMP2, l);
2610 M_ISUB(REG_ITMP2, REG_ITMP1);
2613 /* number of targets */
2619 ICONST(REG_ITMP2, i);
2620 M_ICMPU(REG_ITMP1, REG_ITMP2);
2621 emit_bge(cd, table[0].block);
2623 /* build jump table top down and use address of lowest entry */
2628 dseg_add_target(cd, table->block);
2633 /* length of dataseg after last dseg_add_target is used by load */
2635 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2636 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2637 N_L(REG_ITMP1, 0, REG_ITMP1, REG_PV);
2638 M_JMP(RN, REG_ITMP1);
2643 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2646 lookup_target_t *lookup;
2648 lookup = iptr->dst.lookup;
2650 i = iptr->sx.s23.s2.lookupcount;
2652 MCODECHECK(8 + ((7 + 6) * i) + 5);
2653 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2656 if (N_VALID_IMM(lookup->value)) {
2657 M_ICMP_IMM(s1, lookup->value);
2659 ICONST(REG_ITMP2, lookup->value);
2660 M_ICMP(REG_ITMP2, s1);
2662 emit_beq(cd, lookup->target.block);
2666 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2671 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2673 bte = iptr->sx.s23.s3.bte;
2677 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2678 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2679 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2680 case ICMD_INVOKEINTERFACE:
2682 REPLACEMENT_POINT_INVOKE(cd, iptr);
2684 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2686 um = iptr->sx.s23.s3.um;
2687 md = um->methodref->parseddesc.md;
2690 lm = iptr->sx.s23.s3.fmiref->p.method;
2692 md = lm->parseddesc;
2696 s3 = md->paramcount;
2698 MCODECHECK((s3 << 1) + 64);
2700 /* copy arguments to registers or stack location */
2702 for (s3 = s3 - 1; s3 >= 0; s3--) {
2703 var = VAR(iptr->sx.s23.s2.args[s3]);
2705 /* Already Preallocated? */
2706 if (var->flags & PREALLOC)
2709 if (IS_INT_LNG_TYPE(var->type)) {
2710 if (!md->params[s3].inmemory) {
2711 if (IS_2_WORD_TYPE(var->type)) {
2713 GET_LOW_REG(md->params[s3].regoff),
2714 GET_HIGH_REG(md->params[s3].regoff)
2716 d = emit_load(jd, iptr, var, s1);
2720 s1 = md->params[s3].regoff;
2721 d = emit_load(jd, iptr, var, s1);
2726 if (IS_2_WORD_TYPE(var->type)) {
2727 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2728 M_LST(d, REG_SP, md->params[s3].regoff * 4);
2731 d = emit_load(jd, iptr, var, REG_ITMP1);
2732 M_IST(d, REG_SP, md->params[s3].regoff * 4);
2737 if (!md->params[s3].inmemory) {
2738 s1 = md->params[s3].regoff;
2739 d = emit_load(jd, iptr, var, s1);
2743 d = emit_load(jd, iptr, var, REG_FTMP1);
2744 if (IS_2_WORD_TYPE(var->type))
2745 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2747 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2752 switch (iptr->opc) {
2754 disp = dseg_add_functionptr(cd, bte->fp);
2756 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2757 N_LHI(REG_ITMP1, disp);
2758 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2761 case ICMD_INVOKESPECIAL:
2763 /* Implicit NULL pointer check */
2764 M_ILD(REG_ITMP1, REG_A0, 0);
2768 case ICMD_INVOKESTATIC:
2770 disp = dseg_add_unique_address(cd, um);
2772 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2776 disp = dseg_add_address(cd, lm->stubroutine);
2778 N_LHI(REG_ITMP1, disp);
2779 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2782 case ICMD_INVOKEVIRTUAL:
2783 /* TODO softnull REG_A0 */
2786 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2791 s1 = OFFSET(vftbl_t, table[0]) +
2792 sizeof(methodptr) * lm->vftblindex;
2795 /* implicit null-pointer check */
2797 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2798 M_ALD(REG_PV, REG_METHODPTR, s1);
2801 case ICMD_INVOKEINTERFACE:
2802 /* TODO softnull REG_A0 */
2804 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2805 * and -0xFFF in index register (itmp1)
2808 N_LHI(REG_ITMP1, -N_DISP_MAX);
2811 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2817 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2818 sizeof(methodptr*) * lm->class->index +
2821 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2824 /* Implicit null-pointer check */
2825 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2826 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
2827 M_ALD(REG_PV, REG_METHODPTR, s2);
2831 /* generate the actual call */
2834 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2835 emit_restore_pv(cd);
2837 /* post call finalization */
2839 switch (iptr->opc) {
2841 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2842 emit_exception_check(cd, iptr); /* check for exception */
2846 /* store return value */
2848 d = md->returntype.type;
2850 if (d != TYPE_VOID) {
2851 if (IS_INT_LNG_TYPE(d)) {
2852 if (IS_2_WORD_TYPE(d)) {
2853 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2854 M_LNGMOVE(REG_RESULT_PACKED, s1);
2857 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2858 M_INTMOVE(REG_RESULT, s1);
2862 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2863 M_FLTMOVE(REG_FRESULT, s1);
2865 emit_store_dst(jd, iptr, s1);
2871 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2873 /* val.a: (classinfo*) superclass */
2875 /* superclass is an interface:
2877 * OK if ((sub == NULL) ||
2878 * (sub->vftbl->interfacetablelength > super->index) &&
2879 * (sub->vftbl->interfacetable[-super->index] != NULL));
2881 * superclass is a class:
2883 * OK if ((sub == NULL) || (0
2884 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2885 * super->vftbl->diffval));
2888 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2889 /* object type cast-check */
2892 vftbl_t *supervftbl;
2895 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2896 # define LABEL_CLASS BRANCH_LABEL_2
2897 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2898 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2899 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2901 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2907 super = iptr->sx.s23.s3.c.cls;
2908 superindex = super->index;
2909 supervftbl = super->vftbl;
2912 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2913 CODEGEN_CRITICAL_SECTION_NEW;
2915 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2917 /* if class is not resolved, check which code to call */
2919 if (super == NULL) {
2921 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2923 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2925 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
2926 iptr->sx.s23.s3.c.ref,
2929 ICONST(REG_ITMP2, ACC_INTERFACE);
2930 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
2931 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
2932 emit_label_beq(cd, LABEL_CLASS);
2935 /* interface checkcast code */
2937 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2938 if (super == NULL) {
2939 codegen_add_patch_ref(cd,
2940 PATCHER_checkcast_instanceof_interface,
2941 iptr->sx.s23.s3.c.ref,
2945 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
2948 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2949 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2950 M_ISUB_IMM(superindex, REG_ITMP3);
2951 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
2954 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2955 superindex * sizeof(methodptr*))
2957 M_ALD(REG_ITMP2, REG_ITMP2, 0);
2958 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
2960 if (super == NULL) {
2961 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
2965 /* class checkcast code */
2967 if (super == NULL) {
2968 emit_label(cd, LABEL_CLASS);
2971 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2972 if (super == NULL) {
2973 disp = dseg_add_unique_address(cd, NULL);
2975 codegen_add_patch_ref(cd,
2976 PATCHER_resolve_classref_to_vftbl,
2977 iptr->sx.s23.s3.c.ref,
2981 disp = dseg_add_address(cd, supervftbl);
2983 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
2986 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2987 M_ALD(REG_ITMP3, REG_PV, disp);
2989 CODEGEN_CRITICAL_SECTION_START;
2991 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2992 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2993 M_ISUB(REG_ITMP3, REG_ITMP2);
2994 M_ALD(REG_ITMP3, REG_PV, disp);
2995 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2997 CODEGEN_CRITICAL_SECTION_END;
2999 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3000 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3001 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3002 /* Branch if greater then */
3003 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3006 if (super == NULL) {
3007 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3008 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3009 } else if (super->flags & ACC_INTERFACE) {
3010 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3012 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3015 d = codegen_reg_of_dst(jd, iptr, s1);
3017 # undef LABEL_EXIT_CHECK_NULL
3019 # undef LABEL_EXIT_INTERFACE_NULL
3020 # undef LABEL_EXIT_INTERFACE_DONE
3021 # undef LABEL_EXIT_CLASS_NULL
3024 /* array type cast-check */
3026 s1 = emit_load_s1(jd, iptr, REG_A0);
3027 M_INTMOVE(s1, REG_A0);
3029 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3030 disp = dseg_add_unique_address(cd, NULL);
3032 codegen_add_patch_ref(cd,
3033 PATCHER_resolve_classref_to_classinfo,
3034 iptr->sx.s23.s3.c.ref,
3038 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3040 M_ALD(REG_A1, REG_PV, disp);
3041 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3042 M_ALD(REG_ITMP1, REG_PV, disp);
3043 M_ASUB_IMM(96, REG_SP);
3044 M_JSR(REG_RA, REG_ITMP1);
3045 M_AADD_IMM(96, REG_SP);
3047 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3048 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3050 d = codegen_reg_of_dst(jd, iptr, s1);
3054 emit_store_dst(jd, iptr, d);
3057 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3058 /* val.a: (classinfo*) superclass */
3060 /* superclass is an interface:
3062 * return (sub != NULL) &&
3063 * (sub->vftbl->interfacetablelength > super->index) &&
3064 * (sub->vftbl->interfacetable[-super->index] != NULL);
3066 * superclass is a class:
3068 * return ((sub != NULL) && (0
3069 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3070 * super->vftbl->diffvall));
3072 * If superclass is unresolved, we include both code snippets
3073 * above, a patcher resolves the class' flags and we select
3074 * the right code at runtime.
3079 vftbl_t *supervftbl;
3082 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3088 super = iptr->sx.s23.s3.c.cls;
3089 superindex = super->index;
3090 supervftbl = super->vftbl;
3093 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3094 # define LABEL_CLASS BRANCH_LABEL_2
3095 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3096 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3097 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3098 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3100 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3101 CODEGEN_CRITICAL_SECTION_NEW;
3103 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3104 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3106 M_MOV(s1, REG_ITMP1);
3110 /* if class is not resolved, check which code to call */
3112 if (super == NULL) {
3116 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3118 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3120 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3121 iptr->sx.s23.s3.c.ref, disp);
3123 ICONST(REG_ITMP2, ACC_INTERFACE);
3124 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3125 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3126 emit_label_beq(cd, LABEL_CLASS);
3129 /* interface instanceof code */
3131 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3132 if (super == NULL) {
3133 /* If d == REG_ITMP2, then it's destroyed in check
3138 codegen_add_patch_ref(cd,
3139 PATCHER_checkcast_instanceof_interface,
3140 iptr->sx.s23.s3.c.ref, 0);
3145 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3148 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3149 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3150 M_ISUB_IMM(superindex, REG_ITMP3);
3152 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3156 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3157 superindex * sizeof(methodptr*))
3159 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3161 /* d := (REG_ITMP1 != 0) */
3163 N_LTR(d, REG_ITMP1);
3164 M_BEQ(SZ_BRC + SZ_LHI);
3167 if (super == NULL) {
3168 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3172 /* class instanceof code */
3174 if (super == NULL) {
3175 emit_label(cd, LABEL_CLASS);
3178 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3179 if (super == NULL) {
3180 disp = dseg_add_unique_address(cd, NULL);
3182 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3183 iptr->sx.s23.s3.c.ref,
3187 disp = dseg_add_address(cd, supervftbl);
3192 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3195 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3196 M_ALD(REG_ITMP2, REG_PV, disp);
3198 CODEGEN_CRITICAL_SECTION_START;
3200 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3201 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3202 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3204 CODEGEN_CRITICAL_SECTION_END;
3206 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3208 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3210 M_BGT(SZ_BRC + SZ_LHI);
3214 if (super == NULL) {
3215 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3216 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3217 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3218 } else if (super->flags & ACC_INTERFACE) {
3219 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3220 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3222 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3225 # undef LABEL_EXIT_CHECK_NULL
3227 # undef LABEL_EXIT_INTERFACE_NULL
3228 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3229 # undef LABEL_EXIT_INTERFACE_DONE
3230 # undef LABEL_EXIT_CLASS_NULL
3232 emit_store_dst(jd, iptr, d);
3238 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3240 /* check for negative sizes and copy sizes to stack if necessary */
3242 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3245 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3247 /* copy SAVEDVAR sizes to stack */
3248 var = VAR(iptr->sx.s23.s2.args[s1]);
3250 /* Already Preallocated? */
3251 if (!(var->flags & PREALLOC)) {
3252 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3253 M_IST(s2, REG_SP, s1 * 4);
3257 /* is a patcher function set? */
3259 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3260 disp = dseg_add_unique_address(cd, 0);
3262 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
3263 iptr->sx.s23.s3.c.ref,
3267 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3269 /* a0 = dimension count */
3271 ICONST(REG_A0, iptr->s1.argcount);
3273 /* a1 = classinfo */
3275 M_ALD(REG_A1, REG_PV, disp);
3277 /* a2 = pointer to dimensions = stack pointer */
3279 M_MOV(REG_SP, REG_A2);
3281 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3282 M_ALD(REG_ITMP1, REG_PV, disp);
3283 M_ASUB_IMM(96, REG_SP);
3284 M_JSR(REG_RA, REG_ITMP1);
3285 M_AADD_IMM(96, REG_SP);
3287 /* check for exception before result assignment */
3289 emit_exception_check(cd, iptr);
3291 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3292 M_INTMOVE(REG_RESULT, s1);
3293 emit_store_dst(jd, iptr, s1);
3298 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3302 } /* for instruction */
3304 MCODECHECK(512); /* XXX require a lower number? */
3306 /* At the end of a basic block we may have to append some nops,
3307 because the patcher stub calling code might be longer than the
3308 actual instruction. So codepatching does not change the
3309 following block unintentionally. */
3311 if (cd->mcodeptr < cd->lastmcodeptr) {
3312 while (cd->mcodeptr < cd->lastmcodeptr) {
3317 } /* if (bptr -> flags >= BBREACHED) */
3318 } /* for basic block */
3320 dseg_createlinenumbertable(cd);
3322 /* generate stubs */
3324 emit_patcher_stubs(jd);
3326 emit_replacement_stubs(jd);
3329 /* everything's ok */
3335 /* codegen_emit_stub_compiler **************************************************
3337 Emits a stub routine which calls the compiler.
3339 *******************************************************************************/
3341 void codegen_emit_stub_compiler(jitdata *jd)
3346 /* get required compiler data */
3351 /* code for the stub */
3353 /* don't touch ITMP3 as it cointains the return address */
3355 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3357 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3358 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3359 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3364 /* codegen_emit_stub_native ****************************************************
3366 Emits a stub routine which calls a native method.
3368 *******************************************************************************/
3371 arguments on stack \
3372 -------------------------------------------------| <- SP on nativestub entry
3374 callee saved int regs (none) |
3375 callee saved float regs (none) | stack frame like in cacao
3376 local variable slots (none) |
3377 arguments for calling methods (none) /
3378 ------------------------------------------------------------------ <- datasp
3383 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3384 0 - 96 register save area for callee /
3385 -------------------------------------------------------- <- SP native method
3387 SP after method entry
3390 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3398 s4 i, j; /* count variables */
3403 /* get required compiler data */
3410 /* initialize variables */
3413 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3415 /* calculate stack frame size */
3417 cd->stackframesize =
3418 1 + /* r14 - return address */ +
3419 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3420 sizeof(localref_table) / SIZEOF_VOID_P +
3422 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3423 nmd->memuse + /* parameter passing */
3424 96 / SIZEOF_VOID_P /* required by ABI */;
3426 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3429 /* create method header */
3431 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3432 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3433 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3434 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3435 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3436 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3437 (void) dseg_addlinenumbertablesize(cd);
3438 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3440 /* generate native method profiling code */
3442 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3443 /* count frequency */
3445 M_MOV_IMM(code, REG_ITMP3);
3446 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3450 /* generate stub code */
3452 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3454 /* save return address */
3456 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3458 #if !defined(NDEBUG)
3459 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3460 emit_verbosecall_enter(jd);
3463 /* get function address (this must happen before the stackframeinfo) */
3465 disp = dseg_add_functionptr(cd, f);
3467 #if !defined(WITH_STATIC_CLASSPATH)
3469 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3472 M_ILD(REG_ITMP1, REG_PV, disp);
3474 j = 96 + (nmd->memuse * 4);
3476 /* todo some arg registers are not volatile in C-abi terms */
3478 /* save integer and float argument registers */
3480 for (i = 0; i < md->paramcount; i++) {
3481 if (! md->params[i].inmemory) {
3482 s1 = md->params[i].regoff;
3483 t = md->paramtypes[i].type;
3485 if (IS_INT_LNG_TYPE(t)) {
3486 if (IS_2_WORD_TYPE(t)) {
3487 /* todo store multiple */
3488 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3489 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3491 N_ST(s1, j, RN, REG_SP);
3494 if (IS_2_WORD_TYPE(t)) {
3495 N_STD(s1, j, RN, REG_SP);
3497 N_STE(s1, j, RN, REG_SP);
3505 N_ST(REG_ITMP1, j, RN, REG_SP);
3507 /* create dynamic stack info */
3509 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3510 N_LR(REG_A1, REG_PV); /* pv */
3511 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3512 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3514 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3515 M_ILD(REG_ITMP1, REG_PV, disp);
3517 M_CALL(REG_ITMP1); /* call */
3519 /* restore integer and float argument registers */
3521 j = 96 + (nmd->memuse * 4);
3523 for (i = 0; i < md->paramcount; i++) {
3524 if (! md->params[i].inmemory) {
3525 s1 = md->params[i].regoff;
3526 t = md->paramtypes[i].type;
3528 if (IS_INT_LNG_TYPE(t)) {
3529 if (IS_2_WORD_TYPE(t)) {
3530 /* todo load multiple ! */
3531 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3532 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3534 N_L(s1, j, RN, REG_SP);
3537 if (IS_2_WORD_TYPE(t)) {
3538 N_LD(s1, j, RN, REG_SP);
3540 N_LE(s1, j, RN, REG_SP);
3548 N_L(REG_ITMP1, j, RN, REG_SP);
3550 /* copy or spill arguments to new locations */
3552 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3553 t = md->paramtypes[i].type;
3555 if (IS_INT_LNG_TYPE(t)) {
3557 if (!md->params[i].inmemory) {
3559 s1 = md->params[i].regoff;
3561 if (!nmd->params[j].inmemory) {
3562 s2 = nmd->params[j].regoff;
3563 if (IS_2_WORD_TYPE(t)) {
3579 s2 = nmd->params[j].regoff;
3580 if (IS_2_WORD_TYPE(t)) {
3584 96 + (s2 * 4), REG_SP
3589 96 + (s2 * 4), RN, REG_SP
3595 s1 = cd->stackframesize + md->params[i].regoff;
3596 s2 = nmd->params[j].regoff;
3598 if (IS_2_WORD_TYPE(t)) {
3599 N_MVC(96 + (s2 * 4), 8, REG_SP, (s1 * 4), REG_SP);
3601 N_MVC(96 + (s2 * 4), 4, REG_SP, (s1 * 4), REG_SP);
3606 /* We only copy spilled float arguments, as the float argument */
3607 /* registers keep unchanged. */
3609 if (md->params[i].inmemory) {
3610 s1 = cd->stackframesize + md->params[i].regoff;
3611 s2 = nmd->params[j].regoff;
3613 if (IS_2_WORD_TYPE(t)) {
3614 N_MVC(96 + (s2 * 4), 8, REG_SP, (s1 * 4), REG_SP);
3616 N_MVC(96 + (s2 * 4), 4, REG_SP, (s1 * 4), REG_SP);
3622 /* put class into second argument register */
3624 if (m->flags & ACC_STATIC) {
3625 disp = dseg_add_address(cd, m->class);
3626 M_ILD(REG_A1, REG_PV, disp);
3629 /* put env into first argument register */
3631 disp = dseg_add_address(cd, _Jv_env);
3632 M_ILD(REG_A0, REG_PV, disp);
3634 /* do the native function call */
3636 M_CALL(REG_ITMP1); /* call */
3638 /* save return value */
3640 t = md->returntype.type;
3642 if (t != TYPE_VOID) {
3643 if (IS_INT_LNG_TYPE(t)) {
3644 if (IS_2_WORD_TYPE(t)) {
3645 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3647 N_ST(REG_RESULT, 96, RN, REG_SP);
3650 if (IS_2_WORD_TYPE(t)) {
3651 N_STD(REG_FRESULT, 96, RN, REG_SP);
3653 N_STE(REG_FRESULT, 96, RN, REG_SP);
3658 #if !defined(NDEBUG)
3659 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3660 emit_verbosecall_exit(jd);
3663 /* remove native stackframe info */
3665 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3666 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3667 M_ILD(REG_ITMP1, REG_PV, disp);
3669 N_LR(REG_ITMP3, REG_RESULT);
3671 /* restore return value */
3673 if (t != TYPE_VOID) {
3674 if (IS_INT_LNG_TYPE(t)) {
3675 if (IS_2_WORD_TYPE(t)) {
3676 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3678 N_L(REG_RESULT, 96, RN, REG_SP);
3681 if (IS_2_WORD_TYPE(t)) {
3682 N_LD(REG_FRESULT, 96, RN, REG_SP);
3684 N_LE(REG_FRESULT, 96, RN, REG_SP);
3689 /* load return address */
3691 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3693 /* remove stackframe */
3695 N_AHI(REG_SP, cd->stackframesize * 4);
3697 /* test for exception */
3699 N_LTR(REG_ITMP3, REG_ITMP3);
3700 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3704 N_BCR(DD_ANY, REG_ITMP2);
3706 /* handle exception */
3708 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3709 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3713 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3716 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3717 M_ALD(REG_ITMP3, REG_PV, disp);
3718 M_JMP(RN, REG_ITMP3);
3720 /* generate patcher stubs */
3722 emit_patcher_stubs(jd);
3725 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3726 codegendata *cd = jd->cd;
3727 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3729 M_MOV(reg, tempregnum);
3737 * These are local overrides for various environment variables in Emacs.
3738 * Please do not remove this and leave it at the end of the file, where
3739 * Emacs will automagically detect them.
3740 * ---------------------------------------------------------------------
3743 * indent-tabs-mode: t
3747 * vim:noexpandtab:sw=4:ts=4: