1 /* src/vm/jit/x86_64/codegen.c - machine code generator for x86_64
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
32 $Id: codegen.c 7616 2007-03-29 23:21:50Z michi $
46 #include "vm/jit/s390/arch.h"
47 #include "vm/jit/s390/codegen.h"
48 #include "vm/jit/s390/emit.h"
50 #include "mm/memory.h"
51 #include "native/jni.h"
52 #include "native/native.h"
54 #if defined(ENABLE_THREADS)
55 # include "threads/native/lock.h"
58 #include "vm/builtin.h"
59 #include "vm/exceptions.h"
60 #include "vm/global.h"
61 #include "vmcore/loader.h"
62 #include "vmcore/options.h"
63 #include "vmcore/statistics.h"
64 #include "vm/stringlocal.h"
66 #include "vm/jit/asmpart.h"
67 #include "vm/jit/codegen-common.h"
68 #include "vm/jit/dseg.h"
69 #include "vm/jit/emit-common.h"
70 #include "vm/jit/jit.h"
71 #include "vm/jit/methodheader.h"
72 #include "vm/jit/parse.h"
73 #include "vm/jit/patcher.h"
74 #include "vm/jit/reg.h"
75 #include "vm/jit/replace.h"
76 #include "vm/jit/stacktrace.h"
78 #if defined(ENABLE_LSRA)
79 # include "vm/jit/allocator/lsra.h"
82 #define OOPS() assert(0);
87 u1 *createcompilerstub(methodinfo *m) {
96 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) {
98 return createcompilerstub(NULL);
104 /* codegen *********************************************************************
106 Generates machine code.
108 *******************************************************************************/
111 bool codegen(jitdata *jd)
117 s4 len, s1, s2, s3, d, disp;
120 varinfo *var, *var1, *var2, *dst;
124 constant_classref *cr;
125 unresolved_class *uc;
126 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
127 unresolved_method *um;
128 builtintable_entry *bte;
131 unresolved_field *uf;
134 rplpoint *replacementpoint;
138 /* get required compiler data */
145 /* prevent compiler warnings */
158 /* space to save used callee saved registers */
160 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
161 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
163 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
166 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
169 #if defined(ENABLE_THREADS)
170 /* space to save argument of monitor_enter */
171 OOPS(); /* see powerpc */
173 if (checksync && (m->flags & ACC_SYNCHRONIZED))
174 cd->stackframesize++;
178 /* Keep stack of non-leaf functions 16-byte aligned for calls into
179 native code e.g. libc or jni (alignment problems with
182 if (!jd->isleafmethod || opt_verbosecall )
183 /* TODO really 16 bytes ? */
184 cd->stackframesize = (cd->stackframesize + 3) & ~3;
186 /* create method header */
188 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
189 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
191 #if defined(ENABLE_THREADS)
192 /* IsSync contains the offset relative to the stack pointer for the
193 argument of monitor_exit used in the exception handler. Since the
194 offset could be zero and give a wrong meaning of the flag it is
198 if (checksync && (m->flags & ACC_SYNCHRONIZED))
199 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
203 (void) dseg_add_unique_s4(cd, 0);*/ /* IsSync */
205 disp = dseg_add_unique_address(cd, 0);
207 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
208 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
209 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
211 (void) dseg_addlinenumbertablesize(cd);
213 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
215 /* create exception table */
217 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
218 dseg_add_target(cd, ex->start);
219 dseg_add_target(cd, ex->end);
220 dseg_add_target(cd, ex->handler);
221 (void) dseg_add_unique_address(cd, ex->catchtype.any);
224 /* generate method profiling code */
226 #if defined(ENABLE_PROFILING)
227 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
228 /* count frequency */
230 M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
231 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
232 M_IADD_IMM(1, REG_ITMP2);
233 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
235 /* PROFILE_CYCLE_START; */
239 /* create stack frame (if necessary) */
241 if (cd->stackframesize)
242 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
244 N_LHI(REG_ITMP2, disp);
245 N_ST(REG_SP, 0, REG_ITMP2, REG_PV);
247 /* save used callee saved registers and return address */
249 p = cd->stackframesize;
250 p--; M_AST(REG_RA, REG_SP, p * 4);
252 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
253 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
255 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
256 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
259 /* take arguments out of register or stack frame */
263 for (p = 0, l = 0; p < md->paramcount; p++) {
264 t = md->paramtypes[p].type;
265 varindex = jd->local_map[l * 5 + t];
268 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
271 if (varindex == UNUSED)
276 s1 = md->params[p].regoff;
277 if (IS_INT_LNG_TYPE(t)) { /* integer args */
278 if (IS_2_WORD_TYPE(t))
279 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
280 rd->argintregs[GET_HIGH_REG(s1)]);
282 s2 = rd->argintregs[s1];
283 if (!md->params[p].inmemory) { /* register arguments */
284 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
285 if (IS_2_WORD_TYPE(t))
286 M_LNGMOVE(s2, var->vv.regoff);
288 M_INTMOVE(s2, var->vv.regoff);
290 } else { /* reg arg -> spilled */
291 if (IS_2_WORD_TYPE(t))
292 M_LST(s2, REG_SP, var->vv.regoff * 4);
294 M_IST(s2, REG_SP, var->vv.regoff * 4);
297 } else { /* stack arguments */
298 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
299 if (IS_2_WORD_TYPE(t))
300 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
302 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
304 } else { /* stack arg -> spilled */
305 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
306 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
307 if (IS_2_WORD_TYPE(t)) {
308 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4);
309 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
314 } else { /* floating args */
315 if (!md->params[p].inmemory) { /* register arguments */
316 s2 = rd->argfltregs[s1];
317 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
318 M_FLTMOVE(s2, var->vv.regoff);
320 } else { /* reg arg -> spilled */
321 if (IS_2_WORD_TYPE(t))
322 M_DST(s2, REG_SP, var->vv.regoff * 4);
324 M_FST(s2, REG_SP, var->vv.regoff * 4);
327 } else { /* stack arguments */
328 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
329 if (IS_2_WORD_TYPE(t))
330 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
333 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
335 } else { /* stack-arg -> spilled */
336 if (IS_2_WORD_TYPE(t)) {
337 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
338 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
339 var->vv.regoff = cd->stackframesize + s1;
342 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
343 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
350 /* save monitorenter argument */
352 #if defined(ENABLE_THREADS)
353 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
354 /* stack offset for monitor argument */
358 if (opt_verbosecall) {
359 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
361 for (p = 0; p < INT_ARG_CNT; p++)
362 M_LST(rd->argintregs[p], REG_SP, p * 8);
364 for (p = 0; p < FLT_ARG_CNT; p++)
365 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
367 s1 += INT_ARG_CNT + FLT_ARG_CNT;
370 /* decide which monitor enter function to call */
372 if (m->flags & ACC_STATIC) {
373 M_MOV_IMM(&m->class->object.header, REG_A0);
378 codegen_add_nullpointerexception_ref(cd);
381 M_AST(REG_A0, REG_SP, s1 * 8);
382 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
385 if (opt_verbosecall) {
386 for (p = 0; p < INT_ARG_CNT; p++)
387 M_LLD(rd->argintregs[p], REG_SP, p * 8);
389 for (p = 0; p < FLT_ARG_CNT; p++)
390 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
392 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
398 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
399 emit_verbosecall_enter(jd);
400 #endif /* !defined(NDEBUG) */
404 /* end of header generation */
406 replacementpoint = jd->code->rplpoints;
409 /* walk through all basic blocks */
411 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
413 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
415 if (bptr->flags >= BBREACHED) {
417 /* branch resolving */
419 codegen_resolve_branchrefs(cd, bptr);
421 /* handle replacement points */
424 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
425 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
429 assert(cd->lastmcodeptr <= cd->mcodeptr);
430 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
434 /* copy interface registers to their destination */
439 /* generate basicblock profiling code */
441 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
442 /* count frequency */
444 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
445 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
447 /* if this is an exception handler, start profiling again */
449 if (bptr->type == BBTYPE_EXH)
453 #if defined(ENABLE_LSRA)
457 src = bptr->invars[len];
458 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
459 if (bptr->type == BBTYPE_EXH) {
460 /* d = reg_of_var(rd, src, REG_ITMP1); */
461 if (!IS_INMEMORY(src->flags))
465 M_INTMOVE(REG_ITMP1, d);
466 emit_store(jd, NULL, src, d);
476 var = VAR(bptr->invars[len]);
477 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
478 if (bptr->type == BBTYPE_EXH) {
479 d = codegen_reg_of_var(0, var, REG_ITMP1);
480 M_INTMOVE(REG_ITMP1, d);
481 emit_store(jd, NULL, var, d);
485 assert((var->flags & INOUT));
488 #if defined(ENABLE_LSRA)
491 /* walk through all instructions */
496 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
497 if (iptr->line != currentline) {
498 dseg_addlinenumber(cd, iptr->line);
499 currentline = iptr->line;
502 MCODECHECK(1024); /* 1KB should be enough */
505 case ICMD_NOP: /* ... ==> ... */
506 case ICMD_POP: /* ..., value ==> ... */
507 case ICMD_POP2: /* ..., value, value ==> ... */
508 case ICMD_INLINE_START: /* internal ICMDs */
509 case ICMD_INLINE_END:
512 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
513 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
516 codegen_add_nullpointerexception_ref(cd);
519 /* constant operations ************************************************/
521 case ICMD_ICONST: /* ... ==> ..., constant */
522 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
523 ICONST(d, iptr->sx.val.i);
524 emit_store_dst(jd, iptr, d);
527 case ICMD_LCONST: /* ... ==> ..., constant */
529 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
530 LCONST(d, iptr->sx.val.l);
531 emit_store_dst(jd, iptr, d);
534 case ICMD_FCONST: /* ... ==> ..., constant */
535 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
536 disp = dseg_add_float(cd, iptr->sx.val.f);
537 M_FLDN(d, REG_PV, disp, REG_ITMP1);
538 emit_store_dst(jd, iptr, d);
541 case ICMD_DCONST: /* ... ==> ..., constant */
542 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
543 disp = dseg_add_double(cd, iptr->sx.val.d);
544 M_DLDN(d, REG_PV, disp, REG_ITMP1);
545 emit_store_dst(jd, iptr, d);
548 case ICMD_ACONST: /* ... ==> ..., constant */
549 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
551 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
552 cr = iptr->sx.val.c.ref;
553 disp = dseg_add_unique_address(cd, cr);
555 /* PROFILE_CYCLE_STOP; */
557 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
560 /* PROFILE_CYCLE_START; */
562 M_ALD(d, REG_PV, disp);
564 if (iptr->sx.val.anyptr == 0) {
567 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
568 M_ALD(d, REG_PV, disp);
571 emit_store_dst(jd, iptr, d);
575 /* load/store/copy/move operations ************************************/
577 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
578 case ICMD_ALOAD: /* s1 = local variable */
582 case ICMD_ISTORE: /* ..., value ==> ... */
588 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
592 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
593 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
596 /* integer operations *************************************************/
598 case ICMD_INEG: /* ..., value ==> ..., - value */
600 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
601 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
603 emit_store_dst(jd, iptr, d);
607 case ICMD_LNEG: /* ..., value ==> ..., - value */
610 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
611 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
614 emit_store_dst(jd, iptr, d);
618 case ICMD_I2L: /* ..., value ==> ..., value */
620 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
621 s2 = emit_load_s2(jd, iptr, GET_HIGH_REG(d));
623 M_INTMOVE(s2, GET_HIGH_REG(d));
624 ICONST(GET_LOW_REG(d), 0);
625 N_SRDA(GET_HIGH_REG(d), 32, RN);
627 emit_copy_dst(jd, iptr, d);
628 emit_store_dst(jd, iptr, d);
629 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
633 case ICMD_L2I: /* ..., value ==> ..., value */
634 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
635 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
636 M_INTMOVE(GET_LOW_REG(s1), d);
637 emit_store_dst(jd, iptr, d);
640 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
643 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
644 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
646 emit_store_dst(jd, iptr, d);
650 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
651 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
652 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
656 emit_store_dst(jd, iptr, d);
659 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
662 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
663 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
665 emit_store_dst(jd, iptr, d);
670 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
672 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
673 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
674 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
681 emit_store_dst(jd, iptr, d);
686 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
687 /* sx.val.i = constant */
688 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
689 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
692 if (N_VALID_IMM(iptr->sx.val.i)) {
693 M_IADD_IMM(iptr->sx.val.i, d);
695 disp = dseg_add_s4(cd, iptr->sx.val.i);
696 M_ILD(REG_ITMP2, REG_PV, disp);
697 M_IADD(REG_ITMP2, d);
699 emit_store_dst(jd, iptr, d);
702 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
705 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
706 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
707 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
714 emit_store_dst(jd, iptr, d);
718 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
719 /* sx.val.l = constant */
722 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
723 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
725 if (IS_IMM32(iptr->sx.val.l))
726 M_LADD_IMM(iptr->sx.val.l, d);
728 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
729 M_LADD(REG_ITMP2, d);
731 emit_store_dst(jd, iptr, d);
735 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
737 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
738 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
739 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
741 M_INTMOVE(s1, REG_ITMP1);
742 M_ISUB(s2, REG_ITMP1);
743 M_INTMOVE(REG_ITMP1, d);
748 emit_store_dst(jd, iptr, d);
752 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
753 /* sx.val.i = constant */
755 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
756 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
759 if (N_VALID_IMM(iptr->sx.val.i)) {
760 M_ISUB_IMM(iptr->sx.val.i, d);
762 disp = dseg_add_s4(cd, iptr->sx.val.i);
763 M_ILD(REG_ITMP2, REG_PV, disp);
764 M_ISUB(REG_ITMP2, d);
766 emit_store_dst(jd, iptr, d);
770 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
773 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
774 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
775 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
777 M_INTMOVE(s1, REG_ITMP1);
778 M_LSUB(s2, REG_ITMP1);
779 M_INTMOVE(REG_ITMP1, d);
784 emit_store_dst(jd, iptr, d);
788 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
789 /* sx.val.l = constant */
792 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
793 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
795 if (IS_IMM32(iptr->sx.val.l))
796 M_LSUB_IMM(iptr->sx.val.l, d);
798 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
799 M_LSUB(REG_ITMP2, d);
801 emit_store_dst(jd, iptr, d);
805 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
807 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
808 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
809 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
816 emit_store_dst(jd, iptr, d);
820 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
821 /* sx.val.i = constant */
822 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
823 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
825 if (iptr->sx.val.i == 2) {
827 } else if (N_VALID_IMM(iptr->sx.val.i)) {
828 M_IMUL_IMM(iptr->sx.val.i, d);
830 disp = dseg_add_s4(cd, iptr->sx.val.i);
831 M_ILD(REG_ITMP2, REG_PV, disp);
832 M_IMUL(REG_ITMP2, d);
834 emit_store_dst(jd, iptr, d);
837 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
838 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
840 /* For this operation we need a register pair.
841 * We will use r0 and itmp1 and will backup r0.
844 M_INTMOVE(R0, REG_ITMP3);
846 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
848 s1 = emit_load_s1(jd, iptr, R0);
855 if (iptr->opc == ICMD_IREM) {
856 d = codegen_reg_of_dst(jd, iptr, R0);
859 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
860 M_INTMOVE(REG_ITMP1, d);
863 emit_store_dst(jd, iptr, d);
865 M_INTMOVE(REG_ITMP3, R0);
869 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
870 /* sx.val.i = constant */
873 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
874 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
875 M_INTMOVE(s1, REG_ITMP1);
876 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
877 emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
878 emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
879 emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
880 emit_mov_reg_reg(cd, REG_ITMP1, d);
881 emit_store_dst(jd, iptr, d);
885 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
886 /* sx.val.i = constant */
889 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
890 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
891 M_INTMOVE(s1, REG_ITMP1);
892 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
893 emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
894 emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
895 emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
896 emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
897 emit_mov_reg_reg(cd, REG_ITMP1, d);
898 emit_store_dst(jd, iptr, d);
903 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
904 /* sx.val.i = constant */
907 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
908 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
909 M_INTMOVE(s1, REG_ITMP1);
910 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
911 emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
912 emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
913 emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
914 emit_mov_reg_reg(cd, REG_ITMP1, d);
915 emit_store_dst(jd, iptr, d);
919 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
920 /* sx.val.l = constant */
923 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
924 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
925 M_INTMOVE(s1, REG_ITMP1);
926 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
927 emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
928 emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
929 emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
930 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
931 emit_mov_reg_reg(cd, REG_ITMP1, d);
932 emit_store_dst(jd, iptr, d);
936 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
937 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
938 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
940 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
941 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
942 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
957 emit_store_dst(jd, iptr, d);
960 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
961 /* sx.val.i = constant */
962 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
963 /* sx.val.i = constant */
964 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
965 /* sx.val.i = constant */
967 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
968 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
972 if (N_VALID_DISP(iptr->sx.val.i)) {
973 disp = iptr->sx.val.i;
976 ICONST(REG_ITMP3, iptr->sx.val.i);
988 case ICMD_IUSHRCONST:
995 emit_store_dst(jd, iptr, d);
998 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1000 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1002 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1004 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1005 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1007 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1008 M_INTMOVE(s2, REG_ITMP3);
1012 s1 = emit_load_s1(jd, iptr, d);
1016 switch (iptr->opc) {
1018 N_SLDA(GET_HIGH_REG(d), 0, s2);
1021 N_SRDA(GET_HIGH_REG(d), 0, s2);
1024 N_SRDL(GET_HIGH_REG(d), 0, s2);
1030 emit_copy_dst(jd, iptr, d);
1031 emit_store_dst(jd, iptr, d);
1032 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1036 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1037 /* sx.val.i = constant */
1038 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1039 /* sx.val.i = constant */
1040 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1041 /* sx.val.l = constant */
1043 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1044 s1 = emit_load_s1(jd, iptr, d);
1048 if (N_VALID_DISP(iptr->sx.val.i)) {
1049 disp = iptr->sx.val.i;
1052 ICONST(REG_ITMP3, iptr->sx.val.i);
1057 switch (iptr->opc) {
1058 case ICMD_LSHLCONST:
1059 N_SLDA(GET_HIGH_REG(d), disp, s3);
1061 case ICMD_LSHRCONST:
1062 N_SRDA(GET_HIGH_REG(d), disp, s3);
1064 case ICMD_LUSHRCONST:
1065 N_SRDL(GET_HIGH_REG(d), disp, s3);
1071 emit_copy_dst(jd, iptr, d);
1072 emit_store_dst(jd, iptr, d);
1073 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1077 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1079 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1080 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1081 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1088 emit_store_dst(jd, iptr, d);
1092 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1094 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1095 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1096 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1103 emit_store_dst(jd, iptr, d);
1107 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1109 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1110 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1111 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1118 emit_store_dst(jd, iptr, d);
1124 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1125 /* sx.val.i = constant */
1128 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1129 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1131 M_IAND_IMM(iptr->sx.val.i, d);
1132 emit_store_dst(jd, iptr, d);
1136 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1137 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1138 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1140 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1142 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1143 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1145 M_INTMOVE(s1, GET_LOW_REG(d));
1147 switch (iptr->opc) {
1149 M_IAND(s2, GET_LOW_REG(d));
1152 M_IXOR(s2, GET_LOW_REG(d));
1155 M_IOR(s2, GET_LOW_REG(d));
1161 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1162 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1164 M_INTMOVE(s1, GET_HIGH_REG(d));
1166 switch (iptr->opc) {
1168 M_IAND(s2, GET_HIGH_REG(d));
1171 M_IXOR(s2, GET_HIGH_REG(d));
1174 M_IOR(s2, GET_HIGH_REG(d));
1180 emit_store_dst(jd, iptr, d);
1183 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1184 /* sx.val.l = constant */
1185 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1186 /* sx.val.l = constant */
1187 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1188 /* sx.val.l = constant */
1190 /* TODO should use memory operand to access data segment, not load */
1192 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1194 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1195 s3 = iptr->sx.val.l & 0xffffffff;
1197 M_INTMOVE(s1, GET_LOW_REG(d));
1199 ICONST(REG_ITMP3, s3);
1201 switch (iptr->opc) {
1202 case ICMD_LANDCONST:
1203 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1205 case ICMD_LXORCONST:
1206 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1209 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1215 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1216 s3 = iptr->sx.val.l >> 32;
1218 M_INTMOVE(s1, GET_HIGH_REG(d));
1220 ICONST(REG_ITMP3, s3);
1222 switch (iptr->opc) {
1223 case ICMD_LANDCONST:
1224 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1226 case ICMD_LXORCONST:
1227 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1230 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1236 emit_store_dst(jd, iptr, d);
1240 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1241 /* sx.val.i = constant */
1244 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1245 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1247 M_IOR_IMM(iptr->sx.val.i, d);
1248 emit_store_dst(jd, iptr, d);
1252 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1253 /* sx.val.i = constant */
1256 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1257 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1259 M_IXOR_IMM(iptr->sx.val.i, d);
1260 emit_store_dst(jd, iptr, d);
1265 /* floating operations ************************************************/
1267 case ICMD_FNEG: /* ..., value ==> ..., - value */
1270 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1271 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1272 disp = dseg_add_s4(cd, 0x80000000);
1274 emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1275 emit_xorps_reg_reg(cd, REG_FTMP2, d);
1276 emit_store_dst(jd, iptr, d);
1280 case ICMD_DNEG: /* ..., value ==> ..., - value */
1283 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1284 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1285 disp = dseg_add_s8(cd, 0x8000000000000000);
1287 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1288 emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1289 emit_store_dst(jd, iptr, d);
1293 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1294 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1295 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1296 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1303 emit_store_dst(jd, iptr, d);
1306 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1307 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1308 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1309 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1316 emit_store_dst(jd, iptr, d);
1319 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1320 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1321 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1322 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1326 emit_store_dst(jd, iptr, d);
1329 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1330 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1331 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1332 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1336 emit_store_dst(jd, iptr, d);
1339 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1340 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1341 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1342 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1349 emit_store_dst(jd, iptr, d);
1352 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1353 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1354 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1355 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1362 emit_store_dst(jd, iptr, d);
1365 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1366 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1367 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1368 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1372 emit_store_dst(jd, iptr, d);
1375 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1376 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1377 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1378 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1382 emit_store_dst(jd, iptr, d);
1385 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1386 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1387 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1389 emit_store_dst(jd, iptr, d);
1392 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1393 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1394 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1396 emit_store_dst(jd, iptr, d);
1399 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1402 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1403 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1405 emit_store_dst(jd, iptr, d);
1409 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1412 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1413 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1415 emit_store_dst(jd, iptr, d);
1419 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1420 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1421 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1423 emit_store_dst(jd, iptr, d);
1424 /* TODO: corner cases ? */
1427 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1428 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1429 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1431 emit_store_dst(jd, iptr, d);
1432 /* TODO: corner cases ? */
1435 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1438 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1439 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1441 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1442 M_LCMP(REG_ITMP2, d); /* corner cases */
1443 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1444 ((REG_RESULT == d) ? 0 : 3);
1446 M_FLTMOVE(s1, REG_FTMP1);
1447 M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1449 M_INTMOVE(REG_RESULT, d);
1450 emit_store_dst(jd, iptr, d);
1454 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1457 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1458 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1460 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1461 M_LCMP(REG_ITMP2, d); /* corner cases */
1462 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1463 ((REG_RESULT == d) ? 0 : 3);
1465 M_FLTMOVE(s1, REG_FTMP1);
1466 M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1468 M_INTMOVE(REG_RESULT, d);
1469 emit_store_dst(jd, iptr, d);
1473 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1474 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1475 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1477 emit_store_dst(jd, iptr, d);
1480 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1483 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1484 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1486 emit_store_dst(jd, iptr, d);
1490 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1491 /* == => 0, < => 1, > => -1 */
1495 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1496 /* == => 0, < => 1, > => -1 */
1499 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1500 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1501 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1503 switch (iptr->opc) {
1515 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1516 SZ_BRC + SZ_BRC + SZ_BRC
1519 N_BRC( /* load -1 */
1520 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1521 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1526 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1529 N_LHI(d, 1); /* GT */
1530 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1531 N_LHI(d, -1); /* LT */
1532 M_BR(SZ_BRC + SZ_LHI);
1533 N_LHI(d, 0); /* EQ */
1535 emit_store_dst(jd, iptr, d);
1540 /* memory operations **************************************************/
1542 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1544 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1545 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1546 gen_nullptr_check(s1);
1547 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1548 emit_store_dst(jd, iptr, d);
1552 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1553 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1554 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1555 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1557 emit_array_checks(cd, iptr, s1, s2);
1559 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1560 /* TODO improove this */
1563 emit_store_dst(jd, iptr, d);
1566 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1568 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1569 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1570 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1572 emit_array_checks(cd, iptr, s1, s2);
1574 M_INTMOVE(s2, REG_ITMP2);
1575 M_ISLL_IMM(1, REG_ITMP2);
1577 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1578 emit_store_dst(jd, iptr, d);
1581 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1582 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1583 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1584 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1586 emit_array_checks(cd, iptr, s1, s2);
1588 M_INTMOVE(s2, REG_ITMP2);
1589 M_ISLL_IMM(1, REG_ITMP2);
1591 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1592 emit_store_dst(jd, iptr, d);
1595 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1596 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1597 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1598 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1599 emit_array_checks(cd, iptr, s1, s2);
1601 M_INTMOVE(s2, REG_ITMP2);
1602 M_ISLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1603 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1604 emit_store_dst(jd, iptr, d);
1607 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1609 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1610 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1612 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1613 emit_array_checks(cd, iptr, s1, s2);
1615 M_INTMOVE(s2, REG_ITMP2);
1616 M_ISLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1618 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1619 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1620 emit_store_dst(jd, iptr, d);
1624 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1627 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1628 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1629 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1630 if (INSTRUCTION_MUST_CHECK(iptr)) {
1631 gen_nullptr_check(s1);
1634 emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1635 emit_store_dst(jd, iptr, d);
1639 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1642 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1643 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1644 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1645 if (INSTRUCTION_MUST_CHECK(iptr)) {
1646 gen_nullptr_check(s1);
1649 emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1650 emit_store_dst(jd, iptr, d);
1654 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1655 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1656 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1657 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1658 emit_array_checks(cd, iptr, s1, s2);
1660 M_INTMOVE(s2, REG_ITMP2);
1661 M_ISLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1662 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1663 emit_store_dst(jd, iptr, d);
1666 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1667 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1668 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1669 emit_array_checks(cd, iptr, s1, s2);
1670 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1672 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1675 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1677 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1678 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1679 emit_array_checks(cd, iptr, s1, s2);
1680 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1682 M_INTMOVE(s2, REG_ITMP2);
1683 M_ISLL_IMM(1, REG_ITMP2);
1685 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1689 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1690 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1691 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1692 emit_array_checks(cd, iptr, s1, s2);
1693 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1695 M_INTMOVE(s2, REG_ITMP2);
1696 M_ISLL_IMM(1, REG_ITMP2);
1698 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1701 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1702 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1703 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1704 emit_array_checks(cd, iptr, s1, s2);
1705 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1707 M_INTMOVE(s2, REG_ITMP2);
1708 M_ISLL_IMM(2, REG_ITMP2);
1710 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1713 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1714 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1715 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1716 emit_array_checks(cd, iptr, s1, s2);
1718 M_INTMOVE(s2, REG_ITMP2);
1719 M_ISLL_IMM(3, REG_ITMP2);
1721 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1722 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1723 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1724 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1727 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1728 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1729 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1730 emit_array_checks(cd, iptr, s1, s2);
1731 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1733 M_INTMOVE(s2, REG_ITMP2);
1734 M_ISLL_IMM(2, REG_ITMP2);
1736 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1739 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1740 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1741 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1742 emit_array_checks(cd, iptr, s1, s2);
1743 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1745 M_INTMOVE(s2, REG_ITMP2);
1746 M_ISLL_IMM(3, REG_ITMP2);
1748 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1751 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1753 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1754 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1755 emit_array_checks(cd, iptr, s1, s2);
1756 s3 = emit_load_s3(jd, iptr, REG_A1);
1758 M_INTMOVE(s1, REG_A0);
1759 M_INTMOVE(s3, REG_A1);
1761 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1762 ICONST(REG_ITMP3, disp);
1763 N_L(REG_PV, 0, REG_ITMP3, REG_PV);
1764 M_ISUB_IMM(96, REG_SP);
1765 M_JSR(REG_RA, REG_PV);
1766 M_IADD_IMM(96, REG_SP);
1767 N_BASR(REG_ITMP1, RN);
1768 disp = (s4) (cd->mcodeptr - cd->mcodebase);
1769 M_LDA(REG_PV, REG_ITMP1, -disp);
1773 codegen_add_arraystoreexception_ref(cd);
1775 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1776 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1777 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1779 M_INTMOVE(s2, REG_ITMP2);
1780 M_ISLL_IMM(2, REG_ITMP2);
1781 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1784 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1785 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1790 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1793 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1794 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1795 if (INSTRUCTION_MUST_CHECK(iptr)) {
1796 gen_nullptr_check(s1);
1799 emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1803 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1806 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1807 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1808 if (INSTRUCTION_MUST_CHECK(iptr)) {
1809 gen_nullptr_check(s1);
1812 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
1816 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1819 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1820 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1821 if (INSTRUCTION_MUST_CHECK(iptr)) {
1822 gen_nullptr_check(s1);
1825 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1829 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1832 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1833 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1834 if (INSTRUCTION_MUST_CHECK(iptr)) {
1835 gen_nullptr_check(s1);
1838 emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
1842 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1845 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1846 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1847 if (INSTRUCTION_MUST_CHECK(iptr)) {
1848 gen_nullptr_check(s1);
1852 if (IS_IMM32(iptr->sx.s23.s3.constval)) {
1853 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
1855 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
1856 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
1861 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1864 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1865 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1866 if (INSTRUCTION_MUST_CHECK(iptr)) {
1867 gen_nullptr_check(s1);
1870 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
1875 case ICMD_GETSTATIC: /* ... ==> ..., value */
1877 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1878 uf = iptr->sx.s23.s3.uf;
1879 fieldtype = uf->fieldref->parseddesc.fd->type;
1880 disp = dseg_add_unique_address(cd, NULL);
1882 /* PROFILE_CYCLE_STOP; */
1884 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1886 /* PROFILE_CYCLE_START; */
1889 fi = iptr->sx.s23.s3.fmiref->p.field;
1890 fieldtype = fi->type;
1891 disp = dseg_add_address(cd, &(fi->value));
1893 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1896 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
1898 PROFILE_CYCLE_START;
1902 M_ALD(REG_ITMP1, REG_PV, disp);
1904 switch (fieldtype) {
1906 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1907 M_ILD(d, REG_ITMP1, 0);
1910 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1911 M_LLD(d, REG_ITMP1, 0);
1914 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1915 M_ALD(d, REG_ITMP1, 0);
1918 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1919 M_FLD(d, REG_ITMP1, 0);
1922 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1923 M_DLD(d, REG_ITMP1, 0);
1927 emit_store_dst(jd, iptr, d);
1931 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1933 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1934 uf = iptr->sx.s23.s3.uf;
1935 fieldtype = uf->fieldref->parseddesc.fd->type;
1936 disp = dseg_add_unique_address(cd, uf);
1938 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
1941 fi = iptr->sx.s23.s3.fmiref->p.field;
1942 fieldtype = fi->type;
1943 disp = dseg_add_address(cd, &(fi->value));
1945 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1946 codegen_addpatchref(cd, PATCHER_clinit,
1950 M_ALD(REG_ITMP1, REG_PV, disp);
1951 switch (fieldtype) {
1953 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1954 M_IST(s1, REG_ITMP1, 0);
1957 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
1958 M_LST(s1, REG_ITMP1, 0);
1961 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1962 M_AST(s1, REG_ITMP1, 0);
1965 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1966 M_FST(s1, REG_ITMP1, 0);
1969 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1970 M_DST(s1, REG_ITMP1, 0);
1975 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1976 /* val = value (in current instruction) */
1977 /* following NOP) */
1980 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1981 uf = iptr->sx.s23.s3.uf;
1982 fieldtype = uf->fieldref->parseddesc.fd->type;
1983 disp = dseg_add_unique_address(cd, uf);
1985 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1988 fi = iptr->sx.s23.s3.fmiref->p.field;
1989 fieldtype = fi->type;
1990 disp = dseg_add_address(cd, &(fi->value));
1992 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1993 codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class,
1997 M_ALD(REG_ITMP1, REG_PV, disp);
1999 switch (fieldtype) {
2001 M_IST(REG_ZERO, REG_ITMP1, 0);
2004 M_LST(REG_ZERO, REG_ITMP1, 0);
2007 M_AST(REG_ZERO, REG_ITMP1, 0);
2010 M_FST(REG_ZERO, REG_ITMP1, 0);
2013 M_DST(REG_ZERO, REG_ITMP1, 0);
2019 case ICMD_GETFIELD: /* ... ==> ..., value */
2021 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2022 emit_nullpointer_check(cd, iptr, s1);
2024 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2025 uf = iptr->sx.s23.s3.uf;
2026 fieldtype = uf->fieldref->parseddesc.fd->type;
2029 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2032 fi = iptr->sx.s23.s3.fmiref->p.field;
2033 fieldtype = fi->type;
2037 switch (fieldtype) {
2039 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2043 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2044 if (GET_HIGH_REG(d) == s1) {
2045 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2046 M_ILD(GET_HIGH_REG(d), s1, disp);
2049 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2050 M_ILD(GET_HIGH_REG(d), s1, disp);
2054 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2058 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2062 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2066 emit_store_dst(jd, iptr, d);
2069 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2071 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2072 gen_nullptr_check(s1);
2074 s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2076 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2077 uf = iptr->sx.s23.s3.uf;
2078 fieldtype = uf->fieldref->parseddesc.fd->type;
2082 fi = iptr->sx.s23.s3.fmiref->p.field;
2083 fieldtype = fi->type;
2087 if (IS_INT_LNG_TYPE(fieldtype)) {
2088 if (IS_2_WORD_TYPE(fieldtype))
2089 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2091 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2094 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2096 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2097 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2099 switch (fieldtype) {
2101 M_IST(s2, s1, disp);
2104 /* TODO really order */
2105 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2106 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2109 M_AST(s2, s1, disp);
2112 M_FST(s2, s1, disp);
2115 M_DST(s2, s1, disp);
2120 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2121 /* val = value (in current instruction) */
2122 /* following NOP) */
2125 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2126 gen_nullptr_check(s1);
2128 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2129 uf = iptr->sx.s23.s3.uf;
2130 fieldtype = uf->fieldref->parseddesc.fd->type;
2133 /* PROFILE_CYCLE_STOP; */
2135 codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
2137 /* PROFILE_CYCLE_START; */
2140 fi = iptr->sx.s23.s3.fmiref->p.field;
2141 fieldtype = fi->type;
2145 switch (fieldtype) {
2148 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2153 /* XXX why no check for IS_IMM32? */
2154 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2155 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2162 /* branch operations **************************************************/
2164 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2166 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2167 M_INTMOVE(s1, REG_ITMP1_XPTR);
2171 #ifdef ENABLE_VERIFIER
2172 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2173 uc = iptr->sx.s23.s2.uc;
2175 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2177 #endif /* ENABLE_VERIFIER */
2179 disp = dseg_add_functionptr(cd, asm_handle_exception);
2180 M_ALD(REG_ITMP2, REG_PV, disp);
2181 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2186 case ICMD_GOTO: /* ... ==> ... */
2187 case ICMD_RET: /* ... ==> ... */
2190 codegen_add_branch_ref(cd, iptr->dst.block);
2194 case ICMD_JSR: /* ... ==> ... */
2198 codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2202 case ICMD_IFNULL: /* ..., value ==> ... */
2203 case ICMD_IFNONNULL: /* ..., value ==> ... */
2204 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2206 switch (iptr->opc) {
2210 case ICMD_IFNONNULL:
2214 codegen_add_branch_ref(cd, iptr->dst.block);
2217 case ICMD_IFEQ: /* ..., value ==> ... */
2218 case ICMD_IFLT: /* ..., value ==> ... */
2219 case ICMD_IFLE: /* ..., value ==> ... */
2220 case ICMD_IFNE: /* ..., value ==> ... */
2221 case ICMD_IFGT: /* ..., value ==> ... */
2222 case ICMD_IFGE: /* ..., value ==> ... */
2224 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2226 if (N_VALID_IMM(iptr->sx.val.i))
2227 N_CHI(s1, iptr->sx.val.i);
2229 disp = dseg_add_s4(cd, iptr->sx.val.i);
2230 N_LHI(REG_ITMP2, disp);
2231 N_C(s1, 0, REG_ITMP2, REG_PV);
2234 switch (iptr->opc) {
2254 codegen_add_branch_ref(cd, iptr->dst.block);
2258 case ICMD_IF_LLT: /* ..., value ==> ... */
2259 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2268 /* ATTENTION: compare high words signed and low words unsigned */
2270 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2272 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2273 N_CHI(s1, iptr->sx.val.l >> 32);
2275 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2276 N_LHI(REG_ITMP2, disp);
2277 N_C(s1, 0, REG_ITMP2, REG_PV);
2284 codegen_addreference(cd, iptr->dst.block);
2285 /* EQ ... fall through */
2286 out_ref = cd->mcodeptr;
2292 codegen_addreference(cd, iptr->dst.block);
2293 /* EQ ... fall through */
2294 out_ref = cd->mcodeptr;
2298 /* EQ ... fall through */
2299 out_ref = cd->mcodeptr;
2303 /* EQ ... fall through */
2305 codegen_addreference(cd, iptr->dst.block);
2311 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2313 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2314 N_LHI(REG_ITMP2, disp);
2315 N_CL(s1, 0, REG_ITMP2, REG_PV);
2339 codegen_addreference(cd, iptr->dst.block);
2341 if (out_ref != NULL) {
2342 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2348 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2349 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2351 /* Compare addresses as 31 bit unsigned integers */
2353 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2354 N_LA(REG_ITMP1, 0, RN, s1);
2356 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2357 N_LA(REG_ITMP2, 0, RN, s2);
2359 M_CMP(REG_ITMP1, REG_ITMP2);
2361 switch (iptr->opc) {
2362 case ICMD_IF_ACMPEQ:
2365 case ICMD_IF_ACMPNE:
2370 codegen_add_branch_ref(cd, iptr->dst.block);
2374 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2375 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2376 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2377 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2378 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2379 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2381 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2382 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2384 switch (iptr->opc) {
2385 case ICMD_IF_ICMPEQ:
2388 case ICMD_IF_ICMPNE:
2391 case ICMD_IF_ICMPLT:
2394 case ICMD_IF_ICMPGT:
2397 case ICMD_IF_ICMPLE:
2400 case ICMD_IF_ICMPGE:
2404 codegen_add_branch_ref(cd, iptr->dst.block);
2408 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2409 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2410 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2411 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2412 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2413 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2418 /* ATTENTION: compare high words signed and low words unsigned */
2420 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2421 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2426 case ICMD_IF_LCMPLT:
2427 case ICMD_IF_LCMPLE:
2429 codegen_addreference(cd, iptr->dst.block);
2430 /* EQ ... fall through */
2431 out_ref = cd->mcodeptr;
2434 case ICMD_IF_LCMPGT:
2435 case ICMD_IF_LCMPGE:
2437 codegen_addreference(cd, iptr->dst.block);
2438 /* EQ ... fall through */
2439 out_ref = cd->mcodeptr;
2442 case ICMD_IF_LCMPEQ:
2443 /* EQ ... fall through */
2444 out_ref = cd->mcodeptr;
2447 case ICMD_IF_LCMPNE:
2448 /* EQ ... fall through */
2450 codegen_addreference(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:
2465 case ICMD_IF_LCMPLE:
2468 case ICMD_IF_LCMPGT:
2471 case ICMD_IF_LCMPGE:
2474 case ICMD_IF_LCMPEQ:
2477 case ICMD_IF_LCMPNE:
2484 codegen_addreference(cd, iptr->dst.block);
2486 if (out_ref != NULL) {
2487 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2493 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2495 REPLACEMENT_POINT_RETURN(cd, iptr);
2496 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2497 M_INTMOVE(s1, REG_RESULT);
2498 goto nowperformreturn;
2500 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2502 REPLACEMENT_POINT_RETURN(cd, iptr);
2503 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2504 M_INTMOVE(s1, REG_RESULT);
2506 #ifdef ENABLE_VERIFIER
2507 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2508 unresolved_class *uc = iptr->sx.s23.s2.uc;
2510 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2512 #endif /* ENABLE_VERIFIER */
2513 goto nowperformreturn;
2515 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2517 REPLACEMENT_POINT_RETURN(cd, iptr);
2518 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2519 M_LNGMOVE(s1, REG_RESULT_PACKED);
2520 goto nowperformreturn;
2522 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2525 REPLACEMENT_POINT_RETURN(cd, iptr);
2526 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2527 M_FLTMOVE(s1, REG_FRESULT);
2528 goto nowperformreturn;
2530 case ICMD_RETURN: /* ... ==> ... */
2532 REPLACEMENT_POINT_RETURN(cd, iptr);
2538 p = cd->stackframesize;
2540 /* call trace function */
2542 #if !defined(NDEBUG)
2543 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2544 emit_verbosecall_exit(jd);
2545 #endif /* !defined(NDEBUG) */
2547 #if defined(ENABLE_THREADS)
2548 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2549 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2550 M_ALD(REG_ITMP3, REG_PV, disp);
2553 /* we need to save the proper return value */
2555 switch (iptr->opc) {
2557 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2561 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2564 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2567 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2571 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2574 /* and now restore the proper return value */
2576 switch (iptr->opc) {
2578 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2582 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2585 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2588 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2594 /* restore return address */
2596 p--; M_ALD(REG_RA, REG_SP, p * 4);
2598 /* restore saved registers */
2600 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2601 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2603 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2604 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2607 /* deallocate stack */
2609 if (cd->stackframesize)
2610 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2617 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);
2633 M_ISUB_IMM(l, REG_ITMP1);
2635 /* number of targets */
2639 M_ICMP_IMM(i - 1, REG_ITMP1);
2642 codegen_add_branch_ref(cd, table[0].block); /* default target */
2644 /* build jump table top down and use address of lowest entry */
2649 dseg_add_target(cd, table->block);
2653 /* length of dataseg after last dseg_add_target is used
2656 M_MOV_IMM(0, REG_ITMP2);
2658 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2665 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2670 lookup_target_t *lookup;
2672 lookup = iptr->dst.lookup;
2674 i = iptr->sx.s23.s2.lookupcount;
2676 MCODECHECK(8 + ((7 + 6) * i) + 5);
2677 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2680 M_ICMP_IMM(lookup->value, s1);
2682 codegen_add_branch_ref(cd, lookup->target.block);
2688 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2694 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2696 bte = iptr->sx.s23.s3.bte;
2700 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2701 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2702 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2703 case ICMD_INVOKEINTERFACE:
2705 REPLACEMENT_POINT_INVOKE(cd, iptr);
2707 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2709 um = iptr->sx.s23.s3.um;
2710 md = um->methodref->parseddesc.md;
2713 lm = iptr->sx.s23.s3.fmiref->p.method;
2715 md = lm->parseddesc;
2719 s3 = md->paramcount;
2721 MCODECHECK((s3 << 1) + 64);
2723 /* copy arguments to registers or stack location */
2725 for (s3 = s3 - 1; s3 >= 0; s3--) {
2726 var = VAR(iptr->sx.s23.s2.args[s3]);
2728 /* Already Preallocated? */
2729 if (var->flags & PREALLOC)
2732 if (IS_INT_LNG_TYPE(var->type)) {
2733 if (!md->params[s3].inmemory) {
2734 if (IS_2_WORD_TYPE(var->type)) {
2736 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2737 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2739 d = emit_load(jd, iptr, var, s1);
2743 s1 = rd->argintregs[md->params[s3].regoff];
2744 d = emit_load(jd, iptr, var, s1);
2749 if (IS_2_WORD_TYPE(var->type)) {
2750 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2751 M_LST(d, REG_SP, md->params[s3].regoff * 4);
2754 d = emit_load(jd, iptr, var, REG_ITMP1);
2755 M_IST(d, REG_SP, md->params[s3].regoff * 4);
2760 if (!md->params[s3].inmemory) {
2761 s1 = rd->argfltregs[md->params[s3].regoff];
2762 d = emit_load(jd, iptr, var, s1);
2766 d = emit_load(jd, iptr, var, REG_FTMP1);
2767 if (IS_2_WORD_TYPE(var->type))
2768 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2770 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2775 switch (iptr->opc) {
2777 disp = dseg_add_functionptr(cd, bte->fp);
2779 N_AHI(REG_SP, -96); /* register save area as required by C abi */
2780 N_LHI(REG_ITMP1, disp);
2781 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2784 case ICMD_INVOKESPECIAL:
2785 emit_nullpointer_check(cd, iptr, REG_A0);
2786 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
2789 case ICMD_INVOKESTATIC:
2791 disp = dseg_add_unique_address(cd, um);
2793 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2797 disp = dseg_add_address(cd, lm->stubroutine);
2799 N_LHI(REG_ITMP1, disp);
2800 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2803 case ICMD_INVOKEVIRTUAL:
2804 emit_nullpointer_check(cd, iptr, REG_A0);
2807 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2812 s1 = OFFSET(vftbl_t, table[0]) +
2813 sizeof(methodptr) * lm->vftblindex;
2816 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2817 M_ALD(REG_PV, REG_METHODPTR, s1);
2820 case ICMD_INVOKEINTERFACE:
2821 emit_nullpointer_check(cd, iptr, REG_A0);
2823 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2824 * and -0xFFF in index register (itmp1)
2827 N_LHI(REG_ITMP1, -N_DISP_MAX);
2830 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2836 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2837 sizeof(methodptr*) * lm->class->index +
2840 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2843 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2844 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
2845 M_ALD(REG_PV, REG_METHODPTR, s2);
2849 /* generate the actual call */
2852 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2853 N_BASR(REG_ITMP1, RN);
2854 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2855 M_LDA(REG_PV, REG_ITMP1, -disp);
2857 /* post call finalization */
2859 if (iptr->opc == ICMD_BUILTIN) {
2860 N_AHI(REG_SP, 96); /* remove C abi register save area */
2863 /* actually only used for ICMD_BUILTIN */
2865 if (INSTRUCTION_MUST_CHECK(iptr)) {
2868 codegen_add_fillinstacktrace_ref(cd);
2871 /* store return value */
2873 d = md->returntype.type;
2875 if (d != TYPE_VOID) {
2876 if (IS_INT_LNG_TYPE(d)) {
2877 if (IS_2_WORD_TYPE(d)) {
2878 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2879 M_LNGMOVE(REG_RESULT_PACKED, s1);
2882 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2883 M_INTMOVE(REG_RESULT, s1);
2887 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2888 M_FLTMOVE(REG_FRESULT, s1);
2890 emit_store_dst(jd, iptr, s1);
2896 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2898 /* val.a: (classinfo*) superclass */
2900 /* superclass is an interface:
2902 * OK if ((sub == NULL) ||
2903 * (sub->vftbl->interfacetablelength > super->index) &&
2904 * (sub->vftbl->interfacetable[-super->index] != NULL));
2906 * superclass is a class:
2908 * OK if ((sub == NULL) || (0
2909 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2910 * super->vftbl->diffval));
2913 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2914 /* object type cast-check */
2917 vftbl_t *supervftbl;
2920 u1 *class_label_refs[] = { 0 }, *class_label;
2921 u1 *exit_label_refs[] = { 0, 0, 0, 0 };
2923 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2929 super = iptr->sx.s23.s3.c.cls;
2930 superindex = super->index;
2931 supervftbl = super->vftbl;
2934 #if defined(ENABLE_THREADS)
2935 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2937 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2939 /* if class is not resolved, check which code to call */
2941 if (super == NULL) {
2943 exit_label_refs[0] = cd->mcodeptr;
2946 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2948 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
2949 iptr->sx.s23.s3.c.ref,
2952 ICONST(REG_ITMP2, ACC_INTERFACE);
2953 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
2954 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
2955 class_label_refs[0] = cd->mcodeptr;
2959 /* interface checkcast code */
2961 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2962 if (super == NULL) {
2963 codegen_add_patch_ref(cd,
2964 PATCHER_checkcast_instanceof_interface,
2965 iptr->sx.s23.s3.c.ref,
2969 exit_label_refs[1] = cd->mcodeptr;
2973 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2974 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2975 M_ISUB_IMM(superindex, REG_ITMP3);
2977 codegen_add_classcastexception_ref(cd, s1);
2980 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2981 superindex * sizeof(methodptr*))
2983 M_ALD(REG_ITMP2, REG_ITMP2, 0);
2986 codegen_add_classcastexception_ref(cd, s1);
2988 if (super == NULL) {
2989 exit_label_refs[2] = cd->mcodeptr;
2994 /* class checkcast code */
2996 class_label = cd->mcodeptr;
2998 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2999 if (super == NULL) {
3000 disp = dseg_add_unique_address(cd, NULL);
3002 codegen_add_patch_ref(cd,
3003 PATCHER_resolve_classref_to_vftbl,
3004 iptr->sx.s23.s3.c.ref,
3008 disp = dseg_add_address(cd, supervftbl);
3010 exit_label_refs[3] = cd->mcodeptr;
3014 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3015 M_ALD(REG_ITMP3, REG_PV, disp);
3016 #if defined(ENABLE_THREADS)
3017 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3019 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3020 /* if (s1 != REG_ITMP1) { */
3021 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3022 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3023 /* #if defined(ENABLE_THREADS) */
3024 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3026 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3029 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3030 M_ISUB(REG_ITMP3, REG_ITMP2);
3031 M_ALD(REG_ITMP3, REG_PV, disp);
3032 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3033 #if defined(ENABLE_THREADS)
3034 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3037 N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3038 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3039 M_BGT(0); /* Branch if greater then */
3040 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3041 codegen_add_classcastexception_ref(cd, s1);
3044 /* resolve labels by adding the correct displacement */
3046 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3047 if (exit_label_refs[s2])
3048 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3051 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3052 if (class_label_refs[s2])
3053 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3056 d = codegen_reg_of_dst(jd, iptr, s1);
3059 /* array type cast-check */
3061 s1 = emit_load_s1(jd, iptr, REG_A0);
3062 M_INTMOVE(s1, REG_A0);
3064 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3065 disp = dseg_add_unique_address(cd, NULL);
3067 codegen_add_patch_ref(cd,
3068 PATCHER_resolve_classref_to_classinfo,
3069 iptr->sx.s23.s3.c.ref,
3073 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3075 M_ALD(REG_A1, REG_PV, disp);
3076 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3077 ICONST(REG_ITMP1, disp); /* TODO negative displacement */
3078 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3079 M_JSR(REG_RA, REG_PV);
3080 N_BASR(REG_ITMP1, RN);
3081 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3082 M_LDA(REG_PV, REG_ITMP1, -disp);
3084 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3087 codegen_add_classcastexception_ref(cd, s1);
3089 d = codegen_reg_of_dst(jd, iptr, s1);
3093 emit_store_dst(jd, iptr, d);
3096 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3097 /* val.a: (classinfo*) superclass */
3099 /* superclass is an interface:
3101 * return (sub != NULL) &&
3102 * (sub->vftbl->interfacetablelength > super->index) &&
3103 * (sub->vftbl->interfacetable[-super->index] != NULL);
3105 * superclass is a class:
3107 * return ((sub != NULL) && (0
3108 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3109 * super->vftbl->diffvall));
3114 vftbl_t *supervftbl;
3117 u1 *class_label, *class_label_refs[1] = { 0 };
3118 u1 *exit_label_refs[4] = { 0, 0, 0, 0 };
3119 u1 *label1, *label1_refs[1] = { 0 };
3121 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3127 super = iptr->sx.s23.s3.c.cls;
3128 superindex = super->index;
3129 supervftbl = super->vftbl;
3132 #if defined(ENABLE_THREADS)
3133 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3135 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3136 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3138 M_MOV(s1, REG_ITMP1);
3142 /* if class is not resolved, check which code to call */
3144 if (super == NULL) {
3148 exit_label_refs[0] = cd->mcodeptr;
3151 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3153 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3154 iptr->sx.s23.s3.c.ref, disp);
3156 ICONST(REG_ITMP2, ACC_INTERFACE);
3157 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3158 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3159 class_label_refs[0] = cd->mcodeptr;
3163 /* interface instanceof code */
3165 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3166 if (super == NULL) {
3167 /* If d == REG_ITMP2, then it's destroyed in check
3172 codegen_add_patch_ref(cd,
3173 PATCHER_checkcast_instanceof_interface,
3174 iptr->sx.s23.s3.c.ref, 0);
3179 exit_label_refs[1] = cd->mcodeptr;
3183 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3184 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3185 M_ISUB_IMM(superindex, REG_ITMP3);
3186 label1_refs[0] = cd->mcodeptr;
3190 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3191 superindex * sizeof(methodptr*))
3193 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3195 /* d := (REG_ITMP1 != 0) */
3197 N_LTR(d, REG_ITMP1);
3198 M_BEQ(SZ_BRC + SZ_LHI);
3201 label1 = cd->mcodeptr;
3203 if (super == NULL) {
3204 exit_label_refs[2] = cd->mcodeptr;
3209 /* class instanceof code */
3211 class_label = cd->mcodeptr;
3213 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3214 if (super == NULL) {
3215 disp = dseg_add_unique_address(cd, NULL);
3217 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3218 iptr->sx.s23.s3.c.ref,
3222 disp = dseg_add_address(cd, supervftbl);
3227 exit_label_refs[3] = cd->mcodeptr;
3231 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3232 M_ALD(REG_ITMP2, REG_PV, disp);
3233 #if defined(ENABLE_THREADS)
3234 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3236 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3237 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3238 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3239 #if defined(ENABLE_THREADS)
3240 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3242 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3244 N_CLR(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3246 M_BGT(SZ_BRC + SZ_LHI);
3250 /* resolve labels by adding the correct displacement */
3252 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3253 if (exit_label_refs[s2])
3254 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3257 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3258 if (class_label_refs[s2])
3259 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3262 for (s2 = 0; s2 < sizeof(label1_refs) / sizeof(label1_refs[0]); ++s2) {
3263 if (label1_refs[s2])
3264 *(u4 *)label1_refs[s2] |= (u4)(label1 - label1_refs[s2]) / 2;
3267 emit_store_dst(jd, iptr, d);
3273 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3277 /* check for negative sizes and copy sizes to stack if necessary */
3279 MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3281 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3283 /* copy SAVEDVAR sizes to stack */
3284 var = VAR(iptr->sx.s23.s2.args[s1]);
3286 /* Already Preallocated? */
3287 if (!(var->flags & PREALLOC)) {
3288 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3289 M_LST(s2, REG_SP, s1 * 8);
3293 /* is a patcher function set? */
3295 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3296 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
3297 iptr->sx.s23.s3.c.ref, 0);
3300 /* a0 = dimension count */
3302 M_MOV_IMM(iptr->s1.argcount, REG_A0);
3304 /* a1 = classinfo */
3306 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3308 /* a2 = pointer to dimensions = stack pointer */
3310 M_MOV(REG_SP, REG_A2);
3312 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3315 /* check for exception before result assignment */
3319 codegen_add_fillinstacktrace_ref(cd);
3321 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3322 M_INTMOVE(REG_RESULT, s1);
3323 emit_store_dst(jd, iptr, s1);
3328 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3332 } /* for instruction */
3334 MCODECHECK(512); /* XXX require a lower number? */
3336 /* At the end of a basic block we may have to append some nops,
3337 because the patcher stub calling code might be longer than the
3338 actual instruction. So codepatching does not change the
3339 following block unintentionally. */
3341 if (cd->mcodeptr < cd->lastmcodeptr) {
3342 while (cd->mcodeptr < cd->lastmcodeptr) {
3347 } /* if (bptr -> flags >= BBREACHED) */
3348 } /* for basic block */
3350 dseg_createlinenumbertable(cd);
3352 /* generate stubs */
3354 emit_exception_stubs(jd);
3355 emit_patcher_stubs(jd);
3357 emit_replacement_stubs(jd);
3362 /* everything's ok */
3368 /* createcompilerstub **********************************************************
3370 Creates a stub routine which calls the compiler.
3372 *******************************************************************************/
3374 #define COMPILERSTUB_DATASIZE (3 * SIZEOF_VOID_P)
3375 #define COMPILERSTUB_CODESIZE (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
3377 #define COMPILERSTUB_SIZE (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE)
3380 u1 *createcompilerstub(methodinfo *m)
3382 u1 *s; /* memory to hold the stub */
3388 s = CNEW(u1, COMPILERSTUB_SIZE);
3390 /* set data pointer and code pointer */
3393 s = s + COMPILERSTUB_DATASIZE;
3395 /* mark start of dump memory area */
3397 dumpsize = dump_size();
3399 cd = DNEW(codegendata);
3402 /* Store the codeinfo pointer in the same place as in the
3403 methodheader for compiled methods. */
3405 code = code_codeinfo_new(m);
3407 d[0] = (ptrint) asm_call_jit_compiler;
3409 d[2] = (ptrint) code;
3411 /* code for the stub */
3413 /* don't touch ITMP3 as it cointains the return address */
3415 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3417 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3418 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3419 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3422 #if defined(ENABLE_STATISTICS)
3424 count_cstub_len += COMPILERSTUB_SIZE;
3427 /* release dump area */
3429 dump_release(dumpsize);
3435 /* createnativestub ************************************************************
3437 Creates a stub routine which calls a native method.
3439 *******************************************************************************/
3442 arguments on stack \
3443 -------------------------------------------------| <- SP on nativestub entry
3445 callee saved int regs (none) |
3446 callee saved float regs (none) | stack frame like in cacao
3447 local variable slots (none) |
3448 arguments for calling methods (none) /
3449 ------------------------------------------------------------------ <- datasp
3454 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3455 0 - 96 register save area for callee /
3456 -------------------------------------------------------- <- SP native method
3458 SP after method entry
3461 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3469 s4 i, j; /* count variables */
3474 /* get required compiler data */
3481 /* initialize variables */
3484 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3486 /* calculate stack frame size */
3488 cd->stackframesize =
3489 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3490 sizeof(localref_table) / SIZEOF_VOID_P +
3491 INT_ARG_CNT + FLT_ARG_CNT +
3492 1 + /* functionptr, TODO: store in data segment */
3495 cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */
3498 cd->stackframesize =
3499 1 + /* r14 - return address */ +
3500 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3501 sizeof(localref_table) / SIZEOF_VOID_P +
3503 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3504 nmd->memuse + /* parameter passing */
3505 96 / SIZEOF_VOID_P /* required by ABI */;
3507 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3510 /* create method header */
3512 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3513 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3514 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3515 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3516 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3517 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3518 (void) dseg_addlinenumbertablesize(cd);
3519 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3521 /* generate native method profiling code */
3523 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3524 /* count frequency */
3526 M_MOV_IMM(code, REG_ITMP3);
3527 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3531 /* generate stub code */
3533 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3535 /* save return address */
3537 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3540 #if !defined(NDEBUG)
3541 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3542 emit_verbosecall_enter(jd);
3546 /* get function address (this must happen before the stackframeinfo) */
3548 disp = dseg_add_functionptr(cd, f);
3550 #if !defined(WITH_STATIC_CLASSPATH)
3552 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3555 M_ILD(REG_ITMP1, REG_PV, disp);
3557 j = 96 + (nmd->memuse * 4);
3559 /* todo some arg registers are not volatile in C-abi terms */
3561 /* save integer and float argument registers */
3563 for (i = 0; i < md->paramcount; i++) {
3564 if (! md->params[i].inmemory) {
3565 s1 = md->params[i].regoff;
3567 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3568 if (IS_2_WORD_TYPE(t)) {
3569 /* todo store multiple */
3570 N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3571 N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3573 N_ST(rd->argintregs[s1], j, RN, REG_SP);
3576 if (IS_2_WORD_TYPE(t)) {
3577 N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3579 N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3587 N_ST(REG_ITMP1, j, RN, REG_SP);
3589 /* create dynamic stack info */
3591 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3592 N_LR(REG_A1, REG_PV); /* pv */
3593 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3594 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3596 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3597 M_ILD(REG_ITMP1, REG_PV, disp);
3599 M_CALL(REG_ITMP1); /* call */
3601 /* restore integer and float argument registers */
3603 j = 96 + (nmd->memuse * 4);
3605 for (i = 0; i < md->paramcount; i++) {
3606 if (! md->params[i].inmemory) {
3607 s1 = md->params[i].regoff;
3609 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3610 if (IS_2_WORD_TYPE(t)) {
3611 /* todo load multiple ! */
3612 N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3613 N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3615 N_L(rd->argintregs[s1], j, RN, REG_SP);
3618 if (IS_2_WORD_TYPE(t)) {
3619 N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3621 N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3629 N_L(REG_ITMP1, j, RN, REG_SP);
3631 /* copy or spill arguments to new locations */
3633 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3634 t = md->paramtypes[i].type;
3636 if (IS_INT_LNG_TYPE(t)) {
3638 if (!md->params[i].inmemory) {
3640 s1 = rd->argintregs[md->params[i].regoff];
3642 if (!nmd->params[j].inmemory) {
3643 s2 = rd->argintregs[nmd->params[j].regoff];
3644 if (IS_2_WORD_TYPE(t)) {
3645 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3646 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3651 s2 = nmd->params[j].regoff;
3652 if (IS_2_WORD_TYPE(t)) {
3653 N_STM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3655 N_ST(s1, 96 + (s2 * 4), RN, REG_SP);
3660 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3661 s2 = nmd->params[j].regoff;
3663 if (IS_2_WORD_TYPE(t)) {
3664 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3666 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3671 /* We only copy spilled float arguments, as the float argument */
3672 /* registers keep unchanged. */
3674 if (md->params[i].inmemory) {
3675 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3676 s2 = nmd->params[j].regoff;
3678 if (IS_2_WORD_TYPE(t)) {
3679 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3681 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3687 /* put class into second argument register */
3689 if (m->flags & ACC_STATIC) {
3690 disp = dseg_add_address(cd, m->class);
3691 M_ILD(REG_A1, REG_PV, disp);
3694 /* put env into first argument register */
3696 disp = dseg_add_address(cd, _Jv_env);
3697 M_ILD(REG_A0, REG_PV, disp);
3699 /* do the native function call */
3701 M_CALL(REG_ITMP1); /* call */
3703 /* save return value */
3705 t = md->returntype.type;
3707 if (t != TYPE_VOID) {
3708 if (IS_INT_LNG_TYPE(t)) {
3709 if (IS_2_WORD_TYPE(t)) {
3710 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3712 N_ST(REG_RESULT, 96, RN, REG_SP);
3715 if (IS_2_WORD_TYPE(t)) {
3716 N_STD(REG_FRESULT, 96, RN, REG_SP);
3718 N_STE(REG_FRESULT, 96, RN, REG_SP);
3724 #if !defined(NDEBUG)
3725 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3726 emit_verbosecall_exit(jd);
3730 /* remove native stackframe info */
3732 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3733 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3734 M_ILD(REG_ITMP1, REG_PV, disp);
3736 N_LR(REG_ITMP3, REG_RESULT);
3738 /* restore return value */
3740 if (t != TYPE_VOID) {
3741 if (IS_INT_LNG_TYPE(t)) {
3742 if (IS_2_WORD_TYPE(t)) {
3743 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3745 N_L(REG_RESULT, 96, RN, REG_SP);
3748 if (IS_2_WORD_TYPE(t)) {
3749 N_LD(REG_FRESULT, 96, RN, REG_SP);
3751 N_LE(REG_FRESULT, 96, RN, REG_SP);
3756 /* load return address */
3758 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3760 /* remove stackframe */
3762 N_AHI(REG_SP, cd->stackframesize * 4);
3764 /* test for exception */
3766 N_LTR(REG_ITMP3, REG_ITMP3);
3767 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3771 N_BCR(DD_ANY, REG_ITMP2);
3773 /* handle exception */
3775 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3776 M_ALD(REG_ITMP2_XPC, REG_SP, (cd->stackframesize - 1) * 4); /* get return address from stack */
3779 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3781 disp = dseg_add_functionptr(cd, /*asm_handle_nat_exception*/ panic);
3783 M_ALD(REG_ITMP3, REG_PV, disp);
3784 M_JMP(RN, REG_ITMP3);
3786 /* generate patcher stubs */
3788 emit_patcher_stubs(jd);
3792 return code->entrypoint;
3796 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3797 codegendata *cd = jd->cd;
3798 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3800 M_MOV(reg, tempregnum);
3808 * These are local overrides for various environment variables in Emacs.
3809 * Please do not remove this and leave it at the end of the file, where
3810 * Emacs will automagically detect them.
3811 * ---------------------------------------------------------------------
3814 * indent-tabs-mode: t
3818 * vim:noexpandtab:sw=4:ts=4: