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 4764 2006-04-13 09:32:09Z 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"
76 /* codegen *********************************************************************
78 Generates machine code.
80 *******************************************************************************/
82 bool codegen(jitdata *jd)
87 s4 len, s1, s2, s3, d, disp;
96 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
97 builtintable_entry *bte;
99 rplpoint *replacementpoint;
101 /* get required compiler data */
107 /* prevent compiler warnings */
119 /* space to save used callee saved registers */
121 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
122 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
124 stackframesize = rd->memuse + savedregs_num;
126 #if defined(USE_THREADS)
127 /* space to save argument of monitor_enter */
129 if (checksync && (m->flags & ACC_SYNCHRONIZED))
133 /* Keep stack of non-leaf functions 16-byte aligned for calls into native */
134 /* code e.g. libc or jni (alignment problems with movaps). */
136 if (!m->isleafmethod || opt_verbosecall)
137 stackframesize |= 0x1;
139 /* create method header */
141 (void) dseg_addaddress(cd, m); /* MethodPointer */
142 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
144 #if defined(USE_THREADS)
145 /* IsSync contains the offset relative to the stack pointer for the
146 argument of monitor_exit used in the exception handler. Since the
147 offset could be zero and give a wrong meaning of the flag it is
151 if (checksync && (m->flags & ACC_SYNCHRONIZED))
152 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
155 (void) dseg_adds4(cd, 0); /* IsSync */
157 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
158 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
159 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
161 (void) dseg_addlinenumbertablesize(cd);
163 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
165 /* create exception table */
167 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
168 dseg_addtarget(cd, ex->start);
169 dseg_addtarget(cd, ex->end);
170 dseg_addtarget(cd, ex->handler);
171 (void) dseg_addaddress(cd, ex->catchtype.cls);
174 /* initialize mcode variables */
176 cd->mcodeptr = (u1 *) cd->mcodebase;
177 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
179 /* initialize the last patcher pointer */
181 cd->lastmcodeptr = cd->mcodeptr;
183 /* generate method profiling code */
186 /* count frequency */
188 M_MOV_IMM(m, REG_ITMP3);
189 M_IINC_MEMBASE(REG_ITMP3, OFFSET(methodinfo, frequency));
194 /* create stack frame (if necessary) */
197 M_ASUB_IMM(stackframesize * 8, REG_SP);
199 /* save used callee saved registers */
202 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
203 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
205 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
206 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
209 /* take arguments out of register or stack frame */
213 for (p = 0, l = 0; p < md->paramcount; p++) {
214 t = md->paramtypes[p].type;
215 var = &(rd->locals[l][t]);
217 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
221 s1 = md->params[p].regoff;
222 if (IS_INT_LNG_TYPE(t)) { /* integer args */
223 s2 = rd->argintregs[s1];
224 if (!md->params[p].inmemory) { /* register arguments */
225 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
226 M_INTMOVE(s2, var->regoff);
228 } else { /* reg arg -> spilled */
229 M_LST(s2, REG_SP, var->regoff * 8);
232 } else { /* stack arguments */
233 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
234 /* + 8 for return address */
235 M_LLD(var->regoff, REG_SP, (stackframesize + s1) * 8 + 8);
237 } else { /* stack arg -> spilled */
238 var->regoff = stackframesize + s1 + 1;
242 } else { /* floating args */
243 if (!md->params[p].inmemory) { /* register arguments */
244 s2 = rd->argfltregs[s1];
245 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
246 M_FLTMOVE(s2, var->regoff);
248 } else { /* reg arg -> spilled */
249 M_DST(s2, REG_SP, var->regoff * 8);
252 } else { /* stack arguments */
253 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
254 M_DLD(var->regoff, REG_SP, (stackframesize + s1) * 8 + 8);
257 var->regoff = stackframesize + s1 + 1;
263 /* save monitorenter argument */
265 #if defined(USE_THREADS)
266 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
267 /* stack offset for monitor argument */
271 if (opt_verbosecall) {
272 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
274 for (p = 0; p < INT_ARG_CNT; p++)
275 M_LST(rd->argintregs[p], REG_SP, p * 8);
277 for (p = 0; p < FLT_ARG_CNT; p++)
278 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
280 s1 += INT_ARG_CNT + FLT_ARG_CNT;
283 /* decide which monitor enter function to call */
285 if (m->flags & ACC_STATIC) {
286 M_MOV_IMM(m->class, REG_ITMP1);
287 M_AST(REG_ITMP1, REG_SP, s1 * 8);
288 M_INTMOVE(REG_ITMP1, rd->argintregs[0]);
289 M_MOV_IMM(BUILTIN_staticmonitorenter, REG_ITMP1);
293 M_TEST(rd->argintregs[0]);
295 codegen_add_nullpointerexception_ref(cd, cd->mcodeptr);
296 M_AST(rd->argintregs[0], REG_SP, s1 * 8);
297 M_MOV_IMM(BUILTIN_monitorenter, REG_ITMP1);
301 if (opt_verbosecall) {
302 for (p = 0; p < INT_ARG_CNT; p++)
303 M_LLD(rd->argintregs[p], REG_SP, p * 8);
305 for (p = 0; p < FLT_ARG_CNT; p++)
306 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
308 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
314 /* Copy argument registers to stack and call trace function with
315 pointer to arguments on stack. */
317 if (opt_verbosecall) {
318 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
320 /* save integer argument registers */
322 for (p = 0; p < INT_ARG_CNT; p++)
323 M_LST(rd->argintregs[p], REG_SP, (1 + p) * 8);
325 /* save float argument registers */
327 for (p = 0; p < FLT_ARG_CNT; p++)
328 M_DST(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
330 /* save temporary registers for leaf methods */
332 if (m->isleafmethod) {
333 for (p = 0; p < INT_TMP_CNT; p++)
334 M_LST(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
336 for (p = 0; p < FLT_TMP_CNT; p++)
337 M_DST(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
340 /* show integer hex code for float arguments */
342 for (p = 0, l = 0; p < md->paramcount && p < INT_ARG_CNT; p++) {
343 /* If the paramtype is a float, we have to right shift all
344 following integer registers. */
346 if (IS_FLT_DBL_TYPE(md->paramtypes[p].type)) {
347 for (s1 = INT_ARG_CNT - 2; s1 >= p; s1--) {
348 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
351 x86_64_movd_freg_reg(cd, rd->argfltregs[l], rd->argintregs[p]);
356 M_MOV_IMM(m, REG_ITMP2);
357 M_AST(REG_ITMP2, REG_SP, 0 * 8);
358 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
361 /* restore integer argument registers */
363 for (p = 0; p < INT_ARG_CNT; p++)
364 M_LLD(rd->argintregs[p], REG_SP, (1 + p) * 8);
366 /* restore float argument registers */
368 for (p = 0; p < FLT_ARG_CNT; p++)
369 M_DLD(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
371 /* restore temporary registers for leaf methods */
373 if (m->isleafmethod) {
374 for (p = 0; p < INT_TMP_CNT; p++)
375 M_LLD(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
377 for (p = 0; p < FLT_TMP_CNT; p++)
378 M_DLD(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
381 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
383 #endif /* !defined(NDEBUG) */
387 /* end of header generation */
389 replacementpoint = jd->code->rplpoints;
391 /* walk through all basic blocks */
393 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
395 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
397 if (bptr->flags >= BBREACHED) {
399 /* branch resolving */
402 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
403 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
408 /* handle replacement points */
410 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
411 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
415 assert(cd->lastmcodeptr <= cd->mcodeptr);
416 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
419 /* copy interface registers to their destination */
425 /* generate basicblock profiling code */
428 /* count frequency */
430 M_MOV_IMM(m->bbfrequency, REG_ITMP2);
431 M_IINC_MEMBASE(REG_ITMP2, bptr->debug_nr * 4);
433 /* if this is an exception handler, start profiling again */
435 if (bptr->type == BBTYPE_EXH)
439 #if defined(ENABLE_LSRA)
441 while (src != NULL) {
443 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
444 if (bptr->type == BBTYPE_SBR) {
445 /* d = reg_of_var(rd, src, REG_ITMP1); */
446 if (!(src->flags & INMEMORY))
450 x86_64_pop_reg(cd, d);
451 store_reg_to_var_int(src, d);
453 } else if (bptr->type == BBTYPE_EXH) {
454 /* d = reg_of_var(rd, src, REG_ITMP1); */
455 if (!(src->flags & INMEMORY))
459 M_INTMOVE(REG_ITMP1, d);
460 store_reg_to_var_int(src, d);
469 while (src != NULL) {
471 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
472 if (bptr->type == BBTYPE_SBR) {
473 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
475 store_reg_to_var_int(src, d);
477 } else if (bptr->type == BBTYPE_EXH) {
478 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
479 M_INTMOVE(REG_ITMP1, d);
480 store_reg_to_var_int(src, d);
484 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
485 if ((src->varkind != STACKVAR)) {
487 if (IS_FLT_DBL_TYPE(s2)) {
488 s1 = rd->interfaces[len][s2].regoff;
490 if (!(rd->interfaces[len][s2].flags & INMEMORY))
493 M_DLD(d, REG_SP, s1 * 8);
495 store_reg_to_var_flt(src, d);
498 s1 = rd->interfaces[len][s2].regoff;
500 if (!(rd->interfaces[len][s2].flags & INMEMORY))
503 M_LLD(d, REG_SP, s1 * 8);
505 store_reg_to_var_int(src, d);
511 #if defined(ENABLE_LSRA)
514 /* walk through all instructions */
520 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
521 if (iptr->line != currentline) {
522 dseg_addlinenumber(cd, iptr->line, cd->mcodeptr);
523 currentline = iptr->line;
526 MCODECHECK(1024); /* 1KB should be enough */
529 case ICMD_INLINE_START: /* internal ICMDs */
530 case ICMD_INLINE_END:
533 case ICMD_NOP: /* ... ==> ... */
536 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
538 if (src->flags & INMEMORY)
539 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8);
543 codegen_add_nullpointerexception_ref(cd, cd->mcodeptr);
546 /* constant operations ************************************************/
548 case ICMD_ICONST: /* ... ==> ..., constant */
549 /* op1 = 0, val.i = constant */
551 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
552 if (iptr->val.i == 0)
555 M_IMOV_IMM(iptr->val.i, d);
556 store_reg_to_var_int(iptr->dst, d);
559 case ICMD_LCONST: /* ... ==> ..., constant */
560 /* op1 = 0, val.l = constant */
562 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
563 if (iptr->val.l == 0)
566 M_MOV_IMM(iptr->val.l, d);
567 store_reg_to_var_int(iptr->dst, d);
570 case ICMD_FCONST: /* ... ==> ..., constant */
571 /* op1 = 0, val.f = constant */
573 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
574 disp = dseg_addfloat(cd, iptr->val.f);
575 x86_64_movdl_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + ((d > 7) ? 9 : 8)) - (s8) cd->mcodebase) + disp, d);
576 store_reg_to_var_flt(iptr->dst, d);
579 case ICMD_DCONST: /* ... ==> ..., constant */
580 /* op1 = 0, val.d = constant */
582 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
583 disp = dseg_adddouble(cd, iptr->val.d);
584 x86_64_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, d);
585 store_reg_to_var_flt(iptr->dst, d);
588 case ICMD_ACONST: /* ... ==> ..., constant */
589 /* op1 = 0, val.a = constant */
591 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
593 if ((iptr->target != NULL) && (iptr->val.a == NULL)) {
594 /* PROFILE_CYCLE_STOP; */
596 codegen_addpatchref(cd, cd->mcodeptr,
598 (unresolved_class *) iptr->target, 0);
600 if (opt_showdisassemble) {
601 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
604 /* PROFILE_CYCLE_START; */
606 M_MOV_IMM(iptr->val.a, d);
609 if (iptr->val.a == 0)
612 M_MOV_IMM(iptr->val.a, d);
614 store_reg_to_var_int(iptr->dst, d);
618 /* load/store operations **********************************************/
620 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
621 /* op1 = local variable */
623 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
624 if ((iptr->dst->varkind == LOCALVAR) &&
625 (iptr->dst->varnum == iptr->op1)) {
628 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
629 if (var->flags & INMEMORY) {
630 x86_64_movl_membase_reg(cd, REG_SP, var->regoff * 8, d);
631 store_reg_to_var_int(iptr->dst, d);
634 if (iptr->dst->flags & INMEMORY) {
635 x86_64_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
638 M_INTMOVE(var->regoff, d);
643 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
644 case ICMD_ALOAD: /* op1 = local variable */
646 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
647 if ((iptr->dst->varkind == LOCALVAR) &&
648 (iptr->dst->varnum == iptr->op1)) {
651 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
652 if (var->flags & INMEMORY) {
653 x86_64_mov_membase_reg(cd, REG_SP, var->regoff * 8, d);
654 store_reg_to_var_int(iptr->dst, d);
657 if (iptr->dst->flags & INMEMORY) {
658 x86_64_mov_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
661 M_INTMOVE(var->regoff, d);
666 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
667 case ICMD_DLOAD: /* op1 = local variable */
669 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
670 if ((iptr->dst->varkind == LOCALVAR) &&
671 (iptr->dst->varnum == iptr->op1)) {
674 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
675 if (var->flags & INMEMORY) {
676 x86_64_movq_membase_reg(cd, REG_SP, var->regoff * 8, d);
677 store_reg_to_var_flt(iptr->dst, d);
680 if (iptr->dst->flags & INMEMORY) {
681 x86_64_movq_reg_membase(cd, var->regoff, REG_SP, iptr->dst->regoff * 8);
684 M_FLTMOVE(var->regoff, d);
689 case ICMD_ISTORE: /* ..., value ==> ... */
690 case ICMD_LSTORE: /* op1 = local variable */
693 if ((src->varkind == LOCALVAR) &&
694 (src->varnum == iptr->op1)) {
697 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
698 if (var->flags & INMEMORY) {
699 var_to_reg_int(s1, src, REG_ITMP1);
700 x86_64_mov_reg_membase(cd, s1, REG_SP, var->regoff * 8);
703 var_to_reg_int(s1, src, var->regoff);
704 M_INTMOVE(s1, var->regoff);
708 case ICMD_FSTORE: /* ..., value ==> ... */
709 case ICMD_DSTORE: /* op1 = local variable */
711 if ((src->varkind == LOCALVAR) &&
712 (src->varnum == iptr->op1)) {
715 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
716 if (var->flags & INMEMORY) {
717 var_to_reg_flt(s1, src, REG_FTMP1);
718 x86_64_movq_reg_membase(cd, s1, REG_SP, var->regoff * 8);
721 var_to_reg_flt(s1, src, var->regoff);
722 M_FLTMOVE(s1, var->regoff);
727 /* pop/dup/swap operations ********************************************/
729 /* attention: double and longs are only one entry in CACAO ICMDs */
731 case ICMD_POP: /* ..., value ==> ... */
732 case ICMD_POP2: /* ..., value, value ==> ... */
735 case ICMD_DUP: /* ..., a ==> ..., a, a */
736 M_COPY(src, iptr->dst);
739 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
741 M_COPY(src, iptr->dst);
742 M_COPY(src->prev, iptr->dst->prev);
743 M_COPY(iptr->dst, iptr->dst->prev->prev);
746 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
748 M_COPY(src, iptr->dst);
749 M_COPY(src->prev, iptr->dst->prev);
750 M_COPY(src->prev->prev, iptr->dst->prev->prev);
751 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
754 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
756 M_COPY(src, iptr->dst);
757 M_COPY(src->prev, iptr->dst->prev);
760 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
762 M_COPY(src, iptr->dst);
763 M_COPY(src->prev, iptr->dst->prev);
764 M_COPY(src->prev->prev, iptr->dst->prev->prev);
765 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
766 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
769 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
771 M_COPY(src, iptr->dst);
772 M_COPY(src->prev, iptr->dst->prev);
773 M_COPY(src->prev->prev, iptr->dst->prev->prev);
774 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
775 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
776 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
779 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
781 M_COPY(src, iptr->dst->prev);
782 M_COPY(src->prev, iptr->dst);
786 /* integer operations *************************************************/
788 case ICMD_INEG: /* ..., value ==> ..., - value */
790 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
791 if (iptr->dst->flags & INMEMORY) {
792 if (src->flags & INMEMORY) {
793 if (src->regoff == iptr->dst->regoff) {
794 x86_64_negl_membase(cd, REG_SP, iptr->dst->regoff * 8);
797 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
798 x86_64_negl_reg(cd, REG_ITMP1);
799 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
803 x86_64_movl_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
804 x86_64_negl_membase(cd, REG_SP, iptr->dst->regoff * 8);
808 if (src->flags & INMEMORY) {
809 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
810 x86_64_negl_reg(cd, d);
813 M_INTMOVE(src->regoff, iptr->dst->regoff);
814 x86_64_negl_reg(cd, iptr->dst->regoff);
819 case ICMD_LNEG: /* ..., value ==> ..., - value */
821 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
822 if (iptr->dst->flags & INMEMORY) {
823 if (src->flags & INMEMORY) {
824 if (src->regoff == iptr->dst->regoff) {
825 x86_64_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
828 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
829 x86_64_neg_reg(cd, REG_ITMP1);
830 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
834 x86_64_mov_reg_membase(cd, src->regoff, REG_SP, iptr->dst->regoff * 8);
835 x86_64_neg_membase(cd, REG_SP, iptr->dst->regoff * 8);
839 if (src->flags & INMEMORY) {
840 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
841 x86_64_neg_reg(cd, iptr->dst->regoff);
844 M_INTMOVE(src->regoff, iptr->dst->regoff);
845 x86_64_neg_reg(cd, iptr->dst->regoff);
850 case ICMD_I2L: /* ..., value ==> ..., value */
852 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
853 if (src->flags & INMEMORY) {
854 x86_64_movslq_membase_reg(cd, REG_SP, src->regoff * 8, d);
857 x86_64_movslq_reg_reg(cd, src->regoff, d);
859 store_reg_to_var_int(iptr->dst, d);
862 case ICMD_L2I: /* ..., value ==> ..., value */
864 var_to_reg_int(s1, src, REG_ITMP1);
865 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
867 store_reg_to_var_int(iptr->dst, d);
870 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
872 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
873 if (src->flags & INMEMORY) {
874 x86_64_movsbq_membase_reg(cd, REG_SP, src->regoff * 8, d);
877 x86_64_movsbq_reg_reg(cd, src->regoff, d);
879 store_reg_to_var_int(iptr->dst, d);
882 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
884 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
885 if (src->flags & INMEMORY) {
886 x86_64_movzwq_membase_reg(cd, REG_SP, src->regoff * 8, d);
889 x86_64_movzwq_reg_reg(cd, src->regoff, d);
891 store_reg_to_var_int(iptr->dst, d);
894 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
896 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
897 if (src->flags & INMEMORY) {
898 x86_64_movswq_membase_reg(cd, REG_SP, src->regoff * 8, d);
901 x86_64_movswq_reg_reg(cd, src->regoff, d);
903 store_reg_to_var_int(iptr->dst, d);
907 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
909 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
910 x86_64_emit_ialu(cd, X86_64_ADD, src, iptr);
913 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
914 /* val.i = constant */
916 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
917 x86_64_emit_ialuconst(cd, X86_64_ADD, src, iptr);
920 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
922 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
923 x86_64_emit_lalu(cd, X86_64_ADD, src, iptr);
926 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
927 /* val.l = constant */
929 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
930 x86_64_emit_laluconst(cd, X86_64_ADD, src, iptr);
933 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
935 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
936 if (iptr->dst->flags & INMEMORY) {
937 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
938 if (src->prev->regoff == iptr->dst->regoff) {
939 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
940 x86_64_alul_reg_membase(cd, X86_64_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
943 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
944 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
945 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
948 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
949 M_INTMOVE(src->prev->regoff, REG_ITMP1);
950 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
951 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
953 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
954 if (src->prev->regoff == iptr->dst->regoff) {
955 x86_64_alul_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
958 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
959 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
960 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
964 x86_64_movl_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
965 x86_64_alul_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
969 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
970 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
971 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
973 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
974 M_INTMOVE(src->prev->regoff, d);
975 x86_64_alul_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
977 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
978 /* workaround for reg alloc */
979 if (src->regoff == iptr->dst->regoff) {
980 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
981 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
982 M_INTMOVE(REG_ITMP1, d);
985 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
986 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, d);
990 /* workaround for reg alloc */
991 if (src->regoff == iptr->dst->regoff) {
992 M_INTMOVE(src->prev->regoff, REG_ITMP1);
993 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
994 M_INTMOVE(REG_ITMP1, d);
997 M_INTMOVE(src->prev->regoff, d);
998 x86_64_alul_reg_reg(cd, X86_64_SUB, src->regoff, d);
1004 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
1005 /* val.i = constant */
1007 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1008 x86_64_emit_ialuconst(cd, X86_64_SUB, src, iptr);
1011 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1013 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1014 if (iptr->dst->flags & INMEMORY) {
1015 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1016 if (src->prev->regoff == iptr->dst->regoff) {
1017 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1018 x86_64_alu_reg_membase(cd, X86_64_SUB, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1021 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1022 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1023 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1026 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1027 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1028 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, REG_ITMP1);
1029 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1031 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1032 if (src->prev->regoff == iptr->dst->regoff) {
1033 x86_64_alu_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1036 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1037 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1038 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1042 x86_64_mov_reg_membase(cd, src->prev->regoff, REG_SP, iptr->dst->regoff * 8);
1043 x86_64_alu_reg_membase(cd, X86_64_SUB, src->regoff, REG_SP, iptr->dst->regoff * 8);
1047 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1048 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1049 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
1051 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1052 M_INTMOVE(src->prev->regoff, d);
1053 x86_64_alu_membase_reg(cd, X86_64_SUB, REG_SP, src->regoff * 8, d);
1055 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1056 /* workaround for reg alloc */
1057 if (src->regoff == iptr->dst->regoff) {
1058 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1059 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1060 M_INTMOVE(REG_ITMP1, d);
1063 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, d);
1064 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, d);
1068 /* workaround for reg alloc */
1069 if (src->regoff == iptr->dst->regoff) {
1070 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1071 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, REG_ITMP1);
1072 M_INTMOVE(REG_ITMP1, d);
1075 M_INTMOVE(src->prev->regoff, d);
1076 x86_64_alu_reg_reg(cd, X86_64_SUB, src->regoff, d);
1082 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1083 /* val.l = constant */
1085 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1086 x86_64_emit_laluconst(cd, X86_64_SUB, src, iptr);
1089 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1091 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1092 if (iptr->dst->flags & INMEMORY) {
1093 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1094 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1095 x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1096 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1098 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1099 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1100 x86_64_imull_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1101 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1103 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1104 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1105 x86_64_imull_reg_reg(cd, src->regoff, REG_ITMP1);
1106 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1109 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1110 x86_64_imull_reg_reg(cd, src->regoff, REG_ITMP1);
1111 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1115 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1116 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1117 x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1119 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1120 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1121 x86_64_imull_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1123 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1124 M_INTMOVE(src->regoff, iptr->dst->regoff);
1125 x86_64_imull_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1128 if (src->regoff == iptr->dst->regoff) {
1129 x86_64_imull_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1132 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1133 x86_64_imull_reg_reg(cd, src->regoff, iptr->dst->regoff);
1139 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1140 /* val.i = constant */
1142 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1143 if (iptr->dst->flags & INMEMORY) {
1144 if (src->flags & INMEMORY) {
1145 x86_64_imull_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, REG_ITMP1);
1146 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1149 x86_64_imull_imm_reg_reg(cd, iptr->val.i, src->regoff, REG_ITMP1);
1150 x86_64_movl_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1154 if (src->flags & INMEMORY) {
1155 x86_64_imull_imm_membase_reg(cd, iptr->val.i, REG_SP, src->regoff * 8, iptr->dst->regoff);
1158 if (iptr->val.i == 2) {
1159 M_INTMOVE(src->regoff, iptr->dst->regoff);
1160 x86_64_alul_reg_reg(cd, X86_64_ADD, iptr->dst->regoff, iptr->dst->regoff);
1163 x86_64_imull_imm_reg_reg(cd, iptr->val.i, src->regoff, iptr->dst->regoff); /* 3 cycles */
1169 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1171 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1172 if (iptr->dst->flags & INMEMORY) {
1173 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1174 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1175 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1176 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1178 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1179 x86_64_mov_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1180 x86_64_imul_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1181 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1183 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1184 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, REG_ITMP1);
1185 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1186 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1189 x86_64_mov_reg_reg(cd, src->prev->regoff, REG_ITMP1);
1190 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1191 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1195 if ((src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1196 x86_64_mov_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1197 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1199 } else if ((src->flags & INMEMORY) && !(src->prev->flags & INMEMORY)) {
1200 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1201 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1203 } else if (!(src->flags & INMEMORY) && (src->prev->flags & INMEMORY)) {
1204 M_INTMOVE(src->regoff, iptr->dst->regoff);
1205 x86_64_imul_membase_reg(cd, REG_SP, src->prev->regoff * 8, iptr->dst->regoff);
1208 if (src->regoff == iptr->dst->regoff) {
1209 x86_64_imul_reg_reg(cd, src->prev->regoff, iptr->dst->regoff);
1212 M_INTMOVE(src->prev->regoff, iptr->dst->regoff);
1213 x86_64_imul_reg_reg(cd, src->regoff, iptr->dst->regoff);
1219 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1220 /* val.l = constant */
1222 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1223 if (iptr->dst->flags & INMEMORY) {
1224 if (src->flags & INMEMORY) {
1225 if (IS_IMM32(iptr->val.l)) {
1226 x86_64_imul_imm_membase_reg(cd, iptr->val.l, REG_SP, src->regoff * 8, REG_ITMP1);
1229 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1230 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP1);
1232 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1235 if (IS_IMM32(iptr->val.l)) {
1236 x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, REG_ITMP1);
1239 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1240 x86_64_imul_reg_reg(cd, src->regoff, REG_ITMP1);
1242 x86_64_mov_reg_membase(cd, REG_ITMP1, REG_SP, iptr->dst->regoff * 8);
1246 if (src->flags & INMEMORY) {
1247 if (IS_IMM32(iptr->val.l)) {
1248 x86_64_imul_imm_membase_reg(cd, iptr->val.l, REG_SP, src->regoff * 8, iptr->dst->regoff);
1251 x86_64_mov_imm_reg(cd, iptr->val.l, iptr->dst->regoff);
1252 x86_64_imul_membase_reg(cd, REG_SP, src->regoff * 8, iptr->dst->regoff);
1256 /* should match in many cases */
1257 if (iptr->val.l == 2) {
1258 M_INTMOVE(src->regoff, iptr->dst->regoff);
1259 x86_64_alul_reg_reg(cd, X86_64_ADD, iptr->dst->regoff, iptr->dst->regoff);
1262 if (IS_IMM32(iptr->val.l)) {
1263 x86_64_imul_imm_reg_reg(cd, iptr->val.l, src->regoff, iptr->dst->regoff); /* 4 cycles */
1266 x86_64_mov_imm_reg(cd, iptr->val.l, REG_ITMP1);
1267 M_INTMOVE(src->regoff, iptr->dst->regoff);
1268 x86_64_imul_reg_reg(cd, REG_ITMP1, iptr->dst->regoff);
1275 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1277 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1278 if (src->prev->flags & INMEMORY) {
1279 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, RAX);
1282 M_INTMOVE(src->prev->regoff, RAX);
1285 if (src->flags & INMEMORY) {
1286 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1289 M_INTMOVE(src->regoff, REG_ITMP3);
1293 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1294 x86_64_jcc(cd, X86_64_CC_NE, 4 + 6);
1295 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3); /* 4 bytes */
1296 x86_64_jcc(cd, X86_64_CC_E, 3 + 1 + 3); /* 6 bytes */
1298 x86_64_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1300 x86_64_idivl_reg(cd, REG_ITMP3);
1302 if (iptr->dst->flags & INMEMORY) {
1303 x86_64_mov_reg_membase(cd, RAX, REG_SP, iptr->dst->regoff * 8);
1304 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1307 M_INTMOVE(RAX, iptr->dst->regoff);
1309 if (iptr->dst->regoff != RDX) {
1310 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1315 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1316 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1317 if (src->prev->flags & INMEMORY) {
1318 x86_64_movl_membase_reg(cd, REG_SP, src->prev->regoff * 8, RAX);
1321 M_INTMOVE(src->prev->regoff, RAX);
1324 if (src->flags & INMEMORY) {
1325 x86_64_movl_membase_reg(cd, REG_SP, src->regoff * 8, REG_ITMP3);
1328 M_INTMOVE(src->regoff, REG_ITMP3);
1332 x86_64_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1334 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1335 x86_64_jcc(cd, X86_64_CC_NE, 2 + 4 + 6);
1338 x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX); /* 2 bytes */
1339 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP3); /* 4 bytes */
1340 x86_64_jcc(cd, X86_64_CC_E, 1 + 3); /* 6 bytes */
1343 x86_64_idivl_reg(cd, REG_ITMP3);
1345 if (iptr->dst->flags & INMEMORY) {
1346 x86_64_mov_reg_membase(cd, RDX, REG_SP, iptr->dst->regoff * 8);
1347 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1350 M_INTMOVE(RDX, iptr->dst->regoff);
1352 if (iptr->dst->regoff != RDX) {
1353 x86_64_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1358 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1359 /* val.i = constant */
1361 var_to_reg_int(s1, src, REG_ITMP1);
1362 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1363 M_INTMOVE(s1, REG_ITMP1);
1364 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1365 x86_64_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1366 x86_64_cmovccl_reg_reg(cd, X86_64_CC_LE, REG_ITMP2, REG_ITMP1);
1367 x86_64_shiftl_imm_reg(cd, X86_64_SAR, iptr->val.i, REG_ITMP1);
1368 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1369 store_reg_to_var_int(iptr->dst, d);
1372 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1373 /* val.i = constant */
1375 var_to_reg_int(s1, src, REG_ITMP1);
1376 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1377 M_INTMOVE(s1, REG_ITMP1);
1378 x86_64_alul_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1379 x86_64_leal_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1380 x86_64_cmovccl_reg_reg(cd, X86_64_CC_G, REG_ITMP1, REG_ITMP2);
1381 x86_64_alul_imm_reg(cd, X86_64_AND, -1 - (iptr->val.i), REG_ITMP2);
1382 x86_64_alul_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
1383 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1384 store_reg_to_var_int(iptr->dst, d);
1388 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1390 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1392 if (src->prev->flags & INMEMORY) {
1393 M_LLD(RAX, REG_SP, src->prev->regoff * 8);
1396 M_INTMOVE(src->prev->regoff, RAX);
1399 if (src->flags & INMEMORY) {
1400 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1403 M_INTMOVE(src->regoff, REG_ITMP3);
1407 /* check as described in jvm spec */
1408 disp = dseg_adds8(cd, 0x8000000000000000LL);
1409 M_CMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, RAX);
1411 M_CMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1412 M_BEQ(3 + 2 + 3); /* 6 bytes */
1414 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1416 x86_64_idiv_reg(cd, REG_ITMP3);
1418 if (iptr->dst->flags & INMEMORY) {
1419 M_LST(RAX, REG_SP, iptr->dst->regoff * 8);
1420 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1423 M_INTMOVE(RAX, iptr->dst->regoff);
1425 if (iptr->dst->regoff != RDX) {
1426 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1431 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1433 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1434 if (src->prev->flags & INMEMORY) {
1435 M_LLD(REG_ITMP1, REG_SP, src->prev->regoff * 8);
1438 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1441 if (src->flags & INMEMORY) {
1442 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1445 M_INTMOVE(src->regoff, REG_ITMP3);
1449 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1451 /* check as described in jvm spec */
1452 disp = dseg_adds8(cd, 0x8000000000000000LL);
1453 M_CMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP1);
1457 x86_64_alul_reg_reg(cd, X86_64_XOR, RDX, RDX); /* 2 bytes */
1459 M_XOR(RDX, RDX); /* 3 bytes */
1460 M_CMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1461 M_BEQ(2 + 3); /* 6 bytes */
1464 x86_64_idiv_reg(cd, REG_ITMP3);
1466 if (iptr->dst->flags & INMEMORY) {
1467 M_LST(RDX, REG_SP, iptr->dst->regoff * 8);
1468 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1471 M_INTMOVE(RDX, iptr->dst->regoff);
1473 if (iptr->dst->regoff != RDX) {
1474 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1479 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1480 /* val.i = constant */
1482 var_to_reg_int(s1, src, REG_ITMP1);
1483 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1484 M_INTMOVE(s1, REG_ITMP1);
1485 x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1486 x86_64_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1487 x86_64_cmovcc_reg_reg(cd, X86_64_CC_LE, REG_ITMP2, REG_ITMP1);
1488 x86_64_shift_imm_reg(cd, X86_64_SAR, iptr->val.i, REG_ITMP1);
1489 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1490 store_reg_to_var_int(iptr->dst, d);
1493 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1494 /* val.l = constant */
1496 var_to_reg_int(s1, src, REG_ITMP1);
1497 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1498 M_INTMOVE(s1, REG_ITMP1);
1499 x86_64_alu_imm_reg(cd, X86_64_CMP, -1, REG_ITMP1);
1500 x86_64_lea_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1501 x86_64_cmovcc_reg_reg(cd, X86_64_CC_G, REG_ITMP1, REG_ITMP2);
1502 x86_64_alu_imm_reg(cd, X86_64_AND, -1 - (iptr->val.i), REG_ITMP2);
1503 x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
1504 x86_64_mov_reg_reg(cd, REG_ITMP1, d);
1505 store_reg_to_var_int(iptr->dst, d);
1508 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1510 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1511 x86_64_emit_ishift(cd, X86_64_SHL, src, iptr);
1514 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1515 /* val.i = constant */
1517 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1518 x86_64_emit_ishiftconst(cd, X86_64_SHL, src, iptr);
1521 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1523 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1524 x86_64_emit_ishift(cd, X86_64_SAR, src, iptr);
1527 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1528 /* val.i = constant */
1530 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1531 x86_64_emit_ishiftconst(cd, X86_64_SAR, src, iptr);
1534 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1536 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1537 x86_64_emit_ishift(cd, X86_64_SHR, src, iptr);
1540 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1541 /* val.i = constant */
1543 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1544 x86_64_emit_ishiftconst(cd, X86_64_SHR, src, iptr);
1547 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1549 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1550 x86_64_emit_lshift(cd, X86_64_SHL, src, iptr);
1553 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1554 /* val.i = constant */
1556 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1557 x86_64_emit_lshiftconst(cd, X86_64_SHL, src, iptr);
1560 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1562 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1563 x86_64_emit_lshift(cd, X86_64_SAR, src, iptr);
1566 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1567 /* val.i = constant */
1569 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1570 x86_64_emit_lshiftconst(cd, X86_64_SAR, src, iptr);
1573 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1575 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1576 x86_64_emit_lshift(cd, X86_64_SHR, src, iptr);
1579 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1580 /* val.l = constant */
1582 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1583 x86_64_emit_lshiftconst(cd, X86_64_SHR, src, iptr);
1586 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1588 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1589 x86_64_emit_ialu(cd, X86_64_AND, src, iptr);
1592 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1593 /* val.i = constant */
1595 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1596 x86_64_emit_ialuconst(cd, X86_64_AND, src, iptr);
1599 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1601 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1602 x86_64_emit_lalu(cd, X86_64_AND, src, iptr);
1605 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1606 /* val.l = constant */
1608 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1609 x86_64_emit_laluconst(cd, X86_64_AND, src, iptr);
1612 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1614 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1615 x86_64_emit_ialu(cd, X86_64_OR, src, iptr);
1618 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1619 /* val.i = constant */
1621 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1622 x86_64_emit_ialuconst(cd, X86_64_OR, src, iptr);
1625 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1627 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1628 x86_64_emit_lalu(cd, X86_64_OR, src, iptr);
1631 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1632 /* val.l = constant */
1634 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1635 x86_64_emit_laluconst(cd, X86_64_OR, src, iptr);
1638 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1640 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1641 x86_64_emit_ialu(cd, X86_64_XOR, src, iptr);
1644 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1645 /* val.i = constant */
1647 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1648 x86_64_emit_ialuconst(cd, X86_64_XOR, src, iptr);
1651 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1653 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1654 x86_64_emit_lalu(cd, X86_64_XOR, src, iptr);
1657 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1658 /* val.l = constant */
1660 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1661 x86_64_emit_laluconst(cd, X86_64_XOR, src, iptr);
1665 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1666 /* op1 = variable, val.i = constant */
1668 /* using inc and dec is definitely faster than add -- tested */
1671 var = &(rd->locals[iptr->op1][TYPE_INT]);
1673 if (var->flags & INMEMORY) {
1674 if (iptr->val.i == 1) {
1675 x86_64_incl_membase(cd, REG_SP, d * 8);
1677 } else if (iptr->val.i == -1) {
1678 x86_64_decl_membase(cd, REG_SP, d * 8);
1681 x86_64_alul_imm_membase(cd, X86_64_ADD, iptr->val.i, REG_SP, d * 8);
1685 if (iptr->val.i == 1) {
1686 x86_64_incl_reg(cd, d);
1688 } else if (iptr->val.i == -1) {
1689 x86_64_decl_reg(cd, d);
1692 x86_64_alul_imm_reg(cd, X86_64_ADD, iptr->val.i, d);
1698 /* floating operations ************************************************/
1700 case ICMD_FNEG: /* ..., value ==> ..., - value */
1702 var_to_reg_flt(s1, src, REG_FTMP1);
1703 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1704 disp = dseg_adds4(cd, 0x80000000);
1706 x86_64_movss_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1707 x86_64_xorps_reg_reg(cd, REG_FTMP2, d);
1708 store_reg_to_var_flt(iptr->dst, d);
1711 case ICMD_DNEG: /* ..., value ==> ..., - value */
1713 var_to_reg_flt(s1, src, REG_FTMP1);
1714 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1715 disp = dseg_adds8(cd, 0x8000000000000000);
1717 x86_64_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1718 x86_64_xorpd_reg_reg(cd, REG_FTMP2, d);
1719 store_reg_to_var_flt(iptr->dst, d);
1722 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1724 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1725 var_to_reg_flt(s2, src, REG_FTMP2);
1726 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1728 x86_64_addss_reg_reg(cd, s2, d);
1729 } else if (s2 == d) {
1730 x86_64_addss_reg_reg(cd, s1, d);
1733 x86_64_addss_reg_reg(cd, s2, d);
1735 store_reg_to_var_flt(iptr->dst, d);
1738 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1740 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1741 var_to_reg_flt(s2, src, REG_FTMP2);
1742 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1744 x86_64_addsd_reg_reg(cd, s2, d);
1745 } else if (s2 == d) {
1746 x86_64_addsd_reg_reg(cd, s1, d);
1749 x86_64_addsd_reg_reg(cd, s2, d);
1751 store_reg_to_var_flt(iptr->dst, d);
1754 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1756 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1757 var_to_reg_flt(s2, src, REG_FTMP2);
1758 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1760 M_FLTMOVE(s2, REG_FTMP2);
1764 x86_64_subss_reg_reg(cd, s2, d);
1765 store_reg_to_var_flt(iptr->dst, d);
1768 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1770 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1771 var_to_reg_flt(s2, src, REG_FTMP2);
1772 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1774 M_FLTMOVE(s2, REG_FTMP2);
1778 x86_64_subsd_reg_reg(cd, s2, d);
1779 store_reg_to_var_flt(iptr->dst, d);
1782 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1784 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1785 var_to_reg_flt(s2, src, REG_FTMP2);
1786 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1788 x86_64_mulss_reg_reg(cd, s2, d);
1789 } else if (s2 == d) {
1790 x86_64_mulss_reg_reg(cd, s1, d);
1793 x86_64_mulss_reg_reg(cd, s2, d);
1795 store_reg_to_var_flt(iptr->dst, d);
1798 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1800 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1801 var_to_reg_flt(s2, src, REG_FTMP2);
1802 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1804 x86_64_mulsd_reg_reg(cd, s2, d);
1805 } else if (s2 == d) {
1806 x86_64_mulsd_reg_reg(cd, s1, d);
1809 x86_64_mulsd_reg_reg(cd, s2, d);
1811 store_reg_to_var_flt(iptr->dst, d);
1814 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1816 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1817 var_to_reg_flt(s2, src, REG_FTMP2);
1818 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1820 M_FLTMOVE(s2, REG_FTMP2);
1824 x86_64_divss_reg_reg(cd, s2, d);
1825 store_reg_to_var_flt(iptr->dst, d);
1828 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1830 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1831 var_to_reg_flt(s2, src, REG_FTMP2);
1832 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1834 M_FLTMOVE(s2, REG_FTMP2);
1838 x86_64_divsd_reg_reg(cd, s2, d);
1839 store_reg_to_var_flt(iptr->dst, d);
1842 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1844 var_to_reg_int(s1, src, REG_ITMP1);
1845 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1846 x86_64_cvtsi2ss_reg_reg(cd, s1, d);
1847 store_reg_to_var_flt(iptr->dst, d);
1850 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1852 var_to_reg_int(s1, src, REG_ITMP1);
1853 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1854 x86_64_cvtsi2sd_reg_reg(cd, s1, d);
1855 store_reg_to_var_flt(iptr->dst, d);
1858 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1860 var_to_reg_int(s1, src, REG_ITMP1);
1861 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1862 x86_64_cvtsi2ssq_reg_reg(cd, s1, d);
1863 store_reg_to_var_flt(iptr->dst, d);
1866 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1868 var_to_reg_int(s1, src, REG_ITMP1);
1869 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1870 x86_64_cvtsi2sdq_reg_reg(cd, s1, d);
1871 store_reg_to_var_flt(iptr->dst, d);
1874 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1876 var_to_reg_flt(s1, src, REG_FTMP1);
1877 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1878 x86_64_cvttss2si_reg_reg(cd, s1, d);
1879 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, d); /* corner cases */
1880 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1881 x86_64_jcc(cd, X86_64_CC_NE, a);
1882 M_FLTMOVE(s1, REG_FTMP1);
1883 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_f2i, REG_ITMP2);
1884 x86_64_call_reg(cd, REG_ITMP2);
1885 M_INTMOVE(REG_RESULT, d);
1886 store_reg_to_var_int(iptr->dst, d);
1889 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1891 var_to_reg_flt(s1, src, REG_FTMP1);
1892 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1893 x86_64_cvttsd2si_reg_reg(cd, s1, d);
1894 x86_64_alul_imm_reg(cd, X86_64_CMP, 0x80000000, d); /* corner cases */
1895 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1896 x86_64_jcc(cd, X86_64_CC_NE, a);
1897 M_FLTMOVE(s1, REG_FTMP1);
1898 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_d2i, REG_ITMP2);
1899 x86_64_call_reg(cd, REG_ITMP2);
1900 M_INTMOVE(REG_RESULT, d);
1901 store_reg_to_var_int(iptr->dst, d);
1904 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1906 var_to_reg_flt(s1, src, REG_FTMP1);
1907 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1908 x86_64_cvttss2siq_reg_reg(cd, s1, d);
1909 x86_64_mov_imm_reg(cd, 0x8000000000000000, REG_ITMP2);
1910 x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, d); /* corner cases */
1911 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1912 x86_64_jcc(cd, X86_64_CC_NE, a);
1913 M_FLTMOVE(s1, REG_FTMP1);
1914 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_f2l, REG_ITMP2);
1915 x86_64_call_reg(cd, REG_ITMP2);
1916 M_INTMOVE(REG_RESULT, d);
1917 store_reg_to_var_int(iptr->dst, d);
1920 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1922 var_to_reg_flt(s1, src, REG_FTMP1);
1923 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1924 x86_64_cvttsd2siq_reg_reg(cd, s1, d);
1925 x86_64_mov_imm_reg(cd, 0x8000000000000000, REG_ITMP2);
1926 x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP2, d); /* corner cases */
1927 a = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 + ((REG_RESULT == d) ? 0 : 3);
1928 x86_64_jcc(cd, X86_64_CC_NE, a);
1929 M_FLTMOVE(s1, REG_FTMP1);
1930 x86_64_mov_imm_reg(cd, (ptrint) asm_builtin_d2l, REG_ITMP2);
1931 x86_64_call_reg(cd, REG_ITMP2);
1932 M_INTMOVE(REG_RESULT, d);
1933 store_reg_to_var_int(iptr->dst, d);
1936 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1938 var_to_reg_flt(s1, src, REG_FTMP1);
1939 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1940 x86_64_cvtss2sd_reg_reg(cd, s1, d);
1941 store_reg_to_var_flt(iptr->dst, d);
1944 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1946 var_to_reg_flt(s1, src, REG_FTMP1);
1947 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1948 x86_64_cvtsd2ss_reg_reg(cd, s1, d);
1949 store_reg_to_var_flt(iptr->dst, d);
1952 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1953 /* == => 0, < => 1, > => -1 */
1955 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1956 var_to_reg_flt(s2, src, REG_FTMP2);
1957 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1959 M_MOV_IMM(1, REG_ITMP1);
1960 M_MOV_IMM(-1, REG_ITMP2);
1961 x86_64_ucomiss_reg_reg(cd, s1, s2);
1962 M_CMOVB(REG_ITMP1, d);
1963 M_CMOVA(REG_ITMP2, d);
1964 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1965 store_reg_to_var_int(iptr->dst, d);
1968 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1969 /* == => 0, < => 1, > => -1 */
1971 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1972 var_to_reg_flt(s2, src, REG_FTMP2);
1973 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1975 M_MOV_IMM(1, REG_ITMP1);
1976 M_MOV_IMM(-1, REG_ITMP2);
1977 x86_64_ucomiss_reg_reg(cd, s1, s2);
1978 M_CMOVB(REG_ITMP1, d);
1979 M_CMOVA(REG_ITMP2, d);
1980 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1981 store_reg_to_var_int(iptr->dst, d);
1984 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1985 /* == => 0, < => 1, > => -1 */
1987 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1988 var_to_reg_flt(s2, src, REG_FTMP2);
1989 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1991 M_MOV_IMM(1, REG_ITMP1);
1992 M_MOV_IMM(-1, REG_ITMP2);
1993 x86_64_ucomisd_reg_reg(cd, s1, s2);
1994 M_CMOVB(REG_ITMP1, d);
1995 M_CMOVA(REG_ITMP2, d);
1996 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1997 store_reg_to_var_int(iptr->dst, d);
2000 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
2001 /* == => 0, < => 1, > => -1 */
2003 var_to_reg_flt(s1, src->prev, REG_FTMP1);
2004 var_to_reg_flt(s2, src, REG_FTMP2);
2005 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2007 M_MOV_IMM(1, REG_ITMP1);
2008 M_MOV_IMM(-1, REG_ITMP2);
2009 x86_64_ucomisd_reg_reg(cd, s1, s2);
2010 M_CMOVB(REG_ITMP1, d);
2011 M_CMOVA(REG_ITMP2, d);
2012 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
2013 store_reg_to_var_int(iptr->dst, d);
2017 /* memory operations **************************************************/
2019 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
2021 var_to_reg_int(s1, src, REG_ITMP1);
2022 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2023 gen_nullptr_check(s1);
2024 M_ILD(d, s1, OFFSET(java_arrayheader, size));
2025 store_reg_to_var_int(iptr->dst, d);
2028 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
2030 var_to_reg_int(s1, src->prev, REG_ITMP1);
2031 var_to_reg_int(s2, src, REG_ITMP2);
2032 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2033 if (iptr->op1 == 0) {
2034 gen_nullptr_check(s1);
2037 x86_64_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
2038 store_reg_to_var_int(iptr->dst, d);
2041 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
2043 var_to_reg_int(s1, src->prev, REG_ITMP1);
2044 var_to_reg_int(s2, src, REG_ITMP2);
2045 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2046 if (iptr->op1 == 0) {
2047 gen_nullptr_check(s1);
2050 x86_64_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
2051 store_reg_to_var_int(iptr->dst, d);
2054 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
2056 var_to_reg_int(s1, src->prev, REG_ITMP1);
2057 var_to_reg_int(s2, src, REG_ITMP2);
2058 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2059 if (iptr->op1 == 0) {
2060 gen_nullptr_check(s1);
2063 x86_64_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
2064 store_reg_to_var_int(iptr->dst, d);
2067 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
2069 var_to_reg_int(s1, src->prev, REG_ITMP1);
2070 var_to_reg_int(s2, src, REG_ITMP2);
2071 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2072 if (iptr->op1 == 0) {
2073 gen_nullptr_check(s1);
2076 x86_64_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
2077 store_reg_to_var_int(iptr->dst, d);
2080 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
2082 var_to_reg_int(s1, src->prev, REG_ITMP1);
2083 var_to_reg_int(s2, src, REG_ITMP2);
2084 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2085 if (iptr->op1 == 0) {
2086 gen_nullptr_check(s1);
2089 x86_64_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
2090 store_reg_to_var_int(iptr->dst, d);
2093 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
2095 var_to_reg_int(s1, src->prev, REG_ITMP1);
2096 var_to_reg_int(s2, src, REG_ITMP2);
2097 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2098 if (iptr->op1 == 0) {
2099 gen_nullptr_check(s1);
2102 x86_64_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
2103 store_reg_to_var_flt(iptr->dst, d);
2106 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
2108 var_to_reg_int(s1, src->prev, REG_ITMP1);
2109 var_to_reg_int(s2, src, REG_ITMP2);
2110 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
2111 if (iptr->op1 == 0) {
2112 gen_nullptr_check(s1);
2115 x86_64_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
2116 store_reg_to_var_flt(iptr->dst, d);
2119 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
2121 var_to_reg_int(s1, src->prev, REG_ITMP1);
2122 var_to_reg_int(s2, src, REG_ITMP2);
2123 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2124 if (iptr->op1 == 0) {
2125 gen_nullptr_check(s1);
2128 x86_64_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
2129 store_reg_to_var_int(iptr->dst, d);
2133 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
2135 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2136 var_to_reg_int(s2, src->prev, REG_ITMP2);
2137 if (iptr->op1 == 0) {
2138 gen_nullptr_check(s1);
2141 var_to_reg_int(s3, src, REG_ITMP3);
2142 x86_64_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2145 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
2147 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2148 var_to_reg_int(s2, src->prev, REG_ITMP2);
2149 if (iptr->op1 == 0) {
2150 gen_nullptr_check(s1);
2153 var_to_reg_int(s3, src, REG_ITMP3);
2154 x86_64_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
2157 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
2159 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2160 var_to_reg_int(s2, src->prev, REG_ITMP2);
2161 if (iptr->op1 == 0) {
2162 gen_nullptr_check(s1);
2165 var_to_reg_int(s3, src, REG_ITMP3);
2166 x86_64_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2169 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2171 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2172 var_to_reg_int(s2, src->prev, REG_ITMP2);
2173 if (iptr->op1 == 0) {
2174 gen_nullptr_check(s1);
2177 var_to_reg_int(s3, src, REG_ITMP3);
2178 x86_64_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2181 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2183 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2184 var_to_reg_int(s2, src->prev, REG_ITMP2);
2185 if (iptr->op1 == 0) {
2186 gen_nullptr_check(s1);
2189 var_to_reg_int(s3, src, REG_ITMP3);
2190 x86_64_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2193 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2195 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2196 var_to_reg_int(s2, src->prev, REG_ITMP2);
2197 if (iptr->op1 == 0) {
2198 gen_nullptr_check(s1);
2201 var_to_reg_flt(s3, src, REG_FTMP3);
2202 x86_64_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2205 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2207 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2208 var_to_reg_int(s2, src->prev, REG_ITMP2);
2209 if (iptr->op1 == 0) {
2210 gen_nullptr_check(s1);
2213 var_to_reg_flt(s3, src, REG_FTMP3);
2214 x86_64_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2217 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2219 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2220 var_to_reg_int(s2, src->prev, REG_ITMP2);
2221 if (iptr->op1 == 0) {
2222 gen_nullptr_check(s1);
2225 var_to_reg_int(s3, src, REG_ITMP3);
2227 M_MOV(s1, rd->argintregs[0]);
2228 M_MOV(s3, rd->argintregs[1]);
2229 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2233 codegen_add_arraystoreexception_ref(cd, cd->mcodeptr);
2235 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
2236 var_to_reg_int(s2, src->prev, REG_ITMP2);
2237 var_to_reg_int(s3, src, REG_ITMP3);
2238 x86_64_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2242 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2244 var_to_reg_int(s1, src->prev, REG_ITMP1);
2245 var_to_reg_int(s2, src, REG_ITMP2);
2246 if (iptr->op1 == 0) {
2247 gen_nullptr_check(s1);
2250 x86_64_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2253 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2255 var_to_reg_int(s1, src->prev, REG_ITMP1);
2256 var_to_reg_int(s2, src, REG_ITMP2);
2257 if (iptr->op1 == 0) {
2258 gen_nullptr_check(s1);
2261 x86_64_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2264 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2266 var_to_reg_int(s1, src->prev, REG_ITMP1);
2267 var_to_reg_int(s2, src, REG_ITMP2);
2268 if (iptr->op1 == 0) {
2269 gen_nullptr_check(s1);
2272 x86_64_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2275 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2277 var_to_reg_int(s1, src->prev, REG_ITMP1);
2278 var_to_reg_int(s2, src, REG_ITMP2);
2279 if (iptr->op1 == 0) {
2280 gen_nullptr_check(s1);
2283 x86_64_movl_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2286 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2288 var_to_reg_int(s1, src->prev, REG_ITMP1);
2289 var_to_reg_int(s2, src, REG_ITMP2);
2290 if (iptr->op1 == 0) {
2291 gen_nullptr_check(s1);
2295 if (IS_IMM32(iptr->val.l)) {
2296 x86_64_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2298 x86_64_movl_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2299 x86_64_movl_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2303 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2305 var_to_reg_int(s1, src->prev, REG_ITMP1);
2306 var_to_reg_int(s2, src, REG_ITMP2);
2307 if (iptr->op1 == 0) {
2308 gen_nullptr_check(s1);
2311 x86_64_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2315 case ICMD_GETSTATIC: /* ... ==> ..., value */
2316 /* op1 = type, val.a = field address */
2318 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2319 disp = dseg_addaddress(cd, NULL);
2321 /* PROFILE_CYCLE_STOP; */
2323 codegen_addpatchref(cd, cd->mcodeptr,
2324 PATCHER_get_putstatic,
2325 INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
2327 if (opt_showdisassemble) {
2328 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2331 /* PROFILE_CYCLE_START; */
2334 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2336 disp = dseg_addaddress(cd, &(fi->value));
2338 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2341 codegen_addpatchref(cd, cd->mcodeptr,
2342 PATCHER_clinit, fi->class, 0);
2344 if (opt_showdisassemble) {
2345 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2348 PROFILE_CYCLE_START;
2352 /* This approach is much faster than moving the field
2353 address inline into a register. */
2355 M_ALD(REG_ITMP2, RIP, -(((ptrint) cd->mcodeptr + 7) -
2356 (ptrint) cd->mcodebase) + disp);
2358 switch (iptr->op1) {
2360 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2361 M_ILD(d, REG_ITMP2, 0);
2362 store_reg_to_var_int(iptr->dst, d);
2366 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2367 M_LLD(d, REG_ITMP2, 0);
2368 store_reg_to_var_int(iptr->dst, d);
2371 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2372 x86_64_movss_membase_reg(cd, REG_ITMP2, 0, d);
2373 store_reg_to_var_flt(iptr->dst, d);
2376 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2377 x86_64_movsd_membase_reg(cd, REG_ITMP2, 0, d);
2378 store_reg_to_var_flt(iptr->dst, d);
2383 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2384 /* op1 = type, val.a = field address */
2386 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2387 disp = dseg_addaddress(cd, NULL);
2389 /* PROFILE_CYCLE_STOP; */
2391 codegen_addpatchref(cd, cd->mcodeptr,
2392 PATCHER_get_putstatic,
2393 INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
2395 if (opt_showdisassemble) {
2396 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2399 /* PROFILE_CYCLE_START; */
2402 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2404 disp = dseg_addaddress(cd, &(fi->value));
2406 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2409 codegen_addpatchref(cd, cd->mcodeptr,
2410 PATCHER_clinit, fi->class, 0);
2412 if (opt_showdisassemble) {
2413 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2416 PROFILE_CYCLE_START;
2420 /* This approach is much faster than moving the field
2421 address inline into a register. */
2423 M_ALD(REG_ITMP2, RIP, -(((ptrint) cd->mcodeptr + 7) -
2424 (ptrint) cd->mcodebase) + disp);
2426 switch (iptr->op1) {
2428 var_to_reg_int(s2, src, REG_ITMP1);
2429 M_IST(s2, REG_ITMP2, 0);
2433 var_to_reg_int(s2, src, REG_ITMP1);
2434 M_LST(s2, REG_ITMP2, 0);
2437 var_to_reg_flt(s2, src, REG_FTMP1);
2438 x86_64_movss_reg_membase(cd, s2, REG_ITMP2, 0);
2441 var_to_reg_flt(s2, src, REG_FTMP1);
2442 x86_64_movsd_reg_membase(cd, s2, REG_ITMP2, 0);
2447 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2448 /* val = value (in current instruction) */
2449 /* op1 = type, val.a = field address (in */
2450 /* following NOP) */
2452 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2453 disp = dseg_addaddress(cd, NULL);
2455 /* PROFILE_CYCLE_STOP; */
2457 codegen_addpatchref(cd, cd->mcodeptr,
2458 PATCHER_get_putstatic,
2459 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), disp);
2461 if (opt_showdisassemble) {
2462 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2465 /* PROFILE_CYCLE_START; */
2468 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
2470 disp = dseg_addaddress(cd, &(fi->value));
2472 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2475 codegen_addpatchref(cd, cd->mcodeptr,
2476 PATCHER_clinit, fi->class, 0);
2478 if (opt_showdisassemble) {
2479 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2482 PROFILE_CYCLE_START;
2486 /* This approach is much faster than moving the field
2487 address inline into a register. */
2489 M_ALD(REG_ITMP1, RIP, -(((ptrint) cd->mcodeptr + 7) -
2490 (ptrint) cd->mcodebase) + disp);
2492 switch (iptr->op1) {
2495 M_IST_IMM(iptr->val.i, REG_ITMP1, 0);
2500 if (IS_IMM32(iptr->val.l)) {
2501 M_LST_IMM32(iptr->val.l, REG_ITMP1, 0);
2503 M_IST_IMM(iptr->val.l, REG_ITMP1, 0);
2504 M_IST_IMM(iptr->val.l >> 32, REG_ITMP1, 4);
2510 case ICMD_GETFIELD: /* ... ==> ..., value */
2511 /* op1 = type, val.i = field offset */
2513 var_to_reg_int(s1, src, REG_ITMP1);
2514 gen_nullptr_check(s1);
2516 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2517 /* PROFILE_CYCLE_STOP; */
2519 codegen_addpatchref(cd, cd->mcodeptr,
2520 PATCHER_get_putfield,
2521 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2523 if (opt_showdisassemble) {
2524 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2527 /* PROFILE_CYCLE_START; */
2532 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2535 switch (iptr->op1) {
2537 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2538 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2539 M_ILD32(d, s1, disp);
2542 store_reg_to_var_int(iptr->dst, d);
2546 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2547 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2548 M_LLD32(d, s1, disp);
2551 store_reg_to_var_int(iptr->dst, d);
2554 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2555 x86_64_movss_membase32_reg(cd, s1, disp, d);
2556 store_reg_to_var_flt(iptr->dst, d);
2559 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2560 x86_64_movsd_membase32_reg(cd, s1, disp, d);
2561 store_reg_to_var_flt(iptr->dst, d);
2566 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2567 /* op1 = type, val.i = field offset */
2569 var_to_reg_int(s1, src->prev, REG_ITMP1);
2570 gen_nullptr_check(s1);
2572 if (IS_INT_LNG_TYPE(iptr->op1)) {
2573 var_to_reg_int(s2, src, REG_ITMP2);
2575 var_to_reg_flt(s2, src, REG_FTMP2);
2578 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2579 /* PROFILE_CYCLE_STOP; */
2581 codegen_addpatchref(cd, cd->mcodeptr,
2582 PATCHER_get_putfield,
2583 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2585 if (opt_showdisassemble) {
2586 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2589 /* PROFILE_CYCLE_START; */
2594 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2597 switch (iptr->op1) {
2599 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2600 M_IST32(s2, s1, disp);
2602 M_IST(s2, s1, disp);
2606 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2607 M_LST32(s2, s1, disp);
2609 M_LST(s2, s1, disp);
2612 x86_64_movss_reg_membase32(cd, s2, s1, disp);
2615 x86_64_movsd_reg_membase32(cd, s2, s1, disp);
2620 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2621 /* val = value (in current instruction) */
2622 /* op1 = type, val.a = field address (in */
2623 /* following NOP) */
2625 var_to_reg_int(s1, src, REG_ITMP1);
2626 gen_nullptr_check(s1);
2628 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2629 /* PROFILE_CYCLE_STOP; */
2631 codegen_addpatchref(cd, cd->mcodeptr,
2632 PATCHER_putfieldconst,
2633 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2635 if (opt_showdisassemble) {
2636 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2639 /* PROFILE_CYCLE_START; */
2644 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
2647 switch (iptr->op1) {
2650 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1))
2651 M_IST32_IMM(iptr->val.i, s1, disp);
2653 M_IST_IMM(iptr->val.i, s1, disp);
2658 /* We can only optimize the move, if the class is
2659 resolved. Otherwise we don't know what to patch. */
2660 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2661 M_IST32_IMM(iptr->val.l, s1, disp);
2662 M_IST32_IMM(iptr->val.l >> 32, s1, disp + 4);
2664 if (IS_IMM32(iptr->val.l)) {
2665 M_LST_IMM32(iptr->val.l, s1, disp);
2667 M_IST_IMM(iptr->val.l, s1, disp);
2668 M_IST_IMM(iptr->val.l >> 32, s1, disp + 4);
2676 /* branch operations **************************************************/
2678 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2680 var_to_reg_int(s1, src, REG_ITMP1);
2681 M_INTMOVE(s1, REG_ITMP1_XPTR);
2685 #ifdef ENABLE_VERIFIER
2687 codegen_addpatchref(cd, cd->mcodeptr,
2688 PATCHER_athrow_areturn,
2689 (unresolved_class *) iptr->val.a, 0);
2691 if (opt_showdisassemble) {
2692 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2695 #endif /* ENABLE_VERIFIER */
2697 M_CALL_IMM(0); /* passing exception pc */
2698 M_POP(REG_ITMP2_XPC);
2700 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2704 case ICMD_GOTO: /* ... ==> ... */
2705 /* op1 = target JavaVM pc */
2708 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
2711 case ICMD_JSR: /* ... ==> ... */
2712 /* op1 = target JavaVM pc */
2715 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
2718 case ICMD_RET: /* ... ==> ... */
2719 /* op1 = local variable */
2721 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2722 var_to_reg_int(s1, var, REG_ITMP1);
2726 case ICMD_IFNULL: /* ..., value ==> ... */
2727 /* op1 = target JavaVM pc */
2729 if (src->flags & INMEMORY)
2730 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8);
2732 M_TEST(src->regoff);
2734 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
2737 case ICMD_IFNONNULL: /* ..., value ==> ... */
2738 /* op1 = target JavaVM pc */
2740 if (src->flags & INMEMORY)
2741 M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8);
2743 M_TEST(src->regoff);
2745 codegen_addreference(cd, (basicblock *) iptr->target, cd->mcodeptr);
2748 case ICMD_IFEQ: /* ..., value ==> ... */
2749 /* op1 = target JavaVM pc, val.i = constant */
2751 x86_64_emit_ifcc(cd, X86_64_CC_E, src, iptr);
2754 case ICMD_IFLT: /* ..., value ==> ... */
2755 /* op1 = target JavaVM pc, val.i = constant */
2757 x86_64_emit_ifcc(cd, X86_64_CC_L, src, iptr);
2760 case ICMD_IFLE: /* ..., value ==> ... */
2761 /* op1 = target JavaVM pc, val.i = constant */
2763 x86_64_emit_ifcc(cd, X86_64_CC_LE, src, iptr);
2766 case ICMD_IFNE: /* ..., value ==> ... */
2767 /* op1 = target JavaVM pc, val.i = constant */
2769 x86_64_emit_ifcc(cd, X86_64_CC_NE, src, iptr);
2772 case ICMD_IFGT: /* ..., value ==> ... */
2773 /* op1 = target JavaVM pc, val.i = constant */
2775 x86_64_emit_ifcc(cd, X86_64_CC_G, src, iptr);
2778 case ICMD_IFGE: /* ..., value ==> ... */
2779 /* op1 = target JavaVM pc, val.i = constant */
2781 x86_64_emit_ifcc(cd, X86_64_CC_GE, src, iptr);
2784 case ICMD_IF_LEQ: /* ..., value ==> ... */
2785 /* op1 = target JavaVM pc, val.l = constant */
2787 x86_64_emit_if_lcc(cd, X86_64_CC_E, src, iptr);
2790 case ICMD_IF_LLT: /* ..., value ==> ... */
2791 /* op1 = target JavaVM pc, val.l = constant */
2793 x86_64_emit_if_lcc(cd, X86_64_CC_L, src, iptr);
2796 case ICMD_IF_LLE: /* ..., value ==> ... */
2797 /* op1 = target JavaVM pc, val.l = constant */
2799 x86_64_emit_if_lcc(cd, X86_64_CC_LE, src, iptr);
2802 case ICMD_IF_LNE: /* ..., value ==> ... */
2803 /* op1 = target JavaVM pc, val.l = constant */
2805 x86_64_emit_if_lcc(cd, X86_64_CC_NE, src, iptr);
2808 case ICMD_IF_LGT: /* ..., value ==> ... */
2809 /* op1 = target JavaVM pc, val.l = constant */
2811 x86_64_emit_if_lcc(cd, X86_64_CC_G, src, iptr);
2814 case ICMD_IF_LGE: /* ..., value ==> ... */
2815 /* op1 = target JavaVM pc, val.l = constant */
2817 x86_64_emit_if_lcc(cd, X86_64_CC_GE, src, iptr);
2820 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2821 /* op1 = target JavaVM pc */
2823 x86_64_emit_if_icmpcc(cd, X86_64_CC_E, src, iptr);
2826 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2827 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2829 x86_64_emit_if_lcmpcc(cd, X86_64_CC_E, src, iptr);
2832 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2833 /* op1 = target JavaVM pc */
2835 x86_64_emit_if_icmpcc(cd, X86_64_CC_NE, src, iptr);
2838 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2839 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2841 x86_64_emit_if_lcmpcc(cd, X86_64_CC_NE, src, iptr);
2844 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2845 /* op1 = target JavaVM pc */
2847 x86_64_emit_if_icmpcc(cd, X86_64_CC_L, src, iptr);
2850 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2851 /* op1 = target JavaVM pc */
2853 x86_64_emit_if_lcmpcc(cd, X86_64_CC_L, src, iptr);
2856 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2857 /* op1 = target JavaVM pc */
2859 x86_64_emit_if_icmpcc(cd, X86_64_CC_G, src, iptr);
2862 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2863 /* op1 = target JavaVM pc */
2865 x86_64_emit_if_lcmpcc(cd, X86_64_CC_G, src, iptr);
2868 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2869 /* op1 = target JavaVM pc */
2871 x86_64_emit_if_icmpcc(cd, X86_64_CC_LE, src, iptr);
2874 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2875 /* op1 = target JavaVM pc */
2877 x86_64_emit_if_lcmpcc(cd, X86_64_CC_LE, src, iptr);
2880 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2881 /* op1 = target JavaVM pc */
2883 x86_64_emit_if_icmpcc(cd, X86_64_CC_GE, src, iptr);
2886 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2887 /* op1 = target JavaVM pc */
2889 x86_64_emit_if_lcmpcc(cd, X86_64_CC_GE, src, iptr);
2892 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2894 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2897 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2898 case ICMD_IFNE_ICONST: /* val.i = constant */
2899 case ICMD_IFLT_ICONST:
2900 case ICMD_IFGE_ICONST:
2901 case ICMD_IFGT_ICONST:
2902 case ICMD_IFLE_ICONST:
2904 var_to_reg_int(s1, src, REG_ITMP1);
2905 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2906 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2908 M_INTMOVE(s1, REG_ITMP1);
2911 if (iptr[1].val.i == 0)
2914 M_IMOV_IMM(iptr[1].val.i, d);
2916 if (iptr->val.i == 0)
2919 M_IMOV_IMM(iptr->val.i, REG_ITMP2);
2922 switch (iptr->opc) {
2923 case ICMD_IFEQ_ICONST:
2924 M_CMOVEQ(REG_ITMP2, d);
2926 case ICMD_IFNE_ICONST:
2927 M_CMOVNE(REG_ITMP2, d);
2929 case ICMD_IFLT_ICONST:
2930 M_CMOVLT(REG_ITMP2, d);
2932 case ICMD_IFGE_ICONST:
2933 M_CMOVGE(REG_ITMP2, d);
2935 case ICMD_IFGT_ICONST:
2936 M_CMOVGT(REG_ITMP2, d);
2938 case ICMD_IFLE_ICONST:
2939 M_CMOVLE(REG_ITMP2, d);
2943 store_reg_to_var_int(iptr->dst, d);
2947 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2950 var_to_reg_int(s1, src, REG_RESULT);
2951 M_INTMOVE(s1, REG_RESULT);
2952 goto nowperformreturn;
2954 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2956 var_to_reg_int(s1, src, REG_RESULT);
2957 M_INTMOVE(s1, REG_RESULT);
2959 #ifdef ENABLE_VERIFIER
2963 codegen_addpatchref(cd, cd->mcodeptr,
2964 PATCHER_athrow_areturn,
2965 (unresolved_class *) iptr->val.a, 0);
2967 if (opt_showdisassemble) {
2968 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2971 PROFILE_CYCLE_START;
2973 #endif /* ENABLE_VERIFIER */
2974 goto nowperformreturn;
2976 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2979 var_to_reg_flt(s1, src, REG_FRESULT);
2980 M_FLTMOVE(s1, REG_FRESULT);
2981 goto nowperformreturn;
2983 case ICMD_RETURN: /* ... ==> ... */
2991 #if !defined(NDEBUG)
2992 /* generate call trace */
2994 if (opt_verbosecall) {
2995 x86_64_alu_imm_reg(cd, X86_64_SUB, 2 * 8, REG_SP);
2997 x86_64_mov_reg_membase(cd, REG_RESULT, REG_SP, 0 * 8);
2998 x86_64_movq_reg_membase(cd, REG_FRESULT, REG_SP, 1 * 8);
3000 x86_64_mov_imm_reg(cd, (u8) m, rd->argintregs[0]);
3001 x86_64_mov_reg_reg(cd, REG_RESULT, rd->argintregs[1]);
3002 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3003 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3005 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
3008 x86_64_mov_membase_reg(cd, REG_SP, 0 * 8, REG_RESULT);
3009 x86_64_movq_membase_reg(cd, REG_SP, 1 * 8, REG_FRESULT);
3011 x86_64_alu_imm_reg(cd, X86_64_ADD, 2 * 8, REG_SP);
3013 #endif /* !defined(NDEBUG) */
3015 #if defined(USE_THREADS)
3016 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
3017 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
3019 /* we need to save the proper return value */
3020 switch (iptr->opc) {
3024 M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
3028 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
3032 M_MOV_IMM(builtin_monitorexit, REG_ITMP1);
3035 /* and now restore the proper return value */
3036 switch (iptr->opc) {
3040 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
3044 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
3050 /* restore saved registers */
3052 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
3053 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
3055 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
3056 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
3059 /* deallocate stack */
3062 M_AADD_IMM(stackframesize * 8, REG_SP);
3064 /* generate method profiling code */
3073 case ICMD_TABLESWITCH: /* ..., index ==> ... */
3078 tptr = (void **) iptr->target;
3080 s4ptr = iptr->val.a;
3081 l = s4ptr[1]; /* low */
3082 i = s4ptr[2]; /* high */
3084 var_to_reg_int(s1, src, REG_ITMP1);
3085 M_INTMOVE(s1, REG_ITMP1);
3087 x86_64_alul_imm_reg(cd, X86_64_SUB, l, REG_ITMP1);
3092 x86_64_alul_imm_reg(cd, X86_64_CMP, i - 1, REG_ITMP1);
3093 x86_64_jcc(cd, X86_64_CC_A, 0);
3095 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), cd->mcodeptr); */
3096 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3098 /* build jump table top down and use address of lowest entry */
3100 /* s4ptr += 3 + i; */
3104 dseg_addtarget(cd, (basicblock *) tptr[0]);
3108 /* length of dataseg after last dseg_addtarget is used by load */
3110 x86_64_mov_imm_reg(cd, 0, REG_ITMP2);
3111 dseg_adddata(cd, cd->mcodeptr);
3112 x86_64_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
3113 x86_64_jmp_reg(cd, REG_ITMP1);
3118 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3120 s4 i, l, val, *s4ptr;
3123 tptr = (void **) iptr->target;
3125 s4ptr = iptr->val.a;
3126 l = s4ptr[0]; /* default */
3127 i = s4ptr[1]; /* count */
3129 MCODECHECK(8 + ((7 + 6) * i) + 5);
3130 var_to_reg_int(s1, src, REG_ITMP1); /* reg compare should always be faster */
3136 x86_64_alul_imm_reg(cd, X86_64_CMP, val, s1);
3137 x86_64_jcc(cd, X86_64_CC_E, 0);
3138 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3141 x86_64_jmp_imm(cd, 0);
3143 tptr = (void **) iptr->target;
3144 codegen_addreference(cd, (basicblock *) tptr[0], cd->mcodeptr);
3149 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
3150 /* op1 = arg count val.a = builtintable entry */
3156 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3157 /* op1 = arg count, val.a = method pointer */
3159 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3160 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3161 case ICMD_INVOKEINTERFACE:
3163 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3164 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
3168 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
3169 md = lm->parseddesc;
3173 s3 = md->paramcount;
3175 MCODECHECK((20 * s3) + 128);
3177 /* copy arguments to registers or stack location */
3179 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3180 if (src->varkind == ARGVAR)
3182 if (IS_INT_LNG_TYPE(src->type)) {
3183 if (!md->params[s3].inmemory) {
3184 s1 = rd->argintregs[md->params[s3].regoff];
3185 var_to_reg_int(d, src, s1);
3188 var_to_reg_int(d, src, REG_ITMP1);
3189 M_LST(d, REG_SP, md->params[s3].regoff * 8);
3193 if (!md->params[s3].inmemory) {
3194 s1 = rd->argfltregs[md->params[s3].regoff];
3195 var_to_reg_flt(d, src, s1);
3198 var_to_reg_flt(d, src, REG_FTMP1);
3199 M_DST(d, REG_SP, md->params[s3].regoff * 8);
3204 /* generate method profiling code */
3208 switch (iptr->opc) {
3210 a = (ptrint) bte->fp;
3211 d = md->returntype.type;
3213 M_MOV_IMM(a, REG_ITMP1);
3216 /* if op1 == true, we need to check for an exception */
3218 if (iptr->op1 == true) {
3221 codegen_add_fillinstacktrace_ref(cd, cd->mcodeptr);
3225 case ICMD_INVOKESPECIAL:
3226 M_TEST(rd->argintregs[0]);
3228 codegen_add_nullpointerexception_ref(cd, cd->mcodeptr);
3230 /* first argument contains pointer */
3231 /* gen_nullptr_check(rd->argintregs[0]); */
3233 /* access memory for hardware nullptr */
3234 /* x86_64_mov_membase_reg(cd, rd->argintregs[0], 0, REG_ITMP2); */
3238 case ICMD_INVOKESTATIC:
3240 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3242 codegen_addpatchref(cd, cd->mcodeptr,
3243 PATCHER_invokestatic_special, um, 0);
3245 if (opt_showdisassemble) {
3246 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3250 d = um->methodref->parseddesc.md->returntype.type;
3253 a = (ptrint) lm->stubroutine;
3254 d = lm->parseddesc->returntype.type;
3257 M_MOV_IMM(a, REG_ITMP2);
3261 case ICMD_INVOKEVIRTUAL:
3262 gen_nullptr_check(rd->argintregs[0]);
3265 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3267 codegen_addpatchref(cd, cd->mcodeptr,
3268 PATCHER_invokevirtual, um, 0);
3270 if (opt_showdisassemble) {
3271 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3275 d = um->methodref->parseddesc.md->returntype.type;
3278 s1 = OFFSET(vftbl_t, table[0]) +
3279 sizeof(methodptr) * lm->vftblindex;
3280 d = lm->parseddesc->returntype.type;
3283 x86_64_mov_membase_reg(cd, rd->argintregs[0],
3284 OFFSET(java_objectheader, vftbl),
3286 x86_64_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP1);
3290 case ICMD_INVOKEINTERFACE:
3291 gen_nullptr_check(rd->argintregs[0]);
3294 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3296 codegen_addpatchref(cd, cd->mcodeptr,
3297 PATCHER_invokeinterface, um, 0);
3299 if (opt_showdisassemble) {
3300 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3305 d = um->methodref->parseddesc.md->returntype.type;
3308 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3309 sizeof(methodptr) * lm->class->index;
3311 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3313 d = lm->parseddesc->returntype.type;
3316 M_ALD(REG_ITMP2, rd->argintregs[0],
3317 OFFSET(java_objectheader, vftbl));
3318 x86_64_mov_membase32_reg(cd, REG_ITMP2, s1, REG_ITMP2);
3319 x86_64_mov_membase32_reg(cd, REG_ITMP2, s2, REG_ITMP1);
3324 /* generate method profiling code */
3326 PROFILE_CYCLE_START;
3328 /* d contains return type */
3330 if (d != TYPE_VOID) {
3331 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3332 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3333 M_INTMOVE(REG_RESULT, s1);
3334 store_reg_to_var_int(iptr->dst, s1);
3336 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FRESULT);
3337 M_FLTMOVE(REG_FRESULT, s1);
3338 store_reg_to_var_flt(iptr->dst, s1);
3344 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3346 /* op1: 0 == array, 1 == class */
3347 /* val.a: (classinfo *) superclass */
3349 /* superclass is an interface:
3351 * OK if ((sub == NULL) ||
3352 * (sub->vftbl->interfacetablelength > super->index) &&
3353 * (sub->vftbl->interfacetable[-super->index] != NULL));
3355 * superclass is a class:
3357 * OK if ((sub == NULL) || (0
3358 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3359 * super->vftbl->diffval));
3362 if (iptr->op1 == 1) {
3363 /* object type cast-check */
3366 vftbl_t *supervftbl;
3369 super = (classinfo *) iptr->val.a;
3376 superindex = super->index;
3377 supervftbl = super->vftbl;
3380 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3381 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3383 var_to_reg_int(s1, src, REG_ITMP1);
3385 /* calculate interface checkcast code size */
3387 s2 = 3; /* mov_membase_reg */
3388 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3390 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub imm32 */ +
3391 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3392 3 /* test */ + 6 /* jcc */;
3395 s2 += (opt_showdisassemble ? 5 : 0);
3397 /* calculate class checkcast code size */
3399 s3 = 3; /* mov_membase_reg */
3400 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3401 s3 += 10 /* mov_imm_reg */ + 3 + 4 /* movl_membase32_reg */;
3404 if (s1 != REG_ITMP1) {
3405 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3406 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3407 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3408 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3414 s3 += 3 + 4 /* movl_membase32_reg */ + 3 /* sub */ +
3415 10 /* mov_imm_reg */ + 3 /* movl_membase_reg */;
3416 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3419 s3 += 3 /* cmp */ + 6 /* jcc */;
3422 s3 += (opt_showdisassemble ? 5 : 0);
3424 /* if class is not resolved, check which code to call */
3428 M_BEQ(6 + (opt_showdisassemble ? 5 : 0) + 7 + 6 + s2 + 5 + s3);
3430 codegen_addpatchref(cd, cd->mcodeptr,
3431 PATCHER_checkcast_instanceof_flags,
3432 (constant_classref *) iptr->target, 0);
3434 if (opt_showdisassemble) {
3435 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3438 M_IMOV_IMM(0, REG_ITMP2); /* super->flags */
3439 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
3443 /* interface checkcast code */
3445 if (!super || (super->flags & ACC_INTERFACE)) {
3451 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3454 codegen_addpatchref(cd, cd->mcodeptr,
3455 PATCHER_checkcast_instanceof_interface,
3456 (constant_classref *) iptr->target, 0);
3458 if (opt_showdisassemble) {
3459 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3463 x86_64_movl_membase32_reg(cd, REG_ITMP2,
3464 OFFSET(vftbl_t, interfacetablelength),
3466 /* XXX TWISTI: should this be int arithmetic? */
3467 M_LSUB_IMM32(superindex, REG_ITMP3);
3470 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
3471 x86_64_mov_membase32_reg(cd, REG_ITMP2,
3472 OFFSET(vftbl_t, interfacetable[0]) -
3473 superindex * sizeof(methodptr*),
3477 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
3483 /* class checkcast code */
3485 if (!super || !(super->flags & ACC_INTERFACE)) {
3491 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3494 codegen_addpatchref(cd, cd->mcodeptr,
3495 PATCHER_checkcast_class,
3496 (constant_classref *) iptr->target,
3499 if (opt_showdisassemble) {
3500 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3504 M_MOV_IMM(supervftbl, REG_ITMP3);
3505 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3506 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3508 x86_64_movl_membase32_reg(cd, REG_ITMP2,
3509 OFFSET(vftbl_t, baseval),
3511 /* if (s1 != REG_ITMP1) { */
3512 /* x86_64_movl_membase_reg(cd, REG_ITMP3, */
3513 /* OFFSET(vftbl_t, baseval), */
3515 /* x86_64_movl_membase_reg(cd, REG_ITMP3, */
3516 /* OFFSET(vftbl_t, diffval), */
3518 /* #if defined(USE_THREADS) && defined(NATIVE_THREADS) */
3519 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3521 /* x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP1, REG_ITMP2); */
3524 x86_64_movl_membase32_reg(cd, REG_ITMP3,
3525 OFFSET(vftbl_t, baseval),
3527 M_LSUB(REG_ITMP3, REG_ITMP2);
3528 M_MOV_IMM(supervftbl, REG_ITMP3);
3529 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3531 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3532 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3534 M_CMP(REG_ITMP3, REG_ITMP2);
3535 M_BA(0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
3536 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
3538 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
3541 /* array type cast-check */
3543 var_to_reg_int(s1, src, REG_ITMP1);
3544 M_INTMOVE(s1, rd->argintregs[0]);
3546 if (iptr->val.a == NULL) {
3547 codegen_addpatchref(cd, cd->mcodeptr,
3548 PATCHER_builtin_arraycheckcast,
3549 (constant_classref *) iptr->target, 0);
3551 if (opt_showdisassemble) {
3552 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3556 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3557 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
3561 codegen_add_classcastexception_ref(cd, cd->mcodeptr);
3563 var_to_reg_int(s1, src, REG_ITMP1);
3564 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
3567 store_reg_to_var_int(iptr->dst, d);
3570 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3572 /* op1: 0 == array, 1 == class */
3573 /* val.a: (classinfo *) superclass */
3575 /* superclass is an interface:
3577 * return (sub != NULL) &&
3578 * (sub->vftbl->interfacetablelength > super->index) &&
3579 * (sub->vftbl->interfacetable[-super->index] != NULL);
3581 * superclass is a class:
3583 * return ((sub != NULL) && (0
3584 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3585 * super->vftbl->diffvall));
3590 vftbl_t *supervftbl;
3593 super = (classinfo *) iptr->val.a;
3600 superindex = super->index;
3601 supervftbl = super->vftbl;
3604 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3605 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3608 var_to_reg_int(s1, src, REG_ITMP1);
3609 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3611 M_INTMOVE(s1, REG_ITMP1);
3615 /* calculate interface instanceof code size */
3617 s2 = 3; /* mov_membase_reg */
3618 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3619 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub_imm32 */ +
3620 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3621 3 /* test */ + 4 /* setcc */;
3624 s2 += (opt_showdisassemble ? 5 : 0);
3626 /* calculate class instanceof code size */
3628 s3 = 3; /* mov_membase_reg */
3629 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3630 s3 += 10; /* mov_imm_reg */
3631 s3 += 2; /* movl_membase_reg - only if REG_ITMP1 == RAX */
3632 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3633 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3634 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3635 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3636 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3637 s3 += 3 /* sub */ + 3 /* xor */ + 3 /* cmp */ + 4 /* setcc */;
3640 s3 += (opt_showdisassemble ? 5 : 0);
3642 x86_64_alu_reg_reg(cd, X86_64_XOR, d, d);
3644 /* if class is not resolved, check which code to call */
3647 x86_64_test_reg_reg(cd, s1, s1);
3648 x86_64_jcc(cd, X86_64_CC_Z, (6 + (opt_showdisassemble ? 5 : 0) +
3649 7 + 6 + s2 + 5 + s3));
3651 codegen_addpatchref(cd, cd->mcodeptr,
3652 PATCHER_checkcast_instanceof_flags,
3653 (constant_classref *) iptr->target, 0);
3655 if (opt_showdisassemble) {
3656 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3659 x86_64_movl_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
3660 x86_64_alul_imm_reg(cd, X86_64_AND, ACC_INTERFACE, REG_ITMP3);
3661 x86_64_jcc(cd, X86_64_CC_Z, s2 + 5);
3664 /* interface instanceof code */
3666 if (!super || (super->flags & ACC_INTERFACE)) {
3668 x86_64_test_reg_reg(cd, s1, s1);
3669 x86_64_jcc(cd, X86_64_CC_Z, s2);
3672 x86_64_mov_membase_reg(cd, s1,
3673 OFFSET(java_objectheader, vftbl),
3676 codegen_addpatchref(cd, cd->mcodeptr,
3677 PATCHER_checkcast_instanceof_interface,
3678 (constant_classref *) iptr->target, 0);
3680 if (opt_showdisassemble) {
3681 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3685 x86_64_movl_membase32_reg(cd, REG_ITMP1,
3686 OFFSET(vftbl_t, interfacetablelength),
3688 x86_64_alu_imm32_reg(cd, X86_64_SUB, superindex, REG_ITMP3);
3689 x86_64_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
3691 a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
3693 x86_64_jcc(cd, X86_64_CC_LE, a);
3694 x86_64_mov_membase32_reg(cd, REG_ITMP1,
3695 OFFSET(vftbl_t, interfacetable[0]) -
3696 superindex * sizeof(methodptr*),
3698 x86_64_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3699 x86_64_setcc_reg(cd, X86_64_CC_NE, d);
3702 x86_64_jmp_imm(cd, s3);
3705 /* class instanceof code */
3707 if (!super || !(super->flags & ACC_INTERFACE)) {
3709 x86_64_test_reg_reg(cd, s1, s1);
3710 x86_64_jcc(cd, X86_64_CC_E, s3);
3713 x86_64_mov_membase_reg(cd, s1,
3714 OFFSET(java_objectheader, vftbl),
3718 codegen_addpatchref(cd, cd->mcodeptr,
3719 PATCHER_instanceof_class,
3720 (constant_classref *) iptr->target, 0);
3722 if (opt_showdisassemble) {
3723 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3727 x86_64_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
3728 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3729 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3731 x86_64_movl_membase_reg(cd, REG_ITMP1,
3732 OFFSET(vftbl_t, baseval),
3734 x86_64_movl_membase_reg(cd, REG_ITMP2,
3735 OFFSET(vftbl_t, diffval),
3737 x86_64_movl_membase_reg(cd, REG_ITMP2,
3738 OFFSET(vftbl_t, baseval),
3740 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3741 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3743 x86_64_alu_reg_reg(cd, X86_64_SUB, REG_ITMP2, REG_ITMP1);
3744 x86_64_alu_reg_reg(cd, X86_64_XOR, d, d); /* may be REG_ITMP2 */
3745 x86_64_alu_reg_reg(cd, X86_64_CMP, REG_ITMP3, REG_ITMP1);
3746 x86_64_setcc_reg(cd, X86_64_CC_BE, d);
3748 store_reg_to_var_int(iptr->dst, d);
3752 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3753 /* op1 = dimension, val.a = class */
3755 /* check for negative sizes and copy sizes to stack if necessary */
3757 MCODECHECK((10 * 4 * iptr->op1) + 5 + 10 * 8);
3759 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3760 /* copy SAVEDVAR sizes to stack */
3762 if (src->varkind != ARGVAR) {
3763 var_to_reg_int(s2, src, REG_ITMP1);
3764 M_LST(s2, REG_SP, s1 * 8);
3768 /* is a patcher function set? */
3770 if (iptr->val.a == NULL) {
3771 codegen_addpatchref(cd, cd->mcodeptr,
3772 PATCHER_builtin_multianewarray,
3773 (constant_classref *) iptr->target, 0);
3775 if (opt_showdisassemble) {
3776 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3782 a = (ptrint) iptr->val.a;
3785 /* a0 = dimension count */
3787 M_MOV_IMM(iptr->op1, rd->argintregs[0]);
3789 /* a1 = arrayvftbl */
3791 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3793 /* a2 = pointer to dimensions = stack pointer */
3795 M_MOV(REG_SP, rd->argintregs[2]);
3797 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3800 /* check for exception before result assignment */
3804 codegen_add_fillinstacktrace_ref(cd, cd->mcodeptr);
3806 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3807 M_INTMOVE(REG_RESULT, s1);
3808 store_reg_to_var_int(iptr->dst, s1);
3812 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3816 } /* for instruction */
3818 /* copy values to interface registers */
3820 src = bptr->outstack;
3821 len = bptr->outdepth;
3823 #if defined(ENABLE_LSRA)
3828 if ((src->varkind != STACKVAR)) {
3830 if (IS_FLT_DBL_TYPE(s2)) {
3831 var_to_reg_flt(s1, src, REG_FTMP1);
3832 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3833 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3836 x86_64_movq_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3840 var_to_reg_int(s1, src, REG_ITMP1);
3841 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3842 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3845 x86_64_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3852 /* At the end of a basic block we may have to append some nops,
3853 because the patcher stub calling code might be longer than the
3854 actual instruction. So codepatching does not change the
3855 following block unintentionally. */
3857 if (cd->mcodeptr < cd->lastmcodeptr) {
3858 while (cd->mcodeptr < cd->lastmcodeptr) {
3863 } /* if (bptr -> flags >= BBREACHED) */
3864 } /* for basic block */
3866 dseg_createlinenumbertable(cd);
3869 /* generate exception and patcher stubs */
3878 savedmcodeptr = NULL;
3880 /* generate exception stubs */
3882 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
3883 gen_resolvebranch(cd->mcodebase + eref->branchpos,
3885 cd->mcodeptr - cd->mcodebase);
3889 /* Check if the exception is an
3890 ArrayIndexOutOfBoundsException. If so, move index register
3893 if (eref->reg != -1)
3894 M_MOV(eref->reg, rd->argintregs[4]);
3896 /* calcuate exception address */
3898 M_MOV_IMM(0, rd->argintregs[3]);
3899 dseg_adddata(cd, cd->mcodeptr);
3900 M_AADD_IMM32(eref->branchpos - 6, rd->argintregs[3]);
3902 /* move function to call into REG_ITMP3 */
3904 M_MOV_IMM(eref->function, REG_ITMP3);
3906 if (savedmcodeptr != NULL) {
3907 M_JMP_IMM(savedmcodeptr - cd->mcodeptr - 5);
3910 savedmcodeptr = cd->mcodeptr;
3912 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[0]);
3913 M_MOV(REG_SP, rd->argintregs[1]);
3914 M_ALD(rd->argintregs[2], REG_SP, stackframesize * 8);
3916 M_ASUB_IMM(2 * 8, REG_SP);
3917 M_AST(rd->argintregs[3], REG_SP, 0 * 8); /* store XPC */
3921 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3922 M_AADD_IMM(2 * 8, REG_SP);
3924 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
3930 /* generate code patching stub call code */
3932 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3933 /* check size of code segment */
3937 /* Get machine code which is patched back in later. A
3938 `call rel32' is 5 bytes long (but read 8 bytes). */
3940 savedmcodeptr = cd->mcodebase + pref->branchpos;
3941 mcode = *((ptrint *) savedmcodeptr);
3943 /* patch in `call rel32' to call the following code */
3945 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
3946 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
3948 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
3950 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3952 /* move pointer to java_objectheader onto stack */
3954 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3955 /* create a virtual java_objectheader */
3957 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3958 a = dseg_addaddress(cd, NULL); /* vftbl */
3960 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + a, REG_ITMP3);
3966 /* move machine code bytes and classinfo pointer into registers */
3968 M_MOV_IMM(mcode, REG_ITMP3);
3970 M_MOV_IMM(pref->ref, REG_ITMP3);
3972 M_MOV_IMM(pref->disp, REG_ITMP3);
3975 M_MOV_IMM(pref->patcher, REG_ITMP3);
3978 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
3983 /* generate replacement-out stubs */
3988 replacementpoint = jd->code->rplpoints;
3990 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
3991 /* check code segment size */
3995 /* note start of stub code */
3997 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
3999 /* make machine code for patching */
4001 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
4002 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
4004 /* push address of `rplpoint` struct */
4006 M_MOV_IMM(replacementpoint, REG_ITMP3);
4009 /* jump to replacement function */
4011 M_MOV_IMM(asm_replacement_out, REG_ITMP3);
4016 codegen_finish(jd, (s4) (cd->mcodeptr - cd->mcodebase));
4018 /* everything's ok */
4024 /* createcompilerstub **********************************************************
4026 Creates a stub routine which calls the compiler.
4028 *******************************************************************************/
4030 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
4031 #define COMPILERSTUB_CODESIZE 7 + 7 + 3
4033 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
4036 u1 *createcompilerstub(methodinfo *m)
4038 u1 *s; /* memory to hold the stub */
4043 s = CNEW(u1, COMPILERSTUB_SIZE);
4045 /* set data pointer and code pointer */
4048 s = s + COMPILERSTUB_DATASIZE;
4050 /* mark start of dump memory area */
4052 dumpsize = dump_size();
4054 cd = DNEW(codegendata);
4057 /* Store the methodinfo* in the same place as in the methodheader
4058 for compiled methods. */
4060 d[0] = (ptrint) asm_call_jit_compiler;
4063 /* code for the stub */
4065 M_ALD(REG_ITMP1, RIP, -(7 * 1 + 1 * SIZEOF_VOID_P)); /* methodinfo */
4066 M_ALD(REG_ITMP3, RIP, -(7 * 2 + 2 * SIZEOF_VOID_P)); /* compiler pointer */
4069 #if defined(ENABLE_STATISTICS)
4071 count_cstub_len += COMPILERSTUB_SIZE;
4074 /* release dump area */
4076 dump_release(dumpsize);
4082 /* createnativestub ************************************************************
4084 Creates a stub routine which calls a native method.
4086 *******************************************************************************/
4088 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
4094 s4 stackframesize; /* size of stackframe if needed */
4096 s4 i, j; /* count variables */
4100 /* get required compiler data */
4106 /* initialize variables */
4109 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4111 /* calculate stack frame size */
4114 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4115 sizeof(localref_table) / SIZEOF_VOID_P +
4116 INT_ARG_CNT + FLT_ARG_CNT + 1 + /* + 1 for function address */
4119 if (!(stackframesize & 0x1)) /* keep stack 16-byte aligned */
4122 /* create method header */
4124 (void) dseg_addaddress(cd, m); /* MethodPointer */
4125 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4126 (void) dseg_adds4(cd, 0); /* IsSync */
4127 (void) dseg_adds4(cd, 0); /* IsLeaf */
4128 (void) dseg_adds4(cd, 0); /* IntSave */
4129 (void) dseg_adds4(cd, 0); /* FltSave */
4130 (void) dseg_addlinenumbertablesize(cd);
4131 (void) dseg_adds4(cd, 0); /* ExTableSize */
4133 /* initialize mcode variables */
4135 cd->mcodeptr = (u1 *) cd->mcodebase;
4136 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
4138 /* generate native method profiling code */
4141 /* count frequency */
4143 M_MOV_IMM(m, REG_ITMP2);
4144 M_IINC_MEMBASE(REG_ITMP2, OFFSET(methodinfo, frequency));
4147 /* generate stub code */
4149 M_ASUB_IMM(stackframesize * 8, REG_SP);
4151 #if !defined(NDEBUG)
4152 /* generate call trace */
4154 if (opt_verbosecall) {
4155 /* save integer and float argument registers */
4157 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4158 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4159 M_LST(rd->argintregs[j++], REG_SP, (1 + i) * 8);
4161 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4162 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4163 M_DST(rd->argfltregs[j++], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4165 /* show integer hex code for float arguments */
4167 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++) {
4168 /* if the paramtype is a float, we have to right shift all
4169 following integer registers */
4171 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4172 for (s1 = INT_ARG_CNT - 2; s1 >= i; s1--)
4173 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
4175 x86_64_movd_freg_reg(cd, rd->argfltregs[j], rd->argintregs[i]);
4180 M_MOV_IMM(m, REG_ITMP1);
4181 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4182 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
4185 /* restore integer and float argument registers */
4187 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4188 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4189 M_LLD(rd->argintregs[j++], REG_SP, (1 + i) * 8);
4191 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4192 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4193 M_DLD(rd->argfltregs[j++], REG_SP, (1 + INT_ARG_CNT + i) * 8);
4195 #endif /* !defined(NDEBUG) */
4197 /* get function address (this must happen before the stackframeinfo) */
4199 #if !defined(WITH_STATIC_CLASSPATH)
4201 codegen_addpatchref(cd, cd->mcodeptr, PATCHER_resolve_native, m, 0);
4203 if (opt_showdisassemble) {
4204 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4209 M_MOV_IMM(f, REG_ITMP3);
4212 /* save integer and float argument registers */
4214 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4215 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4216 M_LST(rd->argintregs[j++], REG_SP, i * 8);
4218 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4219 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4220 M_DST(rd->argfltregs[j++], REG_SP, (INT_ARG_CNT + i) * 8);
4222 M_AST(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4224 /* create dynamic stack info */
4226 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4227 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[1]);
4228 M_ALEA(REG_SP, stackframesize * 8 + SIZEOF_VOID_P, rd->argintregs[2]);
4229 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8);
4230 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
4233 /* restore integer and float argument registers */
4235 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++)
4236 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4237 M_LLD(rd->argintregs[j++], REG_SP, i * 8);
4239 for (i = 0, j = 0; i < md->paramcount && j < FLT_ARG_CNT; i++)
4240 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type))
4241 M_DLD(rd->argfltregs[j++], REG_SP, (INT_ARG_CNT + i) * 8);
4243 M_ALD(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4246 /* copy or spill arguments to new locations */
4248 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4249 t = md->paramtypes[i].type;
4251 if (IS_INT_LNG_TYPE(t)) {
4252 if (!md->params[i].inmemory) {
4253 s1 = rd->argintregs[md->params[i].regoff];
4255 if (!nmd->params[j].inmemory) {
4256 s2 = rd->argintregs[nmd->params[j].regoff];
4260 s2 = nmd->params[j].regoff;
4261 M_LST(s1, REG_SP, s2 * 8);
4265 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4266 s2 = nmd->params[j].regoff;
4267 M_LLD(REG_ITMP1, REG_SP, s1 * 8);
4268 M_LST(REG_ITMP1, REG_SP, s2 * 8);
4272 /* We only copy spilled float arguments, as the float argument */
4273 /* registers keep unchanged. */
4275 if (md->params[i].inmemory) {
4276 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4277 s2 = nmd->params[j].regoff;
4278 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4279 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4284 /* put class into second argument register */
4286 if (m->flags & ACC_STATIC)
4287 M_MOV_IMM(m->class, rd->argintregs[1]);
4289 /* put env into first argument register */
4291 M_MOV_IMM(_Jv_env, rd->argintregs[0]);
4293 /* do the native function call */
4297 /* save return value */
4299 if (md->returntype.type != TYPE_VOID) {
4300 if (IS_INT_LNG_TYPE(md->returntype.type))
4301 M_LST(REG_RESULT, REG_SP, 0 * 8);
4303 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4306 /* remove native stackframe info */
4308 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4309 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
4312 #if !defined(NDEBUG)
4313 /* generate call trace */
4315 if (opt_verbosecall) {
4316 /* just restore the value we need, don't care about the other */
4318 if (md->returntype.type != TYPE_VOID) {
4319 if (IS_INT_LNG_TYPE(md->returntype.type))
4320 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4322 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4325 M_MOV_IMM(m, rd->argintregs[0]);
4326 M_MOV(REG_RESULT, rd->argintregs[1]);
4327 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4328 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4330 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
4333 #endif /* !defined(NDEBUG) */
4335 /* check for exception */
4337 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4338 M_MOV_IMM(builtin_get_exceptionptrptr, REG_ITMP3);
4341 M_MOV_IMM(&_no_threads_exceptionptr, REG_RESULT);
4343 M_ALD(REG_ITMP2, REG_RESULT, 0);
4345 /* restore return value */
4347 if (md->returntype.type != TYPE_VOID) {
4348 if (IS_INT_LNG_TYPE(md->returntype.type))
4349 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4351 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4354 /* test for exception */
4359 /* remove stackframe */
4361 M_AADD_IMM(stackframesize * 8, REG_SP);
4365 /* handle exception */
4367 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4368 M_LST(REG_ITMP2, REG_SP, 0 * 8);
4369 M_MOV_IMM(builtin_get_exceptionptrptr, REG_ITMP3);
4371 M_AST_IMM32(0, REG_RESULT, 0); /* clear exception pointer */
4372 M_LLD(REG_ITMP1_XPTR, REG_SP, 0 * 8);
4374 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
4375 M_MOV_IMM(&_no_threads_exceptionptr, REG_ITMP3);
4376 M_AST_IMM32(0, REG_ITMP3, 0); /* clear exception pointer */
4379 /* remove stackframe */
4381 M_AADD_IMM(stackframesize * 8, REG_SP);
4383 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
4384 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
4386 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4390 /* process patcher calls **************************************************/
4397 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4401 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4402 /* Get machine code which is patched back in later. A
4403 `call rel32' is 5 bytes long (but read 8 bytes). */
4405 savedmcodeptr = cd->mcodebase + pref->branchpos;
4406 mcode = *((ptrint *) savedmcodeptr);
4408 /* patch in `call rel32' to call the following code */
4410 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4411 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
4413 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
4415 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4417 /* move pointer to java_objectheader onto stack */
4419 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4420 /* create a virtual java_objectheader */
4422 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4423 disp = dseg_addaddress(cd, NULL); /* vftbl */
4425 x86_64_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP3);
4431 /* move machine code bytes and classinfo pointer into registers */
4433 M_MOV_IMM(mcode, REG_ITMP3);
4435 M_MOV_IMM(pref->ref, REG_ITMP3);
4437 M_MOV_IMM(pref->disp, REG_ITMP3);
4440 M_MOV_IMM(pref->patcher, REG_ITMP3);
4443 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
4448 codegen_finish(jd, (s4) (cd->mcodeptr - cd->mcodebase));
4450 return jd->code->entrypoint;
4455 * These are local overrides for various environment variables in Emacs.
4456 * Please do not remove this and leave it at the end of the file, where
4457 * Emacs will automagically detect them.
4458 * ---------------------------------------------------------------------
4461 * indent-tabs-mode: t
4465 * vim:noexpandtab:sw=4:ts=4: