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 8151 2007-06-27 20:08:30Z pm $
39 #include "vm/jit/s390/arch.h"
40 #include "vm/jit/s390/codegen.h"
41 #include "vm/jit/s390/emit.h"
43 #include "mm/memory.h"
44 #include "native/jni.h"
45 #include "native/native.h"
47 #if defined(ENABLE_THREADS)
48 # include "threads/native/lock.h"
51 #include "vm/builtin.h"
52 #include "vm/exceptions.h"
53 #include "vm/global.h"
54 #include "vmcore/loader.h"
55 #include "vmcore/options.h"
56 #include "vmcore/statistics.h"
57 #include "vm/stringlocal.h"
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/codegen-common.h"
61 #include "vm/jit/dseg.h"
62 #include "vm/jit/emit-common.h"
63 #include "vm/jit/jit.h"
64 #include "vm/jit/methodheader.h"
65 #include "vm/jit/parse.h"
66 #include "vm/jit/patcher.h"
67 #include "vm/jit/reg.h"
68 #include "vm/jit/replace.h"
69 #include "vm/jit/stacktrace.h"
70 #include "vm/jit/abi.h"
71 #include "vm/jit/emit-common.h"
73 #if defined(ENABLE_LSRA)
74 # include "vm/jit/allocator/lsra.h"
77 #define OOPS() assert(0);
78 #define SUPPORT_HERCULES 1
82 /* codegen *********************************************************************
84 Generates machine code.
86 *******************************************************************************/
89 bool codegen_emit(jitdata *jd)
95 s4 len, s1, s2, s3, d, dd, disp;
98 varinfo *var, *var1, *var2, *dst;
102 constant_classref *cr;
103 unresolved_class *uc;
104 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
105 unresolved_method *um;
106 builtintable_entry *bte;
109 unresolved_field *uf;
112 rplpoint *replacementpoint;
116 /* get required compiler data */
123 /* prevent compiler warnings */
136 /* space to save used callee saved registers */
138 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
139 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
141 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
144 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
147 #if defined(ENABLE_THREADS)
148 /* Space to save argument of monitor_enter and Return Values to
149 survive monitor_exit. The stack position for the argument can
150 not be shared with place to save the return register
151 since both values reside in R2. */
153 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
154 /* reserve 2 slots for long/double return values for monitorexit */
156 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
157 cd->stackframesize += 3;
159 cd->stackframesize += 2;
163 /* Keep stack of non-leaf functions 16-byte aligned for calls into
164 native code e.g. libc or jni (alignment problems with
167 if (!jd->isleafmethod || opt_verbosecall )
168 /* TODO really 16 bytes ? */
169 cd->stackframesize = (cd->stackframesize + 3) & ~3;
171 /* create method header */
173 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
174 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
176 #if defined(ENABLE_THREADS)
177 /* IsSync contains the offset relative to the stack pointer for the
178 argument of monitor_exit used in the exception handler. Since the
179 offset could be zero and give a wrong meaning of the flag it is
183 if (checksync && (m->flags & ACC_SYNCHRONIZED))
184 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
188 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
190 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
191 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
192 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
194 (void) dseg_addlinenumbertablesize(cd);
196 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
198 /* create exception table */
200 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
201 dseg_add_target(cd, ex->start);
202 dseg_add_target(cd, ex->end);
203 dseg_add_target(cd, ex->handler);
204 (void) dseg_add_unique_address(cd, ex->catchtype.any);
209 M_AADD_IMM(N_PV_OFFSET, REG_PV);
211 /* generate method profiling code */
213 #if defined(ENABLE_PROFILING)
214 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
215 /* count frequency */
217 M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
218 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
219 M_IADD_IMM(1, REG_ITMP2);
220 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
222 /* PROFILE_CYCLE_START; */
226 /* create stack frame (if necessary) */
228 if (cd->stackframesize)
229 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
231 /* save used callee saved registers and return address */
233 p = cd->stackframesize;
234 p--; M_AST(REG_RA, REG_SP, p * 4);
236 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
237 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
239 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
240 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
243 /* take arguments out of register or stack frame */
247 for (p = 0, l = 0; p < md->paramcount; p++) {
248 t = md->paramtypes[p].type;
249 varindex = jd->local_map[l * 5 + t];
252 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
255 if (varindex == UNUSED)
260 s1 = md->params[p].regoff;
261 if (IS_INT_LNG_TYPE(t)) { /* integer args */
262 if (IS_2_WORD_TYPE(t)) {
270 if (!md->params[p].inmemory) { /* register arguments */
271 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
272 if (IS_2_WORD_TYPE(t))
273 M_LNGMOVE(s2, var->vv.regoff);
275 M_INTMOVE(s2, var->vv.regoff);
277 } else { /* reg arg -> spilled */
278 if (IS_2_WORD_TYPE(t))
279 M_LST(s2, REG_SP, var->vv.regoff);
281 M_IST(s2, REG_SP, var->vv.regoff);
284 } else { /* stack arguments */
285 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
286 if (IS_2_WORD_TYPE(t))
287 M_LLD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
289 M_ILD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
291 } else { /* stack arg -> spilled */
292 if (IS_2_WORD_TYPE(t)) {
293 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
295 N_MVC(var->vv.regoff, 4, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
300 } else { /* floating args */
301 if (!md->params[p].inmemory) { /* register arguments */
303 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
304 M_FLTMOVE(s2, var->vv.regoff);
306 } else { /* reg arg -> spilled */
307 if (IS_2_WORD_TYPE(t))
308 M_DST(s2, REG_SP, var->vv.regoff);
310 M_FST(s2, REG_SP, var->vv.regoff);
313 } else { /* stack arguments */
314 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
315 if (IS_2_WORD_TYPE(t))
316 M_DLD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
319 M_FLD(var->vv.regoff, REG_SP, cd->stackframesize * 4 + s1);
321 } else { /* stack-arg -> spilled */
322 if (IS_2_WORD_TYPE(t)) {
323 N_MVC(var->vv.regoff, 8, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
324 var->vv.regoff = cd->stackframesize * 4 + s1;
327 N_MVC(var->vv.regoff, 4, REG_SP, cd->stackframesize * 4 + s1, REG_SP);
334 /* save monitorenter argument */
336 #if defined(ENABLE_THREADS)
337 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
338 /* stack offset for monitor argument */
343 if (opt_verbosecall) {
344 M_ASUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
346 for (p = 0; p < INT_ARG_CNT; p++)
347 M_IST(abi_registers_integer_argument[p], REG_SP, p * 8);
349 for (p = 0; p < FLT_ARG_CNT; p++)
350 M_FST(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
352 s1 += ((INT_ARG_CNT + FLT_ARG_CNT) * 2);
356 /* decide which monitor enter function to call */
358 if (m->flags & ACC_STATIC) {
359 disp = dseg_add_address(cd, &m->class->object.header);
360 M_ALD_DSEG(REG_A0, disp);
364 M_BNE(SZ_BRC + SZ_ILL);
365 M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
368 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
369 M_ALD_DSEG(REG_ITMP3, disp);
371 M_AST(REG_A0, REG_SP, s1 * 4);
373 M_ASUB_IMM(96, REG_SP);
375 M_AADD_IMM(96, REG_SP);
378 if (opt_verbosecall) {
379 for (p = 0; p < INT_ARG_CNT; p++)
380 M_ILD(abi_registers_integer_argument[p], REG_SP, p * 8);
382 for (p = 0; p < FLT_ARG_CNT; p++)
383 M_FLD(abi_registers_float_argument[p], REG_SP, (INT_ARG_CNT + p) * 8);
385 M_AADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
392 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
393 emit_verbosecall_enter(jd);
394 #endif /* !defined(NDEBUG) */
398 /* end of header generation */
400 replacementpoint = jd->code->rplpoints;
403 /* walk through all basic blocks */
405 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
407 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
409 if (bptr->flags >= BBREACHED) {
411 /* branch resolving */
413 codegen_resolve_branchrefs(cd, bptr);
415 /* handle replacement points */
418 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
419 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
423 assert(cd->lastmcodeptr <= cd->mcodeptr);
424 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
428 /* copy interface registers to their destination */
433 /* generate basicblock profiling code */
435 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
436 /* count frequency */
438 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
439 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
441 /* if this is an exception handler, start profiling again */
443 if (bptr->type == BBTYPE_EXH)
447 #if defined(ENABLE_LSRA)
451 src = bptr->invars[len];
452 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
453 if (bptr->type == BBTYPE_EXH) {
454 /* d = reg_of_var(rd, src, REG_ITMP1); */
455 if (!IS_INMEMORY(src->flags))
459 M_INTMOVE(REG_ITMP1, d);
460 emit_store(jd, NULL, src, d);
470 var = VAR(bptr->invars[len]);
471 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
472 if (bptr->type == BBTYPE_EXH) {
473 d = codegen_reg_of_var(0, var, REG_ITMP1);
474 M_INTMOVE(REG_ITMP1, d);
475 emit_store(jd, NULL, var, d);
479 assert((var->flags & INOUT));
482 #if defined(ENABLE_LSRA)
485 /* walk through all instructions */
490 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
491 if (iptr->line != currentline) {
492 dseg_addlinenumber(cd, iptr->line);
493 currentline = iptr->line;
496 MCODECHECK(1024); /* 1KB should be enough */
499 case ICMD_NOP: /* ... ==> ... */
500 case ICMD_POP: /* ..., value ==> ... */
501 case ICMD_POP2: /* ..., value, value ==> ... */
502 case ICMD_INLINE_START: /* internal ICMDs */
503 case ICMD_INLINE_END:
506 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
507 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
508 emit_nullpointer_check(cd, iptr, s1);
511 /* constant operations ************************************************/
513 case ICMD_ICONST: /* ... ==> ..., constant */
514 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
515 ICONST(d, iptr->sx.val.i);
516 emit_store_dst(jd, iptr, d);
519 case ICMD_LCONST: /* ... ==> ..., constant */
521 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
522 LCONST(d, iptr->sx.val.l);
523 emit_store_dst(jd, iptr, d);
526 case ICMD_FCONST: /* ... ==> ..., constant */
527 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
528 disp = dseg_add_float(cd, iptr->sx.val.f);
529 M_FLD_DSEG(d, disp, REG_ITMP1);
530 emit_store_dst(jd, iptr, d);
533 case ICMD_DCONST: /* ... ==> ..., constant */
534 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
535 disp = dseg_add_double(cd, iptr->sx.val.d);
536 M_DLD_DSEG(d, disp, REG_ITMP1);
537 emit_store_dst(jd, iptr, d);
540 case ICMD_ACONST: /* ... ==> ..., constant */
541 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
543 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
544 cr = iptr->sx.val.c.ref;
545 disp = dseg_add_unique_address(cd, cr);
547 /* PROFILE_CYCLE_STOP; */
549 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
552 /* PROFILE_CYCLE_START; */
556 if (iptr->sx.val.anyptr == 0) {
559 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
563 emit_store_dst(jd, iptr, d);
567 /* load/store/copy/move operations ************************************/
569 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
570 case ICMD_ALOAD: /* s1 = local variable */
574 case ICMD_ISTORE: /* ..., value ==> ... */
585 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
589 /* integer operations *************************************************/
591 case ICMD_INEG: /* ..., value ==> ..., - value */
593 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
594 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
596 emit_store_dst(jd, iptr, d);
600 case ICMD_LNEG: /* ..., value ==> ..., - value */
602 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
603 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
604 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
605 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
606 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
607 N_AHI(GET_HIGH_REG(d), -1);
608 emit_store_dst(jd, iptr, d);
611 case ICMD_I2L: /* ..., value ==> ..., value */
613 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
614 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
616 M_INTMOVE(s1, GET_HIGH_REG(d));
617 ICONST(GET_LOW_REG(d), 0);
618 M_SRDA_IMM(32, GET_HIGH_REG(d));
620 emit_copy_dst(jd, iptr, d);
621 emit_store_dst(jd, iptr, d);
622 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
626 case ICMD_L2I: /* ..., value ==> ..., value */
627 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
628 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
629 M_INTMOVE(GET_LOW_REG(s1), d);
630 emit_store_dst(jd, iptr, d);
633 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
634 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
635 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
639 emit_store_dst(jd, iptr, d);
642 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
643 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
644 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
648 emit_store_dst(jd, iptr, d);
651 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
653 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
654 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
658 emit_store_dst(jd, iptr, d);
661 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
663 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
664 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
665 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
672 emit_store_dst(jd, iptr, d);
677 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
678 /* sx.val.i = constant */
679 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
680 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
683 if (N_VALID_IMM(iptr->sx.val.i)) {
684 M_IADD_IMM(iptr->sx.val.i, d);
686 ICONST(REG_ITMP2, iptr->sx.val.i);
687 M_IADD(REG_ITMP2, d);
689 emit_store_dst(jd, iptr, d);
692 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
694 /* M, (r, q) -> (r, q) */
696 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
698 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
699 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
700 dd = GET_HIGH_REG(d);
709 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
710 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
720 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
721 N_AHI(GET_HIGH_REG(d), 1);
723 emit_store_dst(jd, iptr, d);
726 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
727 /* sx.val.l = constant */
729 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
730 dd = GET_HIGH_REG(d);
732 s1 = emit_load_s1_high(jd, iptr, dd);
733 s3 = iptr->sx.val.l >> 32;
737 if (N_VALID_IMM(s3)) {
740 ICONST(REG_ITMP3, s3);
741 M_IADD(REG_ITMP3, dd);
745 s1 = emit_load_s1_low(jd, iptr, dd);
746 s3 = iptr->sx.val.l & 0xffffffff;
747 ICONST(REG_ITMP3, s3);
750 N_ALR(dd, REG_ITMP3);
752 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
753 N_AHI(GET_HIGH_REG(d), 1);
755 emit_store_dst(jd, iptr, d);
758 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
760 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
761 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
762 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
764 M_INTMOVE(s1, REG_ITMP1);
765 M_ISUB(s2, REG_ITMP1);
766 M_INTMOVE(REG_ITMP1, d);
771 emit_store_dst(jd, iptr, d);
775 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
776 /* sx.val.i = constant */
778 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
779 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
782 if (N_VALID_IMM(-iptr->sx.val.i)) {
783 M_ISUB_IMM(iptr->sx.val.i, d);
785 ICONST(REG_ITMP2, iptr->sx.val.i);
786 M_ISUB(REG_ITMP2, d);
788 emit_store_dst(jd, iptr, d);
792 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
794 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
796 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
797 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
798 dd = GET_HIGH_REG(d);
801 M_INTMOVE(s2, REG_ITMP3);
808 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
809 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
813 M_INTMOVE(s2, REG_ITMP3);
820 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
821 N_AHI(GET_HIGH_REG(d), -1);
823 emit_store_dst(jd, iptr, d);
826 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
827 /* sx.val.l = constant */
829 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
831 dd = GET_HIGH_REG(d);
832 s1 = emit_load_s1_high(jd, iptr, dd);
833 s3 = iptr->sx.val.l >> 32;
837 if (N_VALID_IMM(-s3)) {
840 ICONST(REG_ITMP3, s3);
841 M_ISUB(REG_ITMP3, dd);
845 s1 = emit_load_s1_low(jd, iptr, dd);
846 s3 = iptr->sx.val.l & 0xffffffff;
847 ICONST(REG_ITMP3, s3);
850 N_SLR(dd, REG_ITMP3);
852 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
853 N_AHI(GET_HIGH_REG(d), -1);
855 emit_store_dst(jd, iptr, d);
858 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
860 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
861 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
862 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
869 emit_store_dst(jd, iptr, d);
873 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
874 /* sx.val.i = constant */
875 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
876 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
878 if (iptr->sx.val.i == 2) {
880 } else if (N_VALID_IMM(iptr->sx.val.i)) {
881 M_IMUL_IMM(iptr->sx.val.i, d);
883 disp = dseg_add_s4(cd, iptr->sx.val.i);
884 M_ILD_DSEG(REG_ITMP2, disp);
885 M_IMUL(REG_ITMP2, d);
887 emit_store_dst(jd, iptr, d);
890 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
891 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
893 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
894 emit_arithmetic_check(cd, iptr, s2);
896 /* For this operation we need a register pair.
897 * We will use r0 and itmp1 and will backup r0.
900 M_INTMOVE(R0, REG_ITMP3);
902 /* We won't check for division by 0, we catch a SIGFPE instead
903 * Special case 0x80000000 / 0xffffffff handled by signal handler too.
906 s1 = emit_load_s1(jd, iptr, R0);
915 d = codegen_reg_of_dst(jd, iptr, R0);
919 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
920 M_INTMOVE(REG_ITMP1, d);
924 emit_store_dst(jd, iptr, d);
926 /* If destionation of operation was not register R0,
930 if (! ((d == R0) && !IS_INMEMORY(VAROP(iptr->dst)->flags))) {
931 M_INTMOVE(REG_ITMP3, R0);
936 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
937 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
939 bte = iptr->sx.s23.s3.bte;
942 /* test s2 for zero */
944 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
945 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
946 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
947 emit_arithmetic_check(cd, iptr, REG_ITMP3);
951 disp = dseg_add_functionptr(cd, bte->fp);
955 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
957 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
958 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
962 M_ASUB_IMM(96, REG_SP);
963 M_ALD_DSEG(REG_ITMP3, disp);
964 M_JSR(REG_RA, REG_ITMP3);
965 M_AADD_IMM(96, REG_SP);
969 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
970 M_LNGMOVE(REG_RESULT_PACKED, d);
971 emit_store_dst(jd, iptr, d);
975 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
976 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
977 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
979 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
980 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
981 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
983 /* Use only 5 bits of sencond operand. */
985 M_INTMOVE(s2, REG_ITMP2);
987 ICONST(REG_ITMP3, 0x1F);
988 M_IAND(REG_ITMP3, s2);
1005 emit_store_dst(jd, iptr, d);
1008 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1009 /* sx.val.i = constant */
1013 assert(iptr->sx.val.i <= 32);
1015 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1016 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1023 s3 = (1 << iptr->sx.val.i) - 1;
1025 if (N_VALID_IMM(s3)) {
1028 ICONST(REG_ITMP1, -1);
1029 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
1030 M_IADD(REG_ITMP1, d);
1033 N_BRC_BACK_PATCH(ref);
1035 M_SRA_IMM(iptr->sx.val.i, d);
1037 emit_store_dst(jd, iptr, d);
1042 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1043 /* sx.val.i = constant */
1045 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1046 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1049 M_MOV(s1, REG_ITMP1);
1053 ICONST(REG_ITMP3, iptr->sx.val.i);
1056 M_IAND(REG_ITMP3, d);
1059 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1065 emit_store_dst(jd, iptr, d);
1069 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1070 /* sx.val.i = constant */
1071 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1072 /* sx.val.i = constant */
1073 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1074 /* sx.val.i = constant */
1075 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1076 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1080 disp = iptr->sx.val.i & 0x1F; /* Use only 5 bits of value */
1082 switch (iptr->opc) {
1083 case ICMD_ISHLCONST:
1086 case ICMD_ISHRCONST:
1089 case ICMD_IUSHRCONST:
1096 emit_store_dst(jd, iptr, d);
1099 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1101 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1103 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1105 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1107 /* Use only 6 bits of second operand */
1109 M_INTMOVE(s2, REG_ITMP3);
1111 ICONST(REG_ITMP2, 0x3F);
1112 M_IAND(REG_ITMP2, s2);
1114 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1116 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1117 M_INTMOVE(s2, REG_ITMP3);
1121 s1 = emit_load_s1(jd, iptr, d);
1125 switch (iptr->opc) {
1127 M_SLDL(s2, GET_HIGH_REG(d));
1130 M_SRDA(s2, GET_HIGH_REG(d));
1133 M_SRDL(s2, GET_HIGH_REG(d));
1139 emit_copy_dst(jd, iptr, d);
1140 emit_store_dst(jd, iptr, d);
1141 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1145 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1146 /* sx.val.i = constant */
1147 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1148 /* sx.val.i = constant */
1149 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1150 /* sx.val.l = constant */
1153 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1154 s1 = emit_load_s1(jd, iptr, d);
1158 disp = iptr->sx.val.i & 0x3F; /* Use only 6 bits of operand */
1160 switch (iptr->opc) {
1161 case ICMD_LSHLCONST:
1162 N_SLDL(GET_HIGH_REG(d), disp, RN);
1164 case ICMD_LSHRCONST:
1165 N_SRDA(GET_HIGH_REG(d), disp, RN);
1167 case ICMD_LUSHRCONST:
1168 N_SRDL(GET_HIGH_REG(d), disp, RN);
1171 N_SLDL(GET_HIGH_REG(d), disp, RN);
1177 emit_copy_dst(jd, iptr, d);
1178 emit_store_dst(jd, iptr, d);
1179 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1183 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1185 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1186 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1187 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1194 emit_store_dst(jd, iptr, d);
1198 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1200 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1201 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1202 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1209 emit_store_dst(jd, iptr, d);
1213 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1215 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1216 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1217 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1224 emit_store_dst(jd, iptr, d);
1230 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1231 /* sx.val.i = constant */
1232 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1233 /* sx.val.i = constant */
1234 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1235 /* sx.val.i = constant */
1237 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1238 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1241 ICONST(REG_ITMP2, iptr->sx.val.i);
1243 switch (iptr->opc) {
1244 case ICMD_IANDCONST:
1245 M_IAND(REG_ITMP2, d);
1247 case ICMD_IXORCONST:
1248 M_IXOR(REG_ITMP2, d);
1251 M_IOR(REG_ITMP2, d);
1257 emit_store_dst(jd, iptr, d);
1261 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1262 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1263 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1265 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1267 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(REG_ITMP12_PACKED));
1268 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1269 dd = GET_LOW_REG(d);
1271 switch (iptr->opc) {
1300 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(REG_ITMP12_PACKED));
1301 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1302 dd = GET_HIGH_REG(d);
1304 switch (iptr->opc) {
1333 emit_store_dst(jd, iptr, d);
1336 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1337 /* sx.val.l = constant */
1338 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1339 /* sx.val.l = constant */
1340 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1341 /* sx.val.l = constant */
1343 /* TODO should use memory operand to access data segment, not load */
1345 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1347 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1348 s3 = iptr->sx.val.l & 0xffffffff;
1350 M_INTMOVE(s1, GET_LOW_REG(d));
1352 ICONST(REG_ITMP3, s3);
1354 switch (iptr->opc) {
1355 case ICMD_LANDCONST:
1356 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1358 case ICMD_LXORCONST:
1359 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1362 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1368 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1369 s3 = iptr->sx.val.l >> 32;
1371 M_INTMOVE(s1, GET_HIGH_REG(d));
1373 ICONST(REG_ITMP3, s3);
1375 switch (iptr->opc) {
1376 case ICMD_LANDCONST:
1377 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1379 case ICMD_LXORCONST:
1380 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1383 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1389 emit_store_dst(jd, iptr, d);
1393 /* floating operations ************************************************/
1395 case ICMD_FNEG: /* ..., value ==> ..., - value */
1396 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1397 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1399 emit_store_dst(jd, iptr, d);
1402 case ICMD_DNEG: /* ..., value ==> ..., - value */
1403 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1404 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1406 emit_store_dst(jd, iptr, d);
1409 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1410 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1411 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1412 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1419 emit_store_dst(jd, iptr, d);
1422 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1423 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1424 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1425 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1432 emit_store_dst(jd, iptr, d);
1435 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1436 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1437 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1438 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1442 emit_store_dst(jd, iptr, d);
1445 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1446 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1447 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1448 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1452 emit_store_dst(jd, iptr, d);
1455 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1456 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1457 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1458 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1465 emit_store_dst(jd, iptr, d);
1468 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1469 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1470 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1471 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1478 emit_store_dst(jd, iptr, d);
1481 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1482 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1483 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1484 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1488 emit_store_dst(jd, iptr, d);
1491 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1492 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1493 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1494 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1498 emit_store_dst(jd, iptr, d);
1501 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1502 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1503 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1505 emit_store_dst(jd, iptr, d);
1508 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1509 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1510 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1512 emit_store_dst(jd, iptr, d);
1515 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1519 #ifdef SUPPORT_HERCULES
1523 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1524 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1528 switch (iptr->opc) {
1537 N_BRC(DD_0 | DD_1 | DD_2, SZ_BRC + SZ_LHI + SZ_BRC); /* Non a NaN */
1538 N_LHI(d, 0); /* Load 0 */
1539 ref1 = cd->mcodeptr;
1540 N_BRC(DD_ANY, 0); /* Exit */
1544 switch (iptr->opc) {
1553 #ifdef SUPPORT_HERCULES
1554 /* Hercules does the conversion using a plain C conversion.
1555 * According to manual, real hardware should *NOT* require this.
1557 * Corner case: Positive float leads to INT_MIN (overflow).
1560 switch (iptr->opc) {
1569 ref2 = cd->mcodeptr;
1570 N_BRC(DD_0 | DD_1 | DD_3, 0); /* If operand is positive, continue */
1574 ref3 = cd->mcodeptr;
1575 M_BGE(0); /* If integer result is negative, continue */
1577 disp = dseg_add_s4(cd, 0x7fffffff); /* Load INT_MAX */
1578 M_ILD_DSEG(d, disp);
1580 N_BRC_BACK_PATCH(ref1);
1581 #ifdef SUPPORT_HERCULES
1582 N_BRC_BACK_PATCH(ref2);
1583 N_BRC_BACK_PATCH(ref3);
1585 emit_store_dst(jd, iptr, d);
1589 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1592 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1593 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1594 #ifdef SUPPORT_HERCULES
1597 N_BRC(DD_0 | DD_1 | DD_2, 0); /* Non a NaN */
1598 disp = dseg_add_double(cd, 0.0 / 0.0);
1599 M_DLD_DSEG(d, disp, REG_ITMP1);
1600 emit_label_br(cd, BRANCH_LABEL_1);
1601 N_BRC_BACK_PATCH(ref);
1604 #ifdef SUPPORT_HERCULES
1605 emit_label(cd, BRANCH_LABEL_1);
1607 emit_store_dst(jd, iptr, d);
1611 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1612 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1613 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1615 emit_store_dst(jd, iptr, d);
1618 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1619 /* == => 0, < => 1, > => -1 */
1623 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1624 /* == => 0, < => 1, > => -1 */
1627 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1628 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1629 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1631 switch (iptr->opc) {
1643 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1644 SZ_BRC + SZ_BRC + SZ_BRC
1647 N_BRC( /* load -1 */
1648 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1649 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1654 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1657 N_LHI(d, 1); /* GT */
1658 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1659 N_LHI(d, -1); /* LT */
1660 M_BR(SZ_BRC + SZ_LHI);
1661 N_LHI(d, 0); /* EQ */
1663 emit_store_dst(jd, iptr, d);
1668 /* memory operations **************************************************/
1670 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1672 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1673 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1675 /* implicit null-pointer check */
1676 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1677 emit_store_dst(jd, iptr, d);
1681 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1682 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1683 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1684 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1686 /* implicit null-pointer check */
1687 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1689 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1694 emit_store_dst(jd, iptr, d);
1697 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1699 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1700 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1701 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1703 /* implicit null-pointer check */
1704 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1706 M_INTMOVE(s2, REG_ITMP2);
1707 M_SLL_IMM(1, REG_ITMP2);
1709 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1711 /* N_LH does sign extends, undo ! */
1716 emit_store_dst(jd, iptr, d);
1719 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1720 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1721 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1722 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1724 /* implicit null-pointer check */
1725 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1727 M_INTMOVE(s2, REG_ITMP2);
1728 M_SLL_IMM(1, REG_ITMP2);
1730 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1731 emit_store_dst(jd, iptr, d);
1734 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1735 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1736 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1737 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1739 /* implicit null-pointer check */
1740 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1742 M_INTMOVE(s2, REG_ITMP2);
1743 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1744 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1745 emit_store_dst(jd, iptr, d);
1748 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1750 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1751 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1753 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1755 /* implicit null-pointer check */
1756 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1758 M_INTMOVE(s2, REG_ITMP2);
1759 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1761 /* We need to preserve the array address after the first load */
1763 if (GET_HIGH_REG(d) == s1) {
1764 M_INTMOVE(s1, REG_ITMP3);
1768 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1769 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1770 emit_store_dst(jd, iptr, d);
1774 case ICMD_FALOAD: /* ..., 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(2, REG_ITMP2); /* scale index by 4 */
1786 N_LE(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1788 emit_store_dst(jd, iptr, d);
1791 case ICMD_DALOAD: /* ..., 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_FTMP1);
1796 /* implicit null-pointer check */
1797 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1799 M_INTMOVE(s2, REG_ITMP2);
1800 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1802 N_LD(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1804 emit_store_dst(jd, iptr, d);
1807 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1808 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1809 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1810 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1812 /* implicit null-pointer check */
1813 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1815 M_INTMOVE(s2, REG_ITMP2);
1816 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1817 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1818 emit_store_dst(jd, iptr, d);
1821 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1822 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1823 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1824 /* implicit null-pointer check */
1825 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1826 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1828 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1831 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1833 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1834 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1835 /* implicit null-pointer check */
1836 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1837 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1839 M_INTMOVE(s2, REG_ITMP2);
1840 M_SLL_IMM(1, REG_ITMP2);
1842 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1846 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1847 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1848 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1849 /* implicit null-pointer check */
1850 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1851 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1853 M_INTMOVE(s2, REG_ITMP2);
1854 M_SLL_IMM(1, REG_ITMP2);
1856 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1859 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1861 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1862 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1863 /* implicit null-pointer check */
1864 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1866 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1868 M_INTMOVE(s2, REG_ITMP2);
1869 M_SLL_IMM(2, REG_ITMP2);
1871 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1874 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1876 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1877 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1878 /* implicit null-pointer check */
1879 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1881 M_INTMOVE(s2, REG_ITMP2);
1882 M_SLL_IMM(3, REG_ITMP2);
1884 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1885 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1886 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1887 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1890 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1891 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1892 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1893 /* implicit null-pointer check */
1894 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1895 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1897 M_INTMOVE(s2, REG_ITMP2);
1898 M_SLL_IMM(2, REG_ITMP2);
1900 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1903 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1904 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1905 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1906 /* implicit null-pointer check */
1907 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1908 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1910 M_INTMOVE(s2, REG_ITMP2);
1911 M_SLL_IMM(3, REG_ITMP2);
1913 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1916 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1918 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1919 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1920 /* implicit null-pointer check */
1921 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1922 s3 = emit_load_s3(jd, iptr, REG_A1);
1924 M_INTMOVE(s1, REG_A0);
1925 M_INTMOVE(s3, REG_A1);
1927 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1928 M_ALD_DSEG(REG_ITMP3, disp);
1929 M_ASUB_IMM(96, REG_SP);
1930 M_JSR(REG_RA, REG_ITMP3);
1931 M_AADD_IMM(96, REG_SP);
1933 emit_exception_check(cd, iptr);
1935 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1936 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1937 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1939 M_INTMOVE(s2, REG_ITMP2);
1940 M_SLL_IMM(2, REG_ITMP2);
1941 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1944 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1945 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1950 case ICMD_GETSTATIC: /* ... ==> ..., value */
1952 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1953 uf = iptr->sx.s23.s3.uf;
1954 fieldtype = uf->fieldref->parseddesc.fd->type;
1955 disp = dseg_add_unique_address(cd, NULL);
1957 /* PROFILE_CYCLE_STOP; */
1959 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1961 /* PROFILE_CYCLE_START; */
1964 fi = iptr->sx.s23.s3.fmiref->p.field;
1965 fieldtype = fi->type;
1966 disp = dseg_add_address(cd, &(fi->value));
1968 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1971 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
1973 PROFILE_CYCLE_START;
1977 M_ALD_DSEG(REG_ITMP1, disp);
1979 switch (fieldtype) {
1981 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1982 M_ILD(d, REG_ITMP1, 0);
1985 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
1986 M_LLD(d, REG_ITMP1, 0);
1989 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1990 M_ALD(d, REG_ITMP1, 0);
1993 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1994 M_FLD(d, REG_ITMP1, 0);
1997 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1998 M_DLD(d, REG_ITMP1, 0);
2002 emit_store_dst(jd, iptr, d);
2006 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2008 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2009 uf = iptr->sx.s23.s3.uf;
2010 fieldtype = uf->fieldref->parseddesc.fd->type;
2011 disp = dseg_add_unique_address(cd, uf);
2013 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2016 fi = iptr->sx.s23.s3.fmiref->p.field;
2017 fieldtype = fi->type;
2018 disp = dseg_add_address(cd, &(fi->value));
2020 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2021 codegen_addpatchref(cd, PATCHER_clinit,
2025 M_ALD_DSEG(REG_ITMP1, disp);
2026 switch (fieldtype) {
2028 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2029 M_IST(s1, REG_ITMP1, 0);
2032 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2033 M_LST(s1, REG_ITMP1, 0);
2036 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2037 M_AST(s1, REG_ITMP1, 0);
2040 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2041 M_FST(s1, REG_ITMP1, 0);
2044 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2045 M_DST(s1, REG_ITMP1, 0);
2050 case ICMD_GETFIELD: /* ... ==> ..., value */
2052 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2053 emit_nullpointer_check(cd, iptr, s1);
2055 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2056 uf = iptr->sx.s23.s3.uf;
2057 fieldtype = uf->fieldref->parseddesc.fd->type;
2060 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2063 fi = iptr->sx.s23.s3.fmiref->p.field;
2064 fieldtype = fi->type;
2068 switch (fieldtype) {
2070 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2074 d = codegen_reg_of_dst(jd, iptr, REG_ITMP23_PACKED);
2075 if (GET_HIGH_REG(d) == s1) {
2076 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2077 M_ILD(GET_HIGH_REG(d), s1, disp);
2080 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2081 M_ILD(GET_HIGH_REG(d), s1, disp);
2085 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2089 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2093 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2097 emit_store_dst(jd, iptr, d);
2100 case ICMD_PUTFIELD: /* ..., objectref, 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;
2113 fi = iptr->sx.s23.s3.fmiref->p.field;
2114 fieldtype = fi->type;
2118 /* We can't add a patcher ref behind this load,
2119 * because the patcher would destroy REG_ITMP3.
2121 * We pass in the disp parameter, how many bytes
2122 * to skip to the to the actual store.
2124 * XXX this relies on codegen_add_patch_ref internals
2127 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2128 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2133 if (IS_INT_LNG_TYPE(fieldtype)) {
2134 if (IS_2_WORD_TYPE(fieldtype))
2135 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2137 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2139 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2142 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2143 cd->patchrefs->disp = (cd->mcodeptr - ref);
2146 switch (fieldtype) {
2148 M_IST(s2, s1, disp);
2151 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2152 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2155 M_AST(s2, s1, disp);
2158 M_FST(s2, s1, disp);
2161 M_DST(s2, s1, disp);
2168 /* branch operations **************************************************/
2170 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2172 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2173 M_INTMOVE(s1, REG_ITMP1_XPTR);
2177 #ifdef ENABLE_VERIFIER
2178 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2179 uc = iptr->sx.s23.s2.uc;
2181 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2183 #endif /* ENABLE_VERIFIER */
2185 disp = dseg_add_functionptr(cd, asm_handle_exception);
2186 M_ALD_DSEG(REG_ITMP2, disp);
2187 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2192 case ICMD_GOTO: /* ... ==> ... */
2193 case ICMD_RET: /* ... ==> ... */
2195 emit_br(cd, iptr->dst.block);
2199 case ICMD_JSR: /* ... ==> ... */
2201 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
2205 case ICMD_IFNULL: /* ..., value ==> ... */
2206 case ICMD_IFNONNULL: /* ..., value ==> ... */
2207 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2209 switch (iptr->opc) {
2211 emit_beq(cd, iptr->dst.block);
2213 case ICMD_IFNONNULL:
2214 emit_bne(cd, iptr->dst.block);
2219 case ICMD_IFEQ: /* ..., value ==> ... */
2220 case ICMD_IFLT: /* ..., value ==> ... */
2221 case ICMD_IFLE: /* ..., value ==> ... */
2222 case ICMD_IFNE: /* ..., value ==> ... */
2223 case ICMD_IFGT: /* ..., value ==> ... */
2224 case ICMD_IFGE: /* ..., value ==> ... */
2226 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2228 if (N_VALID_IMM(iptr->sx.val.i))
2229 M_ICMP_IMM(s1, iptr->sx.val.i);
2231 disp = dseg_add_s4(cd, iptr->sx.val.i);
2232 if (N_VALID_DSEG_DISP(disp)) {
2233 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2235 ICONST(REG_ITMP2, disp);
2236 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2240 switch (iptr->opc) {
2242 emit_blt(cd, iptr->dst.block);
2245 emit_ble(cd, iptr->dst.block);
2248 emit_bne(cd, iptr->dst.block);
2251 emit_bgt(cd, iptr->dst.block);
2254 emit_bge(cd, iptr->dst.block);
2257 emit_beq(cd, iptr->dst.block);
2263 case ICMD_IF_LLT: /* ..., value ==> ... */
2264 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2270 /* ATTENTION: compare high words signed and low words unsigned */
2272 # define LABEL_OUT BRANCH_LABEL_1
2274 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2276 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2277 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2279 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2280 if (N_VALID_DSEG_DISP(disp)) {
2281 N_C(s1, N_DSEG_DISP(disp), RN, REG_PV);
2283 ICONST(REG_ITMP2, disp);
2284 N_C(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2291 emit_blt(cd, iptr->dst.block);
2292 /* EQ ... fall through */
2293 emit_label_bgt(cd, LABEL_OUT);
2297 emit_bgt(cd, iptr->dst.block);
2298 /* EQ ... fall through */
2299 emit_label_blt(cd, LABEL_OUT);
2302 /* EQ ... fall through */
2303 emit_label_bne(cd, LABEL_OUT);
2306 /* EQ ... fall through */
2307 emit_bne(cd, iptr->dst.block);
2313 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2315 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2316 if (N_VALID_DSEG_DISP(disp)) {
2317 N_CL(s1, N_DSEG_DISP(disp), RN, REG_PV);
2319 ICONST(REG_ITMP2, disp);
2320 N_CL(s1, -N_PV_OFFSET, REG_ITMP2, REG_PV);
2325 emit_blt(cd, iptr->dst.block);
2326 emit_label(cd, LABEL_OUT);
2329 emit_ble(cd, iptr->dst.block);
2330 emit_label(cd, LABEL_OUT);
2333 emit_bgt(cd, iptr->dst.block);
2334 emit_label(cd, LABEL_OUT);
2337 emit_bge(cd, iptr->dst.block);
2338 emit_label(cd, LABEL_OUT);
2341 emit_beq(cd, iptr->dst.block);
2342 emit_label(cd, LABEL_OUT);
2345 emit_bne(cd, iptr->dst.block);
2354 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2355 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2357 /* Compare addresses as 31 bit unsigned integers */
2359 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2360 M_LDA(REG_ITMP1, s1, 0);
2362 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2363 M_LDA(REG_ITMP2, s2, 0);
2365 M_CMP(REG_ITMP1, REG_ITMP2);
2367 switch (iptr->opc) {
2368 case ICMD_IF_ACMPEQ:
2369 emit_beq(cd, iptr->dst.block);
2371 case ICMD_IF_ACMPNE:
2372 emit_bne(cd, iptr->dst.block);
2378 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2379 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2380 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2381 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2382 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2383 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2385 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2386 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2388 switch (iptr->opc) {
2389 case ICMD_IF_ICMPEQ:
2390 emit_beq(cd, iptr->dst.block);
2392 case ICMD_IF_ICMPNE:
2393 emit_bne(cd, iptr->dst.block);
2395 case ICMD_IF_ICMPLT:
2396 emit_blt(cd, iptr->dst.block);
2398 case ICMD_IF_ICMPGT:
2399 emit_bgt(cd, iptr->dst.block);
2401 case ICMD_IF_ICMPLE:
2402 emit_ble(cd, iptr->dst.block);
2404 case ICMD_IF_ICMPGE:
2405 emit_bge(cd, iptr->dst.block);
2411 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2412 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2413 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2414 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2415 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2416 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2421 /* ATTENTION: compare high words signed and low words unsigned */
2423 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2424 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2429 case ICMD_IF_LCMPLT:
2430 case ICMD_IF_LCMPLE:
2431 emit_blt(cd, iptr->dst.block);
2432 /* EQ ... fall through */
2433 out_ref = cd->mcodeptr;
2436 case ICMD_IF_LCMPGT:
2437 case ICMD_IF_LCMPGE:
2438 emit_bgt(cd, iptr->dst.block);
2439 /* EQ ... fall through */
2440 out_ref = cd->mcodeptr;
2443 case ICMD_IF_LCMPEQ:
2444 /* EQ ... fall through */
2445 out_ref = cd->mcodeptr;
2448 case ICMD_IF_LCMPNE:
2449 /* EQ ... fall through */
2450 emit_bne(cd, iptr->dst.block);
2456 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2457 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2462 case ICMD_IF_LCMPLT:
2463 emit_blt(cd, iptr->dst.block);
2465 case ICMD_IF_LCMPLE:
2466 emit_ble(cd, iptr->dst.block);
2468 case ICMD_IF_LCMPGT:
2469 emit_bgt(cd, iptr->dst.block);
2471 case ICMD_IF_LCMPGE:
2472 emit_bge(cd, iptr->dst.block);
2474 case ICMD_IF_LCMPEQ:
2475 emit_beq(cd, iptr->dst.block);
2477 case ICMD_IF_LCMPNE:
2478 emit_bne(cd, iptr->dst.block);
2485 if (out_ref != NULL) {
2486 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2492 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2494 REPLACEMENT_POINT_RETURN(cd, iptr);
2495 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2496 M_INTMOVE(s1, REG_RESULT);
2497 goto nowperformreturn;
2499 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2501 REPLACEMENT_POINT_RETURN(cd, iptr);
2502 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2503 M_INTMOVE(s1, REG_RESULT);
2505 #ifdef ENABLE_VERIFIER
2506 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2507 unresolved_class *uc = iptr->sx.s23.s2.uc;
2509 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2511 #endif /* ENABLE_VERIFIER */
2512 goto nowperformreturn;
2514 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2516 REPLACEMENT_POINT_RETURN(cd, iptr);
2517 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2518 M_LNGMOVE(s1, REG_RESULT_PACKED);
2519 goto nowperformreturn;
2521 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2524 REPLACEMENT_POINT_RETURN(cd, iptr);
2525 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2526 M_FLTMOVE(s1, REG_FRESULT);
2527 goto nowperformreturn;
2529 case ICMD_RETURN: /* ... ==> ... */
2531 REPLACEMENT_POINT_RETURN(cd, iptr);
2537 p = cd->stackframesize;
2539 /* call trace function */
2541 #if !defined(NDEBUG)
2542 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2543 emit_verbosecall_exit(jd);
2544 #endif /* !defined(NDEBUG) */
2546 #if defined(ENABLE_THREADS)
2547 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2549 /* we need to save the proper return value */
2551 switch (iptr->opc) {
2553 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2557 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2560 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2563 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2567 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2569 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2570 M_ALD_DSEG(REG_ITMP3, disp);
2572 M_ASUB_IMM(96, REG_SP);
2574 M_AADD_IMM(96, REG_SP);
2576 /* and now restore the proper return value */
2578 switch (iptr->opc) {
2580 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2584 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2587 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2590 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2596 /* restore return address */
2598 p--; M_ALD(REG_RA, REG_SP, p * 4);
2600 /* restore saved registers */
2602 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2603 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2605 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2606 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2609 /* deallocate stack */
2611 if (cd->stackframesize)
2612 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2619 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2622 branch_target_t *table;
2624 table = iptr->dst.table;
2626 l = iptr->sx.s23.s2.tablelow;
2627 i = iptr->sx.s23.s3.tablehigh;
2629 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2630 M_INTMOVE(s1, REG_ITMP1);
2634 } else if (N_VALID_IMM(-l)) {
2635 M_ISUB_IMM(l, REG_ITMP1);
2637 ICONST(REG_ITMP2, l);
2638 M_ISUB(REG_ITMP2, REG_ITMP1);
2641 /* number of targets */
2647 ICONST(REG_ITMP2, i);
2648 M_ICMPU(REG_ITMP1, REG_ITMP2);
2649 emit_bge(cd, table[0].block);
2651 /* build jump table top down and use address of lowest entry */
2656 dseg_add_target(cd, table->block);
2661 /* length of dataseg after last dseg_add_target is used by load */
2663 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2664 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2665 N_L(REG_ITMP1, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2666 M_JMP(RN, REG_ITMP1);
2671 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2674 lookup_target_t *lookup;
2676 lookup = iptr->dst.lookup;
2678 i = iptr->sx.s23.s2.lookupcount;
2680 MCODECHECK(8 + ((7 + 6) * i) + 5);
2681 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2684 if (N_VALID_IMM(lookup->value)) {
2685 M_ICMP_IMM(s1, lookup->value);
2687 ICONST(REG_ITMP2, lookup->value);
2688 M_ICMP(REG_ITMP2, s1);
2690 emit_beq(cd, lookup->target.block);
2694 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2699 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2701 bte = iptr->sx.s23.s3.bte;
2705 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2706 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2707 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2708 case ICMD_INVOKEINTERFACE:
2710 REPLACEMENT_POINT_INVOKE(cd, iptr);
2712 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2714 um = iptr->sx.s23.s3.um;
2715 md = um->methodref->parseddesc.md;
2718 lm = iptr->sx.s23.s3.fmiref->p.method;
2720 md = lm->parseddesc;
2724 s3 = md->paramcount;
2726 MCODECHECK((s3 << 1) + 64);
2728 /* copy arguments to registers or stack location */
2730 for (s3 = s3 - 1; s3 >= 0; s3--) {
2731 var = VAR(iptr->sx.s23.s2.args[s3]);
2733 /* Already Preallocated? */
2734 if (var->flags & PREALLOC)
2737 if (IS_INT_LNG_TYPE(var->type)) {
2738 if (!md->params[s3].inmemory) {
2739 if (IS_2_WORD_TYPE(var->type)) {
2741 GET_LOW_REG(md->params[s3].regoff),
2742 GET_HIGH_REG(md->params[s3].regoff)
2744 d = emit_load(jd, iptr, var, s1);
2748 s1 = md->params[s3].regoff;
2749 d = emit_load(jd, iptr, var, s1);
2754 if (IS_2_WORD_TYPE(var->type)) {
2755 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2756 M_LST(d, REG_SP, md->params[s3].regoff);
2759 d = emit_load(jd, iptr, var, REG_ITMP1);
2760 M_IST(d, REG_SP, md->params[s3].regoff);
2765 if (!md->params[s3].inmemory) {
2766 s1 = md->params[s3].regoff;
2767 d = emit_load(jd, iptr, var, s1);
2771 d = emit_load(jd, iptr, var, REG_FTMP1);
2772 if (IS_2_WORD_TYPE(var->type))
2773 M_DST(d, REG_SP, md->params[s3].regoff);
2775 M_FST(d, REG_SP, md->params[s3].regoff);
2780 switch (iptr->opc) {
2782 disp = dseg_add_functionptr(cd, bte->fp);
2784 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2785 if (N_VALID_DSEG_DISP(disp)) {
2786 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2788 N_LHI(REG_ITMP1, disp);
2789 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2793 case ICMD_INVOKESPECIAL:
2795 /* Implicit NULL pointer check */
2796 M_ILD(REG_ITMP1, REG_A0, 0);
2800 case ICMD_INVOKESTATIC:
2802 disp = dseg_add_unique_address(cd, um);
2804 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2808 disp = dseg_add_address(cd, lm->stubroutine);
2810 if (N_VALID_DSEG_DISP(disp)) {
2811 N_L(REG_PV, N_DSEG_DISP(disp), RN, REG_PV);
2813 N_LHI(REG_ITMP1, disp);
2814 N_L(REG_PV, -N_PV_OFFSET, REG_ITMP1, REG_PV);
2818 case ICMD_INVOKEVIRTUAL:
2819 /* TODO softnull REG_A0 */
2822 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2827 s1 = OFFSET(vftbl_t, table[0]) +
2828 sizeof(methodptr) * lm->vftblindex;
2831 /* implicit null-pointer check */
2833 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2834 M_ALD(REG_PV, REG_METHODPTR, s1);
2837 case ICMD_INVOKEINTERFACE:
2838 /* TODO softnull REG_A0 */
2840 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2841 * and -0xFFF in index register (itmp1)
2844 N_LHI(REG_ITMP1, -N_DISP_MAX);
2847 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2853 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2854 sizeof(methodptr*) * lm->class->index +
2857 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2860 /* Implicit null-pointer check */
2861 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2862 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
2863 M_ALD(REG_PV, REG_METHODPTR, s2);
2867 /* generate the actual call */
2870 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2871 emit_restore_pv(cd);
2873 /* post call finalization */
2875 switch (iptr->opc) {
2877 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2878 emit_exception_check(cd, iptr); /* check for exception */
2882 /* store return value */
2884 d = md->returntype.type;
2886 if (d != TYPE_VOID) {
2887 if (IS_INT_LNG_TYPE(d)) {
2888 if (IS_2_WORD_TYPE(d)) {
2889 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2890 M_LNGMOVE(REG_RESULT_PACKED, s1);
2893 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2894 M_INTMOVE(REG_RESULT, s1);
2898 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2899 M_FLTMOVE(REG_FRESULT, s1);
2901 emit_store_dst(jd, iptr, s1);
2907 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2909 /* val.a: (classinfo*) superclass */
2911 /* superclass is an interface:
2913 * OK if ((sub == NULL) ||
2914 * (sub->vftbl->interfacetablelength > super->index) &&
2915 * (sub->vftbl->interfacetable[-super->index] != NULL));
2917 * superclass is a class:
2919 * OK if ((sub == NULL) || (0
2920 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2921 * super->vftbl->diffval));
2924 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2925 /* object type cast-check */
2928 vftbl_t *supervftbl;
2931 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
2932 # define LABEL_CLASS BRANCH_LABEL_2
2933 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
2934 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_4
2935 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_5
2937 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2943 super = iptr->sx.s23.s3.c.cls;
2944 superindex = super->index;
2945 supervftbl = super->vftbl;
2948 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2949 CODEGEN_CRITICAL_SECTION_NEW;
2951 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2953 /* if class is not resolved, check which code to call */
2955 if (super == NULL) {
2957 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
2959 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2961 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
2962 iptr->sx.s23.s3.c.ref,
2965 ICONST(REG_ITMP2, ACC_INTERFACE);
2966 if (N_VALID_DSEG_DISP(disp)) {
2967 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
2969 ICONST(REG_ITMP3, disp);
2970 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
2972 emit_label_beq(cd, LABEL_CLASS);
2975 /* interface checkcast code */
2977 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2978 if (super == NULL) {
2979 codegen_add_patch_ref(cd,
2980 PATCHER_checkcast_instanceof_interface,
2981 iptr->sx.s23.s3.c.ref,
2985 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
2988 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2989 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2990 M_ISUB_IMM(superindex, REG_ITMP3);
2991 emit_classcast_check(cd, iptr, BRANCH_LE, RN, s1);
2994 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2995 superindex * sizeof(methodptr*))
2997 M_ALD(REG_ITMP2, REG_ITMP2, 0);
2998 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP2, s1);
3000 if (super == NULL) {
3001 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3005 /* class checkcast code */
3007 if (super == NULL) {
3008 emit_label(cd, LABEL_CLASS);
3011 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3012 if (super == NULL) {
3013 disp = dseg_add_unique_address(cd, NULL);
3015 codegen_add_patch_ref(cd,
3016 PATCHER_resolve_classref_to_vftbl,
3017 iptr->sx.s23.s3.c.ref,
3021 disp = dseg_add_address(cd, supervftbl);
3023 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3026 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3027 M_ALD_DSEG(REG_ITMP3, disp);
3029 CODEGEN_CRITICAL_SECTION_START;
3031 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3032 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3033 M_ISUB(REG_ITMP3, REG_ITMP2);
3034 M_ALD_DSEG(REG_ITMP3, disp);
3035 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3037 CODEGEN_CRITICAL_SECTION_END;
3039 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3040 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3041 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3042 /* Branch if greater then */
3043 emit_classcast_check(cd, iptr, BRANCH_GT, RN, s1);
3046 if (super == NULL) {
3047 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3048 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3049 } else if (super->flags & ACC_INTERFACE) {
3050 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3052 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3055 d = codegen_reg_of_dst(jd, iptr, s1);
3057 # undef LABEL_EXIT_CHECK_NULL
3059 # undef LABEL_EXIT_INTERFACE_NULL
3060 # undef LABEL_EXIT_INTERFACE_DONE
3061 # undef LABEL_EXIT_CLASS_NULL
3064 /* array type cast-check */
3066 s1 = emit_load_s1(jd, iptr, REG_A0);
3067 M_INTMOVE(s1, REG_A0);
3069 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3070 disp = dseg_add_unique_address(cd, NULL);
3072 codegen_add_patch_ref(cd,
3073 PATCHER_resolve_classref_to_classinfo,
3074 iptr->sx.s23.s3.c.ref,
3078 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3080 M_ALD_DSEG(REG_A1, disp);
3081 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3082 M_ALD_DSEG(REG_ITMP1, disp);
3083 M_ASUB_IMM(96, REG_SP);
3084 M_JSR(REG_RA, REG_ITMP1);
3085 M_AADD_IMM(96, REG_SP);
3087 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3088 emit_classcast_check(cd, iptr, BRANCH_EQ, REG_RESULT, s1);
3090 d = codegen_reg_of_dst(jd, iptr, s1);
3094 emit_store_dst(jd, iptr, d);
3097 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3098 /* val.a: (classinfo*) superclass */
3100 /* superclass is an interface:
3102 * return (sub != NULL) &&
3103 * (sub->vftbl->interfacetablelength > super->index) &&
3104 * (sub->vftbl->interfacetable[-super->index] != NULL);
3106 * superclass is a class:
3108 * return ((sub != NULL) && (0
3109 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3110 * super->vftbl->diffvall));
3112 * If superclass is unresolved, we include both code snippets
3113 * above, a patcher resolves the class' flags and we select
3114 * the right code at runtime.
3119 vftbl_t *supervftbl;
3122 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3128 super = iptr->sx.s23.s3.c.cls;
3129 superindex = super->index;
3130 supervftbl = super->vftbl;
3133 # define LABEL_EXIT_CHECK_NULL BRANCH_LABEL_1
3134 # define LABEL_CLASS BRANCH_LABEL_2
3135 # define LABEL_EXIT_INTERFACE_NULL BRANCH_LABEL_3
3136 # define LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE BRANCH_LABEL_4
3137 # define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
3138 # define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
3140 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
3141 CODEGEN_CRITICAL_SECTION_NEW;
3143 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
3144 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3146 M_MOV(s1, REG_ITMP1);
3150 /* if class is not resolved, check which code to call */
3152 if (super == NULL) {
3156 emit_label_beq(cd, LABEL_EXIT_CHECK_NULL);
3158 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3160 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3161 iptr->sx.s23.s3.c.ref, disp);
3163 ICONST(REG_ITMP2, ACC_INTERFACE);
3165 if (N_VALID_DSEG_DISP(disp)) {
3166 N_N(REG_ITMP2, N_DSEG_DISP(disp), RN, REG_PV);
3168 ICONST(REG_ITMP3, disp);
3169 N_N(REG_ITMP2, -N_PV_OFFSET, REG_ITMP3, REG_PV);
3172 emit_label_beq(cd, LABEL_CLASS);
3175 /* interface instanceof code */
3177 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3178 if (super == NULL) {
3179 /* If d == REG_ITMP2, then it's destroyed in check
3184 codegen_add_patch_ref(cd,
3185 PATCHER_checkcast_instanceof_interface,
3186 iptr->sx.s23.s3.c.ref, 0);
3191 emit_label_beq(cd, LABEL_EXIT_INTERFACE_NULL);
3194 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3195 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3196 M_ISUB_IMM(superindex, REG_ITMP3);
3198 emit_label_ble(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3202 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3203 superindex * sizeof(methodptr*))
3205 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3207 /* d := (REG_ITMP1 != 0) */
3209 N_LTR(d, REG_ITMP1);
3210 M_BEQ(SZ_BRC + SZ_LHI);
3213 if (super == NULL) {
3214 emit_label_br(cd, LABEL_EXIT_INTERFACE_DONE);
3218 /* class instanceof code */
3220 if (super == NULL) {
3221 emit_label(cd, LABEL_CLASS);
3224 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3225 if (super == NULL) {
3226 disp = dseg_add_unique_address(cd, NULL);
3228 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3229 iptr->sx.s23.s3.c.ref,
3233 disp = dseg_add_address(cd, supervftbl);
3238 emit_label_beq(cd, LABEL_EXIT_CLASS_NULL);
3241 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3242 M_ALD_DSEG(REG_ITMP2, disp);
3244 CODEGEN_CRITICAL_SECTION_START;
3246 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3247 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3248 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3250 CODEGEN_CRITICAL_SECTION_END;
3252 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3254 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3256 M_BGT(SZ_BRC + SZ_LHI);
3260 if (super == NULL) {
3261 emit_label(cd, LABEL_EXIT_CHECK_NULL);
3262 emit_label(cd, LABEL_EXIT_INTERFACE_DONE);
3263 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3264 } else if (super->flags & ACC_INTERFACE) {
3265 emit_label(cd, LABEL_EXIT_INTERFACE_NULL);
3266 emit_label(cd, LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE);
3268 emit_label(cd, LABEL_EXIT_CLASS_NULL);
3271 # undef LABEL_EXIT_CHECK_NULL
3273 # undef LABEL_EXIT_INTERFACE_NULL
3274 # undef LABEL_EXIT_INTERFACE_INDEX_NOT_IN_TABLE
3275 # undef LABEL_EXIT_INTERFACE_DONE
3276 # undef LABEL_EXIT_CLASS_NULL
3278 emit_store_dst(jd, iptr, d);
3284 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3286 /* check for negative sizes and copy sizes to stack if necessary */
3288 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3291 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3293 /* copy SAVEDVAR sizes to stack */
3294 var = VAR(iptr->sx.s23.s2.args[s1]);
3296 /* Already Preallocated? */
3297 if (!(var->flags & PREALLOC)) {
3298 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3299 M_IST(s2, REG_SP, s1 * 4);
3303 /* is a patcher function set? */
3305 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3306 disp = dseg_add_unique_address(cd, 0);
3308 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
3309 iptr->sx.s23.s3.c.ref,
3313 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3315 /* a0 = dimension count */
3317 ICONST(REG_A0, iptr->s1.argcount);
3319 /* a1 = classinfo */
3321 M_ALD_DSEG(REG_A1, disp);
3323 /* a2 = pointer to dimensions = stack pointer */
3325 M_MOV(REG_SP, REG_A2);
3327 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3328 M_ALD_DSEG(REG_ITMP1, disp);
3329 M_ASUB_IMM(96, REG_SP);
3330 M_JSR(REG_RA, REG_ITMP1);
3331 M_AADD_IMM(96, REG_SP);
3333 /* check for exception before result assignment */
3335 emit_exception_check(cd, iptr);
3337 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3338 M_INTMOVE(REG_RESULT, s1);
3339 emit_store_dst(jd, iptr, s1);
3344 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3348 } /* for instruction */
3350 MCODECHECK(512); /* XXX require a lower number? */
3352 /* At the end of a basic block we may have to append some nops,
3353 because the patcher stub calling code might be longer than the
3354 actual instruction. So codepatching does not change the
3355 following block unintentionally. */
3357 if (cd->mcodeptr < cd->lastmcodeptr) {
3358 while (cd->mcodeptr < cd->lastmcodeptr) {
3363 } /* if (bptr -> flags >= BBREACHED) */
3364 } /* for basic block */
3366 dseg_createlinenumbertable(cd);
3368 /* generate stubs */
3370 emit_patcher_stubs(jd);
3372 emit_replacement_stubs(jd);
3375 /* everything's ok */
3381 /* codegen_emit_stub_compiler **************************************************
3383 Emits a stub routine which calls the compiler.
3385 *******************************************************************************/
3387 void codegen_emit_stub_compiler(jitdata *jd)
3392 /* get required compiler data */
3397 /* code for the stub */
3399 /* don't touch ITMP3 as it cointains the return address */
3401 M_AADD_IMM(N_PV_OFFSET, REG_PV); /* suppress negative displacements */
3403 M_ILD_DSEG(REG_ITMP1, -2 * SIZEOF_VOID_P); /* methodinfo */
3404 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3405 M_ILD_DSEG(REG_PV, -3 * SIZEOF_VOID_P); /* compiler pointer */
3410 /* codegen_emit_stub_native ****************************************************
3412 Emits a stub routine which calls a native method.
3414 *******************************************************************************/
3417 arguments on stack \
3418 -------------------------------------------------| <- SP on nativestub entry
3420 callee saved int regs (none) |
3421 callee saved float regs (none) | stack frame like in cacao
3422 local variable slots (none) |
3423 arguments for calling methods (none) /
3424 ------------------------------------------------------------------ <- datasp
3429 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3430 0 - 96 register save area for callee /
3431 -------------------------------------------------------- <- SP native method
3433 SP after method entry
3436 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3444 s4 i, j; /* count variables */
3449 /* get required compiler data */
3456 /* initialize variables */
3459 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3461 /* calculate stack frame size */
3463 cd->stackframesize =
3464 1 + /* r14 - return address */ +
3465 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3466 sizeof(localref_table) / SIZEOF_VOID_P +
3468 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3469 nmd->memuse + /* parameter passing */
3470 96 / SIZEOF_VOID_P /* required by ABI */;
3472 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3475 /* create method header */
3477 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3478 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3479 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3480 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3481 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3482 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3483 (void) dseg_addlinenumbertablesize(cd);
3484 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3486 /* generate native method profiling code */
3488 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3489 /* count frequency */
3491 M_MOV_IMM(code, REG_ITMP3);
3492 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3496 /* generate stub code */
3498 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3499 N_AHI(REG_PV, N_PV_OFFSET);
3501 /* save return address */
3503 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3505 #if !defined(NDEBUG)
3506 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3507 emit_verbosecall_enter(jd);
3510 /* get function address (this must happen before the stackframeinfo) */
3512 disp = dseg_add_functionptr(cd, f);
3514 #if !defined(WITH_STATIC_CLASSPATH)
3516 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3519 M_ILD_DSEG(REG_ITMP1, disp);
3521 j = 96 + (nmd->memuse * 4);
3523 /* todo some arg registers are not volatile in C-abi terms */
3525 /* save integer and float argument registers */
3527 for (i = 0; i < md->paramcount; i++) {
3528 if (! md->params[i].inmemory) {
3529 s1 = md->params[i].regoff;
3530 t = md->paramtypes[i].type;
3532 if (IS_INT_LNG_TYPE(t)) {
3533 if (IS_2_WORD_TYPE(t)) {
3534 /* todo store multiple */
3535 N_ST(GET_HIGH_REG(s1), j, RN, REG_SP);
3536 N_ST(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3538 N_ST(s1, j, RN, REG_SP);
3541 if (IS_2_WORD_TYPE(t)) {
3542 N_STD(s1, j, RN, REG_SP);
3544 N_STE(s1, j, RN, REG_SP);
3552 N_ST(REG_ITMP1, j, RN, REG_SP);
3554 /* create dynamic stack info */
3556 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3557 N_LA(REG_A1, -N_PV_OFFSET, RN, REG_PV); /* pv */
3558 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3559 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3561 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3562 M_ILD_DSEG(REG_ITMP1, disp);
3564 M_CALL(REG_ITMP1); /* call */
3566 /* restore integer and float argument registers */
3568 j = 96 + (nmd->memuse * 4);
3570 for (i = 0; i < md->paramcount; i++) {
3571 if (! md->params[i].inmemory) {
3572 s1 = md->params[i].regoff;
3573 t = md->paramtypes[i].type;
3575 if (IS_INT_LNG_TYPE(t)) {
3576 if (IS_2_WORD_TYPE(t)) {
3577 /* todo load multiple ! */
3578 N_L(GET_HIGH_REG(s1), j, RN, REG_SP);
3579 N_L(GET_LOW_REG(s1), j + 4, RN, REG_SP);
3581 N_L(s1, j, RN, REG_SP);
3584 if (IS_2_WORD_TYPE(t)) {
3585 N_LD(s1, j, RN, REG_SP);
3587 N_LE(s1, j, RN, REG_SP);
3595 N_L(REG_ITMP1, j, RN, REG_SP);
3597 /* copy or spill arguments to new locations */
3599 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3600 t = md->paramtypes[i].type;
3602 if (IS_INT_LNG_TYPE(t)) {
3604 if (!md->params[i].inmemory) {
3606 s1 = md->params[i].regoff;
3608 if (!nmd->params[j].inmemory) {
3609 s2 = nmd->params[j].regoff;
3610 if (IS_2_WORD_TYPE(t)) {
3626 s2 = nmd->params[j].regoff;
3627 if (IS_2_WORD_TYPE(t)) {
3642 s1 = cd->stackframesize * 4 + md->params[i].regoff;
3643 s2 = nmd->params[j].regoff;
3645 if (IS_2_WORD_TYPE(t)) {
3646 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3648 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3653 /* We only copy spilled float arguments, as the float argument */
3654 /* registers keep unchanged. */
3656 if (md->params[i].inmemory) {
3657 s1 = cd->stackframesize * 4 + md->params[i].regoff;
3658 s2 = nmd->params[j].regoff;
3660 if (IS_2_WORD_TYPE(t)) {
3661 N_MVC(96 + s2, 8, REG_SP, s1, REG_SP);
3663 N_MVC(96 + s2, 4, REG_SP, s1, REG_SP);
3669 /* put class into second argument register */
3671 if (m->flags & ACC_STATIC) {
3672 disp = dseg_add_address(cd, m->class);
3673 M_ILD_DSEG(REG_A1, disp);
3676 /* put env into first argument register */
3678 disp = dseg_add_address(cd, _Jv_env);
3679 M_ILD_DSEG(REG_A0, disp);
3681 /* do the native function call */
3683 M_CALL(REG_ITMP1); /* call */
3685 /* save return value */
3687 t = md->returntype.type;
3689 if (t != TYPE_VOID) {
3690 if (IS_INT_LNG_TYPE(t)) {
3691 if (IS_2_WORD_TYPE(t)) {
3692 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3694 N_ST(REG_RESULT, 96, RN, REG_SP);
3697 if (IS_2_WORD_TYPE(t)) {
3698 N_STD(REG_FRESULT, 96, RN, REG_SP);
3700 N_STE(REG_FRESULT, 96, RN, REG_SP);
3705 #if !defined(NDEBUG)
3706 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3707 emit_verbosecall_exit(jd);
3710 /* remove native stackframe info */
3712 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3713 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3714 M_ALD_DSEG(REG_ITMP1, disp);
3716 N_LR(REG_ITMP3, REG_RESULT);
3718 /* restore return value */
3720 if (t != TYPE_VOID) {
3721 if (IS_INT_LNG_TYPE(t)) {
3722 if (IS_2_WORD_TYPE(t)) {
3723 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3725 N_L(REG_RESULT, 96, RN, REG_SP);
3728 if (IS_2_WORD_TYPE(t)) {
3729 N_LD(REG_FRESULT, 96, RN, REG_SP);
3731 N_LE(REG_FRESULT, 96, RN, REG_SP);
3736 /* load return address */
3738 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3740 /* remove stackframe */
3742 N_AHI(REG_SP, cd->stackframesize * 4);
3744 /* test for exception */
3746 N_LTR(REG_ITMP3, REG_ITMP3);
3747 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3751 N_BCR(DD_ANY, REG_ITMP2);
3753 /* handle exception */
3755 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3756 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3760 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3763 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3764 M_ALD_DSEG(REG_ITMP3, disp);
3765 M_JMP(RN, REG_ITMP3);
3767 /* generate patcher stubs */
3769 emit_patcher_stubs(jd);
3772 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3773 codegendata *cd = jd->cd;
3774 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3776 M_MOV(reg, tempregnum);
3784 * These are local overrides for various environment variables in Emacs.
3785 * Please do not remove this and leave it at the end of the file, where
3786 * Emacs will automagically detect them.
3787 * ---------------------------------------------------------------------
3790 * indent-tabs-mode: t
3794 * vim:noexpandtab:sw=4:ts=4: