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
30 Changes: Christian Ullrich
33 $Id: codegen.c 5587 2006-09-30 10:16:48Z christian $
48 #include "vm/jit/x86_64/arch.h"
49 #include "vm/jit/x86_64/codegen.h"
50 #include "vm/jit/x86_64/emit.h"
52 #include "mm/memory.h"
53 #include "native/jni.h"
54 #include "native/native.h"
56 #if defined(ENABLE_THREADS)
57 # include "threads/native/lock.h"
60 #include "vm/builtin.h"
61 #include "vm/exceptions.h"
62 #include "vm/global.h"
63 #include "vm/loader.h"
64 #include "vm/options.h"
65 #include "vm/statistics.h"
66 #include "vm/stringlocal.h"
68 #include "vm/jit/asmpart.h"
69 #include "vm/jit/codegen-common.h"
70 #include "vm/jit/dseg.h"
71 #include "vm/jit/emit-common.h"
72 #include "vm/jit/jit.h"
73 #include "vm/jit/methodheader.h"
74 #include "vm/jit/parse.h"
75 #include "vm/jit/patcher.h"
76 #include "vm/jit/reg.h"
77 #include "vm/jit/replace.h"
79 #if defined(ENABLE_LSRA)
80 # include "vm/jit/allocator/lsra.h"
84 /* codegen *********************************************************************
86 Generates machine code.
88 *******************************************************************************/
90 bool codegen(jitdata *jd)
96 s4 len, s1, s2, s3, d, disp;
100 varinfo *var, *var1, *var2, *dst;
104 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
105 unresolved_method *um;
106 builtintable_entry *bte;
108 rplpoint *replacementpoint;
111 /* get required compiler data */
118 /* prevent compiler warnings */
130 /* space to save used callee saved registers */
132 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
133 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
135 cd->stackframesize = rd->memuse + savedregs_num;
137 #if defined(ENABLE_THREADS)
138 /* space to save argument of monitor_enter */
140 if (checksync && (m->flags & ACC_SYNCHRONIZED))
141 cd->stackframesize++;
144 /* Keep stack of non-leaf functions 16-byte aligned for calls into
145 native code e.g. libc or jni (alignment problems with
148 if (!jd->isleafmethod || opt_verbosecall)
149 cd->stackframesize |= 0x1;
151 /* create method header */
153 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
154 (void) dseg_adds4(cd, cd->stackframesize * 8); /* FrameSize */
156 #if defined(ENABLE_THREADS)
157 /* IsSync contains the offset relative to the stack pointer for the
158 argument of monitor_exit used in the exception handler. Since the
159 offset could be zero and give a wrong meaning of the flag it is
163 if (checksync && (m->flags & ACC_SYNCHRONIZED))
164 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
167 (void) dseg_adds4(cd, 0); /* IsSync */
169 (void) dseg_adds4(cd, jd->isleafmethod); /* IsLeaf */
170 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
171 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
173 (void) dseg_addlinenumbertablesize(cd);
175 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
177 /* create exception table */
179 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
180 dseg_addtarget(cd, ex->start);
181 dseg_addtarget(cd, ex->end);
182 dseg_addtarget(cd, ex->handler);
183 (void) dseg_addaddress(cd, ex->catchtype.any);
186 /* generate method profiling code */
188 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
189 /* count frequency */
191 M_MOV_IMM(code, REG_ITMP3);
192 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
197 /* create stack frame (if necessary) */
199 if (cd->stackframesize)
200 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
202 /* save used callee saved registers */
204 p = cd->stackframesize;
205 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
206 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
208 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
209 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
212 /* take arguments out of register or stack frame */
216 for (p = 0, l = 0; p < md->paramcount; p++) {
217 t = md->paramtypes[p].type;
219 varindex = jd->local_map[l * 5 + t];
222 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
225 if (varindex == UNUSED)
230 s1 = md->params[p].regoff;
232 if (IS_INT_LNG_TYPE(t)) { /* integer args */
233 s2 = rd->argintregs[s1];
234 if (!md->params[p].inmemory) { /* register arguments */
235 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
236 M_INTMOVE(s2, var->vv.regoff);
238 } else { /* reg arg -> spilled */
239 M_LST(s2, REG_SP, var->vv.regoff * 8);
242 } else { /* stack arguments */
243 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
244 /* + 8 for return address */
245 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 8 + 8);
247 } else { /* stack arg -> spilled */
248 var->vv.regoff = cd->stackframesize + s1 + 1;
252 } else { /* floating args */
253 if (!md->params[p].inmemory) { /* register arguments */
254 s2 = rd->argfltregs[s1];
255 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
256 M_FLTMOVE(s2, var->vv.regoff);
258 } else { /* reg arg -> spilled */
259 M_DST(s2, REG_SP, var->vv.regoff * 8);
262 } else { /* stack arguments */
263 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
264 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 8 + 8);
267 var->vv.regoff = cd->stackframesize + s1 + 1;
273 /* save monitorenter argument */
275 #if defined(ENABLE_THREADS)
276 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
277 /* stack offset for monitor argument */
281 if (opt_verbosecall) {
282 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
284 for (p = 0; p < INT_ARG_CNT; p++)
285 M_LST(rd->argintregs[p], REG_SP, p * 8);
287 for (p = 0; p < FLT_ARG_CNT; p++)
288 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
290 s1 += INT_ARG_CNT + FLT_ARG_CNT;
293 /* decide which monitor enter function to call */
295 if (m->flags & ACC_STATIC) {
296 M_MOV_IMM(&m->class->object.header, REG_A0);
301 codegen_add_nullpointerexception_ref(cd);
304 M_AST(REG_A0, REG_SP, s1 * 8);
305 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
308 if (opt_verbosecall) {
309 for (p = 0; p < INT_ARG_CNT; p++)
310 M_LLD(rd->argintregs[p], REG_SP, p * 8);
312 for (p = 0; p < FLT_ARG_CNT; p++)
313 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
315 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
321 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
322 emit_verbosecall_enter(jd);
323 #endif /* !defined(NDEBUG) */
327 /* end of header generation */
329 replacementpoint = jd->code->rplpoints;
331 /* walk through all basic blocks */
333 for (bptr = jd->new_basicblocks; bptr != NULL; bptr = bptr->next) {
335 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
337 if (bptr->flags >= BBREACHED) {
339 /* branch resolving */
342 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
343 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
348 /* handle replacement points */
351 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
352 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
356 assert(cd->lastmcodeptr <= cd->mcodeptr);
357 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
361 /* copy interface registers to their destination */
366 /* generate basicblock profiling code */
368 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
369 /* count frequency */
371 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
372 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
374 /* if this is an exception handler, start profiling again */
376 if (bptr->type == BBTYPE_EXH)
380 #if defined(ENABLE_LSRA)
384 src = bptr->invars[len];
385 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
386 if (bptr->type == BBTYPE_SBR) {
387 /* d = reg_of_var(rd, src, REG_ITMP1); */
388 if (!IS_INMEMORY(src->flags))
393 emit_store(jd, NULL, src, d);
395 } else if (bptr->type == BBTYPE_EXH) {
396 /* d = reg_of_var(rd, src, REG_ITMP1); */
397 if (!IS_INMEMORY(src->flags))
401 M_INTMOVE(REG_ITMP1, d);
402 emit_store(jd, NULL, src, d);
412 varindex = bptr->invars[len];
414 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
415 if (bptr->type == BBTYPE_SBR) {
416 d = codegen_reg_of_var(0, var, REG_ITMP1);
418 emit_store(jd, NULL, var, d);
421 else if (bptr->type == BBTYPE_EXH) {
422 d = codegen_reg_of_var(0, var, REG_ITMP1);
423 M_INTMOVE(REG_ITMP1, d);
424 emit_store(jd, NULL, var, d);
428 assert((var->flags & OUTVAR));
429 d = codegen_reg_of_var(0, var, REG_ITMP1);
432 #if defined(ENABLE_LSRA)
435 /* walk through all instructions */
440 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
441 if (iptr->line != currentline) {
442 dseg_addlinenumber(cd, iptr->line);
443 currentline = iptr->line;
446 MCODECHECK(1024); /* 1KB should be enough */
449 case ICMD_INLINE_START: /* internal ICMDs */
450 case ICMD_INLINE_END:
453 case ICMD_NOP: /* ... ==> ... */
456 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
458 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
461 codegen_add_nullpointerexception_ref(cd);
464 /* constant operations ************************************************/
466 case ICMD_ICONST: /* ... ==> ..., constant */
468 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
469 ICONST(d, iptr->sx.val.i);
470 emit_store_dst(jd, iptr, d);
473 case ICMD_LCONST: /* ... ==> ..., constant */
475 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
476 LCONST(d, iptr->sx.val.l);
477 emit_store_dst(jd, iptr, d);
480 case ICMD_FCONST: /* ... ==> ..., constant */
482 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
483 disp = dseg_addfloat(cd, iptr->sx.val.f);
484 emit_movdl_membase_reg(cd, RIP, -((cd->mcodeptr + ((d > 7) ? 9 : 8)) - cd->mcodebase) + disp, d);
485 emit_store_dst(jd, iptr, d);
488 case ICMD_DCONST: /* ... ==> ..., constant */
490 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
491 disp = dseg_adddouble(cd, iptr->sx.val.d);
492 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, d);
493 emit_store_dst(jd, iptr, d);
496 case ICMD_ACONST: /* ... ==> ..., constant */
498 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
500 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
501 /* PROFILE_CYCLE_STOP; */
503 codegen_addpatchref(cd, PATCHER_aconst,
504 iptr->sx.val.c.ref, 0);
506 if (opt_showdisassemble) {
507 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
510 /* PROFILE_CYCLE_START; */
515 if (iptr->sx.val.anyptr == 0)
518 M_MOV_IMM(iptr->sx.val.anyptr, d);
520 emit_store_dst(jd, iptr, d);
524 /* load/store operations **********************************************/
526 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
527 case ICMD_ALOAD: /* s1 = local variable */
531 case ICMD_ISTORE: /* ..., value ==> ... */
532 case ICMD_ASTORE: /* dst = local variable */
537 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
540 /* pop/copy/move operations *******************************************/
542 /* attention: double and longs are only one entry in CACAO ICMDs */
544 case ICMD_POP: /* ..., value ==> ... */
545 case ICMD_POP2: /* ..., value, value ==> ... */
552 M_COPY(iptr->s1.varindex, iptr->dst.varindex);
555 /* integer operations *************************************************/
557 case ICMD_INEG: /* ..., value ==> ..., - value */
559 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
560 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
563 emit_store_dst(jd, iptr, d);
566 case ICMD_LNEG: /* ..., value ==> ..., - value */
568 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
569 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
572 emit_store_dst(jd, iptr, d);
575 case ICMD_I2L: /* ..., value ==> ..., value */
577 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
578 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
580 emit_store_dst(jd, iptr, d);
583 case ICMD_L2I: /* ..., value ==> ..., value */
585 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
586 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
588 emit_store_dst(jd, iptr, d);
591 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
593 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
594 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
596 emit_store_dst(jd, iptr, d);
599 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
601 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
602 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
604 emit_store_dst(jd, iptr, d);
607 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
609 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
610 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
612 emit_store_dst(jd, iptr, d);
616 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
618 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
619 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
620 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
627 emit_store_dst(jd, iptr, d);
630 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
631 /* sx.val.i = constant */
633 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
634 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
636 M_IADD_IMM(iptr->sx.val.i, d);
637 emit_store_dst(jd, iptr, d);
640 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
642 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
643 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
644 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
651 emit_store_dst(jd, iptr, d);
654 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
655 /* sx.val.l = constant */
657 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
658 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
660 if (IS_IMM32(iptr->sx.val.l))
661 M_LADD_IMM(iptr->sx.val.l, d);
663 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
664 M_LADD(REG_ITMP2, d);
666 emit_store_dst(jd, iptr, d);
669 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
671 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
672 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
673 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
675 M_INTMOVE(s1, REG_ITMP1);
676 M_ISUB(s2, REG_ITMP1);
677 M_INTMOVE(REG_ITMP1, d);
682 emit_store_dst(jd, iptr, d);
685 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
686 /* sx.val.i = constant */
688 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
689 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
691 M_ISUB_IMM(iptr->sx.val.i, d);
692 emit_store_dst(jd, iptr, d);
695 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
697 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
698 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
699 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
701 M_INTMOVE(s1, REG_ITMP1);
702 M_LSUB(s2, REG_ITMP1);
703 M_INTMOVE(REG_ITMP1, d);
708 emit_store_dst(jd, iptr, d);
711 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
712 /* sx.val.l = constant */
714 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
715 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
717 if (IS_IMM32(iptr->sx.val.l))
718 M_LSUB_IMM(iptr->sx.val.l, d);
720 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
721 M_LSUB(REG_ITMP2, d);
723 emit_store_dst(jd, iptr, d);
726 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
728 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
729 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
730 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
737 emit_store_dst(jd, iptr, d);
740 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
741 /* sx.val.i = constant */
743 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
744 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
745 if (iptr->sx.val.i == 2) {
749 M_IMUL_IMM(s1, iptr->sx.val.i, d);
750 emit_store_dst(jd, iptr, d);
753 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
755 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
756 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
757 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
764 emit_store_dst(jd, iptr, d);
767 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
768 /* sx.val.l = constant */
770 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
771 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
772 if (IS_IMM32(iptr->sx.val.l))
773 M_LMUL_IMM(s1, iptr->sx.val.l, d);
775 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
777 M_LMUL(REG_ITMP2, d);
779 emit_store_dst(jd, iptr, d);
782 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
784 var1 = VAROP(iptr->s1);
785 var2 = VAROP(iptr->sx.s23.s2);
786 dst = VAROP(iptr->dst);
788 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
789 if (IS_INMEMORY(var1->flags))
790 M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
792 M_INTMOVE(var1->vv.regoff, RAX);
794 if (IS_INMEMORY(var2->flags))
795 M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
797 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
802 codegen_add_arithmeticexception_ref(cd);
805 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
806 emit_jcc(cd, CC_NE, 4 + 6);
807 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
808 emit_jcc(cd, CC_E, 3 + 1 + 3); /* 6 bytes */
810 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
812 emit_idivl_reg(cd, REG_ITMP3);
814 if (IS_INMEMORY(dst->flags)) {
815 emit_mov_reg_membase(cd, RAX, REG_SP, dst->vv.regoff * 8);
816 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
819 M_INTMOVE(RAX, dst->vv.regoff);
821 if (dst->vv.regoff != RDX) {
822 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
827 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
829 var1 = VAROP(iptr->s1);
830 var2 = VAROP(iptr->sx.s23.s2);
831 dst = VAROP(iptr->dst);
833 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
834 if (IS_INMEMORY(var1->flags))
835 M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
837 M_INTMOVE(var1->vv.regoff, RAX);
839 if (IS_INMEMORY(var2->flags))
840 M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
842 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
847 codegen_add_arithmeticexception_ref(cd);
850 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
852 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
853 emit_jcc(cd, CC_NE, 2 + 4 + 6);
856 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
857 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
858 emit_jcc(cd, CC_E, 1 + 3); /* 6 bytes */
861 emit_idivl_reg(cd, REG_ITMP3);
863 if (IS_INMEMORY(dst->flags)) {
864 emit_mov_reg_membase(cd, RDX, REG_SP, dst->vv.regoff * 8);
865 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
868 M_INTMOVE(RDX, dst->vv.regoff);
870 if (dst->vv.regoff != RDX) {
871 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
876 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
877 /* sx.val.i = constant */
879 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
880 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
881 M_INTMOVE(s1, REG_ITMP1);
882 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
883 emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
884 emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
885 emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
886 emit_mov_reg_reg(cd, REG_ITMP1, d);
887 emit_store_dst(jd, iptr, d);
890 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
891 /* sx.val.i = constant */
893 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
894 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
895 M_INTMOVE(s1, REG_ITMP1);
896 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
897 emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
898 emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
899 emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
900 emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
901 emit_mov_reg_reg(cd, REG_ITMP1, d);
902 emit_store_dst(jd, iptr, d);
906 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
908 var1 = VAROP(iptr->s1);
909 var2 = VAROP(iptr->sx.s23.s2);
910 dst = VAROP(iptr->dst);
912 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
914 if (IS_INMEMORY(var1->flags))
915 M_LLD(RAX, REG_SP, var1->vv.regoff * 8);
917 M_INTMOVE(var1->vv.regoff, RAX);
919 if (IS_INMEMORY(var2->flags))
920 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
922 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
927 codegen_add_arithmeticexception_ref(cd);
930 /* check as described in jvm spec */
931 disp = dseg_adds8(cd, 0x8000000000000000LL);
932 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX);
934 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
935 M_BEQ(3 + 2 + 3); /* 6 bytes */
937 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
939 emit_idiv_reg(cd, REG_ITMP3);
941 if (IS_INMEMORY(dst->flags)) {
942 M_LST(RAX, REG_SP, dst->vv.regoff * 8);
943 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
946 M_INTMOVE(RAX, dst->vv.regoff);
948 if (dst->vv.regoff != RDX) {
949 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
954 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
956 var1 = VAROP(iptr->s1);
957 var2 = VAROP(iptr->sx.s23.s2);
958 dst = VAROP(iptr->dst);
960 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
962 if (IS_INMEMORY(var1->flags))
963 M_LLD(REG_ITMP1, REG_SP, var1->vv.regoff * 8);
965 M_INTMOVE(var1->vv.regoff, REG_ITMP1);
967 if (IS_INMEMORY(var2->flags))
968 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
970 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
972 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
973 M_INTMOVE(s1, REG_ITMP1);
974 s2 = emit_load_s2(jd, iptr, REG_ITMP3);
975 M_INTMOVE(s2, REG_ITMP3);
980 codegen_add_arithmeticexception_ref(cd);
983 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
985 /* check as described in jvm spec */
986 disp = dseg_adds8(cd, 0x8000000000000000LL);
987 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1);
991 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
993 M_LXOR(RDX, RDX); /* 3 bytes */
994 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
995 M_BEQ(2 + 3); /* 6 bytes */
998 emit_idiv_reg(cd, REG_ITMP3);
1000 if (IS_INMEMORY(dst->flags)) {
1001 M_LST(RDX, REG_SP, dst->vv.regoff * 8);
1002 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1005 M_INTMOVE(RDX, dst->vv.regoff);
1007 if (dst->vv.regoff != RDX) {
1008 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1013 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1014 /* sx.val.i = constant */
1016 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1017 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1018 M_INTMOVE(s1, REG_ITMP1);
1019 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1020 emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
1021 emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
1022 emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
1023 emit_mov_reg_reg(cd, REG_ITMP1, d);
1024 emit_store_dst(jd, iptr, d);
1027 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1028 /* sx.val.l = constant */
1030 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1031 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1032 M_INTMOVE(s1, REG_ITMP1);
1033 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1034 emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
1035 emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1036 emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
1037 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1038 emit_mov_reg_reg(cd, REG_ITMP1, d);
1039 emit_store_dst(jd, iptr, d);
1042 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1044 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1045 emit_ishift(jd, SHIFT_SHL, iptr);
1048 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1049 /* sx.val.i = constant */
1051 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1052 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1054 M_ISLL_IMM(iptr->sx.val.i, d);
1055 emit_store_dst(jd, iptr, d);
1058 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1060 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1061 emit_ishift(jd, SHIFT_SAR, iptr);
1064 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1065 /* sx.val.i = constant */
1067 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1068 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1070 M_ISRA_IMM(iptr->sx.val.i, d);
1071 emit_store_dst(jd, iptr, d);
1074 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1076 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1077 emit_ishift(jd, SHIFT_SHR, iptr);
1080 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1081 /* sx.val.i = constant */
1083 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1084 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1086 M_ISRL_IMM(iptr->sx.val.i, d);
1087 emit_store_dst(jd, iptr, d);
1090 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1092 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1093 emit_lshift(jd, SHIFT_SHL, iptr);
1096 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1097 /* sx.val.i = constant */
1099 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1100 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1102 M_LSLL_IMM(iptr->sx.val.i, d);
1103 emit_store_dst(jd, iptr, d);
1106 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1108 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1109 emit_lshift(jd, SHIFT_SAR, iptr);
1112 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1113 /* sx.val.i = constant */
1115 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1116 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1118 M_LSRA_IMM(iptr->sx.val.i, d);
1119 emit_store_dst(jd, iptr, d);
1122 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1124 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1125 emit_lshift(jd, SHIFT_SHR, iptr);
1128 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1129 /* sx.val.l = constant */
1131 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1132 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1134 M_LSRL_IMM(iptr->sx.val.i, d);
1135 emit_store_dst(jd, iptr, d);
1138 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1140 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1141 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1142 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1149 emit_store_dst(jd, iptr, d);
1152 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1153 /* sx.val.i = constant */
1155 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1156 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1158 M_IAND_IMM(iptr->sx.val.i, d);
1159 emit_store_dst(jd, iptr, d);
1162 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1164 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1165 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1166 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1173 emit_store_dst(jd, iptr, d);
1176 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1177 /* sx.val.l = constant */
1179 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1180 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1182 if (IS_IMM32(iptr->sx.val.l))
1183 M_LAND_IMM(iptr->sx.val.l, d);
1185 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1186 M_LAND(REG_ITMP2, d);
1188 emit_store_dst(jd, iptr, d);
1191 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1193 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1194 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1195 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1202 emit_store_dst(jd, iptr, d);
1205 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1206 /* sx.val.i = constant */
1208 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1209 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1211 M_IOR_IMM(iptr->sx.val.i, d);
1212 emit_store_dst(jd, iptr, d);
1215 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1217 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1218 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1219 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1226 emit_store_dst(jd, iptr, d);
1229 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1230 /* sx.val.l = constant */
1232 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1233 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1235 if (IS_IMM32(iptr->sx.val.l))
1236 M_LOR_IMM(iptr->sx.val.l, d);
1238 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1239 M_LOR(REG_ITMP2, d);
1241 emit_store_dst(jd, iptr, d);
1244 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1246 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1247 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1248 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1255 emit_store_dst(jd, iptr, d);
1258 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1259 /* sx.val.i = constant */
1261 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1262 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1264 M_IXOR_IMM(iptr->sx.val.i, d);
1265 emit_store_dst(jd, iptr, d);
1268 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1270 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1271 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1272 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1279 emit_store_dst(jd, iptr, d);
1282 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1283 /* sx.val.l = constant */
1285 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1286 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1288 if (IS_IMM32(iptr->sx.val.l))
1289 M_LXOR_IMM(iptr->sx.val.l, d);
1291 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1292 M_LXOR(REG_ITMP2, d);
1294 emit_store_dst(jd, iptr, d);
1298 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1299 /* s1.localindex = variable, sx.val.i = constant */
1301 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1302 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1304 /* Using inc and dec is not faster than add (tested with
1308 M_IADD_IMM(iptr->sx.val.i, d);
1310 emit_store_dst(jd, iptr, d);
1314 /* floating operations ************************************************/
1316 case ICMD_FNEG: /* ..., value ==> ..., - value */
1318 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1319 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1320 disp = dseg_adds4(cd, 0x80000000);
1322 emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1323 emit_xorps_reg_reg(cd, REG_FTMP2, d);
1324 emit_store_dst(jd, iptr, d);
1327 case ICMD_DNEG: /* ..., value ==> ..., - value */
1329 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1330 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1331 disp = dseg_adds8(cd, 0x8000000000000000);
1333 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1334 emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1335 emit_store_dst(jd, iptr, d);
1338 case ICMD_FADD: /* ..., 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_FTMP3);
1349 emit_store_dst(jd, iptr, d);
1352 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1354 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1355 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1356 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1363 emit_store_dst(jd, iptr, d);
1366 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1368 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1369 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1370 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1372 M_FLTMOVE(s2, REG_FTMP2);
1377 emit_store_dst(jd, iptr, d);
1380 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1382 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1383 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1384 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1386 M_FLTMOVE(s2, REG_FTMP2);
1391 emit_store_dst(jd, iptr, d);
1394 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1396 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1397 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1398 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1405 emit_store_dst(jd, iptr, d);
1408 case ICMD_DMUL: /* ..., 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_FTMP3);
1419 emit_store_dst(jd, iptr, d);
1422 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1424 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1425 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1426 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1428 M_FLTMOVE(s2, REG_FTMP2);
1433 emit_store_dst(jd, iptr, d);
1436 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1438 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1439 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1440 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1442 M_FLTMOVE(s2, REG_FTMP2);
1447 emit_store_dst(jd, iptr, d);
1450 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1452 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1453 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1455 emit_store_dst(jd, iptr, d);
1458 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1460 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1461 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1463 emit_store_dst(jd, iptr, d);
1466 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1468 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1469 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1471 emit_store_dst(jd, iptr, d);
1474 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1476 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1477 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1479 emit_store_dst(jd, iptr, d);
1482 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1484 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1485 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1487 M_ICMP_IMM(0x80000000, d); /* corner cases */
1488 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1489 ((REG_RESULT == d) ? 0 : 3);
1491 M_FLTMOVE(s1, REG_FTMP1);
1492 M_MOV_IMM(asm_builtin_f2i, REG_ITMP2);
1494 M_INTMOVE(REG_RESULT, d);
1495 emit_store_dst(jd, iptr, d);
1498 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1500 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1501 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1503 M_ICMP_IMM(0x80000000, d); /* corner cases */
1504 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1505 ((REG_RESULT == d) ? 0 : 3);
1507 M_FLTMOVE(s1, REG_FTMP1);
1508 M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1510 M_INTMOVE(REG_RESULT, d);
1511 emit_store_dst(jd, iptr, d);
1514 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1516 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1517 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1519 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1520 M_LCMP(REG_ITMP2, d); /* corner cases */
1521 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1522 ((REG_RESULT == d) ? 0 : 3);
1524 M_FLTMOVE(s1, REG_FTMP1);
1525 M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1527 M_INTMOVE(REG_RESULT, d);
1528 emit_store_dst(jd, iptr, d);
1531 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1533 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1534 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1536 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1537 M_LCMP(REG_ITMP2, d); /* corner cases */
1538 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1539 ((REG_RESULT == d) ? 0 : 3);
1541 M_FLTMOVE(s1, REG_FTMP1);
1542 M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1544 M_INTMOVE(REG_RESULT, d);
1545 emit_store_dst(jd, iptr, d);
1548 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1550 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1551 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1553 emit_store_dst(jd, iptr, d);
1556 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1558 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1559 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1561 emit_store_dst(jd, iptr, d);
1564 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1565 /* == => 0, < => 1, > => -1 */
1567 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1568 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1569 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1571 M_MOV_IMM(1, REG_ITMP1);
1572 M_MOV_IMM(-1, REG_ITMP2);
1573 emit_ucomiss_reg_reg(cd, s1, s2);
1574 M_CMOVB(REG_ITMP1, d);
1575 M_CMOVA(REG_ITMP2, d);
1576 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1577 emit_store_dst(jd, iptr, d);
1580 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1581 /* == => 0, < => 1, > => -1 */
1583 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1584 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1585 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1587 M_MOV_IMM(1, REG_ITMP1);
1588 M_MOV_IMM(-1, REG_ITMP2);
1589 emit_ucomiss_reg_reg(cd, s1, s2);
1590 M_CMOVB(REG_ITMP1, d);
1591 M_CMOVA(REG_ITMP2, d);
1592 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1593 emit_store_dst(jd, iptr, d);
1596 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1597 /* == => 0, < => 1, > => -1 */
1599 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1600 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1601 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1603 M_MOV_IMM(1, REG_ITMP1);
1604 M_MOV_IMM(-1, REG_ITMP2);
1605 emit_ucomisd_reg_reg(cd, s1, s2);
1606 M_CMOVB(REG_ITMP1, d);
1607 M_CMOVA(REG_ITMP2, d);
1608 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1609 emit_store_dst(jd, iptr, d);
1612 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1613 /* == => 0, < => 1, > => -1 */
1615 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1616 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1617 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1619 M_MOV_IMM(1, REG_ITMP1);
1620 M_MOV_IMM(-1, REG_ITMP2);
1621 emit_ucomisd_reg_reg(cd, s1, s2);
1622 M_CMOVB(REG_ITMP1, d);
1623 M_CMOVA(REG_ITMP2, d);
1624 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1625 emit_store_dst(jd, iptr, d);
1629 /* memory operations **************************************************/
1631 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1633 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1634 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1635 gen_nullptr_check(s1);
1636 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1637 emit_store_dst(jd, iptr, d);
1640 case ICMD_BALOAD: /* ..., 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_ITMP3);
1645 if (INSTRUCTION_MUST_CHECK(iptr)) {
1646 gen_nullptr_check(s1);
1649 emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
1650 emit_store_dst(jd, iptr, d);
1653 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1655 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1656 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1657 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1658 if (INSTRUCTION_MUST_CHECK(iptr)) {
1659 gen_nullptr_check(s1);
1662 emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
1663 emit_store_dst(jd, iptr, d);
1666 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1668 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1669 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1670 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1671 if (INSTRUCTION_MUST_CHECK(iptr)) {
1672 gen_nullptr_check(s1);
1675 emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
1676 emit_store_dst(jd, iptr, d);
1679 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1681 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1682 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1683 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1684 if (INSTRUCTION_MUST_CHECK(iptr)) {
1685 gen_nullptr_check(s1);
1688 emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
1689 emit_store_dst(jd, iptr, d);
1692 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1694 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1695 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1696 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1697 if (INSTRUCTION_MUST_CHECK(iptr)) {
1698 gen_nullptr_check(s1);
1701 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1702 emit_store_dst(jd, iptr, d);
1705 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1707 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1708 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1709 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1710 if (INSTRUCTION_MUST_CHECK(iptr)) {
1711 gen_nullptr_check(s1);
1714 emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1715 emit_store_dst(jd, iptr, d);
1718 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1720 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1721 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1722 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1723 if (INSTRUCTION_MUST_CHECK(iptr)) {
1724 gen_nullptr_check(s1);
1727 emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1728 emit_store_dst(jd, iptr, d);
1731 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1733 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1734 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1735 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1736 if (INSTRUCTION_MUST_CHECK(iptr)) {
1737 gen_nullptr_check(s1);
1740 emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
1741 emit_store_dst(jd, iptr, d);
1745 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1747 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1748 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1749 if (INSTRUCTION_MUST_CHECK(iptr)) {
1750 gen_nullptr_check(s1);
1753 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1754 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1757 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1759 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1760 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1761 if (INSTRUCTION_MUST_CHECK(iptr)) {
1762 gen_nullptr_check(s1);
1765 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1766 emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
1769 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1771 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1772 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1773 if (INSTRUCTION_MUST_CHECK(iptr)) {
1774 gen_nullptr_check(s1);
1777 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1778 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1781 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1783 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1784 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1785 if (INSTRUCTION_MUST_CHECK(iptr)) {
1786 gen_nullptr_check(s1);
1789 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1790 emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
1793 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1795 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1796 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1797 if (INSTRUCTION_MUST_CHECK(iptr)) {
1798 gen_nullptr_check(s1);
1801 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1802 emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
1805 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1807 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1808 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1809 if (INSTRUCTION_MUST_CHECK(iptr)) {
1810 gen_nullptr_check(s1);
1813 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1814 emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
1817 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
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 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1826 emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
1829 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1831 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1832 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1833 if (INSTRUCTION_MUST_CHECK(iptr)) {
1834 gen_nullptr_check(s1);
1837 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1841 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
1845 codegen_add_arraystoreexception_ref(cd);
1847 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1848 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1849 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1850 emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
1854 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1856 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1857 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1858 if (INSTRUCTION_MUST_CHECK(iptr)) {
1859 gen_nullptr_check(s1);
1862 emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1865 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1867 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1868 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1869 if (INSTRUCTION_MUST_CHECK(iptr)) {
1870 gen_nullptr_check(s1);
1873 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
1876 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1878 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1879 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1880 if (INSTRUCTION_MUST_CHECK(iptr)) {
1881 gen_nullptr_check(s1);
1884 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1887 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1889 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1890 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1891 if (INSTRUCTION_MUST_CHECK(iptr)) {
1892 gen_nullptr_check(s1);
1895 emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
1898 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1900 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1901 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1902 if (INSTRUCTION_MUST_CHECK(iptr)) {
1903 gen_nullptr_check(s1);
1907 if (IS_IMM32(iptr->sx.s23.s3.constval)) {
1908 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
1910 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
1911 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
1915 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1917 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1918 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1919 if (INSTRUCTION_MUST_CHECK(iptr)) {
1920 gen_nullptr_check(s1);
1923 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
1927 case ICMD_GETSTATIC: /* ... ==> ..., value */
1929 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1930 unresolved_field *uf = iptr->sx.s23.s3.uf;
1932 fieldtype = uf->fieldref->parseddesc.fd->type;
1933 disp = dseg_addaddress(cd, NULL);
1934 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
1936 /* must be calculated before codegen_addpatchref */
1938 if (opt_showdisassemble)
1939 disp -= PATCHER_CALL_SIZE;
1941 /* PROFILE_CYCLE_STOP; */
1943 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
1945 if (opt_showdisassemble) {
1946 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
1949 /* PROFILE_CYCLE_START; */
1952 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1954 fieldtype = fi->type;
1956 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1959 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
1961 if (opt_showdisassemble) {
1962 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
1965 PROFILE_CYCLE_START;
1968 disp = dseg_addaddress(cd, &(fi->value));
1969 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
1972 /* This approach is much faster than moving the field
1973 address inline into a register. */
1975 M_ALD(REG_ITMP1, RIP, disp);
1977 switch (fieldtype) {
1979 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1980 M_ILD(d, REG_ITMP1, 0);
1984 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1985 M_LLD(d, REG_ITMP1, 0);
1988 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1989 M_FLD(d, REG_ITMP1, 0);
1992 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1993 M_DLD(d, REG_ITMP1, 0);
1996 emit_store_dst(jd, iptr, d);
1999 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2001 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2002 unresolved_field *uf = iptr->sx.s23.s3.uf;
2004 fieldtype = uf->fieldref->parseddesc.fd->type;
2005 disp = dseg_addaddress(cd, NULL);
2006 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2008 /* must be calculated before codegen_addpatchref */
2010 if (opt_showdisassemble)
2011 disp -= PATCHER_CALL_SIZE;
2013 /* PROFILE_CYCLE_STOP; */
2015 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2017 if (opt_showdisassemble) {
2018 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2021 /* PROFILE_CYCLE_START; */
2024 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
2026 fieldtype = fi->type;
2028 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2031 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2033 if (opt_showdisassemble) {
2034 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2035 disp -= PATCHER_CALL_SIZE;
2038 PROFILE_CYCLE_START;
2041 disp = dseg_addaddress(cd, &(fi->value));
2042 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2045 /* This approach is much faster than moving the field
2046 address inline into a register. */
2048 M_ALD(REG_ITMP1, RIP, disp);
2050 switch (fieldtype) {
2052 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2053 M_IST(s1, REG_ITMP1, 0);
2057 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2058 M_LST(s1, REG_ITMP1, 0);
2061 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
2062 M_FST(s1, REG_ITMP1, 0);
2065 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
2066 M_DST(s1, REG_ITMP1, 0);
2071 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2072 /* val = value (in current instruction) */
2073 /* following NOP) */
2075 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2076 unresolved_field *uf = iptr->sx.s23.s3.uf;
2078 fieldtype = uf->fieldref->parseddesc.fd->type;
2079 disp = dseg_addaddress(cd, NULL);
2080 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2082 /* must be calculated before codegen_addpatchref */
2084 if (opt_showdisassemble)
2085 disp -= PATCHER_CALL_SIZE;
2088 /* PROFILE_CYCLE_STOP; */
2090 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2092 if (opt_showdisassemble) {
2093 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2096 /* PROFILE_CYCLE_START; */
2099 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
2101 fieldtype = fi->type;
2103 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2106 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2108 if (opt_showdisassemble) {
2109 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2112 PROFILE_CYCLE_START;
2115 disp = dseg_addaddress(cd, &(fi->value));
2116 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2119 /* This approach is much faster than moving the field
2120 address inline into a register. */
2122 M_ALD(REG_ITMP1, RIP, disp);
2124 switch (fieldtype) {
2127 M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
2132 if (IS_IMM32(iptr->sx.s23.s2.constval))
2133 M_LST_IMM32(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
2135 M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
2136 M_IST_IMM(iptr->sx.s23.s2.constval >> 32, REG_ITMP1, 4);
2142 case ICMD_GETFIELD: /* ... ==> ..., value */
2144 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2145 gen_nullptr_check(s1);
2147 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2148 unresolved_field *uf = iptr->sx.s23.s3.uf;
2150 /* PROFILE_CYCLE_STOP; */
2152 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2154 if (opt_showdisassemble) {
2155 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2158 /* PROFILE_CYCLE_START; */
2160 fieldtype = uf->fieldref->parseddesc.fd->type;
2164 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
2166 fieldtype = fi->type;
2170 switch (fieldtype) {
2172 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2173 M_ILD32(d, s1, disp);
2177 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2178 M_LLD32(d, s1, disp);
2181 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2182 M_FLD32(d, s1, disp);
2185 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2186 M_DLD32(d, s1, disp);
2189 emit_store_dst(jd, iptr, d);
2192 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2194 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2195 gen_nullptr_check(s1);
2197 s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2199 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2200 unresolved_field *uf = iptr->sx.s23.s3.uf;
2202 /* PROFILE_CYCLE_STOP; */
2204 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2206 if (opt_showdisassemble) {
2207 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2210 /* PROFILE_CYCLE_START; */
2212 fieldtype = uf->fieldref->parseddesc.fd->type;
2216 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
2218 fieldtype = fi->type;
2222 switch (fieldtype) {
2224 M_IST32(s2, s1, disp);
2228 M_LST32(s2, s1, disp);
2231 M_FST32(s2, s1, disp);
2234 M_DST32(s2, s1, disp);
2239 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2240 /* val = value (in current instruction) */
2241 /* following NOP) */
2243 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2244 gen_nullptr_check(s1);
2246 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2247 unresolved_field *uf = iptr->sx.s23.s3.uf;
2249 /* PROFILE_CYCLE_STOP; */
2251 codegen_addpatchref(cd, PATCHER_putfieldconst, uf, 0);
2253 if (opt_showdisassemble) {
2254 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2257 /* PROFILE_CYCLE_START; */
2259 fieldtype = uf->fieldref->parseddesc.fd->type;
2263 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
2265 fieldtype = fi->type;
2269 switch (fieldtype) {
2272 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2277 /* XXX why no check for IS_IMM32? */
2278 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2279 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2285 /* branch operations **************************************************/
2287 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2289 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2290 M_INTMOVE(s1, REG_ITMP1_XPTR);
2294 #ifdef ENABLE_VERIFIER
2295 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2296 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2297 iptr->sx.s23.s2.uc, 0);
2299 if (opt_showdisassemble) {
2300 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2303 #endif /* ENABLE_VERIFIER */
2305 M_CALL_IMM(0); /* passing exception pc */
2306 M_POP(REG_ITMP2_XPC);
2308 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2312 case ICMD_GOTO: /* ... ==> ... */
2315 codegen_addreference(cd, iptr->dst.block);
2318 case ICMD_JSR: /* ... ==> ... */
2321 codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block);
2324 case ICMD_RET: /* ... ==> ... */
2325 /* s1.localindex = local variable */
2328 codegen_addreference(cd, iptr->dst.block);
2331 case ICMD_IFNULL: /* ..., value ==> ... */
2333 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2336 codegen_addreference(cd, iptr->dst.block);
2339 case ICMD_IFNONNULL: /* ..., value ==> ... */
2341 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2344 codegen_addreference(cd, iptr->dst.block);
2347 case ICMD_IFEQ: /* ..., value ==> ... */
2349 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2350 M_ICMP_IMM(iptr->sx.val.i, s1);
2352 codegen_addreference(cd, iptr->dst.block);
2355 case ICMD_IFLT: /* ..., value ==> ... */
2357 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2358 M_ICMP_IMM(iptr->sx.val.i, s1);
2360 codegen_addreference(cd, iptr->dst.block);
2363 case ICMD_IFLE: /* ..., value ==> ... */
2365 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2366 M_ICMP_IMM(iptr->sx.val.i, s1);
2368 codegen_addreference(cd, iptr->dst.block);
2371 case ICMD_IFNE: /* ..., value ==> ... */
2373 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2374 M_ICMP_IMM(iptr->sx.val.i, s1);
2376 codegen_addreference(cd, iptr->dst.block);
2379 case ICMD_IFGT: /* ..., value ==> ... */
2381 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2382 M_ICMP_IMM(iptr->sx.val.i, s1);
2384 codegen_addreference(cd, iptr->dst.block);
2387 case ICMD_IFGE: /* ..., value ==> ... */
2389 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2390 M_ICMP_IMM(iptr->sx.val.i, s1);
2392 codegen_addreference(cd, iptr->dst.block);
2395 case ICMD_IF_LEQ: /* ..., value ==> ... */
2397 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2398 if (IS_IMM32(iptr->sx.val.l))
2399 M_LCMP_IMM(iptr->sx.val.l, s1);
2401 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2402 M_LCMP(REG_ITMP2, s1);
2405 codegen_addreference(cd, iptr->dst.block);
2408 case ICMD_IF_LLT: /* ..., value ==> ... */
2410 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2411 if (IS_IMM32(iptr->sx.val.l))
2412 M_LCMP_IMM(iptr->sx.val.l, s1);
2414 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2415 M_LCMP(REG_ITMP2, s1);
2418 codegen_addreference(cd, iptr->dst.block);
2421 case ICMD_IF_LLE: /* ..., value ==> ... */
2423 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2424 if (IS_IMM32(iptr->sx.val.l))
2425 M_LCMP_IMM(iptr->sx.val.l, s1);
2427 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2428 M_LCMP(REG_ITMP2, s1);
2431 codegen_addreference(cd, iptr->dst.block);
2434 case ICMD_IF_LNE: /* ..., value ==> ... */
2436 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2437 if (IS_IMM32(iptr->sx.val.l))
2438 M_LCMP_IMM(iptr->sx.val.l, s1);
2440 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2441 M_LCMP(REG_ITMP2, s1);
2444 codegen_addreference(cd, iptr->dst.block);
2447 case ICMD_IF_LGT: /* ..., value ==> ... */
2449 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2450 if (IS_IMM32(iptr->sx.val.l))
2451 M_LCMP_IMM(iptr->sx.val.l, s1);
2453 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2454 M_LCMP(REG_ITMP2, s1);
2457 codegen_addreference(cd, iptr->dst.block);
2460 case ICMD_IF_LGE: /* ..., value ==> ... */
2462 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2463 if (IS_IMM32(iptr->sx.val.l))
2464 M_LCMP_IMM(iptr->sx.val.l, s1);
2466 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2467 M_LCMP(REG_ITMP2, s1);
2470 codegen_addreference(cd, iptr->dst.block);
2473 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2475 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2476 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2479 codegen_addreference(cd, iptr->dst.block);
2482 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2483 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2485 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2486 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2489 codegen_addreference(cd, iptr->dst.block);
2492 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2494 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2495 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2498 codegen_addreference(cd, iptr->dst.block);
2501 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2502 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2504 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2505 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2508 codegen_addreference(cd, iptr->dst.block);
2511 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2513 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2514 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2517 codegen_addreference(cd, iptr->dst.block);
2520 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2522 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2523 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2526 codegen_addreference(cd, iptr->dst.block);
2529 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2531 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2532 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2535 codegen_addreference(cd, iptr->dst.block);
2538 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2540 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2541 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2544 codegen_addreference(cd, iptr->dst.block);
2547 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2549 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2550 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2553 codegen_addreference(cd, iptr->dst.block);
2556 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2558 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2559 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2562 codegen_addreference(cd, iptr->dst.block);
2565 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2567 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2568 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2571 codegen_addreference(cd, iptr->dst.block);
2574 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2576 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2577 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2580 codegen_addreference(cd, iptr->dst.block);
2583 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2586 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2587 M_INTMOVE(s1, REG_RESULT);
2588 goto nowperformreturn;
2590 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2592 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2593 M_INTMOVE(s1, REG_RESULT);
2595 #ifdef ENABLE_VERIFIER
2596 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2599 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2600 iptr->sx.s23.s2.uc, 0);
2602 if (opt_showdisassemble) {
2603 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2606 PROFILE_CYCLE_START;
2608 #endif /* ENABLE_VERIFIER */
2609 goto nowperformreturn;
2611 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2614 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2615 M_FLTMOVE(s1, REG_FRESULT);
2616 goto nowperformreturn;
2618 case ICMD_RETURN: /* ... ==> ... */
2624 p = cd->stackframesize;
2626 #if !defined(NDEBUG)
2627 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2628 emit_verbosecall_exit(jd);
2629 #endif /* !defined(NDEBUG) */
2631 #if defined(ENABLE_THREADS)
2632 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2633 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2635 /* we need to save the proper return value */
2636 switch (iptr->opc) {
2640 M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
2644 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
2648 M_MOV_IMM(LOCK_monitor_exit, REG_ITMP1);
2651 /* and now restore the proper return value */
2652 switch (iptr->opc) {
2656 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2660 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2666 /* restore saved registers */
2668 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2669 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2671 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2672 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2675 /* deallocate stack */
2677 if (cd->stackframesize)
2678 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2680 /* generate method profiling code */
2689 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2692 branch_target_t *table;
2694 table = iptr->dst.table;
2696 l = iptr->sx.s23.s2.tablelow;
2697 i = iptr->sx.s23.s3.tablehigh;
2699 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2700 M_INTMOVE(s1, REG_ITMP1);
2703 M_ISUB_IMM(l, REG_ITMP1);
2705 /* number of targets */
2709 M_ICMP_IMM(i - 1, REG_ITMP1);
2712 codegen_addreference(cd, table[0].block); /* default target */
2714 /* build jump table top down and use address of lowest entry */
2719 dseg_addtarget(cd, table->block);
2723 /* length of dataseg after last dseg_addtarget is used
2726 M_MOV_IMM(0, REG_ITMP2);
2728 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2734 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2737 lookup_target_t *lookup;
2739 lookup = iptr->dst.lookup;
2741 i = iptr->sx.s23.s2.lookupcount;
2743 MCODECHECK(8 + ((7 + 6) * i) + 5);
2744 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2747 M_ICMP_IMM(lookup->value, s1);
2749 codegen_addreference(cd, lookup->target.block);
2755 codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block);
2760 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2762 bte = iptr->sx.s23.s3.bte;
2766 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2768 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2769 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2770 case ICMD_INVOKEINTERFACE:
2772 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2774 um = iptr->sx.s23.s3.um;
2775 md = um->methodref->parseddesc.md;
2778 lm = iptr->sx.s23.s3.fmiref->p.method;
2780 md = lm->parseddesc;
2784 s3 = md->paramcount;
2786 MCODECHECK((20 * s3) + 128);
2788 /* copy arguments to registers or stack location */
2790 for (s3 = s3 - 1; s3 >= 0; s3--) {
2791 s1 = iptr->sx.s23.s2.args[s3];
2792 var1 = jd->var + s1;
2794 /* Already Preallocated (ARGVAR) ? */
2795 if (var1->flags & PREALLOC)
2798 if (IS_INT_LNG_TYPE(var1->type)) {
2799 if (!md->params[s3].inmemory) {
2800 s1 = rd->argintregs[md->params[s3].regoff];
2801 d = emit_load(jd, iptr, var1, s1);
2805 d = emit_load(jd, iptr, var1, REG_ITMP1);
2806 M_LST(d, REG_SP, md->params[s3].regoff * 8);
2810 if (!md->params[s3].inmemory) {
2811 s1 = rd->argfltregs[md->params[s3].regoff];
2812 d = emit_load(jd, iptr, var1, s1);
2816 d = emit_load(jd, iptr, var1, REG_FTMP1);
2818 if (IS_2_WORD_TYPE(var1->type))
2819 M_DST(d, REG_SP, md->params[s3].regoff * 8);
2821 M_FST(d, REG_SP, md->params[s3].regoff * 8);
2826 /* generate method profiling code */
2830 switch (iptr->opc) {
2832 M_MOV_IMM(bte->fp, REG_ITMP1);
2835 if (INSTRUCTION_MUST_CHECK(iptr)) {
2838 codegen_add_fillinstacktrace_ref(cd);
2842 case ICMD_INVOKESPECIAL:
2845 codegen_add_nullpointerexception_ref(cd);
2849 case ICMD_INVOKESTATIC:
2851 disp = dseg_addaddress(cd, NULL);
2852 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2854 /* must be calculated before codegen_addpatchref */
2856 if (opt_showdisassemble)
2857 disp -= PATCHER_CALL_SIZE;
2859 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2862 if (opt_showdisassemble) {
2863 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2869 disp = dseg_addaddress(cd, lm->stubroutine);
2870 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2872 /* a = (ptrint) lm->stubroutine; */
2875 /* M_MOV_IMM(a, REG_ITMP2); */
2876 M_ALD(REG_ITMP2, RIP, disp);
2880 case ICMD_INVOKEVIRTUAL:
2881 gen_nullptr_check(REG_A0);
2884 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2886 if (opt_showdisassemble) {
2887 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2893 s1 = OFFSET(vftbl_t, table[0]) +
2894 sizeof(methodptr) * lm->vftblindex;
2896 M_ALD(REG_METHODPTR, REG_A0,
2897 OFFSET(java_objectheader, vftbl));
2898 M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
2902 case ICMD_INVOKEINTERFACE:
2903 gen_nullptr_check(REG_A0);
2906 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2908 if (opt_showdisassemble) {
2909 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2916 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2917 sizeof(methodptr) * lm->class->index;
2919 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2922 M_ALD(REG_METHODPTR, REG_A0,
2923 OFFSET(java_objectheader, vftbl));
2924 M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
2925 M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
2930 /* generate method profiling code */
2932 PROFILE_CYCLE_START;
2934 /* store return value */
2936 d = md->returntype.type;
2938 if (d != TYPE_VOID) {
2939 if (IS_INT_LNG_TYPE(d)) {
2940 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2941 M_INTMOVE(REG_RESULT, s1);
2944 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2945 M_FLTMOVE(REG_FRESULT, s1);
2947 emit_store_dst(jd, iptr, s1);
2952 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2954 /* val.a: (classinfo *) superclass */
2956 /* superclass is an interface:
2958 * OK if ((sub == NULL) ||
2959 * (sub->vftbl->interfacetablelength > super->index) &&
2960 * (sub->vftbl->interfacetable[-super->index] != NULL));
2962 * superclass is a class:
2964 * OK if ((sub == NULL) || (0
2965 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2966 * super->vftbl->diffval));
2969 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2970 /* object type cast-check */
2973 vftbl_t *supervftbl;
2976 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2982 super = iptr->sx.s23.s3.c.cls;
2983 superindex = super->index;
2984 supervftbl = super->vftbl;
2987 #if defined(ENABLE_THREADS)
2988 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2990 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2992 /* calculate interface checkcast code size */
2994 s2 = 3; /* mov_membase_reg */
2995 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
2997 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub imm32 */ +
2998 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
2999 3 /* test */ + 6 /* jcc */;
3002 s2 += (opt_showdisassemble ? 5 : 0);
3004 /* calculate class checkcast code size */
3006 s3 = 3; /* mov_membase_reg */
3007 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3008 s3 += 10 /* mov_imm_reg */ + 3 + 4 /* movl_membase32_reg */;
3011 if (s1 != REG_ITMP1) {
3012 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3013 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3014 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3015 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3021 s3 += 3 + 4 /* movl_membase32_reg */ + 3 /* sub */ +
3022 10 /* mov_imm_reg */ + 3 /* movl_membase_reg */;
3023 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3026 s3 += 3 /* cmp */ + 6 /* jcc */;
3029 s3 += (opt_showdisassemble ? 5 : 0);
3031 /* if class is not resolved, check which code to call */
3033 if (super == NULL) {
3035 M_BEQ(6 + (opt_showdisassemble ? 5 : 0) + 7 + 6 + s2 + 5 + s3);
3037 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3038 iptr->sx.s23.s3.c.ref, 0);
3040 if (opt_showdisassemble) {
3041 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3044 M_IMOV_IMM(0, REG_ITMP2); /* super->flags */
3045 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
3049 /* interface checkcast code */
3051 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3052 if (super != NULL) {
3057 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3059 if (super == NULL) {
3060 codegen_addpatchref(cd,
3061 PATCHER_checkcast_instanceof_interface,
3062 iptr->sx.s23.s3.c.ref,
3065 if (opt_showdisassemble) {
3066 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3070 emit_movl_membase32_reg(cd, REG_ITMP2,
3071 OFFSET(vftbl_t, interfacetablelength),
3073 /* XXX TWISTI: should this be int arithmetic? */
3074 M_LSUB_IMM32(superindex, REG_ITMP3);
3077 codegen_add_classcastexception_ref(cd, s1);
3078 emit_mov_membase32_reg(cd, REG_ITMP2,
3079 OFFSET(vftbl_t, interfacetable[0]) -
3080 superindex * sizeof(methodptr*),
3084 codegen_add_classcastexception_ref(cd, s1);
3090 /* class checkcast code */
3092 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3093 if (super != NULL) {
3098 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3100 if (super == NULL) {
3101 codegen_addpatchref(cd, PATCHER_checkcast_class,
3102 iptr->sx.s23.s3.c.ref,
3105 if (opt_showdisassemble) {
3106 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3110 M_MOV_IMM(supervftbl, REG_ITMP3);
3111 #if defined(ENABLE_THREADS)
3112 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3114 emit_movl_membase32_reg(cd, REG_ITMP2,
3115 OFFSET(vftbl_t, baseval),
3117 /* if (s1 != REG_ITMP1) { */
3118 /* emit_movl_membase_reg(cd, REG_ITMP3, */
3119 /* OFFSET(vftbl_t, baseval), */
3121 /* emit_movl_membase_reg(cd, REG_ITMP3, */
3122 /* OFFSET(vftbl_t, diffval), */
3124 /* #if defined(ENABLE_THREADS) */
3125 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3127 /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
3130 emit_movl_membase32_reg(cd, REG_ITMP3,
3131 OFFSET(vftbl_t, baseval),
3133 M_LSUB(REG_ITMP3, REG_ITMP2);
3134 M_MOV_IMM(supervftbl, REG_ITMP3);
3135 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3137 #if defined(ENABLE_THREADS)
3138 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3140 M_LCMP(REG_ITMP3, REG_ITMP2);
3141 M_BA(0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
3142 codegen_add_classcastexception_ref(cd, s1);
3145 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
3148 /* array type cast-check */
3150 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
3151 M_INTMOVE(s1, REG_A0);
3153 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3154 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
3155 iptr->sx.s23.s3.c.ref, 0);
3157 if (opt_showdisassemble) {
3158 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3162 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3163 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
3166 /* s1 may have been destroyed over the function call */
3167 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
3170 codegen_add_classcastexception_ref(cd, s1);
3172 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3176 emit_store_dst(jd, iptr, d);
3179 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3181 /* val.a: (classinfo *) superclass */
3183 /* superclass is an interface:
3185 * return (sub != NULL) &&
3186 * (sub->vftbl->interfacetablelength > super->index) &&
3187 * (sub->vftbl->interfacetable[-super->index] != NULL);
3189 * superclass is a class:
3191 * return ((sub != NULL) && (0
3192 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3193 * super->vftbl->diffvall));
3198 vftbl_t *supervftbl;
3201 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3207 super = iptr->sx.s23.s3.c.cls;
3208 superindex = super->index;
3209 supervftbl = super->vftbl;
3212 #if defined(ENABLE_THREADS)
3213 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3216 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3217 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3219 M_INTMOVE(s1, REG_ITMP1);
3223 /* calculate interface instanceof code size */
3225 s2 = 3; /* mov_membase_reg */
3226 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3227 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub_imm32 */ +
3228 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3229 3 /* test */ + 4 /* setcc */;
3232 s2 += (opt_showdisassemble ? 5 : 0);
3234 /* calculate class instanceof code size */
3236 s3 = 3; /* mov_membase_reg */
3237 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3238 s3 += 10; /* mov_imm_reg */
3239 s3 += 2; /* movl_membase_reg - only if REG_ITMP1 == RAX */
3240 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3241 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3242 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3243 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3244 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3245 s3 += 3 /* sub */ + 3 /* xor */ + 3 /* cmp */ + 4 /* setcc */;
3248 s3 += (opt_showdisassemble ? 5 : 0);
3250 emit_alu_reg_reg(cd, ALU_XOR, d, d);
3252 /* if class is not resolved, check which code to call */
3255 emit_test_reg_reg(cd, s1, s1);
3256 emit_jcc(cd, CC_Z, (6 + (opt_showdisassemble ? 5 : 0) +
3257 7 + 6 + s2 + 5 + s3));
3259 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3260 iptr->sx.s23.s3.c.ref, 0);
3262 if (opt_showdisassemble) {
3263 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3266 emit_movl_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
3267 emit_alul_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
3268 emit_jcc(cd, CC_Z, s2 + 5);
3271 /* interface instanceof code */
3273 if (!super || (super->flags & ACC_INTERFACE)) {
3275 emit_test_reg_reg(cd, s1, s1);
3276 emit_jcc(cd, CC_Z, s2);
3279 emit_mov_membase_reg(cd, s1,
3280 OFFSET(java_objectheader, vftbl),
3283 codegen_addpatchref(cd,
3284 PATCHER_checkcast_instanceof_interface,
3285 iptr->sx.s23.s3.c.ref, 0);
3287 if (opt_showdisassemble) {
3288 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3292 emit_movl_membase32_reg(cd, REG_ITMP1,
3293 OFFSET(vftbl_t, interfacetablelength),
3295 emit_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
3296 emit_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
3298 a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
3300 emit_jcc(cd, CC_LE, a);
3301 emit_mov_membase32_reg(cd, REG_ITMP1,
3302 OFFSET(vftbl_t, interfacetable[0]) -
3303 superindex * sizeof(methodptr*),
3305 emit_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3306 emit_setcc_reg(cd, CC_NE, d);
3309 emit_jmp_imm(cd, s3);
3312 /* class instanceof code */
3314 if (!super || !(super->flags & ACC_INTERFACE)) {
3316 emit_test_reg_reg(cd, s1, s1);
3317 emit_jcc(cd, CC_E, s3);
3320 emit_mov_membase_reg(cd, s1,
3321 OFFSET(java_objectheader, vftbl),
3325 codegen_addpatchref(cd, PATCHER_instanceof_class,
3326 iptr->sx.s23.s3.c.ref, 0);
3328 if (opt_showdisassemble) {
3329 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3333 emit_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
3334 #if defined(ENABLE_THREADS)
3335 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3337 emit_movl_membase_reg(cd, REG_ITMP1,
3338 OFFSET(vftbl_t, baseval),
3340 emit_movl_membase_reg(cd, REG_ITMP2,
3341 OFFSET(vftbl_t, diffval),
3343 emit_movl_membase_reg(cd, REG_ITMP2,
3344 OFFSET(vftbl_t, baseval),
3346 #if defined(ENABLE_THREADS)
3347 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3349 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
3350 emit_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
3351 emit_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
3352 emit_setcc_reg(cd, CC_BE, d);
3354 emit_store_dst(jd, iptr, d);
3358 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3360 /* check for negative sizes and copy sizes to stack if necessary */
3362 MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3364 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3366 /* copy SAVEDVAR sizes to stack */
3367 s3 = iptr->sx.s23.s2.args[s1];
3368 var1 = jd->var + s3;
3370 /* Already Preallocated (ARGVAR) ? */
3371 if (!(var1->flags & PREALLOC)) {
3372 s2 = emit_load(jd, iptr, var1, REG_ITMP1);
3373 M_LST(s2, REG_SP, s1 * 8);
3377 /* is a patcher function set? */
3379 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3380 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
3381 iptr->sx.s23.s3.c.ref, 0);
3383 if (opt_showdisassemble) {
3384 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3388 /* a0 = dimension count */
3390 M_MOV_IMM(iptr->s1.argcount, REG_A0);
3392 /* a1 = classinfo */
3394 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3396 /* a2 = pointer to dimensions = stack pointer */
3398 M_MOV(REG_SP, REG_A2);
3400 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3403 /* check for exception before result assignment */
3407 codegen_add_fillinstacktrace_ref(cd);
3409 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3410 M_INTMOVE(REG_RESULT, s1);
3411 emit_store_dst(jd, iptr, s1);
3415 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3419 } /* for instruction */
3421 /* copy values to interface registers */
3423 len = bptr->outdepth;
3426 /* At the end of a basic block we may have to append some nops,
3427 because the patcher stub calling code might be longer than the
3428 actual instruction. So codepatching does not change the
3429 following block unintentionally. */
3431 if (cd->mcodeptr < cd->lastmcodeptr) {
3432 while (cd->mcodeptr < cd->lastmcodeptr) {
3437 } /* if (bptr -> flags >= BBREACHED) */
3438 } /* for basic block */
3440 dseg_createlinenumbertable(cd);
3442 /* generate stubs */
3444 emit_exception_stubs(jd);
3445 emit_patcher_stubs(jd);
3447 emit_replacement_stubs(jd);
3452 /* everything's ok */
3458 /* createcompilerstub **********************************************************
3460 Creates a stub routine which calls the compiler.
3462 *******************************************************************************/
3464 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
3465 #define COMPILERSTUB_CODESIZE 7 + 7 + 3
3467 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
3470 u1 *createcompilerstub(methodinfo *m)
3472 u1 *s; /* memory to hold the stub */
3478 s = CNEW(u1, COMPILERSTUB_SIZE);
3480 /* set data pointer and code pointer */
3483 s = s + COMPILERSTUB_DATASIZE;
3485 /* mark start of dump memory area */
3487 dumpsize = dump_size();
3489 cd = DNEW(codegendata);
3492 /* Store the codeinfo pointer in the same place as in the
3493 methodheader for compiled methods. */
3495 code = code_codeinfo_new(m);
3497 d[0] = (ptrint) asm_call_jit_compiler;
3499 d[2] = (ptrint) code;
3501 /* code for the stub */
3503 M_ALD(REG_ITMP1, RIP, -(7 * 1 + 2 * SIZEOF_VOID_P)); /* methodinfo */
3504 M_ALD(REG_ITMP3, RIP, -(7 * 2 + 3 * SIZEOF_VOID_P)); /* compiler pointer */
3507 #if defined(ENABLE_STATISTICS)
3509 count_cstub_len += COMPILERSTUB_SIZE;
3512 /* release dump area */
3514 dump_release(dumpsize);
3520 /* createnativestub ************************************************************
3522 Creates a stub routine which calls a native method.
3524 *******************************************************************************/
3526 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3534 s4 i, j; /* count variables */
3538 /* get required compiler data */
3545 /* initialize variables */
3548 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3550 /* calculate stack frame size */
3552 cd->stackframesize =
3553 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3554 sizeof(localref_table) / SIZEOF_VOID_P +
3555 INT_ARG_CNT + FLT_ARG_CNT +
3556 1 + /* functionptr, TODO: store in data segment */
3559 cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */
3561 /* create method header */
3563 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
3564 (void) dseg_adds4(cd, cd->stackframesize * 8); /* FrameSize */
3565 (void) dseg_adds4(cd, 0); /* IsSync */
3566 (void) dseg_adds4(cd, 0); /* IsLeaf */
3567 (void) dseg_adds4(cd, 0); /* IntSave */
3568 (void) dseg_adds4(cd, 0); /* FltSave */
3569 (void) dseg_addlinenumbertablesize(cd);
3570 (void) dseg_adds4(cd, 0); /* ExTableSize */
3572 /* generate native method profiling code */
3574 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3575 /* count frequency */
3577 M_MOV_IMM(code, REG_ITMP3);
3578 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3581 /* generate stub code */
3583 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3585 #if !defined(NDEBUG)
3586 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3587 emit_verbosecall_enter(jd);
3590 /* get function address (this must happen before the stackframeinfo) */
3592 #if !defined(WITH_STATIC_CLASSPATH)
3594 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
3596 if (opt_showdisassemble) {
3597 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3602 M_MOV_IMM(f, REG_ITMP3);
3605 /* save integer and float argument registers */
3607 for (i = 0, j = 0; i < md->paramcount; i++) {
3608 if (!md->params[i].inmemory) {
3609 s1 = md->params[i].regoff;
3611 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
3612 M_LST(rd->argintregs[s1], REG_SP, j * 8);
3614 M_DST(rd->argfltregs[s1], REG_SP, j * 8);
3620 M_AST(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
3622 /* create dynamic stack info */
3624 M_ALEA(REG_SP, cd->stackframesize * 8, REG_A0);
3625 emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), REG_A1);
3626 M_ALEA(REG_SP, cd->stackframesize * 8 + SIZEOF_VOID_P, REG_A2);
3627 M_ALD(REG_A3, REG_SP, cd->stackframesize * 8);
3628 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
3631 /* restore integer and float argument registers */
3633 for (i = 0, j = 0; i < md->paramcount; i++) {
3634 if (!md->params[i].inmemory) {
3635 s1 = md->params[i].regoff;
3637 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
3638 M_LLD(rd->argintregs[s1], REG_SP, j * 8);
3640 M_DLD(rd->argfltregs[s1], REG_SP, j * 8);
3646 M_ALD(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
3649 /* copy or spill arguments to new locations */
3651 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3652 t = md->paramtypes[i].type;
3654 if (IS_INT_LNG_TYPE(t)) {
3655 if (!md->params[i].inmemory) {
3656 s1 = rd->argintregs[md->params[i].regoff];
3658 if (!nmd->params[j].inmemory) {
3659 s2 = rd->argintregs[nmd->params[j].regoff];
3663 s2 = nmd->params[j].regoff;
3664 M_LST(s1, REG_SP, s2 * 8);
3668 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3669 s2 = nmd->params[j].regoff;
3670 M_LLD(REG_ITMP1, REG_SP, s1 * 8);
3671 M_LST(REG_ITMP1, REG_SP, s2 * 8);
3675 /* We only copy spilled float arguments, as the float argument */
3676 /* registers keep unchanged. */
3678 if (md->params[i].inmemory) {
3679 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3680 s2 = nmd->params[j].regoff;
3682 if (IS_2_WORD_TYPE(t)) {
3683 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
3684 M_DST(REG_FTMP1, REG_SP, s2 * 8);
3686 M_FLD(REG_FTMP1, REG_SP, s1 * 8);
3687 M_FST(REG_FTMP1, REG_SP, s2 * 8);
3693 /* put class into second argument register */
3695 if (m->flags & ACC_STATIC)
3696 M_MOV_IMM(m->class, REG_A1);
3698 /* put env into first argument register */
3700 M_MOV_IMM(_Jv_env, REG_A0);
3702 /* do the native function call */
3706 /* save return value */
3708 if (md->returntype.type != TYPE_VOID) {
3709 if (IS_INT_LNG_TYPE(md->returntype.type))
3710 M_LST(REG_RESULT, REG_SP, 0 * 8);
3712 M_DST(REG_FRESULT, REG_SP, 0 * 8);
3715 #if !defined(NDEBUG)
3716 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3717 emit_verbosecall_exit(jd);
3720 /* remove native stackframe info */
3722 M_ALEA(REG_SP, cd->stackframesize * 8, REG_A0);
3723 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
3725 M_MOV(REG_RESULT, REG_ITMP3);
3727 /* restore return value */
3729 if (md->returntype.type != TYPE_VOID) {
3730 if (IS_INT_LNG_TYPE(md->returntype.type))
3731 M_LLD(REG_RESULT, REG_SP, 0 * 8);
3733 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
3736 /* remove stackframe */
3738 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3740 /* test for exception */
3746 /* handle exception */
3748 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3749 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
3750 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3752 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
3755 /* generate patcher stubs */
3757 emit_patcher_stubs(jd);
3761 return code->entrypoint;
3766 * These are local overrides for various environment variables in Emacs.
3767 * Please do not remove this and leave it at the end of the file, where
3768 * Emacs will automagically detect them.
3769 * ---------------------------------------------------------------------
3772 * indent-tabs-mode: t
3776 * vim:noexpandtab:sw=4:ts=4: