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 4943 2006-05-23 08:51:33Z twisti $
48 #include "vm/jit/x86_64/arch.h"
49 #include "vm/jit/x86_64/codegen.h"
50 #include "vm/jit/x86_64/md-emit.h"
52 #include "mm/memory.h"
53 #include "native/jni.h"
54 #include "native/native.h"
55 #include "vm/builtin.h"
56 #include "vm/exceptions.h"
57 #include "vm/global.h"
58 #include "vm/loader.h"
59 #include "vm/options.h"
60 #include "vm/statistics.h"
61 #include "vm/stringlocal.h"
63 #include "vm/jit/asmpart.h"
64 #include "vm/jit/codegen-common.h"
65 #include "vm/jit/dseg.h"
66 #include "vm/jit/emit.h"
67 #include "vm/jit/jit.h"
68 #include "vm/jit/methodheader.h"
69 #include "vm/jit/parse.h"
70 #include "vm/jit/patcher.h"
71 #include "vm/jit/reg.h"
72 #include "vm/jit/replace.h"
74 #if defined(ENABLE_LSRA)
75 # include "vm/jit/allocator/lsra.h"
79 /* codegen *********************************************************************
81 Generates machine code.
83 *******************************************************************************/
85 bool codegen(jitdata *jd)
90 s4 len, s1, s2, s3, d, disp;
99 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
100 builtintable_entry *bte;
102 rplpoint *replacementpoint;
104 /* get required compiler data */
110 /* prevent compiler warnings */
122 /* space to save used callee saved registers */
124 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
125 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
127 stackframesize = rd->memuse + savedregs_num;
129 #if defined(ENABLE_THREADS)
130 /* space to save argument of monitor_enter */
132 if (checksync && (m->flags & ACC_SYNCHRONIZED))
136 /* Keep stack of non-leaf functions 16-byte aligned for calls into native */
137 /* code e.g. libc or jni (alignment problems with movaps). */
139 if (!m->isleafmethod || opt_verbosecall)
140 stackframesize |= 0x1;
142 /* create method header */
144 (void) dseg_addaddress(cd, m); /* MethodPointer */
145 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
147 #if defined(ENABLE_THREADS)
148 /* IsSync contains the offset relative to the stack pointer for the
149 argument of monitor_exit used in the exception handler. Since the
150 offset could be zero and give a wrong meaning of the flag it is
154 if (checksync && (m->flags & ACC_SYNCHRONIZED))
155 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
158 (void) dseg_adds4(cd, 0); /* IsSync */
160 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
161 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
162 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
164 (void) dseg_addlinenumbertablesize(cd);
166 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
168 /* create exception table */
170 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
171 dseg_addtarget(cd, ex->start);
172 dseg_addtarget(cd, ex->end);
173 dseg_addtarget(cd, ex->handler);
174 (void) dseg_addaddress(cd, ex->catchtype.cls);
177 /* generate method profiling code */
180 /* count frequency */
182 M_MOV_IMM(m, REG_ITMP3);
183 M_IINC_MEMBASE(REG_ITMP3, OFFSET(methodinfo, frequency));
188 /* create stack frame (if necessary) */
191 M_ASUB_IMM(stackframesize * 8, REG_SP);
193 /* save used callee saved registers */
196 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
197 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
199 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
200 p--; M_DST(rd->savfltregs[i], REG_SP, p * 8);
203 /* take arguments out of register or stack frame */
207 for (p = 0, l = 0; p < md->paramcount; p++) {
208 t = md->paramtypes[p].type;
209 var = &(rd->locals[l][t]);
211 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
215 s1 = md->params[p].regoff;
216 if (IS_INT_LNG_TYPE(t)) { /* integer args */
217 s2 = rd->argintregs[s1];
218 if (!md->params[p].inmemory) { /* register arguments */
219 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
220 M_INTMOVE(s2, var->regoff);
222 } else { /* reg arg -> spilled */
223 M_LST(s2, REG_SP, var->regoff * 8);
226 } else { /* stack arguments */
227 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
228 /* + 8 for return address */
229 M_LLD(var->regoff, REG_SP, (stackframesize + s1) * 8 + 8);
231 } else { /* stack arg -> spilled */
232 var->regoff = stackframesize + s1 + 1;
236 } else { /* floating args */
237 if (!md->params[p].inmemory) { /* register arguments */
238 s2 = rd->argfltregs[s1];
239 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
240 M_FLTMOVE(s2, var->regoff);
242 } else { /* reg arg -> spilled */
243 M_DST(s2, REG_SP, var->regoff * 8);
246 } else { /* stack arguments */
247 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
248 M_DLD(var->regoff, REG_SP, (stackframesize + s1) * 8 + 8);
251 var->regoff = stackframesize + s1 + 1;
257 /* save monitorenter argument */
259 #if defined(ENABLE_THREADS)
260 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
261 /* stack offset for monitor argument */
265 if (opt_verbosecall) {
266 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
268 for (p = 0; p < INT_ARG_CNT; p++)
269 M_LST(rd->argintregs[p], REG_SP, p * 8);
271 for (p = 0; p < FLT_ARG_CNT; p++)
272 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
274 s1 += INT_ARG_CNT + FLT_ARG_CNT;
277 /* decide which monitor enter function to call */
279 if (m->flags & ACC_STATIC) {
280 M_MOV_IMM(m->class, REG_ITMP1);
281 M_AST(REG_ITMP1, REG_SP, s1 * 8);
282 M_INTMOVE(REG_ITMP1, rd->argintregs[0]);
283 M_MOV_IMM(BUILTIN_staticmonitorenter, REG_ITMP1);
287 M_TEST(rd->argintregs[0]);
289 codegen_add_nullpointerexception_ref(cd);
290 M_AST(rd->argintregs[0], REG_SP, s1 * 8);
291 M_MOV_IMM(BUILTIN_monitorenter, REG_ITMP1);
295 if (opt_verbosecall) {
296 for (p = 0; p < INT_ARG_CNT; p++)
297 M_LLD(rd->argintregs[p], REG_SP, p * 8);
299 for (p = 0; p < FLT_ARG_CNT; p++)
300 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
302 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
308 /* Copy argument registers to stack and call trace function with
309 pointer to arguments on stack. */
311 if (opt_verbosecall) {
312 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
314 /* save integer argument registers */
316 for (p = 0; p < INT_ARG_CNT; p++)
317 M_LST(rd->argintregs[p], REG_SP, (1 + p) * 8);
319 /* save float argument registers */
321 for (p = 0; p < FLT_ARG_CNT; p++)
322 M_DST(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
324 /* save temporary registers for leaf methods */
326 if (m->isleafmethod) {
327 for (p = 0; p < INT_TMP_CNT; p++)
328 M_LST(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
330 for (p = 0; p < FLT_TMP_CNT; p++)
331 M_DST(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
334 /* show integer hex code for float arguments */
336 for (p = 0, l = 0; p < md->paramcount && p < INT_ARG_CNT; p++) {
337 /* If the paramtype is a float, we have to right shift all
338 following integer registers. */
340 if (IS_FLT_DBL_TYPE(md->paramtypes[p].type)) {
341 for (s1 = INT_ARG_CNT - 2; s1 >= p; s1--)
342 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
344 emit_movd_freg_reg(cd, rd->argfltregs[l], rd->argintregs[p]);
349 M_MOV_IMM(m, REG_ITMP2);
350 M_AST(REG_ITMP2, REG_SP, 0 * 8);
351 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
354 /* restore integer argument registers */
356 for (p = 0; p < INT_ARG_CNT; p++)
357 M_LLD(rd->argintregs[p], REG_SP, (1 + p) * 8);
359 /* restore float argument registers */
361 for (p = 0; p < FLT_ARG_CNT; p++)
362 M_DLD(rd->argfltregs[p], REG_SP, (1 + INT_ARG_CNT + p) * 8);
364 /* restore temporary registers for leaf methods */
366 if (m->isleafmethod) {
367 for (p = 0; p < INT_TMP_CNT; p++)
368 M_LLD(rd->tmpintregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + p) * 8);
370 for (p = 0; p < FLT_TMP_CNT; p++)
371 M_DLD(rd->tmpfltregs[p], REG_SP, (1 + INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + p) * 8);
374 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT + INT_TMP_CNT + FLT_TMP_CNT + 1 + 1) * 8, REG_SP);
376 #endif /* !defined(NDEBUG) */
380 /* end of header generation */
382 replacementpoint = jd->code->rplpoints;
384 /* walk through all basic blocks */
386 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
388 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
390 if (bptr->flags >= BBREACHED) {
392 /* branch resolving */
395 for (bref = bptr->branchrefs; bref != NULL; bref = bref->next) {
396 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
401 /* handle replacement points */
403 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
404 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
408 assert(cd->lastmcodeptr <= cd->mcodeptr);
409 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
412 /* copy interface registers to their destination */
418 /* generate basicblock profiling code */
421 /* count frequency */
423 M_MOV_IMM(m->bbfrequency, REG_ITMP2);
424 M_IINC_MEMBASE(REG_ITMP2, bptr->debug_nr * 4);
426 /* if this is an exception handler, start profiling again */
428 if (bptr->type == BBTYPE_EXH)
432 #if defined(ENABLE_LSRA)
434 while (src != NULL) {
436 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
437 if (bptr->type == BBTYPE_SBR) {
438 /* d = reg_of_var(rd, src, REG_ITMP1); */
439 if (!(src->flags & INMEMORY))
444 emit_store(jd, NULL, src, d);
446 } else if (bptr->type == BBTYPE_EXH) {
447 /* d = reg_of_var(rd, src, REG_ITMP1); */
448 if (!(src->flags & INMEMORY))
452 M_INTMOVE(REG_ITMP1, d);
453 emit_store(jd, NULL, src, d);
462 while (src != NULL) {
464 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
465 if (bptr->type == BBTYPE_SBR) {
466 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
468 emit_store(jd, NULL, src, d);
470 } else if (bptr->type == BBTYPE_EXH) {
471 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
472 M_INTMOVE(REG_ITMP1, d);
473 emit_store(jd, NULL, src, d);
477 d = codegen_reg_of_var(rd, 0, src, REG_ITMP1);
478 if ((src->varkind != STACKVAR)) {
480 if (IS_FLT_DBL_TYPE(s2)) {
481 s1 = rd->interfaces[len][s2].regoff;
483 if (!(rd->interfaces[len][s2].flags & INMEMORY))
486 M_DLD(d, REG_SP, s1 * 8);
488 emit_store(jd, NULL, src, d);
491 s1 = rd->interfaces[len][s2].regoff;
493 if (!(rd->interfaces[len][s2].flags & INMEMORY))
496 M_LLD(d, REG_SP, s1 * 8);
498 emit_store(jd, NULL, src, d);
504 #if defined(ENABLE_LSRA)
507 /* walk through all instructions */
513 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
514 if (iptr->line != currentline) {
515 dseg_addlinenumber(cd, iptr->line);
516 currentline = iptr->line;
519 MCODECHECK(1024); /* 1KB should be enough */
522 case ICMD_INLINE_START: /* internal ICMDs */
523 case ICMD_INLINE_END:
526 case ICMD_NOP: /* ... ==> ... */
529 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
531 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
534 codegen_add_nullpointerexception_ref(cd);
537 /* constant operations ************************************************/
539 case ICMD_ICONST: /* ... ==> ..., constant */
540 /* op1 = 0, val.i = constant */
542 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
543 ICONST(d, iptr->val.i);
544 emit_store(jd, iptr, iptr->dst, d);
547 case ICMD_LCONST: /* ... ==> ..., constant */
548 /* op1 = 0, val.l = constant */
550 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
551 LCONST(d, iptr->val.l);
552 emit_store(jd, iptr, iptr->dst, d);
555 case ICMD_FCONST: /* ... ==> ..., constant */
556 /* op1 = 0, val.f = constant */
558 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
559 disp = dseg_addfloat(cd, iptr->val.f);
560 emit_movdl_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + ((d > 7) ? 9 : 8)) - (s8) cd->mcodebase) + disp, d);
561 emit_store(jd, iptr, iptr->dst, d);
564 case ICMD_DCONST: /* ... ==> ..., constant */
565 /* op1 = 0, val.d = constant */
567 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
568 disp = dseg_adddouble(cd, iptr->val.d);
569 emit_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, d);
570 emit_store(jd, iptr, iptr->dst, d);
573 case ICMD_ACONST: /* ... ==> ..., constant */
574 /* op1 = 0, val.a = constant */
576 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
578 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
579 /* PROFILE_CYCLE_STOP; */
581 codegen_addpatchref(cd, PATCHER_aconst,
582 ICMD_ACONST_UNRESOLVED_CLASSREF(iptr), 0);
584 if (opt_showdisassemble) {
585 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
588 /* PROFILE_CYCLE_START; */
593 if (iptr->val.a == 0)
596 M_MOV_IMM(iptr->val.a, d);
598 emit_store(jd, iptr, iptr->dst, d);
602 /* load/store operations **********************************************/
604 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
605 /* op1 = local variable */
607 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
608 if ((iptr->dst->varkind == LOCALVAR) &&
609 (iptr->dst->varnum == iptr->op1))
611 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
612 if (var->flags & INMEMORY)
613 M_ILD(d, REG_SP, var->regoff * 8);
615 M_INTMOVE(var->regoff, d);
616 emit_store(jd, iptr, iptr->dst, d);
619 case ICMD_LLOAD: /* ... ==> ..., content of local variable */
620 case ICMD_ALOAD: /* op1 = local variable */
622 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
623 if ((iptr->dst->varkind == LOCALVAR) &&
624 (iptr->dst->varnum == iptr->op1))
626 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
627 if (var->flags & INMEMORY)
628 M_LLD(d, REG_SP, var->regoff * 8);
630 M_INTMOVE(var->regoff, d);
631 emit_store(jd, iptr, iptr->dst, d);
634 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
635 /* op1 = local variable */
637 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
638 if ((iptr->dst->varkind == LOCALVAR) &&
639 (iptr->dst->varnum == iptr->op1))
641 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
642 if (var->flags & INMEMORY)
643 M_FLD(d, REG_SP, var->regoff * 8);
645 M_FLTMOVE(var->regoff, d);
646 emit_store(jd, iptr, iptr->dst, d);
649 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
650 /* op1 = local variable */
652 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
653 if ((iptr->dst->varkind == LOCALVAR) &&
654 (iptr->dst->varnum == iptr->op1))
656 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
657 if (var->flags & INMEMORY)
658 M_DLD(d, REG_SP, var->regoff * 8);
660 M_FLTMOVE(var->regoff, d);
661 emit_store(jd, iptr, iptr->dst, d);
664 case ICMD_ISTORE: /* ..., value ==> ... */
665 /* op1 = local variable */
667 if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
669 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
670 if (var->flags & INMEMORY) {
671 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
672 M_IST(s1, REG_SP, var->regoff * 8);
674 s1 = emit_load_s1(jd, iptr, src, var->regoff);
675 M_INTMOVE(s1, var->regoff);
679 case ICMD_LSTORE: /* ..., value ==> ... */
680 case ICMD_ASTORE: /* op1 = local variable */
682 if ((src->varkind == LOCALVAR) && (src->varnum == iptr->op1))
684 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
685 if (var->flags & INMEMORY) {
686 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
687 M_LST(s1, REG_SP, var->regoff * 8);
689 s1 = emit_load_s1(jd, iptr, src, var->regoff);
690 M_INTMOVE(s1, var->regoff);
694 case ICMD_FSTORE: /* ..., value ==> ... */
695 /* op1 = local variable */
697 if ((src->varkind == LOCALVAR) &&
698 (src->varnum == iptr->op1)) {
701 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
702 if (var->flags & INMEMORY) {
703 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
704 M_FST(s1, REG_SP, var->regoff * 8);
706 s1 = emit_load_s1(jd, iptr, src, var->regoff);
707 M_FLTMOVE(s1, var->regoff);
711 case ICMD_DSTORE: /* ..., value ==> ... */
712 /* op1 = local variable */
714 if ((src->varkind == LOCALVAR) &&
715 (src->varnum == iptr->op1)) {
718 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
719 if (var->flags & INMEMORY) {
720 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
721 M_DST(s1, REG_SP, var->regoff * 8);
723 s1 = emit_load_s1(jd, iptr, src, var->regoff);
724 M_FLTMOVE(s1, var->regoff);
729 /* pop/dup/swap operations ********************************************/
731 /* attention: double and longs are only one entry in CACAO ICMDs */
733 case ICMD_POP: /* ..., value ==> ... */
734 case ICMD_POP2: /* ..., value, value ==> ... */
737 case ICMD_DUP: /* ..., a ==> ..., a, a */
738 M_COPY(src, iptr->dst);
741 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
743 M_COPY(src, iptr->dst);
744 M_COPY(src->prev, iptr->dst->prev);
745 M_COPY(iptr->dst, iptr->dst->prev->prev);
748 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
750 M_COPY(src, iptr->dst);
751 M_COPY(src->prev, iptr->dst->prev);
752 M_COPY(src->prev->prev, iptr->dst->prev->prev);
753 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
756 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
758 M_COPY(src, iptr->dst);
759 M_COPY(src->prev, iptr->dst->prev);
762 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
764 M_COPY(src, iptr->dst);
765 M_COPY(src->prev, iptr->dst->prev);
766 M_COPY(src->prev->prev, iptr->dst->prev->prev);
767 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
768 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
771 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
773 M_COPY(src, iptr->dst);
774 M_COPY(src->prev, iptr->dst->prev);
775 M_COPY(src->prev->prev, iptr->dst->prev->prev);
776 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
777 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
778 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
781 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
783 M_COPY(src, iptr->dst->prev);
784 M_COPY(src->prev, iptr->dst);
788 /* integer operations *************************************************/
790 case ICMD_INEG: /* ..., value ==> ..., - value */
792 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
793 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
796 emit_store(jd, iptr, iptr->dst, d);
799 case ICMD_LNEG: /* ..., value ==> ..., - value */
801 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
802 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
805 emit_store(jd, iptr, iptr->dst, d);
808 case ICMD_I2L: /* ..., value ==> ..., value */
810 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
811 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
813 emit_store(jd, iptr, iptr->dst, d);
816 case ICMD_L2I: /* ..., value ==> ..., value */
818 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
819 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
821 emit_store(jd, iptr, iptr->dst, d);
824 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
826 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
827 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
829 emit_store(jd, iptr, iptr->dst, d);
832 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
834 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
835 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
837 emit_store(jd, iptr, iptr->dst, d);
840 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
842 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
843 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
845 emit_store(jd, iptr, iptr->dst, d);
849 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
851 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
852 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
853 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
860 emit_store(jd, iptr, iptr->dst, d);
863 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
864 /* val.i = constant */
866 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
867 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
869 M_IADD_IMM(iptr->val.i, d);
870 emit_store(jd, iptr, iptr->dst, d);
873 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
875 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
876 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
877 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
884 emit_store(jd, iptr, iptr->dst, d);
887 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
888 /* val.l = constant */
890 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
891 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
893 if (IS_IMM32(iptr->val.l))
894 M_LADD_IMM(iptr->val.l, d);
896 M_MOV_IMM(iptr->val.l, REG_ITMP2);
897 M_LADD(REG_ITMP2, d);
899 emit_store(jd, iptr, iptr->dst, d);
902 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
904 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
905 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
906 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
908 M_INTMOVE(s1, REG_ITMP1);
909 M_ISUB(s2, REG_ITMP1);
910 M_INTMOVE(REG_ITMP1, d);
915 emit_store(jd, iptr, iptr->dst, d);
918 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
919 /* val.i = constant */
921 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
922 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
924 M_ISUB_IMM(iptr->val.i, d);
925 emit_store(jd, iptr, iptr->dst, d);
928 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
930 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
931 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
932 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
934 M_INTMOVE(s1, REG_ITMP1);
935 M_LSUB(s2, REG_ITMP1);
936 M_INTMOVE(REG_ITMP1, d);
941 emit_store(jd, iptr, iptr->dst, d);
944 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
945 /* val.l = constant */
947 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
948 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
950 if (IS_IMM32(iptr->val.l))
951 M_LSUB_IMM(iptr->val.l, d);
953 M_MOV_IMM(iptr->val.l, REG_ITMP2);
954 M_LSUB(REG_ITMP2, d);
956 emit_store(jd, iptr, iptr->dst, d);
959 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
961 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
962 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
963 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
970 emit_store(jd, iptr, iptr->dst, d);
973 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
974 /* val.i = constant */
976 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
977 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
978 if (iptr->val.i == 2) {
982 M_IMUL_IMM(s1, iptr->val.i, d);
983 emit_store(jd, iptr, iptr->dst, d);
986 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
988 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
989 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
990 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
997 emit_store(jd, iptr, iptr->dst, d);
1000 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
1001 /* val.l = constant */
1003 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1004 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1005 if (IS_IMM32(iptr->val.l))
1006 M_LMUL_IMM(s1, iptr->val.l, d);
1008 M_MOV_IMM(iptr->val.l, REG_ITMP2);
1010 M_LMUL(REG_ITMP2, d);
1012 emit_store(jd, iptr, iptr->dst, d);
1015 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1017 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1018 if (src->prev->flags & INMEMORY)
1019 M_ILD(RAX, REG_SP, src->prev->regoff * 8);
1021 M_INTMOVE(src->prev->regoff, RAX);
1023 if (src->flags & INMEMORY)
1024 M_ILD(REG_ITMP3, REG_SP, src->regoff * 8);
1026 M_INTMOVE(src->regoff, REG_ITMP3);
1031 codegen_add_arithmeticexception_ref(cd);
1034 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1035 emit_jcc(cd, CC_NE, 4 + 6);
1036 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
1037 emit_jcc(cd, CC_E, 3 + 1 + 3); /* 6 bytes */
1039 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1041 emit_idivl_reg(cd, REG_ITMP3);
1043 if (iptr->dst->flags & INMEMORY) {
1044 emit_mov_reg_membase(cd, RAX, REG_SP, iptr->dst->regoff * 8);
1045 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1048 M_INTMOVE(RAX, iptr->dst->regoff);
1050 if (iptr->dst->regoff != RDX) {
1051 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1056 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1058 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1059 if (src->prev->flags & INMEMORY)
1060 M_ILD(RAX, REG_SP, src->prev->regoff * 8);
1062 M_INTMOVE(src->prev->regoff, RAX);
1064 if (src->flags & INMEMORY)
1065 M_ILD(REG_ITMP3, REG_SP, src->regoff * 8);
1067 M_INTMOVE(src->regoff, REG_ITMP3);
1072 codegen_add_arithmeticexception_ref(cd);
1075 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1077 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
1078 emit_jcc(cd, CC_NE, 2 + 4 + 6);
1081 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
1082 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
1083 emit_jcc(cd, CC_E, 1 + 3); /* 6 bytes */
1086 emit_idivl_reg(cd, REG_ITMP3);
1088 if (iptr->dst->flags & INMEMORY) {
1089 emit_mov_reg_membase(cd, RDX, REG_SP, iptr->dst->regoff * 8);
1090 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1093 M_INTMOVE(RDX, iptr->dst->regoff);
1095 if (iptr->dst->regoff != RDX) {
1096 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
1101 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
1102 /* val.i = constant */
1104 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1105 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1106 M_INTMOVE(s1, REG_ITMP1);
1107 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1108 emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1109 emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
1110 emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->val.i, REG_ITMP1);
1111 emit_mov_reg_reg(cd, REG_ITMP1, d);
1112 emit_store(jd, iptr, iptr->dst, d);
1115 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1116 /* val.i = constant */
1118 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1119 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1120 M_INTMOVE(s1, REG_ITMP1);
1121 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1122 emit_leal_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1123 emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1124 emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->val.i), REG_ITMP2);
1125 emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1126 emit_mov_reg_reg(cd, REG_ITMP1, d);
1127 emit_store(jd, iptr, iptr->dst, d);
1131 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1133 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1135 if (src->prev->flags & INMEMORY)
1136 M_LLD(RAX, REG_SP, src->prev->regoff * 8);
1138 M_INTMOVE(src->prev->regoff, RAX);
1140 if (src->flags & INMEMORY)
1141 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1143 M_INTMOVE(src->regoff, REG_ITMP3);
1148 codegen_add_arithmeticexception_ref(cd);
1151 /* check as described in jvm spec */
1152 disp = dseg_adds8(cd, 0x8000000000000000LL);
1153 M_LCMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, RAX);
1155 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1156 M_BEQ(3 + 2 + 3); /* 6 bytes */
1158 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1160 emit_idiv_reg(cd, REG_ITMP3);
1162 if (iptr->dst->flags & INMEMORY) {
1163 M_LST(RAX, REG_SP, iptr->dst->regoff * 8);
1164 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1167 M_INTMOVE(RAX, iptr->dst->regoff);
1169 if (iptr->dst->regoff != RDX) {
1170 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1175 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1177 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1178 if (src->prev->flags & INMEMORY)
1179 M_LLD(REG_ITMP1, REG_SP, src->prev->regoff * 8);
1181 M_INTMOVE(src->prev->regoff, REG_ITMP1);
1183 if (src->flags & INMEMORY)
1184 M_LLD(REG_ITMP3, REG_SP, src->regoff * 8);
1186 M_INTMOVE(src->regoff, REG_ITMP3);
1191 codegen_add_arithmeticexception_ref(cd);
1194 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1196 /* check as described in jvm spec */
1197 disp = dseg_adds8(cd, 0x8000000000000000LL);
1198 M_LCMP_MEMBASE(RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP1);
1202 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
1204 M_LXOR(RDX, RDX); /* 3 bytes */
1205 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1206 M_BEQ(2 + 3); /* 6 bytes */
1209 emit_idiv_reg(cd, REG_ITMP3);
1211 if (iptr->dst->flags & INMEMORY) {
1212 M_LST(RDX, REG_SP, iptr->dst->regoff * 8);
1213 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1216 M_INTMOVE(RDX, iptr->dst->regoff);
1218 if (iptr->dst->regoff != RDX) {
1219 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1224 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1225 /* val.i = constant */
1227 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1228 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1229 M_INTMOVE(s1, REG_ITMP1);
1230 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1231 emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->val.i) - 1, REG_ITMP2);
1232 emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
1233 emit_shift_imm_reg(cd, SHIFT_SAR, iptr->val.i, REG_ITMP1);
1234 emit_mov_reg_reg(cd, REG_ITMP1, d);
1235 emit_store(jd, iptr, iptr->dst, d);
1238 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1239 /* val.l = constant */
1241 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1242 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1243 M_INTMOVE(s1, REG_ITMP1);
1244 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1245 emit_lea_membase_reg(cd, REG_ITMP1, iptr->val.i, REG_ITMP2);
1246 emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1247 emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->val.i), REG_ITMP2);
1248 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1249 emit_mov_reg_reg(cd, REG_ITMP1, d);
1250 emit_store(jd, iptr, iptr->dst, d);
1253 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1255 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1256 emit_ishift(cd, SHIFT_SHL, src, iptr);
1259 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1260 /* val.i = constant */
1262 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1263 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1265 M_ISLL_IMM(iptr->val.i, d);
1266 emit_store(jd, iptr, iptr->dst, d);
1269 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1271 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1272 emit_ishift(cd, SHIFT_SAR, src, iptr);
1275 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1276 /* val.i = constant */
1278 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1279 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1281 M_ISRA_IMM(iptr->val.i, d);
1282 emit_store(jd, iptr, iptr->dst, d);
1285 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1287 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1288 emit_ishift(cd, SHIFT_SHR, src, iptr);
1291 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1292 /* val.i = constant */
1294 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1295 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1297 M_ISRL_IMM(iptr->val.i, d);
1298 emit_store(jd, iptr, iptr->dst, d);
1301 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1303 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1304 emit_lshift(cd, SHIFT_SHL, src, iptr);
1307 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1308 /* val.i = constant */
1310 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1311 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1313 M_LSLL_IMM(iptr->val.i, d);
1314 emit_store(jd, iptr, iptr->dst, d);
1317 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1319 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1320 emit_lshift(cd, SHIFT_SAR, src, iptr);
1323 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1324 /* val.i = constant */
1326 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1327 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1329 M_LSRA_IMM(iptr->val.i, d);
1330 emit_store(jd, iptr, iptr->dst, d);
1333 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1335 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_NULL);
1336 emit_lshift(cd, SHIFT_SHR, src, iptr);
1339 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1340 /* val.l = constant */
1342 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1343 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1345 M_LSRL_IMM(iptr->val.i, d);
1346 emit_store(jd, iptr, iptr->dst, d);
1349 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1351 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1352 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1353 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1360 emit_store(jd, iptr, iptr->dst, d);
1363 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1364 /* val.i = constant */
1366 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1367 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1369 M_IAND_IMM(iptr->val.i, d);
1370 emit_store(jd, iptr, iptr->dst, d);
1373 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1375 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1376 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1377 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1384 emit_store(jd, iptr, iptr->dst, d);
1387 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1388 /* val.l = constant */
1390 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1391 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1393 if (IS_IMM32(iptr->val.l))
1394 M_LAND_IMM(iptr->val.l, d);
1396 M_MOV_IMM(iptr->val.l, REG_ITMP2);
1397 M_LAND(REG_ITMP2, d);
1399 emit_store(jd, iptr, iptr->dst, d);
1402 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1404 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1405 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1406 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1413 emit_store(jd, iptr, iptr->dst, d);
1416 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1417 /* val.i = constant */
1419 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1420 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1422 M_IOR_IMM(iptr->val.i, d);
1423 emit_store(jd, iptr, iptr->dst, d);
1426 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1428 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1429 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1430 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1437 emit_store(jd, iptr, iptr->dst, d);
1440 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1441 /* val.l = constant */
1443 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1444 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1446 if (IS_IMM32(iptr->val.l))
1447 M_LOR_IMM(iptr->val.l, d);
1449 M_MOV_IMM(iptr->val.l, REG_ITMP2);
1450 M_LOR(REG_ITMP2, d);
1452 emit_store(jd, iptr, iptr->dst, d);
1455 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1457 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1458 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1459 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1466 emit_store(jd, iptr, iptr->dst, d);
1469 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1470 /* val.i = constant */
1472 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1473 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1475 M_IXOR_IMM(iptr->val.i, d);
1476 emit_store(jd, iptr, iptr->dst, d);
1479 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1481 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1482 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1483 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
1490 emit_store(jd, iptr, iptr->dst, d);
1493 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1494 /* val.l = constant */
1496 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1497 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1499 if (IS_IMM32(iptr->val.l))
1500 M_LXOR_IMM(iptr->val.l, d);
1502 M_MOV_IMM(iptr->val.l, REG_ITMP2);
1503 M_LXOR(REG_ITMP2, d);
1505 emit_store(jd, iptr, iptr->dst, d);
1509 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1510 /* op1 = variable, val.i = constant */
1512 var = &(rd->locals[iptr->op1][TYPE_INT]);
1513 if (var->flags & INMEMORY) {
1515 M_ILD(s1, REG_SP, var->regoff * 8);
1519 /* Using inc and dec is not faster than add (tested with
1522 M_IADD_IMM(iptr->val.i, s1);
1524 if (var->flags & INMEMORY)
1525 M_IST(s1, REG_SP, var->regoff * 8);
1529 /* floating operations ************************************************/
1531 case ICMD_FNEG: /* ..., value ==> ..., - value */
1533 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1534 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1535 disp = dseg_adds4(cd, 0x80000000);
1537 emit_movss_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1538 emit_xorps_reg_reg(cd, REG_FTMP2, d);
1539 emit_store(jd, iptr, iptr->dst, d);
1542 case ICMD_DNEG: /* ..., value ==> ..., - value */
1544 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1545 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1546 disp = dseg_adds8(cd, 0x8000000000000000);
1548 emit_movd_membase_reg(cd, RIP, -(((s8) cd->mcodeptr + 9) - (s8) cd->mcodebase) + disp, REG_FTMP2);
1549 emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1550 emit_store(jd, iptr, iptr->dst, d);
1553 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1555 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1556 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1557 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1564 emit_store(jd, iptr, iptr->dst, d);
1567 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1569 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1570 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1571 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1578 emit_store(jd, iptr, iptr->dst, d);
1581 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1583 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1584 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1585 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1587 M_FLTMOVE(s2, REG_FTMP2);
1592 emit_store(jd, iptr, iptr->dst, d);
1595 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1597 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1598 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1599 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1601 M_FLTMOVE(s2, REG_FTMP2);
1606 emit_store(jd, iptr, iptr->dst, d);
1609 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1611 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1612 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1613 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1620 emit_store(jd, iptr, iptr->dst, d);
1623 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1625 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1626 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1627 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1634 emit_store(jd, iptr, iptr->dst, d);
1637 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1639 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1640 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1641 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1643 M_FLTMOVE(s2, REG_FTMP2);
1648 emit_store(jd, iptr, iptr->dst, d);
1651 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1653 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1654 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1655 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1657 M_FLTMOVE(s2, REG_FTMP2);
1662 emit_store(jd, iptr, iptr->dst, d);
1665 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1667 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1668 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1670 emit_store(jd, iptr, iptr->dst, d);
1673 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1675 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1676 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1678 emit_store(jd, iptr, iptr->dst, d);
1681 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1683 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1684 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1686 emit_store(jd, iptr, iptr->dst, d);
1689 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1691 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1692 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
1694 emit_store(jd, iptr, iptr->dst, d);
1697 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1699 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1700 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1702 M_ICMP_IMM(0x80000000, d); /* corner cases */
1703 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1704 ((REG_RESULT == d) ? 0 : 3);
1706 M_FLTMOVE(s1, REG_FTMP1);
1707 M_MOV_IMM(asm_builtin_f2i, REG_ITMP2);
1709 M_INTMOVE(REG_RESULT, d);
1710 emit_store(jd, iptr, iptr->dst, d);
1713 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1715 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1716 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1718 M_ICMP_IMM(0x80000000, d); /* corner cases */
1719 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1720 ((REG_RESULT == d) ? 0 : 3);
1722 M_FLTMOVE(s1, REG_FTMP1);
1723 M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1725 M_INTMOVE(REG_RESULT, d);
1726 emit_store(jd, iptr, iptr->dst, d);
1729 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1731 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1732 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1734 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1735 M_LCMP(REG_ITMP2, d); /* corner cases */
1736 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1737 ((REG_RESULT == d) ? 0 : 3);
1739 M_FLTMOVE(s1, REG_FTMP1);
1740 M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1742 M_INTMOVE(REG_RESULT, d);
1743 emit_store(jd, iptr, iptr->dst, d);
1746 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1748 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1749 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
1751 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1752 M_LCMP(REG_ITMP2, d); /* corner cases */
1753 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1754 ((REG_RESULT == d) ? 0 : 3);
1756 M_FLTMOVE(s1, REG_FTMP1);
1757 M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1759 M_INTMOVE(REG_RESULT, d);
1760 emit_store(jd, iptr, iptr->dst, d);
1763 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1765 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1766 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1768 emit_store(jd, iptr, iptr->dst, d);
1771 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1773 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
1774 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1776 emit_store(jd, iptr, iptr->dst, d);
1779 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1780 /* == => 0, < => 1, > => -1 */
1782 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1783 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1784 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1786 M_MOV_IMM(1, REG_ITMP1);
1787 M_MOV_IMM(-1, REG_ITMP2);
1788 emit_ucomiss_reg_reg(cd, s1, s2);
1789 M_CMOVB(REG_ITMP1, d);
1790 M_CMOVA(REG_ITMP2, d);
1791 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1792 emit_store(jd, iptr, iptr->dst, d);
1795 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1796 /* == => 0, < => 1, > => -1 */
1798 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1799 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1800 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1802 M_MOV_IMM(1, REG_ITMP1);
1803 M_MOV_IMM(-1, REG_ITMP2);
1804 emit_ucomiss_reg_reg(cd, s1, s2);
1805 M_CMOVB(REG_ITMP1, d);
1806 M_CMOVA(REG_ITMP2, d);
1807 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1808 emit_store(jd, iptr, iptr->dst, d);
1811 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1812 /* == => 0, < => 1, > => -1 */
1814 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1815 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1816 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1818 M_MOV_IMM(1, REG_ITMP1);
1819 M_MOV_IMM(-1, REG_ITMP2);
1820 emit_ucomisd_reg_reg(cd, s1, s2);
1821 M_CMOVB(REG_ITMP1, d);
1822 M_CMOVA(REG_ITMP2, d);
1823 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1824 emit_store(jd, iptr, iptr->dst, d);
1827 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1828 /* == => 0, < => 1, > => -1 */
1830 s1 = emit_load_s1(jd, iptr, src->prev, REG_FTMP1);
1831 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
1832 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1834 M_MOV_IMM(1, REG_ITMP1);
1835 M_MOV_IMM(-1, REG_ITMP2);
1836 emit_ucomisd_reg_reg(cd, s1, s2);
1837 M_CMOVB(REG_ITMP1, d);
1838 M_CMOVA(REG_ITMP2, d);
1839 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1840 emit_store(jd, iptr, iptr->dst, d);
1844 /* memory operations **************************************************/
1846 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1848 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
1849 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1850 gen_nullptr_check(s1);
1851 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1852 emit_store(jd, iptr, iptr->dst, d);
1855 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1857 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1858 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1859 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1860 if (iptr->op1 == 0) {
1861 gen_nullptr_check(s1);
1864 emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
1865 emit_store(jd, iptr, iptr->dst, d);
1868 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1870 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1871 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1872 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1873 if (iptr->op1 == 0) {
1874 gen_nullptr_check(s1);
1877 emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
1878 emit_store(jd, iptr, iptr->dst, d);
1881 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1883 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1884 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1885 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1886 if (iptr->op1 == 0) {
1887 gen_nullptr_check(s1);
1890 emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
1891 emit_store(jd, iptr, iptr->dst, d);
1894 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1896 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1897 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1898 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1899 if (iptr->op1 == 0) {
1900 gen_nullptr_check(s1);
1903 emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
1904 emit_store(jd, iptr, iptr->dst, d);
1907 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1909 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1910 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1911 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1912 if (iptr->op1 == 0) {
1913 gen_nullptr_check(s1);
1916 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1917 emit_store(jd, iptr, iptr->dst, d);
1920 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1922 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1923 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1924 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1925 if (iptr->op1 == 0) {
1926 gen_nullptr_check(s1);
1929 emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1930 emit_store(jd, iptr, iptr->dst, d);
1933 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1935 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1936 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1937 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP3);
1938 if (iptr->op1 == 0) {
1939 gen_nullptr_check(s1);
1942 emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1943 emit_store(jd, iptr, iptr->dst, d);
1946 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1948 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
1949 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
1950 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
1951 if (iptr->op1 == 0) {
1952 gen_nullptr_check(s1);
1955 emit_mov_memindex_reg(cd, OFFSET(java_objectarray, data[0]), s1, s2, 3, d);
1956 emit_store(jd, iptr, iptr->dst, d);
1960 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1962 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
1963 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
1964 if (iptr->op1 == 0) {
1965 gen_nullptr_check(s1);
1968 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
1969 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1972 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1974 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
1975 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
1976 if (iptr->op1 == 0) {
1977 gen_nullptr_check(s1);
1980 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
1981 emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
1984 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1986 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
1987 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
1988 if (iptr->op1 == 0) {
1989 gen_nullptr_check(s1);
1992 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
1993 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1996 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1998 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
1999 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2000 if (iptr->op1 == 0) {
2001 gen_nullptr_check(s1);
2004 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2005 emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
2008 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
2010 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2011 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2012 if (iptr->op1 == 0) {
2013 gen_nullptr_check(s1);
2016 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2017 emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
2020 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
2022 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2023 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2024 if (iptr->op1 == 0) {
2025 gen_nullptr_check(s1);
2028 s3 = emit_load_s3(jd, iptr, src, REG_FTMP3);
2029 emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
2032 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
2034 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2035 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2036 if (iptr->op1 == 0) {
2037 gen_nullptr_check(s1);
2040 s3 = emit_load_s3(jd, iptr, src, REG_FTMP3);
2041 emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2044 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2046 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2047 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2048 if (iptr->op1 == 0) {
2049 gen_nullptr_check(s1);
2052 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2054 M_MOV(s1, rd->argintregs[0]);
2055 M_MOV(s3, rd->argintregs[1]);
2056 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2060 codegen_add_arraystoreexception_ref(cd);
2062 s1 = emit_load_s1(jd, iptr, src->prev->prev, REG_ITMP1);
2063 s2 = emit_load_s2(jd, iptr, src->prev, REG_ITMP2);
2064 s3 = emit_load_s3(jd, iptr, src, REG_ITMP3);
2065 emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2069 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2071 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2072 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2073 if (iptr->op1 == 0) {
2074 gen_nullptr_check(s1);
2077 emit_movb_imm_memindex(cd, iptr->val.i, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2080 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2082 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2083 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2084 if (iptr->op1 == 0) {
2085 gen_nullptr_check(s1);
2088 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_chararray, data[0]), s1, s2, 1);
2091 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2093 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2094 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2095 if (iptr->op1 == 0) {
2096 gen_nullptr_check(s1);
2099 emit_movw_imm_memindex(cd, iptr->val.i, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2102 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2104 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2105 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2106 if (iptr->op1 == 0) {
2107 gen_nullptr_check(s1);
2110 emit_movl_imm_memindex(cd, iptr->val.i, OFFSET(java_intarray, data[0]), s1, s2, 2);
2113 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2115 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2116 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2117 if (iptr->op1 == 0) {
2118 gen_nullptr_check(s1);
2122 if (IS_IMM32(iptr->val.l)) {
2123 emit_mov_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2125 emit_movl_imm_memindex(cd, (u4) (iptr->val.l & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2126 emit_movl_imm_memindex(cd, (u4) (iptr->val.l >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2130 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2132 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2133 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2134 if (iptr->op1 == 0) {
2135 gen_nullptr_check(s1);
2138 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2142 case ICMD_GETSTATIC: /* ... ==> ..., value */
2143 /* op1 = type, val.a = field address */
2145 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2146 disp = dseg_addaddress(cd, NULL);
2148 /* PROFILE_CYCLE_STOP; */
2150 codegen_addpatchref(cd, PATCHER_get_putstatic,
2151 INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
2153 if (opt_showdisassemble) {
2154 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2157 /* PROFILE_CYCLE_START; */
2160 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2162 disp = dseg_addaddress(cd, &(fi->value));
2164 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2167 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2169 if (opt_showdisassemble) {
2170 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2173 PROFILE_CYCLE_START;
2177 /* This approach is much faster than moving the field
2178 address inline into a register. */
2180 M_ALD(REG_ITMP1, RIP, -(((ptrint) cd->mcodeptr + 7) -
2181 (ptrint) cd->mcodebase) + disp);
2183 switch (iptr->op1) {
2185 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2186 M_ILD(d, REG_ITMP1, 0);
2190 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
2191 M_LLD(d, REG_ITMP1, 0);
2194 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2195 M_FLD(d, REG_ITMP1, 0);
2198 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2199 M_DLD(d, REG_ITMP1, 0);
2202 emit_store(jd, iptr, iptr->dst, d);
2205 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2206 /* op1 = type, val.a = field address */
2208 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2209 disp = dseg_addaddress(cd, NULL);
2211 /* PROFILE_CYCLE_STOP; */
2213 codegen_addpatchref(cd, PATCHER_get_putstatic,
2214 INSTRUCTION_UNRESOLVED_FIELD(iptr), disp);
2216 if (opt_showdisassemble) {
2217 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2220 /* PROFILE_CYCLE_START; */
2223 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr);
2225 disp = dseg_addaddress(cd, &(fi->value));
2227 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2230 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2232 if (opt_showdisassemble) {
2233 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2236 PROFILE_CYCLE_START;
2240 /* This approach is much faster than moving the field
2241 address inline into a register. */
2243 M_ALD(REG_ITMP1, RIP, -(((ptrint) cd->mcodeptr + 7) -
2244 (ptrint) cd->mcodebase) + disp);
2246 switch (iptr->op1) {
2248 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2249 M_IST(s2, REG_ITMP1, 0);
2253 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2254 M_LST(s2, REG_ITMP1, 0);
2257 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2258 M_FST(s2, REG_ITMP1, 0);
2261 s2 = emit_load_s2(jd, iptr, src, REG_FTMP1);
2262 M_DST(s2, REG_ITMP1, 0);
2267 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2268 /* val = value (in current instruction) */
2269 /* op1 = type, val.a = field address (in */
2270 /* following NOP) */
2272 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2273 disp = dseg_addaddress(cd, NULL);
2275 /* PROFILE_CYCLE_STOP; */
2277 codegen_addpatchref(cd, PATCHER_get_putstatic,
2278 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), disp);
2280 if (opt_showdisassemble) {
2281 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2284 /* PROFILE_CYCLE_START; */
2287 fieldinfo *fi = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1);
2289 disp = dseg_addaddress(cd, &(fi->value));
2291 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2294 codegen_addpatchref(cd, PATCHER_clinit, fi->class, 0);
2296 if (opt_showdisassemble) {
2297 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2300 PROFILE_CYCLE_START;
2304 /* This approach is much faster than moving the field
2305 address inline into a register. */
2307 M_ALD(REG_ITMP1, RIP, -(((ptrint) cd->mcodeptr + 7) -
2308 (ptrint) cd->mcodebase) + disp);
2310 switch (iptr->op1) {
2313 M_IST_IMM(iptr->val.i, REG_ITMP1, 0);
2318 if (IS_IMM32(iptr->val.l))
2319 M_LST_IMM32(iptr->val.l, REG_ITMP1, 0);
2321 M_IST_IMM(iptr->val.l, REG_ITMP1, 0);
2322 M_IST_IMM(iptr->val.l >> 32, REG_ITMP1, 4);
2328 case ICMD_GETFIELD: /* ... ==> ..., value */
2329 /* op1 = type, val.i = field offset */
2331 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2332 gen_nullptr_check(s1);
2334 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2335 /* PROFILE_CYCLE_STOP; */
2337 codegen_addpatchref(cd, PATCHER_get_putfield,
2338 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2340 if (opt_showdisassemble) {
2341 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2344 /* PROFILE_CYCLE_START; */
2349 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2351 switch (iptr->op1) {
2353 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2354 M_ILD32(d, s1, disp);
2358 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
2359 M_LLD32(d, s1, disp);
2362 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2363 M_FLD32(d, s1, disp);
2366 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FTMP1);
2367 M_DLD32(d, s1, disp);
2370 emit_store(jd, iptr, iptr->dst, d);
2373 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2374 /* op1 = type, val.i = field offset */
2376 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2377 gen_nullptr_check(s1);
2379 if (IS_INT_LNG_TYPE(iptr->op1))
2380 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2382 s2 = emit_load_s2(jd, iptr, src, REG_FTMP2);
2384 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2385 /* PROFILE_CYCLE_STOP; */
2387 codegen_addpatchref(cd, PATCHER_get_putfield,
2388 INSTRUCTION_UNRESOLVED_FIELD(iptr), 0);
2390 if (opt_showdisassemble) {
2391 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2394 /* PROFILE_CYCLE_START; */
2399 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr)->offset;
2401 switch (iptr->op1) {
2403 M_IST32(s2, s1, disp);
2407 M_LST32(s2, s1, disp);
2410 M_FST32(s2, s1, disp);
2413 M_DST32(s2, s1, disp);
2418 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2419 /* val = value (in current instruction) */
2420 /* op1 = type, val.a = field address (in */
2421 /* following NOP) */
2423 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2424 gen_nullptr_check(s1);
2426 if (INSTRUCTION_IS_UNRESOLVED(iptr + 1)) {
2427 /* PROFILE_CYCLE_STOP; */
2429 codegen_addpatchref(cd, PATCHER_putfieldconst,
2430 INSTRUCTION_UNRESOLVED_FIELD(iptr + 1), 0);
2432 if (opt_showdisassemble) {
2433 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2436 /* PROFILE_CYCLE_START; */
2441 disp = INSTRUCTION_RESOLVED_FIELDINFO(iptr + 1)->offset;
2443 switch (iptr->op1) {
2446 M_IST32_IMM(iptr->val.i, s1, disp);
2451 M_IST32_IMM(iptr->val.l, s1, disp);
2452 M_IST32_IMM(iptr->val.l >> 32, s1, disp + 4);
2458 /* branch operations **************************************************/
2460 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2462 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2463 M_INTMOVE(s1, REG_ITMP1_XPTR);
2467 #ifdef ENABLE_VERIFIER
2469 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2470 (unresolved_class *) iptr->val.a, 0);
2472 if (opt_showdisassemble) {
2473 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2476 #endif /* ENABLE_VERIFIER */
2478 M_CALL_IMM(0); /* passing exception pc */
2479 M_POP(REG_ITMP2_XPC);
2481 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
2485 case ICMD_GOTO: /* ... ==> ... */
2486 /* op1 = target JavaVM pc */
2489 codegen_addreference(cd, (basicblock *) iptr->target);
2492 case ICMD_JSR: /* ... ==> ... */
2493 /* op1 = target JavaVM pc */
2496 codegen_addreference(cd, (basicblock *) iptr->target);
2499 case ICMD_RET: /* ... ==> ... */
2500 /* op1 = local variable */
2502 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2503 if (var->flags & INMEMORY) {
2504 M_ALD(REG_ITMP1, REG_SP, var->regoff * 8);
2510 case ICMD_IFNULL: /* ..., value ==> ... */
2511 /* op1 = target JavaVM pc */
2513 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2516 codegen_addreference(cd, (basicblock *) iptr->target);
2519 case ICMD_IFNONNULL: /* ..., value ==> ... */
2520 /* op1 = target JavaVM pc */
2522 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2525 codegen_addreference(cd, (basicblock *) iptr->target);
2528 case ICMD_IFEQ: /* ..., value ==> ... */
2529 /* op1 = target JavaVM pc, val.i = constant */
2531 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2532 M_ICMP_IMM(iptr->val.i, s1);
2534 codegen_addreference(cd, (basicblock *) iptr->target);
2537 case ICMD_IFLT: /* ..., value ==> ... */
2538 /* op1 = target JavaVM pc, val.i = constant */
2540 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2541 M_ICMP_IMM(iptr->val.i, s1);
2543 codegen_addreference(cd, (basicblock *) iptr->target);
2546 case ICMD_IFLE: /* ..., value ==> ... */
2547 /* op1 = target JavaVM pc, val.i = constant */
2549 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2550 M_ICMP_IMM(iptr->val.i, s1);
2552 codegen_addreference(cd, (basicblock *) iptr->target);
2555 case ICMD_IFNE: /* ..., value ==> ... */
2556 /* op1 = target JavaVM pc, val.i = constant */
2558 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2559 M_ICMP_IMM(iptr->val.i, s1);
2561 codegen_addreference(cd, (basicblock *) iptr->target);
2564 case ICMD_IFGT: /* ..., value ==> ... */
2565 /* op1 = target JavaVM pc, val.i = constant */
2567 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2568 M_ICMP_IMM(iptr->val.i, s1);
2570 codegen_addreference(cd, (basicblock *) iptr->target);
2573 case ICMD_IFGE: /* ..., value ==> ... */
2574 /* op1 = target JavaVM pc, val.i = constant */
2576 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2577 M_ICMP_IMM(iptr->val.i, s1);
2579 codegen_addreference(cd, (basicblock *) iptr->target);
2582 case ICMD_IF_LEQ: /* ..., value ==> ... */
2583 /* op1 = target JavaVM pc, val.l = constant */
2585 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2586 if (IS_IMM32(iptr->val.l))
2587 M_LCMP_IMM(iptr->val.l, s1);
2589 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2590 M_LCMP(REG_ITMP2, s1);
2593 codegen_addreference(cd, (basicblock *) iptr->target);
2596 case ICMD_IF_LLT: /* ..., value ==> ... */
2597 /* op1 = target JavaVM pc, val.l = constant */
2599 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2600 if (IS_IMM32(iptr->val.l))
2601 M_LCMP_IMM(iptr->val.l, s1);
2603 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2604 M_LCMP(REG_ITMP2, s1);
2607 codegen_addreference(cd, (basicblock *) iptr->target);
2610 case ICMD_IF_LLE: /* ..., value ==> ... */
2611 /* op1 = target JavaVM pc, val.l = constant */
2613 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2614 if (IS_IMM32(iptr->val.l))
2615 M_LCMP_IMM(iptr->val.l, s1);
2617 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2618 M_LCMP(REG_ITMP2, s1);
2621 codegen_addreference(cd, (basicblock *) iptr->target);
2624 case ICMD_IF_LNE: /* ..., value ==> ... */
2625 /* op1 = target JavaVM pc, val.l = constant */
2627 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2628 if (IS_IMM32(iptr->val.l))
2629 M_LCMP_IMM(iptr->val.l, s1);
2631 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2632 M_LCMP(REG_ITMP2, s1);
2635 codegen_addreference(cd, (basicblock *) iptr->target);
2638 case ICMD_IF_LGT: /* ..., value ==> ... */
2639 /* op1 = target JavaVM pc, val.l = constant */
2641 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2642 if (IS_IMM32(iptr->val.l))
2643 M_LCMP_IMM(iptr->val.l, s1);
2645 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2646 M_LCMP(REG_ITMP2, s1);
2649 codegen_addreference(cd, (basicblock *) iptr->target);
2652 case ICMD_IF_LGE: /* ..., value ==> ... */
2653 /* op1 = target JavaVM pc, val.l = constant */
2655 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2656 if (IS_IMM32(iptr->val.l))
2657 M_LCMP_IMM(iptr->val.l, s1);
2659 M_MOV_IMM(iptr->val.l, REG_ITMP2);
2660 M_LCMP(REG_ITMP2, s1);
2663 codegen_addreference(cd, (basicblock *) iptr->target);
2666 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2667 /* op1 = target JavaVM pc */
2669 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2670 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2673 codegen_addreference(cd, (basicblock *) iptr->target);
2676 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2677 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2679 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2680 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2683 codegen_addreference(cd, (basicblock *) iptr->target);
2686 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2687 /* op1 = target JavaVM pc */
2689 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2690 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2693 codegen_addreference(cd, (basicblock *) iptr->target);
2696 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2697 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2699 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2700 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2703 codegen_addreference(cd, (basicblock *) iptr->target);
2706 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2707 /* op1 = target JavaVM pc */
2709 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2710 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2713 codegen_addreference(cd, (basicblock *) iptr->target);
2716 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2717 /* op1 = target JavaVM pc */
2719 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2720 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2723 codegen_addreference(cd, (basicblock *) iptr->target);
2726 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2727 /* op1 = target JavaVM pc */
2729 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2730 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2733 codegen_addreference(cd, (basicblock *) iptr->target);
2736 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2737 /* op1 = target JavaVM pc */
2739 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2740 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2743 codegen_addreference(cd, (basicblock *) iptr->target);
2746 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2747 /* op1 = target JavaVM pc */
2749 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2750 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2753 codegen_addreference(cd, (basicblock *) iptr->target);
2756 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2757 /* op1 = target JavaVM pc */
2759 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2760 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2763 codegen_addreference(cd, (basicblock *) iptr->target);
2766 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2767 /* op1 = target JavaVM pc */
2769 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2770 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2773 codegen_addreference(cd, (basicblock *) iptr->target);
2776 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2777 /* op1 = target JavaVM pc */
2779 s1 = emit_load_s1(jd, iptr, src->prev, REG_ITMP1);
2780 s2 = emit_load_s2(jd, iptr, src, REG_ITMP2);
2783 codegen_addreference(cd, (basicblock *) iptr->target);
2786 /* (value xx 0) ? IFxx_ICONST : ELSE_ICONST */
2788 case ICMD_ELSE_ICONST: /* handled by IFxx_ICONST */
2791 case ICMD_IFEQ_ICONST: /* ..., value ==> ..., constant */
2792 case ICMD_IFNE_ICONST: /* val.i = constant */
2793 case ICMD_IFLT_ICONST:
2794 case ICMD_IFGE_ICONST:
2795 case ICMD_IFGT_ICONST:
2796 case ICMD_IFLE_ICONST:
2798 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2799 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
2800 if (iptr[1].opc == ICMD_ELSE_ICONST) {
2802 M_INTMOVE(s1, REG_ITMP1);
2805 if (iptr[1].val.i == 0)
2808 M_IMOV_IMM(iptr[1].val.i, d);
2810 if (iptr->val.i == 0)
2813 M_IMOV_IMM(iptr->val.i, REG_ITMP2);
2816 switch (iptr->opc) {
2817 case ICMD_IFEQ_ICONST:
2818 M_CMOVEQ(REG_ITMP2, d);
2820 case ICMD_IFNE_ICONST:
2821 M_CMOVNE(REG_ITMP2, d);
2823 case ICMD_IFLT_ICONST:
2824 M_CMOVLT(REG_ITMP2, d);
2826 case ICMD_IFGE_ICONST:
2827 M_CMOVGE(REG_ITMP2, d);
2829 case ICMD_IFGT_ICONST:
2830 M_CMOVGT(REG_ITMP2, d);
2832 case ICMD_IFLE_ICONST:
2833 M_CMOVLE(REG_ITMP2, d);
2837 emit_store(jd, iptr, iptr->dst, d);
2841 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2844 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
2845 M_INTMOVE(s1, REG_RESULT);
2846 goto nowperformreturn;
2848 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2850 s1 = emit_load_s1(jd, iptr, src, REG_RESULT);
2851 M_INTMOVE(s1, REG_RESULT);
2853 #ifdef ENABLE_VERIFIER
2857 codegen_addpatchref(cd, PATCHER_athrow_areturn,
2858 (unresolved_class *) iptr->val.a, 0);
2860 if (opt_showdisassemble) {
2861 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
2864 PROFILE_CYCLE_START;
2866 #endif /* ENABLE_VERIFIER */
2867 goto nowperformreturn;
2869 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2872 s1 = emit_load_s1(jd, iptr, src, REG_FRESULT);
2873 M_FLTMOVE(s1, REG_FRESULT);
2874 goto nowperformreturn;
2876 case ICMD_RETURN: /* ... ==> ... */
2884 #if !defined(NDEBUG)
2885 /* generate call trace */
2887 if (opt_verbosecall) {
2888 emit_alu_imm_reg(cd, ALU_SUB, 2 * 8, REG_SP);
2890 emit_mov_reg_membase(cd, REG_RESULT, REG_SP, 0 * 8);
2891 emit_movq_reg_membase(cd, REG_FRESULT, REG_SP, 1 * 8);
2893 emit_mov_imm_reg(cd, (u8) m, rd->argintregs[0]);
2894 emit_mov_reg_reg(cd, REG_RESULT, rd->argintregs[1]);
2895 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2896 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2898 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
2901 emit_mov_membase_reg(cd, REG_SP, 0 * 8, REG_RESULT);
2902 emit_movq_membase_reg(cd, REG_SP, 1 * 8, REG_FRESULT);
2904 emit_alu_imm_reg(cd, ALU_ADD, 2 * 8, REG_SP);
2906 #endif /* !defined(NDEBUG) */
2908 #if defined(ENABLE_THREADS)
2909 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2910 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
2912 /* we need to save the proper return value */
2913 switch (iptr->opc) {
2917 M_LST(REG_RESULT, REG_SP, rd->memuse * 8);
2921 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8);
2925 M_MOV_IMM(builtin_monitorexit, REG_ITMP1);
2928 /* and now restore the proper return value */
2929 switch (iptr->opc) {
2933 M_LLD(REG_RESULT, REG_SP, rd->memuse * 8);
2937 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8);
2943 /* restore saved registers */
2945 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2946 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2948 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2949 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2952 /* deallocate stack */
2955 M_AADD_IMM(stackframesize * 8, REG_SP);
2957 /* generate method profiling code */
2966 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2971 tptr = (void **) iptr->target;
2973 s4ptr = iptr->val.a;
2974 l = s4ptr[1]; /* low */
2975 i = s4ptr[2]; /* high */
2977 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
2978 M_INTMOVE(s1, REG_ITMP1);
2981 M_ISUB_IMM(l, REG_ITMP1);
2986 M_ICMP_IMM(i - 1, REG_ITMP1);
2989 codegen_addreference(cd, (basicblock *) tptr[0]);
2991 /* build jump table top down and use address of lowest entry */
2993 /* s4ptr += 3 + i; */
2997 dseg_addtarget(cd, (basicblock *) tptr[0]);
3001 /* length of dataseg after last dseg_addtarget is used
3004 M_MOV_IMM(0, REG_ITMP2);
3006 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
3012 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
3014 s4 i, l, val, *s4ptr;
3017 tptr = (void **) iptr->target;
3019 s4ptr = iptr->val.a;
3020 l = s4ptr[0]; /* default */
3021 i = s4ptr[1]; /* count */
3023 MCODECHECK(8 + ((7 + 6) * i) + 5);
3024 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3031 M_ICMP_IMM(val, s1);
3033 codegen_addreference(cd, (basicblock *) tptr[0]);
3038 tptr = (void **) iptr->target;
3039 codegen_addreference(cd, (basicblock *) tptr[0]);
3044 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
3045 /* op1 = arg count val.a = builtintable entry */
3051 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
3052 /* op1 = arg count, val.a = method pointer */
3054 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
3055 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
3056 case ICMD_INVOKEINTERFACE:
3058 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3059 md = INSTRUCTION_UNRESOLVED_METHOD(iptr)->methodref->parseddesc.md;
3063 lm = INSTRUCTION_RESOLVED_METHODINFO(iptr);
3064 md = lm->parseddesc;
3068 s3 = md->paramcount;
3070 MCODECHECK((20 * s3) + 128);
3072 /* copy arguments to registers or stack location */
3074 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
3075 if (src->varkind == ARGVAR)
3077 if (IS_INT_LNG_TYPE(src->type)) {
3078 if (!md->params[s3].inmemory) {
3079 s1 = rd->argintregs[md->params[s3].regoff];
3080 d = emit_load_s1(jd, iptr, src, s1);
3083 d = emit_load_s1(jd, iptr, src, REG_ITMP1);
3084 M_LST(d, REG_SP, md->params[s3].regoff * 8);
3088 if (!md->params[s3].inmemory) {
3089 s1 = rd->argfltregs[md->params[s3].regoff];
3090 d = emit_load_s1(jd, iptr, src, s1);
3093 d = emit_load_s1(jd, iptr, src, REG_FTMP1);
3095 if (IS_2_WORD_TYPE(src->type))
3096 M_DST(d, REG_SP, md->params[s3].regoff * 8);
3098 M_FST(d, REG_SP, md->params[s3].regoff * 8);
3103 /* generate method profiling code */
3107 switch (iptr->opc) {
3109 a = (ptrint) bte->fp;
3110 d = md->returntype.type;
3112 M_MOV_IMM(a, REG_ITMP1);
3115 /* if op1 == true, we need to check for an exception */
3117 if (iptr->op1 == true) {
3120 codegen_add_fillinstacktrace_ref(cd);
3124 case ICMD_INVOKESPECIAL:
3125 M_TEST(rd->argintregs[0]);
3127 codegen_add_nullpointerexception_ref(cd);
3129 /* first argument contains pointer */
3130 /* gen_nullptr_check(rd->argintregs[0]); */
3132 /* access memory for hardware nullptr */
3133 /* emit_mov_membase_reg(cd, rd->argintregs[0], 0, REG_ITMP2); */
3137 case ICMD_INVOKESTATIC:
3139 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3141 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3144 if (opt_showdisassemble) {
3145 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3149 d = um->methodref->parseddesc.md->returntype.type;
3152 a = (ptrint) lm->stubroutine;
3153 d = lm->parseddesc->returntype.type;
3156 M_MOV_IMM(a, REG_ITMP2);
3160 case ICMD_INVOKEVIRTUAL:
3161 gen_nullptr_check(rd->argintregs[0]);
3164 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3166 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3168 if (opt_showdisassemble) {
3169 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3173 d = um->methodref->parseddesc.md->returntype.type;
3176 s1 = OFFSET(vftbl_t, table[0]) +
3177 sizeof(methodptr) * lm->vftblindex;
3178 d = lm->parseddesc->returntype.type;
3181 M_ALD(REG_METHODPTR, rd->argintregs[0],
3182 OFFSET(java_objectheader, vftbl));
3183 M_ALD32(REG_ITMP3, REG_METHODPTR, s1);
3187 case ICMD_INVOKEINTERFACE:
3188 gen_nullptr_check(rd->argintregs[0]);
3191 unresolved_method *um = INSTRUCTION_UNRESOLVED_METHOD(iptr);
3193 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3195 if (opt_showdisassemble) {
3196 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3201 d = um->methodref->parseddesc.md->returntype.type;
3204 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3205 sizeof(methodptr) * lm->class->index;
3207 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3209 d = lm->parseddesc->returntype.type;
3212 M_ALD(REG_METHODPTR, rd->argintregs[0],
3213 OFFSET(java_objectheader, vftbl));
3214 M_ALD32(REG_METHODPTR, REG_METHODPTR, s1);
3215 M_ALD32(REG_ITMP3, REG_METHODPTR, s2);
3220 /* generate method profiling code */
3222 PROFILE_CYCLE_START;
3224 /* d contains return type */
3226 if (d != TYPE_VOID) {
3227 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
3228 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3229 M_INTMOVE(REG_RESULT, s1);
3230 emit_store(jd, iptr, iptr->dst, s1);
3232 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_FRESULT);
3233 M_FLTMOVE(REG_FRESULT, s1);
3234 emit_store(jd, iptr, iptr->dst, s1);
3240 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3242 /* op1: 0 == array, 1 == class */
3243 /* val.a: (classinfo *) superclass */
3245 /* superclass is an interface:
3247 * OK if ((sub == NULL) ||
3248 * (sub->vftbl->interfacetablelength > super->index) &&
3249 * (sub->vftbl->interfacetable[-super->index] != NULL));
3251 * superclass is a class:
3253 * OK if ((sub == NULL) || (0
3254 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3255 * super->vftbl->diffval));
3258 if (iptr->op1 == 1) {
3259 /* object type cast-check */
3262 vftbl_t *supervftbl;
3265 super = (classinfo *) iptr->val.a;
3272 superindex = super->index;
3273 supervftbl = super->vftbl;
3276 #if defined(ENABLE_THREADS)
3277 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3279 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3281 /* calculate interface checkcast code size */
3283 s2 = 3; /* mov_membase_reg */
3284 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3286 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub imm32 */ +
3287 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3288 3 /* test */ + 6 /* jcc */;
3291 s2 += (opt_showdisassemble ? 5 : 0);
3293 /* calculate class checkcast code size */
3295 s3 = 3; /* mov_membase_reg */
3296 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3297 s3 += 10 /* mov_imm_reg */ + 3 + 4 /* movl_membase32_reg */;
3300 if (s1 != REG_ITMP1) {
3301 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3302 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, baseval));
3303 a += 3; /* movl_membase_reg - only if REG_ITMP3 == R11 */
3304 CALCOFFSETBYTES(a, REG_ITMP3, OFFSET(vftbl_t, diffval));
3310 s3 += 3 + 4 /* movl_membase32_reg */ + 3 /* sub */ +
3311 10 /* mov_imm_reg */ + 3 /* movl_membase_reg */;
3312 CALCOFFSETBYTES(s3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3315 s3 += 3 /* cmp */ + 6 /* jcc */;
3318 s3 += (opt_showdisassemble ? 5 : 0);
3320 /* if class is not resolved, check which code to call */
3324 M_BEQ(6 + (opt_showdisassemble ? 5 : 0) + 7 + 6 + s2 + 5 + s3);
3326 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3327 (constant_classref *) iptr->target, 0);
3329 if (opt_showdisassemble) {
3330 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3333 M_IMOV_IMM(0, REG_ITMP2); /* super->flags */
3334 M_IAND_IMM(ACC_INTERFACE, REG_ITMP2);
3338 /* interface checkcast code */
3340 if (!super || (super->flags & ACC_INTERFACE)) {
3346 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3349 codegen_addpatchref(cd,
3350 PATCHER_checkcast_instanceof_interface,
3351 (constant_classref *) iptr->target,
3354 if (opt_showdisassemble) {
3355 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3359 emit_movl_membase32_reg(cd, REG_ITMP2,
3360 OFFSET(vftbl_t, interfacetablelength),
3362 /* XXX TWISTI: should this be int arithmetic? */
3363 M_LSUB_IMM32(superindex, REG_ITMP3);
3366 codegen_add_classcastexception_ref(cd);
3367 emit_mov_membase32_reg(cd, REG_ITMP2,
3368 OFFSET(vftbl_t, interfacetable[0]) -
3369 superindex * sizeof(methodptr*),
3373 codegen_add_classcastexception_ref(cd);
3379 /* class checkcast code */
3381 if (!super || !(super->flags & ACC_INTERFACE)) {
3387 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3390 codegen_addpatchref(cd, PATCHER_checkcast_class,
3391 (constant_classref *) iptr->target,
3394 if (opt_showdisassemble) {
3395 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3399 M_MOV_IMM(supervftbl, REG_ITMP3);
3400 #if defined(ENABLE_THREADS)
3401 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3403 emit_movl_membase32_reg(cd, REG_ITMP2,
3404 OFFSET(vftbl_t, baseval),
3406 /* if (s1 != REG_ITMP1) { */
3407 /* emit_movl_membase_reg(cd, REG_ITMP3, */
3408 /* OFFSET(vftbl_t, baseval), */
3410 /* emit_movl_membase_reg(cd, REG_ITMP3, */
3411 /* OFFSET(vftbl_t, diffval), */
3413 /* #if defined(ENABLE_THREADS) */
3414 /* codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
3416 /* emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP1, REG_ITMP2); */
3419 emit_movl_membase32_reg(cd, REG_ITMP3,
3420 OFFSET(vftbl_t, baseval),
3422 M_LSUB(REG_ITMP3, REG_ITMP2);
3423 M_MOV_IMM(supervftbl, REG_ITMP3);
3424 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3426 #if defined(ENABLE_THREADS)
3427 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3429 M_LCMP(REG_ITMP3, REG_ITMP2);
3430 M_BA(0); /* (u) REG_ITMP1 > (u) REG_ITMP2 -> jump */
3431 codegen_add_classcastexception_ref(cd);
3433 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP3);
3436 /* array type cast-check */
3438 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3439 M_INTMOVE(s1, rd->argintregs[0]);
3441 if (iptr->val.a == NULL) {
3442 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
3443 (constant_classref *) iptr->target, 0);
3445 if (opt_showdisassemble) {
3446 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3450 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3451 M_MOV_IMM(BUILTIN_arraycheckcast, REG_ITMP1);
3455 codegen_add_classcastexception_ref(cd);
3457 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3458 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP1);
3461 emit_store(jd, iptr, iptr->dst, d);
3464 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3466 /* op1: 0 == array, 1 == class */
3467 /* val.a: (classinfo *) superclass */
3469 /* superclass is an interface:
3471 * return (sub != NULL) &&
3472 * (sub->vftbl->interfacetablelength > super->index) &&
3473 * (sub->vftbl->interfacetable[-super->index] != NULL);
3475 * superclass is a class:
3477 * return ((sub != NULL) && (0
3478 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3479 * super->vftbl->diffvall));
3484 vftbl_t *supervftbl;
3487 super = (classinfo *) iptr->val.a;
3494 superindex = super->index;
3495 supervftbl = super->vftbl;
3498 #if defined(ENABLE_THREADS)
3499 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3502 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3503 d = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_ITMP2);
3505 M_INTMOVE(s1, REG_ITMP1);
3509 /* calculate interface instanceof code size */
3511 s2 = 3; /* mov_membase_reg */
3512 CALCOFFSETBYTES(s2, s1, OFFSET(java_objectheader, vftbl));
3513 s2 += 3 + 4 /* movl_membase32_reg */ + 3 + 4 /* sub_imm32 */ +
3514 3 /* test */ + 6 /* jcc */ + 3 + 4 /* mov_membase32_reg */ +
3515 3 /* test */ + 4 /* setcc */;
3518 s2 += (opt_showdisassemble ? 5 : 0);
3520 /* calculate class instanceof code size */
3522 s3 = 3; /* mov_membase_reg */
3523 CALCOFFSETBYTES(s3, s1, OFFSET(java_objectheader, vftbl));
3524 s3 += 10; /* mov_imm_reg */
3525 s3 += 2; /* movl_membase_reg - only if REG_ITMP1 == RAX */
3526 CALCOFFSETBYTES(s3, REG_ITMP1, OFFSET(vftbl_t, baseval));
3527 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3528 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3529 s3 += 3; /* movl_membase_reg - only if REG_ITMP2 == R10 */
3530 CALCOFFSETBYTES(s3, REG_ITMP2, OFFSET(vftbl_t, diffval));
3531 s3 += 3 /* sub */ + 3 /* xor */ + 3 /* cmp */ + 4 /* setcc */;
3534 s3 += (opt_showdisassemble ? 5 : 0);
3536 emit_alu_reg_reg(cd, ALU_XOR, d, d);
3538 /* if class is not resolved, check which code to call */
3541 emit_test_reg_reg(cd, s1, s1);
3542 emit_jcc(cd, CC_Z, (6 + (opt_showdisassemble ? 5 : 0) +
3543 7 + 6 + s2 + 5 + s3));
3545 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
3546 (constant_classref *) iptr->target, 0);
3548 if (opt_showdisassemble) {
3549 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3552 emit_movl_imm_reg(cd, 0, REG_ITMP3); /* super->flags */
3553 emit_alul_imm_reg(cd, ALU_AND, ACC_INTERFACE, REG_ITMP3);
3554 emit_jcc(cd, CC_Z, s2 + 5);
3557 /* interface instanceof code */
3559 if (!super || (super->flags & ACC_INTERFACE)) {
3561 emit_test_reg_reg(cd, s1, s1);
3562 emit_jcc(cd, CC_Z, s2);
3565 emit_mov_membase_reg(cd, s1,
3566 OFFSET(java_objectheader, vftbl),
3569 codegen_addpatchref(cd,
3570 PATCHER_checkcast_instanceof_interface,
3571 (constant_classref *) iptr->target, 0);
3573 if (opt_showdisassemble) {
3574 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3578 emit_movl_membase32_reg(cd, REG_ITMP1,
3579 OFFSET(vftbl_t, interfacetablelength),
3581 emit_alu_imm32_reg(cd, ALU_SUB, superindex, REG_ITMP3);
3582 emit_test_reg_reg(cd, REG_ITMP3, REG_ITMP3);
3584 a = 3 + 4 /* mov_membase32_reg */ + 3 /* test */ + 4 /* setcc */;
3586 emit_jcc(cd, CC_LE, a);
3587 emit_mov_membase32_reg(cd, REG_ITMP1,
3588 OFFSET(vftbl_t, interfacetable[0]) -
3589 superindex * sizeof(methodptr*),
3591 emit_test_reg_reg(cd, REG_ITMP1, REG_ITMP1);
3592 emit_setcc_reg(cd, CC_NE, d);
3595 emit_jmp_imm(cd, s3);
3598 /* class instanceof code */
3600 if (!super || !(super->flags & ACC_INTERFACE)) {
3602 emit_test_reg_reg(cd, s1, s1);
3603 emit_jcc(cd, CC_E, s3);
3606 emit_mov_membase_reg(cd, s1,
3607 OFFSET(java_objectheader, vftbl),
3611 codegen_addpatchref(cd, PATCHER_instanceof_class,
3612 (constant_classref *) iptr->target, 0);
3614 if (opt_showdisassemble) {
3615 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3619 emit_mov_imm_reg(cd, (ptrint) supervftbl, REG_ITMP2);
3620 #if defined(ENABLE_THREADS)
3621 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3623 emit_movl_membase_reg(cd, REG_ITMP1,
3624 OFFSET(vftbl_t, baseval),
3626 emit_movl_membase_reg(cd, REG_ITMP2,
3627 OFFSET(vftbl_t, diffval),
3629 emit_movl_membase_reg(cd, REG_ITMP2,
3630 OFFSET(vftbl_t, baseval),
3632 #if defined(ENABLE_THREADS)
3633 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3635 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
3636 emit_alu_reg_reg(cd, ALU_XOR, d, d); /* may be REG_ITMP2 */
3637 emit_alu_reg_reg(cd, ALU_CMP, REG_ITMP3, REG_ITMP1);
3638 emit_setcc_reg(cd, CC_BE, d);
3640 emit_store(jd, iptr, iptr->dst, d);
3644 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3645 /* op1 = dimension, val.a = class */
3647 /* check for negative sizes and copy sizes to stack if necessary */
3649 MCODECHECK((10 * 4 * iptr->op1) + 5 + 10 * 8);
3651 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3652 /* copy SAVEDVAR sizes to stack */
3654 if (src->varkind != ARGVAR) {
3655 s2 = emit_load_s2(jd, iptr, src, REG_ITMP1);
3656 M_LST(s2, REG_SP, s1 * 8);
3660 /* is a patcher function set? */
3662 if (iptr->val.a == NULL) {
3663 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
3664 (constant_classref *) iptr->target, 0);
3666 if (opt_showdisassemble) {
3667 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
3673 a = (ptrint) iptr->val.a;
3676 /* a0 = dimension count */
3678 M_MOV_IMM(iptr->op1, rd->argintregs[0]);
3680 /* a1 = arrayvftbl */
3682 M_MOV_IMM(iptr->val.a, rd->argintregs[1]);
3684 /* a2 = pointer to dimensions = stack pointer */
3686 M_MOV(REG_SP, rd->argintregs[2]);
3688 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3691 /* check for exception before result assignment */
3695 codegen_add_fillinstacktrace_ref(cd);
3697 s1 = codegen_reg_of_var(rd, iptr->opc, iptr->dst, REG_RESULT);
3698 M_INTMOVE(REG_RESULT, s1);
3699 emit_store(jd, iptr, iptr->dst, s1);
3703 *exceptionptr = new_internalerror("Unknown ICMD %d", iptr->opc);
3707 } /* for instruction */
3709 /* copy values to interface registers */
3711 src = bptr->outstack;
3712 len = bptr->outdepth;
3714 #if defined(ENABLE_LSRA)
3719 if ((src->varkind != STACKVAR)) {
3721 if (IS_FLT_DBL_TYPE(s2)) {
3722 s1 = emit_load_s1(jd, iptr, src, REG_FTMP1);
3723 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3724 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3727 emit_movq_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3731 s1 = emit_load_s1(jd, iptr, src, REG_ITMP1);
3732 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3733 M_INTMOVE(s1, rd->interfaces[len][s2].regoff);
3736 emit_mov_reg_membase(cd, s1, REG_SP, rd->interfaces[len][s2].regoff * 8);
3743 /* At the end of a basic block we may have to append some nops,
3744 because the patcher stub calling code might be longer than the
3745 actual instruction. So codepatching does not change the
3746 following block unintentionally. */
3748 if (cd->mcodeptr < cd->lastmcodeptr) {
3749 while (cd->mcodeptr < cd->lastmcodeptr) {
3754 } /* if (bptr -> flags >= BBREACHED) */
3755 } /* for basic block */
3757 dseg_createlinenumbertable(cd);
3760 /* generate exception and patcher stubs */
3769 savedmcodeptr = NULL;
3771 /* generate exception stubs */
3773 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
3774 gen_resolvebranch(cd->mcodebase + eref->branchpos,
3776 cd->mcodeptr - cd->mcodebase);
3780 /* Check if the exception is an
3781 ArrayIndexOutOfBoundsException. If so, move index register
3784 if (eref->reg != -1)
3785 M_MOV(eref->reg, rd->argintregs[4]);
3787 /* calcuate exception address */
3789 M_MOV_IMM(0, rd->argintregs[3]);
3791 M_AADD_IMM32(eref->branchpos - 6, rd->argintregs[3]);
3793 /* move function to call into REG_ITMP3 */
3795 M_MOV_IMM(eref->function, REG_ITMP3);
3797 if (savedmcodeptr != NULL) {
3798 M_JMP_IMM(savedmcodeptr - cd->mcodeptr - 5);
3801 savedmcodeptr = cd->mcodeptr;
3803 emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[0]);
3804 M_MOV(REG_SP, rd->argintregs[1]);
3805 M_ALD(rd->argintregs[2], REG_SP, stackframesize * 8);
3807 M_ASUB_IMM(2 * 8, REG_SP);
3808 M_AST(rd->argintregs[3], REG_SP, 0 * 8); /* store XPC */
3812 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3813 M_AADD_IMM(2 * 8, REG_SP);
3815 M_MOV_IMM(asm_handle_exception, REG_ITMP3);
3821 /* generate code patching stub call code */
3823 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3824 /* check size of code segment */
3828 /* Get machine code which is patched back in later. A
3829 `call rel32' is 5 bytes long (but read 8 bytes). */
3831 savedmcodeptr = cd->mcodebase + pref->branchpos;
3832 mcode = *((ptrint *) savedmcodeptr);
3834 /* patch in `call rel32' to call the following code */
3836 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
3837 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
3839 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
3841 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3843 /* move pointer to java_objectheader onto stack */
3845 #if defined(ENABLE_THREADS)
3846 /* create a virtual java_objectheader */
3848 (void) dseg_addaddress(cd, NULL); /* flcword */
3849 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
3850 a = dseg_addaddress(cd, NULL); /* vftbl */
3852 emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + a, REG_ITMP3);
3858 /* move machine code bytes and classinfo pointer into registers */
3860 M_MOV_IMM(mcode, REG_ITMP3);
3862 M_MOV_IMM(pref->ref, REG_ITMP3);
3864 M_MOV_IMM(pref->disp, REG_ITMP3);
3867 M_MOV_IMM(pref->patcher, REG_ITMP3);
3870 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
3875 /* generate replacement-out stubs */
3880 replacementpoint = jd->code->rplpoints;
3882 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
3883 /* check code segment size */
3887 /* note start of stub code */
3889 replacementpoint->outcode = (u1*) (ptrint)(cd->mcodeptr - cd->mcodebase);
3891 /* make machine code for patching */
3893 disp = (ptrint)(replacementpoint->outcode - replacementpoint->pc) - 5;
3894 replacementpoint->mcode = 0xe9 | ((u8)disp << 8);
3896 /* push address of `rplpoint` struct */
3898 M_MOV_IMM(replacementpoint, REG_ITMP3);
3901 /* jump to replacement function */
3903 M_MOV_IMM(asm_replacement_out, REG_ITMP3);
3910 /* everything's ok */
3916 /* createcompilerstub **********************************************************
3918 Creates a stub routine which calls the compiler.
3920 *******************************************************************************/
3922 #define COMPILERSTUB_DATASIZE 2 * SIZEOF_VOID_P
3923 #define COMPILERSTUB_CODESIZE 7 + 7 + 3
3925 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
3928 u1 *createcompilerstub(methodinfo *m)
3930 u1 *s; /* memory to hold the stub */
3935 s = CNEW(u1, COMPILERSTUB_SIZE);
3937 /* set data pointer and code pointer */
3940 s = s + COMPILERSTUB_DATASIZE;
3942 /* mark start of dump memory area */
3944 dumpsize = dump_size();
3946 cd = DNEW(codegendata);
3949 /* Store the methodinfo* in the same place as in the methodheader
3950 for compiled methods. */
3952 d[0] = (ptrint) asm_call_jit_compiler;
3955 /* code for the stub */
3957 M_ALD(REG_ITMP1, RIP, -(7 * 1 + 1 * SIZEOF_VOID_P)); /* methodinfo */
3958 M_ALD(REG_ITMP3, RIP, -(7 * 2 + 2 * SIZEOF_VOID_P)); /* compiler pointer */
3961 #if defined(ENABLE_STATISTICS)
3963 count_cstub_len += COMPILERSTUB_SIZE;
3966 /* release dump area */
3968 dump_release(dumpsize);
3974 /* createnativestub ************************************************************
3976 Creates a stub routine which calls a native method.
3978 *******************************************************************************/
3980 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3986 s4 stackframesize; /* size of stackframe if needed */
3988 s4 i, j; /* count variables */
3992 /* get required compiler data */
3998 /* initialize variables */
4001 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
4003 /* calculate stack frame size */
4006 sizeof(stackframeinfo) / SIZEOF_VOID_P +
4007 sizeof(localref_table) / SIZEOF_VOID_P +
4008 INT_ARG_CNT + FLT_ARG_CNT + 1 + /* + 1 for function address */
4011 if (!(stackframesize & 0x1)) /* keep stack 16-byte aligned */
4014 /* create method header */
4016 (void) dseg_addaddress(cd, m); /* MethodPointer */
4017 (void) dseg_adds4(cd, stackframesize * 8); /* FrameSize */
4018 (void) dseg_adds4(cd, 0); /* IsSync */
4019 (void) dseg_adds4(cd, 0); /* IsLeaf */
4020 (void) dseg_adds4(cd, 0); /* IntSave */
4021 (void) dseg_adds4(cd, 0); /* FltSave */
4022 (void) dseg_addlinenumbertablesize(cd);
4023 (void) dseg_adds4(cd, 0); /* ExTableSize */
4025 /* generate native method profiling code */
4028 /* count frequency */
4030 M_MOV_IMM(m, REG_ITMP2);
4031 M_IINC_MEMBASE(REG_ITMP2, OFFSET(methodinfo, frequency));
4034 /* generate stub code */
4036 M_ASUB_IMM(stackframesize * 8, REG_SP);
4038 #if !defined(NDEBUG)
4039 /* generate call trace */
4041 if (opt_verbosecall) {
4042 /* save integer and float argument registers */
4044 for (i = 0, j = 1; i < md->paramcount; i++) {
4045 if (!md->params[i].inmemory) {
4046 s1 = md->params[i].regoff;
4048 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4049 M_LST(rd->argintregs[s1], REG_SP, j * 8);
4051 M_DST(rd->argfltregs[s1], REG_SP, j * 8);
4057 /* show integer hex code for float arguments */
4059 for (i = 0, j = 0; i < md->paramcount && j < INT_ARG_CNT; i++) {
4060 /* if the paramtype is a float, we have to right shift all
4061 following integer registers */
4063 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
4064 for (s1 = INT_ARG_CNT - 2; s1 >= i; s1--)
4065 M_MOV(rd->argintregs[s1], rd->argintregs[s1 + 1]);
4067 emit_movd_freg_reg(cd, rd->argfltregs[j], rd->argintregs[i]);
4072 M_MOV_IMM(m, REG_ITMP1);
4073 M_AST(REG_ITMP1, REG_SP, 0 * 8);
4074 M_MOV_IMM(builtin_trace_args, REG_ITMP1);
4077 /* restore integer and float argument registers */
4079 for (i = 0, j = 1; i < md->paramcount; i++) {
4080 if (!md->params[i].inmemory) {
4081 s1 = md->params[i].regoff;
4083 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4084 M_LLD(rd->argintregs[s1], REG_SP, j * 8);
4086 M_DLD(rd->argfltregs[s1], REG_SP, j * 8);
4092 #endif /* !defined(NDEBUG) */
4094 /* get function address (this must happen before the stackframeinfo) */
4096 #if !defined(WITH_STATIC_CLASSPATH)
4098 codegen_addpatchref(cd, PATCHER_resolve_native, m, 0);
4100 if (opt_showdisassemble) {
4101 M_NOP; M_NOP; M_NOP; M_NOP; M_NOP;
4106 M_MOV_IMM(f, REG_ITMP3);
4109 /* save integer and float argument registers */
4111 for (i = 0, j = 0; i < md->paramcount; i++) {
4112 if (!md->params[i].inmemory) {
4113 s1 = md->params[i].regoff;
4115 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4116 M_LST(rd->argintregs[s1], REG_SP, j * 8);
4118 M_DST(rd->argfltregs[s1], REG_SP, j * 8);
4124 M_AST(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4126 /* create dynamic stack info */
4128 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4129 emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase), rd->argintregs[1]);
4130 M_ALEA(REG_SP, stackframesize * 8 + SIZEOF_VOID_P, rd->argintregs[2]);
4131 M_ALD(rd->argintregs[3], REG_SP, stackframesize * 8);
4132 M_MOV_IMM(codegen_start_native_call, REG_ITMP1);
4135 /* restore integer and float argument registers */
4137 for (i = 0, j = 0; i < md->paramcount; i++) {
4138 if (!md->params[i].inmemory) {
4139 s1 = md->params[i].regoff;
4141 if (IS_INT_LNG_TYPE(md->paramtypes[i].type))
4142 M_LLD(rd->argintregs[s1], REG_SP, j * 8);
4144 M_DLD(rd->argfltregs[s1], REG_SP, j * 8);
4150 M_ALD(REG_ITMP3, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
4153 /* copy or spill arguments to new locations */
4155 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
4156 t = md->paramtypes[i].type;
4158 if (IS_INT_LNG_TYPE(t)) {
4159 if (!md->params[i].inmemory) {
4160 s1 = rd->argintregs[md->params[i].regoff];
4162 if (!nmd->params[j].inmemory) {
4163 s2 = rd->argintregs[nmd->params[j].regoff];
4167 s2 = nmd->params[j].regoff;
4168 M_LST(s1, REG_SP, s2 * 8);
4172 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4173 s2 = nmd->params[j].regoff;
4174 M_LLD(REG_ITMP1, REG_SP, s1 * 8);
4175 M_LST(REG_ITMP1, REG_SP, s2 * 8);
4179 /* We only copy spilled float arguments, as the float argument */
4180 /* registers keep unchanged. */
4182 if (md->params[i].inmemory) {
4183 s1 = md->params[i].regoff + stackframesize + 1; /* + 1 (RA) */
4184 s2 = nmd->params[j].regoff;
4186 if (IS_2_WORD_TYPE(t)) {
4187 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
4188 M_DST(REG_FTMP1, REG_SP, s2 * 8);
4190 M_FLD(REG_FTMP1, REG_SP, s1 * 8);
4191 M_FST(REG_FTMP1, REG_SP, s2 * 8);
4197 /* put class into second argument register */
4199 if (m->flags & ACC_STATIC)
4200 M_MOV_IMM(m->class, rd->argintregs[1]);
4202 /* put env into first argument register */
4204 M_MOV_IMM(_Jv_env, rd->argintregs[0]);
4206 /* do the native function call */
4210 /* save return value */
4212 if (md->returntype.type != TYPE_VOID) {
4213 if (IS_INT_LNG_TYPE(md->returntype.type))
4214 M_LST(REG_RESULT, REG_SP, 0 * 8);
4216 M_DST(REG_FRESULT, REG_SP, 0 * 8);
4219 /* remove native stackframe info */
4221 M_ALEA(REG_SP, stackframesize * 8, rd->argintregs[0]);
4222 M_MOV_IMM(codegen_finish_native_call, REG_ITMP1);
4225 #if !defined(NDEBUG)
4226 /* generate call trace */
4228 if (opt_verbosecall) {
4229 /* just restore the value we need, don't care about the other */
4231 if (md->returntype.type != TYPE_VOID) {
4232 if (IS_INT_LNG_TYPE(md->returntype.type))
4233 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4235 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4238 M_MOV_IMM(m, rd->argintregs[0]);
4239 M_MOV(REG_RESULT, rd->argintregs[1]);
4240 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
4241 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
4243 M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
4246 #endif /* !defined(NDEBUG) */
4248 /* check for exception */
4250 #if defined(ENABLE_THREADS)
4251 M_MOV_IMM(builtin_get_exceptionptrptr, REG_ITMP3);
4254 M_MOV_IMM(&_no_threads_exceptionptr, REG_RESULT);
4256 M_ALD(REG_ITMP2, REG_RESULT, 0);
4258 /* restore return value */
4260 if (md->returntype.type != TYPE_VOID) {
4261 if (IS_INT_LNG_TYPE(md->returntype.type))
4262 M_LLD(REG_RESULT, REG_SP, 0 * 8);
4264 M_DLD(REG_FRESULT, REG_SP, 0 * 8);
4267 /* test for exception */
4272 /* remove stackframe */
4274 M_AADD_IMM(stackframesize * 8, REG_SP);
4278 /* handle exception */
4280 #if defined(ENABLE_THREADS)
4281 M_LST(REG_ITMP2, REG_SP, 0 * 8);
4282 M_MOV_IMM(builtin_get_exceptionptrptr, REG_ITMP3);
4284 M_AST_IMM32(0, REG_RESULT, 0); /* clear exception pointer */
4285 M_LLD(REG_ITMP1_XPTR, REG_SP, 0 * 8);
4287 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
4288 M_MOV_IMM(&_no_threads_exceptionptr, REG_ITMP3);
4289 M_AST_IMM32(0, REG_ITMP3, 0); /* clear exception pointer */
4292 /* remove stackframe */
4294 M_AADD_IMM(stackframesize * 8, REG_SP);
4296 M_LLD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
4297 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
4299 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4303 /* process patcher calls **************************************************/
4310 #if defined(ENABLE_THREADS)
4314 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4315 /* Get machine code which is patched back in later. A
4316 `call rel32' is 5 bytes long (but read 8 bytes). */
4318 savedmcodeptr = cd->mcodebase + pref->branchpos;
4319 mcode = *((ptrint *) savedmcodeptr);
4321 /* patch in `call rel32' to call the following code */
4323 tmpmcodeptr = cd->mcodeptr; /* save current mcodeptr */
4324 cd->mcodeptr = savedmcodeptr; /* set mcodeptr to patch position */
4326 M_CALL_IMM(tmpmcodeptr - (savedmcodeptr + PATCHER_CALL_SIZE));
4328 cd->mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4330 /* move pointer to java_objectheader onto stack */
4332 #if defined(ENABLE_THREADS)
4333 /* create a virtual java_objectheader */
4335 (void) dseg_addaddress(cd, NULL); /* flcword */
4336 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
4337 disp = dseg_addaddress(cd, NULL); /* vftbl */
4339 emit_lea_membase_reg(cd, RIP, -(((ptrint) cd->mcodeptr + 7) - (ptrint) cd->mcodebase) + disp, REG_ITMP3);
4345 /* move machine code bytes and classinfo pointer into registers */
4347 M_MOV_IMM(mcode, REG_ITMP3);
4349 M_MOV_IMM(pref->ref, REG_ITMP3);
4351 M_MOV_IMM(pref->disp, REG_ITMP3);
4354 M_MOV_IMM(pref->patcher, REG_ITMP3);
4357 M_MOV_IMM(asm_wrapper_patcher, REG_ITMP3);
4364 return jd->code->entrypoint;
4369 * These are local overrides for various environment variables in Emacs.
4370 * Please do not remove this and leave it at the end of the file, where
4371 * Emacs will automagically detect them.
4372 * ---------------------------------------------------------------------
4375 * indent-tabs-mode: t
4379 * vim:noexpandtab:sw=4:ts=4: