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 4826 2006-04-24 16:06:16Z twisti $
48 #include "vm/jit/x86_64/arch.h"
49 #include "vm/jit/x86_64/codegen.h"
50 #include "vm/jit/x86_64/md-emit.h"
52 #include "mm/memory.h"
53 #include "native/jni.h"
54 #include "native/native.h"
55 #include "vm/builtin.h"
56 #include "vm/exceptions.h"
57 #include "vm/global.h"
58 #include "vm/loader.h"
59 #include "vm/options.h"
60 #include "vm/statistics.h"
61 #include "vm/stringlocal.h"
63 #include "vm/jit/asmpart.h"
64 #include "vm/jit/codegen-common.h"
65 #include "vm/jit/dseg.h"
66 #include "vm/jit/emit.h"
67 #include "vm/jit/jit.h"
68 #include "vm/jit/methodheader.h"
69 #include "vm/jit/parse.h"
70 #include "vm/jit/patcher.h"
71 #include "vm/jit/reg.h"
72 #include "vm/jit/replace.h"
74 #if defined(ENABLE_LSRA)
75 # include "vm/jit/allocator/lsra.h"
79 /* codegen *********************************************************************
81 Generates machine code.
83 *******************************************************************************/
85 bool codegen(jitdata *jd)
90 s4 len, s1, s2, s3, d, disp;
99 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
100 builtintable_entry *bte;
102 rplpoint *replacementpoint;
104 /* get required compiler data */
110 /* prevent compiler warnings */
122 /* space to save used callee saved registers */
124 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
125 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
127 stackframesize = rd->memuse + savedregs_num;
129 #if defined(USE_THREADS)
130 /* space to save argument of monitor_enter */
132 if (checksync && (m->flags & ACC_SYNCHRONIZED))
136 /* Keep stack of non-leaf functions 16-byte aligned for calls into native */
137 /* code e.g. libc or jni (alignment problems with movaps). */
139 if (!m->isleafmethod || opt_verbosecall)
140 stackframesize |= 0x1;
142 /* create method header */
144 (void) dseg_addaddress(cd, m); /* MethodPointer */
145 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
147 #if defined(USE_THREADS)
148 /* IsSync contains the offset relative to the stack pointer for the
149 argument of monitor_exit used in the exception handler. Since the
150 offset could be zero and give a wrong meaning of the flag it is
154 if (checksync && (m->flags & ACC_SYNCHRONIZED))
155 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
158 (void) dseg_adds4(cd, 0); /* IsSync */
160 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
161 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
162 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
164 (void) dseg_addlinenumbertablesize(cd);
166 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
168 /* create exception table */
170 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
171 dseg_addtarget(cd, ex->start);
172 dseg_addtarget(cd, ex->end);
173 dseg_addtarget(cd, ex->handler);
174 (void) dseg_addaddress(cd, ex->catchtype.cls);
177 /* generate method profiling code */
180 /* count frequency */
182 M_MOV_IMM(m, REG_ITMP3);
183 M_IINC_MEMBASE(REG_ITMP3, OFFSET(methodinfo, frequency));
188 /* create stack frame (if necessary) */
191 M_ASUB_IMM(stackframesize * 8, REG_SP);
193 /* save used callee saved registers */
196 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
197 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
199 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
200 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
203 /* take arguments out of register or stack frame */
207 for (p = 0, l = 0; p < md->paramcount; p++) {
208 t = md->paramtypes[p].type;
209 var = &(rd->locals[l][t]);
211 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
215 s1 = md->params[p].regoff;
216 if (IS_INT_LNG_TYPE(t)) { /* integer args */
217 s2 = rd->argintregs[s1];
218 if (!md->params[p].inmemory) { /* register arguments */
219 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
220 M_INTMOVE(s2, var->regoff);
222 } else { /* reg arg -> spilled */
223 M_LST(s2, REG_SP, var->regoff * 8);
226 } else { /* stack arguments */
227 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
228 /* + 8 for return address */
229 M_LLD(var->regoff, REG_SP, (stackframesize + s1) * 8 + 8);
231 } else { /* stack arg -> spilled */
232 var->regoff = stackframesize + s1 + 1;
236 } else { /* floating args */
237 if (!md->params[p].inmemory) { /* register arguments */
238 s2 = rd->argfltregs[s1];
239 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
240 M_FLTMOVE(s2, var->regoff);
242 } else { /* reg arg -> spilled */
243 M_DST(s2, REG_SP, var->regoff * 8);
246 } else { /* stack arguments */
247 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
248 M_DLD(var->regoff, REG_SP, (stackframesize + s1) * 8 + 8);
251 var->regoff = stackframesize + s1 + 1;
257 /* save monitorenter argument */
259 #if defined(USE_THREADS)
260 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
261 /* stack offset for monitor argument */
265 if (opt_verbosecall) {
266 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
268 for (p = 0; p < INT_ARG_CNT; p++)
269 M_LST(rd->argintregs[p], REG_SP, p * 8);
271 for (p = 0; p < FLT_ARG_CNT; p++)
272 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
274 s1 += INT_ARG_CNT + FLT_ARG_CNT;
277 /* decide which monitor enter function to call */
279 if (m->flags & ACC_STATIC) {
280 M_MOV_IMM(m->class, REG_ITMP1);
281 M_AST(REG_ITMP1, REG_SP, s1 * 8);
282 M_INTMOVE(REG_ITMP1, rd->argintregs[0]);
283 M_MOV_IMM(BUILTIN_staticmonitorenter, REG_ITMP1);
287 M_TEST(rd->argintregs[0]);
289 codegen_add_nullpointerexception_ref(cd);
290 M_AST(rd->argintregs[0], REG_SP, s1 * 8);
291 M_MOV_IMM(BUILTIN_monitorenter, REG_ITMP1);
295 if (opt_verbosecall) {
296 for (p = 0; p < INT_ARG_CNT; p++)
297 M_LLD(rd->argintregs[p], REG_SP, p * 8);
299 for (p = 0; p < FLT_ARG_CNT; p++)
300 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
302 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
308 /* Copy argument registers to stack and call trace function with
309 pointer to arguments on stack. */
311 if (opt_verbosecall) {
312 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
314 /* save integer argument registers */
316 for (p = 0; p < INT_ARG_CNT; p++)
317 M_LST(rd->argintregs[p], REG_SP, (1 + p) * 8);
319 /* save float argument registers */
321 for (p = 0; p < FLT_ARG_CNT; p++)
322 M_DST(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
324 /* save temporary registers for leaf methods */
326 if (m->isleafmethod) {
327 for (p = 0; p < INT_TMP_CNT; p++)
328 M_LST(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
330 for (p = 0; p < FLT_TMP_CNT; p++)
331 M_DST(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
334 /* show integer hex code for float arguments */
336 for (p = 0, l = 0; p < md->paramcount && p < INT_ARG_CNT; p++) {
337 /* If the paramtype is a float, we have to right shift all
338 following integer registers. */
340 if (IS_FLT_DBL_TYPE(md->paramtypes[p].type)) {
341 for (s1 = INT_ARG_CNT - 2; s1 >= p; s1--) {
342 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
345 x86_64_movd_freg_reg(cd, rd->argfltregs[l], rd->argintregs[p]);
350 M_MOV_IMM(m, REG_ITMP2);
351 M_AST(REG_ITMP2, REG_SP, 0 * 8);
352 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
355 /* restore integer argument registers */
357 for (p = 0; p < INT_ARG_CNT; p++)
358 M_LLD(rd->argintregs[p], REG_SP, (1 + p) * 8);
360 /* restore float argument registers */
362 for (p = 0; p < FLT_ARG_CNT; p++)
363 M_DLD(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
365 /* restore temporary registers for leaf methods */
367 if (m->isleafmethod) {
368 for (p = 0; p < INT_TMP_CNT; p++)
369 M_LLD(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
371 for (p = 0; p < FLT_TMP_CNT; p++)
372 M_DLD(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
375 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
377 #endif /* !defined(NDEBUG) */
381 /* end of header generation */
383 replacementpoint = jd->code->rplpoints;
385 /* walk through all basic blocks */
387 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
389 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
391 if (bptr->flags >= BBREACHED) {
393 /* branch resolving */
396 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
397 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
402 /* handle replacement points */
404 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
405 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
409 assert(cd->lastmcodeptr <= cd->mcodeptr);
410 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
413 /* copy interface registers to their destination */
419 /* generate basicblock profiling code */
422 /* count frequency */
424 M_MOV_IMM(m->bbfrequency, REG_ITMP2);
425 M_IINC_MEMBASE(REG_ITMP2, bptr->debug_nr * 4);
427 /* if this is an exception handler, start profiling again */
429 if (bptr->type == BBTYPE_EXH)
433 #if defined(ENABLE_LSRA)
435 while (src != NULL) {
437 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
438 if (bptr->type == BBTYPE_SBR) {
439 /* d = reg_of_var(rd, src, REG_ITMP1); */
440 if (!(src->flags & INMEMORY))
444 x86_64_pop_reg(cd, d);
445 emit_store(jd, NULL, src, d);
447 } else if (bptr->type == BBTYPE_EXH) {
448 /* d = reg_of_var(rd, src, REG_ITMP1); */
449 if (!(src->flags & INMEMORY))
453 M_INTMOVE(REG_ITMP1, d);
454 emit_store(jd, NULL, src, d);
463 while (src != NULL) {
465 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
466 if (bptr->type == BBTYPE_SBR) {
467 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
469 emit_store(jd, NULL, src, d);
471 } else if (bptr->type == BBTYPE_EXH) {
472 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
473 M_INTMOVE(REG_ITMP1, d);
474 emit_store(jd, NULL, src, d);
478 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
479 if ((src->varkind != STACKVAR)) {
481 if (IS_FLT_DBL_TYPE(s2)) {
482 s1 = rd->interfaces[len][s2].regoff;
484 if (!(rd->interfaces[len][s2].flags & INMEMORY))
487 M_DLD(d, REG_SP, s1 * 8);
489 emit_store(jd, NULL, src, d);
492 s1 = rd->interfaces[len][s2].regoff;
494 if (!(rd->interfaces[len][s2].flags & INMEMORY))
497 M_LLD(d, REG_SP, s1 * 8);
499 emit_store(jd, NULL, src, d);
505 #if defined(ENABLE_LSRA)
508 /* walk through all instructions */
514 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
515 if (iptr->line != currentline) {
516 dseg_addlinenumber(cd, iptr->line);
517 currentline = iptr->line;
520 MCODECHECK(1024); /* 1KB should be enough */
523 case ICMD_INLINE_START: /* internal ICMDs */
524 case ICMD_INLINE_END:
527 case ICMD_NOP: /* ... ==> ... */
530 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
532 if (src->flags & INMEMORY)
533 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8);
537 codegen_add_nullpointerexception_ref(cd);
540 /* constant operations ************************************************/
542 case ICMD_ICONST: /* ... ==> ..., constant */
543 /* op1 = 0, val.i = constant */
545 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
546 ICONST(d, iptr->val.i);
547 emit_store(jd, iptr, iptr->dst, d);
550 case ICMD_LCONST: /* ... ==> ..., constant */
551 /* op1 = 0, val.l = constant */
553 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
554 LCONST(d, iptr->val.l);
555 emit_store(jd, iptr, iptr->dst, d);
558 case ICMD_FCONST: /* ... ==> ..., constant */
559 /* op1 = 0, val.f = constant */
561 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
562 disp = dseg_addfloat(cd, iptr->val.f);
563 x86_64_movdl_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + ((d > 7) ? 9 : 8)) - (s8) cd->mcodebase) + disp, d);
564 emit_store(jd, iptr, iptr->dst, d);
567 case ICMD_DCONST: /* ... ==> ..., constant */
568 /* op1 = 0, val.d = constant */
570 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
571 disp = dseg_adddouble(cd, iptr->val.d);
572 x86_64_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, d);
573 emit_store(jd, iptr, iptr->dst, d);
576 case ICMD_ACONST: /* ... ==> ..., constant */
577 /* op1 = 0, val.a = constant */
579 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
581 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
582 /* PROFILE_CYCLE_STOP; */
584 codegen_addpatchref(cd, PATCHER_aconst,
585 (unresolved_class *) iptr->target, 0);
587 if (opt_showdisassemble) {
588 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
591 /* PROFILE_CYCLE_START; */
593 M_MOV_IMM(iptr->val.a, d);
596 if (iptr->val.a == 0)
599 M_MOV_IMM(iptr->val.a, d);
601 emit_store(jd, iptr, iptr->dst, d);
605 /* load/store operations **********************************************/
607 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
608 /* op1 = local variable */
610 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
611 if ((iptr->dst->varkind == LOCALVAR) &&
612 (iptr->dst->varnum == iptr->op1))
614 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
615 if (var->flags & INMEMORY)
616 M_ILD(d, REG_SP, var->regoff * 8);
618 M_INTMOVE(var->regoff, d);
619 emit_store(jd, iptr, iptr->dst, d);
622 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
623 case ICMD_ALOAD: /* op1 = local variable */
625 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
626 if ((iptr->dst->varkind == LOCALVAR) &&
627 (iptr->dst->varnum == iptr->op1))
629 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
630 if (var->flags & INMEMORY)
631 M_LLD(d, REG_SP, var->regoff * 8);
633 M_INTMOVE(var->regoff, d);
634 emit_store(jd, iptr, iptr->dst, d);
637 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
638 case ICMD_DLOAD: /* op1 = local variable */
640 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
641 if ((iptr->dst->varkind == LOCALVAR) &&
642 (iptr->dst->varnum == iptr->op1))
644 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
645 if (var->flags & INMEMORY)
646 M_DLD(d, REG_SP, var->regoff * 8);
648 M_FLTMOVE(var->regoff, d);
649 emit_store(jd, iptr, iptr->dst, d);
652 case ICMD_ISTORE: /* ..., value ==> ... */
653 /* op1 = local variable */
655 if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
657 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
658 if (var->flags & INMEMORY) {
659 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
660 M_IST(s1, REG_SP, var->regoff * 8);
662 s1 = emit_load_s1(jd, iptr, src, var->regoff);
663 M_INTMOVE(s1, var->regoff);
667 case ICMD_LSTORE: /* ..., value ==> ... */
668 case ICMD_ASTORE: /* op1 = local variable */
670 if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
672 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
673 if (var->flags & INMEMORY) {
674 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
675 M_LST(s1, REG_SP, var->regoff * 8);
677 s1 = emit_load_s1(jd, iptr, src, var->regoff);
678 M_INTMOVE(s1, var->regoff);
682 case ICMD_FSTORE: /* ..., value ==> ... */
683 case ICMD_DSTORE: /* op1 = local variable */
685 if ((src->varkind == LOCALVAR) &&
686 (src->varnum == iptr->op1)) {
689 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
690 if (var->flags & INMEMORY) {
691 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
692 M_DST(s1, REG_SP, var->regoff * 8);
694 s1 = emit_load_s1(jd, iptr, src, var->regoff);
695 M_FLTMOVE(s1, var->regoff);
700 /* pop/dup/swap operations ********************************************/
702 /* attention: double and longs are only one entry in CACAO ICMDs */
704 case ICMD_POP: /* ..., value ==> ... */
705 case ICMD_POP2: /* ..., value, value ==> ... */
708 case ICMD_DUP: /* ..., a ==> ..., a, a */
709 M_COPY(src, iptr->dst);
712 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
714 M_COPY(src, iptr->dst);
715 M_COPY(src->prev, iptr->dst->prev);
716 M_COPY(iptr->dst, iptr->dst->prev->prev);
719 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
721 M_COPY(src, iptr->dst);
722 M_COPY(src->prev, iptr->dst->prev);
723 M_COPY(src->prev->prev, iptr->dst->prev->prev);
724 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
727 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
729 M_COPY(src, iptr->dst);
730 M_COPY(src->prev, iptr->dst->prev);
733 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
735 M_COPY(src, iptr->dst);
736 M_COPY(src->prev, iptr->dst->prev);
737 M_COPY(src->prev->prev, iptr->dst->prev->prev);
738 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
739 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
742 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
744 M_COPY(src, iptr->dst);
745 M_COPY(src->prev, iptr->dst->prev);
746 M_COPY(src->prev->prev, iptr->dst->prev->prev);
747 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
748 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
749 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
752 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
754 M_COPY(src, iptr->dst->prev);
755 M_COPY(src->prev, iptr->dst);
759 /* integer operations *************************************************/
761 case ICMD_INEG: /* ..., value ==> ..., - value */
763 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
764 if (iptr->dst->flags & INMEMORY) {
765 if (src->flags & INMEMORY) {
766 if (src->regoff == iptr->dst->regoff)
767 M_INEG_MEMBASE(REG_SP, iptr->dst->regoff * 8);
769 M_ILD(REG_ITMP1, REG_SP, src->regoff * 8);
771 M_IST(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
775 M_IST(src->regoff, REG_SP, iptr->dst->regoff * 8);
776 M_INEG_MEMBASE(REG_SP, iptr->dst->regoff * 8);
780 if (src->flags & INMEMORY) {
781 M_ILD(iptr->dst->regoff, REG_SP, src->regoff * 8);
782 M_INEG(iptr->dst->regoff);
785 M_INTMOVE(src->regoff, iptr->dst->regoff);
786 M_INEG(iptr->dst->regoff);
791 case ICMD_LNEG: /* ..., value ==> ..., - value */
793 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
794 if (iptr->dst->flags & INMEMORY) {
795 if (src->flags & INMEMORY) {
796 if (src->regoff == iptr->dst->regoff)
797 M_LNEG_MEMBASE(REG_SP, iptr->dst->regoff * 8);
799 M_LLD(REG_ITMP1, REG_SP, src->regoff * 8);
801 M_LST(REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
805 M_LST(src->regoff, REG_SP, iptr->dst->regoff * 8);
806 M_LNEG_MEMBASE(REG_SP, iptr->dst->regoff * 8);
810 if (src->flags & INMEMORY) {
811 M_LLD(iptr->dst->regoff, REG_SP, src->regoff * 8);
812 M_LNEG(iptr->dst->regoff);
815 M_INTMOVE(src->regoff, iptr->dst->regoff);
816 M_LNEG(iptr->dst->regoff);
821 case ICMD_I2L: /* ..., value ==> ..., value */
823 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
824 if (src->flags & INMEMORY) {
825 x86_64_movslq_membase_reg(cd, REG_SP, src->regoff * 8, d);
828 x86_64_movslq_reg_reg(cd, src->regoff, d);
830 emit_store(jd, iptr, iptr->dst, d);
833 case ICMD_L2I: /* ..., value ==> ..., value */
835 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
836 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
838 emit_store(jd, iptr, iptr->dst, d);
841 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
843 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
844 if (src->flags & INMEMORY) {
845 x86_64_movsbq_membase_reg(cd, REG_SP, src->regoff * 8, d);
848 x86_64_movsbq_reg_reg(cd, src->regoff, d);
850 emit_store(jd, iptr, iptr->dst, d);
853 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
855 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
856 if (src->flags & INMEMORY) {
857 x86_64_movzwq_membase_reg(cd, REG_SP, src->regoff * 8, d);
860 x86_64_movzwq_reg_reg(cd, src->regoff, d);
862 emit_store(jd, iptr, iptr->dst, d);
865 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
867 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
868 if (src->flags & INMEMORY) {
869 x86_64_movswq_membase_reg(cd, REG_SP, src->regoff * 8, d);
872 x86_64_movswq_reg_reg(cd, src->regoff, d);
874 emit_store(jd, iptr, iptr->dst, d);
878 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
880 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
881 x86_64_emit_ialu(cd, X86_64_ADD, src, iptr);
884 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
885 /* val.i = constant */
887 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
888 x86_64_emit_ialuconst(cd, X86_64_ADD, src, iptr);
891 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
893 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
894 x86_64_emit_lalu(cd, X86_64_ADD, src, iptr);
897 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
898 /* val.l = constant */
900 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
901 x86_64_emit_laluconst(cd, X86_64_ADD, src, iptr);
904 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
906 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
907 if (iptr->dst->flags & INMEMORY) {
908 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
909 if (src->prev->regoff == iptr->dst->regoff) {
910 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
911 x86_64_alul_reg_membase(cd, X86_64_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
914 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
915 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
916 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
919 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
920 M_INTMOVE(src->prev->regoff, REG_ITMP1);
921 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
922 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
924 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
925 if (src->prev->regoff == iptr->dst->regoff) {
926 x86_64_alul_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
929 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
930 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
931 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
935 x86_64_movl_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
936 x86_64_alul_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
940 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
941 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
942 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
944 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
945 M_INTMOVE(src->prev->regoff, d);
946 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
948 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
949 /* workaround for reg alloc */
950 if (src->regoff == iptr->dst->regoff) {
951 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
952 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
953 M_INTMOVE(REG_ITMP1, d);
956 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
957 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, d);
961 /* workaround for reg alloc */
962 if (src->regoff == iptr->dst->regoff) {
963 M_INTMOVE(src->prev->regoff, REG_ITMP1);
964 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
965 M_INTMOVE(REG_ITMP1, d);
968 M_INTMOVE(src->prev->regoff, d);
969 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, d);
975 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
976 /* val.i = constant */
978 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
979 x86_64_emit_ialuconst(cd, X86_64_SUB, src, iptr);
982 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
984 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
985 if (iptr->dst->flags & INMEMORY) {
986 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
987 if (src->prev->regoff == iptr->dst->regoff) {
988 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
989 x86_64_alu_reg_membase(cd, X86_64_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
992 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
993 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
994 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
997 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
998 M_INTMOVE(src->prev->regoff, REG_ITMP1);
999 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1000 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1002 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1003 if (src->prev->regoff == iptr->dst->regoff) {
1004 x86_64_alu_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1007 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1008 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1009 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1013 x86_64_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1014 x86_64_alu_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1018 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1019 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1020 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
1022 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1023 M_INTMOVE(src->prev->regoff, d);
1024 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
1026 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1027 /* workaround for reg alloc */
1028 if (src->regoff == iptr->dst->regoff) {
1029 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1030 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1031 M_INTMOVE(REG_ITMP1, d);
1034 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1035 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, d);
1039 /* workaround for reg alloc */
1040 if (src->regoff == iptr->dst->regoff) {
1041 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1042 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1043 M_INTMOVE(REG_ITMP1, d);
1046 M_INTMOVE(src->prev->regoff, d);
1047 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, d);
1053 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1054 /* val.l = constant */
1056 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1057 x86_64_emit_laluconst(cd, X86_64_SUB, src, iptr);
1060 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1062 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1063 if (iptr->dst->flags & INMEMORY) {
1064 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1065 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1066 x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1067 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1069 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1070 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1071 x86_64_imull_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1072 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1074 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1075 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1076 x86_64_imull_reg_reg(cd, src->regoff, REG_ITMP1);
1077 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1080 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1081 x86_64_imull_reg_reg(cd, src->regoff, REG_ITMP1);
1082 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1086 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1087 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1088 x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1090 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1091 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1092 x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1094 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1095 M_INTMOVE(src->regoff, iptr->dst->regoff);
1096 x86_64_imull_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1099 if (src->regoff == iptr->dst->regoff) {
1100 x86_64_imull_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1103 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1104 x86_64_imull_reg_reg(cd, src->regoff, iptr->dst->regoff);
1110 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1111 /* val.i = constant */
1113 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1114 if (iptr->dst->flags & INMEMORY) {
1115 if (src->flags & INMEMORY) {
1116 x86_64_imull_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1117 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1120 x86_64_imull_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1121 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1125 if (src->flags & INMEMORY) {
1126 x86_64_imull_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1129 if (iptr->val.i == 2) {
1130 M_INTMOVE(src->regoff, iptr->dst->regoff);
1131 x86_64_alul_reg_reg(cd, X86_64_ADD, iptr->dst->regoff, iptr->dst->regoff);
1134 x86_64_imull_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff); /* 3 cycles */
1140 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1142 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1143 if (iptr->dst->flags & INMEMORY) {
1144 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1145 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1146 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1147 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1149 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1150 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1151 x86_64_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1152 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1154 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1155 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1156 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1157 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1160 x86_64_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1161 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1162 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1166 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1167 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1168 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1170 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1171 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1172 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1174 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1175 M_INTMOVE(src->regoff, iptr->dst->regoff);
1176 x86_64_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1179 if (src->regoff == iptr->dst->regoff) {
1180 x86_64_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1183 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1184 x86_64_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1190 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1191 /* val.l = constant */
1193 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1194 if (iptr->dst->flags & INMEMORY) {
1195 if (src->flags & INMEMORY) {
1196 if (IS_IMM32(iptr->val.l)) {
1197 x86_64_imul_imm_membase_reg(cd, iptr->val.l, REG_SP, src->regoff * 8, REG_ITMP1);
1200 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1201 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1203 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1206 if (IS_IMM32(iptr->val.l)) {
1207 x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, REG_ITMP1);
1210 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1211 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1213 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1217 if (src->flags & INMEMORY) {
1218 if (IS_IMM32(iptr->val.l)) {
1219 x86_64_imul_imm_membase_reg(cd, iptr->val.l, REG_SP, src->regoff * 8, iptr->dst->regoff);
1222 x86_64_mov_imm_reg(cd, iptr->val.l, iptr->dst->regoff);
1223 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1227 /* should match in many cases */
1228 if (iptr->val.l == 2) {
1229 M_INTMOVE(src->regoff, iptr->dst->regoff);
1230 x86_64_alul_reg_reg(cd, X86_64_ADD, iptr->dst->regoff, iptr->dst->regoff);
1233 if (IS_IMM32(iptr->val.l)) {
1234 x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, iptr->dst->regoff); /* 4 cycles */
1237 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1238 M_INTMOVE(src->regoff, iptr->dst->regoff);
1239 x86_64_imul_reg_reg(cd, REG_ITMP1, iptr->dst->regoff);
1246 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1248 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1249 if (src->prev->flags & INMEMORY) {
1250 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, RAX);
1253 M_INTMOVE(src->prev->regoff, RAX);
1256 if (src->flags & INMEMORY) {
1257 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1260 M_INTMOVE(src->regoff, REG_ITMP3);
1264 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1265 x86_64_jcc(cd, X86_64_CC_NE, 4 + 6);
1266 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3); /* 4 bytes */
1267 x86_64_jcc(cd, X86_64_CC_E, 3 + 1 + 3); /* 6 bytes */
1269 x86_64_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1271 x86_64_idivl_reg(cd, REG_ITMP3);
1273 if (iptr->dst->flags & INMEMORY) {
1274 x86_64_mov_reg_membase(cd, RAX, REG_SP, iptr->dst->regoff * 8);
1275 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1278 M_INTMOVE(RAX, iptr->dst->regoff);
1280 if (iptr->dst->regoff != RDX) {
1281 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1286 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1287 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1288 if (src->prev->flags & INMEMORY) {
1289 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, RAX);
1292 M_INTMOVE(src->prev->regoff, RAX);
1295 if (src->flags & INMEMORY) {
1296 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1299 M_INTMOVE(src->regoff, REG_ITMP3);
1303 x86_64_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1305 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1306 x86_64_jcc(cd, X86_64_CC_NE, 2 + 4 + 6);
1309 x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX); /* 2 bytes */
1310 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3); /* 4 bytes */
1311 x86_64_jcc(cd, X86_64_CC_E, 1 + 3); /* 6 bytes */
1314 x86_64_idivl_reg(cd, REG_ITMP3);
1316 if (iptr->dst->flags & INMEMORY) {
1317 x86_64_mov_reg_membase(cd, RDX, REG_SP, iptr->dst->regoff * 8);
1318 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1321 M_INTMOVE(RDX, iptr->dst->regoff);
1323 if (iptr->dst->regoff != RDX) {
1324 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1329 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1330 /* val.i = constant */
1332 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1333 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1334 M_INTMOVE(s1, REG_ITMP1);
1335 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1336 x86_64_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1337 x86_64_cmovccl_reg_reg(cd, X86_64_CC_LE, REG_ITMP2, REG_ITMP1);
1338 x86_64_shiftl_imm_reg(cd, X86_64_SAR, iptr->val.i, REG_ITMP1);
1339 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1340 emit_store(jd, iptr, iptr->dst, d);
1343 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1344 /* val.i = constant */
1346 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1347 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1348 M_INTMOVE(s1, REG_ITMP1);
1349 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1350 x86_64_leal_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1351 x86_64_cmovccl_reg_reg(cd, X86_64_CC_G, REG_ITMP1, REG_ITMP2);
1352 x86_64_alul_imm_reg(cd, X86_64_AND, -1 - (iptr->val.i), REG_ITMP2);
1353 x86_64_alul_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
1354 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1355 emit_store(jd, iptr, iptr->dst, d);
1359 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1361 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1363 if (src->prev->flags & INMEMORY) {
1364 M_LLD(RAX, REG_SP, src->prev->regoff * 8);
1367 M_INTMOVE(src->prev->regoff, RAX);
1370 if (src->flags & INMEMORY) {
1371 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1374 M_INTMOVE(src->regoff, REG_ITMP3);
1378 /* check as described in jvm spec */
1379 disp = dseg_adds8(cd, 0x8000000000000000LL);
1380 M_CMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, RAX);
1382 M_CMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1383 M_BEQ(3 + 2 + 3); /* 6 bytes */
1385 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1387 x86_64_idiv_reg(cd, REG_ITMP3);
1389 if (iptr->dst->flags & INMEMORY) {
1390 M_LST(RAX, REG_SP, iptr->dst->regoff * 8);
1391 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1394 M_INTMOVE(RAX, iptr->dst->regoff);
1396 if (iptr->dst->regoff != RDX) {
1397 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1402 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1404 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1405 if (src->prev->flags & INMEMORY) {
1406 M_LLD(REG_ITMP1, REG_SP, src->prev->regoff * 8);
1409 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1412 if (src->flags & INMEMORY) {
1413 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1416 M_INTMOVE(src->regoff, REG_ITMP3);
1420 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1422 /* check as described in jvm spec */
1423 disp = dseg_adds8(cd, 0x8000000000000000LL);
1424 M_CMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP1);
1428 x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX); /* 2 bytes */
1430 M_XOR(RDX, RDX); /* 3 bytes */
1431 M_CMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1432 M_BEQ(2 + 3); /* 6 bytes */
1435 x86_64_idiv_reg(cd, REG_ITMP3);
1437 if (iptr->dst->flags & INMEMORY) {
1438 M_LST(RDX, REG_SP, iptr->dst->regoff * 8);
1439 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1442 M_INTMOVE(RDX, iptr->dst->regoff);
1444 if (iptr->dst->regoff != RDX) {
1445 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1450 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1451 /* val.i = constant */
1453 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1454 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1455 M_INTMOVE(s1, REG_ITMP1);
1456 x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1457 x86_64_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1458 x86_64_cmovcc_reg_reg(cd, X86_64_CC_LE, REG_ITMP2, REG_ITMP1);
1459 x86_64_shift_imm_reg(cd, X86_64_SAR, iptr->val.i, REG_ITMP1);
1460 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1461 emit_store(jd, iptr, iptr->dst, d);
1464 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1465 /* val.l = constant */
1467 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1468 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1469 M_INTMOVE(s1, REG_ITMP1);
1470 x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1471 x86_64_lea_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1472 x86_64_cmovcc_reg_reg(cd, X86_64_CC_G, REG_ITMP1, REG_ITMP2);
1473 x86_64_alu_imm_reg(cd, X86_64_AND, -1 - (iptr->val.i), REG_ITMP2);
1474 x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
1475 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1476 emit_store(jd, iptr, iptr->dst, d);
1479 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1481 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1482 x86_64_emit_ishift(cd, X86_64_SHL, src, iptr);
1485 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1486 /* val.i = constant */
1488 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1489 x86_64_emit_ishiftconst(cd, X86_64_SHL, src, iptr);
1492 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1494 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1495 x86_64_emit_ishift(cd, X86_64_SAR, src, iptr);
1498 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1499 /* val.i = constant */
1501 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1502 x86_64_emit_ishiftconst(cd, X86_64_SAR, src, iptr);
1505 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1507 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1508 x86_64_emit_ishift(cd, X86_64_SHR, src, iptr);
1511 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1512 /* val.i = constant */
1514 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1515 x86_64_emit_ishiftconst(cd, X86_64_SHR, src, iptr);
1518 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1520 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1521 x86_64_emit_lshift(cd, X86_64_SHL, src, iptr);
1524 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1525 /* val.i = constant */
1527 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1528 x86_64_emit_lshiftconst(cd, X86_64_SHL, src, iptr);
1531 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1533 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1534 x86_64_emit_lshift(cd, X86_64_SAR, src, iptr);
1537 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1538 /* val.i = constant */
1540 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1541 x86_64_emit_lshiftconst(cd, X86_64_SAR, src, iptr);
1544 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1546 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1547 x86_64_emit_lshift(cd, X86_64_SHR, src, iptr);
1550 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1551 /* val.l = constant */
1553 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1554 x86_64_emit_lshiftconst(cd, X86_64_SHR, src, iptr);
1557 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1559 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1560 x86_64_emit_ialu(cd, X86_64_AND, src, iptr);
1563 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1564 /* val.i = constant */
1566 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1567 x86_64_emit_ialuconst(cd, X86_64_AND, src, iptr);
1570 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1572 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1573 x86_64_emit_lalu(cd, X86_64_AND, src, iptr);
1576 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1577 /* val.l = constant */
1579 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1580 x86_64_emit_laluconst(cd, X86_64_AND, src, iptr);
1583 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1585 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1586 x86_64_emit_ialu(cd, X86_64_OR, src, iptr);
1589 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1590 /* val.i = constant */
1592 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1593 x86_64_emit_ialuconst(cd, X86_64_OR, src, iptr);
1596 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1598 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1599 x86_64_emit_lalu(cd, X86_64_OR, src, iptr);
1602 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1603 /* val.l = constant */
1605 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1606 x86_64_emit_laluconst(cd, X86_64_OR, src, iptr);
1609 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1611 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1612 x86_64_emit_ialu(cd, X86_64_XOR, src, iptr);
1615 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1616 /* val.i = constant */
1618 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1619 x86_64_emit_ialuconst(cd, X86_64_XOR, src, iptr);
1622 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1624 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1625 x86_64_emit_lalu(cd, X86_64_XOR, src, iptr);
1628 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1629 /* val.l = constant */
1631 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1632 x86_64_emit_laluconst(cd, X86_64_XOR, src, iptr);
1636 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1637 /* op1 = variable, val.i = constant */
1639 /* using inc and dec is definitely faster than add -- tested */
1642 var = &(rd->locals[iptr->op1][TYPE_INT]);
1644 if (var->flags & INMEMORY) {
1645 if (iptr->val.i == 1) {
1646 x86_64_incl_membase(cd, REG_SP, d * 8);
1648 } else if (iptr->val.i == -1) {
1649 x86_64_decl_membase(cd, REG_SP, d * 8);
1652 x86_64_alul_imm_membase(cd, X86_64_ADD, iptr->val.i, REG_SP, d * 8);
1656 if (iptr->val.i == 1) {
1657 x86_64_incl_reg(cd, d);
1659 } else if (iptr->val.i == -1) {
1660 x86_64_decl_reg(cd, d);
1663 x86_64_alul_imm_reg(cd, X86_64_ADD, iptr->val.i, d);
1669 /* floating operations ************************************************/
1671 case ICMD_FNEG: /* ..., value ==> ..., - value */
1673 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1674 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1675 disp = dseg_adds4(cd, 0x80000000);
1677 x86_64_movss_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1678 x86_64_xorps_reg_reg(cd, REG_FTMP2, d);
1679 emit_store(jd, iptr, iptr->dst, d);
1682 case ICMD_DNEG: /* ..., value ==> ..., - value */
1684 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1685 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1686 disp = dseg_adds8(cd, 0x8000000000000000);
1688 x86_64_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1689 x86_64_xorpd_reg_reg(cd, REG_FTMP2, d);
1690 emit_store(jd, iptr, iptr->dst, d);
1693 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1695 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1696 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1697 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1699 x86_64_addss_reg_reg(cd, s2, d);
1700 } else if (s2 == d) {
1701 x86_64_addss_reg_reg(cd, s1, d);
1704 x86_64_addss_reg_reg(cd, s2, d);
1706 emit_store(jd, iptr, iptr->dst, d);
1709 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1711 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1712 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1713 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1715 x86_64_addsd_reg_reg(cd, s2, d);
1716 } else if (s2 == d) {
1717 x86_64_addsd_reg_reg(cd, s1, d);
1720 x86_64_addsd_reg_reg(cd, s2, d);
1722 emit_store(jd, iptr, iptr->dst, d);
1725 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1727 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1728 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1729 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1731 M_FLTMOVE(s2, REG_FTMP2);
1735 x86_64_subss_reg_reg(cd, s2, d);
1736 emit_store(jd, iptr, iptr->dst, d);
1739 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1741 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1742 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1743 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1745 M_FLTMOVE(s2, REG_FTMP2);
1749 x86_64_subsd_reg_reg(cd, s2, d);
1750 emit_store(jd, iptr, iptr->dst, d);
1753 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1755 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1756 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1757 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1759 x86_64_mulss_reg_reg(cd, s2, d);
1760 } else if (s2 == d) {
1761 x86_64_mulss_reg_reg(cd, s1, d);
1764 x86_64_mulss_reg_reg(cd, s2, d);
1766 emit_store(jd, iptr, iptr->dst, d);
1769 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1771 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1772 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1773 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1775 x86_64_mulsd_reg_reg(cd, s2, d);
1776 } else if (s2 == d) {
1777 x86_64_mulsd_reg_reg(cd, s1, d);
1780 x86_64_mulsd_reg_reg(cd, s2, d);
1782 emit_store(jd, iptr, iptr->dst, d);
1785 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1787 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1788 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1789 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1791 M_FLTMOVE(s2, REG_FTMP2);
1795 x86_64_divss_reg_reg(cd, s2, d);
1796 emit_store(jd, iptr, iptr->dst, d);
1799 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1801 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1802 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1803 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1805 M_FLTMOVE(s2, REG_FTMP2);
1809 x86_64_divsd_reg_reg(cd, s2, d);
1810 emit_store(jd, iptr, iptr->dst, d);
1813 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1815 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1816 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1817 x86_64_cvtsi2ss_reg_reg(cd, s1, d);
1818 emit_store(jd, iptr, iptr->dst, d);
1821 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1823 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1824 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1825 x86_64_cvtsi2sd_reg_reg(cd, s1, d);
1826 emit_store(jd, iptr, iptr->dst, d);
1829 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1831 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1832 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1833 x86_64_cvtsi2ssq_reg_reg(cd, s1, d);
1834 emit_store(jd, iptr, iptr->dst, d);
1837 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1839 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1840 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1841 x86_64_cvtsi2sdq_reg_reg(cd, s1, d);
1842 emit_store(jd, iptr, iptr->dst, d);
1845 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1847 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1848 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1849 x86_64_cvttss2si_reg_reg(cd, s1, d);
1850 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, d); /* corner cases */
1851 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1852 x86_64_jcc(cd, X86_64_CC_NE, a);
1853 M_FLTMOVE(s1, REG_FTMP1);
1854 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP2);
1855 x86_64_call_reg(cd, REG_ITMP2);
1856 M_INTMOVE(REG_RESULT, d);
1857 emit_store(jd, iptr, iptr->dst, d);
1860 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1862 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1863 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1864 x86_64_cvttsd2si_reg_reg(cd, s1, d);
1865 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, d); /* corner cases */
1866 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1867 x86_64_jcc(cd, X86_64_CC_NE, a);
1868 M_FLTMOVE(s1, REG_FTMP1);
1869 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP2);
1870 x86_64_call_reg(cd, REG_ITMP2);
1871 M_INTMOVE(REG_RESULT, d);
1872 emit_store(jd, iptr, iptr->dst, d);
1875 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1877 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1878 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1879 x86_64_cvttss2siq_reg_reg(cd, s1, d);
1880 x86_64_mov_imm_reg(cd, 0x8000000000000000, REG_ITMP2);
1881 x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, d); /* corner cases */
1882 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1883 x86_64_jcc(cd, X86_64_CC_NE, a);
1884 M_FLTMOVE(s1, REG_FTMP1);
1885 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP2);
1886 x86_64_call_reg(cd, REG_ITMP2);
1887 M_INTMOVE(REG_RESULT, d);
1888 emit_store(jd, iptr, iptr->dst, d);
1891 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1893 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1894 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1895 x86_64_cvttsd2siq_reg_reg(cd, s1, d);
1896 x86_64_mov_imm_reg(cd, 0x8000000000000000, REG_ITMP2);
1897 x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, d); /* corner cases */
1898 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1899 x86_64_jcc(cd, X86_64_CC_NE, a);
1900 M_FLTMOVE(s1, REG_FTMP1);
1901 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP2);
1902 x86_64_call_reg(cd, REG_ITMP2);
1903 M_INTMOVE(REG_RESULT, d);
1904 emit_store(jd, iptr, iptr->dst, d);
1907 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1909 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1910 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1911 x86_64_cvtss2sd_reg_reg(cd, s1, d);
1912 emit_store(jd, iptr, iptr->dst, d);
1915 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1917 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1918 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1919 x86_64_cvtsd2ss_reg_reg(cd, s1, d);
1920 emit_store(jd, iptr, iptr->dst, d);
1923 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1924 /* == => 0, < => 1, > => -1 */
1926 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1927 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1928 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1930 M_MOV_IMM(1, REG_ITMP1);
1931 M_MOV_IMM(-1, REG_ITMP2);
1932 x86_64_ucomiss_reg_reg(cd, s1, s2);
1933 M_CMOVB(REG_ITMP1, d);
1934 M_CMOVA(REG_ITMP2, d);
1935 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1936 emit_store(jd, iptr, iptr->dst, d);
1939 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1940 /* == => 0, < => 1, > => -1 */
1942 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1943 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1944 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1946 M_MOV_IMM(1, REG_ITMP1);
1947 M_MOV_IMM(-1, REG_ITMP2);
1948 x86_64_ucomiss_reg_reg(cd, s1, s2);
1949 M_CMOVB(REG_ITMP1, d);
1950 M_CMOVA(REG_ITMP2, d);
1951 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1952 emit_store(jd, iptr, iptr->dst, d);
1955 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1956 /* == => 0, < => 1, > => -1 */
1958 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1959 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1960 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1962 M_MOV_IMM(1, REG_ITMP1);
1963 M_MOV_IMM(-1, REG_ITMP2);
1964 x86_64_ucomisd_reg_reg(cd, s1, s2);
1965 M_CMOVB(REG_ITMP1, d);
1966 M_CMOVA(REG_ITMP2, d);
1967 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1968 emit_store(jd, iptr, iptr->dst, d);
1971 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1972 /* == => 0, < => 1, > => -1 */
1974 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1975 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1976 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1978 M_MOV_IMM(1, REG_ITMP1);
1979 M_MOV_IMM(-1, REG_ITMP2);
1980 x86_64_ucomisd_reg_reg(cd, s1, s2);
1981 M_CMOVB(REG_ITMP1, d);
1982 M_CMOVA(REG_ITMP2, d);
1983 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1984 emit_store(jd, iptr, iptr->dst, d);
1988 /* memory operations **************************************************/
1990 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1992 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1993 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1994 gen_nullptr_check(s1);
1995 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1996 emit_store(jd, iptr, iptr->dst, d);
1999 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2001 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2002 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2003 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2004 if (iptr->op1 == 0) {
2005 gen_nullptr_check(s1);
2008 x86_64_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2009 emit_store(jd, iptr, iptr->dst, d);
2012 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2014 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2015 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2016 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2017 if (iptr->op1 == 0) {
2018 gen_nullptr_check(s1);
2021 x86_64_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2022 emit_store(jd, iptr, iptr->dst, d);
2025 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2027 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2028 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2029 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2030 if (iptr->op1 == 0) {
2031 gen_nullptr_check(s1);
2034 x86_64_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2035 emit_store(jd, iptr, iptr->dst, d);
2038 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2040 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2041 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2042 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2043 if (iptr->op1 == 0) {
2044 gen_nullptr_check(s1);
2047 x86_64_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2048 emit_store(jd, iptr, iptr->dst, d);
2051 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2053 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2054 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2055 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2056 if (iptr->op1 == 0) {
2057 gen_nullptr_check(s1);
2060 x86_64_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
2061 emit_store(jd, iptr, iptr->dst, d);
2064 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2066 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2067 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2068 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2069 if (iptr->op1 == 0) {
2070 gen_nullptr_check(s1);
2073 x86_64_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
2074 emit_store(jd, iptr, iptr->dst, d);
2077 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2079 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2080 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2081 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2082 if (iptr->op1 == 0) {
2083 gen_nullptr_check(s1);
2086 x86_64_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
2087 emit_store(jd, iptr, iptr->dst, d);
2090 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2092 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2093 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2094 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2095 if (iptr->op1 == 0) {
2096 gen_nullptr_check(s1);
2099 x86_64_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
2100 emit_store(jd, iptr, iptr->dst, d);
2104 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2106 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2107 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2108 if (iptr->op1 == 0) {
2109 gen_nullptr_check(s1);
2112 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2113 x86_64_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2116 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2118 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2119 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2120 if (iptr->op1 == 0) {
2121 gen_nullptr_check(s1);
2124 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2125 x86_64_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2128 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2130 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2131 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2132 if (iptr->op1 == 0) {
2133 gen_nullptr_check(s1);
2136 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2137 x86_64_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2140 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2142 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2143 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2144 if (iptr->op1 == 0) {
2145 gen_nullptr_check(s1);
2148 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2149 x86_64_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2152 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2154 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2155 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2156 if (iptr->op1 == 0) {
2157 gen_nullptr_check(s1);
2160 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2161 x86_64_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2164 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2166 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2167 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2168 if (iptr->op1 == 0) {
2169 gen_nullptr_check(s1);
2172 s3 = emit_load_s3(jd, iptr, src, REG_FTMP3);
2173 x86_64_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2176 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2178 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2179 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2180 if (iptr->op1 == 0) {
2181 gen_nullptr_check(s1);
2184 s3 = emit_load_s3(jd, iptr, src, REG_FTMP3);
2185 x86_64_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2188 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2190 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2191 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2192 if (iptr->op1 == 0) {
2193 gen_nullptr_check(s1);
2196 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2198 M_MOV(s1, rd->argintregs[0]);
2199 M_MOV(s3, rd->argintregs[1]);
2200 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2204 codegen_add_arraystoreexception_ref(cd);
2206 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2207 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2208 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2209 x86_64_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2213 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2215 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2216 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2217 if (iptr->op1 == 0) {
2218 gen_nullptr_check(s1);
2221 x86_64_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2224 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2226 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2227 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2228 if (iptr->op1 == 0) {
2229 gen_nullptr_check(s1);
2232 x86_64_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2235 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2237 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2238 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2239 if (iptr->op1 == 0) {
2240 gen_nullptr_check(s1);
2243 x86_64_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2246 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2248 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2249 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2250 if (iptr->op1 == 0) {
2251 gen_nullptr_check(s1);
2254 x86_64_movl_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2257 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2259 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2260 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2261 if (iptr->op1 == 0) {
2262 gen_nullptr_check(s1);
2266 if (IS_IMM32(iptr->val.l)) {
2267 x86_64_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2269 x86_64_movl_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2270 x86_64_movl_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2274 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2276 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2277 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2278 if (iptr->op1 == 0) {
2279 gen_nullptr_check(s1);
2282 x86_64_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2286 case ICMD_GETSTATIC: /* ... ==> ..., value */
2287 /* op1 = type, val.a = field address */
2289 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2290 disp = dseg_addaddress(cd, NULL);
2292 /* PROFILE_CYCLE_STOP; */
2294 codegen_addpatchref(cd, PATCHER_get_putstatic,
2295 INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
2297 if (opt_showdisassemble) {
2298 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2301 /* PROFILE_CYCLE_START; */
2304 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2306 disp = dseg_addaddress(cd, &(fi->value));
2308 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2311 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2313 if (opt_showdisassemble) {
2314 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2317 PROFILE_CYCLE_START;
2321 /* This approach is much faster than moving the field
2322 address inline into a register. */
2324 M_ALD(REG_ITMP2, RIP, -(((ptrint) cd->mcodeptr + 7) -
2325 (ptrint) cd->mcodebase) + disp);
2327 switch (iptr->op1) {
2329 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2330 M_ILD(d, REG_ITMP2, 0);
2331 emit_store(jd, iptr, iptr->dst, d);
2335 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2336 M_LLD(d, REG_ITMP2, 0);
2337 emit_store(jd, iptr, iptr->dst, d);
2340 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2341 x86_64_movss_membase_reg(cd, REG_ITMP2, 0, d);
2342 emit_store(jd, iptr, iptr->dst, d);
2345 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2346 x86_64_movsd_membase_reg(cd, REG_ITMP2, 0, d);
2347 emit_store(jd, iptr, iptr->dst, d);
2352 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2353 /* op1 = type, val.a = field address */
2355 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2356 disp = dseg_addaddress(cd, NULL);
2358 /* PROFILE_CYCLE_STOP; */
2360 codegen_addpatchref(cd, PATCHER_get_putstatic,
2361 INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
2363 if (opt_showdisassemble) {
2364 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2367 /* PROFILE_CYCLE_START; */
2370 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2372 disp = dseg_addaddress(cd, &(fi->value));
2374 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2377 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2379 if (opt_showdisassemble) {
2380 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2383 PROFILE_CYCLE_START;
2387 /* This approach is much faster than moving the field
2388 address inline into a register. */
2390 M_ALD(REG_ITMP2, RIP, -(((ptrint) cd->mcodeptr + 7) -
2391 (ptrint) cd->mcodebase) + disp);
2393 switch (iptr->op1) {
2395 s2 = emit_load_s2(jd, iptr, src, REG_ITMP1);
2396 M_IST(s2, REG_ITMP2, 0);
2400 s2 = emit_load_s2(jd, iptr, src, REG_ITMP1);
2401 M_LST(s2, REG_ITMP2, 0);
2404 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2405 x86_64_movss_reg_membase(cd, s2, REG_ITMP2, 0);
2408 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2409 x86_64_movsd_reg_membase(cd, s2, REG_ITMP2, 0);
2414 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2415 /* val = value (in current instruction) */
2416 /* op1 = type, val.a = field address (in */
2417 /* following NOP) */
2419 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2420 disp = dseg_addaddress(cd, NULL);
2422 /* PROFILE_CYCLE_STOP; */
2424 codegen_addpatchref(cd, PATCHER_get_putstatic,
2425 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), disp);
2427 if (opt_showdisassemble) {
2428 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2431 /* PROFILE_CYCLE_START; */
2434 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
2436 disp = dseg_addaddress(cd, &(fi->value));
2438 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2441 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2443 if (opt_showdisassemble) {
2444 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2447 PROFILE_CYCLE_START;
2451 /* This approach is much faster than moving the field
2452 address inline into a register. */
2454 M_ALD(REG_ITMP1, RIP, -(((ptrint) cd->mcodeptr + 7) -
2455 (ptrint) cd->mcodebase) + disp);
2457 switch (iptr->op1) {
2460 M_IST_IMM(iptr->val.i, REG_ITMP1, 0);
2465 if (IS_IMM32(iptr->val.l)) {
2466 M_LST_IMM32(iptr->val.l, REG_ITMP1, 0);
2468 M_IST_IMM(iptr->val.l, REG_ITMP1, 0);
2469 M_IST_IMM(iptr->val.l >> 32, REG_ITMP1, 4);
2475 case ICMD_GETFIELD: /* ... ==> ..., value */
2476 /* op1 = type, val.i = field offset */
2478 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2479 gen_nullptr_check(s1);
2481 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2482 /* PROFILE_CYCLE_STOP; */
2484 codegen_addpatchref(cd, PATCHER_get_putfield,
2485 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2487 if (opt_showdisassemble) {
2488 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2491 /* PROFILE_CYCLE_START; */
2496 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2499 switch (iptr->op1) {
2501 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2502 M_ILD32(d, s1, disp);
2503 emit_store(jd, iptr, iptr->dst, d);
2507 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2508 M_LLD32(d, s1, disp);
2509 emit_store(jd, iptr, iptr->dst, d);
2512 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2513 x86_64_movss_membase32_reg(cd, s1, disp, d);
2514 emit_store(jd, iptr, iptr->dst, d);
2517 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2518 x86_64_movsd_membase32_reg(cd, s1, disp, d);
2519 emit_store(jd, iptr, iptr->dst, d);
2524 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2525 /* op1 = type, val.i = field offset */
2527 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2528 gen_nullptr_check(s1);
2530 if (IS_INT_LNG_TYPE(iptr->op1)) {
2531 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2533 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2536 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2537 /* PROFILE_CYCLE_STOP; */
2539 codegen_addpatchref(cd, PATCHER_get_putfield,
2540 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2542 if (opt_showdisassemble) {
2543 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2546 /* PROFILE_CYCLE_START; */
2551 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2554 switch (iptr->op1) {
2556 M_IST32(s2, s1, disp);
2560 M_LST32(s2, s1, disp);
2563 x86_64_movss_reg_membase32(cd, s2, s1, disp);
2566 x86_64_movsd_reg_membase32(cd, s2, s1, disp);
2571 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2572 /* val = value (in current instruction) */
2573 /* op1 = type, val.a = field address (in */
2574 /* following NOP) */
2576 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2577 gen_nullptr_check(s1);
2579 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2580 /* PROFILE_CYCLE_STOP; */
2582 codegen_addpatchref(cd, PATCHER_putfieldconst,
2583 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2585 if (opt_showdisassemble) {
2586 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2589 /* PROFILE_CYCLE_START; */
2594 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
2597 switch (iptr->op1) {
2600 M_IST32_IMM(iptr->val.i, s1, disp);
2605 M_IST32_IMM(iptr->val.l, s1, disp);
2606 M_IST32_IMM(iptr->val.l >> 32, s1, disp + 4);
2612 /* branch operations **************************************************/
2614 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2616 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2617 M_INTMOVE(s1, REG_ITMP1_XPTR);
2621 #ifdef ENABLE_VERIFIER
2623 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2624 (unresolved_class *) iptr->val.a, 0);
2626 if (opt_showdisassemble) {
2627 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2630 #endif /* ENABLE_VERIFIER */
2632 M_CALL_IMM(0); /* passing exception pc */
2633 M_POP(REG_ITMP2_XPC);
2635 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2639 case ICMD_GOTO: /* ... ==> ... */
2640 /* op1 = target JavaVM pc */
2643 codegen_addreference(cd, (basicblock *) iptr->target);
2646 case ICMD_JSR: /* ... ==> ... */
2647 /* op1 = target JavaVM pc */
2650 codegen_addreference(cd, (basicblock *) iptr->target);
2653 case ICMD_RET: /* ... ==> ... */
2654 /* op1 = local variable */
2656 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2657 if (var->flags & INMEMORY) {
2658 M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
2664 case ICMD_IFNULL: /* ..., value ==> ... */
2665 /* op1 = target JavaVM pc */
2667 if (src->flags & INMEMORY)
2668 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8);
2670 M_TEST(src->regoff);
2672 /* If the conditional branch is part of an if-converted
2673 block, don't generate the actual branch. */
2675 if ((iptr->opc & ICMD_CONDITION_MASK) == 0) {
2677 codegen_addreference(cd, (basicblock *) iptr->target);
2681 case ICMD_IFNONNULL: /* ..., value ==> ... */
2682 /* op1 = target JavaVM pc */
2684 if (src->flags & INMEMORY)
2685 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8);
2687 M_TEST(src->regoff);
2689 /* If the conditional branch is part of an if-converted
2690 block, don't generate the actual branch. */
2692 if ((iptr->opc & ICMD_CONDITION_MASK) == 0) {
2694 codegen_addreference(cd, (basicblock *) iptr->target);
2698 case ICMD_IFEQ: /* ..., value ==> ... */
2699 /* op1 = target JavaVM pc, val.i = constant */
2701 x86_64_emit_ifcc(cd, X86_64_CC_E, src, iptr);
2704 case ICMD_IFLT: /* ..., value ==> ... */
2705 /* op1 = target JavaVM pc, val.i = constant */
2707 x86_64_emit_ifcc(cd, X86_64_CC_L, src, iptr);
2710 case ICMD_IFLE: /* ..., value ==> ... */
2711 /* op1 = target JavaVM pc, val.i = constant */
2713 x86_64_emit_ifcc(cd, X86_64_CC_LE, src, iptr);
2716 case ICMD_IFNE: /* ..., value ==> ... */
2717 /* op1 = target JavaVM pc, val.i = constant */
2719 x86_64_emit_ifcc(cd, X86_64_CC_NE, src, iptr);
2722 case ICMD_IFGT: /* ..., value ==> ... */
2723 /* op1 = target JavaVM pc, val.i = constant */
2725 x86_64_emit_ifcc(cd, X86_64_CC_G, src, iptr);
2728 case ICMD_IFGE: /* ..., value ==> ... */
2729 /* op1 = target JavaVM pc, val.i = constant */
2731 x86_64_emit_ifcc(cd, X86_64_CC_GE, src, iptr);
2734 case ICMD_IF_LEQ: /* ..., value ==> ... */
2735 /* op1 = target JavaVM pc, val.l = constant */
2737 x86_64_emit_if_lcc(cd, X86_64_CC_E, src, iptr);
2740 case ICMD_IF_LLT: /* ..., value ==> ... */
2741 /* op1 = target JavaVM pc, val.l = constant */
2743 x86_64_emit_if_lcc(cd, X86_64_CC_L, src, iptr);
2746 case ICMD_IF_LLE: /* ..., value ==> ... */
2747 /* op1 = target JavaVM pc, val.l = constant */
2749 x86_64_emit_if_lcc(cd, X86_64_CC_LE, src, iptr);
2752 case ICMD_IF_LNE: /* ..., value ==> ... */
2753 /* op1 = target JavaVM pc, val.l = constant */
2755 x86_64_emit_if_lcc(cd, X86_64_CC_NE, src, iptr);
2758 case ICMD_IF_LGT: /* ..., value ==> ... */
2759 /* op1 = target JavaVM pc, val.l = constant */
2761 x86_64_emit_if_lcc(cd, X86_64_CC_G, src, iptr);
2764 case ICMD_IF_LGE: /* ..., value ==> ... */
2765 /* op1 = target JavaVM pc, val.l = constant */
2767 x86_64_emit_if_lcc(cd, X86_64_CC_GE, src, iptr);
2770 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2771 /* op1 = target JavaVM pc */
2773 x86_64_emit_if_icmpcc(cd, X86_64_CC_E, src, iptr);
2776 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2777 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2779 x86_64_emit_if_lcmpcc(cd, X86_64_CC_E, src, iptr);
2782 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2783 /* op1 = target JavaVM pc */
2785 x86_64_emit_if_icmpcc(cd, X86_64_CC_NE, src, iptr);
2788 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2789 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2791 x86_64_emit_if_lcmpcc(cd, X86_64_CC_NE, src, iptr);
2794 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2795 /* op1 = target JavaVM pc */
2797 x86_64_emit_if_icmpcc(cd, X86_64_CC_L, src, iptr);
2800 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2801 /* op1 = target JavaVM pc */
2803 x86_64_emit_if_lcmpcc(cd, X86_64_CC_L, src, iptr);
2806 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2807 /* op1 = target JavaVM pc */
2809 x86_64_emit_if_icmpcc(cd, X86_64_CC_G, src, iptr);
2812 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2813 /* op1 = target JavaVM pc */
2815 x86_64_emit_if_lcmpcc(cd, X86_64_CC_G, src, iptr);
2818 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2819 /* op1 = target JavaVM pc */
2821 x86_64_emit_if_icmpcc(cd, X86_64_CC_LE, src, iptr);
2824 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2825 /* op1 = target JavaVM pc */
2827 x86_64_emit_if_lcmpcc(cd, X86_64_CC_LE, src, iptr);
2830 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2831 /* op1 = target JavaVM pc */
2833 x86_64_emit_if_icmpcc(cd, X86_64_CC_GE, src, iptr);
2836 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2837 /* op1 = target JavaVM pc */
2839 x86_64_emit_if_lcmpcc(cd, X86_64_CC_GE, src, iptr);
2842 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2844 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2847 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2848 case ICMD_IFNE_ICONST: /* val.i = constant */
2849 case ICMD_IFLT_ICONST:
2850 case ICMD_IFGE_ICONST:
2851 case ICMD_IFGT_ICONST:
2852 case ICMD_IFLE_ICONST:
2854 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2855 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2856 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2858 M_INTMOVE(s1, REG_ITMP1);
2861 if (iptr[1].val.i == 0)
2864 M_IMOV_IMM(iptr[1].val.i, d);
2866 if (iptr->val.i == 0)
2869 M_IMOV_IMM(iptr->val.i, REG_ITMP2);
2872 switch (iptr->opc) {
2873 case ICMD_IFEQ_ICONST:
2874 M_CMOVEQ(REG_ITMP2, d);
2876 case ICMD_IFNE_ICONST:
2877 M_CMOVNE(REG_ITMP2, d);
2879 case ICMD_IFLT_ICONST:
2880 M_CMOVLT(REG_ITMP2, d);
2882 case ICMD_IFGE_ICONST:
2883 M_CMOVGE(REG_ITMP2, d);
2885 case ICMD_IFGT_ICONST:
2886 M_CMOVGT(REG_ITMP2, d);
2888 case ICMD_IFLE_ICONST:
2889 M_CMOVLE(REG_ITMP2, d);
2893 emit_store(jd, iptr, iptr->dst, d);
2897 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2900 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
2901 M_INTMOVE(s1, REG_RESULT);
2902 goto nowperformreturn;
2904 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2906 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
2907 M_INTMOVE(s1, REG_RESULT);
2909 #ifdef ENABLE_VERIFIER
2913 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2914 (unresolved_class *) iptr->val.a, 0);
2916 if (opt_showdisassemble) {
2917 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2920 PROFILE_CYCLE_START;
2922 #endif /* ENABLE_VERIFIER */
2923 goto nowperformreturn;
2925 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2928 s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
2929 M_FLTMOVE(s1, REG_FRESULT);
2930 goto nowperformreturn;
2932 case ICMD_RETURN: /* ... ==> ... */
2940 #if !defined(NDEBUG)
2941 /* generate call trace */
2943 if (opt_verbosecall) {
2944 x86_64_alu_imm_reg(cd, X86_64_SUB, 2 * 8, REG_SP);
2946 x86_64_mov_reg_membase(cd, REG_RESULT, REG_SP, 0 * 8);
2947 x86_64_movq_reg_membase(cd, REG_FRESULT, REG_SP, 1 * 8);
2949 x86_64_mov_imm_reg(cd, (u8) m, rd->argintregs[0]);
2950 x86_64_mov_reg_reg(cd, REG_RESULT, rd->argintregs[1]);
2951 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2952 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2954 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
2957 x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_RESULT);
2958 x86_64_movq_membase_reg(cd, REG_SP, 1 * 8, REG_FRESULT);
2960 x86_64_alu_imm_reg(cd, X86_64_ADD, 2 * 8, REG_SP);
2962 #endif /* !defined(NDEBUG) */
2964 #if defined(USE_THREADS)
2965 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2966 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2968 /* we need to save the proper return value */
2969 switch (iptr->opc) {
2973 M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
2977 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
2981 M_MOV_IMM(builtin_monitorexit, REG_ITMP1);
2984 /* and now restore the proper return value */
2985 switch (iptr->opc) {
2989 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2993 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2999 /* restore saved registers */
3001 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
3002 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
3004 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
3005 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
3008 /* deallocate stack */
3011 M_AADD_IMM(stackframesize * 8, REG_SP);
3013 /* generate method profiling code */
3022 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3027 tptr = (void **) iptr->target;
3029 s4ptr = iptr->val.a;
3030 l = s4ptr[1]; /* low */
3031 i = s4ptr[2]; /* high */
3033 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3034 M_INTMOVE(s1, REG_ITMP1);
3036 x86_64_alul_imm_reg(cd, X86_64_SUB, l, REG_ITMP1);
3041 x86_64_alul_imm_reg(cd, X86_64_CMP, i - 1, REG_ITMP1);
3042 x86_64_jcc(cd, X86_64_CC_A, 0);
3044 codegen_addreference(cd, (basicblock *) tptr[0]);
3046 /* build jump table top down and use address of lowest entry */
3048 /* s4ptr += 3 + i; */
3052 dseg_addtarget(cd, (basicblock *) tptr[0]);
3056 /* length of dataseg after last dseg_addtarget is used
3059 M_MOV_IMM(0, REG_ITMP2);
3061 x86_64_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
3062 x86_64_jmp_reg(cd, REG_ITMP1);
3067 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3069 s4 i, l, val, *s4ptr;
3072 tptr = (void **) iptr->target;
3074 s4ptr = iptr->val.a;
3075 l = s4ptr[0]; /* default */
3076 i = s4ptr[1]; /* count */
3078 MCODECHECK(8 + ((7 + 6) * i) + 5);
3079 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1); /* reg compare should always be faster */
3085 x86_64_alul_imm_reg(cd, X86_64_CMP, val, s1);
3086 x86_64_jcc(cd, X86_64_CC_E, 0);
3087 codegen_addreference(cd, (basicblock *) tptr[0]);
3090 x86_64_jmp_imm(cd, 0);
3092 tptr = (void **) iptr->target;
3093 codegen_addreference(cd, (basicblock *) tptr[0]);
3098 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
3099 /* op1 = arg count val.a = builtintable entry */
3105 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3106 /* op1 = arg count, val.a = method pointer */
3108 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3109 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3110 case ICMD_INVOKEINTERFACE:
3112 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3113 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
3117 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
3118 md = lm->parseddesc;
3122 s3 = md->paramcount;
3124 MCODECHECK((20 * s3) + 128);
3126 /* copy arguments to registers or stack location */
3128 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3129 if (src->varkind == ARGVAR)
3131 if (IS_INT_LNG_TYPE(src->type)) {
3132 if (!md->params[s3].inmemory) {
3133 s1 = rd->argintregs[md->params[s3].regoff];
3134 d = emit_load_s1(jd, iptr, src, s1);
3137 d = emit_load_s1(jd, iptr, src, REG_ITMP1);
3138 M_LST(d, REG_SP, md->params[s3].regoff * 8);
3142 if (!md->params[s3].inmemory) {
3143 s1 = rd->argfltregs[md->params[s3].regoff];
3144 d = emit_load_s1(jd, iptr, src, s1);
3147 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
3148 M_DST(d, REG_SP, md->params[s3].regoff * 8);
3153 /* generate method profiling code */
3157 switch (iptr->opc) {
3159 a = (ptrint) bte->fp;
3160 d = md->returntype.type;
3162 M_MOV_IMM(a, REG_ITMP1);
3165 /* if op1 == true, we need to check for an exception */
3167 if (iptr->op1 == true) {
3170 codegen_add_fillinstacktrace_ref(cd);
3174 case ICMD_INVOKESPECIAL:
3175 M_TEST(rd->argintregs[0]);
3177 codegen_add_nullpointerexception_ref(cd);
3179 /* first argument contains pointer */
3180 /* gen_nullptr_check(rd->argintregs[0]); */
3182 /* access memory for hardware nullptr */
3183 /* x86_64_mov_membase_reg(cd, rd->argintregs[0], 0, REG_ITMP2); */
3187 case ICMD_INVOKESTATIC:
3189 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3191 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3194 if (opt_showdisassemble) {
3195 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3199 d = um->methodref->parseddesc.md->returntype.type;
3202 a = (ptrint) lm->stubroutine;
3203 d = lm->parseddesc->returntype.type;
3206 M_MOV_IMM(a, REG_ITMP2);
3210 case ICMD_INVOKEVIRTUAL:
3211 gen_nullptr_check(rd->argintregs[0]);
3214 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3216 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3218 if (opt_showdisassemble) {
3219 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3223 d = um->methodref->parseddesc.md->returntype.type;
3226 s1 = OFFSET(vftbl_t, table[0]) +
3227 sizeof(methodptr) * lm->vftblindex;
3228 d = lm->parseddesc->returntype.type;
3231 M_ALD(REG_METHODPTR, rd->argintregs[0],
3232 OFFSET(java_objectheader, vftbl));
3233 M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
3237 case ICMD_INVOKEINTERFACE:
3238 gen_nullptr_check(rd->argintregs[0]);
3241 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3243 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3245 if (opt_showdisassemble) {
3246 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3251 d = um->methodref->parseddesc.md->returntype.type;
3254 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3255 sizeof(methodptr) * lm->class->index;
3257 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3259 d = lm->parseddesc->returntype.type;
3262 M_ALD(REG_METHODPTR, rd->argintregs[0],
3263 OFFSET(java_objectheader, vftbl));
3264 M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
3265 M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
3270 /* generate method profiling code */
3272 PROFILE_CYCLE_START;
3274 /* d contains return type */
3276 if (d != TYPE_VOID) {
3277 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3278 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3279 M_INTMOVE(REG_RESULT, s1);
3280 emit_store(jd, iptr, iptr->dst, s1);
3282 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FRESULT);
3283 M_FLTMOVE(REG_FRESULT, s1);
3284 emit_store(jd, iptr, iptr->dst, s1);
3290 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3292 /* op1: 0 == array, 1 == class */
3293 /* val.a: (classinfo *) superclass */
3295 /* superclass is an interface:
3297 * OK if ((sub == NULL) ||
3298 * (sub->vftbl->interfacetablelength > super->index) &&
3299 * (sub->vftbl->interfacetable[-super->index] != NULL));
3301 * superclass is a class:
3303 * OK if ((sub == NULL) || (0
3304 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3305 * super->vftbl->diffval));
3308 if (iptr->op1 == 1) {
3309 /* object type cast-check */
3312 vftbl_t *supervftbl;
3315 super = (classinfo *) iptr->val.a;
3322 superindex = super->index;
3323 supervftbl = super->vftbl;
3326 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3327 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3329 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3331 /* calculate interface checkcast code size */
3333 s2 = 3; /* mov_membase_reg */
3334 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3336 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub imm32 */ +
3337 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3338 3 /* test */ + 6 /* jcc */;
3341 s2 += (opt_showdisassemble ? 5 : 0);
3343 /* calculate class checkcast code size */
3345 s3 = 3; /* mov_membase_reg */
3346 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3347 s3 += 10 /* mov_imm_reg */ + 3 + 4 /* movl_membase32_reg */;
3350 if (s1 != REG_ITMP1) {
3351 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3352 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3353 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3354 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3360 s3 += 3 + 4 /* movl_membase32_reg */ + 3 /* sub */ +
3361 10 /* mov_imm_reg */ + 3 /* movl_membase_reg */;
3362 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3365 s3 += 3 /* cmp */ + 6 /* jcc */;
3368 s3 += (opt_showdisassemble ? 5 : 0);
3370 /* if class is not resolved, check which code to call */
3374 M_BEQ(6 + (opt_showdisassemble ? 5 : 0) + 7 + 6 + s2 + 5 + s3);
3376 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3377 (constant_classref *) iptr->target, 0);
3379 if (opt_showdisassemble) {
3380 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3383 M_IMOV_IMM(0, REG_ITMP2); /* super->flags */
3384 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
3388 /* interface checkcast code */
3390 if (!super || (super->flags & ACC_INTERFACE)) {
3396 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3399 codegen_addpatchref(cd,
3400 PATCHER_checkcast_instanceof_interface,
3401 (constant_classref *) iptr->target,
3404 if (opt_showdisassemble) {
3405 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3409 x86_64_movl_membase32_reg(cd, REG_ITMP2,
3410 OFFSET(vftbl_t, interfacetablelength),
3412 /* XXX TWISTI: should this be int arithmetic? */
3413 M_LSUB_IMM32(superindex, REG_ITMP3);
3416 codegen_add_classcastexception_ref(cd);
3417 x86_64_mov_membase32_reg(cd, REG_ITMP2,
3418 OFFSET(vftbl_t, interfacetable[0]) -
3419 superindex * sizeof(methodptr*),
3423 codegen_add_classcastexception_ref(cd);
3429 /* class checkcast code */
3431 if (!super || !(super->flags & ACC_INTERFACE)) {
3437 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3440 codegen_addpatchref(cd, PATCHER_checkcast_class,
3441 (constant_classref *) iptr->target,
3444 if (opt_showdisassemble) {
3445 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3449 M_MOV_IMM(supervftbl, REG_ITMP3);
3450 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3451 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3453 x86_64_movl_membase32_reg(cd, REG_ITMP2,
3454 OFFSET(vftbl_t, baseval),
3456 /* if (s1 != REG_ITMP1) { */
3457 /* x86_64_movl_membase_reg(cd, REG_ITMP3, */
3458 /* OFFSET(vftbl_t, baseval), */
3460 /* x86_64_movl_membase_reg(cd, REG_ITMP3, */
3461 /* OFFSET(vftbl_t, diffval), */
3463 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3464 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3466 /* x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP1, REG_ITMP2); */
3469 x86_64_movl_membase32_reg(cd, REG_ITMP3,
3470 OFFSET(vftbl_t, baseval),
3472 M_LSUB(REG_ITMP3, REG_ITMP2);
3473 M_MOV_IMM(supervftbl, REG_ITMP3);
3474 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3476 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3477 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3479 M_CMP(REG_ITMP3, REG_ITMP2);
3480 M_BA(0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
3481 codegen_add_classcastexception_ref(cd);
3483 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
3486 /* array type cast-check */
3488 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3489 M_INTMOVE(s1, rd->argintregs[0]);
3491 if (iptr->val.a == NULL) {
3492 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
3493 (constant_classref *) iptr->target, 0);
3495 if (opt_showdisassemble) {
3496 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3500 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3501 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
3505 codegen_add_classcastexception_ref(cd);
3507 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3508 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
3511 emit_store(jd, iptr, iptr->dst, d);
3514 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3516 /* op1: 0 == array, 1 == class */
3517 /* val.a: (classinfo *) superclass */
3519 /* superclass is an interface:
3521 * return (sub != NULL) &&
3522 * (sub->vftbl->interfacetablelength > super->index) &&
3523 * (sub->vftbl->interfacetable[-super->index] != NULL);
3525 * superclass is a class:
3527 * return ((sub != NULL) && (0
3528 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3529 * super->vftbl->diffvall));
3534 vftbl_t *supervftbl;
3537 super = (classinfo *) iptr->val.a;
3544 superindex = super->index;
3545 supervftbl = super->vftbl;
3548 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3549 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3552 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3553 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3555 M_INTMOVE(s1, REG_ITMP1);
3559 /* calculate interface instanceof code size */
3561 s2 = 3; /* mov_membase_reg */
3562 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3563 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub_imm32 */ +
3564 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3565 3 /* test */ + 4 /* setcc */;
3568 s2 += (opt_showdisassemble ? 5 : 0);
3570 /* calculate class instanceof code size */
3572 s3 = 3; /* mov_membase_reg */
3573 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3574 s3 += 10; /* mov_imm_reg */
3575 s3 += 2; /* movl_membase_reg - only if REG_ITMP1 == RAX */
3576 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3577 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3578 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3579 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3580 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3581 s3 += 3 /* sub */ + 3 /* xor */ + 3 /* cmp */ + 4 /* setcc */;
3584 s3 += (opt_showdisassemble ? 5 : 0);
3586 x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
3588 /* if class is not resolved, check which code to call */
3591 x86_64_test_reg_reg(cd, s1, s1);
3592 x86_64_jcc(cd, X86_64_CC_Z, (6 + (opt_showdisassemble ? 5 : 0) +
3593 7 + 6 + s2 + 5 + s3));
3595 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3596 (constant_classref *) iptr->target, 0);
3598 if (opt_showdisassemble) {
3599 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3602 x86_64_movl_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
3603 x86_64_alul_imm_reg(cd, X86_64_AND, ACC_INTERFACE, REG_ITMP3);
3604 x86_64_jcc(cd, X86_64_CC_Z, s2 + 5);
3607 /* interface instanceof code */
3609 if (!super || (super->flags & ACC_INTERFACE)) {
3611 x86_64_test_reg_reg(cd, s1, s1);
3612 x86_64_jcc(cd, X86_64_CC_Z, s2);
3615 x86_64_mov_membase_reg(cd, s1,
3616 OFFSET(java_objectheader, vftbl),
3619 codegen_addpatchref(cd,
3620 PATCHER_checkcast_instanceof_interface,
3621 (constant_classref *) iptr->target, 0);
3623 if (opt_showdisassemble) {
3624 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3628 x86_64_movl_membase32_reg(cd, REG_ITMP1,
3629 OFFSET(vftbl_t, interfacetablelength),
3631 x86_64_alu_imm32_reg(cd, X86_64_SUB, superindex, REG_ITMP3);
3632 x86_64_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
3634 a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
3636 x86_64_jcc(cd, X86_64_CC_LE, a);
3637 x86_64_mov_membase32_reg(cd, REG_ITMP1,
3638 OFFSET(vftbl_t, interfacetable[0]) -
3639 superindex * sizeof(methodptr*),
3641 x86_64_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3642 x86_64_setcc_reg(cd, X86_64_CC_NE, d);
3645 x86_64_jmp_imm(cd, s3);
3648 /* class instanceof code */
3650 if (!super || !(super->flags & ACC_INTERFACE)) {
3652 x86_64_test_reg_reg(cd, s1, s1);
3653 x86_64_jcc(cd, X86_64_CC_E, s3);
3656 x86_64_mov_membase_reg(cd, s1,
3657 OFFSET(java_objectheader, vftbl),
3661 codegen_addpatchref(cd, PATCHER_instanceof_class,
3662 (constant_classref *) iptr->target, 0);
3664 if (opt_showdisassemble) {
3665 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3669 x86_64_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
3670 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3671 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3673 x86_64_movl_membase_reg(cd, REG_ITMP1,
3674 OFFSET(vftbl_t, baseval),
3676 x86_64_movl_membase_reg(cd, REG_ITMP2,
3677 OFFSET(vftbl_t, diffval),
3679 x86_64_movl_membase_reg(cd, REG_ITMP2,
3680 OFFSET(vftbl_t, baseval),
3682 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3683 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3685 x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
3686 x86_64_alu_reg_reg(cd, X86_64_XOR, d, d); /* may be REG_ITMP2 */
3687 x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP3, REG_ITMP1);
3688 x86_64_setcc_reg(cd, X86_64_CC_BE, d);
3690 emit_store(jd, iptr, iptr->dst, d);
3694 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3695 /* op1 = dimension, val.a = class */
3697 /* check for negative sizes and copy sizes to stack if necessary */
3699 MCODECHECK((10 * 4 * iptr->op1) + 5 + 10 * 8);
3701 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3702 /* copy SAVEDVAR sizes to stack */
3704 if (src->varkind != ARGVAR) {
3705 s2 = emit_load_s2(jd, iptr, src, REG_ITMP1);
3706 M_LST(s2, REG_SP, s1 * 8);
3710 /* is a patcher function set? */
3712 if (iptr->val.a == NULL) {
3713 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
3714 (constant_classref *) iptr->target, 0);
3716 if (opt_showdisassemble) {
3717 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3723 a = (ptrint) iptr->val.a;
3726 /* a0 = dimension count */
3728 M_MOV_IMM(iptr->op1, rd->argintregs[0]);
3730 /* a1 = arrayvftbl */
3732 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3734 /* a2 = pointer to dimensions = stack pointer */
3736 M_MOV(REG_SP, rd->argintregs[2]);
3738 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3741 /* check for exception before result assignment */
3745 codegen_add_fillinstacktrace_ref(cd);
3747 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3748 M_INTMOVE(REG_RESULT, s1);
3749 emit_store(jd, iptr, iptr->dst, s1);
3753 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3757 } /* for instruction */
3759 /* copy values to interface registers */
3761 src = bptr->outstack;
3762 len = bptr->outdepth;
3764 #if defined(ENABLE_LSRA)
3769 if ((src->varkind != STACKVAR)) {
3771 if (IS_FLT_DBL_TYPE(s2)) {
3772 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
3773 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3774 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3777 x86_64_movq_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3781 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3782 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3783 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3786 x86_64_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3793 /* At the end of a basic block we may have to append some nops,
3794 because the patcher stub calling code might be longer than the
3795 actual instruction. So codepatching does not change the
3796 following block unintentionally. */
3798 if (cd->mcodeptr < cd->lastmcodeptr) {
3799 while (cd->mcodeptr < cd->lastmcodeptr) {
3804 } /* if (bptr -> flags >= BBREACHED) */
3805 } /* for basic block */
3807 dseg_createlinenumbertable(cd);
3810 /* generate exception and patcher stubs */
3819 savedmcodeptr = NULL;
3821 /* generate exception stubs */
3823 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
3824 gen_resolvebranch(cd->mcodebase + eref->branchpos,
3826 cd->mcodeptr - cd->mcodebase);
3830 /* Check if the exception is an
3831 ArrayIndexOutOfBoundsException. If so, move index register
3834 if (eref->reg != -1)
3835 M_MOV(eref->reg, rd->argintregs[4]);
3837 /* calcuate exception address */
3839 M_MOV_IMM(0, rd->argintregs[3]);
3841 M_AADD_IMM32(eref->branchpos - 6, rd->argintregs[3]);
3843 /* move function to call into REG_ITMP3 */
3845 M_MOV_IMM(eref->function, REG_ITMP3);
3847 if (savedmcodeptr != NULL) {
3848 M_JMP_IMM(savedmcodeptr - cd->mcodeptr - 5);
3851 savedmcodeptr = cd->mcodeptr;
3853 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[0]);
3854 M_MOV(REG_SP, rd->argintregs[1]);
3855 M_ALD(rd->argintregs[2], REG_SP, stackframesize * 8);
3857 M_ASUB_IMM(2 * 8, REG_SP);
3858 M_AST(rd->argintregs[3], REG_SP, 0 * 8); /* store XPC */
3862 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3863 M_AADD_IMM(2 * 8, REG_SP);
3865 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
3871 /* generate code patching stub call code */
3873 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3874 /* check size of code segment */
3878 /* Get machine code which is patched back in later. A
3879 `call rel32' is 5 bytes long (but read 8 bytes). */
3881 savedmcodeptr = cd->mcodebase + pref->branchpos;
3882 mcode = *((ptrint *) savedmcodeptr);
3884 /* patch in `call rel32' to call the following code */
3886 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
3887 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
3889 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
3891 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3893 /* move pointer to java_objectheader onto stack */
3895 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3896 /* create a virtual java_objectheader */
3898 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3899 a = dseg_addaddress(cd, NULL); /* vftbl */
3901 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + a, REG_ITMP3);
3907 /* move machine code bytes and classinfo pointer into registers */
3909 M_MOV_IMM(mcode, REG_ITMP3);
3911 M_MOV_IMM(pref->ref, REG_ITMP3);
3913 M_MOV_IMM(pref->disp, REG_ITMP3);
3916 M_MOV_IMM(pref->patcher, REG_ITMP3);
3919 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
3924 /* generate replacement-out stubs */
3929 replacementpoint = jd->code->rplpoints;
3931 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
3932 /* check code segment size */
3936 /* note start of stub code */
3938 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
3940 /* make machine code for patching */
3942 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
3943 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
3945 /* push address of `rplpoint` struct */
3947 M_MOV_IMM(replacementpoint, REG_ITMP3);
3950 /* jump to replacement function */
3952 M_MOV_IMM(asm_replacement_out, REG_ITMP3);
3959 /* everything's ok */
3965 /* createcompilerstub **********************************************************
3967 Creates a stub routine which calls the compiler.
3969 *******************************************************************************/
3971 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
3972 #define COMPILERSTUB_CODESIZE 7 + 7 + 3
3974 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
3977 u1 *createcompilerstub(methodinfo *m)
3979 u1 *s; /* memory to hold the stub */
3984 s = CNEW(u1, COMPILERSTUB_SIZE);
3986 /* set data pointer and code pointer */
3989 s = s + COMPILERSTUB_DATASIZE;
3991 /* mark start of dump memory area */
3993 dumpsize = dump_size();
3995 cd = DNEW(codegendata);
3998 /* Store the methodinfo* in the same place as in the methodheader
3999 for compiled methods. */
4001 d[0] = (ptrint) asm_call_jit_compiler;
4004 /* code for the stub */
4006 M_ALD(REG_ITMP1, RIP, -(7 * 1 + 1 * SIZEOF_VOID_P)); /* methodinfo */
4007 M_ALD(REG_ITMP3, RIP, -(7 * 2 + 2 * SIZEOF_VOID_P)); /* compiler pointer */
4010 #if defined(ENABLE_STATISTICS)
4012 count_cstub_len += COMPILERSTUB_SIZE;
4015 /* release dump area */
4017 dump_release(dumpsize);
4023 /* createnativestub ************************************************************
4025 Creates a stub routine which calls a native method.
4027 *******************************************************************************/
4029 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
4035 s4 stackframesize; /* size of stackframe if needed */
4037 s4 i, j; /* count variables */
4041 /* get required compiler data */
4047 /* initialize variables */
4050 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4052 /* calculate stack frame size */
4055 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4056 sizeof(localref_table) / SIZEOF_VOID_P +
4057 INT_ARG_CNT + FLT_ARG_CNT + 1 + /* + 1 for function address */
4060 if (!(stackframesize & 0x1)) /* keep stack 16-byte aligned */
4063 /* create method header */
4065 (void) dseg_addaddress(cd, m); /* MethodPointer */
4066 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4067 (void) dseg_adds4(cd, 0); /* IsSync */
4068 (void) dseg_adds4(cd, 0); /* IsLeaf */
4069 (void) dseg_adds4(cd, 0); /* IntSave */
4070 (void) dseg_adds4(cd, 0); /* FltSave */
4071 (void) dseg_addlinenumbertablesize(cd);
4072 (void) dseg_adds4(cd, 0); /* ExTableSize */
4074 /* generate native method profiling code */
4077 /* count frequency */
4079 M_MOV_IMM(m, REG_ITMP2);
4080 M_IINC_MEMBASE(REG_ITMP2, OFFSET(methodinfo, frequency));
4083 /* generate stub code */
4085 M_ASUB_IMM(stackframesize * 8, REG_SP);
4087 #if !defined(NDEBUG)
4088 /* generate call trace */
4090 if (opt_verbosecall) {
4091 /* save integer and float argument registers */
4093 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4094 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4095 M_LST(rd->argintregs[j++], REG_SP, (1 + i) * 8);
4097 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4098 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4099 M_DST(rd->argfltregs[j++], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4101 /* show integer hex code for float arguments */
4103 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++) {
4104 /* if the paramtype is a float, we have to right shift all
4105 following integer registers */
4107 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4108 for (s1 = INT_ARG_CNT - 2; s1 >= i; s1--)
4109 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
4111 x86_64_movd_freg_reg(cd, rd->argfltregs[j], rd->argintregs[i]);
4116 M_MOV_IMM(m, REG_ITMP1);
4117 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4118 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
4121 /* restore integer and float argument registers */
4123 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4124 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4125 M_LLD(rd->argintregs[j++], REG_SP, (1 + i) * 8);
4127 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4128 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4129 M_DLD(rd->argfltregs[j++], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4131 #endif /* !defined(NDEBUG) */
4133 /* get function address (this must happen before the stackframeinfo) */
4135 #if !defined(WITH_STATIC_CLASSPATH)
4137 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
4139 if (opt_showdisassemble) {
4140 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4145 M_MOV_IMM(f, REG_ITMP3);
4148 /* save integer and float argument registers */
4150 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4151 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4152 M_LST(rd->argintregs[j++], REG_SP, i * 8);
4154 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4155 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4156 M_DST(rd->argfltregs[j++], REG_SP, (INT_ARG_CNT + i) * 8);
4158 M_AST(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4160 /* create dynamic stack info */
4162 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4163 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[1]);
4164 M_ALEA(REG_SP, stackframesize * 8 + SIZEOF_VOID_P, rd->argintregs[2]);
4165 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8);
4166 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
4169 /* restore integer and float argument registers */
4171 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4172 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4173 M_LLD(rd->argintregs[j++], REG_SP, i * 8);
4175 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4176 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4177 M_DLD(rd->argfltregs[j++], REG_SP, (INT_ARG_CNT + i) * 8);
4179 M_ALD(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4182 /* copy or spill arguments to new locations */
4184 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4185 t = md->paramtypes[i].type;
4187 if (IS_INT_LNG_TYPE(t)) {
4188 if (!md->params[i].inmemory) {
4189 s1 = rd->argintregs[md->params[i].regoff];
4191 if (!nmd->params[j].inmemory) {
4192 s2 = rd->argintregs[nmd->params[j].regoff];
4196 s2 = nmd->params[j].regoff;
4197 M_LST(s1, REG_SP, s2 * 8);
4201 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4202 s2 = nmd->params[j].regoff;
4203 M_LLD(REG_ITMP1, REG_SP, s1 * 8);
4204 M_LST(REG_ITMP1, REG_SP, s2 * 8);
4208 /* We only copy spilled float arguments, as the float argument */
4209 /* registers keep unchanged. */
4211 if (md->params[i].inmemory) {
4212 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4213 s2 = nmd->params[j].regoff;
4214 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4215 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4220 /* put class into second argument register */
4222 if (m->flags & ACC_STATIC)
4223 M_MOV_IMM(m->class, rd->argintregs[1]);
4225 /* put env into first argument register */
4227 M_MOV_IMM(_Jv_env, rd->argintregs[0]);
4229 /* do the native function call */
4233 /* save return value */
4235 if (md->returntype.type != TYPE_VOID) {
4236 if (IS_INT_LNG_TYPE(md->returntype.type))
4237 M_LST(REG_RESULT, REG_SP, 0 * 8);
4239 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4242 /* remove native stackframe info */
4244 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4245 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
4248 #if !defined(NDEBUG)
4249 /* generate call trace */
4251 if (opt_verbosecall) {
4252 /* just restore the value we need, don't care about the other */
4254 if (md->returntype.type != TYPE_VOID) {
4255 if (IS_INT_LNG_TYPE(md->returntype.type))
4256 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4258 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4261 M_MOV_IMM(m, rd->argintregs[0]);
4262 M_MOV(REG_RESULT, rd->argintregs[1]);
4263 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4264 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4266 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
4269 #endif /* !defined(NDEBUG) */
4271 /* check for exception */
4273 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4274 M_MOV_IMM(builtin_get_exceptionptrptr, REG_ITMP3);
4277 M_MOV_IMM(&_no_threads_exceptionptr, REG_RESULT);
4279 M_ALD(REG_ITMP2, REG_RESULT, 0);
4281 /* restore return value */
4283 if (md->returntype.type != TYPE_VOID) {
4284 if (IS_INT_LNG_TYPE(md->returntype.type))
4285 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4287 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4290 /* test for exception */
4295 /* remove stackframe */
4297 M_AADD_IMM(stackframesize * 8, REG_SP);
4301 /* handle exception */
4303 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4304 M_LST(REG_ITMP2, REG_SP, 0 * 8);
4305 M_MOV_IMM(builtin_get_exceptionptrptr, REG_ITMP3);
4307 M_AST_IMM32(0, REG_RESULT, 0); /* clear exception pointer */
4308 M_LLD(REG_ITMP1_XPTR, REG_SP, 0 * 8);
4310 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
4311 M_MOV_IMM(&_no_threads_exceptionptr, REG_ITMP3);
4312 M_AST_IMM32(0, REG_ITMP3, 0); /* clear exception pointer */
4315 /* remove stackframe */
4317 M_AADD_IMM(stackframesize * 8, REG_SP);
4319 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
4320 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
4322 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4326 /* process patcher calls **************************************************/
4333 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4337 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4338 /* Get machine code which is patched back in later. A
4339 `call rel32' is 5 bytes long (but read 8 bytes). */
4341 savedmcodeptr = cd->mcodebase + pref->branchpos;
4342 mcode = *((ptrint *) savedmcodeptr);
4344 /* patch in `call rel32' to call the following code */
4346 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4347 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
4349 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
4351 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4353 /* move pointer to java_objectheader onto stack */
4355 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4356 /* create a virtual java_objectheader */
4358 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4359 disp = dseg_addaddress(cd, NULL); /* vftbl */
4361 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP3);
4367 /* move machine code bytes and classinfo pointer into registers */
4369 M_MOV_IMM(mcode, REG_ITMP3);
4371 M_MOV_IMM(pref->ref, REG_ITMP3);
4373 M_MOV_IMM(pref->disp, REG_ITMP3);
4376 M_MOV_IMM(pref->patcher, REG_ITMP3);
4379 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
4386 return jd->code->entrypoint;
4391 * These are local overrides for various environment variables in Emacs.
4392 * Please do not remove this and leave it at the end of the file, where
4393 * Emacs will automagically detect them.
4394 * ---------------------------------------------------------------------
4397 * indent-tabs-mode: t
4401 * vim:noexpandtab:sw=4:ts=4: