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 5945 2006-11-10 16:41:12Z twisti $
46 #include "vm/jit/x86_64/arch.h"
47 #include "vm/jit/x86_64/codegen.h"
48 #include "vm/jit/x86_64/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 "vm/loader.h"
62 #include "vm/options.h"
63 #include "vm/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"
77 #if defined(ENABLE_LSRA)
78 # include "vm/jit/allocator/lsra.h"
82 /* codegen *********************************************************************
84 Generates machine code.
86 *******************************************************************************/
88 bool codegen(jitdata *jd)
94 s4 len, s1, s2, s3, d, disp;
97 varinfo *var, *var1, *var2, *dst;
101 constant_classref *cr;
102 unresolved_class *uc;
103 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
104 unresolved_method *um;
105 builtintable_entry *bte;
108 unresolved_field *uf;
110 rplpoint *replacementpoint;
113 /* get required compiler data */
120 /* prevent compiler warnings */
133 /* space to save used callee saved registers */
135 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
136 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
138 cd->stackframesize = rd->memuse + savedregs_num;
140 #if defined(ENABLE_THREADS)
141 /* space to save argument of monitor_enter */
143 if (checksync && (m->flags & ACC_SYNCHRONIZED))
144 cd->stackframesize++;
147 /* Keep stack of non-leaf functions 16-byte aligned for calls into
148 native code e.g. libc or jni (alignment problems with
151 if (!jd->isleafmethod || opt_verbosecall)
152 cd->stackframesize |= 0x1;
154 /* create method header */
156 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
157 (void) dseg_adds4(cd, cd->stackframesize * 8); /* FrameSize */
159 #if defined(ENABLE_THREADS)
160 /* IsSync contains the offset relative to the stack pointer for the
161 argument of monitor_exit used in the exception handler. Since the
162 offset could be zero and give a wrong meaning of the flag it is
166 if (checksync && (m->flags & ACC_SYNCHRONIZED))
167 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
170 (void) dseg_adds4(cd, 0); /* IsSync */
172 (void) dseg_adds4(cd, jd->isleafmethod); /* IsLeaf */
173 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
174 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
176 (void) dseg_addlinenumbertablesize(cd);
178 (void) dseg_adds4(cd, jd->exceptiontablelength); /* ExTableSize */
180 /* create exception table */
182 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
183 dseg_addtarget(cd, ex->start);
184 dseg_addtarget(cd, ex->end);
185 dseg_addtarget(cd, ex->handler);
186 (void) dseg_addaddress(cd, ex->catchtype.any);
189 /* generate method profiling code */
191 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
192 /* count frequency */
194 M_MOV_IMM(code, REG_ITMP3);
195 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
200 /* create stack frame (if necessary) */
202 if (cd->stackframesize)
203 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
205 /* save used callee saved registers */
207 p = cd->stackframesize;
208 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
209 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
211 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
212 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
215 /* take arguments out of register or stack frame */
219 for (p = 0, l = 0; p < md->paramcount; p++) {
220 t = md->paramtypes[p].type;
222 varindex = jd->local_map[l * 5 + t];
225 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
228 if (varindex == UNUSED)
233 s1 = md->params[p].regoff;
235 if (IS_INT_LNG_TYPE(t)) { /* integer args */
236 s2 = rd->argintregs[s1];
237 if (!md->params[p].inmemory) { /* register arguments */
238 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
239 M_INTMOVE(s2, var->vv.regoff);
241 } else { /* reg arg -> spilled */
242 M_LST(s2, REG_SP, var->vv.regoff * 8);
245 } else { /* stack arguments */
246 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
247 /* + 8 for return address */
248 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 8 + 8);
250 } else { /* stack arg -> spilled */
251 var->vv.regoff = cd->stackframesize + s1 + 1;
255 } else { /* floating args */
256 if (!md->params[p].inmemory) { /* register arguments */
257 s2 = rd->argfltregs[s1];
258 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
259 M_FLTMOVE(s2, var->vv.regoff);
261 } else { /* reg arg -> spilled */
262 M_DST(s2, REG_SP, var->vv.regoff * 8);
265 } else { /* stack arguments */
266 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
267 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 8 + 8);
270 var->vv.regoff = cd->stackframesize + s1 + 1;
276 /* save monitorenter argument */
278 #if defined(ENABLE_THREADS)
279 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
280 /* stack offset for monitor argument */
284 if (opt_verbosecall) {
285 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
287 for (p = 0; p < INT_ARG_CNT; p++)
288 M_LST(rd->argintregs[p], REG_SP, p * 8);
290 for (p = 0; p < FLT_ARG_CNT; p++)
291 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
293 s1 += INT_ARG_CNT + FLT_ARG_CNT;
296 /* decide which monitor enter function to call */
298 if (m->flags & ACC_STATIC) {
299 M_MOV_IMM(&m->class->object.header, REG_A0);
304 codegen_add_nullpointerexception_ref(cd);
307 M_AST(REG_A0, REG_SP, s1 * 8);
308 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
311 if (opt_verbosecall) {
312 for (p = 0; p < INT_ARG_CNT; p++)
313 M_LLD(rd->argintregs[p], REG_SP, p * 8);
315 for (p = 0; p < FLT_ARG_CNT; p++)
316 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
318 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
324 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
325 emit_verbosecall_enter(jd);
326 #endif /* !defined(NDEBUG) */
330 /* end of header generation */
332 replacementpoint = jd->code->rplpoints;
334 /* walk through all basic blocks */
336 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
338 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
340 if (bptr->flags >= BBREACHED) {
342 /* branch resolving */
344 codegen_resolve_branchrefs(cd, bptr);
346 /* handle replacement points */
349 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
350 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
354 assert(cd->lastmcodeptr <= cd->mcodeptr);
355 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
359 /* copy interface registers to their destination */
364 /* generate basicblock profiling code */
366 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
367 /* count frequency */
369 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
370 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
372 /* if this is an exception handler, start profiling again */
374 if (bptr->type == BBTYPE_EXH)
378 #if defined(ENABLE_LSRA)
382 src = bptr->invars[len];
383 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
384 if (bptr->type == BBTYPE_EXH) {
385 /* d = reg_of_var(rd, src, REG_ITMP1); */
386 if (!IS_INMEMORY(src->flags))
390 M_INTMOVE(REG_ITMP1, d);
391 emit_store(jd, NULL, src, d);
401 var = VAR(bptr->invars[len]);
402 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
403 if (bptr->type == BBTYPE_EXH) {
404 d = codegen_reg_of_var(0, var, REG_ITMP1);
405 M_INTMOVE(REG_ITMP1, d);
406 emit_store(jd, NULL, var, d);
410 assert((var->flags & INOUT));
413 #if defined(ENABLE_LSRA)
416 /* walk through all instructions */
421 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
422 if (iptr->line != currentline) {
423 dseg_addlinenumber(cd, iptr->line);
424 currentline = iptr->line;
427 MCODECHECK(1024); /* 1KB should be enough */
430 case ICMD_NOP: /* ... ==> ... */
431 case ICMD_POP: /* ..., value ==> ... */
432 case ICMD_POP2: /* ..., value, value ==> ... */
433 case ICMD_INLINE_START: /* internal ICMDs */
434 case ICMD_INLINE_END:
437 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
439 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
442 codegen_add_nullpointerexception_ref(cd);
445 /* constant operations ************************************************/
447 case ICMD_ICONST: /* ... ==> ..., constant */
449 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
450 ICONST(d, iptr->sx.val.i);
451 emit_store_dst(jd, iptr, d);
454 case ICMD_LCONST: /* ... ==> ..., constant */
456 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
457 LCONST(d, iptr->sx.val.l);
458 emit_store_dst(jd, iptr, d);
461 case ICMD_FCONST: /* ... ==> ..., constant */
463 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
464 disp = dseg_addfloat(cd, iptr->sx.val.f);
465 emit_movdl_membase_reg(cd, RIP, -((cd->mcodeptr + ((d > 7) ? 9 : 8)) - cd->mcodebase) + disp, d);
466 emit_store_dst(jd, iptr, d);
469 case ICMD_DCONST: /* ... ==> ..., constant */
471 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
472 disp = dseg_adddouble(cd, iptr->sx.val.d);
473 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, d);
474 emit_store_dst(jd, iptr, d);
477 case ICMD_ACONST: /* ... ==> ..., constant */
479 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
481 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
482 cr = iptr->sx.val.c.ref;
484 /* PROFILE_CYCLE_STOP; */
486 codegen_add_patch_ref(cd, PATCHER_aconst, cr, 0);
488 /* PROFILE_CYCLE_START; */
493 if (iptr->sx.val.anyptr == 0)
496 M_MOV_IMM(iptr->sx.val.anyptr, d);
498 emit_store_dst(jd, iptr, d);
502 /* load/store/copy/move operations ************************************/
504 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
505 case ICMD_ALOAD: /* s1 = local variable */
509 case ICMD_ISTORE: /* ..., value ==> ... */
510 case ICMD_ASTORE: /* dst = local variable */
517 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
521 /* integer operations *************************************************/
523 case ICMD_INEG: /* ..., value ==> ..., - value */
525 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
526 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
529 emit_store_dst(jd, iptr, d);
532 case ICMD_LNEG: /* ..., value ==> ..., - value */
534 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
535 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
538 emit_store_dst(jd, iptr, d);
541 case ICMD_I2L: /* ..., value ==> ..., value */
543 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
544 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
546 emit_store_dst(jd, iptr, d);
549 case ICMD_L2I: /* ..., value ==> ..., value */
551 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
552 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
554 emit_store_dst(jd, iptr, d);
557 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
559 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
560 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
562 emit_store_dst(jd, iptr, d);
565 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
567 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
568 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
570 emit_store_dst(jd, iptr, d);
573 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
575 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
576 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
578 emit_store_dst(jd, iptr, d);
582 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
584 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
585 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
586 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
593 emit_store_dst(jd, iptr, d);
597 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
598 /* sx.val.i = constant */
600 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
601 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
603 /* Using inc and dec is not faster than add (tested with
607 M_IADD_IMM(iptr->sx.val.i, d);
608 emit_store_dst(jd, iptr, d);
611 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
613 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
614 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
615 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
622 emit_store_dst(jd, iptr, d);
625 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
626 /* sx.val.l = constant */
628 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
629 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
631 if (IS_IMM32(iptr->sx.val.l))
632 M_LADD_IMM(iptr->sx.val.l, d);
634 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
635 M_LADD(REG_ITMP2, d);
637 emit_store_dst(jd, iptr, d);
640 case ICMD_ISUB: /* ..., 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);
646 M_INTMOVE(s1, REG_ITMP1);
647 M_ISUB(s2, REG_ITMP1);
648 M_INTMOVE(REG_ITMP1, d);
653 emit_store_dst(jd, iptr, d);
656 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
657 /* sx.val.i = constant */
659 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
660 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
662 M_ISUB_IMM(iptr->sx.val.i, d);
663 emit_store_dst(jd, iptr, d);
666 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
668 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
669 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
670 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
672 M_INTMOVE(s1, REG_ITMP1);
673 M_LSUB(s2, REG_ITMP1);
674 M_INTMOVE(REG_ITMP1, d);
679 emit_store_dst(jd, iptr, d);
682 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
683 /* sx.val.l = constant */
685 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
686 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
688 if (IS_IMM32(iptr->sx.val.l))
689 M_LSUB_IMM(iptr->sx.val.l, d);
691 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
692 M_LSUB(REG_ITMP2, d);
694 emit_store_dst(jd, iptr, d);
697 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
699 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
700 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
701 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
708 emit_store_dst(jd, iptr, d);
711 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
712 /* sx.val.i = constant */
714 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
715 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
716 if (iptr->sx.val.i == 2) {
720 M_IMUL_IMM(s1, iptr->sx.val.i, d);
721 emit_store_dst(jd, iptr, d);
724 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
726 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
727 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
728 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
735 emit_store_dst(jd, iptr, d);
738 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
739 /* sx.val.l = constant */
741 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
742 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
743 if (IS_IMM32(iptr->sx.val.l))
744 M_LMUL_IMM(s1, iptr->sx.val.l, d);
746 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
748 M_LMUL(REG_ITMP2, d);
750 emit_store_dst(jd, iptr, d);
753 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
755 var1 = VAROP(iptr->s1);
756 var2 = VAROP(iptr->sx.s23.s2);
757 dst = VAROP(iptr->dst);
759 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
760 if (IS_INMEMORY(var1->flags))
761 M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
763 M_INTMOVE(var1->vv.regoff, RAX);
765 if (IS_INMEMORY(var2->flags))
766 M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
768 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
773 codegen_add_arithmeticexception_ref(cd);
776 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
777 emit_jcc(cd, CC_NE, 4 + 6);
778 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
779 emit_jcc(cd, CC_E, 3 + 1 + 3); /* 6 bytes */
781 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
783 emit_idivl_reg(cd, REG_ITMP3);
785 if (IS_INMEMORY(dst->flags)) {
786 emit_mov_reg_membase(cd, RAX, REG_SP, dst->vv.regoff * 8);
787 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
790 M_INTMOVE(RAX, dst->vv.regoff);
792 if (dst->vv.regoff != RDX) {
793 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
798 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
800 var1 = VAROP(iptr->s1);
801 var2 = VAROP(iptr->sx.s23.s2);
802 dst = VAROP(iptr->dst);
804 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
805 if (IS_INMEMORY(var1->flags))
806 M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
808 M_INTMOVE(var1->vv.regoff, RAX);
810 if (IS_INMEMORY(var2->flags))
811 M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
813 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
818 codegen_add_arithmeticexception_ref(cd);
821 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
823 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
824 emit_jcc(cd, CC_NE, 2 + 4 + 6);
827 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
828 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
829 emit_jcc(cd, CC_E, 1 + 3); /* 6 bytes */
832 emit_idivl_reg(cd, REG_ITMP3);
834 if (IS_INMEMORY(dst->flags)) {
835 emit_mov_reg_membase(cd, RDX, REG_SP, dst->vv.regoff * 8);
836 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
839 M_INTMOVE(RDX, dst->vv.regoff);
841 if (dst->vv.regoff != RDX) {
842 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
847 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
848 /* sx.val.i = constant */
850 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
851 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
852 M_INTMOVE(s1, REG_ITMP1);
853 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
854 emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
855 emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
856 emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
857 emit_mov_reg_reg(cd, REG_ITMP1, d);
858 emit_store_dst(jd, iptr, d);
861 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
862 /* sx.val.i = constant */
864 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
865 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
866 M_INTMOVE(s1, REG_ITMP1);
867 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
868 emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
869 emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
870 emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
871 emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
872 emit_mov_reg_reg(cd, REG_ITMP1, d);
873 emit_store_dst(jd, iptr, d);
877 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
879 var1 = VAROP(iptr->s1);
880 var2 = VAROP(iptr->sx.s23.s2);
881 dst = VAROP(iptr->dst);
883 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
885 if (IS_INMEMORY(var1->flags))
886 M_LLD(RAX, REG_SP, var1->vv.regoff * 8);
888 M_INTMOVE(var1->vv.regoff, RAX);
890 if (IS_INMEMORY(var2->flags))
891 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
893 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
898 codegen_add_arithmeticexception_ref(cd);
901 /* check as described in jvm spec */
902 disp = dseg_adds8(cd, 0x8000000000000000LL);
903 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX);
905 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
906 M_BEQ(3 + 2 + 3); /* 6 bytes */
908 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
910 emit_idiv_reg(cd, REG_ITMP3);
912 if (IS_INMEMORY(dst->flags)) {
913 M_LST(RAX, REG_SP, dst->vv.regoff * 8);
914 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
917 M_INTMOVE(RAX, dst->vv.regoff);
919 if (dst->vv.regoff != RDX) {
920 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
925 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
927 var1 = VAROP(iptr->s1);
928 var2 = VAROP(iptr->sx.s23.s2);
929 dst = VAROP(iptr->dst);
931 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
933 if (IS_INMEMORY(var1->flags))
934 M_LLD(REG_ITMP1, REG_SP, var1->vv.regoff * 8);
936 M_INTMOVE(var1->vv.regoff, REG_ITMP1);
938 if (IS_INMEMORY(var2->flags))
939 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
941 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
943 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
944 M_INTMOVE(s1, REG_ITMP1);
945 s2 = emit_load_s2(jd, iptr, REG_ITMP3);
946 M_INTMOVE(s2, REG_ITMP3);
951 codegen_add_arithmeticexception_ref(cd);
954 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
956 /* check as described in jvm spec */
957 disp = dseg_adds8(cd, 0x8000000000000000LL);
958 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1);
962 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
964 M_LXOR(RDX, RDX); /* 3 bytes */
965 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
966 M_BEQ(2 + 3); /* 6 bytes */
969 emit_idiv_reg(cd, REG_ITMP3);
971 if (IS_INMEMORY(dst->flags)) {
972 M_LST(RDX, REG_SP, dst->vv.regoff * 8);
973 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
976 M_INTMOVE(RDX, dst->vv.regoff);
978 if (dst->vv.regoff != RDX) {
979 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
984 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
985 /* sx.val.i = constant */
987 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
988 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
989 M_INTMOVE(s1, REG_ITMP1);
990 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
991 emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
992 emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
993 emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
994 emit_mov_reg_reg(cd, REG_ITMP1, d);
995 emit_store_dst(jd, iptr, d);
998 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
999 /* sx.val.l = constant */
1001 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1002 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1003 M_INTMOVE(s1, REG_ITMP1);
1004 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1005 emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
1006 emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1007 emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
1008 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1009 emit_mov_reg_reg(cd, REG_ITMP1, d);
1010 emit_store_dst(jd, iptr, d);
1013 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1015 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1016 emit_ishift(jd, SHIFT_SHL, iptr);
1019 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1020 /* sx.val.i = constant */
1022 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1023 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1025 M_ISLL_IMM(iptr->sx.val.i, d);
1026 emit_store_dst(jd, iptr, d);
1029 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1031 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1032 emit_ishift(jd, SHIFT_SAR, iptr);
1035 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1036 /* sx.val.i = constant */
1038 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1039 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1041 M_ISRA_IMM(iptr->sx.val.i, d);
1042 emit_store_dst(jd, iptr, d);
1045 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1047 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1048 emit_ishift(jd, SHIFT_SHR, iptr);
1051 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1052 /* sx.val.i = constant */
1054 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1055 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1057 M_ISRL_IMM(iptr->sx.val.i, d);
1058 emit_store_dst(jd, iptr, d);
1061 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1063 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1064 emit_lshift(jd, SHIFT_SHL, iptr);
1067 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1068 /* sx.val.i = constant */
1070 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1071 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1073 M_LSLL_IMM(iptr->sx.val.i, d);
1074 emit_store_dst(jd, iptr, d);
1077 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1079 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1080 emit_lshift(jd, SHIFT_SAR, iptr);
1083 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1084 /* sx.val.i = constant */
1086 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1087 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1089 M_LSRA_IMM(iptr->sx.val.i, d);
1090 emit_store_dst(jd, iptr, d);
1093 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1095 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1096 emit_lshift(jd, SHIFT_SHR, iptr);
1099 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1100 /* sx.val.l = constant */
1102 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1103 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1105 M_LSRL_IMM(iptr->sx.val.i, d);
1106 emit_store_dst(jd, iptr, d);
1109 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1111 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1112 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1113 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1120 emit_store_dst(jd, iptr, d);
1123 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1124 /* sx.val.i = constant */
1126 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1127 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1129 M_IAND_IMM(iptr->sx.val.i, d);
1130 emit_store_dst(jd, iptr, d);
1133 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1135 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1136 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1137 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1144 emit_store_dst(jd, iptr, d);
1147 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1148 /* sx.val.l = constant */
1150 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1151 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1153 if (IS_IMM32(iptr->sx.val.l))
1154 M_LAND_IMM(iptr->sx.val.l, d);
1156 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1157 M_LAND(REG_ITMP2, d);
1159 emit_store_dst(jd, iptr, d);
1162 case ICMD_IOR: /* ..., 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_IORCONST: /* ..., value ==> ..., value | constant */
1177 /* sx.val.i = constant */
1179 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1180 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1182 M_IOR_IMM(iptr->sx.val.i, d);
1183 emit_store_dst(jd, iptr, d);
1186 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1188 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1189 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1190 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1197 emit_store_dst(jd, iptr, d);
1200 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1201 /* sx.val.l = constant */
1203 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1204 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1206 if (IS_IMM32(iptr->sx.val.l))
1207 M_LOR_IMM(iptr->sx.val.l, d);
1209 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1210 M_LOR(REG_ITMP2, d);
1212 emit_store_dst(jd, iptr, d);
1215 case ICMD_IXOR: /* ..., 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_IXORCONST: /* ..., value ==> ..., value ^ constant */
1230 /* sx.val.i = constant */
1232 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1233 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1235 M_IXOR_IMM(iptr->sx.val.i, d);
1236 emit_store_dst(jd, iptr, d);
1239 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1241 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1242 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1243 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1250 emit_store_dst(jd, iptr, d);
1253 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1254 /* sx.val.l = constant */
1256 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1257 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1259 if (IS_IMM32(iptr->sx.val.l))
1260 M_LXOR_IMM(iptr->sx.val.l, d);
1262 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1263 M_LXOR(REG_ITMP2, d);
1265 emit_store_dst(jd, iptr, d);
1269 /* floating operations ************************************************/
1271 case ICMD_FNEG: /* ..., value ==> ..., - value */
1273 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1274 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1275 disp = dseg_adds4(cd, 0x80000000);
1277 emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1278 emit_xorps_reg_reg(cd, REG_FTMP2, d);
1279 emit_store_dst(jd, iptr, d);
1282 case ICMD_DNEG: /* ..., value ==> ..., - value */
1284 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1285 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1286 disp = dseg_adds8(cd, 0x8000000000000000);
1288 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1289 emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1290 emit_store_dst(jd, iptr, d);
1293 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1295 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1296 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1297 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1304 emit_store_dst(jd, iptr, d);
1307 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1309 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1310 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1311 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1318 emit_store_dst(jd, iptr, d);
1321 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1323 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1324 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1325 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1327 M_FLTMOVE(s2, REG_FTMP2);
1332 emit_store_dst(jd, iptr, d);
1335 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1337 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1338 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1339 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1341 M_FLTMOVE(s2, REG_FTMP2);
1346 emit_store_dst(jd, iptr, d);
1349 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1351 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1352 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1353 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1360 emit_store_dst(jd, iptr, d);
1363 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1365 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1366 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1367 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1374 emit_store_dst(jd, iptr, d);
1377 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1379 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1380 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1381 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1383 M_FLTMOVE(s2, REG_FTMP2);
1388 emit_store_dst(jd, iptr, d);
1391 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1393 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1394 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1395 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1397 M_FLTMOVE(s2, REG_FTMP2);
1402 emit_store_dst(jd, iptr, d);
1405 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1407 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1408 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1410 emit_store_dst(jd, iptr, d);
1413 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1415 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1416 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1418 emit_store_dst(jd, iptr, d);
1421 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1423 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1424 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1426 emit_store_dst(jd, iptr, d);
1429 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1431 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1432 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1434 emit_store_dst(jd, iptr, d);
1437 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1439 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1440 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1442 M_ICMP_IMM(0x80000000, 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_f2i, REG_ITMP2);
1449 M_INTMOVE(REG_RESULT, d);
1450 emit_store_dst(jd, iptr, d);
1453 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1455 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1456 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1458 M_ICMP_IMM(0x80000000, d); /* corner cases */
1459 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1460 ((REG_RESULT == d) ? 0 : 3);
1462 M_FLTMOVE(s1, REG_FTMP1);
1463 M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1465 M_INTMOVE(REG_RESULT, d);
1466 emit_store_dst(jd, iptr, d);
1469 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1471 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1472 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1474 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1475 M_LCMP(REG_ITMP2, d); /* corner cases */
1476 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1477 ((REG_RESULT == d) ? 0 : 3);
1479 M_FLTMOVE(s1, REG_FTMP1);
1480 M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1482 M_INTMOVE(REG_RESULT, d);
1483 emit_store_dst(jd, iptr, d);
1486 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1488 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1489 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1491 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1492 M_LCMP(REG_ITMP2, d); /* corner cases */
1493 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1494 ((REG_RESULT == d) ? 0 : 3);
1496 M_FLTMOVE(s1, REG_FTMP1);
1497 M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1499 M_INTMOVE(REG_RESULT, d);
1500 emit_store_dst(jd, iptr, d);
1503 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1505 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1506 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1508 emit_store_dst(jd, iptr, d);
1511 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1513 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1514 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1516 emit_store_dst(jd, iptr, d);
1519 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1520 /* == => 0, < => 1, > => -1 */
1522 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1523 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1524 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1526 M_MOV_IMM(1, REG_ITMP1);
1527 M_MOV_IMM(-1, REG_ITMP2);
1528 emit_ucomiss_reg_reg(cd, s1, s2);
1529 M_CMOVB(REG_ITMP1, d);
1530 M_CMOVA(REG_ITMP2, d);
1531 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1532 emit_store_dst(jd, iptr, d);
1535 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1536 /* == => 0, < => 1, > => -1 */
1538 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1539 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1540 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1542 M_MOV_IMM(1, REG_ITMP1);
1543 M_MOV_IMM(-1, REG_ITMP2);
1544 emit_ucomiss_reg_reg(cd, s1, s2);
1545 M_CMOVB(REG_ITMP1, d);
1546 M_CMOVA(REG_ITMP2, d);
1547 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1548 emit_store_dst(jd, iptr, d);
1551 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1552 /* == => 0, < => 1, > => -1 */
1554 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1555 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1556 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1558 M_MOV_IMM(1, REG_ITMP1);
1559 M_MOV_IMM(-1, REG_ITMP2);
1560 emit_ucomisd_reg_reg(cd, s1, s2);
1561 M_CMOVB(REG_ITMP1, d);
1562 M_CMOVA(REG_ITMP2, d);
1563 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1564 emit_store_dst(jd, iptr, d);
1567 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1568 /* == => 0, < => 1, > => -1 */
1570 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1571 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1572 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1574 M_MOV_IMM(1, REG_ITMP1);
1575 M_MOV_IMM(-1, REG_ITMP2);
1576 emit_ucomisd_reg_reg(cd, s1, s2);
1577 M_CMOVB(REG_ITMP1, d);
1578 M_CMOVA(REG_ITMP2, d);
1579 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1580 emit_store_dst(jd, iptr, d);
1584 /* memory operations **************************************************/
1586 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1588 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1589 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1590 gen_nullptr_check(s1);
1591 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1592 emit_store_dst(jd, iptr, d);
1595 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1597 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1598 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1599 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1600 if (INSTRUCTION_MUST_CHECK(iptr)) {
1601 gen_nullptr_check(s1);
1604 emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
1605 emit_store_dst(jd, iptr, d);
1608 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1610 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1611 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1612 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1613 if (INSTRUCTION_MUST_CHECK(iptr)) {
1614 gen_nullptr_check(s1);
1617 emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
1618 emit_store_dst(jd, iptr, d);
1621 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1623 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1624 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1625 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1626 if (INSTRUCTION_MUST_CHECK(iptr)) {
1627 gen_nullptr_check(s1);
1630 emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
1631 emit_store_dst(jd, iptr, d);
1634 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1636 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1637 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1638 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1639 if (INSTRUCTION_MUST_CHECK(iptr)) {
1640 gen_nullptr_check(s1);
1643 emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
1644 emit_store_dst(jd, iptr, d);
1647 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1649 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1650 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1651 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1652 if (INSTRUCTION_MUST_CHECK(iptr)) {
1653 gen_nullptr_check(s1);
1656 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1657 emit_store_dst(jd, iptr, d);
1660 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1662 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1663 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1664 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1665 if (INSTRUCTION_MUST_CHECK(iptr)) {
1666 gen_nullptr_check(s1);
1669 emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1670 emit_store_dst(jd, iptr, d);
1673 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1675 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1676 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1677 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1678 if (INSTRUCTION_MUST_CHECK(iptr)) {
1679 gen_nullptr_check(s1);
1682 emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1683 emit_store_dst(jd, iptr, d);
1686 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1688 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1689 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1690 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1691 if (INSTRUCTION_MUST_CHECK(iptr)) {
1692 gen_nullptr_check(s1);
1695 emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
1696 emit_store_dst(jd, iptr, d);
1700 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1702 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1703 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1704 if (INSTRUCTION_MUST_CHECK(iptr)) {
1705 gen_nullptr_check(s1);
1708 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1709 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1712 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1714 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1715 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1716 if (INSTRUCTION_MUST_CHECK(iptr)) {
1717 gen_nullptr_check(s1);
1720 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1721 emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
1724 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1726 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1727 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1728 if (INSTRUCTION_MUST_CHECK(iptr)) {
1729 gen_nullptr_check(s1);
1732 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1733 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1736 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1738 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1739 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1740 if (INSTRUCTION_MUST_CHECK(iptr)) {
1741 gen_nullptr_check(s1);
1744 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1745 emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
1748 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1750 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1751 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1752 if (INSTRUCTION_MUST_CHECK(iptr)) {
1753 gen_nullptr_check(s1);
1756 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1757 emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
1760 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1762 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1763 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1764 if (INSTRUCTION_MUST_CHECK(iptr)) {
1765 gen_nullptr_check(s1);
1768 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1769 emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
1772 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1774 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1775 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1776 if (INSTRUCTION_MUST_CHECK(iptr)) {
1777 gen_nullptr_check(s1);
1780 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1781 emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
1784 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1786 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1787 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1788 if (INSTRUCTION_MUST_CHECK(iptr)) {
1789 gen_nullptr_check(s1);
1792 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1796 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
1800 codegen_add_arraystoreexception_ref(cd);
1802 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1803 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1804 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1805 emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
1809 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1811 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1812 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1813 if (INSTRUCTION_MUST_CHECK(iptr)) {
1814 gen_nullptr_check(s1);
1817 emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1820 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1822 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1823 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1824 if (INSTRUCTION_MUST_CHECK(iptr)) {
1825 gen_nullptr_check(s1);
1828 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
1831 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1833 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1834 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1835 if (INSTRUCTION_MUST_CHECK(iptr)) {
1836 gen_nullptr_check(s1);
1839 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1842 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1844 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1845 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1846 if (INSTRUCTION_MUST_CHECK(iptr)) {
1847 gen_nullptr_check(s1);
1850 emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
1853 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1855 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1856 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1857 if (INSTRUCTION_MUST_CHECK(iptr)) {
1858 gen_nullptr_check(s1);
1862 if (IS_IMM32(iptr->sx.s23.s3.constval)) {
1863 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
1865 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
1866 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
1870 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1872 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1873 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1874 if (INSTRUCTION_MUST_CHECK(iptr)) {
1875 gen_nullptr_check(s1);
1878 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
1882 case ICMD_GETSTATIC: /* ... ==> ..., value */
1884 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1885 uf = iptr->sx.s23.s3.uf;
1886 fieldtype = uf->fieldref->parseddesc.fd->type;
1887 disp = dseg_addaddress(cd, NULL);
1888 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
1890 /* must be calculated before codegen_add_patch_ref */
1893 disp -= PATCHER_CALL_SIZE;
1895 /* PROFILE_CYCLE_STOP; */
1897 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1899 /* PROFILE_CYCLE_START; */
1902 fi = iptr->sx.s23.s3.fmiref->p.field;
1903 fieldtype = fi->type;
1904 disp = dseg_addaddress(cd, &(fi->value));
1905 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
1907 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1910 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
1913 disp -= PATCHER_CALL_SIZE;
1915 PROFILE_CYCLE_START;
1919 /* This approach is much faster than moving the field
1920 address inline into a register. */
1922 M_ALD(REG_ITMP1, RIP, disp);
1924 switch (fieldtype) {
1926 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1927 M_ILD(d, REG_ITMP1, 0);
1931 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1932 M_LLD(d, REG_ITMP1, 0);
1935 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1936 M_FLD(d, REG_ITMP1, 0);
1939 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1940 M_DLD(d, REG_ITMP1, 0);
1943 emit_store_dst(jd, iptr, d);
1946 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1948 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1949 uf = iptr->sx.s23.s3.uf;
1950 fieldtype = uf->fieldref->parseddesc.fd->type;
1951 disp = dseg_addaddress(cd, NULL);
1952 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
1954 /* must be calculated before codegen_add_patch_ref */
1957 disp -= PATCHER_CALL_SIZE;
1959 /* PROFILE_CYCLE_STOP; */
1961 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1963 /* PROFILE_CYCLE_START; */
1966 fi = iptr->sx.s23.s3.fmiref->p.field;
1967 fieldtype = fi->type;
1968 disp = dseg_addaddress(cd, &(fi->value));
1969 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
1971 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1974 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
1977 disp -= PATCHER_CALL_SIZE;
1979 PROFILE_CYCLE_START;
1983 /* This approach is much faster than moving the field
1984 address inline into a register. */
1986 M_ALD(REG_ITMP1, RIP, disp);
1988 switch (fieldtype) {
1990 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1991 M_IST(s1, REG_ITMP1, 0);
1995 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1996 M_LST(s1, REG_ITMP1, 0);
1999 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
2000 M_FST(s1, REG_ITMP1, 0);
2003 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
2004 M_DST(s1, REG_ITMP1, 0);
2009 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2010 /* val = value (in current instruction) */
2011 /* following NOP) */
2013 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2014 uf = iptr->sx.s23.s3.uf;
2015 fieldtype = uf->fieldref->parseddesc.fd->type;
2016 disp = dseg_addaddress(cd, NULL);
2017 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2019 /* must be calculated before codegen_add_patch_ref */
2022 disp -= PATCHER_CALL_SIZE;
2025 /* PROFILE_CYCLE_STOP; */
2027 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2029 /* PROFILE_CYCLE_START; */
2032 fi = iptr->sx.s23.s3.fmiref->p.field;
2033 fieldtype = fi->type;
2034 disp = dseg_addaddress(cd, &(fi->value));
2035 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2037 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2040 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
2043 disp -= PATCHER_CALL_SIZE;
2045 PROFILE_CYCLE_START;
2049 /* This approach is much faster than moving the field
2050 address inline into a register. */
2052 M_ALD(REG_ITMP1, RIP, disp);
2054 switch (fieldtype) {
2057 M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
2062 if (IS_IMM32(iptr->sx.s23.s2.constval))
2063 M_LST_IMM32(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
2065 M_IST_IMM(iptr->sx.s23.s2.constval, REG_ITMP1, 0);
2066 M_IST_IMM(iptr->sx.s23.s2.constval >> 32, REG_ITMP1, 4);
2072 case ICMD_GETFIELD: /* ... ==> ..., value */
2074 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2075 gen_nullptr_check(s1);
2077 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2078 uf = iptr->sx.s23.s3.uf;
2079 fieldtype = uf->fieldref->parseddesc.fd->type;
2082 /* PROFILE_CYCLE_STOP; */
2084 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
2086 /* PROFILE_CYCLE_START; */
2089 fi = iptr->sx.s23.s3.fmiref->p.field;
2090 fieldtype = fi->type;
2094 switch (fieldtype) {
2096 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2097 M_ILD32(d, s1, disp);
2101 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
2102 M_LLD32(d, s1, disp);
2105 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2106 M_FLD32(d, s1, disp);
2109 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2110 M_DLD32(d, s1, disp);
2113 emit_store_dst(jd, iptr, d);
2116 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2118 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2119 gen_nullptr_check(s1);
2121 s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2123 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2124 uf = iptr->sx.s23.s3.uf;
2125 fieldtype = uf->fieldref->parseddesc.fd->type;
2128 /* PROFILE_CYCLE_STOP; */
2130 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
2132 /* PROFILE_CYCLE_START; */
2135 fi = iptr->sx.s23.s3.fmiref->p.field;
2136 fieldtype = fi->type;
2140 switch (fieldtype) {
2142 M_IST32(s2, s1, disp);
2146 M_LST32(s2, s1, disp);
2149 M_FST32(s2, s1, disp);
2152 M_DST32(s2, s1, disp);
2157 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2158 /* val = value (in current instruction) */
2159 /* following NOP) */
2161 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2162 gen_nullptr_check(s1);
2164 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2165 uf = iptr->sx.s23.s3.uf;
2166 fieldtype = uf->fieldref->parseddesc.fd->type;
2169 /* PROFILE_CYCLE_STOP; */
2171 codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
2173 /* PROFILE_CYCLE_START; */
2176 fi = iptr->sx.s23.s3.fmiref->p.field;
2177 fieldtype = fi->type;
2181 switch (fieldtype) {
2184 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2189 /* XXX why no check for IS_IMM32? */
2190 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2191 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2197 /* branch operations **************************************************/
2199 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2201 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2202 M_INTMOVE(s1, REG_ITMP1_XPTR);
2206 #ifdef ENABLE_VERIFIER
2207 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2208 uc = iptr->sx.s23.s2.uc;
2210 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2212 #endif /* ENABLE_VERIFIER */
2214 M_CALL_IMM(0); /* passing exception pc */
2215 M_POP(REG_ITMP2_XPC);
2217 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2221 case ICMD_GOTO: /* ... ==> ... */
2222 case ICMD_RET: /* ... ==> ... */
2225 codegen_addreference(cd, iptr->dst.block);
2228 case ICMD_JSR: /* ... ==> ... */
2231 codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block);
2234 case ICMD_IFNULL: /* ..., value ==> ... */
2236 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2239 codegen_addreference(cd, iptr->dst.block);
2242 case ICMD_IFNONNULL: /* ..., value ==> ... */
2244 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2247 codegen_addreference(cd, iptr->dst.block);
2250 case ICMD_IFEQ: /* ..., value ==> ... */
2252 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2253 M_ICMP_IMM(iptr->sx.val.i, s1);
2255 codegen_addreference(cd, iptr->dst.block);
2258 case ICMD_IFLT: /* ..., value ==> ... */
2260 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2261 M_ICMP_IMM(iptr->sx.val.i, s1);
2263 codegen_addreference(cd, iptr->dst.block);
2266 case ICMD_IFLE: /* ..., value ==> ... */
2268 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2269 M_ICMP_IMM(iptr->sx.val.i, s1);
2271 codegen_addreference(cd, iptr->dst.block);
2274 case ICMD_IFNE: /* ..., value ==> ... */
2276 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2277 M_ICMP_IMM(iptr->sx.val.i, s1);
2279 codegen_addreference(cd, iptr->dst.block);
2282 case ICMD_IFGT: /* ..., value ==> ... */
2284 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2285 M_ICMP_IMM(iptr->sx.val.i, s1);
2287 codegen_addreference(cd, iptr->dst.block);
2290 case ICMD_IFGE: /* ..., value ==> ... */
2292 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2293 M_ICMP_IMM(iptr->sx.val.i, s1);
2295 codegen_addreference(cd, iptr->dst.block);
2298 case ICMD_IF_LEQ: /* ..., value ==> ... */
2300 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2301 if (IS_IMM32(iptr->sx.val.l))
2302 M_LCMP_IMM(iptr->sx.val.l, s1);
2304 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2305 M_LCMP(REG_ITMP2, s1);
2308 codegen_addreference(cd, iptr->dst.block);
2311 case ICMD_IF_LLT: /* ..., value ==> ... */
2313 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2314 if (IS_IMM32(iptr->sx.val.l))
2315 M_LCMP_IMM(iptr->sx.val.l, s1);
2317 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2318 M_LCMP(REG_ITMP2, s1);
2321 codegen_addreference(cd, iptr->dst.block);
2324 case ICMD_IF_LLE: /* ..., value ==> ... */
2326 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2327 if (IS_IMM32(iptr->sx.val.l))
2328 M_LCMP_IMM(iptr->sx.val.l, s1);
2330 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2331 M_LCMP(REG_ITMP2, s1);
2334 codegen_addreference(cd, iptr->dst.block);
2337 case ICMD_IF_LNE: /* ..., value ==> ... */
2339 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2340 if (IS_IMM32(iptr->sx.val.l))
2341 M_LCMP_IMM(iptr->sx.val.l, s1);
2343 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2344 M_LCMP(REG_ITMP2, s1);
2347 codegen_addreference(cd, iptr->dst.block);
2350 case ICMD_IF_LGT: /* ..., value ==> ... */
2352 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2353 if (IS_IMM32(iptr->sx.val.l))
2354 M_LCMP_IMM(iptr->sx.val.l, s1);
2356 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2357 M_LCMP(REG_ITMP2, s1);
2360 codegen_addreference(cd, iptr->dst.block);
2363 case ICMD_IF_LGE: /* ..., value ==> ... */
2365 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2366 if (IS_IMM32(iptr->sx.val.l))
2367 M_LCMP_IMM(iptr->sx.val.l, s1);
2369 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2370 M_LCMP(REG_ITMP2, s1);
2373 codegen_addreference(cd, iptr->dst.block);
2376 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2378 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2379 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2382 codegen_addreference(cd, iptr->dst.block);
2385 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2386 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2388 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2389 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2392 codegen_addreference(cd, iptr->dst.block);
2395 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2397 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2398 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2401 codegen_addreference(cd, iptr->dst.block);
2404 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2405 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2407 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2408 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2411 codegen_addreference(cd, iptr->dst.block);
2414 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2416 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2417 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2420 codegen_addreference(cd, iptr->dst.block);
2423 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2425 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2426 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2429 codegen_addreference(cd, iptr->dst.block);
2432 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2434 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2435 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2438 codegen_addreference(cd, iptr->dst.block);
2441 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2443 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2444 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2447 codegen_addreference(cd, iptr->dst.block);
2450 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2452 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2453 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2456 codegen_addreference(cd, iptr->dst.block);
2459 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2461 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2462 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2465 codegen_addreference(cd, iptr->dst.block);
2468 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2470 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2471 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2474 codegen_addreference(cd, iptr->dst.block);
2477 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2479 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2480 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2483 codegen_addreference(cd, iptr->dst.block);
2486 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2489 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2490 M_INTMOVE(s1, REG_RESULT);
2491 goto nowperformreturn;
2493 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2495 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2496 M_INTMOVE(s1, REG_RESULT);
2498 #ifdef ENABLE_VERIFIER
2499 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2500 uc = iptr->sx.s23.s2.uc;
2504 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2506 PROFILE_CYCLE_START;
2508 #endif /* ENABLE_VERIFIER */
2509 goto nowperformreturn;
2511 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2514 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2515 M_FLTMOVE(s1, REG_FRESULT);
2516 goto nowperformreturn;
2518 case ICMD_RETURN: /* ... ==> ... */
2524 p = cd->stackframesize;
2526 #if !defined(NDEBUG)
2527 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2528 emit_verbosecall_exit(jd);
2529 #endif /* !defined(NDEBUG) */
2531 #if defined(ENABLE_THREADS)
2532 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2533 M_ALD(REG_A0, REG_SP, rd->memuse * 8);
2535 /* we need to save the proper return value */
2536 switch (iptr->opc) {
2540 M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
2544 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
2548 M_MOV_IMM(LOCK_monitor_exit, REG_ITMP1);
2551 /* and now restore the proper return value */
2552 switch (iptr->opc) {
2556 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2560 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2566 /* restore saved registers */
2568 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2569 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2571 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2572 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2575 /* deallocate stack */
2577 if (cd->stackframesize)
2578 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
2580 /* generate method profiling code */
2589 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2592 branch_target_t *table;
2594 table = iptr->dst.table;
2596 l = iptr->sx.s23.s2.tablelow;
2597 i = iptr->sx.s23.s3.tablehigh;
2599 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2600 M_INTMOVE(s1, REG_ITMP1);
2603 M_ISUB_IMM(l, REG_ITMP1);
2605 /* number of targets */
2609 M_ICMP_IMM(i - 1, REG_ITMP1);
2612 codegen_addreference(cd, table[0].block); /* default target */
2614 /* build jump table top down and use address of lowest entry */
2619 dseg_addtarget(cd, table->block);
2623 /* length of dataseg after last dseg_addtarget is used
2626 M_MOV_IMM(0, REG_ITMP2);
2628 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2634 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2637 lookup_target_t *lookup;
2639 lookup = iptr->dst.lookup;
2641 i = iptr->sx.s23.s2.lookupcount;
2643 MCODECHECK(8 + ((7 + 6) * i) + 5);
2644 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2647 M_ICMP_IMM(lookup->value, s1);
2649 codegen_addreference(cd, lookup->target.block);
2655 codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block);
2660 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2662 bte = iptr->sx.s23.s3.bte;
2666 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2668 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2669 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2670 case ICMD_INVOKEINTERFACE:
2672 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2674 um = iptr->sx.s23.s3.um;
2675 md = um->methodref->parseddesc.md;
2678 lm = iptr->sx.s23.s3.fmiref->p.method;
2680 md = lm->parseddesc;
2684 s3 = md->paramcount;
2686 MCODECHECK((20 * s3) + 128);
2688 /* copy arguments to registers or stack location */
2690 for (s3 = s3 - 1; s3 >= 0; s3--) {
2691 var = VAR(iptr->sx.s23.s2.args[s3]);
2693 /* Already Preallocated (ARGVAR) ? */
2694 if (var->flags & PREALLOC)
2697 if (IS_INT_LNG_TYPE(var->type)) {
2698 if (!md->params[s3].inmemory) {
2699 s1 = rd->argintregs[md->params[s3].regoff];
2700 d = emit_load(jd, iptr, var, s1);
2704 d = emit_load(jd, iptr, var, REG_ITMP1);
2705 M_LST(d, REG_SP, md->params[s3].regoff * 8);
2709 if (!md->params[s3].inmemory) {
2710 s1 = rd->argfltregs[md->params[s3].regoff];
2711 d = emit_load(jd, iptr, var, s1);
2715 d = emit_load(jd, iptr, var, REG_FTMP1);
2717 if (IS_2_WORD_TYPE(var->type))
2718 M_DST(d, REG_SP, md->params[s3].regoff * 8);
2720 M_FST(d, REG_SP, md->params[s3].regoff * 8);
2725 /* generate method profiling code */
2729 switch (iptr->opc) {
2731 M_MOV_IMM(bte->fp, REG_ITMP1);
2734 if (INSTRUCTION_MUST_CHECK(iptr)) {
2737 codegen_add_fillinstacktrace_ref(cd);
2741 case ICMD_INVOKESPECIAL:
2744 codegen_add_nullpointerexception_ref(cd);
2748 case ICMD_INVOKESTATIC:
2750 disp = dseg_addaddress(cd, NULL);
2751 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2753 /* must be calculated before codegen_add_patch_ref */
2756 disp -= PATCHER_CALL_SIZE;
2758 codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
2764 disp = dseg_addaddress(cd, lm->stubroutine);
2765 disp = -((cd->mcodeptr + 7) - cd->mcodebase) + disp;
2767 /* a = (ptrint) lm->stubroutine; */
2770 /* M_MOV_IMM(a, REG_ITMP2); */
2771 M_ALD(REG_ITMP2, RIP, disp);
2775 case ICMD_INVOKEVIRTUAL:
2776 gen_nullptr_check(REG_A0);
2779 codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
2784 s1 = OFFSET(vftbl_t, table[0]) +
2785 sizeof(methodptr) * lm->vftblindex;
2787 M_ALD(REG_METHODPTR, REG_A0,
2788 OFFSET(java_objectheader, vftbl));
2789 M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
2793 case ICMD_INVOKEINTERFACE:
2794 gen_nullptr_check(REG_A0);
2797 codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
2803 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2804 sizeof(methodptr) * lm->class->index;
2806 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2809 M_ALD(REG_METHODPTR, REG_A0,
2810 OFFSET(java_objectheader, vftbl));
2811 M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
2812 M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
2817 /* generate method profiling code */
2819 PROFILE_CYCLE_START;
2821 /* store return value */
2823 d = md->returntype.type;
2825 if (d != TYPE_VOID) {
2826 if (IS_INT_LNG_TYPE(d)) {
2827 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2828 M_INTMOVE(REG_RESULT, s1);
2831 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2832 M_FLTMOVE(REG_FRESULT, s1);
2834 emit_store_dst(jd, iptr, s1);
2839 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2841 /* val.a: (classinfo *) superclass */
2843 /* superclass is an interface:
2845 * OK if ((sub == NULL) ||
2846 * (sub->vftbl->interfacetablelength > super->index) &&
2847 * (sub->vftbl->interfacetable[-super->index] != NULL));
2849 * superclass is a class:
2851 * OK if ((sub == NULL) || (0
2852 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2853 * super->vftbl->diffval));
2856 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2857 /* object type cast-check */
2860 vftbl_t *supervftbl;
2863 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2869 super = iptr->sx.s23.s3.c.cls;
2870 superindex = super->index;
2871 supervftbl = super->vftbl;
2874 #if defined(ENABLE_THREADS)
2875 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2877 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2879 /* calculate interface checkcast code size */
2881 s2 = 3; /* mov_membase_reg */
2882 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
2884 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub imm32 */ +
2885 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
2886 3 /* test */ + 6 /* jcc */;
2889 s2 += (opt_shownops ? 5 : 0);
2891 /* calculate class checkcast code size */
2893 s3 = 3; /* mov_membase_reg */
2894 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
2895 s3 += 10 /* mov_imm_reg */ + 3 + 4 /* movl_membase32_reg */;
2898 if (s1 != REG_ITMP1) {
2899 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
2900 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
2901 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
2902 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
2908 s3 += 3 + 4 /* movl_membase32_reg */ + 3 /* sub */ +
2909 10 /* mov_imm_reg */ + 3 /* movl_membase_reg */;
2910 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2913 s3 += 3 /* cmp */ + 6 /* jcc */;
2916 s3 += (opt_shownops ? 5 : 0);
2918 /* if class is not resolved, check which code to call */
2920 if (super == NULL) {
2922 M_BEQ(6 + (opt_shownops ? 5 : 0) + 7 + 6 + s2 + 5 + s3);
2924 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2925 iptr->sx.s23.s3.c.ref, 0);
2927 M_IMOV_IMM(0, REG_ITMP2); /* super->flags */
2928 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
2932 /* interface checkcast code */
2934 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2935 if (super != NULL) {
2940 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2942 if (super == NULL) {
2943 codegen_add_patch_ref(cd,
2944 PATCHER_checkcast_instanceof_interface,
2945 iptr->sx.s23.s3.c.ref,
2949 emit_movl_membase32_reg(cd, REG_ITMP2,
2950 OFFSET(vftbl_t, interfacetablelength),
2952 /* XXX TWISTI: should this be int arithmetic? */
2953 M_LSUB_IMM32(superindex, REG_ITMP3);
2956 codegen_add_classcastexception_ref(cd, s1);
2957 emit_mov_membase32_reg(cd, REG_ITMP2,
2958 OFFSET(vftbl_t, interfacetable[0]) -
2959 superindex * sizeof(methodptr*),
2963 codegen_add_classcastexception_ref(cd, s1);
2969 /* class checkcast code */
2971 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2972 if (super != NULL) {
2977 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2979 if (super == NULL) {
2980 codegen_add_patch_ref(cd, PATCHER_checkcast_class,
2981 iptr->sx.s23.s3.c.ref,
2985 M_MOV_IMM(supervftbl, REG_ITMP3);
2986 #if defined(ENABLE_THREADS)
2987 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
2989 emit_movl_membase32_reg(cd, REG_ITMP2,
2990 OFFSET(vftbl_t, baseval),
2992 /* if (s1 != REG_ITMP1) { */
2993 /* emit_movl_membase_reg(cd, REG_ITMP3, */
2994 /* OFFSET(vftbl_t, baseval), */
2996 /* emit_movl_membase_reg(cd, REG_ITMP3, */
2997 /* OFFSET(vftbl_t, diffval), */
2999 /* #if defined(ENABLE_THREADS) */
3000 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3002 /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
3005 emit_movl_membase32_reg(cd, REG_ITMP3,
3006 OFFSET(vftbl_t, baseval),
3008 M_LSUB(REG_ITMP3, REG_ITMP2);
3009 M_MOV_IMM(supervftbl, REG_ITMP3);
3010 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3012 #if defined(ENABLE_THREADS)
3013 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3015 M_LCMP(REG_ITMP3, REG_ITMP2);
3016 M_BA(0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
3017 codegen_add_classcastexception_ref(cd, s1);
3020 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
3023 /* array type cast-check */
3025 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
3026 M_INTMOVE(s1, REG_A0);
3028 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3029 codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
3030 iptr->sx.s23.s3.c.ref, 0);
3033 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3034 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
3037 /* s1 may have been destroyed over the function call */
3038 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
3041 codegen_add_classcastexception_ref(cd, s1);
3043 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3047 emit_store_dst(jd, iptr, d);
3050 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3052 /* val.a: (classinfo *) superclass */
3054 /* superclass is an interface:
3056 * return (sub != NULL) &&
3057 * (sub->vftbl->interfacetablelength > super->index) &&
3058 * (sub->vftbl->interfacetable[-super->index] != NULL);
3060 * superclass is a class:
3062 * return ((sub != NULL) && (0
3063 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3064 * super->vftbl->diffvall));
3069 vftbl_t *supervftbl;
3072 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3078 super = iptr->sx.s23.s3.c.cls;
3079 superindex = super->index;
3080 supervftbl = super->vftbl;
3083 #if defined(ENABLE_THREADS)
3084 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3087 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3088 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3090 M_INTMOVE(s1, REG_ITMP1);
3094 /* calculate interface instanceof code size */
3096 s2 = 3; /* mov_membase_reg */
3097 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3098 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub_imm32 */ +
3099 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3100 3 /* test */ + 4 /* setcc */;
3103 s2 += (opt_shownops ? 5 : 0);
3105 /* calculate class instanceof code size */
3107 s3 = 3; /* mov_membase_reg */
3108 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3109 s3 += 10; /* mov_imm_reg */
3110 s3 += 2; /* movl_membase_reg - only if REG_ITMP1 == RAX */
3111 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3112 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3113 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3114 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3115 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3116 s3 += 3 /* sub */ + 3 /* xor */ + 3 /* cmp */ + 4 /* setcc */;
3119 s3 += (opt_shownops ? 5 : 0);
3121 emit_alu_reg_reg(cd, ALU_XOR, d, d);
3123 /* if class is not resolved, check which code to call */
3125 if (super == NULL) {
3126 emit_test_reg_reg(cd, s1, s1);
3127 emit_jcc(cd, CC_Z, (6 + (opt_shownops ? 5 : 0) +
3128 7 + 6 + s2 + 5 + s3));
3130 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
3131 iptr->sx.s23.s3.c.ref, 0);
3133 emit_movl_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
3134 emit_alul_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
3135 emit_jcc(cd, CC_Z, s2 + 5);
3138 /* interface instanceof code */
3140 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3141 if (super != NULL) {
3142 emit_test_reg_reg(cd, s1, s1);
3143 emit_jcc(cd, CC_Z, s2);
3146 emit_mov_membase_reg(cd, s1,
3147 OFFSET(java_objectheader, vftbl),
3150 if (super == NULL) {
3151 codegen_add_patch_ref(cd,
3152 PATCHER_checkcast_instanceof_interface,
3153 iptr->sx.s23.s3.c.ref, 0);
3156 emit_movl_membase32_reg(cd, REG_ITMP1,
3157 OFFSET(vftbl_t, interfacetablelength),
3159 emit_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
3160 emit_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
3162 a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
3164 emit_jcc(cd, CC_LE, a);
3165 emit_mov_membase32_reg(cd, REG_ITMP1,
3166 OFFSET(vftbl_t, interfacetable[0]) -
3167 superindex * sizeof(methodptr*),
3169 emit_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3170 emit_setcc_reg(cd, CC_NE, d);
3173 emit_jmp_imm(cd, s3);
3176 /* class instanceof code */
3178 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3179 if (super != NULL) {
3180 emit_test_reg_reg(cd, s1, s1);
3181 emit_jcc(cd, CC_E, s3);
3184 emit_mov_membase_reg(cd, s1,
3185 OFFSET(java_objectheader, vftbl),
3188 if (super == NULL) {
3189 codegen_add_patch_ref(cd, PATCHER_instanceof_class,
3190 iptr->sx.s23.s3.c.ref, 0);
3193 emit_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
3194 #if defined(ENABLE_THREADS)
3195 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3197 emit_movl_membase_reg(cd, REG_ITMP1,
3198 OFFSET(vftbl_t, baseval),
3200 emit_movl_membase_reg(cd, REG_ITMP2,
3201 OFFSET(vftbl_t, diffval),
3203 emit_movl_membase_reg(cd, REG_ITMP2,
3204 OFFSET(vftbl_t, baseval),
3206 #if defined(ENABLE_THREADS)
3207 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3209 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
3210 emit_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
3211 emit_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
3212 emit_setcc_reg(cd, CC_BE, d);
3214 emit_store_dst(jd, iptr, d);
3218 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3220 /* check for negative sizes and copy sizes to stack if necessary */
3222 MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3224 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3226 /* copy SAVEDVAR sizes to stack */
3227 var = VAR(iptr->sx.s23.s2.args[s1]);
3229 /* Already Preallocated? */
3230 if (!(var->flags & PREALLOC)) {
3231 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3232 M_LST(s2, REG_SP, s1 * 8);
3236 /* is a patcher function set? */
3238 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3239 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
3240 iptr->sx.s23.s3.c.ref, 0);
3243 /* a0 = dimension count */
3245 M_MOV_IMM(iptr->s1.argcount, REG_A0);
3247 /* a1 = classinfo */
3249 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3251 /* a2 = pointer to dimensions = stack pointer */
3253 M_MOV(REG_SP, REG_A2);
3255 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3258 /* check for exception before result assignment */
3262 codegen_add_fillinstacktrace_ref(cd);
3264 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3265 M_INTMOVE(REG_RESULT, s1);
3266 emit_store_dst(jd, iptr, s1);
3270 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3274 } /* for instruction */
3276 MCODECHECK(512); /* XXX require a lower number? */
3278 /* At the end of a basic block we may have to append some nops,
3279 because the patcher stub calling code might be longer than the
3280 actual instruction. So codepatching does not change the
3281 following block unintentionally. */
3283 if (cd->mcodeptr < cd->lastmcodeptr) {
3284 while (cd->mcodeptr < cd->lastmcodeptr) {
3289 } /* if (bptr -> flags >= BBREACHED) */
3290 } /* for basic block */
3292 dseg_createlinenumbertable(cd);
3294 /* generate stubs */
3296 emit_exception_stubs(jd);
3297 emit_patcher_stubs(jd);
3299 emit_replacement_stubs(jd);
3304 /* everything's ok */
3310 /* createcompilerstub **********************************************************
3312 Creates a stub routine which calls the compiler.
3314 *******************************************************************************/
3316 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
3317 #define COMPILERSTUB_CODESIZE 7 + 7 + 3
3319 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
3322 u1 *createcompilerstub(methodinfo *m)
3324 u1 *s; /* memory to hold the stub */
3330 s = CNEW(u1, COMPILERSTUB_SIZE);
3332 /* set data pointer and code pointer */
3335 s = s + COMPILERSTUB_DATASIZE;
3337 /* mark start of dump memory area */
3339 dumpsize = dump_size();
3341 cd = DNEW(codegendata);
3344 /* Store the codeinfo pointer in the same place as in the
3345 methodheader for compiled methods. */
3347 code = code_codeinfo_new(m);
3349 d[0] = (ptrint) asm_call_jit_compiler;
3351 d[2] = (ptrint) code;
3353 /* code for the stub */
3355 M_ALD(REG_ITMP1, RIP, -(7 * 1 + 2 * SIZEOF_VOID_P)); /* methodinfo */
3356 M_ALD(REG_ITMP3, RIP, -(7 * 2 + 3 * SIZEOF_VOID_P)); /* compiler pointer */
3359 #if defined(ENABLE_STATISTICS)
3361 count_cstub_len += COMPILERSTUB_SIZE;
3364 /* release dump area */
3366 dump_release(dumpsize);
3372 /* createnativestub ************************************************************
3374 Creates a stub routine which calls a native method.
3376 *******************************************************************************/
3378 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3386 s4 i, j; /* count variables */
3390 /* get required compiler data */
3397 /* initialize variables */
3400 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3402 /* calculate stack frame size */
3404 cd->stackframesize =
3405 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3406 sizeof(localref_table) / SIZEOF_VOID_P +
3407 INT_ARG_CNT + FLT_ARG_CNT +
3408 1 + /* functionptr, TODO: store in data segment */
3411 cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */
3413 /* create method header */
3415 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
3416 (void) dseg_adds4(cd, cd->stackframesize * 8); /* FrameSize */
3417 (void) dseg_adds4(cd, 0); /* IsSync */
3418 (void) dseg_adds4(cd, 0); /* IsLeaf */
3419 (void) dseg_adds4(cd, 0); /* IntSave */
3420 (void) dseg_adds4(cd, 0); /* FltSave */
3421 (void) dseg_addlinenumbertablesize(cd);
3422 (void) dseg_adds4(cd, 0); /* ExTableSize */
3424 /* generate native method profiling code */
3426 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3427 /* count frequency */
3429 M_MOV_IMM(code, REG_ITMP3);
3430 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3433 /* generate stub code */
3435 M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
3437 #if !defined(NDEBUG)
3438 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3439 emit_verbosecall_enter(jd);
3442 /* get function address (this must happen before the stackframeinfo) */
3444 #if !defined(WITH_STATIC_CLASSPATH)
3446 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, 0);
3449 M_MOV_IMM(f, REG_ITMP3);
3452 /* save integer and float argument registers */
3454 for (i = 0, j = 0; i < md->paramcount; i++) {
3455 if (!md->params[i].inmemory) {
3456 s1 = md->params[i].regoff;
3458 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
3459 M_LST(rd->argintregs[s1], REG_SP, j * 8);
3461 M_DST(rd->argfltregs[s1], REG_SP, j * 8);
3467 M_AST(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
3469 /* create dynamic stack info */
3471 M_ALEA(REG_SP, cd->stackframesize * 8, REG_A0);
3472 emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), REG_A1);
3473 M_ALEA(REG_SP, cd->stackframesize * 8 + SIZEOF_VOID_P, REG_A2);
3474 M_ALD(REG_A3, REG_SP, cd->stackframesize * 8);
3475 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
3478 /* restore integer and float argument registers */
3480 for (i = 0, j = 0; i < md->paramcount; i++) {
3481 if (!md->params[i].inmemory) {
3482 s1 = md->params[i].regoff;
3484 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
3485 M_LLD(rd->argintregs[s1], REG_SP, j * 8);
3487 M_DLD(rd->argfltregs[s1], REG_SP, j * 8);
3493 M_ALD(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
3496 /* copy or spill arguments to new locations */
3498 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3499 t = md->paramtypes[i].type;
3501 if (IS_INT_LNG_TYPE(t)) {
3502 if (!md->params[i].inmemory) {
3503 s1 = rd->argintregs[md->params[i].regoff];
3505 if (!nmd->params[j].inmemory) {
3506 s2 = rd->argintregs[nmd->params[j].regoff];
3510 s2 = nmd->params[j].regoff;
3511 M_LST(s1, REG_SP, s2 * 8);
3515 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3516 s2 = nmd->params[j].regoff;
3517 M_LLD(REG_ITMP1, REG_SP, s1 * 8);
3518 M_LST(REG_ITMP1, REG_SP, s2 * 8);
3522 /* We only copy spilled float arguments, as the float argument */
3523 /* registers keep unchanged. */
3525 if (md->params[i].inmemory) {
3526 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3527 s2 = nmd->params[j].regoff;
3529 if (IS_2_WORD_TYPE(t)) {
3530 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
3531 M_DST(REG_FTMP1, REG_SP, s2 * 8);
3533 M_FLD(REG_FTMP1, REG_SP, s1 * 8);
3534 M_FST(REG_FTMP1, REG_SP, s2 * 8);
3540 /* put class into second argument register */
3542 if (m->flags & ACC_STATIC)
3543 M_MOV_IMM(m->class, REG_A1);
3545 /* put env into first argument register */
3547 M_MOV_IMM(_Jv_env, REG_A0);
3549 /* do the native function call */
3553 /* save return value */
3555 if (md->returntype.type != TYPE_VOID) {
3556 if (IS_INT_LNG_TYPE(md->returntype.type))
3557 M_LST(REG_RESULT, REG_SP, 0 * 8);
3559 M_DST(REG_FRESULT, REG_SP, 0 * 8);
3562 #if !defined(NDEBUG)
3563 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3564 emit_verbosecall_exit(jd);
3567 /* remove native stackframe info */
3569 M_ALEA(REG_SP, cd->stackframesize * 8, REG_A0);
3570 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
3572 M_MOV(REG_RESULT, REG_ITMP3);
3574 /* restore return value */
3576 if (md->returntype.type != TYPE_VOID) {
3577 if (IS_INT_LNG_TYPE(md->returntype.type))
3578 M_LLD(REG_RESULT, REG_SP, 0 * 8);
3580 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
3583 /* remove stackframe */
3585 M_AADD_IMM(cd->stackframesize * 8, REG_SP);
3587 /* test for exception */
3593 /* handle exception */
3595 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3596 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
3597 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3599 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
3602 /* generate patcher stubs */
3604 emit_patcher_stubs(jd);
3608 return code->entrypoint;
3613 * These are local overrides for various environment variables in Emacs.
3614 * Please do not remove this and leave it at the end of the file, where
3615 * Emacs will automagically detect them.
3616 * ---------------------------------------------------------------------
3619 * indent-tabs-mode: t
3623 * vim:noexpandtab:sw=4:ts=4: