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
32 $Id: codegen.c 7356 2007-02-14 11:00:28Z twisti $
46 #include "vm/jit/s390/arch.h"
47 #include "vm/jit/s390/codegen.h"
48 #include "vm/jit/s390/emit.h"
50 #include "mm/memory.h"
51 #include "native/jni.h"
52 #include "native/native.h"
54 #if defined(ENABLE_THREADS)
55 # include "threads/native/lock.h"
58 #include "vm/builtin.h"
59 #include "vm/exceptions.h"
60 #include "vm/global.h"
61 #include "vm/loader.h"
62 #include "vm/options.h"
63 #include "vm/statistics.h"
64 #include "vm/stringlocal.h"
66 #include "vm/jit/asmpart.h"
67 #include "vm/jit/codegen-common.h"
68 #include "vm/jit/dseg.h"
69 #include "vm/jit/emit-common.h"
70 #include "vm/jit/jit.h"
71 #include "vm/jit/methodheader.h"
72 #include "vm/jit/parse.h"
73 #include "vm/jit/patcher.h"
74 #include "vm/jit/reg.h"
75 #include "vm/jit/replace.h"
77 #if defined(ENABLE_LSRA)
78 # include "vm/jit/allocator/lsra.h"
81 #define OOPS() assert(0);
84 u1 *createcompilerstub(methodinfo *m) {
93 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) {
95 return createcompilerstub(NULL);
101 /* codegen *********************************************************************
103 Generates machine code.
105 *******************************************************************************/
108 bool codegen(jitdata *jd)
114 s4 len, s1, s2, s3, d, disp;
117 varinfo *var, *var1, *var2, *dst;
121 constant_classref *cr;
122 unresolved_class *uc;
123 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
124 unresolved_method *um;
125 builtintable_entry *bte;
128 unresolved_field *uf;
131 rplpoint *replacementpoint;
135 /* get required compiler data */
142 /* prevent compiler warnings */
155 /* space to save used callee saved registers */
157 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
158 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
160 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
163 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
166 #if defined(ENABLE_THREADS)
167 /* space to save argument of monitor_enter */
168 OOPS(); /* see powerpc */
170 if (checksync && (m->flags & ACC_SYNCHRONIZED))
171 cd->stackframesize++;
175 /* Keep stack of non-leaf functions 16-byte aligned for calls into
176 native code e.g. libc or jni (alignment problems with
179 if (!jd->isleafmethod || opt_verbosecall)
180 /* TODO really 16 bytes ? */
181 cd->stackframesize = (cd->stackframesize + 3) & ~3;
183 /* create method header */
185 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
186 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
188 #if defined(ENABLE_THREADS)
189 /* IsSync contains the offset relative to the stack pointer for the
190 argument of monitor_exit used in the exception handler. Since the
191 offset could be zero and give a wrong meaning of the flag it is
195 if (checksync && (m->flags & ACC_SYNCHRONIZED))
196 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
200 (void) dseg_add_unique_s4(cd, 0);*/ /* IsSync */
202 disp = dseg_add_unique_address(cd, 0);
204 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
205 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
206 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
208 (void) dseg_addlinenumbertablesize(cd);
210 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
212 /* create exception table */
214 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
215 dseg_add_target(cd, ex->start);
216 dseg_add_target(cd, ex->end);
217 dseg_add_target(cd, ex->handler);
218 (void) dseg_add_unique_address(cd, ex->catchtype.any);
221 /* generate method profiling code */
223 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
224 /* count frequency */
226 M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
227 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
228 M_IADD_IMM(1, REG_ITMP2);
229 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
231 /* PROFILE_CYCLE_START; */
234 /* create stack frame (if necessary) */
236 if (cd->stackframesize)
237 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
239 N_LHI(REG_ITMP2, disp);
240 N_ST(REG_SP, 0, REG_ITMP2, REG_PV);
242 /* save used callee saved registers and return address */
244 p = cd->stackframesize;
245 p--; M_AST(REG_RA, REG_SP, p * 4);
246 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
247 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
249 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
250 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
253 /* take arguments out of register or stack frame */
257 for (p = 0, l = 0; p < md->paramcount; p++) {
258 t = md->paramtypes[p].type;
259 varindex = jd->local_map[l * 5 + t];
262 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
265 if (varindex == UNUSED)
270 s1 = md->params[p].regoff;
271 if (IS_INT_LNG_TYPE(t)) { /* integer args */
272 if (IS_2_WORD_TYPE(t))
273 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
274 rd->argintregs[GET_HIGH_REG(s1)]);
276 s2 = rd->argintregs[s1];
277 if (!md->params[p].inmemory) { /* register arguments */
278 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
279 if (IS_2_WORD_TYPE(t))
280 M_LNGMOVE(s2, var->vv.regoff);
282 M_INTMOVE(s2, var->vv.regoff);
284 } else { /* reg arg -> spilled */
285 if (IS_2_WORD_TYPE(t))
286 M_LST(s2, REG_SP, var->vv.regoff * 4);
288 M_IST(s2, REG_SP, var->vv.regoff * 4);
291 } else { /* stack arguments */
292 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
293 if (IS_2_WORD_TYPE(t))
294 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
296 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
298 } else { /* stack arg -> spilled */
299 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
300 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
301 if (IS_2_WORD_TYPE(t)) {
302 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4);
303 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
308 } else { /* floating args */
309 if (!md->params[p].inmemory) { /* register arguments */
310 s2 = rd->argfltregs[s1];
311 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
312 M_FLTMOVE(s2, var->vv.regoff);
314 } else { /* reg arg -> spilled */
315 if (IS_2_WORD_TYPE(t))
316 M_DST(s2, REG_SP, var->vv.regoff * 4);
318 M_FST(s2, REG_SP, var->vv.regoff * 4);
321 } else { /* stack arguments */
322 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
323 if (IS_2_WORD_TYPE(t))
324 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
327 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
329 } else { /* stack-arg -> spilled */
330 if (IS_2_WORD_TYPE(t)) {
331 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
332 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
333 var->vv.regoff = cd->stackframesize + s1;
336 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
337 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
344 /* save monitorenter argument */
346 #if defined(ENABLE_THREADS)
347 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
348 /* stack offset for monitor argument */
352 if (opt_verbosecall) {
353 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
355 for (p = 0; p < INT_ARG_CNT; p++)
356 M_LST(rd->argintregs[p], REG_SP, p * 8);
358 for (p = 0; p < FLT_ARG_CNT; p++)
359 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
361 s1 += INT_ARG_CNT + FLT_ARG_CNT;
364 /* decide which monitor enter function to call */
366 if (m->flags & ACC_STATIC) {
367 M_MOV_IMM(&m->class->object.header, REG_A0);
372 codegen_add_nullpointerexception_ref(cd);
375 M_AST(REG_A0, REG_SP, s1 * 8);
376 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
379 if (opt_verbosecall) {
380 for (p = 0; p < INT_ARG_CNT; p++)
381 M_LLD(rd->argintregs[p], REG_SP, p * 8);
383 for (p = 0; p < FLT_ARG_CNT; p++)
384 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
386 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
392 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
393 emit_verbosecall_enter(jd);
394 #endif /* !defined(NDEBUG) */
398 /* end of header generation */
400 replacementpoint = jd->code->rplpoints;
403 /* walk through all basic blocks */
405 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
407 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
409 if (bptr->flags >= BBREACHED) {
411 /* branch resolving */
413 codegen_resolve_branchrefs(cd, bptr);
415 /* handle replacement points */
418 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
419 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
423 assert(cd->lastmcodeptr <= cd->mcodeptr);
424 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
428 /* copy interface registers to their destination */
433 /* generate basicblock profiling code */
435 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
436 /* count frequency */
438 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
439 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
441 /* if this is an exception handler, start profiling again */
443 if (bptr->type == BBTYPE_EXH)
447 #if defined(ENABLE_LSRA)
451 src = bptr->invars[len];
452 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
453 if (bptr->type == BBTYPE_EXH) {
454 /* d = reg_of_var(rd, src, REG_ITMP1); */
455 if (!IS_INMEMORY(src->flags))
459 M_INTMOVE(REG_ITMP1, d);
460 emit_store(jd, NULL, src, d);
470 var = VAR(bptr->invars[len]);
471 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
472 if (bptr->type == BBTYPE_EXH) {
473 d = codegen_reg_of_var(0, var, REG_ITMP1);
474 M_INTMOVE(REG_ITMP1, d);
475 emit_store(jd, NULL, var, d);
479 assert((var->flags & INOUT));
482 #if defined(ENABLE_LSRA)
485 /* walk through all instructions */
490 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
491 if (iptr->line != currentline) {
492 dseg_addlinenumber(cd, iptr->line);
493 currentline = iptr->line;
496 MCODECHECK(1024); /* 1KB should be enough */
499 case ICMD_NOP: /* ... ==> ... */
500 case ICMD_POP: /* ..., value ==> ... */
501 case ICMD_POP2: /* ..., value, value ==> ... */
502 case ICMD_INLINE_START: /* internal ICMDs */
503 case ICMD_INLINE_END:
506 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
509 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
512 codegen_add_nullpointerexception_ref(cd);
516 /* constant operations ************************************************/
518 case ICMD_ICONST: /* ... ==> ..., constant */
519 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
520 ICONST(d, iptr->sx.val.i);
521 emit_store_dst(jd, iptr, d);
524 case ICMD_LCONST: /* ... ==> ..., constant */
527 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
528 LCONST(d, iptr->sx.val.l);
529 emit_store_dst(jd, iptr, d);
533 case ICMD_FCONST: /* ... ==> ..., constant */
534 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
535 disp = dseg_add_float(cd, iptr->sx.val.f);
536 M_FLDN(d, REG_PV, disp, REG_ITMP1);
537 emit_store_dst(jd, iptr, d);
540 case ICMD_DCONST: /* ... ==> ..., constant */
543 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
544 disp = dseg_add_double(cd, iptr->sx.val.d);
545 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, d);
546 emit_store_dst(jd, iptr, d);
550 case ICMD_ACONST: /* ... ==> ..., constant */
551 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
553 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
554 cr = iptr->sx.val.c.ref;
555 disp = dseg_add_unique_address(cd, cr);
557 /* PROFILE_CYCLE_STOP; */
559 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
562 /* PROFILE_CYCLE_START; */
564 M_ALD(d, REG_PV, disp);
566 if (iptr->sx.val.anyptr == 0) {
569 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
570 M_ALD(d, REG_PV, disp);
573 emit_store_dst(jd, iptr, d);
577 /* load/store/copy/move operations ************************************/
579 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
580 case ICMD_ALOAD: /* s1 = local variable */
584 case ICMD_ISTORE: /* ..., value ==> ... */
590 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
594 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
595 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
598 /* integer operations *************************************************/
600 case ICMD_INEG: /* ..., value ==> ..., - value */
603 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
604 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
607 emit_store_dst(jd, iptr, d);
611 case ICMD_LNEG: /* ..., value ==> ..., - value */
614 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
615 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
618 emit_store_dst(jd, iptr, d);
622 case ICMD_I2L: /* ..., value ==> ..., value */
625 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
626 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
628 emit_store_dst(jd, iptr, d);
632 case ICMD_L2I: /* ..., value ==> ..., value */
635 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
636 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
638 emit_store_dst(jd, iptr, d);
642 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
645 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
646 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
648 emit_store_dst(jd, iptr, d);
652 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
655 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
656 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
658 emit_store_dst(jd, iptr, d);
662 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
665 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
666 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
668 emit_store_dst(jd, iptr, d);
673 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
675 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
676 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
677 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
684 emit_store_dst(jd, iptr, d);
689 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
690 /* sx.val.i = constant */
691 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
692 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
695 M_IADD_IMM(iptr->sx.val.i, d);
696 emit_store_dst(jd, iptr, d);
699 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
702 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
703 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
704 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
711 emit_store_dst(jd, iptr, d);
715 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
716 /* sx.val.l = constant */
719 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
720 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
722 if (IS_IMM32(iptr->sx.val.l))
723 M_LADD_IMM(iptr->sx.val.l, d);
725 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
726 M_LADD(REG_ITMP2, d);
728 emit_store_dst(jd, iptr, d);
732 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
734 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
735 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
736 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
738 M_INTMOVE(s1, REG_ITMP1);
739 M_ISUB(s2, REG_ITMP1);
740 M_INTMOVE(REG_ITMP1, d);
745 emit_store_dst(jd, iptr, d);
749 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
750 /* sx.val.i = constant */
753 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
754 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
756 M_ISUB_IMM(iptr->sx.val.i, d);
757 emit_store_dst(jd, iptr, d);
761 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
764 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
765 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
766 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
768 M_INTMOVE(s1, REG_ITMP1);
769 M_LSUB(s2, REG_ITMP1);
770 M_INTMOVE(REG_ITMP1, d);
775 emit_store_dst(jd, iptr, d);
779 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
780 /* sx.val.l = constant */
783 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
784 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
786 if (IS_IMM32(iptr->sx.val.l))
787 M_LSUB_IMM(iptr->sx.val.l, d);
789 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
790 M_LSUB(REG_ITMP2, d);
792 emit_store_dst(jd, iptr, d);
796 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
799 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
800 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
801 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
808 emit_store_dst(jd, iptr, d);
812 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
813 /* sx.val.i = constant */
816 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
817 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
818 if (iptr->sx.val.i == 2) {
822 M_IMUL_IMM(s1, iptr->sx.val.i, d);
823 emit_store_dst(jd, iptr, d);
827 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
830 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
831 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
832 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
839 emit_store_dst(jd, iptr, d);
843 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
844 /* sx.val.l = constant */
847 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
848 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
849 if (IS_IMM32(iptr->sx.val.l))
850 M_LMUL_IMM(s1, iptr->sx.val.l, d);
852 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
854 M_LMUL(REG_ITMP2, d);
856 emit_store_dst(jd, iptr, d);
860 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
863 var1 = VAROP(iptr->s1);
864 var2 = VAROP(iptr->sx.s23.s2);
865 dst = VAROP(iptr->dst);
867 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
868 if (IS_INMEMORY(var1->flags))
869 M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
871 M_INTMOVE(var1->vv.regoff, RAX);
873 if (IS_INMEMORY(var2->flags))
874 M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
876 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
881 codegen_add_arithmeticexception_ref(cd);
884 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
885 emit_jcc(cd, CC_NE, 4 + 6);
886 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
887 emit_jcc(cd, CC_E, 3 + 1 + 3); /* 6 bytes */
889 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
891 emit_idivl_reg(cd, REG_ITMP3);
893 if (IS_INMEMORY(dst->flags)) {
894 emit_mov_reg_membase(cd, RAX, REG_SP, dst->vv.regoff * 8);
895 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
898 M_INTMOVE(RAX, dst->vv.regoff);
900 if (dst->vv.regoff != RDX) {
901 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
907 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
910 var1 = VAROP(iptr->s1);
911 var2 = VAROP(iptr->sx.s23.s2);
912 dst = VAROP(iptr->dst);
914 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
915 if (IS_INMEMORY(var1->flags))
916 M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
918 M_INTMOVE(var1->vv.regoff, RAX);
920 if (IS_INMEMORY(var2->flags))
921 M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
923 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
928 codegen_add_arithmeticexception_ref(cd);
931 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
933 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
934 emit_jcc(cd, CC_NE, 2 + 4 + 6);
937 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
938 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
939 emit_jcc(cd, CC_E, 1 + 3); /* 6 bytes */
942 emit_idivl_reg(cd, REG_ITMP3);
944 if (IS_INMEMORY(dst->flags)) {
945 emit_mov_reg_membase(cd, RDX, REG_SP, dst->vv.regoff * 8);
946 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
949 M_INTMOVE(RDX, dst->vv.regoff);
951 if (dst->vv.regoff != RDX) {
952 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
958 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
959 /* sx.val.i = constant */
962 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
963 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
964 M_INTMOVE(s1, REG_ITMP1);
965 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
966 emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
967 emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
968 emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
969 emit_mov_reg_reg(cd, REG_ITMP1, d);
970 emit_store_dst(jd, iptr, d);
974 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
975 /* sx.val.i = constant */
978 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
979 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
980 M_INTMOVE(s1, REG_ITMP1);
981 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
982 emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
983 emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
984 emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
985 emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
986 emit_mov_reg_reg(cd, REG_ITMP1, d);
987 emit_store_dst(jd, iptr, d);
992 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
995 var1 = VAROP(iptr->s1);
996 var2 = VAROP(iptr->sx.s23.s2);
997 dst = VAROP(iptr->dst);
999 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1001 if (IS_INMEMORY(var1->flags))
1002 M_LLD(RAX, REG_SP, var1->vv.regoff * 8);
1004 M_INTMOVE(var1->vv.regoff, RAX);
1006 if (IS_INMEMORY(var2->flags))
1007 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
1009 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
1014 codegen_add_arithmeticexception_ref(cd);
1017 /* check as described in jvm spec */
1018 disp = dseg_add_s8(cd, 0x8000000000000000LL);
1019 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX);
1021 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1022 M_BEQ(3 + 2 + 3); /* 6 bytes */
1024 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1026 emit_idiv_reg(cd, REG_ITMP3);
1028 if (IS_INMEMORY(dst->flags)) {
1029 M_LST(RAX, REG_SP, dst->vv.regoff * 8);
1030 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1033 M_INTMOVE(RAX, dst->vv.regoff);
1035 if (dst->vv.regoff != RDX) {
1036 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1042 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1045 var1 = VAROP(iptr->s1);
1046 var2 = VAROP(iptr->sx.s23.s2);
1047 dst = VAROP(iptr->dst);
1049 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1051 if (IS_INMEMORY(var1->flags))
1052 M_LLD(REG_ITMP1, REG_SP, var1->vv.regoff * 8);
1054 M_INTMOVE(var1->vv.regoff, REG_ITMP1);
1056 if (IS_INMEMORY(var2->flags))
1057 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
1059 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
1061 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1062 M_INTMOVE(s1, REG_ITMP1);
1063 s2 = emit_load_s2(jd, iptr, REG_ITMP3);
1064 M_INTMOVE(s2, REG_ITMP3);
1069 codegen_add_arithmeticexception_ref(cd);
1072 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1074 /* check as described in jvm spec */
1075 disp = dseg_add_s8(cd, 0x8000000000000000LL);
1076 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1);
1080 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
1082 M_LXOR(RDX, RDX); /* 3 bytes */
1083 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1084 M_BEQ(2 + 3); /* 6 bytes */
1087 emit_idiv_reg(cd, REG_ITMP3);
1089 if (IS_INMEMORY(dst->flags)) {
1090 M_LST(RDX, REG_SP, dst->vv.regoff * 8);
1091 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1094 M_INTMOVE(RDX, dst->vv.regoff);
1096 if (dst->vv.regoff != RDX) {
1097 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1103 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1104 /* sx.val.i = constant */
1107 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1108 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1109 M_INTMOVE(s1, REG_ITMP1);
1110 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1111 emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
1112 emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
1113 emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
1114 emit_mov_reg_reg(cd, REG_ITMP1, d);
1115 emit_store_dst(jd, iptr, d);
1119 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1120 /* sx.val.l = constant */
1123 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1124 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1125 M_INTMOVE(s1, REG_ITMP1);
1126 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1127 emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
1128 emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1129 emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
1130 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1131 emit_mov_reg_reg(cd, REG_ITMP1, d);
1132 emit_store_dst(jd, iptr, d);
1136 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1139 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1140 emit_ishift(jd, SHIFT_SHL, iptr);
1144 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1145 /* sx.val.i = constant */
1148 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1149 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1151 M_ISLL_IMM(iptr->sx.val.i, d);
1152 emit_store_dst(jd, iptr, d);
1156 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1159 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1160 emit_ishift(jd, SHIFT_SAR, iptr);
1164 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1165 /* sx.val.i = constant */
1168 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1169 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1171 M_ISRA_IMM(iptr->sx.val.i, d);
1172 emit_store_dst(jd, iptr, d);
1176 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1179 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1180 emit_ishift(jd, SHIFT_SHR, iptr);
1184 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1185 /* sx.val.i = constant */
1188 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1189 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1191 M_ISRL_IMM(iptr->sx.val.i, d);
1192 emit_store_dst(jd, iptr, d);
1196 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1199 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1200 emit_lshift(jd, SHIFT_SHL, iptr);
1204 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1205 /* sx.val.i = constant */
1208 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1209 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1211 M_LSLL_IMM(iptr->sx.val.i, d);
1212 emit_store_dst(jd, iptr, d);
1216 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1219 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1220 emit_lshift(jd, SHIFT_SAR, iptr);
1224 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1225 /* sx.val.i = constant */
1228 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1229 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1231 M_LSRA_IMM(iptr->sx.val.i, d);
1232 emit_store_dst(jd, iptr, d);
1236 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1239 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1240 emit_lshift(jd, SHIFT_SHR, iptr);
1244 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1245 /* sx.val.l = constant */
1248 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1249 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1251 M_LSRL_IMM(iptr->sx.val.i, d);
1252 emit_store_dst(jd, iptr, d);
1256 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1259 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1260 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1261 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1268 emit_store_dst(jd, iptr, d);
1272 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1273 /* sx.val.i = constant */
1276 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1277 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1279 M_IAND_IMM(iptr->sx.val.i, d);
1280 emit_store_dst(jd, iptr, d);
1284 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1287 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1288 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1289 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1296 emit_store_dst(jd, iptr, d);
1300 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1301 /* sx.val.l = constant */
1304 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1305 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1307 if (IS_IMM32(iptr->sx.val.l))
1308 M_LAND_IMM(iptr->sx.val.l, d);
1310 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1311 M_LAND(REG_ITMP2, d);
1313 emit_store_dst(jd, iptr, d);
1317 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1320 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1321 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1322 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1329 emit_store_dst(jd, iptr, d);
1333 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1334 /* sx.val.i = constant */
1337 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1338 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1340 M_IOR_IMM(iptr->sx.val.i, d);
1341 emit_store_dst(jd, iptr, d);
1345 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1348 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1349 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1350 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1357 emit_store_dst(jd, iptr, d);
1361 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1362 /* sx.val.l = constant */
1365 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1366 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1368 if (IS_IMM32(iptr->sx.val.l))
1369 M_LOR_IMM(iptr->sx.val.l, d);
1371 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1372 M_LOR(REG_ITMP2, d);
1374 emit_store_dst(jd, iptr, d);
1378 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1381 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1382 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1383 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1390 emit_store_dst(jd, iptr, d);
1394 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1395 /* sx.val.i = constant */
1398 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1399 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1401 M_IXOR_IMM(iptr->sx.val.i, d);
1402 emit_store_dst(jd, iptr, d);
1406 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1409 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1410 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1411 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1418 emit_store_dst(jd, iptr, d);
1422 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1423 /* sx.val.l = constant */
1426 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1427 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1429 if (IS_IMM32(iptr->sx.val.l))
1430 M_LXOR_IMM(iptr->sx.val.l, d);
1432 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1433 M_LXOR(REG_ITMP2, d);
1435 emit_store_dst(jd, iptr, d);
1440 /* floating operations ************************************************/
1442 case ICMD_FNEG: /* ..., value ==> ..., - value */
1445 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1446 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1447 disp = dseg_add_s4(cd, 0x80000000);
1449 emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1450 emit_xorps_reg_reg(cd, REG_FTMP2, d);
1451 emit_store_dst(jd, iptr, d);
1455 case ICMD_DNEG: /* ..., value ==> ..., - value */
1458 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1459 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1460 disp = dseg_add_s8(cd, 0x8000000000000000);
1462 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1463 emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1464 emit_store_dst(jd, iptr, d);
1468 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1471 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1472 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1473 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1480 emit_store_dst(jd, iptr, d);
1484 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1487 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1488 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1489 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1496 emit_store_dst(jd, iptr, d);
1500 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1503 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1504 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1505 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1507 M_FLTMOVE(s2, REG_FTMP2);
1512 emit_store_dst(jd, iptr, d);
1516 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1519 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1520 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1521 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1523 M_FLTMOVE(s2, REG_FTMP2);
1528 emit_store_dst(jd, iptr, d);
1532 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1533 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1534 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1535 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1542 emit_store_dst(jd, iptr, d);
1546 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1549 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1550 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1551 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1558 emit_store_dst(jd, iptr, d);
1562 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1565 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1566 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1567 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1569 M_FLTMOVE(s2, REG_FTMP2);
1574 emit_store_dst(jd, iptr, d);
1578 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1581 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1582 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1583 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1585 M_FLTMOVE(s2, REG_FTMP2);
1590 emit_store_dst(jd, iptr, d);
1594 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1595 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1596 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1598 emit_store_dst(jd, iptr, d);
1601 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1602 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1603 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1605 emit_store_dst(jd, iptr, d);
1608 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1611 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1612 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1614 emit_store_dst(jd, iptr, d);
1618 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1621 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1622 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1624 emit_store_dst(jd, iptr, d);
1628 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1629 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1630 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1632 emit_store_dst(jd, iptr, d);
1633 /* TODO: corner cases ? */
1636 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1639 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1640 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1642 M_ICMP_IMM(0x80000000, d); /* corner cases */
1643 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1644 ((REG_RESULT == d) ? 0 : 3);
1646 M_FLTMOVE(s1, REG_FTMP1);
1647 M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1649 M_INTMOVE(REG_RESULT, d);
1650 emit_store_dst(jd, iptr, d);
1654 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1657 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1658 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1660 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1661 M_LCMP(REG_ITMP2, d); /* corner cases */
1662 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1663 ((REG_RESULT == d) ? 0 : 3);
1665 M_FLTMOVE(s1, REG_FTMP1);
1666 M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1668 M_INTMOVE(REG_RESULT, d);
1669 emit_store_dst(jd, iptr, d);
1673 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1676 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1677 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1679 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1680 M_LCMP(REG_ITMP2, d); /* corner cases */
1681 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1682 ((REG_RESULT == d) ? 0 : 3);
1684 M_FLTMOVE(s1, REG_FTMP1);
1685 M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1687 M_INTMOVE(REG_RESULT, d);
1688 emit_store_dst(jd, iptr, d);
1692 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1695 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1696 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1698 emit_store_dst(jd, iptr, d);
1702 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1705 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1706 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1708 emit_store_dst(jd, iptr, d);
1712 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1713 /* == => 0, < => 1, > => -1 */
1714 /* ICMD_FCMPL: s1 < s2 -> d := 1 */ /* TODO is this correct ? */
1717 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1718 /* == => 0, < => 1, > => -1 */
1720 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1721 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1722 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1726 M_BGT(SZ_BRC + SZ_BRC + SZ_BRC);
1727 M_BLT(SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC);
1728 M_BEQ(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC);
1730 N_LHI(d, iptr->opc == ICMD_FCMPL ? -1 : 1); /* s1 > s2 */
1731 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1732 N_LHI(d, iptr->opc == ICMD_FCMPL ? 1 : -1); /* s1 < s2 */
1733 M_BR(SZ_BRC + SZ_LHI);
1734 N_LHI(d, 0); /* s1 == s2 */
1736 emit_store_dst(jd, iptr, d);
1740 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1741 /* == => 0, < => 1, > => -1 */
1744 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1745 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1746 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1748 M_MOV_IMM(1, REG_ITMP1);
1749 M_MOV_IMM(-1, REG_ITMP2);
1750 emit_ucomisd_reg_reg(cd, s1, s2);
1751 M_CMOVB(REG_ITMP1, d);
1752 M_CMOVA(REG_ITMP2, d);
1753 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1754 emit_store_dst(jd, iptr, d);
1758 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1759 /* == => 0, < => 1, > => -1 */
1762 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1763 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1764 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1766 M_MOV_IMM(1, REG_ITMP1);
1767 M_MOV_IMM(-1, REG_ITMP2);
1768 emit_ucomisd_reg_reg(cd, s1, s2);
1769 M_CMOVB(REG_ITMP1, d);
1770 M_CMOVA(REG_ITMP2, d);
1771 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1772 emit_store_dst(jd, iptr, d);
1777 /* memory operations **************************************************/
1779 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1781 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1782 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1783 gen_nullptr_check(s1);
1784 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1785 emit_store_dst(jd, iptr, d);
1789 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1792 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1793 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1794 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1795 if (INSTRUCTION_MUST_CHECK(iptr)) {
1796 gen_nullptr_check(s1);
1799 emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
1800 emit_store_dst(jd, iptr, d);
1804 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1807 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1808 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1809 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1810 if (INSTRUCTION_MUST_CHECK(iptr)) {
1811 gen_nullptr_check(s1);
1814 emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
1815 emit_store_dst(jd, iptr, d);
1819 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1822 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1823 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1824 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1825 if (INSTRUCTION_MUST_CHECK(iptr)) {
1826 gen_nullptr_check(s1);
1829 emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
1830 emit_store_dst(jd, iptr, d);
1834 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1837 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1838 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1839 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1840 if (INSTRUCTION_MUST_CHECK(iptr)) {
1841 gen_nullptr_check(s1);
1844 emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
1845 emit_store_dst(jd, iptr, d);
1849 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1852 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1853 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1854 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1855 if (INSTRUCTION_MUST_CHECK(iptr)) {
1856 gen_nullptr_check(s1);
1859 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1860 emit_store_dst(jd, iptr, d);
1864 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1867 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1868 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1869 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1870 if (INSTRUCTION_MUST_CHECK(iptr)) {
1871 gen_nullptr_check(s1);
1874 emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1875 emit_store_dst(jd, iptr, d);
1879 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1882 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1883 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1884 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1885 if (INSTRUCTION_MUST_CHECK(iptr)) {
1886 gen_nullptr_check(s1);
1889 emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1890 emit_store_dst(jd, iptr, d);
1894 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1895 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1896 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1897 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1898 emit_array_checks(cd, iptr, s1, s2);
1900 M_INTMOVE(s1, REG_ITMP1);
1901 N_SLL(REG_ITMP1, 2, RN); /* scale index by 4 */
1902 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP1, s2);
1903 emit_store_dst(jd, iptr, d);
1906 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1909 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1910 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1911 if (INSTRUCTION_MUST_CHECK(iptr)) {
1912 gen_nullptr_check(s1);
1915 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1916 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1920 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1923 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1924 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1925 if (INSTRUCTION_MUST_CHECK(iptr)) {
1926 gen_nullptr_check(s1);
1929 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1930 emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
1934 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1937 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1938 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1939 if (INSTRUCTION_MUST_CHECK(iptr)) {
1940 gen_nullptr_check(s1);
1943 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1944 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1948 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1951 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1952 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1953 if (INSTRUCTION_MUST_CHECK(iptr)) {
1954 gen_nullptr_check(s1);
1957 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1958 emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
1962 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1965 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1966 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1967 if (INSTRUCTION_MUST_CHECK(iptr)) {
1968 gen_nullptr_check(s1);
1971 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1972 emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
1976 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1979 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1980 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1981 if (INSTRUCTION_MUST_CHECK(iptr)) {
1982 gen_nullptr_check(s1);
1985 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1986 emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
1990 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1993 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1994 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1995 if (INSTRUCTION_MUST_CHECK(iptr)) {
1996 gen_nullptr_check(s1);
1999 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
2000 emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2004 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2007 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2008 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2009 if (INSTRUCTION_MUST_CHECK(iptr)) {
2010 gen_nullptr_check(s1);
2013 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
2017 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2021 codegen_add_arraystoreexception_ref(cd);
2023 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2024 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2025 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
2026 emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2031 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2034 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2035 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2036 if (INSTRUCTION_MUST_CHECK(iptr)) {
2037 gen_nullptr_check(s1);
2040 emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2044 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2047 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2048 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2049 if (INSTRUCTION_MUST_CHECK(iptr)) {
2050 gen_nullptr_check(s1);
2053 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
2057 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2060 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2061 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2062 if (INSTRUCTION_MUST_CHECK(iptr)) {
2063 gen_nullptr_check(s1);
2066 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2070 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2073 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2074 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2075 if (INSTRUCTION_MUST_CHECK(iptr)) {
2076 gen_nullptr_check(s1);
2079 emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
2083 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2086 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2087 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2088 if (INSTRUCTION_MUST_CHECK(iptr)) {
2089 gen_nullptr_check(s1);
2093 if (IS_IMM32(iptr->sx.s23.s3.constval)) {
2094 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2096 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2097 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2102 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2105 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2106 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2107 if (INSTRUCTION_MUST_CHECK(iptr)) {
2108 gen_nullptr_check(s1);
2111 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2116 case ICMD_GETSTATIC: /* ... ==> ..., value */
2118 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2119 uf = iptr->sx.s23.s3.uf;
2120 fieldtype = uf->fieldref->parseddesc.fd->type;
2121 disp = dseg_add_unique_address(cd, NULL);
2123 /* PROFILE_CYCLE_STOP; */
2125 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2127 /* PROFILE_CYCLE_START; */
2130 fi = iptr->sx.s23.s3.fmiref->p.field;
2131 fieldtype = fi->type;
2132 disp = dseg_add_address(cd, &(fi->value));
2134 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2137 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
2139 PROFILE_CYCLE_START;
2143 M_ALD(REG_ITMP1, REG_PV, disp);
2145 switch (fieldtype) {
2147 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2148 M_ILD(d, REG_ITMP1, 0);
2151 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2152 M_LLD(d, REG_ITMP1, 0);
2155 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2156 M_ALD(d, REG_ITMP1, 0);
2159 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2160 M_FLD(d, REG_ITMP1, 0);
2163 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2164 M_DLD(d, REG_ITMP1, 0);
2168 emit_store_dst(jd, iptr, d);
2172 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2174 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2175 uf = iptr->sx.s23.s3.uf;
2176 fieldtype = uf->fieldref->parseddesc.fd->type;
2177 disp = dseg_add_unique_address(cd, uf);
2179 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2182 fi = iptr->sx.s23.s3.fmiref->p.field;
2183 fieldtype = fi->type;
2184 disp = dseg_add_address(cd, &(fi->value));
2186 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2187 codegen_addpatchref(cd, PATCHER_clinit,
2191 M_ALD(REG_ITMP1, REG_PV, disp);
2192 switch (fieldtype) {
2194 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2195 M_IST(s1, REG_ITMP1, 0);
2198 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2199 M_LST(s1, REG_ITMP1, 0);
2202 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2203 M_AST(s1, REG_ITMP1, 0);
2206 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2207 M_FST(s1, REG_ITMP1, 0);
2210 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2211 M_DST(s1, REG_ITMP1, 0);
2216 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2217 /* val = value (in current instruction) */
2218 /* following NOP) */
2221 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2222 uf = iptr->sx.s23.s3.uf;
2223 fieldtype = uf->fieldref->parseddesc.fd->type;
2224 disp = dseg_add_unique_address(cd, uf);
2226 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2229 fi = iptr->sx.s23.s3.fmiref->p.field;
2230 fieldtype = fi->type;
2231 disp = dseg_add_address(cd, &(fi->value));
2233 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2234 codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class,
2238 M_ALD(REG_ITMP1, REG_PV, disp);
2240 switch (fieldtype) {
2242 M_IST(REG_ZERO, REG_ITMP1, 0);
2245 M_LST(REG_ZERO, REG_ITMP1, 0);
2248 M_AST(REG_ZERO, REG_ITMP1, 0);
2251 M_FST(REG_ZERO, REG_ITMP1, 0);
2254 M_DST(REG_ZERO, REG_ITMP1, 0);
2260 case ICMD_GETFIELD: /* ... ==> ..., value */
2262 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2263 emit_nullpointer_check(cd, iptr, s1);
2265 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2266 uf = iptr->sx.s23.s3.uf;
2267 fieldtype = uf->fieldref->parseddesc.fd->type;
2270 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2273 fi = iptr->sx.s23.s3.fmiref->p.field;
2274 fieldtype = fi->type;
2278 switch (fieldtype) {
2280 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2284 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2285 if (GET_HIGH_REG(d) == s1) {
2286 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2287 M_ILD(GET_HIGH_REG(d), s1, disp);
2290 M_ILD(GET_HIGH_REG(d), s1, disp);
2291 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2295 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2299 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2303 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2307 emit_store_dst(jd, iptr, d);
2310 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2312 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2313 gen_nullptr_check(s1);
2315 s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2317 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2318 uf = iptr->sx.s23.s3.uf;
2319 fieldtype = uf->fieldref->parseddesc.fd->type;
2323 fi = iptr->sx.s23.s3.fmiref->p.field;
2324 fieldtype = fi->type;
2328 if (IS_INT_LNG_TYPE(fieldtype)) {
2329 if (IS_2_WORD_TYPE(fieldtype))
2330 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2332 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2335 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2337 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2338 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2340 switch (fieldtype) {
2342 M_IST(s2, s1, disp);
2345 /* TODO really order */
2346 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2347 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2350 M_AST(s2, s1, disp);
2353 M_FST(s2, s1, disp);
2356 M_DST(s2, s1, disp);
2361 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2362 /* val = value (in current instruction) */
2363 /* following NOP) */
2366 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2367 gen_nullptr_check(s1);
2369 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2370 uf = iptr->sx.s23.s3.uf;
2371 fieldtype = uf->fieldref->parseddesc.fd->type;
2374 /* PROFILE_CYCLE_STOP; */
2376 codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
2378 /* PROFILE_CYCLE_START; */
2381 fi = iptr->sx.s23.s3.fmiref->p.field;
2382 fieldtype = fi->type;
2386 switch (fieldtype) {
2389 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2394 /* XXX why no check for IS_IMM32? */
2395 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2396 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2403 /* branch operations **************************************************/
2405 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2407 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2408 M_INTMOVE(s1, REG_ITMP1_XPTR);
2412 #ifdef ENABLE_VERIFIER
2413 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2414 uc = iptr->sx.s23.s2.uc;
2416 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2418 #endif /* ENABLE_VERIFIER */
2420 disp = dseg_add_functionptr(cd, asm_handle_exception);
2421 M_ALD(REG_ITMP2, REG_PV, disp);
2422 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2427 case ICMD_GOTO: /* ... ==> ... */
2428 case ICMD_RET: /* ... ==> ... */
2431 codegen_add_branch_ref(cd, iptr->dst.block);
2435 case ICMD_JSR: /* ... ==> ... */
2439 codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2443 case ICMD_IFNULL: /* ..., value ==> ... */
2444 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2447 codegen_add_branch_ref(cd, iptr->dst.block);
2450 case ICMD_IFNONNULL: /* ..., value ==> ... */
2451 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2454 codegen_add_branch_ref(cd, iptr->dst.block);
2457 case ICMD_IFEQ: /* ..., value ==> ... */
2458 case ICMD_IFLT: /* ..., value ==> ... */
2459 case ICMD_IFLE: /* ..., value ==> ... */
2460 case ICMD_IFNE: /* ..., value ==> ... */
2461 case ICMD_IFGT: /* ..., value ==> ... */
2462 case ICMD_IFGE: /* ..., value ==> ... */
2464 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2466 if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
2467 N_CHI(s1, iptr->sx.val.i);
2469 disp = dseg_add_s4(cd, iptr->sx.val.i);
2470 N_LHI(REG_ITMP2, disp);
2471 N_CL(s1, 0, REG_ITMP2, REG_PV);
2474 switch (iptr->opc) {
2494 codegen_add_branch_ref(cd, iptr->dst.block);
2498 case ICMD_IF_LEQ: /* ..., value ==> ... */
2501 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2502 if (IS_IMM32(iptr->sx.val.l))
2503 M_LCMP_IMM(iptr->sx.val.l, s1);
2505 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2506 M_LCMP(REG_ITMP2, s1);
2509 codegen_add_branch_ref(cd, iptr->dst.block);
2513 case ICMD_IF_LLT: /* ..., value ==> ... */
2517 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2518 if (IS_IMM32(iptr->sx.val.l))
2519 M_LCMP_IMM(iptr->sx.val.l, s1);
2521 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2522 M_LCMP(REG_ITMP2, s1);
2525 codegen_add_branch_ref(cd, iptr->dst.block);
2529 case ICMD_IF_LLE: /* ..., value ==> ... */
2533 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2534 if (IS_IMM32(iptr->sx.val.l))
2535 M_LCMP_IMM(iptr->sx.val.l, s1);
2537 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2538 M_LCMP(REG_ITMP2, s1);
2541 codegen_add_branch_ref(cd, iptr->dst.block);
2545 case ICMD_IF_LNE: /* ..., value ==> ... */
2549 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2550 if (IS_IMM32(iptr->sx.val.l))
2551 M_LCMP_IMM(iptr->sx.val.l, s1);
2553 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2554 M_LCMP(REG_ITMP2, s1);
2557 codegen_add_branch_ref(cd, iptr->dst.block);
2561 case ICMD_IF_LGT: /* ..., value ==> ... */
2565 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2566 if (IS_IMM32(iptr->sx.val.l))
2567 M_LCMP_IMM(iptr->sx.val.l, s1);
2569 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2570 M_LCMP(REG_ITMP2, s1);
2573 codegen_add_branch_ref(cd, iptr->dst.block);
2577 case ICMD_IF_LGE: /* ..., value ==> ... */
2581 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2582 if (IS_IMM32(iptr->sx.val.l))
2583 M_LCMP_IMM(iptr->sx.val.l, s1);
2585 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2586 M_LCMP(REG_ITMP2, s1);
2589 codegen_add_branch_ref(cd, iptr->dst.block);
2593 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2594 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2596 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2597 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2600 codegen_add_branch_ref(cd, iptr->dst.block);
2603 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2605 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2606 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2608 /* load low-bits before the branch, so we know the distance */
2609 /* TODO do the loads modify the condition code?
2610 * lr, l, la, lhi dont
2612 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2613 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2614 M_BNE(SZ_BRC + SZ_CR + SZ_BRC);
2617 codegen_add_branch_ref(cd, iptr->dst.block);
2620 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2622 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2623 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2626 codegen_add_branch_ref(cd, iptr->dst.block);
2630 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2634 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2635 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2638 codegen_add_branch_ref(cd, iptr->dst.block);
2642 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2643 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2645 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2646 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2649 codegen_add_branch_ref(cd, iptr->dst.block);
2653 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2657 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2658 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2661 codegen_add_branch_ref(cd, iptr->dst.block);
2665 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2667 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2668 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2671 codegen_add_branch_ref(cd, iptr->dst.block);
2675 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2679 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2680 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2683 codegen_add_branch_ref(cd, iptr->dst.block);
2687 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2689 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2690 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2693 codegen_add_branch_ref(cd, iptr->dst.block);
2697 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2699 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2700 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2703 codegen_add_branch_ref(cd, iptr->dst.block);
2704 /* load low-bits before the branch, so we know the distance */
2705 /* TODO: the loads should not touch the condition code. */
2706 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2707 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2708 M_BGT(SZ_BRC + SZ_CR + SZ_BRC);
2711 codegen_add_branch_ref(cd, iptr->dst.block);
2714 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2716 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2717 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2720 codegen_add_branch_ref(cd, iptr->dst.block);
2724 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2728 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2729 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2732 codegen_add_branch_ref(cd, iptr->dst.block);
2736 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2738 REPLACEMENT_POINT_RETURN(cd, iptr);
2739 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2740 M_INTMOVE(s1, REG_RESULT);
2741 goto nowperformreturn;
2743 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2745 REPLACEMENT_POINT_RETURN(cd, iptr);
2746 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2747 M_INTMOVE(s1, REG_RESULT);
2749 #ifdef ENABLE_VERIFIER
2750 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2751 unresolved_class *uc = iptr->sx.s23.s2.uc;
2753 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2755 #endif /* ENABLE_VERIFIER */
2756 goto nowperformreturn;
2758 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2760 REPLACEMENT_POINT_RETURN(cd, iptr);
2761 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2762 M_LNGMOVE(s1, REG_RESULT_PACKED);
2763 goto nowperformreturn;
2765 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2768 REPLACEMENT_POINT_RETURN(cd, iptr);
2769 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2770 M_FLTMOVE(s1, REG_FRESULT);
2771 goto nowperformreturn;
2773 case ICMD_RETURN: /* ... ==> ... */
2775 REPLACEMENT_POINT_RETURN(cd, iptr);
2781 p = cd->stackframesize;
2783 /* call trace function */
2785 /*emit_verbosecall_exit(jd); TODO */
2787 #if defined(ENABLE_THREADS)
2788 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2789 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2790 M_ALD(REG_ITMP3, REG_PV, disp);
2793 /* we need to save the proper return value */
2795 switch (iptr->opc) {
2797 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2801 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2804 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2807 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2811 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2814 /* and now restore the proper return value */
2816 switch (iptr->opc) {
2818 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2822 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2825 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2828 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2834 /* restore return address */
2836 p--; M_ALD(REG_RA, REG_SP, p * 4);
2838 /* restore saved registers */
2840 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2841 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2843 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2844 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2847 /* deallocate stack */
2849 if (cd->stackframesize)
2850 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2857 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2862 branch_target_t *table;
2864 table = iptr->dst.table;
2866 l = iptr->sx.s23.s2.tablelow;
2867 i = iptr->sx.s23.s3.tablehigh;
2869 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2870 M_INTMOVE(s1, REG_ITMP1);
2873 M_ISUB_IMM(l, REG_ITMP1);
2875 /* number of targets */
2879 M_ICMP_IMM(i - 1, REG_ITMP1);
2882 codegen_add_branch_ref(cd, table[0].block); /* default target */
2884 /* build jump table top down and use address of lowest entry */
2889 dseg_add_target(cd, table->block);
2893 /* length of dataseg after last dseg_add_target is used
2896 M_MOV_IMM(0, REG_ITMP2);
2898 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2905 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2910 lookup_target_t *lookup;
2912 lookup = iptr->dst.lookup;
2914 i = iptr->sx.s23.s2.lookupcount;
2916 MCODECHECK(8 + ((7 + 6) * i) + 5);
2917 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2920 M_ICMP_IMM(lookup->value, s1);
2922 codegen_add_branch_ref(cd, lookup->target.block);
2928 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2934 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2936 bte = iptr->sx.s23.s3.bte;
2940 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2941 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2942 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2943 case ICMD_INVOKEINTERFACE:
2945 REPLACEMENT_POINT_INVOKE(cd, iptr);
2947 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2949 um = iptr->sx.s23.s3.um;
2950 md = um->methodref->parseddesc.md;
2953 lm = iptr->sx.s23.s3.fmiref->p.method;
2955 md = lm->parseddesc;
2959 s3 = md->paramcount;
2961 MCODECHECK((s3 << 1) + 64);
2963 /* copy arguments to registers or stack location */
2965 for (s3 = s3 - 1; s3 >= 0; s3--) {
2966 var = VAR(iptr->sx.s23.s2.args[s3]);
2968 /* Already Preallocated? */
2969 if (var->flags & PREALLOC)
2972 if (IS_INT_LNG_TYPE(var->type)) {
2973 if (!md->params[s3].inmemory) {
2974 if (IS_2_WORD_TYPE(var->type)) {
2976 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2977 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2979 d = emit_load(jd, iptr, var, s1);
2983 s1 = rd->argintregs[md->params[s3].regoff];
2984 d = emit_load(jd, iptr, var, s1);
2989 if (IS_2_WORD_TYPE(var->type)) {
2990 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2991 M_LST(d, REG_SP, md->params[s3].regoff * 4);
2994 d = emit_load(jd, iptr, var, REG_ITMP1);
2995 M_IST(d, REG_SP, md->params[s3].regoff * 4);
3000 if (!md->params[s3].inmemory) {
3001 s1 = rd->argfltregs[md->params[s3].regoff];
3002 d = emit_load(jd, iptr, var, s1);
3006 d = emit_load(jd, iptr, var, REG_FTMP1);
3007 if (IS_2_WORD_TYPE(var->type))
3008 M_DST(d, REG_SP, md->params[s3].regoff * 4);
3010 M_FST(d, REG_SP, md->params[s3].regoff * 4);
3015 switch (iptr->opc) {
3017 disp = dseg_add_functionptr(cd, bte->fp);
3019 N_LHI(REG_ITMP1, disp);
3020 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3023 case ICMD_INVOKESPECIAL:
3024 emit_nullpointer_check(cd, iptr, REG_A0);
3025 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
3028 case ICMD_INVOKESTATIC:
3030 disp = dseg_add_unique_address(cd, um);
3032 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3036 disp = dseg_add_address(cd, lm->stubroutine);
3038 N_LHI(REG_ITMP1, disp);
3039 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3042 case ICMD_INVOKEVIRTUAL:
3043 emit_nullpointer_check(cd, iptr, REG_A0);
3046 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3051 s1 = OFFSET(vftbl_t, table[0]) +
3052 sizeof(methodptr) * lm->vftblindex;
3055 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
3056 M_ALD(REG_PV, REG_METHODPTR, s1);
3059 case ICMD_INVOKEINTERFACE:
3060 emit_nullpointer_check(cd, iptr, REG_A0);
3063 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3069 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3070 sizeof(methodptr*) * lm->class->index;
3072 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3075 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
3076 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3077 M_ALD(REG_PV, REG_METHODPTR, s2);
3081 /* generate the actual call */
3084 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
3085 N_BASR(REG_ITMP1, RN);
3086 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3087 M_LDA(REG_PV, REG_ITMP1, -disp);
3089 /* actually only used for ICMD_BUILTIN */
3091 if (INSTRUCTION_MUST_CHECK(iptr)) {
3094 codegen_add_fillinstacktrace_ref(cd);
3097 /* store return value */
3099 d = md->returntype.type;
3101 if (d != TYPE_VOID) {
3102 if (IS_INT_LNG_TYPE(d)) {
3103 if (IS_2_WORD_TYPE(d)) {
3104 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
3105 M_LNGMOVE(REG_RESULT_PACKED, s1);
3108 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3109 M_INTMOVE(REG_RESULT, s1);
3113 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
3114 M_FLTMOVE(REG_FRESULT, s1);
3116 emit_store_dst(jd, iptr, s1);
3122 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3124 /* val.a: (classinfo*) superclass */
3126 /* superclass is an interface:
3128 * OK if ((sub == NULL) ||
3129 * (sub->vftbl->interfacetablelength > super->index) &&
3130 * (sub->vftbl->interfacetable[-super->index] != NULL));
3132 * superclass is a class:
3134 * OK if ((sub == NULL) || (0
3135 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3136 * super->vftbl->diffval));
3139 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
3140 /* object type cast-check */
3143 vftbl_t *supervftbl;
3146 u1 *class_label_refs[] = { 0 }, *class_label;
3147 u1 *exit_label_refs[] = { 0, 0, 0, 0 };
3149 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3155 super = iptr->sx.s23.s3.c.cls;
3156 superindex = super->index;
3157 supervftbl = super->vftbl;
3160 #if defined(ENABLE_THREADS)
3161 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3163 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3165 /* if class is not resolved, check which code to call */
3167 if (super == NULL) {
3169 exit_label_refs[0] = cd->mcodeptr;
3172 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3174 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3175 iptr->sx.s23.s3.c.ref,
3178 ICONST(REG_ITMP2, ACC_INTERFACE);
3179 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3180 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3181 class_label_refs[0] = cd->mcodeptr;
3185 /* interface checkcast code */
3187 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3188 if (super == NULL) {
3189 codegen_add_patch_ref(cd,
3190 PATCHER_checkcast_instanceof_interface,
3191 iptr->sx.s23.s3.c.ref,
3195 exit_label_refs[1] = cd->mcodeptr;
3199 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3200 M_ILD(REG_ITMP3, REG_ITMP2,
3201 OFFSET(vftbl_t, interfacetablelength));
3202 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3205 codegen_add_classcastexception_ref(cd, s1);
3206 M_ALD(REG_ITMP3, REG_ITMP2,
3207 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3208 superindex * sizeof(methodptr*)));
3211 codegen_add_classcastexception_ref(cd, s1);
3213 if (super == NULL) {
3214 exit_label_refs[2] = cd->mcodeptr;
3219 /* class checkcast code */
3221 class_label = cd->mcodeptr;
3223 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3224 if (super == NULL) {
3225 disp = dseg_add_unique_address(cd, NULL);
3227 codegen_add_patch_ref(cd,
3228 PATCHER_resolve_classref_to_vftbl,
3229 iptr->sx.s23.s3.c.ref,
3233 disp = dseg_add_address(cd, supervftbl);
3235 exit_label_refs[3] = cd->mcodeptr;
3239 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3240 M_ALD(REG_ITMP3, REG_PV, disp);
3241 #if defined(ENABLE_THREADS)
3242 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3244 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3245 /* if (s1 != REG_ITMP1) { */
3246 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3247 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3248 /* #if defined(ENABLE_THREADS) */
3249 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3251 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3254 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3255 M_ISUB(REG_ITMP2, REG_ITMP3);
3256 M_ALD(REG_ITMP3, REG_PV, disp);
3257 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3258 #if defined(ENABLE_THREADS)
3259 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3262 N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3263 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3264 M_BGT(0); /* Branch if greater then */
3265 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3266 codegen_add_classcastexception_ref(cd, s1);
3269 /* resolve labels by adding the correct displacement */
3271 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3272 if (exit_label_refs[s2])
3273 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3276 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3277 if (class_label_refs[s2])
3278 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3281 d = codegen_reg_of_dst(jd, iptr, s1);
3284 /* array type cast-check */
3286 s1 = emit_load_s1(jd, iptr, REG_A0);
3287 M_INTMOVE(s1, REG_A0);
3289 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3290 disp = dseg_add_unique_address(cd, NULL);
3292 codegen_add_patch_ref(cd,
3293 PATCHER_resolve_classref_to_classinfo,
3294 iptr->sx.s23.s3.c.ref,
3298 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3300 M_ALD(REG_A1, REG_PV, disp);
3301 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3302 ICONST(REG_ITMP1, disp); /* TODO negative displacement */
3303 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3304 M_JSR(REG_RA, REG_PV);
3305 N_BASR(REG_ITMP1, RN);
3306 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3307 M_LDA(REG_PV, REG_ITMP1, -disp);
3309 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3312 codegen_add_classcastexception_ref(cd, s1);
3314 d = codegen_reg_of_dst(jd, iptr, s1);
3318 emit_store_dst(jd, iptr, d);
3321 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3324 /* val.a: (classinfo*) superclass */
3326 /* superclass is an interface:
3328 * return (sub != NULL) &&
3329 * (sub->vftbl->interfacetablelength > super->index) &&
3330 * (sub->vftbl->interfacetable[-super->index] != NULL);
3332 * superclass is a class:
3334 * return ((sub != NULL) && (0
3335 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3336 * super->vftbl->diffvall));
3341 vftbl_t *supervftbl;
3344 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3350 super = iptr->sx.s23.s3.c.cls;
3351 superindex = super->index;
3352 supervftbl = super->vftbl;
3355 #if defined(ENABLE_THREADS)
3356 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3358 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3359 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3361 M_MOV(s1, REG_ITMP1);
3365 /* calculate interface instanceof code size */
3369 s2 += (d == REG_ITMP2 ? 1 : 0) + (opt_shownops ? 1 : 0);
3371 /* calculate class instanceof code size */
3375 s3 += (opt_shownops ? 1 : 0);
3377 /* if class is not resolved, check which code to call */
3379 if (super == NULL) {
3381 M_BEQZ(s1, 4 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
3383 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3385 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3386 iptr->sx.s23.s3.c.ref, disp);
3388 M_ILD(REG_ITMP3, REG_PV, disp);
3390 disp = dseg_add_s4(cd, ACC_INTERFACE);
3391 M_ILD(REG_ITMP2, REG_PV, disp);
3392 M_AND(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3393 M_BEQZ(REG_ITMP3, s2 + 1);
3396 /* interface instanceof code */
3398 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3399 if (super == NULL) {
3400 /* If d == REG_ITMP2, then it's destroyed in check
3405 codegen_add_patch_ref(cd,
3406 PATCHER_checkcast_instanceof_interface,
3407 iptr->sx.s23.s3.c.ref, 0);
3414 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3415 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3416 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3417 M_BLEZ(REG_ITMP3, 2);
3418 M_ALD(REG_ITMP1, REG_ITMP1,
3419 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3420 superindex * sizeof(methodptr*)));
3421 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3427 /* class instanceof code */
3429 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3430 if (super == NULL) {
3431 disp = dseg_add_unique_address(cd, NULL);
3433 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3434 iptr->sx.s23.s3.c.ref,
3438 disp = dseg_add_address(cd, supervftbl);
3444 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3445 M_ALD(REG_ITMP2, REG_PV, disp);
3446 #if defined(ENABLE_THREADS)
3447 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3449 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3450 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3451 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3452 #if defined(ENABLE_THREADS)
3453 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3455 M_ISUB(REG_ITMP1, REG_ITMP3);
3456 N_CLR(REG_ITMP1, REG_ITMP2);
3457 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3459 emit_store_dst(jd, iptr, d);
3464 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3468 /* check for negative sizes and copy sizes to stack if necessary */
3470 MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3472 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3474 /* copy SAVEDVAR sizes to stack */
3475 var = VAR(iptr->sx.s23.s2.args[s1]);
3477 /* Already Preallocated? */
3478 if (!(var->flags & PREALLOC)) {
3479 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3480 M_LST(s2, REG_SP, s1 * 8);
3484 /* is a patcher function set? */
3486 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3487 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
3488 iptr->sx.s23.s3.c.ref, 0);
3491 /* a0 = dimension count */
3493 M_MOV_IMM(iptr->s1.argcount, REG_A0);
3495 /* a1 = classinfo */
3497 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3499 /* a2 = pointer to dimensions = stack pointer */
3501 M_MOV(REG_SP, REG_A2);
3503 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3506 /* check for exception before result assignment */
3510 codegen_add_fillinstacktrace_ref(cd);
3512 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3513 M_INTMOVE(REG_RESULT, s1);
3514 emit_store_dst(jd, iptr, s1);
3519 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3523 } /* for instruction */
3525 MCODECHECK(512); /* XXX require a lower number? */
3527 /* At the end of a basic block we may have to append some nops,
3528 because the patcher stub calling code might be longer than the
3529 actual instruction. So codepatching does not change the
3530 following block unintentionally. */
3532 if (cd->mcodeptr < cd->lastmcodeptr) {
3533 while (cd->mcodeptr < cd->lastmcodeptr) {
3538 } /* if (bptr -> flags >= BBREACHED) */
3539 } /* for basic block */
3541 dseg_createlinenumbertable(cd);
3543 /* generate stubs */
3545 emit_exception_stubs(jd);
3546 emit_patcher_stubs(jd);
3548 emit_replacement_stubs(jd);
3553 /* everything's ok */
3559 /* createcompilerstub **********************************************************
3561 Creates a stub routine which calls the compiler.
3563 *******************************************************************************/
3565 #define COMPILERSTUB_DATASIZE (3 * SIZEOF_VOID_P)
3566 #define COMPILERSTUB_CODESIZE (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
3568 #define COMPILERSTUB_SIZE (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE)
3571 u1 *createcompilerstub(methodinfo *m)
3573 u1 *s; /* memory to hold the stub */
3579 s = CNEW(u1, COMPILERSTUB_SIZE);
3581 /* set data pointer and code pointer */
3584 s = s + COMPILERSTUB_DATASIZE;
3586 /* mark start of dump memory area */
3588 dumpsize = dump_size();
3590 cd = DNEW(codegendata);
3593 /* Store the codeinfo pointer in the same place as in the
3594 methodheader for compiled methods. */
3596 code = code_codeinfo_new(m);
3598 d[0] = (ptrint) asm_call_jit_compiler;
3600 d[2] = (ptrint) code;
3602 /* code for the stub */
3604 /* don't touch ITMP3 as it cointains the return address */
3606 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3608 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3609 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3610 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3613 #if defined(ENABLE_STATISTICS)
3615 count_cstub_len += COMPILERSTUB_SIZE;
3618 /* release dump area */
3620 dump_release(dumpsize);
3626 /* createnativestub ************************************************************
3628 Creates a stub routine which calls a native method.
3630 *******************************************************************************/
3633 arguments on stack \
3634 -------------------------------------------------| <- SP on nativestub entry
3636 callee saved int regs (none) |
3637 callee saved float regs (none) | stack frame like in cacao
3638 local variable slots (none) |
3639 arguments for calling methods (none) /
3640 ------------------------------------------------------------------ <- datasp
3645 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3646 0 - 96 register save area for callee /
3647 -------------------------------------------------------- <- SP native method
3649 SP after method entry
3652 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3660 s4 i, j; /* count variables */
3665 /* get required compiler data */
3672 /* initialize variables */
3675 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3677 /* calculate stack frame size */
3679 cd->stackframesize =
3680 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3681 sizeof(localref_table) / SIZEOF_VOID_P +
3682 INT_ARG_CNT + FLT_ARG_CNT +
3683 1 + /* functionptr, TODO: store in data segment */
3686 cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */
3689 cd->stackframesize =
3690 1 + /* r14 - return address */ +
3691 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3692 sizeof(localref_table) / SIZEOF_VOID_P +
3694 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3695 nmd->memuse + /* parameter passing */
3696 96 / SIZEOF_VOID_P /* required by ABI */;
3699 /* create method header */
3701 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3702 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3703 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3704 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3705 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3706 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3707 (void) dseg_addlinenumbertablesize(cd);
3708 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3710 /* generate native method profiling code */
3712 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3713 /* count frequency */
3715 M_MOV_IMM(code, REG_ITMP3);
3716 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3720 /* generate stub code */
3722 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3724 /* save return address */
3726 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3729 #if !defined(NDEBUG)
3730 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3731 emit_verbosecall_enter(jd);
3735 /* get function address (this must happen before the stackframeinfo) */
3737 disp = dseg_add_functionptr(cd, f);
3739 #if !defined(WITH_STATIC_CLASSPATH)
3741 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3744 M_ILD(REG_ITMP1, REG_PV, disp);
3746 j = 96 + (nmd->memuse * 4);
3748 /* todo some arg registers are not volatile in C-abi terms */
3750 /* save integer and float argument registers */
3752 for (i = 0; i < md->paramcount; i++) {
3753 if (! md->params[i].inmemory) {
3754 s1 = md->params[i].regoff;
3756 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3757 if (IS_2_WORD_TYPE(t)) {
3758 /* todo store multiple */
3759 N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3760 N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3762 N_ST(rd->argintregs[s1], j, RN, REG_SP);
3765 if (IS_2_WORD_TYPE(t)) {
3766 N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3768 N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3776 N_ST(REG_ITMP1, j, RN, REG_SP);
3778 /* create dynamic stack info */
3780 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3781 N_LR(REG_A1, REG_PV); /* pv */
3782 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3783 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3785 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3786 M_ILD(REG_ITMP1, REG_PV, disp);
3788 M_CALL(REG_ITMP1); /* call */
3790 /* restore integer and float argument registers */
3792 j = 96 + (nmd->memuse * 4);
3794 for (i = 0; i < md->paramcount; i++) {
3795 if (! md->params[i].inmemory) {
3796 s1 = md->params[i].regoff;
3798 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3799 if (IS_2_WORD_TYPE(t)) {
3800 /* todo load multiple ! */
3801 N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3802 N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3804 N_L(rd->argintregs[s1], j, RN, REG_SP);
3807 if (IS_2_WORD_TYPE(t)) {
3808 N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3810 N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3818 N_L(REG_ITMP1, j, RN, REG_SP);
3820 /* copy or spill arguments to new locations */
3822 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3823 t = md->paramtypes[i].type;
3825 if (IS_INT_LNG_TYPE(t)) {
3827 if (!md->params[i].inmemory) {
3829 s1 = rd->argintregs[md->params[i].regoff];
3831 if (!nmd->params[j].inmemory) {
3832 s2 = rd->argintregs[nmd->params[j].regoff];
3833 if (IS_2_WORD_TYPE(t)) {
3834 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3835 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3840 s2 = nmd->params[j].regoff;
3841 if (IS_2_WORD_TYPE(t)) {
3842 N_LM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3844 N_L(s1, 96 + (s2 * 4), RN, REG_SP);
3849 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3850 s2 = nmd->params[j].regoff;
3852 if (IS_2_WORD_TYPE(t)) {
3853 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3855 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3860 /* We only copy spilled float arguments, as the float argument */
3861 /* registers keep unchanged. */
3863 if (md->params[i].inmemory) {
3864 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3865 s2 = nmd->params[j].regoff;
3867 if (IS_2_WORD_TYPE(t)) {
3868 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3870 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3876 /* put class into second argument register */
3878 if (m->flags & ACC_STATIC) {
3879 disp = dseg_add_address(cd, m->class);
3880 M_ILD(REG_A1, REG_PV, disp);
3883 /* put env into first argument register */
3885 disp = dseg_add_address(cd, _Jv_env);
3886 M_ILD(REG_A0, REG_PV, disp);
3888 /* do the native function call */
3890 M_CALL(REG_ITMP1); /* call */
3892 /* save return value */
3894 t = md->returntype.type;
3896 if (t != TYPE_VOID) {
3897 if (IS_INT_LNG_TYPE(t)) {
3898 if (IS_2_WORD_TYPE(t)) {
3899 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3901 N_ST(REG_RESULT, 96, RN, REG_SP);
3904 if (IS_2_WORD_TYPE(t)) {
3905 N_STD(REG_FRESULT, 96, RN, REG_SP);
3907 N_STE(REG_FRESULT, 96, RN, REG_SP);
3913 #if !defined(NDEBUG)
3914 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3915 emit_verbosecall_exit(jd);
3919 /* remove native stackframe info */
3921 N_LAE(REG_A0, cd->stackframesize * 4, RN, REG_SP);
3922 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3923 M_ILD(REG_ITMP1, REG_PV, disp);
3925 N_LR(REG_ITMP3, REG_RESULT);
3927 /* restore return value */
3929 if (t != TYPE_VOID) {
3930 if (IS_INT_LNG_TYPE(t)) {
3931 if (IS_2_WORD_TYPE(t)) {
3932 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3934 N_L(REG_RESULT, 96, RN, REG_SP);
3937 if (IS_2_WORD_TYPE(t)) {
3938 N_LD(REG_FRESULT, 96, RN, REG_SP);
3940 N_LE(REG_FRESULT, 96, RN, REG_SP);
3945 /* remove stackframe */
3947 N_AHI(REG_SP, cd->stackframesize * 4);
3949 /* test for exception */
3951 N_LTR(REG_ITMP3, REG_ITMP3);
3952 N_BRC(DD_NE, SZ_BRC + SZ_BC);
3953 N_BC(DD_ANY, 0, RN, REG_SP); /* return */
3955 /* handle exception */
3960 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3961 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
3962 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3964 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
3968 /* generate patcher stubs */
3970 emit_patcher_stubs(jd);
3974 return code->entrypoint;
3981 * These are local overrides for various environment variables in Emacs.
3982 * Please do not remove this and leave it at the end of the file, where
3983 * Emacs will automagically detect them.
3984 * ---------------------------------------------------------------------
3987 * indent-tabs-mode: t
3991 * vim:noexpandtab:sw=4:ts=4: