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 5123 2006-07-12 21:45:34Z twisti $
48 #include "vm/jit/x86_64/arch.h"
49 #include "vm/jit/x86_64/codegen.h"
50 #include "vm/jit/x86_64/md-emit.h"
52 #include "mm/memory.h"
53 #include "native/jni.h"
54 #include "native/native.h"
56 #if defined(ENABLE_THREADS)
57 # include "threads/native/lock.h"
60 #include "vm/builtin.h"
61 #include "vm/exceptions.h"
62 #include "vm/global.h"
63 #include "vm/loader.h"
64 #include "vm/options.h"
65 #include "vm/statistics.h"
66 #include "vm/stringlocal.h"
68 #include "vm/jit/asmpart.h"
69 #include "vm/jit/codegen-common.h"
70 #include "vm/jit/dseg.h"
71 #include "vm/jit/emit.h"
72 #include "vm/jit/jit.h"
73 #include "vm/jit/methodheader.h"
74 #include "vm/jit/parse.h"
75 #include "vm/jit/patcher.h"
76 #include "vm/jit/reg.h"
77 #include "vm/jit/replace.h"
79 #if defined(ENABLE_LSRA)
80 # include "vm/jit/allocator/lsra.h"
84 /* codegen *********************************************************************
86 Generates machine code.
88 *******************************************************************************/
90 bool codegen(jitdata *jd)
96 s4 len, s1, s2, s3, d, disp;
105 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
106 builtintable_entry *bte;
108 rplpoint *replacementpoint;
110 /* get required compiler data */
117 /* prevent compiler warnings */
129 /* space to save used callee saved registers */
131 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
132 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
134 stackframesize = rd->memuse + savedregs_num;
136 #if defined(ENABLE_THREADS)
137 /* space to save argument of monitor_enter */
139 if (checksync && (m->flags & ACC_SYNCHRONIZED))
143 /* Keep stack of non-leaf functions 16-byte aligned for calls into
144 native code e.g. libc or jni (alignment problems with
147 if (!jd->isleafmethod || opt_verbosecall)
148 stackframesize |= 0x1;
150 /* create method header */
152 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
153 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
155 #if defined(ENABLE_THREADS)
156 /* IsSync contains the offset relative to the stack pointer for the
157 argument of monitor_exit used in the exception handler. Since the
158 offset could be zero and give a wrong meaning of the flag it is
162 if (checksync && (m->flags & ACC_SYNCHRONIZED))
163 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
166 (void) dseg_adds4(cd, 0); /* IsSync */
168 (void) dseg_adds4(cd, jd->isleafmethod); /* IsLeaf */
169 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
170 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
172 (void) dseg_addlinenumbertablesize(cd);
174 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
176 /* create exception table */
178 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
179 dseg_addtarget(cd, ex->start);
180 dseg_addtarget(cd, ex->end);
181 dseg_addtarget(cd, ex->handler);
182 (void) dseg_addaddress(cd, ex->catchtype.cls);
185 /* generate method profiling code */
187 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
188 /* count frequency */
190 M_MOV_IMM(code, REG_ITMP3);
191 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
196 /* create stack frame (if necessary) */
199 M_ASUB_IMM(stackframesize * 8, REG_SP);
201 /* save used callee saved registers */
204 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
205 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
207 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
208 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
211 /* take arguments out of register or stack frame */
215 for (p = 0, l = 0; p < md->paramcount; p++) {
216 t = md->paramtypes[p].type;
217 var = &(rd->locals[l][t]);
219 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
223 s1 = md->params[p].regoff;
224 if (IS_INT_LNG_TYPE(t)) { /* integer args */
225 s2 = rd->argintregs[s1];
226 if (!md->params[p].inmemory) { /* register arguments */
227 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
228 M_INTMOVE(s2, var->regoff);
230 } else { /* reg arg -> spilled */
231 M_LST(s2, REG_SP, var->regoff * 8);
234 } else { /* stack arguments */
235 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
236 /* + 8 for return address */
237 M_LLD(var->regoff, REG_SP, (stackframesize + s1) * 8 + 8);
239 } else { /* stack arg -> spilled */
240 var->regoff = stackframesize + s1 + 1;
244 } else { /* floating args */
245 if (!md->params[p].inmemory) { /* register arguments */
246 s2 = rd->argfltregs[s1];
247 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
248 M_FLTMOVE(s2, var->regoff);
250 } else { /* reg arg -> spilled */
251 M_DST(s2, REG_SP, var->regoff * 8);
254 } else { /* stack arguments */
255 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
256 M_DLD(var->regoff, REG_SP, (stackframesize + s1) * 8 + 8);
259 var->regoff = stackframesize + s1 + 1;
265 /* save monitorenter argument */
267 #if defined(ENABLE_THREADS)
268 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
269 /* stack offset for monitor argument */
273 if (opt_verbosecall) {
274 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
276 for (p = 0; p < INT_ARG_CNT; p++)
277 M_LST(rd->argintregs[p], REG_SP, p * 8);
279 for (p = 0; p < FLT_ARG_CNT; p++)
280 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
282 s1 += INT_ARG_CNT + FLT_ARG_CNT;
285 /* decide which monitor enter function to call */
287 if (m->flags & ACC_STATIC) {
288 M_MOV_IMM(&m->class->object.header, rd->argintregs[0]);
291 M_TEST(rd->argintregs[0]);
293 codegen_add_nullpointerexception_ref(cd);
296 M_AST(rd->argintregs[0], REG_SP, s1 * 8);
297 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
300 if (opt_verbosecall) {
301 for (p = 0; p < INT_ARG_CNT; p++)
302 M_LLD(rd->argintregs[p], REG_SP, p * 8);
304 for (p = 0; p < FLT_ARG_CNT; p++)
305 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
307 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
313 /* Copy argument registers to stack and call trace function with
314 pointer to arguments on stack. */
316 if (opt_verbosecall) {
317 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
319 /* save integer argument registers */
321 for (p = 0; p < INT_ARG_CNT; p++)
322 M_LST(rd->argintregs[p], REG_SP, (1 + p) * 8);
324 /* save float argument registers */
326 for (p = 0; p < FLT_ARG_CNT; p++)
327 M_DST(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
329 /* save temporary registers for leaf methods */
331 if (jd->isleafmethod) {
332 for (p = 0; p < INT_TMP_CNT; p++)
333 M_LST(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
335 for (p = 0; p < FLT_TMP_CNT; p++)
336 M_DST(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
339 /* show integer hex code for float arguments */
341 for (p = 0, l = 0; p < md->paramcount && p < INT_ARG_CNT; p++) {
342 /* If the paramtype is a float, we have to right shift all
343 following integer registers. */
345 if (IS_FLT_DBL_TYPE(md->paramtypes[p].type)) {
346 for (s1 = INT_ARG_CNT - 2; s1 >= p; s1--)
347 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
349 emit_movd_freg_reg(cd, rd->argfltregs[l], rd->argintregs[p]);
354 M_MOV_IMM(m, REG_ITMP2);
355 M_AST(REG_ITMP2, REG_SP, 0 * 8);
356 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
359 /* restore integer argument registers */
361 for (p = 0; p < INT_ARG_CNT; p++)
362 M_LLD(rd->argintregs[p], REG_SP, (1 + p) * 8);
364 /* restore float argument registers */
366 for (p = 0; p < FLT_ARG_CNT; p++)
367 M_DLD(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
369 /* restore temporary registers for leaf methods */
371 if (jd->isleafmethod) {
372 for (p = 0; p < INT_TMP_CNT; p++)
373 M_LLD(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
375 for (p = 0; p < FLT_TMP_CNT; p++)
376 M_DLD(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
379 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
381 #endif /* !defined(NDEBUG) */
385 /* end of header generation */
387 replacementpoint = jd->code->rplpoints;
389 /* walk through all basic blocks */
391 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
393 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
395 if (bptr->flags >= BBREACHED) {
397 /* branch resolving */
400 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
401 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
406 /* handle replacement points */
408 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
409 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
413 assert(cd->lastmcodeptr <= cd->mcodeptr);
414 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
417 /* copy interface registers to their destination */
424 /* generate basicblock profiling code */
426 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
427 /* count frequency */
429 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
430 M_IINC_MEMBASE(REG_ITMP3, bptr->debug_nr * 4);
432 /* if this is an exception handler, start profiling again */
434 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))
451 emit_store(jd, NULL, 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 emit_store(jd, NULL, 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 emit_store(jd, NULL, 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 emit_store(jd, NULL, 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 emit_store(jd, NULL, 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 emit_store(jd, NULL, 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);
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 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
541 codegen_add_nullpointerexception_ref(cd);
544 /* constant operations ************************************************/
546 case ICMD_ICONST: /* ... ==> ..., constant */
547 /* op1 = 0, val.i = constant */
549 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
550 ICONST(d, iptr->val.i);
551 emit_store(jd, iptr, iptr->dst, d);
554 case ICMD_LCONST: /* ... ==> ..., constant */
555 /* op1 = 0, val.l = constant */
557 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
558 LCONST(d, iptr->val.l);
559 emit_store(jd, iptr, iptr->dst, d);
562 case ICMD_FCONST: /* ... ==> ..., constant */
563 /* op1 = 0, val.f = constant */
565 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
566 disp = dseg_addfloat(cd, iptr->val.f);
567 emit_movdl_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + ((d > 7) ? 9 : 8)) - (s8) cd->mcodebase) + disp, d);
568 emit_store(jd, iptr, iptr->dst, d);
571 case ICMD_DCONST: /* ... ==> ..., constant */
572 /* op1 = 0, val.d = constant */
574 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
575 disp = dseg_adddouble(cd, iptr->val.d);
576 emit_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, d);
577 emit_store(jd, iptr, iptr->dst, d);
580 case ICMD_ACONST: /* ... ==> ..., constant */
581 /* op1 = 0, val.a = constant */
583 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
585 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
586 /* PROFILE_CYCLE_STOP; */
588 codegen_addpatchref(cd, PATCHER_aconst,
589 ICMD_ACONST_UNRESOLVED_CLASSREF(iptr), 0);
591 if (opt_showdisassemble) {
592 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
595 /* PROFILE_CYCLE_START; */
600 if (iptr->val.a == 0)
603 M_MOV_IMM(iptr->val.a, d);
605 emit_store(jd, iptr, iptr->dst, d);
609 /* load/store operations **********************************************/
611 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
612 /* op1 = local variable */
614 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
615 if ((iptr->dst->varkind == LOCALVAR) &&
616 (iptr->dst->varnum == iptr->op1))
618 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
619 if (var->flags & INMEMORY)
620 M_ILD(d, REG_SP, var->regoff * 8);
622 M_INTMOVE(var->regoff, d);
623 emit_store(jd, iptr, iptr->dst, d);
626 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
627 case ICMD_ALOAD: /* op1 = local variable */
629 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
630 if ((iptr->dst->varkind == LOCALVAR) &&
631 (iptr->dst->varnum == iptr->op1))
633 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
634 if (var->flags & INMEMORY)
635 M_LLD(d, REG_SP, var->regoff * 8);
637 M_INTMOVE(var->regoff, d);
638 emit_store(jd, iptr, iptr->dst, d);
641 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
642 /* op1 = local variable */
644 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
645 if ((iptr->dst->varkind == LOCALVAR) &&
646 (iptr->dst->varnum == iptr->op1))
648 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
649 if (var->flags & INMEMORY)
650 M_FLD(d, REG_SP, var->regoff * 8);
652 M_FLTMOVE(var->regoff, d);
653 emit_store(jd, iptr, iptr->dst, d);
656 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
657 /* op1 = local variable */
659 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
660 if ((iptr->dst->varkind == LOCALVAR) &&
661 (iptr->dst->varnum == iptr->op1))
663 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
664 if (var->flags & INMEMORY)
665 M_DLD(d, REG_SP, var->regoff * 8);
667 M_FLTMOVE(var->regoff, d);
668 emit_store(jd, iptr, iptr->dst, d);
671 case ICMD_ISTORE: /* ..., value ==> ... */
672 /* op1 = local variable */
674 if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
676 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
677 if (var->flags & INMEMORY) {
678 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
679 M_IST(s1, REG_SP, var->regoff * 8);
681 s1 = emit_load_s1(jd, iptr, src, var->regoff);
682 M_INTMOVE(s1, var->regoff);
686 case ICMD_LSTORE: /* ..., value ==> ... */
687 case ICMD_ASTORE: /* op1 = local variable */
689 if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
691 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
692 if (var->flags & INMEMORY) {
693 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
694 M_LST(s1, REG_SP, var->regoff * 8);
696 s1 = emit_load_s1(jd, iptr, src, var->regoff);
697 M_INTMOVE(s1, var->regoff);
701 case ICMD_FSTORE: /* ..., value ==> ... */
702 /* op1 = local variable */
704 if ((src->varkind == LOCALVAR) &&
705 (src->varnum == iptr->op1)) {
708 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
709 if (var->flags & INMEMORY) {
710 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
711 M_FST(s1, REG_SP, var->regoff * 8);
713 s1 = emit_load_s1(jd, iptr, src, var->regoff);
714 M_FLTMOVE(s1, var->regoff);
718 case ICMD_DSTORE: /* ..., value ==> ... */
719 /* op1 = local variable */
721 if ((src->varkind == LOCALVAR) &&
722 (src->varnum == iptr->op1)) {
725 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
726 if (var->flags & INMEMORY) {
727 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
728 M_DST(s1, REG_SP, var->regoff * 8);
730 s1 = emit_load_s1(jd, iptr, src, var->regoff);
731 M_FLTMOVE(s1, var->regoff);
736 /* pop/dup/swap operations ********************************************/
738 /* attention: double and longs are only one entry in CACAO ICMDs */
740 case ICMD_POP: /* ..., value ==> ... */
741 case ICMD_POP2: /* ..., value, value ==> ... */
744 case ICMD_DUP: /* ..., a ==> ..., a, a */
745 M_COPY(src, iptr->dst);
748 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
750 M_COPY(src, iptr->dst);
751 M_COPY(src->prev, iptr->dst->prev);
752 M_COPY(iptr->dst, iptr->dst->prev->prev);
755 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
757 M_COPY(src, iptr->dst);
758 M_COPY(src->prev, iptr->dst->prev);
759 M_COPY(src->prev->prev, iptr->dst->prev->prev);
760 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
763 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
765 M_COPY(src, iptr->dst);
766 M_COPY(src->prev, iptr->dst->prev);
769 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
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(iptr->dst, iptr->dst->prev->prev->prev);
775 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
778 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
780 M_COPY(src, iptr->dst);
781 M_COPY(src->prev, iptr->dst->prev);
782 M_COPY(src->prev->prev, iptr->dst->prev->prev);
783 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
784 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
785 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
788 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
790 M_COPY(src, iptr->dst->prev);
791 M_COPY(src->prev, iptr->dst);
795 /* integer operations *************************************************/
797 case ICMD_INEG: /* ..., value ==> ..., - value */
799 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
800 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
803 emit_store(jd, iptr, iptr->dst, d);
806 case ICMD_LNEG: /* ..., value ==> ..., - value */
808 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
809 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
812 emit_store(jd, iptr, iptr->dst, d);
815 case ICMD_I2L: /* ..., value ==> ..., value */
817 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
818 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
820 emit_store(jd, iptr, iptr->dst, d);
823 case ICMD_L2I: /* ..., value ==> ..., value */
825 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
826 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
828 emit_store(jd, iptr, iptr->dst, d);
831 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
833 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
834 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
836 emit_store(jd, iptr, iptr->dst, d);
839 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
841 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
842 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
844 emit_store(jd, iptr, iptr->dst, d);
847 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
849 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
850 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
852 emit_store(jd, iptr, iptr->dst, d);
856 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
858 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
859 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
860 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
867 emit_store(jd, iptr, iptr->dst, d);
870 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
871 /* val.i = constant */
873 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
874 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
876 M_IADD_IMM(iptr->val.i, d);
877 emit_store(jd, iptr, iptr->dst, d);
880 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
882 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
883 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
884 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
891 emit_store(jd, iptr, iptr->dst, d);
894 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
895 /* val.l = constant */
897 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
898 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
900 if (IS_IMM32(iptr->val.l))
901 M_LADD_IMM(iptr->val.l, d);
903 M_MOV_IMM(iptr->val.l, REG_ITMP2);
904 M_LADD(REG_ITMP2, d);
906 emit_store(jd, iptr, iptr->dst, d);
909 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
911 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
912 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
913 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
915 M_INTMOVE(s1, REG_ITMP1);
916 M_ISUB(s2, REG_ITMP1);
917 M_INTMOVE(REG_ITMP1, d);
922 emit_store(jd, iptr, iptr->dst, d);
925 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
926 /* val.i = constant */
928 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
929 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
931 M_ISUB_IMM(iptr->val.i, d);
932 emit_store(jd, iptr, iptr->dst, d);
935 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
937 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
938 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
939 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
941 M_INTMOVE(s1, REG_ITMP1);
942 M_LSUB(s2, REG_ITMP1);
943 M_INTMOVE(REG_ITMP1, d);
948 emit_store(jd, iptr, iptr->dst, d);
951 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
952 /* val.l = constant */
954 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
955 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
957 if (IS_IMM32(iptr->val.l))
958 M_LSUB_IMM(iptr->val.l, d);
960 M_MOV_IMM(iptr->val.l, REG_ITMP2);
961 M_LSUB(REG_ITMP2, d);
963 emit_store(jd, iptr, iptr->dst, d);
966 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
968 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
969 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
970 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
977 emit_store(jd, iptr, iptr->dst, d);
980 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
981 /* val.i = constant */
983 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
984 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
985 if (iptr->val.i == 2) {
989 M_IMUL_IMM(s1, iptr->val.i, d);
990 emit_store(jd, iptr, iptr->dst, d);
993 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
995 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
996 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
997 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1004 emit_store(jd, iptr, iptr->dst, d);
1007 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1008 /* val.l = constant */
1010 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1011 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1012 if (IS_IMM32(iptr->val.l))
1013 M_LMUL_IMM(s1, iptr->val.l, d);
1015 M_MOV_IMM(iptr->val.l, REG_ITMP2);
1017 M_LMUL(REG_ITMP2, d);
1019 emit_store(jd, iptr, iptr->dst, d);
1022 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1024 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1025 if (src->prev->flags & INMEMORY)
1026 M_ILD(RAX, REG_SP, src->prev->regoff * 8);
1028 M_INTMOVE(src->prev->regoff, RAX);
1030 if (src->flags & INMEMORY)
1031 M_ILD(REG_ITMP3, REG_SP, src->regoff * 8);
1033 M_INTMOVE(src->regoff, REG_ITMP3);
1038 codegen_add_arithmeticexception_ref(cd);
1041 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1042 emit_jcc(cd, CC_NE, 4 + 6);
1043 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
1044 emit_jcc(cd, CC_E, 3 + 1 + 3); /* 6 bytes */
1046 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1048 emit_idivl_reg(cd, REG_ITMP3);
1050 if (iptr->dst->flags & INMEMORY) {
1051 emit_mov_reg_membase(cd, RAX, REG_SP, iptr->dst->regoff * 8);
1052 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1055 M_INTMOVE(RAX, iptr->dst->regoff);
1057 if (iptr->dst->regoff != RDX) {
1058 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1063 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1065 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1066 if (src->prev->flags & INMEMORY)
1067 M_ILD(RAX, REG_SP, src->prev->regoff * 8);
1069 M_INTMOVE(src->prev->regoff, RAX);
1071 if (src->flags & INMEMORY)
1072 M_ILD(REG_ITMP3, REG_SP, src->regoff * 8);
1074 M_INTMOVE(src->regoff, REG_ITMP3);
1079 codegen_add_arithmeticexception_ref(cd);
1082 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1084 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1085 emit_jcc(cd, CC_NE, 2 + 4 + 6);
1088 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
1089 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
1090 emit_jcc(cd, CC_E, 1 + 3); /* 6 bytes */
1093 emit_idivl_reg(cd, REG_ITMP3);
1095 if (iptr->dst->flags & INMEMORY) {
1096 emit_mov_reg_membase(cd, RDX, REG_SP, iptr->dst->regoff * 8);
1097 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1100 M_INTMOVE(RDX, iptr->dst->regoff);
1102 if (iptr->dst->regoff != RDX) {
1103 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1108 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1109 /* val.i = constant */
1111 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1112 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1113 M_INTMOVE(s1, REG_ITMP1);
1114 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1115 emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1116 emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
1117 emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->val.i, REG_ITMP1);
1118 emit_mov_reg_reg(cd, REG_ITMP1, d);
1119 emit_store(jd, iptr, iptr->dst, d);
1122 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1123 /* val.i = constant */
1125 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1126 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1127 M_INTMOVE(s1, REG_ITMP1);
1128 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1129 emit_leal_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1130 emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1131 emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->val.i), REG_ITMP2);
1132 emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1133 emit_mov_reg_reg(cd, REG_ITMP1, d);
1134 emit_store(jd, iptr, iptr->dst, d);
1138 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1140 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1142 if (src->prev->flags & INMEMORY)
1143 M_LLD(RAX, REG_SP, src->prev->regoff * 8);
1145 M_INTMOVE(src->prev->regoff, RAX);
1147 if (src->flags & INMEMORY)
1148 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1150 M_INTMOVE(src->regoff, REG_ITMP3);
1155 codegen_add_arithmeticexception_ref(cd);
1158 /* check as described in jvm spec */
1159 disp = dseg_adds8(cd, 0x8000000000000000LL);
1160 M_LCMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, RAX);
1162 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1163 M_BEQ(3 + 2 + 3); /* 6 bytes */
1165 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1167 emit_idiv_reg(cd, REG_ITMP3);
1169 if (iptr->dst->flags & INMEMORY) {
1170 M_LST(RAX, REG_SP, iptr->dst->regoff * 8);
1171 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1174 M_INTMOVE(RAX, iptr->dst->regoff);
1176 if (iptr->dst->regoff != RDX) {
1177 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1182 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1184 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1185 if (src->prev->flags & INMEMORY)
1186 M_LLD(REG_ITMP1, REG_SP, src->prev->regoff * 8);
1188 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1190 if (src->flags & INMEMORY)
1191 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1193 M_INTMOVE(src->regoff, REG_ITMP3);
1198 codegen_add_arithmeticexception_ref(cd);
1201 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1203 /* check as described in jvm spec */
1204 disp = dseg_adds8(cd, 0x8000000000000000LL);
1205 M_LCMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP1);
1209 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
1211 M_LXOR(RDX, RDX); /* 3 bytes */
1212 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1213 M_BEQ(2 + 3); /* 6 bytes */
1216 emit_idiv_reg(cd, REG_ITMP3);
1218 if (iptr->dst->flags & INMEMORY) {
1219 M_LST(RDX, REG_SP, iptr->dst->regoff * 8);
1220 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1223 M_INTMOVE(RDX, iptr->dst->regoff);
1225 if (iptr->dst->regoff != RDX) {
1226 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1231 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1232 /* val.i = constant */
1234 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1235 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1236 M_INTMOVE(s1, REG_ITMP1);
1237 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1238 emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1239 emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
1240 emit_shift_imm_reg(cd, SHIFT_SAR, iptr->val.i, REG_ITMP1);
1241 emit_mov_reg_reg(cd, REG_ITMP1, d);
1242 emit_store(jd, iptr, iptr->dst, d);
1245 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1246 /* val.l = constant */
1248 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1249 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1250 M_INTMOVE(s1, REG_ITMP1);
1251 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1252 emit_lea_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1253 emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1254 emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->val.i), REG_ITMP2);
1255 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1256 emit_mov_reg_reg(cd, REG_ITMP1, d);
1257 emit_store(jd, iptr, iptr->dst, d);
1260 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1262 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1263 emit_ishift(cd, SHIFT_SHL, src, iptr);
1266 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1267 /* val.i = constant */
1269 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1270 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1272 M_ISLL_IMM(iptr->val.i, d);
1273 emit_store(jd, iptr, iptr->dst, d);
1276 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1278 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1279 emit_ishift(cd, SHIFT_SAR, src, iptr);
1282 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1283 /* val.i = constant */
1285 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1286 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1288 M_ISRA_IMM(iptr->val.i, d);
1289 emit_store(jd, iptr, iptr->dst, d);
1292 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1294 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1295 emit_ishift(cd, SHIFT_SHR, src, iptr);
1298 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1299 /* val.i = constant */
1301 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1302 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1304 M_ISRL_IMM(iptr->val.i, d);
1305 emit_store(jd, iptr, iptr->dst, d);
1308 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1310 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1311 emit_lshift(cd, SHIFT_SHL, src, iptr);
1314 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1315 /* val.i = constant */
1317 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1318 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1320 M_LSLL_IMM(iptr->val.i, d);
1321 emit_store(jd, iptr, iptr->dst, d);
1324 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1326 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1327 emit_lshift(cd, SHIFT_SAR, src, iptr);
1330 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1331 /* val.i = constant */
1333 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1334 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1336 M_LSRA_IMM(iptr->val.i, d);
1337 emit_store(jd, iptr, iptr->dst, d);
1340 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1342 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1343 emit_lshift(cd, SHIFT_SHR, src, iptr);
1346 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1347 /* val.l = constant */
1349 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1350 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1352 M_LSRL_IMM(iptr->val.i, d);
1353 emit_store(jd, iptr, iptr->dst, d);
1356 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1358 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1359 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1360 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1367 emit_store(jd, iptr, iptr->dst, d);
1370 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1371 /* val.i = constant */
1373 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1374 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1376 M_IAND_IMM(iptr->val.i, d);
1377 emit_store(jd, iptr, iptr->dst, d);
1380 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1382 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1383 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1384 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1391 emit_store(jd, iptr, iptr->dst, d);
1394 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1395 /* val.l = constant */
1397 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1398 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1400 if (IS_IMM32(iptr->val.l))
1401 M_LAND_IMM(iptr->val.l, d);
1403 M_MOV_IMM(iptr->val.l, REG_ITMP2);
1404 M_LAND(REG_ITMP2, d);
1406 emit_store(jd, iptr, iptr->dst, d);
1409 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1411 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1412 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1413 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1420 emit_store(jd, iptr, iptr->dst, d);
1423 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1424 /* val.i = constant */
1426 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1427 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1429 M_IOR_IMM(iptr->val.i, d);
1430 emit_store(jd, iptr, iptr->dst, d);
1433 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1435 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1436 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1437 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1444 emit_store(jd, iptr, iptr->dst, d);
1447 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1448 /* val.l = constant */
1450 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1451 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1453 if (IS_IMM32(iptr->val.l))
1454 M_LOR_IMM(iptr->val.l, d);
1456 M_MOV_IMM(iptr->val.l, REG_ITMP2);
1457 M_LOR(REG_ITMP2, d);
1459 emit_store(jd, iptr, iptr->dst, d);
1462 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1464 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1465 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1466 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1473 emit_store(jd, iptr, iptr->dst, d);
1476 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1477 /* val.i = constant */
1479 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1480 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1482 M_IXOR_IMM(iptr->val.i, d);
1483 emit_store(jd, iptr, iptr->dst, d);
1486 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1488 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1489 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1490 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1497 emit_store(jd, iptr, iptr->dst, d);
1500 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1501 /* val.l = constant */
1503 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1504 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1506 if (IS_IMM32(iptr->val.l))
1507 M_LXOR_IMM(iptr->val.l, d);
1509 M_MOV_IMM(iptr->val.l, REG_ITMP2);
1510 M_LXOR(REG_ITMP2, d);
1512 emit_store(jd, iptr, iptr->dst, d);
1516 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1517 /* op1 = variable, val.i = constant */
1519 var = &(rd->locals[iptr->op1][TYPE_INT]);
1520 if (var->flags & INMEMORY) {
1522 M_ILD(s1, REG_SP, var->regoff * 8);
1526 /* Using inc and dec is not faster than add (tested with
1529 M_IADD_IMM(iptr->val.i, s1);
1531 if (var->flags & INMEMORY)
1532 M_IST(s1, REG_SP, var->regoff * 8);
1536 /* floating operations ************************************************/
1538 case ICMD_FNEG: /* ..., value ==> ..., - value */
1540 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1541 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1542 disp = dseg_adds4(cd, 0x80000000);
1544 emit_movss_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1545 emit_xorps_reg_reg(cd, REG_FTMP2, d);
1546 emit_store(jd, iptr, iptr->dst, d);
1549 case ICMD_DNEG: /* ..., value ==> ..., - value */
1551 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1552 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1553 disp = dseg_adds8(cd, 0x8000000000000000);
1555 emit_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1556 emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1557 emit_store(jd, iptr, iptr->dst, d);
1560 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1562 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1563 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1564 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1571 emit_store(jd, iptr, iptr->dst, d);
1574 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1576 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1577 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1578 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1585 emit_store(jd, iptr, iptr->dst, d);
1588 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1590 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1591 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1592 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1594 M_FLTMOVE(s2, REG_FTMP2);
1599 emit_store(jd, iptr, iptr->dst, d);
1602 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1604 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1605 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1606 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1608 M_FLTMOVE(s2, REG_FTMP2);
1613 emit_store(jd, iptr, iptr->dst, d);
1616 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1618 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1619 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1620 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1627 emit_store(jd, iptr, iptr->dst, d);
1630 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1632 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1633 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1634 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1641 emit_store(jd, iptr, iptr->dst, d);
1644 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1646 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1647 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1648 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1650 M_FLTMOVE(s2, REG_FTMP2);
1655 emit_store(jd, iptr, iptr->dst, d);
1658 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1660 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1661 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1662 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1664 M_FLTMOVE(s2, REG_FTMP2);
1669 emit_store(jd, iptr, iptr->dst, d);
1672 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1674 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1675 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1677 emit_store(jd, iptr, iptr->dst, d);
1680 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1682 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1683 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1685 emit_store(jd, iptr, iptr->dst, d);
1688 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1690 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1691 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1693 emit_store(jd, iptr, iptr->dst, d);
1696 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1698 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1699 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1701 emit_store(jd, iptr, iptr->dst, d);
1704 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1706 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1707 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1709 M_ICMP_IMM(0x80000000, d); /* corner cases */
1710 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1711 ((REG_RESULT == d) ? 0 : 3);
1713 M_FLTMOVE(s1, REG_FTMP1);
1714 M_MOV_IMM(asm_builtin_f2i, REG_ITMP2);
1716 M_INTMOVE(REG_RESULT, d);
1717 emit_store(jd, iptr, iptr->dst, d);
1720 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1722 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1723 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1725 M_ICMP_IMM(0x80000000, d); /* corner cases */
1726 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1727 ((REG_RESULT == d) ? 0 : 3);
1729 M_FLTMOVE(s1, REG_FTMP1);
1730 M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1732 M_INTMOVE(REG_RESULT, d);
1733 emit_store(jd, iptr, iptr->dst, d);
1736 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1738 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1739 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1741 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1742 M_LCMP(REG_ITMP2, d); /* corner cases */
1743 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1744 ((REG_RESULT == d) ? 0 : 3);
1746 M_FLTMOVE(s1, REG_FTMP1);
1747 M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1749 M_INTMOVE(REG_RESULT, d);
1750 emit_store(jd, iptr, iptr->dst, d);
1753 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1755 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1756 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1758 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1759 M_LCMP(REG_ITMP2, d); /* corner cases */
1760 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1761 ((REG_RESULT == d) ? 0 : 3);
1763 M_FLTMOVE(s1, REG_FTMP1);
1764 M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1766 M_INTMOVE(REG_RESULT, d);
1767 emit_store(jd, iptr, iptr->dst, d);
1770 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1772 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1773 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1775 emit_store(jd, iptr, iptr->dst, d);
1778 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1780 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1781 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1783 emit_store(jd, iptr, iptr->dst, d);
1786 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1787 /* == => 0, < => 1, > => -1 */
1789 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1790 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1791 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1793 M_MOV_IMM(1, REG_ITMP1);
1794 M_MOV_IMM(-1, REG_ITMP2);
1795 emit_ucomiss_reg_reg(cd, s1, s2);
1796 M_CMOVB(REG_ITMP1, d);
1797 M_CMOVA(REG_ITMP2, d);
1798 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1799 emit_store(jd, iptr, iptr->dst, d);
1802 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1803 /* == => 0, < => 1, > => -1 */
1805 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1806 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1807 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1809 M_MOV_IMM(1, REG_ITMP1);
1810 M_MOV_IMM(-1, REG_ITMP2);
1811 emit_ucomiss_reg_reg(cd, s1, s2);
1812 M_CMOVB(REG_ITMP1, d);
1813 M_CMOVA(REG_ITMP2, d);
1814 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1815 emit_store(jd, iptr, iptr->dst, d);
1818 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1819 /* == => 0, < => 1, > => -1 */
1821 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1822 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1823 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1825 M_MOV_IMM(1, REG_ITMP1);
1826 M_MOV_IMM(-1, REG_ITMP2);
1827 emit_ucomisd_reg_reg(cd, s1, s2);
1828 M_CMOVB(REG_ITMP1, d);
1829 M_CMOVA(REG_ITMP2, d);
1830 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1831 emit_store(jd, iptr, iptr->dst, d);
1834 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1835 /* == => 0, < => 1, > => -1 */
1837 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1838 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1839 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1841 M_MOV_IMM(1, REG_ITMP1);
1842 M_MOV_IMM(-1, REG_ITMP2);
1843 emit_ucomisd_reg_reg(cd, s1, s2);
1844 M_CMOVB(REG_ITMP1, d);
1845 M_CMOVA(REG_ITMP2, d);
1846 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1847 emit_store(jd, iptr, iptr->dst, d);
1851 /* memory operations **************************************************/
1853 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1855 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1856 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1857 gen_nullptr_check(s1);
1858 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1859 emit_store(jd, iptr, iptr->dst, d);
1862 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1864 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1865 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1866 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1867 if (iptr->op1 == 0) {
1868 gen_nullptr_check(s1);
1871 emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
1872 emit_store(jd, iptr, iptr->dst, d);
1875 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1877 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1878 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1879 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1880 if (iptr->op1 == 0) {
1881 gen_nullptr_check(s1);
1884 emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
1885 emit_store(jd, iptr, iptr->dst, d);
1888 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1890 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1891 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1892 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1893 if (iptr->op1 == 0) {
1894 gen_nullptr_check(s1);
1897 emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
1898 emit_store(jd, iptr, iptr->dst, d);
1901 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1903 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1904 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1905 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1906 if (iptr->op1 == 0) {
1907 gen_nullptr_check(s1);
1910 emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
1911 emit_store(jd, iptr, iptr->dst, d);
1914 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1916 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1917 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1918 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1919 if (iptr->op1 == 0) {
1920 gen_nullptr_check(s1);
1923 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1924 emit_store(jd, iptr, iptr->dst, d);
1927 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1929 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1930 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1931 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1932 if (iptr->op1 == 0) {
1933 gen_nullptr_check(s1);
1936 emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1937 emit_store(jd, iptr, iptr->dst, d);
1940 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1942 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1943 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1944 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1945 if (iptr->op1 == 0) {
1946 gen_nullptr_check(s1);
1949 emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1950 emit_store(jd, iptr, iptr->dst, d);
1953 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1955 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1956 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1957 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1958 if (iptr->op1 == 0) {
1959 gen_nullptr_check(s1);
1962 emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
1963 emit_store(jd, iptr, iptr->dst, d);
1967 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1969 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
1970 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
1971 if (iptr->op1 == 0) {
1972 gen_nullptr_check(s1);
1975 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
1976 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1979 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1981 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
1982 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
1983 if (iptr->op1 == 0) {
1984 gen_nullptr_check(s1);
1987 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
1988 emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
1991 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1993 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
1994 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
1995 if (iptr->op1 == 0) {
1996 gen_nullptr_check(s1);
1999 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2000 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2003 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
2005 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2006 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2007 if (iptr->op1 == 0) {
2008 gen_nullptr_check(s1);
2011 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2012 emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2015 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2017 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2018 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2019 if (iptr->op1 == 0) {
2020 gen_nullptr_check(s1);
2023 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2024 emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2027 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2029 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2030 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2031 if (iptr->op1 == 0) {
2032 gen_nullptr_check(s1);
2035 s3 = emit_load_s3(jd, iptr, src, REG_FTMP3);
2036 emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2039 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2041 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2042 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2043 if (iptr->op1 == 0) {
2044 gen_nullptr_check(s1);
2047 s3 = emit_load_s3(jd, iptr, src, REG_FTMP3);
2048 emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2051 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2053 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2054 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2055 if (iptr->op1 == 0) {
2056 gen_nullptr_check(s1);
2059 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2061 M_MOV(s1, rd->argintregs[0]);
2062 M_MOV(s3, rd->argintregs[1]);
2063 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2067 codegen_add_arraystoreexception_ref(cd);
2069 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2070 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2071 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2072 emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2076 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2078 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2079 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2080 if (iptr->op1 == 0) {
2081 gen_nullptr_check(s1);
2084 emit_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2087 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2089 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2090 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2091 if (iptr->op1 == 0) {
2092 gen_nullptr_check(s1);
2095 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2098 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2100 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2101 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2102 if (iptr->op1 == 0) {
2103 gen_nullptr_check(s1);
2106 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2109 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2111 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2112 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2113 if (iptr->op1 == 0) {
2114 gen_nullptr_check(s1);
2117 emit_movl_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2120 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2122 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2123 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2124 if (iptr->op1 == 0) {
2125 gen_nullptr_check(s1);
2129 if (IS_IMM32(iptr->val.l)) {
2130 emit_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2132 emit_movl_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2133 emit_movl_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2137 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2139 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2140 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2141 if (iptr->op1 == 0) {
2142 gen_nullptr_check(s1);
2145 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2149 case ICMD_GETSTATIC: /* ... ==> ..., value */
2150 /* op1 = type, val.a = field address */
2152 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2153 disp = dseg_addaddress(cd, NULL);
2155 /* PROFILE_CYCLE_STOP; */
2157 codegen_addpatchref(cd, PATCHER_get_putstatic,
2158 INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
2160 if (opt_showdisassemble) {
2161 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2164 /* PROFILE_CYCLE_START; */
2167 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2169 disp = dseg_addaddress(cd, &(fi->value));
2171 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2174 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2176 if (opt_showdisassemble) {
2177 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2180 PROFILE_CYCLE_START;
2184 /* This approach is much faster than moving the field
2185 address inline into a register. */
2187 M_ALD(REG_ITMP1, RIP, -(((ptrint) cd->mcodeptr + 7) -
2188 (ptrint) cd->mcodebase) + disp);
2190 switch (iptr->op1) {
2192 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2193 M_ILD(d, REG_ITMP1, 0);
2197 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2198 M_LLD(d, REG_ITMP1, 0);
2201 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2202 M_FLD(d, REG_ITMP1, 0);
2205 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2206 M_DLD(d, REG_ITMP1, 0);
2209 emit_store(jd, iptr, iptr->dst, d);
2212 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2213 /* op1 = type, val.a = field address */
2215 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2216 disp = dseg_addaddress(cd, NULL);
2218 /* PROFILE_CYCLE_STOP; */
2220 codegen_addpatchref(cd, PATCHER_get_putstatic,
2221 INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
2223 if (opt_showdisassemble) {
2224 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2227 /* PROFILE_CYCLE_START; */
2230 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2232 disp = dseg_addaddress(cd, &(fi->value));
2234 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2237 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2239 if (opt_showdisassemble) {
2240 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2243 PROFILE_CYCLE_START;
2247 /* This approach is much faster than moving the field
2248 address inline into a register. */
2250 M_ALD(REG_ITMP1, RIP, -(((ptrint) cd->mcodeptr + 7) -
2251 (ptrint) cd->mcodebase) + disp);
2253 switch (iptr->op1) {
2255 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2256 M_IST(s2, REG_ITMP1, 0);
2260 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2261 M_LST(s2, REG_ITMP1, 0);
2264 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2265 M_FST(s2, REG_ITMP1, 0);
2268 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2269 M_DST(s2, REG_ITMP1, 0);
2274 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2275 /* val = value (in current instruction) */
2276 /* op1 = type, val.a = field address (in */
2277 /* following NOP) */
2279 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2280 disp = dseg_addaddress(cd, NULL);
2282 /* PROFILE_CYCLE_STOP; */
2284 codegen_addpatchref(cd, PATCHER_get_putstatic,
2285 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), disp);
2287 if (opt_showdisassemble) {
2288 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2291 /* PROFILE_CYCLE_START; */
2294 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
2296 disp = dseg_addaddress(cd, &(fi->value));
2298 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2301 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2303 if (opt_showdisassemble) {
2304 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2307 PROFILE_CYCLE_START;
2311 /* This approach is much faster than moving the field
2312 address inline into a register. */
2314 M_ALD(REG_ITMP1, RIP, -(((ptrint) cd->mcodeptr + 7) -
2315 (ptrint) cd->mcodebase) + disp);
2317 switch (iptr->op1) {
2320 M_IST_IMM(iptr->val.i, REG_ITMP1, 0);
2325 if (IS_IMM32(iptr->val.l))
2326 M_LST_IMM32(iptr->val.l, REG_ITMP1, 0);
2328 M_IST_IMM(iptr->val.l, REG_ITMP1, 0);
2329 M_IST_IMM(iptr->val.l >> 32, REG_ITMP1, 4);
2335 case ICMD_GETFIELD: /* ... ==> ..., value */
2336 /* op1 = type, val.i = field offset */
2338 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2339 gen_nullptr_check(s1);
2341 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2342 /* PROFILE_CYCLE_STOP; */
2344 codegen_addpatchref(cd, PATCHER_get_putfield,
2345 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2347 if (opt_showdisassemble) {
2348 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2351 /* PROFILE_CYCLE_START; */
2356 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2358 switch (iptr->op1) {
2360 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2361 M_ILD32(d, s1, disp);
2365 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2366 M_LLD32(d, s1, disp);
2369 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2370 M_FLD32(d, s1, disp);
2373 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2374 M_DLD32(d, s1, disp);
2377 emit_store(jd, iptr, iptr->dst, d);
2380 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2381 /* op1 = type, val.i = field offset */
2383 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2384 gen_nullptr_check(s1);
2386 if (IS_INT_LNG_TYPE(iptr->op1))
2387 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2389 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2391 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2392 /* PROFILE_CYCLE_STOP; */
2394 codegen_addpatchref(cd, PATCHER_get_putfield,
2395 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2397 if (opt_showdisassemble) {
2398 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2401 /* PROFILE_CYCLE_START; */
2406 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2408 switch (iptr->op1) {
2410 M_IST32(s2, s1, disp);
2414 M_LST32(s2, s1, disp);
2417 M_FST32(s2, s1, disp);
2420 M_DST32(s2, s1, disp);
2425 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2426 /* val = value (in current instruction) */
2427 /* op1 = type, val.a = field address (in */
2428 /* following NOP) */
2430 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2431 gen_nullptr_check(s1);
2433 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2434 /* PROFILE_CYCLE_STOP; */
2436 codegen_addpatchref(cd, PATCHER_putfieldconst,
2437 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2439 if (opt_showdisassemble) {
2440 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2443 /* PROFILE_CYCLE_START; */
2448 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
2450 switch (iptr->op1) {
2453 M_IST32_IMM(iptr->val.i, s1, disp);
2458 M_IST32_IMM(iptr->val.l, s1, disp);
2459 M_IST32_IMM(iptr->val.l >> 32, s1, disp + 4);
2465 /* branch operations **************************************************/
2467 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2469 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2470 M_INTMOVE(s1, REG_ITMP1_XPTR);
2474 #ifdef ENABLE_VERIFIER
2476 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2477 (unresolved_class *) iptr->val.a, 0);
2479 if (opt_showdisassemble) {
2480 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2483 #endif /* ENABLE_VERIFIER */
2485 M_CALL_IMM(0); /* passing exception pc */
2486 M_POP(REG_ITMP2_XPC);
2488 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2492 case ICMD_GOTO: /* ... ==> ... */
2493 /* op1 = target JavaVM pc */
2496 codegen_addreference(cd, (basicblock *) iptr->target);
2499 case ICMD_JSR: /* ... ==> ... */
2500 /* op1 = target JavaVM pc */
2503 codegen_addreference(cd, (basicblock *) iptr->target);
2506 case ICMD_RET: /* ... ==> ... */
2507 /* op1 = local variable */
2509 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2510 if (var->flags & INMEMORY) {
2511 M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
2517 case ICMD_IFNULL: /* ..., value ==> ... */
2518 /* op1 = target JavaVM pc */
2520 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2523 codegen_addreference(cd, (basicblock *) iptr->target);
2526 case ICMD_IFNONNULL: /* ..., value ==> ... */
2527 /* op1 = target JavaVM pc */
2529 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2532 codegen_addreference(cd, (basicblock *) iptr->target);
2535 case ICMD_IFEQ: /* ..., value ==> ... */
2536 /* op1 = target JavaVM pc, val.i = constant */
2538 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2539 M_ICMP_IMM(iptr->val.i, s1);
2541 codegen_addreference(cd, (basicblock *) iptr->target);
2544 case ICMD_IFLT: /* ..., value ==> ... */
2545 /* op1 = target JavaVM pc, val.i = constant */
2547 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2548 M_ICMP_IMM(iptr->val.i, s1);
2550 codegen_addreference(cd, (basicblock *) iptr->target);
2553 case ICMD_IFLE: /* ..., value ==> ... */
2554 /* op1 = target JavaVM pc, val.i = constant */
2556 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2557 M_ICMP_IMM(iptr->val.i, s1);
2559 codegen_addreference(cd, (basicblock *) iptr->target);
2562 case ICMD_IFNE: /* ..., value ==> ... */
2563 /* op1 = target JavaVM pc, val.i = constant */
2565 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2566 M_ICMP_IMM(iptr->val.i, s1);
2568 codegen_addreference(cd, (basicblock *) iptr->target);
2571 case ICMD_IFGT: /* ..., value ==> ... */
2572 /* op1 = target JavaVM pc, val.i = constant */
2574 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2575 M_ICMP_IMM(iptr->val.i, s1);
2577 codegen_addreference(cd, (basicblock *) iptr->target);
2580 case ICMD_IFGE: /* ..., value ==> ... */
2581 /* op1 = target JavaVM pc, val.i = constant */
2583 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2584 M_ICMP_IMM(iptr->val.i, s1);
2586 codegen_addreference(cd, (basicblock *) iptr->target);
2589 case ICMD_IF_LEQ: /* ..., value ==> ... */
2590 /* op1 = target JavaVM pc, val.l = constant */
2592 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2593 if (IS_IMM32(iptr->val.l))
2594 M_LCMP_IMM(iptr->val.l, s1);
2596 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2597 M_LCMP(REG_ITMP2, s1);
2600 codegen_addreference(cd, (basicblock *) iptr->target);
2603 case ICMD_IF_LLT: /* ..., value ==> ... */
2604 /* op1 = target JavaVM pc, val.l = constant */
2606 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2607 if (IS_IMM32(iptr->val.l))
2608 M_LCMP_IMM(iptr->val.l, s1);
2610 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2611 M_LCMP(REG_ITMP2, s1);
2614 codegen_addreference(cd, (basicblock *) iptr->target);
2617 case ICMD_IF_LLE: /* ..., value ==> ... */
2618 /* op1 = target JavaVM pc, val.l = constant */
2620 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2621 if (IS_IMM32(iptr->val.l))
2622 M_LCMP_IMM(iptr->val.l, s1);
2624 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2625 M_LCMP(REG_ITMP2, s1);
2628 codegen_addreference(cd, (basicblock *) iptr->target);
2631 case ICMD_IF_LNE: /* ..., value ==> ... */
2632 /* op1 = target JavaVM pc, val.l = constant */
2634 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2635 if (IS_IMM32(iptr->val.l))
2636 M_LCMP_IMM(iptr->val.l, s1);
2638 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2639 M_LCMP(REG_ITMP2, s1);
2642 codegen_addreference(cd, (basicblock *) iptr->target);
2645 case ICMD_IF_LGT: /* ..., value ==> ... */
2646 /* op1 = target JavaVM pc, val.l = constant */
2648 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2649 if (IS_IMM32(iptr->val.l))
2650 M_LCMP_IMM(iptr->val.l, s1);
2652 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2653 M_LCMP(REG_ITMP2, s1);
2656 codegen_addreference(cd, (basicblock *) iptr->target);
2659 case ICMD_IF_LGE: /* ..., value ==> ... */
2660 /* op1 = target JavaVM pc, val.l = constant */
2662 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2663 if (IS_IMM32(iptr->val.l))
2664 M_LCMP_IMM(iptr->val.l, s1);
2666 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2667 M_LCMP(REG_ITMP2, s1);
2670 codegen_addreference(cd, (basicblock *) iptr->target);
2673 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2674 /* op1 = target JavaVM pc */
2676 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2677 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2680 codegen_addreference(cd, (basicblock *) iptr->target);
2683 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2684 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2686 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2687 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2690 codegen_addreference(cd, (basicblock *) iptr->target);
2693 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2694 /* op1 = target JavaVM pc */
2696 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2697 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2700 codegen_addreference(cd, (basicblock *) iptr->target);
2703 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2704 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2706 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2707 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2710 codegen_addreference(cd, (basicblock *) iptr->target);
2713 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2714 /* op1 = target JavaVM pc */
2716 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2717 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2720 codegen_addreference(cd, (basicblock *) iptr->target);
2723 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2724 /* op1 = target JavaVM pc */
2726 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2727 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2730 codegen_addreference(cd, (basicblock *) iptr->target);
2733 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2734 /* op1 = target JavaVM pc */
2736 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2737 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2740 codegen_addreference(cd, (basicblock *) iptr->target);
2743 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2744 /* op1 = target JavaVM pc */
2746 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2747 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2750 codegen_addreference(cd, (basicblock *) iptr->target);
2753 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2754 /* op1 = target JavaVM pc */
2756 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2757 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2760 codegen_addreference(cd, (basicblock *) iptr->target);
2763 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2764 /* op1 = target JavaVM pc */
2766 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2767 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2770 codegen_addreference(cd, (basicblock *) iptr->target);
2773 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2774 /* op1 = target JavaVM pc */
2776 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2777 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2780 codegen_addreference(cd, (basicblock *) iptr->target);
2783 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2784 /* op1 = target JavaVM pc */
2786 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2787 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2790 codegen_addreference(cd, (basicblock *) iptr->target);
2793 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2795 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2798 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2799 case ICMD_IFNE_ICONST: /* val.i = constant */
2800 case ICMD_IFLT_ICONST:
2801 case ICMD_IFGE_ICONST:
2802 case ICMD_IFGT_ICONST:
2803 case ICMD_IFLE_ICONST:
2805 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2806 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2807 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2809 M_INTMOVE(s1, REG_ITMP1);
2812 if (iptr[1].val.i == 0)
2815 M_IMOV_IMM(iptr[1].val.i, d);
2817 if (iptr->val.i == 0)
2820 M_IMOV_IMM(iptr->val.i, REG_ITMP2);
2823 switch (iptr->opc) {
2824 case ICMD_IFEQ_ICONST:
2825 M_CMOVEQ(REG_ITMP2, d);
2827 case ICMD_IFNE_ICONST:
2828 M_CMOVNE(REG_ITMP2, d);
2830 case ICMD_IFLT_ICONST:
2831 M_CMOVLT(REG_ITMP2, d);
2833 case ICMD_IFGE_ICONST:
2834 M_CMOVGE(REG_ITMP2, d);
2836 case ICMD_IFGT_ICONST:
2837 M_CMOVGT(REG_ITMP2, d);
2839 case ICMD_IFLE_ICONST:
2840 M_CMOVLE(REG_ITMP2, d);
2844 emit_store(jd, iptr, iptr->dst, d);
2848 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2851 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
2852 M_INTMOVE(s1, REG_RESULT);
2853 goto nowperformreturn;
2855 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2857 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
2858 M_INTMOVE(s1, REG_RESULT);
2860 #ifdef ENABLE_VERIFIER
2864 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2865 (unresolved_class *) iptr->val.a, 0);
2867 if (opt_showdisassemble) {
2868 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2871 PROFILE_CYCLE_START;
2873 #endif /* ENABLE_VERIFIER */
2874 goto nowperformreturn;
2876 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2879 s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
2880 M_FLTMOVE(s1, REG_FRESULT);
2881 goto nowperformreturn;
2883 case ICMD_RETURN: /* ... ==> ... */
2891 #if !defined(NDEBUG)
2892 /* generate call trace */
2894 if (opt_verbosecall) {
2895 emit_alu_imm_reg(cd, ALU_SUB, 2 * 8, REG_SP);
2897 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, 0 * 8);
2898 emit_movq_reg_membase(cd, REG_FRESULT, REG_SP, 1 * 8);
2900 emit_mov_imm_reg(cd, (u8) m, rd->argintregs[0]);
2901 emit_mov_reg_reg(cd, REG_RESULT, rd->argintregs[1]);
2902 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2903 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2905 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
2908 emit_mov_membase_reg(cd, REG_SP, 0 * 8, REG_RESULT);
2909 emit_movq_membase_reg(cd, REG_SP, 1 * 8, REG_FRESULT);
2911 emit_alu_imm_reg(cd, ALU_ADD, 2 * 8, REG_SP);
2913 #endif /* !defined(NDEBUG) */
2915 #if defined(ENABLE_THREADS)
2916 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2917 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2919 /* we need to save the proper return value */
2920 switch (iptr->opc) {
2924 M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
2928 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
2932 M_MOV_IMM(LOCK_monitor_exit, REG_ITMP1);
2935 /* and now restore the proper return value */
2936 switch (iptr->opc) {
2940 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2944 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2950 /* restore saved registers */
2952 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2953 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2955 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2956 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2959 /* deallocate stack */
2962 M_AADD_IMM(stackframesize * 8, REG_SP);
2964 /* generate method profiling code */
2973 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2978 tptr = (void **) iptr->target;
2980 s4ptr = iptr->val.a;
2981 l = s4ptr[1]; /* low */
2982 i = s4ptr[2]; /* high */
2984 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2985 M_INTMOVE(s1, REG_ITMP1);
2988 M_ISUB_IMM(l, REG_ITMP1);
2993 M_ICMP_IMM(i - 1, REG_ITMP1);
2996 codegen_addreference(cd, (basicblock *) tptr[0]);
2998 /* build jump table top down and use address of lowest entry */
3000 /* s4ptr += 3 + i; */
3004 dseg_addtarget(cd, (basicblock *) tptr[0]);
3008 /* length of dataseg after last dseg_addtarget is used
3011 M_MOV_IMM(0, REG_ITMP2);
3013 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
3019 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3021 s4 i, l, val, *s4ptr;
3024 tptr = (void **) iptr->target;
3026 s4ptr = iptr->val.a;
3027 l = s4ptr[0]; /* default */
3028 i = s4ptr[1]; /* count */
3030 MCODECHECK(8 + ((7 + 6) * i) + 5);
3031 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3038 M_ICMP_IMM(val, s1);
3040 codegen_addreference(cd, (basicblock *) tptr[0]);
3045 tptr = (void **) iptr->target;
3046 codegen_addreference(cd, (basicblock *) tptr[0]);
3051 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
3052 /* op1 = arg count val.a = builtintable entry */
3058 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3059 /* op1 = arg count, val.a = method pointer */
3061 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3062 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3063 case ICMD_INVOKEINTERFACE:
3065 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3066 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
3070 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
3071 md = lm->parseddesc;
3075 s3 = md->paramcount;
3077 MCODECHECK((20 * s3) + 128);
3079 /* copy arguments to registers or stack location */
3081 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3082 if (src->varkind == ARGVAR)
3084 if (IS_INT_LNG_TYPE(src->type)) {
3085 if (!md->params[s3].inmemory) {
3086 s1 = rd->argintregs[md->params[s3].regoff];
3087 d = emit_load_s1(jd, iptr, src, s1);
3090 d = emit_load_s1(jd, iptr, src, REG_ITMP1);
3091 M_LST(d, REG_SP, md->params[s3].regoff * 8);
3095 if (!md->params[s3].inmemory) {
3096 s1 = rd->argfltregs[md->params[s3].regoff];
3097 d = emit_load_s1(jd, iptr, src, s1);
3100 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
3102 if (IS_2_WORD_TYPE(src->type))
3103 M_DST(d, REG_SP, md->params[s3].regoff * 8);
3105 M_FST(d, REG_SP, md->params[s3].regoff * 8);
3110 /* generate method profiling code */
3114 switch (iptr->opc) {
3116 a = (ptrint) bte->fp;
3117 d = md->returntype.type;
3119 M_MOV_IMM(a, REG_ITMP1);
3122 /* if op1 == true, we need to check for an exception */
3124 if (iptr->op1 == true) {
3127 codegen_add_fillinstacktrace_ref(cd);
3131 case ICMD_INVOKESPECIAL:
3132 M_TEST(rd->argintregs[0]);
3134 codegen_add_nullpointerexception_ref(cd);
3136 /* first argument contains pointer */
3137 /* gen_nullptr_check(rd->argintregs[0]); */
3139 /* access memory for hardware nullptr */
3140 /* emit_mov_membase_reg(cd, rd->argintregs[0], 0, REG_ITMP2); */
3144 case ICMD_INVOKESTATIC:
3146 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3148 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3151 if (opt_showdisassemble) {
3152 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3156 d = um->methodref->parseddesc.md->returntype.type;
3159 a = (ptrint) lm->stubroutine;
3160 d = lm->parseddesc->returntype.type;
3163 M_MOV_IMM(a, REG_ITMP2);
3167 case ICMD_INVOKEVIRTUAL:
3168 gen_nullptr_check(rd->argintregs[0]);
3171 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3173 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3175 if (opt_showdisassemble) {
3176 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3180 d = um->methodref->parseddesc.md->returntype.type;
3183 s1 = OFFSET(vftbl_t, table[0]) +
3184 sizeof(methodptr) * lm->vftblindex;
3185 d = lm->parseddesc->returntype.type;
3188 M_ALD(REG_METHODPTR, rd->argintregs[0],
3189 OFFSET(java_objectheader, vftbl));
3190 M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
3194 case ICMD_INVOKEINTERFACE:
3195 gen_nullptr_check(rd->argintregs[0]);
3198 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3200 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3202 if (opt_showdisassemble) {
3203 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3208 d = um->methodref->parseddesc.md->returntype.type;
3211 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3212 sizeof(methodptr) * lm->class->index;
3214 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3216 d = lm->parseddesc->returntype.type;
3219 M_ALD(REG_METHODPTR, rd->argintregs[0],
3220 OFFSET(java_objectheader, vftbl));
3221 M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
3222 M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
3227 /* generate method profiling code */
3229 PROFILE_CYCLE_START;
3231 /* d contains return type */
3233 if (d != TYPE_VOID) {
3234 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3235 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3236 M_INTMOVE(REG_RESULT, s1);
3237 emit_store(jd, iptr, iptr->dst, s1);
3239 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FRESULT);
3240 M_FLTMOVE(REG_FRESULT, s1);
3241 emit_store(jd, iptr, iptr->dst, s1);
3247 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3249 /* op1: 0 == array, 1 == class */
3250 /* val.a: (classinfo *) superclass */
3252 /* superclass is an interface:
3254 * OK if ((sub == NULL) ||
3255 * (sub->vftbl->interfacetablelength > super->index) &&
3256 * (sub->vftbl->interfacetable[-super->index] != NULL));
3258 * superclass is a class:
3260 * OK if ((sub == NULL) || (0
3261 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3262 * super->vftbl->diffval));
3265 if (iptr->op1 == 1) {
3266 /* object type cast-check */
3269 vftbl_t *supervftbl;
3272 super = (classinfo *) iptr->val.a;
3274 if (super == NULL) {
3279 superindex = super->index;
3280 supervftbl = super->vftbl;
3283 #if defined(ENABLE_THREADS)
3284 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3286 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3288 /* calculate interface checkcast code size */
3290 s2 = 3; /* mov_membase_reg */
3291 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3293 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub imm32 */ +
3294 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3295 3 /* test */ + 6 /* jcc */;
3298 s2 += (opt_showdisassemble ? 5 : 0);
3300 /* calculate class checkcast code size */
3302 s3 = 3; /* mov_membase_reg */
3303 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3304 s3 += 10 /* mov_imm_reg */ + 3 + 4 /* movl_membase32_reg */;
3307 if (s1 != REG_ITMP1) {
3308 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3309 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3310 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3311 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3317 s3 += 3 + 4 /* movl_membase32_reg */ + 3 /* sub */ +
3318 10 /* mov_imm_reg */ + 3 /* movl_membase_reg */;
3319 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3322 s3 += 3 /* cmp */ + 6 /* jcc */;
3325 s3 += (opt_showdisassemble ? 5 : 0);
3327 /* if class is not resolved, check which code to call */
3329 if (super == NULL) {
3331 M_BEQ(6 + (opt_showdisassemble ? 5 : 0) + 7 + 6 + s2 + 5 + s3);
3333 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3334 (constant_classref *) iptr->target, 0);
3336 if (opt_showdisassemble) {
3337 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3340 M_IMOV_IMM(0, REG_ITMP2); /* super->flags */
3341 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
3345 /* interface checkcast code */
3347 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3348 if (super != NULL) {
3353 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3355 if (super == NULL) {
3356 codegen_addpatchref(cd,
3357 PATCHER_checkcast_instanceof_interface,
3358 (constant_classref *) iptr->target,
3361 if (opt_showdisassemble) {
3362 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3366 emit_movl_membase32_reg(cd, REG_ITMP2,
3367 OFFSET(vftbl_t, interfacetablelength),
3369 /* XXX TWISTI: should this be int arithmetic? */
3370 M_LSUB_IMM32(superindex, REG_ITMP3);
3373 codegen_add_classcastexception_ref(cd, s1);
3374 emit_mov_membase32_reg(cd, REG_ITMP2,
3375 OFFSET(vftbl_t, interfacetable[0]) -
3376 superindex * sizeof(methodptr*),
3380 codegen_add_classcastexception_ref(cd, s1);
3386 /* class checkcast code */
3388 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3389 if (super != NULL) {
3394 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3396 if (super == NULL) {
3397 codegen_addpatchref(cd, PATCHER_checkcast_class,
3398 (constant_classref *) iptr->target,
3401 if (opt_showdisassemble) {
3402 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3406 M_MOV_IMM(supervftbl, REG_ITMP3);
3407 #if defined(ENABLE_THREADS)
3408 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3410 emit_movl_membase32_reg(cd, REG_ITMP2,
3411 OFFSET(vftbl_t, baseval),
3413 /* if (s1 != REG_ITMP1) { */
3414 /* emit_movl_membase_reg(cd, REG_ITMP3, */
3415 /* OFFSET(vftbl_t, baseval), */
3417 /* emit_movl_membase_reg(cd, REG_ITMP3, */
3418 /* OFFSET(vftbl_t, diffval), */
3420 /* #if defined(ENABLE_THREADS) */
3421 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3423 /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
3426 emit_movl_membase32_reg(cd, REG_ITMP3,
3427 OFFSET(vftbl_t, baseval),
3429 M_LSUB(REG_ITMP3, REG_ITMP2);
3430 M_MOV_IMM(supervftbl, REG_ITMP3);
3431 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3433 #if defined(ENABLE_THREADS)
3434 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3436 M_LCMP(REG_ITMP3, REG_ITMP2);
3437 M_BA(0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
3438 codegen_add_classcastexception_ref(cd, s1);
3441 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
3444 /* array type cast-check */
3446 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3447 M_INTMOVE(s1, rd->argintregs[0]);
3449 if (iptr->val.a == NULL) {
3450 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
3451 (constant_classref *) iptr->target, 0);
3453 if (opt_showdisassemble) {
3454 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3458 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3459 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
3462 /* s1 may have been destroyed over the function call */
3463 s1 = emit_load_s1(jd, iptr, src, REG_ITMP2);
3466 codegen_add_classcastexception_ref(cd, s1);
3468 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3472 emit_store(jd, iptr, iptr->dst, d);
3475 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3477 /* op1: 0 == array, 1 == class */
3478 /* val.a: (classinfo *) superclass */
3480 /* superclass is an interface:
3482 * return (sub != NULL) &&
3483 * (sub->vftbl->interfacetablelength > super->index) &&
3484 * (sub->vftbl->interfacetable[-super->index] != NULL);
3486 * superclass is a class:
3488 * return ((sub != NULL) && (0
3489 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3490 * super->vftbl->diffvall));
3495 vftbl_t *supervftbl;
3498 super = (classinfo *) iptr->val.a;
3505 superindex = super->index;
3506 supervftbl = super->vftbl;
3509 #if defined(ENABLE_THREADS)
3510 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3513 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3514 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3516 M_INTMOVE(s1, REG_ITMP1);
3520 /* calculate interface instanceof code size */
3522 s2 = 3; /* mov_membase_reg */
3523 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3524 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub_imm32 */ +
3525 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3526 3 /* test */ + 4 /* setcc */;
3529 s2 += (opt_showdisassemble ? 5 : 0);
3531 /* calculate class instanceof code size */
3533 s3 = 3; /* mov_membase_reg */
3534 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3535 s3 += 10; /* mov_imm_reg */
3536 s3 += 2; /* movl_membase_reg - only if REG_ITMP1 == RAX */
3537 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3538 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3539 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3540 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3541 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3542 s3 += 3 /* sub */ + 3 /* xor */ + 3 /* cmp */ + 4 /* setcc */;
3545 s3 += (opt_showdisassemble ? 5 : 0);
3547 emit_alu_reg_reg(cd, ALU_XOR, d, d);
3549 /* if class is not resolved, check which code to call */
3552 emit_test_reg_reg(cd, s1, s1);
3553 emit_jcc(cd, CC_Z, (6 + (opt_showdisassemble ? 5 : 0) +
3554 7 + 6 + s2 + 5 + s3));
3556 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3557 (constant_classref *) iptr->target, 0);
3559 if (opt_showdisassemble) {
3560 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3563 emit_movl_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
3564 emit_alul_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
3565 emit_jcc(cd, CC_Z, s2 + 5);
3568 /* interface instanceof code */
3570 if (!super || (super->flags & ACC_INTERFACE)) {
3572 emit_test_reg_reg(cd, s1, s1);
3573 emit_jcc(cd, CC_Z, s2);
3576 emit_mov_membase_reg(cd, s1,
3577 OFFSET(java_objectheader, vftbl),
3580 codegen_addpatchref(cd,
3581 PATCHER_checkcast_instanceof_interface,
3582 (constant_classref *) iptr->target, 0);
3584 if (opt_showdisassemble) {
3585 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3589 emit_movl_membase32_reg(cd, REG_ITMP1,
3590 OFFSET(vftbl_t, interfacetablelength),
3592 emit_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
3593 emit_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
3595 a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
3597 emit_jcc(cd, CC_LE, a);
3598 emit_mov_membase32_reg(cd, REG_ITMP1,
3599 OFFSET(vftbl_t, interfacetable[0]) -
3600 superindex * sizeof(methodptr*),
3602 emit_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3603 emit_setcc_reg(cd, CC_NE, d);
3606 emit_jmp_imm(cd, s3);
3609 /* class instanceof code */
3611 if (!super || !(super->flags & ACC_INTERFACE)) {
3613 emit_test_reg_reg(cd, s1, s1);
3614 emit_jcc(cd, CC_E, s3);
3617 emit_mov_membase_reg(cd, s1,
3618 OFFSET(java_objectheader, vftbl),
3622 codegen_addpatchref(cd, PATCHER_instanceof_class,
3623 (constant_classref *) iptr->target, 0);
3625 if (opt_showdisassemble) {
3626 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3630 emit_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
3631 #if defined(ENABLE_THREADS)
3632 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3634 emit_movl_membase_reg(cd, REG_ITMP1,
3635 OFFSET(vftbl_t, baseval),
3637 emit_movl_membase_reg(cd, REG_ITMP2,
3638 OFFSET(vftbl_t, diffval),
3640 emit_movl_membase_reg(cd, REG_ITMP2,
3641 OFFSET(vftbl_t, baseval),
3643 #if defined(ENABLE_THREADS)
3644 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3646 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
3647 emit_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
3648 emit_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
3649 emit_setcc_reg(cd, CC_BE, d);
3651 emit_store(jd, iptr, iptr->dst, d);
3655 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3656 /* op1 = dimension, val.a = class */
3658 /* check for negative sizes and copy sizes to stack if necessary */
3660 MCODECHECK((10 * 4 * iptr->op1) + 5 + 10 * 8);
3662 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3663 /* copy SAVEDVAR sizes to stack */
3665 if (src->varkind != ARGVAR) {
3666 s2 = emit_load_s2(jd, iptr, src, REG_ITMP1);
3667 M_LST(s2, REG_SP, s1 * 8);
3671 /* is a patcher function set? */
3673 if (iptr->val.a == NULL) {
3674 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
3675 (constant_classref *) iptr->target, 0);
3677 if (opt_showdisassemble) {
3678 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3684 a = (ptrint) iptr->val.a;
3687 /* a0 = dimension count */
3689 M_MOV_IMM(iptr->op1, rd->argintregs[0]);
3691 /* a1 = arrayvftbl */
3693 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3695 /* a2 = pointer to dimensions = stack pointer */
3697 M_MOV(REG_SP, rd->argintregs[2]);
3699 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3702 /* check for exception before result assignment */
3706 codegen_add_fillinstacktrace_ref(cd);
3708 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3709 M_INTMOVE(REG_RESULT, s1);
3710 emit_store(jd, iptr, iptr->dst, s1);
3714 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3718 } /* for instruction */
3720 /* copy values to interface registers */
3722 src = bptr->outstack;
3723 len = bptr->outdepth;
3725 #if defined(ENABLE_LSRA)
3730 if ((src->varkind != STACKVAR)) {
3732 if (IS_FLT_DBL_TYPE(s2)) {
3733 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
3734 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3735 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3738 emit_movq_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3742 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3743 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3744 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3747 emit_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3754 /* At the end of a basic block we may have to append some nops,
3755 because the patcher stub calling code might be longer than the
3756 actual instruction. So codepatching does not change the
3757 following block unintentionally. */
3759 if (cd->mcodeptr < cd->lastmcodeptr) {
3760 while (cd->mcodeptr < cd->lastmcodeptr) {
3765 } /* if (bptr -> flags >= BBREACHED) */
3766 } /* for basic block */
3768 dseg_createlinenumbertable(cd);
3771 /* generate exception and patcher stubs */
3780 savedmcodeptr = NULL;
3782 /* generate exception stubs */
3784 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
3785 gen_resolvebranch(cd->mcodebase + eref->branchpos,
3787 cd->mcodeptr - cd->mcodebase);
3791 /* Check if the exception is an
3792 ArrayIndexOutOfBoundsException. If so, move index register
3795 if (eref->reg != -1)
3796 M_MOV(eref->reg, rd->argintregs[4]);
3798 /* calcuate exception address */
3800 M_MOV_IMM(0, rd->argintregs[3]);
3802 M_AADD_IMM32(eref->branchpos - 6, rd->argintregs[3]);
3804 /* move function to call into REG_ITMP3 */
3806 M_MOV_IMM(eref->function, REG_ITMP3);
3808 if (savedmcodeptr != NULL) {
3809 M_JMP_IMM(savedmcodeptr - cd->mcodeptr - 5);
3812 savedmcodeptr = cd->mcodeptr;
3814 emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[0]);
3815 M_MOV(REG_SP, rd->argintregs[1]);
3816 M_ALD(rd->argintregs[2], REG_SP, stackframesize * 8);
3818 M_ASUB_IMM(2 * 8, REG_SP);
3819 M_AST(rd->argintregs[3], REG_SP, 0 * 8); /* store XPC */
3823 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3824 M_AADD_IMM(2 * 8, REG_SP);
3826 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
3832 /* generate code patching stub call code */
3834 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3835 /* check size of code segment */
3839 /* Get machine code which is patched back in later. A
3840 `call rel32' is 5 bytes long (but read 8 bytes). */
3842 savedmcodeptr = cd->mcodebase + pref->branchpos;
3843 mcode = *((ptrint *) savedmcodeptr);
3845 /* patch in `call rel32' to call the following code */
3847 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
3848 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
3850 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
3852 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3854 /* move pointer to java_objectheader onto stack */
3856 #if defined(ENABLE_THREADS)
3857 /* create a virtual java_objectheader */
3859 (void) dseg_addaddress(cd, NULL); /* flcword */
3860 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
3861 a = dseg_addaddress(cd, NULL); /* vftbl */
3863 emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + a, REG_ITMP3);
3869 /* move machine code bytes and classinfo pointer into registers */
3871 M_MOV_IMM(mcode, REG_ITMP3);
3873 M_MOV_IMM(pref->ref, REG_ITMP3);
3875 M_MOV_IMM(pref->disp, REG_ITMP3);
3878 M_MOV_IMM(pref->patcher, REG_ITMP3);
3881 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
3886 /* generate replacement-out stubs */
3891 replacementpoint = jd->code->rplpoints;
3893 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
3894 /* check code segment size */
3898 /* note start of stub code */
3900 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
3902 /* make machine code for patching */
3904 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
3905 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
3907 /* push address of `rplpoint` struct */
3909 M_MOV_IMM(replacementpoint, REG_ITMP3);
3912 /* jump to replacement function */
3914 M_MOV_IMM(asm_replacement_out, REG_ITMP3);
3921 /* everything's ok */
3927 /* createcompilerstub **********************************************************
3929 Creates a stub routine which calls the compiler.
3931 *******************************************************************************/
3933 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
3934 #define COMPILERSTUB_CODESIZE 7 + 7 + 3
3936 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
3939 u1 *createcompilerstub(methodinfo *m)
3941 u1 *s; /* memory to hold the stub */
3947 s = CNEW(u1, COMPILERSTUB_SIZE);
3949 /* set data pointer and code pointer */
3952 s = s + COMPILERSTUB_DATASIZE;
3954 /* mark start of dump memory area */
3956 dumpsize = dump_size();
3958 cd = DNEW(codegendata);
3961 /* Store the codeinfo pointer in the same place as in the
3962 methodheader for compiled methods. */
3964 code = code_codeinfo_new(m);
3966 d[0] = (ptrint) asm_call_jit_compiler;
3968 d[2] = (ptrint) code;
3970 /* code for the stub */
3972 M_ALD(REG_ITMP1, RIP, -(7 * 1 + 2 * SIZEOF_VOID_P)); /* methodinfo */
3973 M_ALD(REG_ITMP3, RIP, -(7 * 2 + 3 * SIZEOF_VOID_P)); /* compiler pointer */
3976 #if defined(ENABLE_STATISTICS)
3978 count_cstub_len += COMPILERSTUB_SIZE;
3981 /* release dump area */
3983 dump_release(dumpsize);
3989 /* createnativestub ************************************************************
3991 Creates a stub routine which calls a native method.
3993 *******************************************************************************/
3995 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
4002 s4 stackframesize; /* size of stackframe if needed */
4004 s4 i, j; /* count variables */
4008 /* get required compiler data */
4015 /* initialize variables */
4018 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4020 /* calculate stack frame size */
4023 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4024 sizeof(localref_table) / SIZEOF_VOID_P +
4025 INT_ARG_CNT + FLT_ARG_CNT + 1 + /* + 1 for function address */
4028 if (!(stackframesize & 0x1)) /* keep stack 16-byte aligned */
4031 /* create method header */
4033 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
4034 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4035 (void) dseg_adds4(cd, 0); /* IsSync */
4036 (void) dseg_adds4(cd, 0); /* IsLeaf */
4037 (void) dseg_adds4(cd, 0); /* IntSave */
4038 (void) dseg_adds4(cd, 0); /* FltSave */
4039 (void) dseg_addlinenumbertablesize(cd);
4040 (void) dseg_adds4(cd, 0); /* ExTableSize */
4042 /* generate native method profiling code */
4044 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
4045 /* count frequency */
4047 M_MOV_IMM(code, REG_ITMP3);
4048 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
4051 /* generate stub code */
4053 M_ASUB_IMM(stackframesize * 8, REG_SP);
4055 #if !defined(NDEBUG)
4056 /* generate call trace */
4058 if (opt_verbosecall) {
4059 /* save integer and float argument registers */
4061 for (i = 0, j = 1; i < md->paramcount; i++) {
4062 if (!md->params[i].inmemory) {
4063 s1 = md->params[i].regoff;
4065 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4066 M_LST(rd->argintregs[s1], REG_SP, j * 8);
4068 M_DST(rd->argfltregs[s1], REG_SP, j * 8);
4074 /* show integer hex code for float arguments */
4076 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++) {
4077 /* if the paramtype is a float, we have to right shift all
4078 following integer registers */
4080 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4081 for (s1 = INT_ARG_CNT - 2; s1 >= i; s1--)
4082 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
4084 emit_movd_freg_reg(cd, rd->argfltregs[j], rd->argintregs[i]);
4089 M_MOV_IMM(m, REG_ITMP1);
4090 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4091 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
4094 /* restore integer and float argument registers */
4096 for (i = 0, j = 1; i < md->paramcount; i++) {
4097 if (!md->params[i].inmemory) {
4098 s1 = md->params[i].regoff;
4100 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4101 M_LLD(rd->argintregs[s1], REG_SP, j * 8);
4103 M_DLD(rd->argfltregs[s1], REG_SP, j * 8);
4109 #endif /* !defined(NDEBUG) */
4111 /* get function address (this must happen before the stackframeinfo) */
4113 #if !defined(WITH_STATIC_CLASSPATH)
4115 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
4117 if (opt_showdisassemble) {
4118 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4123 M_MOV_IMM(f, REG_ITMP3);
4126 /* save integer and float argument registers */
4128 for (i = 0, j = 0; i < md->paramcount; i++) {
4129 if (!md->params[i].inmemory) {
4130 s1 = md->params[i].regoff;
4132 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4133 M_LST(rd->argintregs[s1], REG_SP, j * 8);
4135 M_DST(rd->argfltregs[s1], REG_SP, j * 8);
4141 M_AST(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4143 /* create dynamic stack info */
4145 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4146 emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[1]);
4147 M_ALEA(REG_SP, stackframesize * 8 + SIZEOF_VOID_P, rd->argintregs[2]);
4148 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8);
4149 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
4152 /* restore integer and float argument registers */
4154 for (i = 0, j = 0; i < md->paramcount; i++) {
4155 if (!md->params[i].inmemory) {
4156 s1 = md->params[i].regoff;
4158 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4159 M_LLD(rd->argintregs[s1], REG_SP, j * 8);
4161 M_DLD(rd->argfltregs[s1], REG_SP, j * 8);
4167 M_ALD(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4170 /* copy or spill arguments to new locations */
4172 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4173 t = md->paramtypes[i].type;
4175 if (IS_INT_LNG_TYPE(t)) {
4176 if (!md->params[i].inmemory) {
4177 s1 = rd->argintregs[md->params[i].regoff];
4179 if (!nmd->params[j].inmemory) {
4180 s2 = rd->argintregs[nmd->params[j].regoff];
4184 s2 = nmd->params[j].regoff;
4185 M_LST(s1, REG_SP, s2 * 8);
4189 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4190 s2 = nmd->params[j].regoff;
4191 M_LLD(REG_ITMP1, REG_SP, s1 * 8);
4192 M_LST(REG_ITMP1, REG_SP, s2 * 8);
4196 /* We only copy spilled float arguments, as the float argument */
4197 /* registers keep unchanged. */
4199 if (md->params[i].inmemory) {
4200 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4201 s2 = nmd->params[j].regoff;
4203 if (IS_2_WORD_TYPE(t)) {
4204 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4205 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4207 M_FLD(REG_FTMP1, REG_SP, s1 * 8);
4208 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4214 /* put class into second argument register */
4216 if (m->flags & ACC_STATIC)
4217 M_MOV_IMM(m->class, rd->argintregs[1]);
4219 /* put env into first argument register */
4221 M_MOV_IMM(_Jv_env, rd->argintregs[0]);
4223 /* do the native function call */
4227 /* save return value */
4229 if (md->returntype.type != TYPE_VOID) {
4230 if (IS_INT_LNG_TYPE(md->returntype.type))
4231 M_LST(REG_RESULT, REG_SP, 0 * 8);
4233 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4236 #if !defined(NDEBUG)
4237 /* generate call trace */
4239 if (opt_verbosecall) {
4240 /* just restore the value we need, don't care about the other */
4242 if (md->returntype.type != TYPE_VOID) {
4243 if (IS_INT_LNG_TYPE(md->returntype.type))
4244 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4246 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4249 M_MOV_IMM(m, rd->argintregs[0]);
4250 M_MOV(REG_RESULT, rd->argintregs[1]);
4251 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4252 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4254 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
4257 #endif /* !defined(NDEBUG) */
4259 /* remove native stackframe info */
4261 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4262 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
4264 M_MOV(REG_RESULT, REG_ITMP3);
4266 /* restore return value */
4268 if (md->returntype.type != TYPE_VOID) {
4269 if (IS_INT_LNG_TYPE(md->returntype.type))
4270 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4272 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4275 /* remove stackframe */
4277 M_AADD_IMM(stackframesize * 8, REG_SP);
4279 /* test for exception */
4285 /* handle exception */
4287 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
4288 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
4289 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
4291 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4295 /* process patcher calls **************************************************/
4302 #if defined(ENABLE_THREADS)
4306 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4307 /* Get machine code which is patched back in later. A
4308 `call rel32' is 5 bytes long (but read 8 bytes). */
4310 savedmcodeptr = cd->mcodebase + pref->branchpos;
4311 mcode = *((ptrint *) savedmcodeptr);
4313 /* patch in `call rel32' to call the following code */
4315 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4316 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
4318 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
4320 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4322 /* move pointer to java_objectheader onto stack */
4324 #if defined(ENABLE_THREADS)
4325 /* create a virtual java_objectheader */
4327 (void) dseg_addaddress(cd, NULL); /* flcword */
4328 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
4329 disp = dseg_addaddress(cd, NULL); /* vftbl */
4331 emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP3);
4337 /* move machine code bytes and classinfo pointer into registers */
4339 M_MOV_IMM(mcode, REG_ITMP3);
4341 M_MOV_IMM(pref->ref, REG_ITMP3);
4343 M_MOV_IMM(pref->disp, REG_ITMP3);
4346 M_MOV_IMM(pref->patcher, REG_ITMP3);
4349 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
4356 return jd->code->entrypoint;
4361 * These are local overrides for various environment variables in Emacs.
4362 * Please do not remove this and leave it at the end of the file, where
4363 * Emacs will automagically detect them.
4364 * ---------------------------------------------------------------------
4367 * indent-tabs-mode: t
4371 * vim:noexpandtab:sw=4:ts=4: