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 4690 2006-03-27 11:37:46Z twisti $
48 #include "vm/jit/x86_64/arch.h"
49 #include "vm/jit/x86_64/codegen.h"
50 #include "vm/jit/x86_64/emitfuncs.h"
52 #include "native/native.h"
53 #include "vm/builtin.h"
54 #include "vm/exceptions.h"
55 #include "vm/global.h"
56 #include "vm/loader.h"
57 #include "vm/options.h"
58 #include "vm/statistics.h"
59 #include "vm/stringlocal.h"
61 #include "vm/jit/asmpart.h"
62 #include "vm/jit/codegen-common.h"
63 #include "vm/jit/dseg.h"
64 #include "vm/jit/jit.h"
65 #include "vm/jit/methodheader.h"
66 #include "vm/jit/parse.h"
67 #include "vm/jit/patcher.h"
68 #include "vm/jit/reg.h"
69 #include "vm/jit/replace.h"
71 #if defined(ENABLE_LSRA)
72 # include "vm/jit/allocator/lsra.h"
78 /* codegen *********************************************************************
80 Generates machine code.
82 *******************************************************************************/
84 bool codegen(methodinfo *m, codegendata *cd, registerdata *rd)
86 s4 len, s1, s2, s3, d, disp;
95 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
96 builtintable_entry *bte;
98 rplpoint *replacementpoint;
100 /* prevent compiler warnings */
112 /* space to save used callee saved registers */
114 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
115 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
117 parentargs_base = rd->memuse + savedregs_num;
119 #if defined(USE_THREADS)
120 /* space to save argument of monitor_enter */
122 if (checksync && (m->flags & ACC_SYNCHRONIZED))
126 /* Keep stack of non-leaf functions 16-byte aligned for calls into native */
127 /* code e.g. libc or jni (alignment problems with movaps). */
129 if (!m->isleafmethod || opt_verbosecall)
130 parentargs_base |= 0x1;
132 /* create method header */
134 (void) dseg_addaddress(cd, m); /* MethodPointer */
135 (void) dseg_adds4(cd, parentargs_base * 8); /* FrameSize */
137 #if defined(USE_THREADS)
138 /* IsSync contains the offset relative to the stack pointer for the
139 argument of monitor_exit used in the exception handler. Since the
140 offset could be zero and give a wrong meaning of the flag it is
144 if (checksync && (m->flags & ACC_SYNCHRONIZED))
145 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
148 (void) dseg_adds4(cd, 0); /* IsSync */
150 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
151 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
152 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
154 (void) dseg_addlinenumbertablesize(cd);
156 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
158 /* create exception table */
160 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
161 dseg_addtarget(cd, ex->start);
162 dseg_addtarget(cd, ex->end);
163 dseg_addtarget(cd, ex->handler);
164 (void) dseg_addaddress(cd, ex->catchtype.cls);
167 /* initialize mcode variables */
169 cd->mcodeptr = (u1 *) cd->mcodebase;
170 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
172 /* initialize the last patcher pointer */
174 cd->lastmcodeptr = cd->mcodeptr;
176 /* generate method profiling code */
179 /* count frequency */
181 M_MOV_IMM(m, REG_ITMP3);
182 M_IINC_MEMBASE(REG_ITMP3, OFFSET(methodinfo, frequency));
187 /* create stack frame (if necessary) */
190 M_ASUB_IMM(parentargs_base * 8, REG_SP);
192 /* save used callee saved registers */
195 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
196 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
198 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
199 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
202 /* take arguments out of register or stack frame */
206 for (p = 0, l = 0; p < md->paramcount; p++) {
207 t = md->paramtypes[p].type;
208 var = &(rd->locals[l][t]);
210 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
214 s1 = md->params[p].regoff;
215 if (IS_INT_LNG_TYPE(t)) { /* integer args */
216 s2 = rd->argintregs[s1];
217 if (!md->params[p].inmemory) { /* register arguments */
218 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
219 M_INTMOVE(s2, var->regoff);
221 } else { /* reg arg -> spilled */
222 M_LST(s2, REG_SP, var->regoff * 8);
225 } else { /* stack arguments */
226 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
227 /* + 8 for return address */
228 M_LLD(var->regoff, REG_SP, (parentargs_base + s1) * 8 + 8);
230 } else { /* stack arg -> spilled */
231 var->regoff = parentargs_base + s1 + 1;
235 } else { /* floating args */
236 if (!md->params[p].inmemory) { /* register arguments */
237 s2 = rd->argfltregs[s1];
238 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
239 M_FLTMOVE(s2, var->regoff);
241 } else { /* reg arg -> spilled */
242 M_DST(s2, REG_SP, var->regoff * 8);
245 } else { /* stack arguments */
246 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
247 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 8 + 8);
250 var->regoff = parentargs_base + s1 + 1;
256 /* save monitorenter argument */
258 #if defined(USE_THREADS)
259 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
260 /* stack offset for monitor argument */
264 if (opt_verbosecall) {
265 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
267 for (p = 0; p < INT_ARG_CNT; p++)
268 M_LST(rd->argintregs[p], REG_SP, p * 8);
270 for (p = 0; p < FLT_ARG_CNT; p++)
271 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
273 s1 += INT_ARG_CNT + FLT_ARG_CNT;
276 /* decide which monitor enter function to call */
278 if (m->flags & ACC_STATIC) {
279 M_MOV_IMM(m->class, REG_ITMP1);
280 M_AST(REG_ITMP1, REG_SP, s1 * 8);
281 M_INTMOVE(REG_ITMP1, rd->argintregs[0]);
282 M_MOV_IMM(BUILTIN_staticmonitorenter, REG_ITMP1);
286 M_TEST(rd->argintregs[0]);
288 codegen_add_nullpointerexception_ref(cd, cd->mcodeptr);
289 M_AST(rd->argintregs[0], REG_SP, s1 * 8);
290 M_MOV_IMM(BUILTIN_monitorenter, REG_ITMP1);
294 if (opt_verbosecall) {
295 for (p = 0; p < INT_ARG_CNT; p++)
296 M_LLD(rd->argintregs[p], REG_SP, p * 8);
298 for (p = 0; p < FLT_ARG_CNT; p++)
299 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
301 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
307 /* Copy argument registers to stack and call trace function with
308 pointer to arguments on stack. */
310 if (opt_verbosecall) {
311 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
313 /* save integer argument registers */
315 for (p = 0; p < INT_ARG_CNT; p++)
316 M_LST(rd->argintregs[p], REG_SP, (1 + p) * 8);
318 /* save float argument registers */
320 for (p = 0; p < FLT_ARG_CNT; p++)
321 M_DST(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
323 /* save temporary registers for leaf methods */
325 if (m->isleafmethod) {
326 for (p = 0; p < INT_TMP_CNT; p++)
327 M_LST(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
329 for (p = 0; p < FLT_TMP_CNT; p++)
330 M_DST(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
333 /* show integer hex code for float arguments */
335 for (p = 0, l = 0; p < md->paramcount && p < INT_ARG_CNT; p++) {
336 /* If the paramtype is a float, we have to right shift all
337 following integer registers. */
339 if (IS_FLT_DBL_TYPE(md->paramtypes[p].type)) {
340 for (s1 = INT_ARG_CNT - 2; s1 >= p; s1--) {
341 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
344 x86_64_movd_freg_reg(cd, rd->argfltregs[l], rd->argintregs[p]);
349 M_MOV_IMM(m, REG_ITMP2);
350 M_AST(REG_ITMP2, REG_SP, 0 * 8);
351 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
354 /* restore integer argument registers */
356 for (p = 0; p < INT_ARG_CNT; p++)
357 M_LLD(rd->argintregs[p], REG_SP, (1 + p) * 8);
359 /* restore float argument registers */
361 for (p = 0; p < FLT_ARG_CNT; p++)
362 M_DLD(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
364 /* restore temporary registers for leaf methods */
366 if (m->isleafmethod) {
367 for (p = 0; p < INT_TMP_CNT; p++)
368 M_LLD(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
370 for (p = 0; p < FLT_TMP_CNT; p++)
371 M_DLD(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
374 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
376 #endif /* !defined(NDEBUG) */
380 /* end of header generation */
382 replacementpoint = cd->code->rplpoints;
384 /* walk through all basic blocks */
386 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
388 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
390 if (bptr->flags >= BBREACHED) {
392 /* branch resolving */
395 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
396 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
401 /* handle replacement points */
403 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
404 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
408 assert(cd->lastmcodeptr <= cd->mcodeptr);
409 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
412 /* copy interface registers to their destination */
418 /* generate basicblock profiling code */
421 /* count frequency */
423 M_MOV_IMM(m->bbfrequency, REG_ITMP2);
424 M_IINC_MEMBASE(REG_ITMP2, bptr->debug_nr * 4);
426 /* if this is an exception handler, start profiling again */
428 if (bptr->type == BBTYPE_EXH)
432 #if defined(ENABLE_LSRA)
434 while (src != NULL) {
436 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
437 if (bptr->type == BBTYPE_SBR) {
438 /* d = reg_of_var(rd, src, REG_ITMP1); */
439 if (!(src->flags & INMEMORY))
443 x86_64_pop_reg(cd, d);
444 store_reg_to_var_int(src, d);
446 } else if (bptr->type == BBTYPE_EXH) {
447 /* d = reg_of_var(rd, src, REG_ITMP1); */
448 if (!(src->flags & INMEMORY))
452 M_INTMOVE(REG_ITMP1, d);
453 store_reg_to_var_int(src, d);
462 while (src != NULL) {
464 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
465 if (bptr->type == BBTYPE_SBR) {
466 d = reg_of_var(rd, src, REG_ITMP1);
468 store_reg_to_var_int(src, d);
470 } else if (bptr->type == BBTYPE_EXH) {
471 d = reg_of_var(rd, src, REG_ITMP1);
472 M_INTMOVE(REG_ITMP1, d);
473 store_reg_to_var_int(src, d);
477 d = reg_of_var(rd, src, REG_ITMP1);
478 if ((src->varkind != STACKVAR)) {
480 if (IS_FLT_DBL_TYPE(s2)) {
481 s1 = rd->interfaces[len][s2].regoff;
483 if (!(rd->interfaces[len][s2].flags & INMEMORY))
486 M_DLD(d, REG_SP, s1 * 8);
488 store_reg_to_var_flt(src, d);
491 s1 = rd->interfaces[len][s2].regoff;
493 if (!(rd->interfaces[len][s2].flags & INMEMORY))
496 M_LLD(d, REG_SP, s1 * 8);
498 store_reg_to_var_int(src, d);
504 #if defined(ENABLE_LSRA)
507 /* walk through all instructions */
513 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
514 if (iptr->line != currentline) {
515 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
516 currentline = iptr->line;
519 MCODECHECK(1024); /* 1KB should be enough */
522 case ICMD_INLINE_START: /* internal ICMDs */
523 case ICMD_INLINE_END:
526 case ICMD_NOP: /* ... ==> ... */
529 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
531 if (src->flags & INMEMORY)
532 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8);
536 codegen_add_nullpointerexception_ref(cd, cd->mcodeptr);
539 /* constant operations ************************************************/
541 case ICMD_ICONST: /* ... ==> ..., constant */
542 /* op1 = 0, val.i = constant */
544 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
545 if (iptr->val.i == 0)
548 M_IMOV_IMM(iptr->val.i, d);
549 store_reg_to_var_int(iptr->dst, d);
552 case ICMD_LCONST: /* ... ==> ..., constant */
553 /* op1 = 0, val.l = constant */
555 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
556 if (iptr->val.l == 0)
559 M_MOV_IMM(iptr->val.l, d);
560 store_reg_to_var_int(iptr->dst, d);
563 case ICMD_FCONST: /* ... ==> ..., constant */
564 /* op1 = 0, val.f = constant */
566 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
567 disp = dseg_addfloat(cd, iptr->val.f);
568 x86_64_movdl_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + ((d > 7) ? 9 : 8)) - (s8) cd->mcodebase) + disp, d);
569 store_reg_to_var_flt(iptr->dst, d);
572 case ICMD_DCONST: /* ... ==> ..., constant */
573 /* op1 = 0, val.d = constant */
575 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
576 disp = dseg_adddouble(cd, iptr->val.d);
577 x86_64_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, d);
578 store_reg_to_var_flt(iptr->dst, d);
581 case ICMD_ACONST: /* ... ==> ..., constant */
582 /* op1 = 0, val.a = constant */
584 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
586 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
587 /* PROFILE_CYCLE_STOP; */
589 codegen_addpatchref(cd, cd->mcodeptr,
591 (unresolved_class *) iptr->target, 0);
593 if (opt_showdisassemble) {
594 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
597 /* PROFILE_CYCLE_START; */
599 M_MOV_IMM(iptr->val.a, d);
602 if (iptr->val.a == 0)
605 M_MOV_IMM(iptr->val.a, d);
607 store_reg_to_var_int(iptr->dst, d);
611 /* load/store operations **********************************************/
613 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
614 /* op1 = local variable */
616 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
617 if ((iptr->dst->varkind == LOCALVAR) &&
618 (iptr->dst->varnum == iptr->op1)) {
621 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
622 if (var->flags & INMEMORY) {
623 x86_64_movl_membase_reg(cd, REG_SP, var->regoff * 8, d);
624 store_reg_to_var_int(iptr->dst, d);
627 if (iptr->dst->flags & INMEMORY) {
628 x86_64_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
631 M_INTMOVE(var->regoff, d);
636 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
637 case ICMD_ALOAD: /* op1 = local variable */
639 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
640 if ((iptr->dst->varkind == LOCALVAR) &&
641 (iptr->dst->varnum == iptr->op1)) {
644 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
645 if (var->flags & INMEMORY) {
646 x86_64_mov_membase_reg(cd, REG_SP, var->regoff * 8, d);
647 store_reg_to_var_int(iptr->dst, d);
650 if (iptr->dst->flags & INMEMORY) {
651 x86_64_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
654 M_INTMOVE(var->regoff, d);
659 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
660 case ICMD_DLOAD: /* op1 = local variable */
662 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
663 if ((iptr->dst->varkind == LOCALVAR) &&
664 (iptr->dst->varnum == iptr->op1)) {
667 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
668 if (var->flags & INMEMORY) {
669 x86_64_movq_membase_reg(cd, REG_SP, var->regoff * 8, d);
670 store_reg_to_var_flt(iptr->dst, d);
673 if (iptr->dst->flags & INMEMORY) {
674 x86_64_movq_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
677 M_FLTMOVE(var->regoff, d);
682 case ICMD_ISTORE: /* ..., value ==> ... */
683 case ICMD_LSTORE: /* op1 = local variable */
686 if ((src->varkind == LOCALVAR) &&
687 (src->varnum == iptr->op1)) {
690 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
691 if (var->flags & INMEMORY) {
692 var_to_reg_int(s1, src, REG_ITMP1);
693 x86_64_mov_reg_membase(cd, s1, REG_SP, var->regoff * 8);
696 var_to_reg_int(s1, src, var->regoff);
697 M_INTMOVE(s1, var->regoff);
701 case ICMD_FSTORE: /* ..., value ==> ... */
702 case ICMD_DSTORE: /* op1 = local variable */
704 if ((src->varkind == LOCALVAR) &&
705 (src->varnum == iptr->op1)) {
708 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
709 if (var->flags & INMEMORY) {
710 var_to_reg_flt(s1, src, REG_FTMP1);
711 x86_64_movq_reg_membase(cd, s1, REG_SP, var->regoff * 8);
714 var_to_reg_flt(s1, src, var->regoff);
715 M_FLTMOVE(s1, var->regoff);
720 /* pop/dup/swap operations ********************************************/
722 /* attention: double and longs are only one entry in CACAO ICMDs */
724 case ICMD_POP: /* ..., value ==> ... */
725 case ICMD_POP2: /* ..., value, value ==> ... */
728 case ICMD_DUP: /* ..., a ==> ..., a, a */
729 M_COPY(src, iptr->dst);
732 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
734 M_COPY(src, iptr->dst);
735 M_COPY(src->prev, iptr->dst->prev);
736 M_COPY(iptr->dst, iptr->dst->prev->prev);
739 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
741 M_COPY(src, iptr->dst);
742 M_COPY(src->prev, iptr->dst->prev);
743 M_COPY(src->prev->prev, iptr->dst->prev->prev);
744 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
747 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
749 M_COPY(src, iptr->dst);
750 M_COPY(src->prev, iptr->dst->prev);
753 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
755 M_COPY(src, iptr->dst);
756 M_COPY(src->prev, iptr->dst->prev);
757 M_COPY(src->prev->prev, iptr->dst->prev->prev);
758 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
759 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
762 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
764 M_COPY(src, iptr->dst);
765 M_COPY(src->prev, iptr->dst->prev);
766 M_COPY(src->prev->prev, iptr->dst->prev->prev);
767 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
768 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
769 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
772 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
774 M_COPY(src, iptr->dst->prev);
775 M_COPY(src->prev, iptr->dst);
779 /* integer operations *************************************************/
781 case ICMD_INEG: /* ..., value ==> ..., - value */
783 d = reg_of_var(rd, iptr->dst, REG_NULL);
784 if (iptr->dst->flags & INMEMORY) {
785 if (src->flags & INMEMORY) {
786 if (src->regoff == iptr->dst->regoff) {
787 x86_64_negl_membase(cd, REG_SP, iptr->dst->regoff * 8);
790 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
791 x86_64_negl_reg(cd, REG_ITMP1);
792 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
796 x86_64_movl_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
797 x86_64_negl_membase(cd, REG_SP, iptr->dst->regoff * 8);
801 if (src->flags & INMEMORY) {
802 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
803 x86_64_negl_reg(cd, d);
806 M_INTMOVE(src->regoff, iptr->dst->regoff);
807 x86_64_negl_reg(cd, iptr->dst->regoff);
812 case ICMD_LNEG: /* ..., value ==> ..., - value */
814 d = reg_of_var(rd, iptr->dst, REG_NULL);
815 if (iptr->dst->flags & INMEMORY) {
816 if (src->flags & INMEMORY) {
817 if (src->regoff == iptr->dst->regoff) {
818 x86_64_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
821 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
822 x86_64_neg_reg(cd, REG_ITMP1);
823 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
827 x86_64_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
828 x86_64_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
832 if (src->flags & INMEMORY) {
833 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
834 x86_64_neg_reg(cd, iptr->dst->regoff);
837 M_INTMOVE(src->regoff, iptr->dst->regoff);
838 x86_64_neg_reg(cd, iptr->dst->regoff);
843 case ICMD_I2L: /* ..., value ==> ..., value */
845 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
846 if (src->flags & INMEMORY) {
847 x86_64_movslq_membase_reg(cd, REG_SP, src->regoff * 8, d);
850 x86_64_movslq_reg_reg(cd, src->regoff, d);
852 store_reg_to_var_int(iptr->dst, d);
855 case ICMD_L2I: /* ..., value ==> ..., value */
857 var_to_reg_int(s1, src, REG_ITMP1);
858 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
860 store_reg_to_var_int(iptr->dst, d);
863 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
865 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
866 if (src->flags & INMEMORY) {
867 x86_64_movsbq_membase_reg(cd, REG_SP, src->regoff * 8, d);
870 x86_64_movsbq_reg_reg(cd, src->regoff, d);
872 store_reg_to_var_int(iptr->dst, d);
875 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
877 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
878 if (src->flags & INMEMORY) {
879 x86_64_movzwq_membase_reg(cd, REG_SP, src->regoff * 8, d);
882 x86_64_movzwq_reg_reg(cd, src->regoff, d);
884 store_reg_to_var_int(iptr->dst, d);
887 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
889 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
890 if (src->flags & INMEMORY) {
891 x86_64_movswq_membase_reg(cd, REG_SP, src->regoff * 8, d);
894 x86_64_movswq_reg_reg(cd, src->regoff, d);
896 store_reg_to_var_int(iptr->dst, d);
900 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
902 d = reg_of_var(rd, iptr->dst, REG_NULL);
903 x86_64_emit_ialu(cd, X86_64_ADD, src, iptr);
906 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
907 /* val.i = constant */
909 d = reg_of_var(rd, iptr->dst, REG_NULL);
910 x86_64_emit_ialuconst(cd, X86_64_ADD, src, iptr);
913 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
915 d = reg_of_var(rd, iptr->dst, REG_NULL);
916 x86_64_emit_lalu(cd, X86_64_ADD, src, iptr);
919 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
920 /* val.l = constant */
922 d = reg_of_var(rd, iptr->dst, REG_NULL);
923 x86_64_emit_laluconst(cd, X86_64_ADD, src, iptr);
926 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
928 d = reg_of_var(rd, iptr->dst, REG_NULL);
929 if (iptr->dst->flags & INMEMORY) {
930 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
931 if (src->prev->regoff == iptr->dst->regoff) {
932 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
933 x86_64_alul_reg_membase(cd, X86_64_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
936 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
937 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
938 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
941 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
942 M_INTMOVE(src->prev->regoff, REG_ITMP1);
943 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
944 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
946 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
947 if (src->prev->regoff == iptr->dst->regoff) {
948 x86_64_alul_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
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 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
957 x86_64_movl_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
958 x86_64_alul_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
962 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
963 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
964 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
966 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
967 M_INTMOVE(src->prev->regoff, d);
968 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
970 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
971 /* workaround for reg alloc */
972 if (src->regoff == iptr->dst->regoff) {
973 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
974 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
975 M_INTMOVE(REG_ITMP1, d);
978 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
979 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, d);
983 /* workaround for reg alloc */
984 if (src->regoff == iptr->dst->regoff) {
985 M_INTMOVE(src->prev->regoff, REG_ITMP1);
986 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
987 M_INTMOVE(REG_ITMP1, d);
990 M_INTMOVE(src->prev->regoff, d);
991 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, d);
997 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
998 /* val.i = constant */
1000 d = reg_of_var(rd, iptr->dst, REG_NULL);
1001 x86_64_emit_ialuconst(cd, X86_64_SUB, src, iptr);
1004 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1006 d = reg_of_var(rd, iptr->dst, REG_NULL);
1007 if (iptr->dst->flags & INMEMORY) {
1008 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1009 if (src->prev->regoff == iptr->dst->regoff) {
1010 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1011 x86_64_alu_reg_membase(cd, X86_64_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1014 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1015 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1016 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1019 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1020 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1021 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1022 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1024 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1025 if (src->prev->regoff == iptr->dst->regoff) {
1026 x86_64_alu_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
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 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1035 x86_64_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1036 x86_64_alu_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1040 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1041 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1042 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
1044 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1045 M_INTMOVE(src->prev->regoff, d);
1046 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
1048 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1049 /* workaround for reg alloc */
1050 if (src->regoff == iptr->dst->regoff) {
1051 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1052 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1053 M_INTMOVE(REG_ITMP1, d);
1056 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1057 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, d);
1061 /* workaround for reg alloc */
1062 if (src->regoff == iptr->dst->regoff) {
1063 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1064 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1065 M_INTMOVE(REG_ITMP1, d);
1068 M_INTMOVE(src->prev->regoff, d);
1069 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, d);
1075 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1076 /* val.l = constant */
1078 d = reg_of_var(rd, iptr->dst, REG_NULL);
1079 x86_64_emit_laluconst(cd, X86_64_SUB, src, iptr);
1082 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1084 d = reg_of_var(rd, iptr->dst, REG_NULL);
1085 if (iptr->dst->flags & INMEMORY) {
1086 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1087 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1088 x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1089 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1091 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1092 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1093 x86_64_imull_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1094 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1096 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1097 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1098 x86_64_imull_reg_reg(cd, src->regoff, REG_ITMP1);
1099 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1102 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1103 x86_64_imull_reg_reg(cd, src->regoff, REG_ITMP1);
1104 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1108 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1109 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1110 x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1112 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1113 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1114 x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1116 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1117 M_INTMOVE(src->regoff, iptr->dst->regoff);
1118 x86_64_imull_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1121 if (src->regoff == iptr->dst->regoff) {
1122 x86_64_imull_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1125 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1126 x86_64_imull_reg_reg(cd, src->regoff, iptr->dst->regoff);
1132 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1133 /* val.i = constant */
1135 d = reg_of_var(rd, iptr->dst, REG_NULL);
1136 if (iptr->dst->flags & INMEMORY) {
1137 if (src->flags & INMEMORY) {
1138 x86_64_imull_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1139 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1142 x86_64_imull_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1143 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1147 if (src->flags & INMEMORY) {
1148 x86_64_imull_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1151 if (iptr->val.i == 2) {
1152 M_INTMOVE(src->regoff, iptr->dst->regoff);
1153 x86_64_alul_reg_reg(cd, X86_64_ADD, iptr->dst->regoff, iptr->dst->regoff);
1156 x86_64_imull_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff); /* 3 cycles */
1162 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1164 d = reg_of_var(rd, iptr->dst, REG_NULL);
1165 if (iptr->dst->flags & INMEMORY) {
1166 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1167 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1168 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1169 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1171 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1172 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1173 x86_64_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1174 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1176 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1177 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1178 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1179 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1182 x86_64_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1183 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1184 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1188 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1189 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1190 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1192 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1193 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1194 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1196 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1197 M_INTMOVE(src->regoff, iptr->dst->regoff);
1198 x86_64_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1201 if (src->regoff == iptr->dst->regoff) {
1202 x86_64_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1205 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1206 x86_64_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1212 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1213 /* val.l = constant */
1215 d = reg_of_var(rd, iptr->dst, REG_NULL);
1216 if (iptr->dst->flags & INMEMORY) {
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, REG_ITMP1);
1222 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1223 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1225 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1228 if (IS_IMM32(iptr->val.l)) {
1229 x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, REG_ITMP1);
1232 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1233 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1235 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1239 if (src->flags & INMEMORY) {
1240 if (IS_IMM32(iptr->val.l)) {
1241 x86_64_imul_imm_membase_reg(cd, iptr->val.l, REG_SP, src->regoff * 8, iptr->dst->regoff);
1244 x86_64_mov_imm_reg(cd, iptr->val.l, iptr->dst->regoff);
1245 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1249 /* should match in many cases */
1250 if (iptr->val.l == 2) {
1251 M_INTMOVE(src->regoff, iptr->dst->regoff);
1252 x86_64_alul_reg_reg(cd, X86_64_ADD, iptr->dst->regoff, iptr->dst->regoff);
1255 if (IS_IMM32(iptr->val.l)) {
1256 x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, iptr->dst->regoff); /* 4 cycles */
1259 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1260 M_INTMOVE(src->regoff, iptr->dst->regoff);
1261 x86_64_imul_reg_reg(cd, REG_ITMP1, iptr->dst->regoff);
1268 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1270 d = reg_of_var(rd, iptr->dst, REG_NULL);
1271 if (src->prev->flags & INMEMORY) {
1272 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, RAX);
1275 M_INTMOVE(src->prev->regoff, RAX);
1278 if (src->flags & INMEMORY) {
1279 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1282 M_INTMOVE(src->regoff, REG_ITMP3);
1286 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1287 x86_64_jcc(cd, X86_64_CC_NE, 4 + 6);
1288 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3); /* 4 bytes */
1289 x86_64_jcc(cd, X86_64_CC_E, 3 + 1 + 3); /* 6 bytes */
1291 x86_64_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1293 x86_64_idivl_reg(cd, REG_ITMP3);
1295 if (iptr->dst->flags & INMEMORY) {
1296 x86_64_mov_reg_membase(cd, RAX, REG_SP, iptr->dst->regoff * 8);
1297 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1300 M_INTMOVE(RAX, iptr->dst->regoff);
1302 if (iptr->dst->regoff != RDX) {
1303 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1308 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1309 d = reg_of_var(rd, iptr->dst, REG_NULL);
1310 if (src->prev->flags & INMEMORY) {
1311 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, RAX);
1314 M_INTMOVE(src->prev->regoff, RAX);
1317 if (src->flags & INMEMORY) {
1318 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1321 M_INTMOVE(src->regoff, REG_ITMP3);
1325 x86_64_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1327 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1328 x86_64_jcc(cd, X86_64_CC_NE, 2 + 4 + 6);
1331 x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX); /* 2 bytes */
1332 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3); /* 4 bytes */
1333 x86_64_jcc(cd, X86_64_CC_E, 1 + 3); /* 6 bytes */
1336 x86_64_idivl_reg(cd, REG_ITMP3);
1338 if (iptr->dst->flags & INMEMORY) {
1339 x86_64_mov_reg_membase(cd, RDX, REG_SP, iptr->dst->regoff * 8);
1340 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1343 M_INTMOVE(RDX, iptr->dst->regoff);
1345 if (iptr->dst->regoff != RDX) {
1346 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1351 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1352 /* val.i = constant */
1354 var_to_reg_int(s1, src, REG_ITMP1);
1355 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1356 M_INTMOVE(s1, REG_ITMP1);
1357 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1358 x86_64_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1359 x86_64_cmovccl_reg_reg(cd, X86_64_CC_LE, REG_ITMP2, REG_ITMP1);
1360 x86_64_shiftl_imm_reg(cd, X86_64_SAR, iptr->val.i, REG_ITMP1);
1361 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1362 store_reg_to_var_int(iptr->dst, d);
1365 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1366 /* val.i = constant */
1368 var_to_reg_int(s1, src, REG_ITMP1);
1369 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1370 M_INTMOVE(s1, REG_ITMP1);
1371 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1372 x86_64_leal_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1373 x86_64_cmovccl_reg_reg(cd, X86_64_CC_G, REG_ITMP1, REG_ITMP2);
1374 x86_64_alul_imm_reg(cd, X86_64_AND, -1 - (iptr->val.i), REG_ITMP2);
1375 x86_64_alul_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
1376 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1377 store_reg_to_var_int(iptr->dst, d);
1381 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1383 d = reg_of_var(rd, iptr->dst, REG_NULL);
1385 if (src->prev->flags & INMEMORY) {
1386 M_LLD(RAX, REG_SP, src->prev->regoff * 8);
1389 M_INTMOVE(src->prev->regoff, RAX);
1392 if (src->flags & INMEMORY) {
1393 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1396 M_INTMOVE(src->regoff, REG_ITMP3);
1400 /* check as described in jvm spec */
1401 disp = dseg_adds8(cd, 0x8000000000000000LL);
1402 M_CMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, RAX);
1404 M_CMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1405 M_BEQ(3 + 2 + 3); /* 6 bytes */
1407 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1409 x86_64_idiv_reg(cd, REG_ITMP3);
1411 if (iptr->dst->flags & INMEMORY) {
1412 M_LST(RAX, REG_SP, iptr->dst->regoff * 8);
1413 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1416 M_INTMOVE(RAX, iptr->dst->regoff);
1418 if (iptr->dst->regoff != RDX) {
1419 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1424 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1426 d = reg_of_var(rd, iptr->dst, REG_NULL);
1427 if (src->prev->flags & INMEMORY) {
1428 M_LLD(REG_ITMP1, REG_SP, src->prev->regoff * 8);
1431 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1434 if (src->flags & INMEMORY) {
1435 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1438 M_INTMOVE(src->regoff, REG_ITMP3);
1442 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1444 /* check as described in jvm spec */
1445 disp = dseg_adds8(cd, 0x8000000000000000LL);
1446 M_CMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP1);
1450 x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX); /* 2 bytes */
1452 M_XOR(RDX, RDX); /* 3 bytes */
1453 M_CMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1454 M_BEQ(2 + 3); /* 6 bytes */
1457 x86_64_idiv_reg(cd, REG_ITMP3);
1459 if (iptr->dst->flags & INMEMORY) {
1460 M_LST(RDX, REG_SP, iptr->dst->regoff * 8);
1461 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1464 M_INTMOVE(RDX, iptr->dst->regoff);
1466 if (iptr->dst->regoff != RDX) {
1467 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1472 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1473 /* val.i = constant */
1475 var_to_reg_int(s1, src, REG_ITMP1);
1476 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1477 M_INTMOVE(s1, REG_ITMP1);
1478 x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1479 x86_64_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1480 x86_64_cmovcc_reg_reg(cd, X86_64_CC_LE, REG_ITMP2, REG_ITMP1);
1481 x86_64_shift_imm_reg(cd, X86_64_SAR, iptr->val.i, REG_ITMP1);
1482 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1483 store_reg_to_var_int(iptr->dst, d);
1486 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1487 /* val.l = constant */
1489 var_to_reg_int(s1, src, REG_ITMP1);
1490 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1491 M_INTMOVE(s1, REG_ITMP1);
1492 x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1493 x86_64_lea_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1494 x86_64_cmovcc_reg_reg(cd, X86_64_CC_G, REG_ITMP1, REG_ITMP2);
1495 x86_64_alu_imm_reg(cd, X86_64_AND, -1 - (iptr->val.i), REG_ITMP2);
1496 x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
1497 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1498 store_reg_to_var_int(iptr->dst, d);
1501 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1503 d = reg_of_var(rd, iptr->dst, REG_NULL);
1504 x86_64_emit_ishift(cd, X86_64_SHL, src, iptr);
1507 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1508 /* val.i = constant */
1510 d = reg_of_var(rd, iptr->dst, REG_NULL);
1511 x86_64_emit_ishiftconst(cd, X86_64_SHL, src, iptr);
1514 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1516 d = reg_of_var(rd, iptr->dst, REG_NULL);
1517 x86_64_emit_ishift(cd, X86_64_SAR, src, iptr);
1520 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1521 /* val.i = constant */
1523 d = reg_of_var(rd, iptr->dst, REG_NULL);
1524 x86_64_emit_ishiftconst(cd, X86_64_SAR, src, iptr);
1527 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1529 d = reg_of_var(rd, iptr->dst, REG_NULL);
1530 x86_64_emit_ishift(cd, X86_64_SHR, src, iptr);
1533 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1534 /* val.i = constant */
1536 d = reg_of_var(rd, iptr->dst, REG_NULL);
1537 x86_64_emit_ishiftconst(cd, X86_64_SHR, src, iptr);
1540 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1542 d = reg_of_var(rd, iptr->dst, REG_NULL);
1543 x86_64_emit_lshift(cd, X86_64_SHL, src, iptr);
1546 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1547 /* val.i = constant */
1549 d = reg_of_var(rd, iptr->dst, REG_NULL);
1550 x86_64_emit_lshiftconst(cd, X86_64_SHL, src, iptr);
1553 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1555 d = reg_of_var(rd, iptr->dst, REG_NULL);
1556 x86_64_emit_lshift(cd, X86_64_SAR, src, iptr);
1559 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1560 /* val.i = constant */
1562 d = reg_of_var(rd, iptr->dst, REG_NULL);
1563 x86_64_emit_lshiftconst(cd, X86_64_SAR, src, iptr);
1566 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1568 d = reg_of_var(rd, iptr->dst, REG_NULL);
1569 x86_64_emit_lshift(cd, X86_64_SHR, src, iptr);
1572 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1573 /* val.l = constant */
1575 d = reg_of_var(rd, iptr->dst, REG_NULL);
1576 x86_64_emit_lshiftconst(cd, X86_64_SHR, src, iptr);
1579 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1581 d = reg_of_var(rd, iptr->dst, REG_NULL);
1582 x86_64_emit_ialu(cd, X86_64_AND, src, iptr);
1585 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1586 /* val.i = constant */
1588 d = reg_of_var(rd, iptr->dst, REG_NULL);
1589 x86_64_emit_ialuconst(cd, X86_64_AND, src, iptr);
1592 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1594 d = reg_of_var(rd, iptr->dst, REG_NULL);
1595 x86_64_emit_lalu(cd, X86_64_AND, src, iptr);
1598 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1599 /* val.l = constant */
1601 d = reg_of_var(rd, iptr->dst, REG_NULL);
1602 x86_64_emit_laluconst(cd, X86_64_AND, src, iptr);
1605 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1607 d = reg_of_var(rd, iptr->dst, REG_NULL);
1608 x86_64_emit_ialu(cd, X86_64_OR, src, iptr);
1611 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1612 /* val.i = constant */
1614 d = reg_of_var(rd, iptr->dst, REG_NULL);
1615 x86_64_emit_ialuconst(cd, X86_64_OR, src, iptr);
1618 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1620 d = reg_of_var(rd, iptr->dst, REG_NULL);
1621 x86_64_emit_lalu(cd, X86_64_OR, src, iptr);
1624 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1625 /* val.l = constant */
1627 d = reg_of_var(rd, iptr->dst, REG_NULL);
1628 x86_64_emit_laluconst(cd, X86_64_OR, src, iptr);
1631 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1633 d = reg_of_var(rd, iptr->dst, REG_NULL);
1634 x86_64_emit_ialu(cd, X86_64_XOR, src, iptr);
1637 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1638 /* val.i = constant */
1640 d = reg_of_var(rd, iptr->dst, REG_NULL);
1641 x86_64_emit_ialuconst(cd, X86_64_XOR, src, iptr);
1644 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1646 d = reg_of_var(rd, iptr->dst, REG_NULL);
1647 x86_64_emit_lalu(cd, X86_64_XOR, src, iptr);
1650 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1651 /* val.l = constant */
1653 d = reg_of_var(rd, iptr->dst, REG_NULL);
1654 x86_64_emit_laluconst(cd, X86_64_XOR, src, iptr);
1658 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1659 /* op1 = variable, val.i = constant */
1661 /* using inc and dec is definitely faster than add -- tested */
1664 var = &(rd->locals[iptr->op1][TYPE_INT]);
1666 if (var->flags & INMEMORY) {
1667 if (iptr->val.i == 1) {
1668 x86_64_incl_membase(cd, REG_SP, d * 8);
1670 } else if (iptr->val.i == -1) {
1671 x86_64_decl_membase(cd, REG_SP, d * 8);
1674 x86_64_alul_imm_membase(cd, X86_64_ADD, iptr->val.i, REG_SP, d * 8);
1678 if (iptr->val.i == 1) {
1679 x86_64_incl_reg(cd, d);
1681 } else if (iptr->val.i == -1) {
1682 x86_64_decl_reg(cd, d);
1685 x86_64_alul_imm_reg(cd, X86_64_ADD, iptr->val.i, d);
1691 /* floating operations ************************************************/
1693 case ICMD_FNEG: /* ..., value ==> ..., - value */
1695 var_to_reg_flt(s1, src, REG_FTMP1);
1696 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1697 disp = dseg_adds4(cd, 0x80000000);
1699 x86_64_movss_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1700 x86_64_xorps_reg_reg(cd, REG_FTMP2, d);
1701 store_reg_to_var_flt(iptr->dst, d);
1704 case ICMD_DNEG: /* ..., value ==> ..., - value */
1706 var_to_reg_flt(s1, src, REG_FTMP1);
1707 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1708 disp = dseg_adds8(cd, 0x8000000000000000);
1710 x86_64_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1711 x86_64_xorpd_reg_reg(cd, REG_FTMP2, d);
1712 store_reg_to_var_flt(iptr->dst, d);
1715 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1717 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1718 var_to_reg_flt(s2, src, REG_FTMP2);
1719 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1721 x86_64_addss_reg_reg(cd, s2, d);
1722 } else if (s2 == d) {
1723 x86_64_addss_reg_reg(cd, s1, d);
1726 x86_64_addss_reg_reg(cd, s2, d);
1728 store_reg_to_var_flt(iptr->dst, d);
1731 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1733 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1734 var_to_reg_flt(s2, src, REG_FTMP2);
1735 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1737 x86_64_addsd_reg_reg(cd, s2, d);
1738 } else if (s2 == d) {
1739 x86_64_addsd_reg_reg(cd, s1, d);
1742 x86_64_addsd_reg_reg(cd, s2, d);
1744 store_reg_to_var_flt(iptr->dst, d);
1747 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1749 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1750 var_to_reg_flt(s2, src, REG_FTMP2);
1751 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1753 M_FLTMOVE(s2, REG_FTMP2);
1757 x86_64_subss_reg_reg(cd, s2, d);
1758 store_reg_to_var_flt(iptr->dst, d);
1761 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1763 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1764 var_to_reg_flt(s2, src, REG_FTMP2);
1765 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1767 M_FLTMOVE(s2, REG_FTMP2);
1771 x86_64_subsd_reg_reg(cd, s2, d);
1772 store_reg_to_var_flt(iptr->dst, d);
1775 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1777 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1778 var_to_reg_flt(s2, src, REG_FTMP2);
1779 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1781 x86_64_mulss_reg_reg(cd, s2, d);
1782 } else if (s2 == d) {
1783 x86_64_mulss_reg_reg(cd, s1, d);
1786 x86_64_mulss_reg_reg(cd, s2, d);
1788 store_reg_to_var_flt(iptr->dst, d);
1791 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1793 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1794 var_to_reg_flt(s2, src, REG_FTMP2);
1795 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1797 x86_64_mulsd_reg_reg(cd, s2, d);
1798 } else if (s2 == d) {
1799 x86_64_mulsd_reg_reg(cd, s1, d);
1802 x86_64_mulsd_reg_reg(cd, s2, d);
1804 store_reg_to_var_flt(iptr->dst, d);
1807 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1809 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1810 var_to_reg_flt(s2, src, REG_FTMP2);
1811 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1813 M_FLTMOVE(s2, REG_FTMP2);
1817 x86_64_divss_reg_reg(cd, s2, d);
1818 store_reg_to_var_flt(iptr->dst, d);
1821 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1823 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1824 var_to_reg_flt(s2, src, REG_FTMP2);
1825 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1827 M_FLTMOVE(s2, REG_FTMP2);
1831 x86_64_divsd_reg_reg(cd, s2, d);
1832 store_reg_to_var_flt(iptr->dst, d);
1835 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1837 var_to_reg_int(s1, src, REG_ITMP1);
1838 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1839 x86_64_cvtsi2ss_reg_reg(cd, s1, d);
1840 store_reg_to_var_flt(iptr->dst, d);
1843 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1845 var_to_reg_int(s1, src, REG_ITMP1);
1846 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1847 x86_64_cvtsi2sd_reg_reg(cd, s1, d);
1848 store_reg_to_var_flt(iptr->dst, d);
1851 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1853 var_to_reg_int(s1, src, REG_ITMP1);
1854 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1855 x86_64_cvtsi2ssq_reg_reg(cd, s1, d);
1856 store_reg_to_var_flt(iptr->dst, d);
1859 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1861 var_to_reg_int(s1, src, REG_ITMP1);
1862 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1863 x86_64_cvtsi2sdq_reg_reg(cd, s1, d);
1864 store_reg_to_var_flt(iptr->dst, d);
1867 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1869 var_to_reg_flt(s1, src, REG_FTMP1);
1870 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1871 x86_64_cvttss2si_reg_reg(cd, s1, d);
1872 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, d); /* corner cases */
1873 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1874 x86_64_jcc(cd, X86_64_CC_NE, a);
1875 M_FLTMOVE(s1, REG_FTMP1);
1876 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP2);
1877 x86_64_call_reg(cd, REG_ITMP2);
1878 M_INTMOVE(REG_RESULT, d);
1879 store_reg_to_var_int(iptr->dst, d);
1882 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1884 var_to_reg_flt(s1, src, REG_FTMP1);
1885 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1886 x86_64_cvttsd2si_reg_reg(cd, s1, d);
1887 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, d); /* corner cases */
1888 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1889 x86_64_jcc(cd, X86_64_CC_NE, a);
1890 M_FLTMOVE(s1, REG_FTMP1);
1891 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP2);
1892 x86_64_call_reg(cd, REG_ITMP2);
1893 M_INTMOVE(REG_RESULT, d);
1894 store_reg_to_var_int(iptr->dst, d);
1897 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1899 var_to_reg_flt(s1, src, REG_FTMP1);
1900 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1901 x86_64_cvttss2siq_reg_reg(cd, s1, d);
1902 x86_64_mov_imm_reg(cd, 0x8000000000000000, REG_ITMP2);
1903 x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, d); /* corner cases */
1904 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1905 x86_64_jcc(cd, X86_64_CC_NE, a);
1906 M_FLTMOVE(s1, REG_FTMP1);
1907 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP2);
1908 x86_64_call_reg(cd, REG_ITMP2);
1909 M_INTMOVE(REG_RESULT, d);
1910 store_reg_to_var_int(iptr->dst, d);
1913 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1915 var_to_reg_flt(s1, src, REG_FTMP1);
1916 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1917 x86_64_cvttsd2siq_reg_reg(cd, s1, d);
1918 x86_64_mov_imm_reg(cd, 0x8000000000000000, REG_ITMP2);
1919 x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, d); /* corner cases */
1920 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1921 x86_64_jcc(cd, X86_64_CC_NE, a);
1922 M_FLTMOVE(s1, REG_FTMP1);
1923 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP2);
1924 x86_64_call_reg(cd, REG_ITMP2);
1925 M_INTMOVE(REG_RESULT, d);
1926 store_reg_to_var_int(iptr->dst, d);
1929 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1931 var_to_reg_flt(s1, src, REG_FTMP1);
1932 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1933 x86_64_cvtss2sd_reg_reg(cd, s1, d);
1934 store_reg_to_var_flt(iptr->dst, d);
1937 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1939 var_to_reg_flt(s1, src, REG_FTMP1);
1940 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1941 x86_64_cvtsd2ss_reg_reg(cd, s1, d);
1942 store_reg_to_var_flt(iptr->dst, d);
1945 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1946 /* == => 0, < => 1, > => -1 */
1948 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1949 var_to_reg_flt(s2, src, REG_FTMP2);
1950 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1952 M_MOV_IMM(1, REG_ITMP1);
1953 M_MOV_IMM(-1, REG_ITMP2);
1954 x86_64_ucomiss_reg_reg(cd, s1, s2);
1955 M_CMOVB(REG_ITMP1, d);
1956 M_CMOVA(REG_ITMP2, d);
1957 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1958 store_reg_to_var_int(iptr->dst, d);
1961 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1962 /* == => 0, < => 1, > => -1 */
1964 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1965 var_to_reg_flt(s2, src, REG_FTMP2);
1966 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1968 M_MOV_IMM(1, REG_ITMP1);
1969 M_MOV_IMM(-1, REG_ITMP2);
1970 x86_64_ucomiss_reg_reg(cd, s1, s2);
1971 M_CMOVB(REG_ITMP1, d);
1972 M_CMOVA(REG_ITMP2, d);
1973 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1974 store_reg_to_var_int(iptr->dst, d);
1977 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1978 /* == => 0, < => 1, > => -1 */
1980 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1981 var_to_reg_flt(s2, src, REG_FTMP2);
1982 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1984 M_MOV_IMM(1, REG_ITMP1);
1985 M_MOV_IMM(-1, REG_ITMP2);
1986 x86_64_ucomisd_reg_reg(cd, s1, s2);
1987 M_CMOVB(REG_ITMP1, d);
1988 M_CMOVA(REG_ITMP2, d);
1989 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1990 store_reg_to_var_int(iptr->dst, d);
1993 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1994 /* == => 0, < => 1, > => -1 */
1996 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1997 var_to_reg_flt(s2, src, REG_FTMP2);
1998 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2000 M_MOV_IMM(1, REG_ITMP1);
2001 M_MOV_IMM(-1, REG_ITMP2);
2002 x86_64_ucomisd_reg_reg(cd, s1, s2);
2003 M_CMOVB(REG_ITMP1, d);
2004 M_CMOVA(REG_ITMP2, d);
2005 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
2006 store_reg_to_var_int(iptr->dst, d);
2010 /* memory operations **************************************************/
2012 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
2014 var_to_reg_int(s1, src, REG_ITMP1);
2015 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2016 gen_nullptr_check(s1);
2017 M_ILD(d, s1, OFFSET(java_arrayheader, size));
2018 store_reg_to_var_int(iptr->dst, d);
2021 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2023 var_to_reg_int(s1, src->prev, REG_ITMP1);
2024 var_to_reg_int(s2, src, REG_ITMP2);
2025 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2026 if (iptr->op1 == 0) {
2027 gen_nullptr_check(s1);
2030 x86_64_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2031 store_reg_to_var_int(iptr->dst, d);
2034 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2036 var_to_reg_int(s1, src->prev, REG_ITMP1);
2037 var_to_reg_int(s2, src, REG_ITMP2);
2038 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2039 if (iptr->op1 == 0) {
2040 gen_nullptr_check(s1);
2043 x86_64_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2044 store_reg_to_var_int(iptr->dst, d);
2047 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2049 var_to_reg_int(s1, src->prev, REG_ITMP1);
2050 var_to_reg_int(s2, src, REG_ITMP2);
2051 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2052 if (iptr->op1 == 0) {
2053 gen_nullptr_check(s1);
2056 x86_64_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2057 store_reg_to_var_int(iptr->dst, d);
2060 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2062 var_to_reg_int(s1, src->prev, REG_ITMP1);
2063 var_to_reg_int(s2, src, REG_ITMP2);
2064 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2065 if (iptr->op1 == 0) {
2066 gen_nullptr_check(s1);
2069 x86_64_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2070 store_reg_to_var_int(iptr->dst, d);
2073 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2075 var_to_reg_int(s1, src->prev, REG_ITMP1);
2076 var_to_reg_int(s2, src, REG_ITMP2);
2077 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2078 if (iptr->op1 == 0) {
2079 gen_nullptr_check(s1);
2082 x86_64_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
2083 store_reg_to_var_int(iptr->dst, d);
2086 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2088 var_to_reg_int(s1, src->prev, REG_ITMP1);
2089 var_to_reg_int(s2, src, REG_ITMP2);
2090 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2091 if (iptr->op1 == 0) {
2092 gen_nullptr_check(s1);
2095 x86_64_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
2096 store_reg_to_var_flt(iptr->dst, d);
2099 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2101 var_to_reg_int(s1, src->prev, REG_ITMP1);
2102 var_to_reg_int(s2, src, REG_ITMP2);
2103 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
2104 if (iptr->op1 == 0) {
2105 gen_nullptr_check(s1);
2108 x86_64_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
2109 store_reg_to_var_flt(iptr->dst, d);
2112 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2114 var_to_reg_int(s1, src->prev, REG_ITMP1);
2115 var_to_reg_int(s2, src, REG_ITMP2);
2116 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2117 if (iptr->op1 == 0) {
2118 gen_nullptr_check(s1);
2121 x86_64_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
2122 store_reg_to_var_int(iptr->dst, d);
2126 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2128 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2129 var_to_reg_int(s2, src->prev, REG_ITMP2);
2130 if (iptr->op1 == 0) {
2131 gen_nullptr_check(s1);
2134 var_to_reg_int(s3, src, REG_ITMP3);
2135 x86_64_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2138 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2140 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2141 var_to_reg_int(s2, src->prev, REG_ITMP2);
2142 if (iptr->op1 == 0) {
2143 gen_nullptr_check(s1);
2146 var_to_reg_int(s3, src, REG_ITMP3);
2147 x86_64_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2150 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2152 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2153 var_to_reg_int(s2, src->prev, REG_ITMP2);
2154 if (iptr->op1 == 0) {
2155 gen_nullptr_check(s1);
2158 var_to_reg_int(s3, src, REG_ITMP3);
2159 x86_64_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2162 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2164 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2165 var_to_reg_int(s2, src->prev, REG_ITMP2);
2166 if (iptr->op1 == 0) {
2167 gen_nullptr_check(s1);
2170 var_to_reg_int(s3, src, REG_ITMP3);
2171 x86_64_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2174 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2176 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2177 var_to_reg_int(s2, src->prev, REG_ITMP2);
2178 if (iptr->op1 == 0) {
2179 gen_nullptr_check(s1);
2182 var_to_reg_int(s3, src, REG_ITMP3);
2183 x86_64_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2186 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2188 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2189 var_to_reg_int(s2, src->prev, REG_ITMP2);
2190 if (iptr->op1 == 0) {
2191 gen_nullptr_check(s1);
2194 var_to_reg_flt(s3, src, REG_FTMP3);
2195 x86_64_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2198 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2200 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2201 var_to_reg_int(s2, src->prev, REG_ITMP2);
2202 if (iptr->op1 == 0) {
2203 gen_nullptr_check(s1);
2206 var_to_reg_flt(s3, src, REG_FTMP3);
2207 x86_64_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2210 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2212 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2213 var_to_reg_int(s2, src->prev, REG_ITMP2);
2214 if (iptr->op1 == 0) {
2215 gen_nullptr_check(s1);
2218 var_to_reg_int(s3, src, REG_ITMP3);
2220 M_MOV(s1, rd->argintregs[0]);
2221 M_MOV(s3, rd->argintregs[1]);
2222 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2226 codegen_add_arraystoreexception_ref(cd, cd->mcodeptr);
2228 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2229 var_to_reg_int(s2, src->prev, REG_ITMP2);
2230 var_to_reg_int(s3, src, REG_ITMP3);
2231 x86_64_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2235 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2237 var_to_reg_int(s1, src->prev, REG_ITMP1);
2238 var_to_reg_int(s2, src, REG_ITMP2);
2239 if (iptr->op1 == 0) {
2240 gen_nullptr_check(s1);
2243 x86_64_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2246 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2248 var_to_reg_int(s1, src->prev, REG_ITMP1);
2249 var_to_reg_int(s2, src, REG_ITMP2);
2250 if (iptr->op1 == 0) {
2251 gen_nullptr_check(s1);
2254 x86_64_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2257 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2259 var_to_reg_int(s1, src->prev, REG_ITMP1);
2260 var_to_reg_int(s2, src, REG_ITMP2);
2261 if (iptr->op1 == 0) {
2262 gen_nullptr_check(s1);
2265 x86_64_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2268 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2270 var_to_reg_int(s1, src->prev, REG_ITMP1);
2271 var_to_reg_int(s2, src, REG_ITMP2);
2272 if (iptr->op1 == 0) {
2273 gen_nullptr_check(s1);
2276 x86_64_movl_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2279 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2281 var_to_reg_int(s1, src->prev, REG_ITMP1);
2282 var_to_reg_int(s2, src, REG_ITMP2);
2283 if (iptr->op1 == 0) {
2284 gen_nullptr_check(s1);
2288 if (IS_IMM32(iptr->val.l)) {
2289 x86_64_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2291 x86_64_movl_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2292 x86_64_movl_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2296 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2298 var_to_reg_int(s1, src->prev, REG_ITMP1);
2299 var_to_reg_int(s2, src, REG_ITMP2);
2300 if (iptr->op1 == 0) {
2301 gen_nullptr_check(s1);
2304 x86_64_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2308 case ICMD_GETSTATIC: /* ... ==> ..., value */
2309 /* op1 = type, val.a = field address */
2311 if (iptr->val.a == NULL) {
2312 disp = dseg_addaddress(cd, NULL);
2314 /* PROFILE_CYCLE_STOP; */
2316 codegen_addpatchref(cd, cd->mcodeptr,
2317 PATCHER_get_putstatic,
2318 (unresolved_field *) iptr->target, disp);
2320 if (opt_showdisassemble) {
2321 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2324 /* PROFILE_CYCLE_START; */
2327 fieldinfo *fi = iptr->val.a;
2329 disp = dseg_addaddress(cd, &(fi->value));
2331 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2334 codegen_addpatchref(cd, cd->mcodeptr,
2335 PATCHER_clinit, fi->class, 0);
2337 if (opt_showdisassemble) {
2338 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2341 PROFILE_CYCLE_START;
2345 /* This approach is much faster than moving the field
2346 address inline into a register. */
2348 M_ALD(REG_ITMP2, RIP, -(((ptrint) cd->mcodeptr + 7) -
2349 (ptrint) cd->mcodebase) + disp);
2351 switch (iptr->op1) {
2353 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2354 M_ILD(d, REG_ITMP2, 0);
2355 store_reg_to_var_int(iptr->dst, d);
2359 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2360 M_LLD(d, REG_ITMP2, 0);
2361 store_reg_to_var_int(iptr->dst, d);
2364 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2365 x86_64_movss_membase_reg(cd, REG_ITMP2, 0, d);
2366 store_reg_to_var_flt(iptr->dst, d);
2369 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2370 x86_64_movsd_membase_reg(cd, REG_ITMP2, 0, d);
2371 store_reg_to_var_flt(iptr->dst, d);
2376 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2377 /* op1 = type, val.a = field address */
2379 if (iptr->val.a == NULL) {
2380 disp = dseg_addaddress(cd, NULL);
2382 /* PROFILE_CYCLE_STOP; */
2384 codegen_addpatchref(cd, cd->mcodeptr,
2385 PATCHER_get_putstatic,
2386 (unresolved_field *) iptr->target, disp);
2388 if (opt_showdisassemble) {
2389 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2392 /* PROFILE_CYCLE_START; */
2395 fieldinfo *fi = iptr->val.a;
2397 disp = dseg_addaddress(cd, &(fi->value));
2399 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2402 codegen_addpatchref(cd, cd->mcodeptr,
2403 PATCHER_clinit, fi->class, 0);
2405 if (opt_showdisassemble) {
2406 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2409 PROFILE_CYCLE_START;
2413 /* This approach is much faster than moving the field
2414 address inline into a register. */
2416 M_ALD(REG_ITMP2, RIP, -(((ptrint) cd->mcodeptr + 7) -
2417 (ptrint) cd->mcodebase) + disp);
2419 switch (iptr->op1) {
2421 var_to_reg_int(s2, src, REG_ITMP1);
2422 M_IST(s2, REG_ITMP2, 0);
2426 var_to_reg_int(s2, src, REG_ITMP1);
2427 M_LST(s2, REG_ITMP2, 0);
2430 var_to_reg_flt(s2, src, REG_FTMP1);
2431 x86_64_movss_reg_membase(cd, s2, REG_ITMP2, 0);
2434 var_to_reg_flt(s2, src, REG_FTMP1);
2435 x86_64_movsd_reg_membase(cd, s2, REG_ITMP2, 0);
2440 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2441 /* val = value (in current instruction) */
2442 /* op1 = type, val.a = field address (in */
2443 /* following NOP) */
2445 if (iptr[1].val.a == NULL) {
2446 disp = dseg_addaddress(cd, NULL);
2448 /* PROFILE_CYCLE_STOP; */
2450 codegen_addpatchref(cd, cd->mcodeptr,
2451 PATCHER_get_putstatic,
2452 (unresolved_field *) iptr[1].target, disp);
2454 if (opt_showdisassemble) {
2455 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2458 /* PROFILE_CYCLE_START; */
2461 fieldinfo *fi = iptr[1].val.a;
2463 disp = dseg_addaddress(cd, &(fi->value));
2465 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2468 codegen_addpatchref(cd, cd->mcodeptr,
2469 PATCHER_clinit, fi->class, 0);
2471 if (opt_showdisassemble) {
2472 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2475 PROFILE_CYCLE_START;
2479 /* This approach is much faster than moving the field
2480 address inline into a register. */
2482 M_ALD(REG_ITMP1, RIP, -(((ptrint) cd->mcodeptr + 7) -
2483 (ptrint) cd->mcodebase) + disp);
2485 switch (iptr->op1) {
2488 M_IST_IMM(iptr->val.i, REG_ITMP1, 0);
2493 if (IS_IMM32(iptr->val.l)) {
2494 M_LST_IMM32(iptr->val.l, REG_ITMP1, 0);
2496 M_IST_IMM(iptr->val.l, REG_ITMP1, 0);
2497 M_IST_IMM(iptr->val.l >> 32, REG_ITMP1, 4);
2503 case ICMD_GETFIELD: /* ... ==> ..., value */
2504 /* op1 = type, val.i = field offset */
2506 var_to_reg_int(s1, src, REG_ITMP1);
2507 gen_nullptr_check(s1);
2509 if (iptr->val.a == NULL) {
2510 /* PROFILE_CYCLE_STOP; */
2512 codegen_addpatchref(cd, cd->mcodeptr,
2513 PATCHER_get_putfield,
2514 (unresolved_field *) iptr->target, 0);
2516 if (opt_showdisassemble) {
2517 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2520 /* PROFILE_CYCLE_START; */
2525 disp = ((fieldinfo *) (iptr->val.a))->offset;
2528 switch (iptr->op1) {
2530 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2531 if (iptr->val.a == NULL)
2532 M_ILD32(d, s1, disp);
2535 store_reg_to_var_int(iptr->dst, d);
2539 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2540 if (iptr->val.a == NULL)
2541 M_LLD32(d, s1, disp);
2544 store_reg_to_var_int(iptr->dst, d);
2547 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2548 x86_64_movss_membase32_reg(cd, s1, disp, d);
2549 store_reg_to_var_flt(iptr->dst, d);
2552 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
2553 x86_64_movsd_membase32_reg(cd, s1, disp, d);
2554 store_reg_to_var_flt(iptr->dst, d);
2559 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2560 /* op1 = type, val.i = field offset */
2562 var_to_reg_int(s1, src->prev, REG_ITMP1);
2563 gen_nullptr_check(s1);
2565 if (IS_INT_LNG_TYPE(iptr->op1)) {
2566 var_to_reg_int(s2, src, REG_ITMP2);
2568 var_to_reg_flt(s2, src, REG_FTMP2);
2571 if (iptr->val.a == NULL) {
2572 /* PROFILE_CYCLE_STOP; */
2574 codegen_addpatchref(cd, cd->mcodeptr,
2575 PATCHER_get_putfield,
2576 (unresolved_field *) iptr->target, 0);
2578 if (opt_showdisassemble) {
2579 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2582 /* PROFILE_CYCLE_START; */
2587 disp = ((fieldinfo *) (iptr->val.a))->offset;
2590 switch (iptr->op1) {
2592 if (iptr->val.a == NULL)
2593 M_IST32(s2, s1, disp);
2595 M_IST(s2, s1, disp);
2599 if (iptr->val.a == NULL)
2600 M_LST32(s2, s1, disp);
2602 M_LST(s2, s1, disp);
2605 x86_64_movss_reg_membase32(cd, s2, s1, disp);
2608 x86_64_movsd_reg_membase32(cd, s2, s1, disp);
2613 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2614 /* val = value (in current instruction) */
2615 /* op1 = type, val.a = field address (in */
2616 /* following NOP) */
2618 var_to_reg_int(s1, src, REG_ITMP1);
2619 gen_nullptr_check(s1);
2621 if (iptr[1].val.a == NULL) {
2622 /* PROFILE_CYCLE_STOP; */
2624 codegen_addpatchref(cd, cd->mcodeptr,
2625 PATCHER_putfieldconst,
2626 (unresolved_field *) iptr[1].target, 0);
2628 if (opt_showdisassemble) {
2629 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2632 /* PROFILE_CYCLE_START; */
2637 disp = ((fieldinfo *) (iptr[1].val.a))->offset;
2640 switch (iptr->op1) {
2643 if (iptr[1].val.a == NULL)
2644 M_IST32_IMM(iptr->val.i, s1, disp);
2646 M_IST_IMM(iptr->val.i, s1, disp);
2651 /* We can only optimize the move, if the class is
2652 resolved. Otherwise we don't know what to patch. */
2653 if (iptr[1].val.a == NULL) {
2654 M_IST32_IMM(iptr->val.l, s1, disp);
2655 M_IST32_IMM(iptr->val.l >> 32, s1, disp + 4);
2657 if (IS_IMM32(iptr->val.l)) {
2658 M_LST_IMM32(iptr->val.l, s1, disp);
2660 M_IST_IMM(iptr->val.l, s1, disp);
2661 M_IST_IMM(iptr->val.l >> 32, s1, disp + 4);
2669 /* branch operations **************************************************/
2671 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2673 var_to_reg_int(s1, src, REG_ITMP1);
2674 M_INTMOVE(s1, REG_ITMP1_XPTR);
2678 #ifdef ENABLE_VERIFIER
2680 codegen_addpatchref(cd, cd->mcodeptr,
2681 PATCHER_athrow_areturn,
2682 (unresolved_class *) iptr->val.a, 0);
2684 if (opt_showdisassemble) {
2685 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2688 #endif /* ENABLE_VERIFIER */
2690 M_CALL_IMM(0); /* passing exception pc */
2691 M_POP(REG_ITMP2_XPC);
2693 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2697 case ICMD_GOTO: /* ... ==> ... */
2698 /* op1 = target JavaVM pc */
2701 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
2704 case ICMD_JSR: /* ... ==> ... */
2705 /* op1 = target JavaVM pc */
2708 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
2711 case ICMD_RET: /* ... ==> ... */
2712 /* op1 = local variable */
2714 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2715 var_to_reg_int(s1, var, REG_ITMP1);
2719 case ICMD_IFNULL: /* ..., value ==> ... */
2720 /* op1 = target JavaVM pc */
2722 if (src->flags & INMEMORY)
2723 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8);
2725 M_TEST(src->regoff);
2727 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
2730 case ICMD_IFNONNULL: /* ..., value ==> ... */
2731 /* op1 = target JavaVM pc */
2733 if (src->flags & INMEMORY)
2734 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8);
2736 M_TEST(src->regoff);
2738 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
2741 case ICMD_IFEQ: /* ..., value ==> ... */
2742 /* op1 = target JavaVM pc, val.i = constant */
2744 x86_64_emit_ifcc(cd, X86_64_CC_E, src, iptr);
2747 case ICMD_IFLT: /* ..., value ==> ... */
2748 /* op1 = target JavaVM pc, val.i = constant */
2750 x86_64_emit_ifcc(cd, X86_64_CC_L, src, iptr);
2753 case ICMD_IFLE: /* ..., value ==> ... */
2754 /* op1 = target JavaVM pc, val.i = constant */
2756 x86_64_emit_ifcc(cd, X86_64_CC_LE, src, iptr);
2759 case ICMD_IFNE: /* ..., value ==> ... */
2760 /* op1 = target JavaVM pc, val.i = constant */
2762 x86_64_emit_ifcc(cd, X86_64_CC_NE, src, iptr);
2765 case ICMD_IFGT: /* ..., value ==> ... */
2766 /* op1 = target JavaVM pc, val.i = constant */
2768 x86_64_emit_ifcc(cd, X86_64_CC_G, src, iptr);
2771 case ICMD_IFGE: /* ..., value ==> ... */
2772 /* op1 = target JavaVM pc, val.i = constant */
2774 x86_64_emit_ifcc(cd, X86_64_CC_GE, src, iptr);
2777 case ICMD_IF_LEQ: /* ..., value ==> ... */
2778 /* op1 = target JavaVM pc, val.l = constant */
2780 x86_64_emit_if_lcc(cd, X86_64_CC_E, src, iptr);
2783 case ICMD_IF_LLT: /* ..., value ==> ... */
2784 /* op1 = target JavaVM pc, val.l = constant */
2786 x86_64_emit_if_lcc(cd, X86_64_CC_L, src, iptr);
2789 case ICMD_IF_LLE: /* ..., value ==> ... */
2790 /* op1 = target JavaVM pc, val.l = constant */
2792 x86_64_emit_if_lcc(cd, X86_64_CC_LE, src, iptr);
2795 case ICMD_IF_LNE: /* ..., value ==> ... */
2796 /* op1 = target JavaVM pc, val.l = constant */
2798 x86_64_emit_if_lcc(cd, X86_64_CC_NE, src, iptr);
2801 case ICMD_IF_LGT: /* ..., value ==> ... */
2802 /* op1 = target JavaVM pc, val.l = constant */
2804 x86_64_emit_if_lcc(cd, X86_64_CC_G, src, iptr);
2807 case ICMD_IF_LGE: /* ..., value ==> ... */
2808 /* op1 = target JavaVM pc, val.l = constant */
2810 x86_64_emit_if_lcc(cd, X86_64_CC_GE, src, iptr);
2813 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2814 /* op1 = target JavaVM pc */
2816 x86_64_emit_if_icmpcc(cd, X86_64_CC_E, src, iptr);
2819 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2820 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2822 x86_64_emit_if_lcmpcc(cd, X86_64_CC_E, src, iptr);
2825 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2826 /* op1 = target JavaVM pc */
2828 x86_64_emit_if_icmpcc(cd, X86_64_CC_NE, src, iptr);
2831 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2832 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2834 x86_64_emit_if_lcmpcc(cd, X86_64_CC_NE, src, iptr);
2837 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2838 /* op1 = target JavaVM pc */
2840 x86_64_emit_if_icmpcc(cd, X86_64_CC_L, src, iptr);
2843 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2844 /* op1 = target JavaVM pc */
2846 x86_64_emit_if_lcmpcc(cd, X86_64_CC_L, src, iptr);
2849 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2850 /* op1 = target JavaVM pc */
2852 x86_64_emit_if_icmpcc(cd, X86_64_CC_G, src, iptr);
2855 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2856 /* op1 = target JavaVM pc */
2858 x86_64_emit_if_lcmpcc(cd, X86_64_CC_G, src, iptr);
2861 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2862 /* op1 = target JavaVM pc */
2864 x86_64_emit_if_icmpcc(cd, X86_64_CC_LE, src, iptr);
2867 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2868 /* op1 = target JavaVM pc */
2870 x86_64_emit_if_lcmpcc(cd, X86_64_CC_LE, src, iptr);
2873 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2874 /* op1 = target JavaVM pc */
2876 x86_64_emit_if_icmpcc(cd, X86_64_CC_GE, src, iptr);
2879 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2880 /* op1 = target JavaVM pc */
2882 x86_64_emit_if_lcmpcc(cd, X86_64_CC_GE, src, iptr);
2885 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2887 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2890 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2891 case ICMD_IFNE_ICONST: /* val.i = constant */
2892 case ICMD_IFLT_ICONST:
2893 case ICMD_IFGE_ICONST:
2894 case ICMD_IFGT_ICONST:
2895 case ICMD_IFLE_ICONST:
2897 var_to_reg_int(s1, src, REG_ITMP1);
2898 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2899 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2901 M_INTMOVE(s1, REG_ITMP1);
2904 if (iptr[1].val.i == 0)
2907 M_IMOV_IMM(iptr[1].val.i, d);
2909 if (iptr->val.i == 0)
2912 M_IMOV_IMM(iptr->val.i, REG_ITMP2);
2915 switch (iptr->opc) {
2916 case ICMD_IFEQ_ICONST:
2917 M_CMOVEQ(REG_ITMP2, d);
2919 case ICMD_IFNE_ICONST:
2920 M_CMOVNE(REG_ITMP2, d);
2922 case ICMD_IFLT_ICONST:
2923 M_CMOVLT(REG_ITMP2, d);
2925 case ICMD_IFGE_ICONST:
2926 M_CMOVGE(REG_ITMP2, d);
2928 case ICMD_IFGT_ICONST:
2929 M_CMOVGT(REG_ITMP2, d);
2931 case ICMD_IFLE_ICONST:
2932 M_CMOVLE(REG_ITMP2, d);
2936 store_reg_to_var_int(iptr->dst, d);
2940 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2943 var_to_reg_int(s1, src, REG_RESULT);
2944 M_INTMOVE(s1, REG_RESULT);
2945 goto nowperformreturn;
2947 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2949 var_to_reg_int(s1, src, REG_RESULT);
2950 M_INTMOVE(s1, REG_RESULT);
2952 #ifdef ENABLE_VERIFIER
2956 codegen_addpatchref(cd, cd->mcodeptr,
2957 PATCHER_athrow_areturn,
2958 (unresolved_class *) iptr->val.a, 0);
2960 if (opt_showdisassemble) {
2961 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2964 PROFILE_CYCLE_START;
2966 #endif /* ENABLE_VERIFIER */
2967 goto nowperformreturn;
2969 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2972 var_to_reg_flt(s1, src, REG_FRESULT);
2973 M_FLTMOVE(s1, REG_FRESULT);
2974 goto nowperformreturn;
2976 case ICMD_RETURN: /* ... ==> ... */
2982 p = parentargs_base;
2984 #if !defined(NDEBUG)
2985 /* generate call trace */
2987 if (opt_verbosecall) {
2988 x86_64_alu_imm_reg(cd, X86_64_SUB, 2 * 8, REG_SP);
2990 x86_64_mov_reg_membase(cd, REG_RESULT, REG_SP, 0 * 8);
2991 x86_64_movq_reg_membase(cd, REG_FRESULT, REG_SP, 1 * 8);
2993 x86_64_mov_imm_reg(cd, (u8) m, rd->argintregs[0]);
2994 x86_64_mov_reg_reg(cd, REG_RESULT, rd->argintregs[1]);
2995 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2996 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2998 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
3001 x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_RESULT);
3002 x86_64_movq_membase_reg(cd, REG_SP, 1 * 8, REG_FRESULT);
3004 x86_64_alu_imm_reg(cd, X86_64_ADD, 2 * 8, REG_SP);
3006 #endif /* !defined(NDEBUG) */
3008 #if defined(USE_THREADS)
3009 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3010 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
3012 /* we need to save the proper return value */
3013 switch (iptr->opc) {
3017 M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
3021 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
3025 M_MOV_IMM(builtin_monitorexit, REG_ITMP1);
3028 /* and now restore the proper return value */
3029 switch (iptr->opc) {
3033 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
3037 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
3043 /* restore saved registers */
3045 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
3046 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
3048 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
3049 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
3052 /* deallocate stack */
3054 if (parentargs_base)
3055 M_AADD_IMM(parentargs_base * 8, REG_SP);
3057 /* generate method profiling code */
3066 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3071 tptr = (void **) iptr->target;
3073 s4ptr = iptr->val.a;
3074 l = s4ptr[1]; /* low */
3075 i = s4ptr[2]; /* high */
3077 var_to_reg_int(s1, src, REG_ITMP1);
3078 M_INTMOVE(s1, REG_ITMP1);
3080 x86_64_alul_imm_reg(cd, X86_64_SUB, l, REG_ITMP1);
3085 x86_64_alul_imm_reg(cd, X86_64_CMP, i - 1, REG_ITMP1);
3086 x86_64_jcc(cd, X86_64_CC_A, 0);
3088 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3089 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3091 /* build jump table top down and use address of lowest entry */
3093 /* s4ptr += 3 + i; */
3097 dseg_addtarget(cd, (basicblock *) tptr[0]);
3101 /* length of dataseg after last dseg_addtarget is used by load */
3103 x86_64_mov_imm_reg(cd, 0, REG_ITMP2);
3104 dseg_adddata(cd, cd->mcodeptr);
3105 x86_64_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
3106 x86_64_jmp_reg(cd, REG_ITMP1);
3111 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3113 s4 i, l, val, *s4ptr;
3116 tptr = (void **) iptr->target;
3118 s4ptr = iptr->val.a;
3119 l = s4ptr[0]; /* default */
3120 i = s4ptr[1]; /* count */
3122 MCODECHECK(8 + ((7 + 6) * i) + 5);
3123 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3129 x86_64_alul_imm_reg(cd, X86_64_CMP, val, s1);
3130 x86_64_jcc(cd, X86_64_CC_E, 0);
3131 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3134 x86_64_jmp_imm(cd, 0);
3136 tptr = (void **) iptr->target;
3137 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3142 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
3143 /* op1 = arg count val.a = builtintable entry */
3149 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3150 /* op1 = arg count, val.a = method pointer */
3152 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3153 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3154 case ICMD_INVOKEINTERFACE:
3159 unresolved_method *um = iptr->target;
3160 md = um->methodref->parseddesc.md;
3162 md = lm->parseddesc;
3166 s3 = md->paramcount;
3168 MCODECHECK((20 * s3) + 128);
3170 /* copy arguments to registers or stack location */
3172 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3173 if (src->varkind == ARGVAR)
3175 if (IS_INT_LNG_TYPE(src->type)) {
3176 if (!md->params[s3].inmemory) {
3177 s1 = rd->argintregs[md->params[s3].regoff];
3178 var_to_reg_int(d, src, s1);
3181 var_to_reg_int(d, src, REG_ITMP1);
3182 M_LST(d, REG_SP, md->params[s3].regoff * 8);
3186 if (!md->params[s3].inmemory) {
3187 s1 = rd->argfltregs[md->params[s3].regoff];
3188 var_to_reg_flt(d, src, s1);
3191 var_to_reg_flt(d, src, REG_FTMP1);
3192 M_DST(d, REG_SP, md->params[s3].regoff * 8);
3197 /* generate method profiling code */
3201 switch (iptr->opc) {
3203 a = (ptrint) bte->fp;
3204 d = md->returntype.type;
3206 M_MOV_IMM(a, REG_ITMP1);
3209 /* if op1 == true, we need to check for an exception */
3211 if (iptr->op1 == true) {
3214 codegen_add_fillinstacktrace_ref(cd, cd->mcodeptr);
3218 case ICMD_INVOKESPECIAL:
3219 M_TEST(rd->argintregs[0]);
3221 codegen_add_nullpointerexception_ref(cd, cd->mcodeptr);
3223 /* first argument contains pointer */
3224 /* gen_nullptr_check(rd->argintregs[0]); */
3226 /* access memory for hardware nullptr */
3227 /* x86_64_mov_membase_reg(cd, rd->argintregs[0], 0, REG_ITMP2); */
3231 case ICMD_INVOKESTATIC:
3233 unresolved_method *um = iptr->target;
3235 codegen_addpatchref(cd, cd->mcodeptr,
3236 PATCHER_invokestatic_special, um, 0);
3238 if (opt_showdisassemble) {
3239 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3243 d = um->methodref->parseddesc.md->returntype.type;
3246 a = (ptrint) lm->stubroutine;
3247 d = lm->parseddesc->returntype.type;
3250 M_MOV_IMM(a, REG_ITMP2);
3254 case ICMD_INVOKEVIRTUAL:
3255 gen_nullptr_check(rd->argintregs[0]);
3258 unresolved_method *um = iptr->target;
3260 codegen_addpatchref(cd, cd->mcodeptr,
3261 PATCHER_invokevirtual, um, 0);
3263 if (opt_showdisassemble) {
3264 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3268 d = um->methodref->parseddesc.md->returntype.type;
3271 s1 = OFFSET(vftbl_t, table[0]) +
3272 sizeof(methodptr) * lm->vftblindex;
3273 d = lm->parseddesc->returntype.type;
3276 x86_64_mov_membase_reg(cd, rd->argintregs[0],
3277 OFFSET(java_objectheader, vftbl),
3279 x86_64_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1);
3283 case ICMD_INVOKEINTERFACE:
3284 gen_nullptr_check(rd->argintregs[0]);
3287 unresolved_method *um = iptr->target;
3289 codegen_addpatchref(cd, cd->mcodeptr,
3290 PATCHER_invokeinterface, um, 0);
3292 if (opt_showdisassemble) {
3293 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3298 d = um->methodref->parseddesc.md->returntype.type;
3301 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3302 sizeof(methodptr) * lm->class->index;
3304 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3306 d = lm->parseddesc->returntype.type;
3309 M_ALD(REG_ITMP2, rd->argintregs[0],
3310 OFFSET(java_objectheader, vftbl));
3311 x86_64_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP2);
3312 x86_64_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1);
3317 /* generate method profiling code */
3319 PROFILE_CYCLE_START;
3321 /* d contains return type */
3323 if (d != TYPE_VOID) {
3324 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3325 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3326 M_INTMOVE(REG_RESULT, s1);
3327 store_reg_to_var_int(iptr->dst, s1);
3329 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
3330 M_FLTMOVE(REG_FRESULT, s1);
3331 store_reg_to_var_flt(iptr->dst, s1);
3337 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3339 /* op1: 0 == array, 1 == class */
3340 /* val.a: (classinfo *) superclass */
3342 /* superclass is an interface:
3344 * OK if ((sub == NULL) ||
3345 * (sub->vftbl->interfacetablelength > super->index) &&
3346 * (sub->vftbl->interfacetable[-super->index] != NULL));
3348 * superclass is a class:
3350 * OK if ((sub == NULL) || (0
3351 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3352 * super->vftbl->diffval));
3355 if (iptr->op1 == 1) {
3356 /* object type cast-check */
3359 vftbl_t *supervftbl;
3362 super = (classinfo *) iptr->val.a;
3369 superindex = super->index;
3370 supervftbl = super->vftbl;
3373 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3374 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3376 var_to_reg_int(s1, src, REG_ITMP1);
3378 /* calculate interface checkcast code size */
3380 s2 = 3; /* mov_membase_reg */
3381 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3383 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub imm32 */ +
3384 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3385 3 /* test */ + 6 /* jcc */;
3388 s2 += (opt_showdisassemble ? 5 : 0);
3390 /* calculate class checkcast code size */
3392 s3 = 3; /* mov_membase_reg */
3393 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3394 s3 += 10 /* mov_imm_reg */ + 3 + 4 /* movl_membase32_reg */;
3397 if (s1 != REG_ITMP1) {
3398 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3399 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3400 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3401 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3407 s3 += 3 + 4 /* movl_membase32_reg */ + 3 /* sub */ +
3408 10 /* mov_imm_reg */ + 3 /* movl_membase_reg */;
3409 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3412 s3 += 3 /* cmp */ + 6 /* jcc */;
3415 s3 += (opt_showdisassemble ? 5 : 0);
3417 /* if class is not resolved, check which code to call */
3421 M_BEQ(6 + (opt_showdisassemble ? 5 : 0) + 7 + 6 + s2 + 5 + s3);
3423 codegen_addpatchref(cd, cd->mcodeptr,
3424 PATCHER_checkcast_instanceof_flags,
3425 (constant_classref *) iptr->target, 0);
3427 if (opt_showdisassemble) {
3428 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3431 M_IMOV_IMM(0, REG_ITMP2); /* super->flags */
3432 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
3436 /* interface checkcast code */
3438 if (!super || (super->flags & ACC_INTERFACE)) {
3444 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3447 codegen_addpatchref(cd, cd->mcodeptr,
3448 PATCHER_checkcast_instanceof_interface,
3449 (constant_classref *) iptr->target, 0);
3451 if (opt_showdisassemble) {
3452 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3456 x86_64_movl_membase32_reg(cd, REG_ITMP2,
3457 OFFSET(vftbl_t, interfacetablelength),
3459 /* XXX TWISTI: should this be int arithmetic? */
3460 M_LSUB_IMM32(superindex, REG_ITMP3);
3463 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
3464 x86_64_mov_membase32_reg(cd, REG_ITMP2,
3465 OFFSET(vftbl_t, interfacetable[0]) -
3466 superindex * sizeof(methodptr*),
3470 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
3476 /* class checkcast code */
3478 if (!super || !(super->flags & ACC_INTERFACE)) {
3484 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3487 codegen_addpatchref(cd, cd->mcodeptr,
3488 PATCHER_checkcast_class,
3489 (constant_classref *) iptr->target,
3492 if (opt_showdisassemble) {
3493 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3497 M_MOV_IMM(supervftbl, REG_ITMP3);
3498 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3499 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3501 x86_64_movl_membase32_reg(cd, REG_ITMP2,
3502 OFFSET(vftbl_t, baseval),
3504 /* if (s1 != REG_ITMP1) { */
3505 /* x86_64_movl_membase_reg(cd, REG_ITMP3, */
3506 /* OFFSET(vftbl_t, baseval), */
3508 /* x86_64_movl_membase_reg(cd, REG_ITMP3, */
3509 /* OFFSET(vftbl_t, diffval), */
3511 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3512 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3514 /* x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP1, REG_ITMP2); */
3517 x86_64_movl_membase32_reg(cd, REG_ITMP3,
3518 OFFSET(vftbl_t, baseval),
3520 M_LSUB(REG_ITMP3, REG_ITMP2);
3521 M_MOV_IMM(supervftbl, REG_ITMP3);
3522 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3524 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3525 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3527 M_CMP(REG_ITMP3, REG_ITMP2);
3528 M_BA(0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
3529 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
3531 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
3534 /* array type cast-check */
3536 var_to_reg_int(s1, src, REG_ITMP1);
3537 M_INTMOVE(s1, rd->argintregs[0]);
3539 if (iptr->val.a == NULL) {
3540 codegen_addpatchref(cd, cd->mcodeptr,
3541 PATCHER_builtin_arraycheckcast,
3542 (constant_classref *) iptr->target, 0);
3544 if (opt_showdisassemble) {
3545 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3549 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3550 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
3554 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
3556 var_to_reg_int(s1, src, REG_ITMP1);
3557 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
3560 store_reg_to_var_int(iptr->dst, d);
3563 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3565 /* op1: 0 == array, 1 == class */
3566 /* val.a: (classinfo *) superclass */
3568 /* superclass is an interface:
3570 * return (sub != NULL) &&
3571 * (sub->vftbl->interfacetablelength > super->index) &&
3572 * (sub->vftbl->interfacetable[-super->index] != NULL);
3574 * superclass is a class:
3576 * return ((sub != NULL) && (0
3577 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3578 * super->vftbl->diffvall));
3583 vftbl_t *supervftbl;
3586 super = (classinfo *) iptr->val.a;
3593 superindex = super->index;
3594 supervftbl = super->vftbl;
3597 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3598 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3601 var_to_reg_int(s1, src, REG_ITMP1);
3602 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
3604 M_INTMOVE(s1, REG_ITMP1);
3608 /* calculate interface instanceof code size */
3610 s2 = 3; /* mov_membase_reg */
3611 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3612 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub_imm32 */ +
3613 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3614 3 /* test */ + 4 /* setcc */;
3617 s2 += (opt_showdisassemble ? 5 : 0);
3619 /* calculate class instanceof code size */
3621 s3 = 3; /* mov_membase_reg */
3622 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3623 s3 += 10; /* mov_imm_reg */
3624 s3 += 2; /* movl_membase_reg - only if REG_ITMP1 == RAX */
3625 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3626 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3627 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3628 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3629 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3630 s3 += 3 /* sub */ + 3 /* xor */ + 3 /* cmp */ + 4 /* setcc */;
3633 s3 += (opt_showdisassemble ? 5 : 0);
3635 x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
3637 /* if class is not resolved, check which code to call */
3640 x86_64_test_reg_reg(cd, s1, s1);
3641 x86_64_jcc(cd, X86_64_CC_Z, (6 + (opt_showdisassemble ? 5 : 0) +
3642 7 + 6 + s2 + 5 + s3));
3644 codegen_addpatchref(cd, cd->mcodeptr,
3645 PATCHER_checkcast_instanceof_flags,
3646 (constant_classref *) iptr->target, 0);
3648 if (opt_showdisassemble) {
3649 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3652 x86_64_movl_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
3653 x86_64_alul_imm_reg(cd, X86_64_AND, ACC_INTERFACE, REG_ITMP3);
3654 x86_64_jcc(cd, X86_64_CC_Z, s2 + 5);
3657 /* interface instanceof code */
3659 if (!super || (super->flags & ACC_INTERFACE)) {
3661 x86_64_test_reg_reg(cd, s1, s1);
3662 x86_64_jcc(cd, X86_64_CC_Z, s2);
3665 x86_64_mov_membase_reg(cd, s1,
3666 OFFSET(java_objectheader, vftbl),
3669 codegen_addpatchref(cd, cd->mcodeptr,
3670 PATCHER_checkcast_instanceof_interface,
3671 (constant_classref *) iptr->target, 0);
3673 if (opt_showdisassemble) {
3674 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3678 x86_64_movl_membase32_reg(cd, REG_ITMP1,
3679 OFFSET(vftbl_t, interfacetablelength),
3681 x86_64_alu_imm32_reg(cd, X86_64_SUB, superindex, REG_ITMP3);
3682 x86_64_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
3684 a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
3686 x86_64_jcc(cd, X86_64_CC_LE, a);
3687 x86_64_mov_membase32_reg(cd, REG_ITMP1,
3688 OFFSET(vftbl_t, interfacetable[0]) -
3689 superindex * sizeof(methodptr*),
3691 x86_64_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3692 x86_64_setcc_reg(cd, X86_64_CC_NE, d);
3695 x86_64_jmp_imm(cd, s3);
3698 /* class instanceof code */
3700 if (!super || !(super->flags & ACC_INTERFACE)) {
3702 x86_64_test_reg_reg(cd, s1, s1);
3703 x86_64_jcc(cd, X86_64_CC_E, s3);
3706 x86_64_mov_membase_reg(cd, s1,
3707 OFFSET(java_objectheader, vftbl),
3711 codegen_addpatchref(cd, cd->mcodeptr,
3712 PATCHER_instanceof_class,
3713 (constant_classref *) iptr->target, 0);
3715 if (opt_showdisassemble) {
3716 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3720 x86_64_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
3721 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3722 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3724 x86_64_movl_membase_reg(cd, REG_ITMP1,
3725 OFFSET(vftbl_t, baseval),
3727 x86_64_movl_membase_reg(cd, REG_ITMP2,
3728 OFFSET(vftbl_t, diffval),
3730 x86_64_movl_membase_reg(cd, REG_ITMP2,
3731 OFFSET(vftbl_t, baseval),
3733 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3734 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3736 x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
3737 x86_64_alu_reg_reg(cd, X86_64_XOR, d, d); /* may be REG_ITMP2 */
3738 x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP3, REG_ITMP1);
3739 x86_64_setcc_reg(cd, X86_64_CC_BE, d);
3741 store_reg_to_var_int(iptr->dst, d);
3745 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3746 /* op1 = dimension, val.a = class */
3748 /* check for negative sizes and copy sizes to stack if necessary */
3750 MCODECHECK((10 * 4 * iptr->op1) + 5 + 10 * 8);
3752 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3753 /* copy SAVEDVAR sizes to stack */
3755 if (src->varkind != ARGVAR) {
3756 var_to_reg_int(s2, src, REG_ITMP1);
3757 M_LST(s2, REG_SP, s1 * 8);
3761 /* is a patcher function set? */
3763 if (iptr->val.a == NULL) {
3764 codegen_addpatchref(cd, cd->mcodeptr,
3765 PATCHER_builtin_multianewarray,
3766 (constant_classref *) iptr->target, 0);
3768 if (opt_showdisassemble) {
3769 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3775 a = (ptrint) iptr->val.a;
3778 /* a0 = dimension count */
3780 M_MOV_IMM(iptr->op1, rd->argintregs[0]);
3782 /* a1 = arrayvftbl */
3784 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3786 /* a2 = pointer to dimensions = stack pointer */
3788 M_MOV(REG_SP, rd->argintregs[2]);
3790 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3793 /* check for exception before result assignment */
3797 codegen_add_fillinstacktrace_ref(cd, cd->mcodeptr);
3799 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3800 M_INTMOVE(REG_RESULT, s1);
3801 store_reg_to_var_int(iptr->dst, s1);
3805 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3809 } /* for instruction */
3811 /* copy values to interface registers */
3813 src = bptr->outstack;
3814 len = bptr->outdepth;
3816 #if defined(ENABLE_LSRA)
3821 if ((src->varkind != STACKVAR)) {
3823 if (IS_FLT_DBL_TYPE(s2)) {
3824 var_to_reg_flt(s1, src, REG_FTMP1);
3825 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3826 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3829 x86_64_movq_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3833 var_to_reg_int(s1, src, REG_ITMP1);
3834 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3835 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3838 x86_64_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3845 /* At the end of a basic block we may have to append some nops,
3846 because the patcher stub calling code might be longer than the
3847 actual instruction. So codepatching does not change the
3848 following block unintentionally. */
3850 if (cd->mcodeptr < cd->lastmcodeptr) {
3851 while (cd->mcodeptr < cd->lastmcodeptr) {
3856 } /* if (bptr -> flags >= BBREACHED) */
3857 } /* for basic block */
3859 dseg_createlinenumbertable(cd);
3862 /* generate exception and patcher stubs */
3871 savedmcodeptr = NULL;
3873 /* generate exception stubs */
3875 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
3876 gen_resolvebranch(cd->mcodebase + eref->branchpos,
3878 cd->mcodeptr - cd->mcodebase);
3882 /* Check if the exception is an
3883 ArrayIndexOutOfBoundsException. If so, move index register
3886 if (eref->reg != -1)
3887 M_MOV(eref->reg, REG_ITMP1);
3889 /* calcuate exception address */
3891 M_MOV_IMM(0, REG_ITMP2_XPC);
3892 dseg_adddata(cd, cd->mcodeptr);
3893 M_AADD_IMM32(eref->branchpos - 6, REG_ITMP2_XPC);
3895 /* move function to call into REG_ITMP3 */
3897 M_MOV_IMM(eref->function, REG_ITMP3);
3899 if (savedmcodeptr != NULL) {
3900 M_JMP_IMM(savedmcodeptr - cd->mcodeptr - 5);
3903 savedmcodeptr = cd->mcodeptr;
3905 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[0]);
3906 M_MOV(REG_SP, rd->argintregs[1]);
3907 M_ALD(rd->argintregs[2], REG_SP, parentargs_base * 8);
3908 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
3909 M_MOV(REG_ITMP1, rd->argintregs[4]); /* for AIOOBE */
3911 M_ASUB_IMM(2 * 8, REG_SP);
3912 M_AST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3916 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3917 M_AADD_IMM(2 * 8, REG_SP);
3919 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
3925 /* generate code patching stub call code */
3927 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3928 /* check size of code segment */
3932 /* Get machine code which is patched back in later. A
3933 `call rel32' is 5 bytes long (but read 8 bytes). */
3935 savedmcodeptr = cd->mcodebase + pref->branchpos;
3936 mcode = *((ptrint *) savedmcodeptr);
3938 /* patch in `call rel32' to call the following code */
3940 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
3941 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
3943 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
3945 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3947 /* move pointer to java_objectheader onto stack */
3949 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3950 /* create a virtual java_objectheader */
3952 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3953 a = dseg_addaddress(cd, NULL); /* vftbl */
3955 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + a, REG_ITMP3);
3961 /* move machine code bytes and classinfo pointer into registers */
3963 M_MOV_IMM(mcode, REG_ITMP3);
3965 M_MOV_IMM(pref->ref, REG_ITMP3);
3967 M_MOV_IMM(pref->disp, REG_ITMP3);
3970 M_MOV_IMM(pref->patcher, REG_ITMP3);
3973 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
3978 /* generate replacement-out stubs */
3983 replacementpoint = cd->code->rplpoints;
3984 for (i=0; i<cd->code->rplpointcount; ++i, ++replacementpoint) {
3985 /* check code segment size */
3989 /* note start of stub code */
3991 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
3993 /* make machine code for patching */
3995 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
3996 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
3998 /* push address of `rplpoint` struct */
4000 M_MOV_IMM(replacementpoint, REG_ITMP3);
4003 /* jump to replacement function */
4005 M_MOV_IMM(asm_replacement_out, REG_ITMP3);
4010 codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
4012 /* everything's ok */
4018 /* createcompilerstub **********************************************************
4020 Creates a stub routine which calls the compiler.
4022 *******************************************************************************/
4024 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4025 #define COMPILERSTUB_CODESIZE 7 + 7 + 3
4027 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4030 u1 *createcompilerstub(methodinfo *m)
4032 u1 *s; /* memory to hold the stub */
4037 s = CNEW(u1, COMPILERSTUB_SIZE);
4039 /* set data pointer and code pointer */
4042 s = s + COMPILERSTUB_DATASIZE;
4044 /* mark start of dump memory area */
4046 dumpsize = dump_size();
4048 cd = DNEW(codegendata);
4051 /* Store the methodinfo* in the same place as in the methodheader
4052 for compiled methods. */
4054 d[0] = (ptrint) asm_call_jit_compiler;
4057 /* code for the stub */
4059 M_ALD(REG_ITMP1, RIP, -(7 * 1 + 1 * SIZEOF_VOID_P)); /* methodinfo */
4060 M_ALD(REG_ITMP3, RIP, -(7 * 2 + 2 * SIZEOF_VOID_P)); /* compiler pointer */
4063 #if defined(ENABLE_STATISTICS)
4065 count_cstub_len += COMPILERSTUB_SIZE;
4068 /* release dump area */
4070 dump_release(dumpsize);
4076 /* createnativestub ************************************************************
4078 Creates a stub routine which calls a native method.
4080 *******************************************************************************/
4082 u1 *createnativestub(functionptr f, methodinfo *m, codegendata *cd,
4083 registerdata *rd, methoddesc *nmd)
4086 s4 stackframesize; /* size of stackframe if needed */
4088 s4 i, j; /* count variables */
4092 /* initialize variables */
4095 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4097 /* calculate stack frame size */
4100 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4101 sizeof(localref_table) / SIZEOF_VOID_P +
4102 INT_ARG_CNT + FLT_ARG_CNT + 1 + /* + 1 for function address */
4105 if (!(stackframesize & 0x1)) /* keep stack 16-byte aligned */
4108 /* create method header */
4110 (void) dseg_addaddress(cd, m); /* MethodPointer */
4111 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4112 (void) dseg_adds4(cd, 0); /* IsSync */
4113 (void) dseg_adds4(cd, 0); /* IsLeaf */
4114 (void) dseg_adds4(cd, 0); /* IntSave */
4115 (void) dseg_adds4(cd, 0); /* FltSave */
4116 (void) dseg_addlinenumbertablesize(cd);
4117 (void) dseg_adds4(cd, 0); /* ExTableSize */
4119 /* initialize mcode variables */
4121 cd->mcodeptr = (u1 *) cd->mcodebase;
4122 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
4124 /* generate native method profiling code */
4127 /* count frequency */
4129 M_MOV_IMM(m, REG_ITMP2);
4130 M_IINC_MEMBASE(REG_ITMP2, OFFSET(methodinfo, frequency));
4133 /* generate stub code */
4135 M_ASUB_IMM(stackframesize * 8, REG_SP);
4137 #if !defined(NDEBUG)
4138 /* generate call trace */
4140 if (opt_verbosecall) {
4141 /* save integer and float argument registers */
4143 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4144 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4145 M_LST(rd->argintregs[j++], REG_SP, (1 + i) * 8);
4147 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4148 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4149 M_DST(rd->argfltregs[j++], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4151 /* show integer hex code for float arguments */
4153 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++) {
4154 /* if the paramtype is a float, we have to right shift all
4155 following integer registers */
4157 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4158 for (s1 = INT_ARG_CNT - 2; s1 >= i; s1--)
4159 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
4161 x86_64_movd_freg_reg(cd, rd->argfltregs[j], rd->argintregs[i]);
4166 M_MOV_IMM(m, REG_ITMP1);
4167 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4168 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
4171 /* restore integer and float argument registers */
4173 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4174 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4175 M_LLD(rd->argintregs[j++], REG_SP, (1 + i) * 8);
4177 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4178 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4179 M_DLD(rd->argfltregs[j++], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4181 #endif /* !defined(NDEBUG) */
4183 /* get function address (this must happen before the stackframeinfo) */
4185 #if !defined(WITH_STATIC_CLASSPATH)
4187 codegen_addpatchref(cd, cd->mcodeptr, PATCHER_resolve_native, m, 0);
4189 if (opt_showdisassemble) {
4190 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4195 M_MOV_IMM(f, REG_ITMP3);
4198 /* save integer and float argument registers */
4200 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4201 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4202 M_LST(rd->argintregs[j++], REG_SP, i * 8);
4204 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4205 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4206 M_DST(rd->argfltregs[j++], REG_SP, (INT_ARG_CNT + i) * 8);
4208 M_AST(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4210 /* create dynamic stack info */
4212 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4213 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[1]);
4214 M_ALEA(REG_SP, stackframesize * 8 + SIZEOF_VOID_P, rd->argintregs[2]);
4215 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8);
4216 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
4219 /* restore integer and float argument registers */
4221 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4222 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4223 M_LLD(rd->argintregs[j++], REG_SP, i * 8);
4225 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4226 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4227 M_DLD(rd->argfltregs[j++], REG_SP, (INT_ARG_CNT + i) * 8);
4229 M_ALD(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4232 /* copy or spill arguments to new locations */
4234 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4235 t = md->paramtypes[i].type;
4237 if (IS_INT_LNG_TYPE(t)) {
4238 if (!md->params[i].inmemory) {
4239 s1 = rd->argintregs[md->params[i].regoff];
4241 if (!nmd->params[j].inmemory) {
4242 s2 = rd->argintregs[nmd->params[j].regoff];
4246 s2 = nmd->params[j].regoff;
4247 M_LST(s1, REG_SP, s2 * 8);
4251 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4252 s2 = nmd->params[j].regoff;
4253 M_LLD(REG_ITMP1, REG_SP, s1 * 8);
4254 M_LST(REG_ITMP1, REG_SP, s2 * 8);
4258 /* We only copy spilled float arguments, as the float argument */
4259 /* registers keep unchanged. */
4261 if (md->params[i].inmemory) {
4262 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4263 s2 = nmd->params[j].regoff;
4264 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4265 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4270 /* put class into second argument register */
4272 if (m->flags & ACC_STATIC)
4273 M_MOV_IMM(m->class, rd->argintregs[1]);
4275 /* put env into first argument register */
4277 M_MOV_IMM(_Jv_env, rd->argintregs[0]);
4279 /* do the native function call */
4283 /* save return value */
4285 if (md->returntype.type != TYPE_VOID) {
4286 if (IS_INT_LNG_TYPE(md->returntype.type))
4287 M_LST(REG_RESULT, REG_SP, 0 * 8);
4289 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4292 /* remove native stackframe info */
4294 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4295 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
4298 #if !defined(NDEBUG)
4299 /* generate call trace */
4301 if (opt_verbosecall) {
4302 /* just restore the value we need, don't care about the other */
4304 if (md->returntype.type != TYPE_VOID) {
4305 if (IS_INT_LNG_TYPE(md->returntype.type))
4306 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4308 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4311 M_MOV_IMM(m, rd->argintregs[0]);
4312 M_MOV(REG_RESULT, rd->argintregs[1]);
4313 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4314 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4316 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
4319 #endif /* !defined(NDEBUG) */
4321 /* check for exception */
4323 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4324 M_MOV_IMM(builtin_get_exceptionptrptr, REG_ITMP3);
4327 M_MOV_IMM(&_no_threads_exceptionptr, REG_RESULT);
4329 M_ALD(REG_ITMP2, REG_RESULT, 0);
4331 /* restore return value */
4333 if (md->returntype.type != TYPE_VOID) {
4334 if (IS_INT_LNG_TYPE(md->returntype.type))
4335 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4337 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4340 /* test for exception */
4345 /* remove stackframe */
4347 M_AADD_IMM(stackframesize * 8, REG_SP);
4351 /* handle exception */
4353 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4354 M_LST(REG_ITMP2, REG_SP, 0 * 8);
4355 M_MOV_IMM(builtin_get_exceptionptrptr, REG_ITMP3);
4357 M_AST_IMM32(0, REG_RESULT, 0); /* clear exception pointer */
4358 M_LLD(REG_ITMP1_XPTR, REG_SP, 0 * 8);
4360 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
4361 M_MOV_IMM(&_no_threads_exceptionptr, REG_ITMP3);
4362 M_AST_IMM32(0, REG_ITMP3, 0); /* clear exception pointer */
4365 /* remove stackframe */
4367 M_AADD_IMM(stackframesize * 8, REG_SP);
4369 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
4370 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
4372 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4376 /* process patcher calls **************************************************/
4383 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4387 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4388 /* Get machine code which is patched back in later. A
4389 `call rel32' is 5 bytes long (but read 8 bytes). */
4391 savedmcodeptr = cd->mcodebase + pref->branchpos;
4392 mcode = *((ptrint *) savedmcodeptr);
4394 /* patch in `call rel32' to call the following code */
4396 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4397 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
4399 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
4401 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4403 /* move pointer to java_objectheader onto stack */
4405 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4406 /* create a virtual java_objectheader */
4408 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4409 disp = dseg_addaddress(cd, NULL); /* vftbl */
4411 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP3);
4417 /* move machine code bytes and classinfo pointer into registers */
4419 M_MOV_IMM(mcode, REG_ITMP3);
4421 M_MOV_IMM(pref->ref, REG_ITMP3);
4423 M_MOV_IMM(pref->disp, REG_ITMP3);
4426 M_MOV_IMM(pref->patcher, REG_ITMP3);
4429 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
4434 codegen_finish(m, cd, (s4) ((u1 *) cd->mcodeptr - cd->mcodebase));
4436 return cd->code->entrypoint;
4441 * These are local overrides for various environment variables in Emacs.
4442 * Please do not remove this and leave it at the end of the file, where
4443 * Emacs will automagically detect them.
4444 * ---------------------------------------------------------------------
4447 * indent-tabs-mode: t
4451 * vim:noexpandtab:sw=4:ts=4: