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 7405 2007-02-25 22:34:27Z pm $
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 "vmcore/loader.h"
62 #include "vmcore/options.h"
63 #include "vmcore/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"
76 #include "vm/jit/stacktrace.h"
78 #if defined(ENABLE_LSRA)
79 # include "vm/jit/allocator/lsra.h"
82 #define OOPS() assert(0);
85 u1 *createcompilerstub(methodinfo *m) {
94 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) {
96 return createcompilerstub(NULL);
102 /* codegen *********************************************************************
104 Generates machine code.
106 *******************************************************************************/
109 bool codegen(jitdata *jd)
115 s4 len, s1, s2, s3, d, disp;
118 varinfo *var, *var1, *var2, *dst;
122 constant_classref *cr;
123 unresolved_class *uc;
124 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
125 unresolved_method *um;
126 builtintable_entry *bte;
129 unresolved_field *uf;
132 rplpoint *replacementpoint;
136 /* get required compiler data */
143 /* prevent compiler warnings */
156 /* space to save used callee saved registers */
158 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
159 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
161 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
164 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
167 #if defined(ENABLE_THREADS)
168 /* space to save argument of monitor_enter */
169 OOPS(); /* see powerpc */
171 if (checksync && (m->flags & ACC_SYNCHRONIZED))
172 cd->stackframesize++;
176 /* Keep stack of non-leaf functions 16-byte aligned for calls into
177 native code e.g. libc or jni (alignment problems with
180 if (!jd->isleafmethod || opt_verbosecall)
181 /* TODO really 16 bytes ? */
182 cd->stackframesize = (cd->stackframesize + 3) & ~3;
184 /* create method header */
186 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
187 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
189 #if defined(ENABLE_THREADS)
190 /* IsSync contains the offset relative to the stack pointer for the
191 argument of monitor_exit used in the exception handler. Since the
192 offset could be zero and give a wrong meaning of the flag it is
196 if (checksync && (m->flags & ACC_SYNCHRONIZED))
197 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
201 (void) dseg_add_unique_s4(cd, 0);*/ /* IsSync */
203 disp = dseg_add_unique_address(cd, 0);
205 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
206 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
207 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
209 (void) dseg_addlinenumbertablesize(cd);
211 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
213 /* create exception table */
215 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
216 dseg_add_target(cd, ex->start);
217 dseg_add_target(cd, ex->end);
218 dseg_add_target(cd, ex->handler);
219 (void) dseg_add_unique_address(cd, ex->catchtype.any);
222 /* generate method profiling code */
224 #if defined(ENABLE_PROFILING)
225 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
226 /* count frequency */
228 M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
229 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
230 M_IADD_IMM(1, REG_ITMP2);
231 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
233 /* PROFILE_CYCLE_START; */
237 /* create stack frame (if necessary) */
239 if (cd->stackframesize)
240 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
242 N_LHI(REG_ITMP2, disp);
243 N_ST(REG_SP, 0, REG_ITMP2, REG_PV);
245 /* save used callee saved registers and return address */
247 p = cd->stackframesize;
248 p--; M_AST(REG_RA, REG_SP, p * 4);
250 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
251 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
253 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
254 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
257 /* take arguments out of register or stack frame */
261 for (p = 0, l = 0; p < md->paramcount; p++) {
262 t = md->paramtypes[p].type;
263 varindex = jd->local_map[l * 5 + t];
266 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
269 if (varindex == UNUSED)
274 s1 = md->params[p].regoff;
275 if (IS_INT_LNG_TYPE(t)) { /* integer args */
276 if (IS_2_WORD_TYPE(t))
277 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
278 rd->argintregs[GET_HIGH_REG(s1)]);
280 s2 = rd->argintregs[s1];
281 if (!md->params[p].inmemory) { /* register arguments */
282 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
283 if (IS_2_WORD_TYPE(t))
284 M_LNGMOVE(s2, var->vv.regoff);
286 M_INTMOVE(s2, var->vv.regoff);
288 } else { /* reg arg -> spilled */
289 if (IS_2_WORD_TYPE(t))
290 M_LST(s2, REG_SP, var->vv.regoff * 4);
292 M_IST(s2, REG_SP, var->vv.regoff * 4);
295 } else { /* stack arguments */
296 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
297 if (IS_2_WORD_TYPE(t))
298 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
300 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
302 } else { /* stack arg -> spilled */
303 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
304 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
305 if (IS_2_WORD_TYPE(t)) {
306 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4);
307 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
312 } else { /* floating args */
313 if (!md->params[p].inmemory) { /* register arguments */
314 s2 = rd->argfltregs[s1];
315 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
316 M_FLTMOVE(s2, var->vv.regoff);
318 } else { /* reg arg -> spilled */
319 if (IS_2_WORD_TYPE(t))
320 M_DST(s2, REG_SP, var->vv.regoff * 4);
322 M_FST(s2, REG_SP, var->vv.regoff * 4);
325 } else { /* stack arguments */
326 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
327 if (IS_2_WORD_TYPE(t))
328 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
331 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
333 } else { /* stack-arg -> spilled */
334 if (IS_2_WORD_TYPE(t)) {
335 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
336 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
337 var->vv.regoff = cd->stackframesize + s1;
340 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
341 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
348 /* save monitorenter argument */
350 #if defined(ENABLE_THREADS)
351 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
352 /* stack offset for monitor argument */
356 if (opt_verbosecall) {
357 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
359 for (p = 0; p < INT_ARG_CNT; p++)
360 M_LST(rd->argintregs[p], REG_SP, p * 8);
362 for (p = 0; p < FLT_ARG_CNT; p++)
363 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
365 s1 += INT_ARG_CNT + FLT_ARG_CNT;
368 /* decide which monitor enter function to call */
370 if (m->flags & ACC_STATIC) {
371 M_MOV_IMM(&m->class->object.header, REG_A0);
376 codegen_add_nullpointerexception_ref(cd);
379 M_AST(REG_A0, REG_SP, s1 * 8);
380 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
383 if (opt_verbosecall) {
384 for (p = 0; p < INT_ARG_CNT; p++)
385 M_LLD(rd->argintregs[p], REG_SP, p * 8);
387 for (p = 0; p < FLT_ARG_CNT; p++)
388 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
390 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
396 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
397 emit_verbosecall_enter(jd);
398 #endif /* !defined(NDEBUG) */
402 /* end of header generation */
404 replacementpoint = jd->code->rplpoints;
407 /* walk through all basic blocks */
409 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
411 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
413 if (bptr->flags >= BBREACHED) {
415 /* branch resolving */
417 codegen_resolve_branchrefs(cd, bptr);
419 /* handle replacement points */
422 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
423 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
427 assert(cd->lastmcodeptr <= cd->mcodeptr);
428 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
432 /* copy interface registers to their destination */
437 /* generate basicblock profiling code */
439 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
440 /* count frequency */
442 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
443 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
445 /* if this is an exception handler, start profiling again */
447 if (bptr->type == BBTYPE_EXH)
451 #if defined(ENABLE_LSRA)
455 src = bptr->invars[len];
456 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
457 if (bptr->type == BBTYPE_EXH) {
458 /* d = reg_of_var(rd, src, REG_ITMP1); */
459 if (!IS_INMEMORY(src->flags))
463 M_INTMOVE(REG_ITMP1, d);
464 emit_store(jd, NULL, src, d);
474 var = VAR(bptr->invars[len]);
475 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
476 if (bptr->type == BBTYPE_EXH) {
477 d = codegen_reg_of_var(0, var, REG_ITMP1);
478 M_INTMOVE(REG_ITMP1, d);
479 emit_store(jd, NULL, var, d);
483 assert((var->flags & INOUT));
486 #if defined(ENABLE_LSRA)
489 /* walk through all instructions */
494 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
495 if (iptr->line != currentline) {
496 dseg_addlinenumber(cd, iptr->line);
497 currentline = iptr->line;
500 MCODECHECK(1024); /* 1KB should be enough */
503 case ICMD_NOP: /* ... ==> ... */
504 case ICMD_POP: /* ..., value ==> ... */
505 case ICMD_POP2: /* ..., value, value ==> ... */
506 case ICMD_INLINE_START: /* internal ICMDs */
507 case ICMD_INLINE_END:
510 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
513 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
516 codegen_add_nullpointerexception_ref(cd);
520 /* constant operations ************************************************/
522 case ICMD_ICONST: /* ... ==> ..., constant */
523 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
524 ICONST(d, iptr->sx.val.i);
525 emit_store_dst(jd, iptr, d);
528 case ICMD_LCONST: /* ... ==> ..., constant */
531 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
532 LCONST(d, iptr->sx.val.l);
533 emit_store_dst(jd, iptr, d);
537 case ICMD_FCONST: /* ... ==> ..., constant */
538 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
539 disp = dseg_add_float(cd, iptr->sx.val.f);
540 M_FLDN(d, REG_PV, disp, REG_ITMP1);
541 emit_store_dst(jd, iptr, d);
544 case ICMD_DCONST: /* ... ==> ..., constant */
547 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
548 disp = dseg_add_double(cd, iptr->sx.val.d);
549 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, d);
550 emit_store_dst(jd, iptr, d);
554 case ICMD_ACONST: /* ... ==> ..., constant */
555 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
557 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
558 cr = iptr->sx.val.c.ref;
559 disp = dseg_add_unique_address(cd, cr);
561 /* PROFILE_CYCLE_STOP; */
563 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
566 /* PROFILE_CYCLE_START; */
568 M_ALD(d, REG_PV, disp);
570 if (iptr->sx.val.anyptr == 0) {
573 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
574 M_ALD(d, REG_PV, disp);
577 emit_store_dst(jd, iptr, d);
581 /* load/store/copy/move operations ************************************/
583 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
584 case ICMD_ALOAD: /* s1 = local variable */
588 case ICMD_ISTORE: /* ..., value ==> ... */
594 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
598 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
599 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
602 /* integer operations *************************************************/
604 case ICMD_INEG: /* ..., value ==> ..., - value */
607 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
608 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
611 emit_store_dst(jd, iptr, d);
615 case ICMD_LNEG: /* ..., value ==> ..., - value */
618 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
619 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
622 emit_store_dst(jd, iptr, d);
626 case ICMD_I2L: /* ..., value ==> ..., value */
629 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
630 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
632 emit_store_dst(jd, iptr, d);
636 case ICMD_L2I: /* ..., value ==> ..., value */
639 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
640 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
642 emit_store_dst(jd, iptr, d);
646 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
649 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
650 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
652 emit_store_dst(jd, iptr, d);
656 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
659 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
660 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
662 emit_store_dst(jd, iptr, d);
666 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
669 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
670 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
672 emit_store_dst(jd, iptr, d);
677 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
679 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
680 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
681 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
688 emit_store_dst(jd, iptr, d);
693 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
694 /* sx.val.i = constant */
695 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
696 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
699 M_IADD_IMM(iptr->sx.val.i, d);
700 emit_store_dst(jd, iptr, d);
703 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
706 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
707 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
708 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
715 emit_store_dst(jd, iptr, d);
719 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
720 /* sx.val.l = constant */
723 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
724 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
726 if (IS_IMM32(iptr->sx.val.l))
727 M_LADD_IMM(iptr->sx.val.l, d);
729 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
730 M_LADD(REG_ITMP2, d);
732 emit_store_dst(jd, iptr, d);
736 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
738 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
739 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
740 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
742 M_INTMOVE(s1, REG_ITMP1);
743 M_ISUB(s2, REG_ITMP1);
744 M_INTMOVE(REG_ITMP1, d);
749 emit_store_dst(jd, iptr, d);
753 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
754 /* sx.val.i = constant */
757 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
758 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
760 M_ISUB_IMM(iptr->sx.val.i, d);
761 emit_store_dst(jd, iptr, d);
765 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
768 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
769 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
770 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
772 M_INTMOVE(s1, REG_ITMP1);
773 M_LSUB(s2, REG_ITMP1);
774 M_INTMOVE(REG_ITMP1, d);
779 emit_store_dst(jd, iptr, d);
783 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
784 /* sx.val.l = constant */
787 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
788 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
790 if (IS_IMM32(iptr->sx.val.l))
791 M_LSUB_IMM(iptr->sx.val.l, d);
793 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
794 M_LSUB(REG_ITMP2, d);
796 emit_store_dst(jd, iptr, d);
800 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
803 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
804 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
805 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
812 emit_store_dst(jd, iptr, d);
816 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
817 /* sx.val.i = constant */
820 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
821 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
822 if (iptr->sx.val.i == 2) {
826 M_IMUL_IMM(s1, iptr->sx.val.i, d);
827 emit_store_dst(jd, iptr, d);
831 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
834 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
835 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
836 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
843 emit_store_dst(jd, iptr, d);
847 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
848 /* sx.val.l = constant */
851 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
852 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
853 if (IS_IMM32(iptr->sx.val.l))
854 M_LMUL_IMM(s1, iptr->sx.val.l, d);
856 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
858 M_LMUL(REG_ITMP2, d);
860 emit_store_dst(jd, iptr, d);
864 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
867 var1 = VAROP(iptr->s1);
868 var2 = VAROP(iptr->sx.s23.s2);
869 dst = VAROP(iptr->dst);
871 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
872 if (IS_INMEMORY(var1->flags))
873 M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
875 M_INTMOVE(var1->vv.regoff, RAX);
877 if (IS_INMEMORY(var2->flags))
878 M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
880 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
885 codegen_add_arithmeticexception_ref(cd);
888 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
889 emit_jcc(cd, CC_NE, 4 + 6);
890 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
891 emit_jcc(cd, CC_E, 3 + 1 + 3); /* 6 bytes */
893 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
895 emit_idivl_reg(cd, REG_ITMP3);
897 if (IS_INMEMORY(dst->flags)) {
898 emit_mov_reg_membase(cd, RAX, REG_SP, dst->vv.regoff * 8);
899 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
902 M_INTMOVE(RAX, dst->vv.regoff);
904 if (dst->vv.regoff != RDX) {
905 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
911 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
914 var1 = VAROP(iptr->s1);
915 var2 = VAROP(iptr->sx.s23.s2);
916 dst = VAROP(iptr->dst);
918 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
919 if (IS_INMEMORY(var1->flags))
920 M_ILD(RAX, REG_SP, var1->vv.regoff * 8);
922 M_INTMOVE(var1->vv.regoff, RAX);
924 if (IS_INMEMORY(var2->flags))
925 M_ILD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
927 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
932 codegen_add_arithmeticexception_ref(cd);
935 emit_mov_reg_reg(cd, RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
937 emit_alul_imm_reg(cd, ALU_CMP, 0x80000000, RAX); /* check as described in jvm spec */
938 emit_jcc(cd, CC_NE, 2 + 4 + 6);
941 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
942 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP3); /* 4 bytes */
943 emit_jcc(cd, CC_E, 1 + 3); /* 6 bytes */
946 emit_idivl_reg(cd, REG_ITMP3);
948 if (IS_INMEMORY(dst->flags)) {
949 emit_mov_reg_membase(cd, RDX, REG_SP, dst->vv.regoff * 8);
950 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
953 M_INTMOVE(RDX, dst->vv.regoff);
955 if (dst->vv.regoff != RDX) {
956 emit_mov_reg_reg(cd, REG_ITMP2, RDX); /* restore %rdx */
962 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
963 /* sx.val.i = constant */
966 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
967 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
968 M_INTMOVE(s1, REG_ITMP1);
969 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
970 emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
971 emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
972 emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
973 emit_mov_reg_reg(cd, REG_ITMP1, d);
974 emit_store_dst(jd, iptr, d);
978 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
979 /* sx.val.i = constant */
982 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
983 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
984 M_INTMOVE(s1, REG_ITMP1);
985 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
986 emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
987 emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
988 emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
989 emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
990 emit_mov_reg_reg(cd, REG_ITMP1, d);
991 emit_store_dst(jd, iptr, d);
996 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
999 var1 = VAROP(iptr->s1);
1000 var2 = VAROP(iptr->sx.s23.s2);
1001 dst = VAROP(iptr->dst);
1003 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1005 if (IS_INMEMORY(var1->flags))
1006 M_LLD(RAX, REG_SP, var1->vv.regoff * 8);
1008 M_INTMOVE(var1->vv.regoff, RAX);
1010 if (IS_INMEMORY(var2->flags))
1011 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
1013 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
1018 codegen_add_arithmeticexception_ref(cd);
1021 /* check as described in jvm spec */
1022 disp = dseg_add_s8(cd, 0x8000000000000000LL);
1023 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX);
1025 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1026 M_BEQ(3 + 2 + 3); /* 6 bytes */
1028 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1030 emit_idiv_reg(cd, REG_ITMP3);
1032 if (IS_INMEMORY(dst->flags)) {
1033 M_LST(RAX, REG_SP, dst->vv.regoff * 8);
1034 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1037 M_INTMOVE(RAX, dst->vv.regoff);
1039 if (dst->vv.regoff != RDX) {
1040 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1046 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1049 var1 = VAROP(iptr->s1);
1050 var2 = VAROP(iptr->sx.s23.s2);
1051 dst = VAROP(iptr->dst);
1053 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1055 if (IS_INMEMORY(var1->flags))
1056 M_LLD(REG_ITMP1, REG_SP, var1->vv.regoff * 8);
1058 M_INTMOVE(var1->vv.regoff, REG_ITMP1);
1060 if (IS_INMEMORY(var2->flags))
1061 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
1063 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
1065 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1066 M_INTMOVE(s1, REG_ITMP1);
1067 s2 = emit_load_s2(jd, iptr, REG_ITMP3);
1068 M_INTMOVE(s2, REG_ITMP3);
1073 codegen_add_arithmeticexception_ref(cd);
1076 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1078 /* check as described in jvm spec */
1079 disp = dseg_add_s8(cd, 0x8000000000000000LL);
1080 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1);
1084 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
1086 M_LXOR(RDX, RDX); /* 3 bytes */
1087 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1088 M_BEQ(2 + 3); /* 6 bytes */
1091 emit_idiv_reg(cd, REG_ITMP3);
1093 if (IS_INMEMORY(dst->flags)) {
1094 M_LST(RDX, REG_SP, dst->vv.regoff * 8);
1095 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1098 M_INTMOVE(RDX, dst->vv.regoff);
1100 if (dst->vv.regoff != RDX) {
1101 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1107 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1108 /* sx.val.i = constant */
1111 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1112 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1113 M_INTMOVE(s1, REG_ITMP1);
1114 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1115 emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
1116 emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
1117 emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
1118 emit_mov_reg_reg(cd, REG_ITMP1, d);
1119 emit_store_dst(jd, iptr, d);
1123 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1124 /* sx.val.l = constant */
1127 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1128 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1129 M_INTMOVE(s1, REG_ITMP1);
1130 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1131 emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
1132 emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1133 emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
1134 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1135 emit_mov_reg_reg(cd, REG_ITMP1, d);
1136 emit_store_dst(jd, iptr, d);
1140 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1143 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1144 emit_ishift(jd, SHIFT_SHL, iptr);
1148 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1149 /* sx.val.i = constant */
1152 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1153 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1155 M_ISLL_IMM(iptr->sx.val.i, d);
1156 emit_store_dst(jd, iptr, d);
1160 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1163 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1164 emit_ishift(jd, SHIFT_SAR, iptr);
1168 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1169 /* sx.val.i = constant */
1172 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1173 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1175 M_ISRA_IMM(iptr->sx.val.i, d);
1176 emit_store_dst(jd, iptr, d);
1180 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1183 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1184 emit_ishift(jd, SHIFT_SHR, iptr);
1188 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1189 /* sx.val.i = constant */
1192 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1193 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1195 M_ISRL_IMM(iptr->sx.val.i, d);
1196 emit_store_dst(jd, iptr, d);
1200 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1203 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1204 emit_lshift(jd, SHIFT_SHL, iptr);
1208 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1209 /* sx.val.i = constant */
1212 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1213 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1215 M_LSLL_IMM(iptr->sx.val.i, d);
1216 emit_store_dst(jd, iptr, d);
1220 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1223 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1224 emit_lshift(jd, SHIFT_SAR, iptr);
1228 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1229 /* sx.val.i = constant */
1232 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1233 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1235 M_LSRA_IMM(iptr->sx.val.i, d);
1236 emit_store_dst(jd, iptr, d);
1240 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1243 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1244 emit_lshift(jd, SHIFT_SHR, iptr);
1248 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1249 /* sx.val.l = constant */
1252 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1253 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1255 M_LSRL_IMM(iptr->sx.val.i, d);
1256 emit_store_dst(jd, iptr, d);
1260 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1263 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1264 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1265 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1272 emit_store_dst(jd, iptr, d);
1276 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1277 /* sx.val.i = constant */
1280 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1281 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1283 M_IAND_IMM(iptr->sx.val.i, d);
1284 emit_store_dst(jd, iptr, d);
1288 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1291 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1292 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1293 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1300 emit_store_dst(jd, iptr, d);
1304 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1305 /* sx.val.l = constant */
1308 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1309 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1311 if (IS_IMM32(iptr->sx.val.l))
1312 M_LAND_IMM(iptr->sx.val.l, d);
1314 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1315 M_LAND(REG_ITMP2, d);
1317 emit_store_dst(jd, iptr, d);
1321 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1324 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1325 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1326 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1333 emit_store_dst(jd, iptr, d);
1337 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1338 /* sx.val.i = constant */
1341 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1342 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1344 M_IOR_IMM(iptr->sx.val.i, d);
1345 emit_store_dst(jd, iptr, d);
1349 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1352 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1353 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1354 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1361 emit_store_dst(jd, iptr, d);
1365 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1366 /* sx.val.l = constant */
1369 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1370 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1372 if (IS_IMM32(iptr->sx.val.l))
1373 M_LOR_IMM(iptr->sx.val.l, d);
1375 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1376 M_LOR(REG_ITMP2, d);
1378 emit_store_dst(jd, iptr, d);
1382 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1385 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1386 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1387 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1394 emit_store_dst(jd, iptr, d);
1398 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1399 /* sx.val.i = constant */
1402 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1403 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1405 M_IXOR_IMM(iptr->sx.val.i, d);
1406 emit_store_dst(jd, iptr, d);
1410 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1413 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1414 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1415 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1422 emit_store_dst(jd, iptr, d);
1426 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1427 /* sx.val.l = constant */
1430 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1431 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1433 if (IS_IMM32(iptr->sx.val.l))
1434 M_LXOR_IMM(iptr->sx.val.l, d);
1436 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1437 M_LXOR(REG_ITMP2, d);
1439 emit_store_dst(jd, iptr, d);
1444 /* floating operations ************************************************/
1446 case ICMD_FNEG: /* ..., value ==> ..., - value */
1449 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1450 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1451 disp = dseg_add_s4(cd, 0x80000000);
1453 emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1454 emit_xorps_reg_reg(cd, REG_FTMP2, d);
1455 emit_store_dst(jd, iptr, d);
1459 case ICMD_DNEG: /* ..., value ==> ..., - value */
1462 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1463 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1464 disp = dseg_add_s8(cd, 0x8000000000000000);
1466 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1467 emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1468 emit_store_dst(jd, iptr, d);
1472 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1475 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1476 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1477 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1484 emit_store_dst(jd, iptr, d);
1488 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1491 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1492 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1493 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1500 emit_store_dst(jd, iptr, d);
1504 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1507 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1508 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1509 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1511 M_FLTMOVE(s2, REG_FTMP2);
1516 emit_store_dst(jd, iptr, d);
1520 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1523 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1524 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1525 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1527 M_FLTMOVE(s2, REG_FTMP2);
1532 emit_store_dst(jd, iptr, d);
1536 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1537 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1538 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1539 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1546 emit_store_dst(jd, iptr, d);
1550 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1553 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1554 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1555 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1562 emit_store_dst(jd, iptr, d);
1566 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1569 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1570 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1571 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1573 M_FLTMOVE(s2, REG_FTMP2);
1578 emit_store_dst(jd, iptr, d);
1582 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1585 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1586 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1587 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1589 M_FLTMOVE(s2, REG_FTMP2);
1594 emit_store_dst(jd, iptr, d);
1598 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1599 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1600 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1602 emit_store_dst(jd, iptr, d);
1605 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1606 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1607 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1609 emit_store_dst(jd, iptr, d);
1612 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1615 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1616 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1618 emit_store_dst(jd, iptr, d);
1622 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1625 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1626 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1628 emit_store_dst(jd, iptr, d);
1632 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1633 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1634 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1636 emit_store_dst(jd, iptr, d);
1637 /* TODO: corner cases ? */
1640 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1643 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1644 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1646 M_ICMP_IMM(0x80000000, d); /* corner cases */
1647 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1648 ((REG_RESULT == d) ? 0 : 3);
1650 M_FLTMOVE(s1, REG_FTMP1);
1651 M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1653 M_INTMOVE(REG_RESULT, d);
1654 emit_store_dst(jd, iptr, d);
1658 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1661 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1662 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1664 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1665 M_LCMP(REG_ITMP2, d); /* corner cases */
1666 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1667 ((REG_RESULT == d) ? 0 : 3);
1669 M_FLTMOVE(s1, REG_FTMP1);
1670 M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1672 M_INTMOVE(REG_RESULT, d);
1673 emit_store_dst(jd, iptr, d);
1677 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1680 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1681 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1683 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1684 M_LCMP(REG_ITMP2, d); /* corner cases */
1685 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1686 ((REG_RESULT == d) ? 0 : 3);
1688 M_FLTMOVE(s1, REG_FTMP1);
1689 M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1691 M_INTMOVE(REG_RESULT, d);
1692 emit_store_dst(jd, iptr, d);
1696 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1699 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1700 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1702 emit_store_dst(jd, iptr, d);
1706 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1709 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1710 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1712 emit_store_dst(jd, iptr, d);
1716 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1717 /* == => 0, < => 1, > => -1 */
1718 /* ICMD_FCMPL: s1 < s2 -> d := 1 */ /* TODO is this correct ? */
1721 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1722 /* == => 0, < => 1, > => -1 */
1724 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1725 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1726 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1730 M_BGT(SZ_BRC + SZ_BRC + SZ_BRC);
1731 M_BLT(SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC);
1732 M_BEQ(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC);
1734 N_LHI(d, iptr->opc == ICMD_FCMPL ? -1 : 1); /* s1 > s2 */
1735 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1736 N_LHI(d, iptr->opc == ICMD_FCMPL ? 1 : -1); /* s1 < s2 */
1737 M_BR(SZ_BRC + SZ_LHI);
1738 N_LHI(d, 0); /* s1 == s2 */
1740 emit_store_dst(jd, iptr, d);
1744 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1745 /* == => 0, < => 1, > => -1 */
1748 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1749 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1750 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1752 M_MOV_IMM(1, REG_ITMP1);
1753 M_MOV_IMM(-1, REG_ITMP2);
1754 emit_ucomisd_reg_reg(cd, s1, s2);
1755 M_CMOVB(REG_ITMP1, d);
1756 M_CMOVA(REG_ITMP2, d);
1757 M_CMOVP(REG_ITMP2, d); /* treat unordered as GT */
1758 emit_store_dst(jd, iptr, d);
1762 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1763 /* == => 0, < => 1, > => -1 */
1766 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1767 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1768 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1770 M_MOV_IMM(1, REG_ITMP1);
1771 M_MOV_IMM(-1, REG_ITMP2);
1772 emit_ucomisd_reg_reg(cd, s1, s2);
1773 M_CMOVB(REG_ITMP1, d);
1774 M_CMOVA(REG_ITMP2, d);
1775 M_CMOVP(REG_ITMP1, d); /* treat unordered as LT */
1776 emit_store_dst(jd, iptr, d);
1781 /* memory operations **************************************************/
1783 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1785 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1786 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1787 gen_nullptr_check(s1);
1788 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1789 emit_store_dst(jd, iptr, d);
1793 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1796 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1797 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1798 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1799 if (INSTRUCTION_MUST_CHECK(iptr)) {
1800 gen_nullptr_check(s1);
1803 emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
1804 emit_store_dst(jd, iptr, d);
1808 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1811 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1812 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1813 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1814 if (INSTRUCTION_MUST_CHECK(iptr)) {
1815 gen_nullptr_check(s1);
1818 emit_movzwq_memindex_reg(cd, OFFSET(java_chararray, data[0]), s1, s2, 1, d);
1819 emit_store_dst(jd, iptr, d);
1823 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1826 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1827 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1828 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1829 if (INSTRUCTION_MUST_CHECK(iptr)) {
1830 gen_nullptr_check(s1);
1833 emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
1834 emit_store_dst(jd, iptr, d);
1838 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1841 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1842 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1843 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1844 if (INSTRUCTION_MUST_CHECK(iptr)) {
1845 gen_nullptr_check(s1);
1848 emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
1849 emit_store_dst(jd, iptr, d);
1853 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1856 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1857 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1858 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1859 if (INSTRUCTION_MUST_CHECK(iptr)) {
1860 gen_nullptr_check(s1);
1863 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1864 emit_store_dst(jd, iptr, d);
1868 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1871 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1872 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1873 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1874 if (INSTRUCTION_MUST_CHECK(iptr)) {
1875 gen_nullptr_check(s1);
1878 emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1879 emit_store_dst(jd, iptr, d);
1883 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1886 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1887 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1888 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1889 if (INSTRUCTION_MUST_CHECK(iptr)) {
1890 gen_nullptr_check(s1);
1893 emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1894 emit_store_dst(jd, iptr, d);
1898 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1899 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1900 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1901 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1902 emit_array_checks(cd, iptr, s1, s2);
1904 M_INTMOVE(s1, REG_ITMP1);
1905 N_SLL(REG_ITMP1, 2, RN); /* scale index by 4 */
1906 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP1, s2);
1907 emit_store_dst(jd, iptr, d);
1910 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1913 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1914 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1915 if (INSTRUCTION_MUST_CHECK(iptr)) {
1916 gen_nullptr_check(s1);
1919 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1920 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1924 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1927 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1928 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1929 if (INSTRUCTION_MUST_CHECK(iptr)) {
1930 gen_nullptr_check(s1);
1933 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1934 emit_movw_reg_memindex(cd, s3, OFFSET(java_chararray, data[0]), s1, s2, 1);
1938 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1941 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1942 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1943 if (INSTRUCTION_MUST_CHECK(iptr)) {
1944 gen_nullptr_check(s1);
1947 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1948 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1952 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1955 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1956 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1957 if (INSTRUCTION_MUST_CHECK(iptr)) {
1958 gen_nullptr_check(s1);
1961 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1962 emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
1966 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1969 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1970 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1971 if (INSTRUCTION_MUST_CHECK(iptr)) {
1972 gen_nullptr_check(s1);
1975 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1976 emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
1980 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1983 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1984 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1985 if (INSTRUCTION_MUST_CHECK(iptr)) {
1986 gen_nullptr_check(s1);
1989 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1990 emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
1994 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1997 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1998 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1999 if (INSTRUCTION_MUST_CHECK(iptr)) {
2000 gen_nullptr_check(s1);
2003 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
2004 emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
2008 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
2011 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2012 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2013 if (INSTRUCTION_MUST_CHECK(iptr)) {
2014 gen_nullptr_check(s1);
2017 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
2021 M_MOV_IMM(BUILTIN_canstore, REG_ITMP1);
2025 codegen_add_arraystoreexception_ref(cd);
2027 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2028 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2029 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
2030 emit_mov_reg_memindex(cd, s3, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2035 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2038 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2039 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2040 if (INSTRUCTION_MUST_CHECK(iptr)) {
2041 gen_nullptr_check(s1);
2044 emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2048 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2051 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2052 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2053 if (INSTRUCTION_MUST_CHECK(iptr)) {
2054 gen_nullptr_check(s1);
2057 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
2061 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2064 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2065 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2066 if (INSTRUCTION_MUST_CHECK(iptr)) {
2067 gen_nullptr_check(s1);
2070 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2074 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2077 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2078 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2079 if (INSTRUCTION_MUST_CHECK(iptr)) {
2080 gen_nullptr_check(s1);
2083 emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
2087 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2090 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2091 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2092 if (INSTRUCTION_MUST_CHECK(iptr)) {
2093 gen_nullptr_check(s1);
2097 if (IS_IMM32(iptr->sx.s23.s3.constval)) {
2098 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2100 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2101 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2106 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2109 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2110 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2111 if (INSTRUCTION_MUST_CHECK(iptr)) {
2112 gen_nullptr_check(s1);
2115 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2120 case ICMD_GETSTATIC: /* ... ==> ..., value */
2122 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2123 uf = iptr->sx.s23.s3.uf;
2124 fieldtype = uf->fieldref->parseddesc.fd->type;
2125 disp = dseg_add_unique_address(cd, NULL);
2127 /* PROFILE_CYCLE_STOP; */
2129 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2131 /* PROFILE_CYCLE_START; */
2134 fi = iptr->sx.s23.s3.fmiref->p.field;
2135 fieldtype = fi->type;
2136 disp = dseg_add_address(cd, &(fi->value));
2138 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2141 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
2143 PROFILE_CYCLE_START;
2147 M_ALD(REG_ITMP1, REG_PV, disp);
2149 switch (fieldtype) {
2151 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2152 M_ILD(d, REG_ITMP1, 0);
2155 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2156 M_LLD(d, REG_ITMP1, 0);
2159 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2160 M_ALD(d, REG_ITMP1, 0);
2163 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2164 M_FLD(d, REG_ITMP1, 0);
2167 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2168 M_DLD(d, REG_ITMP1, 0);
2172 emit_store_dst(jd, iptr, d);
2176 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2178 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2179 uf = iptr->sx.s23.s3.uf;
2180 fieldtype = uf->fieldref->parseddesc.fd->type;
2181 disp = dseg_add_unique_address(cd, uf);
2183 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2186 fi = iptr->sx.s23.s3.fmiref->p.field;
2187 fieldtype = fi->type;
2188 disp = dseg_add_address(cd, &(fi->value));
2190 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2191 codegen_addpatchref(cd, PATCHER_clinit,
2195 M_ALD(REG_ITMP1, REG_PV, disp);
2196 switch (fieldtype) {
2198 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2199 M_IST(s1, REG_ITMP1, 0);
2202 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2203 M_LST(s1, REG_ITMP1, 0);
2206 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2207 M_AST(s1, REG_ITMP1, 0);
2210 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2211 M_FST(s1, REG_ITMP1, 0);
2214 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2215 M_DST(s1, REG_ITMP1, 0);
2220 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2221 /* val = value (in current instruction) */
2222 /* following NOP) */
2225 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2226 uf = iptr->sx.s23.s3.uf;
2227 fieldtype = uf->fieldref->parseddesc.fd->type;
2228 disp = dseg_add_unique_address(cd, uf);
2230 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2233 fi = iptr->sx.s23.s3.fmiref->p.field;
2234 fieldtype = fi->type;
2235 disp = dseg_add_address(cd, &(fi->value));
2237 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2238 codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class,
2242 M_ALD(REG_ITMP1, REG_PV, disp);
2244 switch (fieldtype) {
2246 M_IST(REG_ZERO, REG_ITMP1, 0);
2249 M_LST(REG_ZERO, REG_ITMP1, 0);
2252 M_AST(REG_ZERO, REG_ITMP1, 0);
2255 M_FST(REG_ZERO, REG_ITMP1, 0);
2258 M_DST(REG_ZERO, REG_ITMP1, 0);
2264 case ICMD_GETFIELD: /* ... ==> ..., value */
2266 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2267 emit_nullpointer_check(cd, iptr, s1);
2269 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2270 uf = iptr->sx.s23.s3.uf;
2271 fieldtype = uf->fieldref->parseddesc.fd->type;
2274 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2277 fi = iptr->sx.s23.s3.fmiref->p.field;
2278 fieldtype = fi->type;
2282 switch (fieldtype) {
2284 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2288 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2289 if (GET_HIGH_REG(d) == s1) {
2290 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2291 M_ILD(GET_HIGH_REG(d), s1, disp);
2294 M_ILD(GET_HIGH_REG(d), s1, disp);
2295 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2299 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2303 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2307 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2311 emit_store_dst(jd, iptr, d);
2314 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2316 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2317 gen_nullptr_check(s1);
2319 s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2321 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2322 uf = iptr->sx.s23.s3.uf;
2323 fieldtype = uf->fieldref->parseddesc.fd->type;
2327 fi = iptr->sx.s23.s3.fmiref->p.field;
2328 fieldtype = fi->type;
2332 if (IS_INT_LNG_TYPE(fieldtype)) {
2333 if (IS_2_WORD_TYPE(fieldtype))
2334 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2336 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2339 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2341 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2342 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2344 switch (fieldtype) {
2346 M_IST(s2, s1, disp);
2349 /* TODO really order */
2350 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2351 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2354 M_AST(s2, s1, disp);
2357 M_FST(s2, s1, disp);
2360 M_DST(s2, s1, disp);
2365 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2366 /* val = value (in current instruction) */
2367 /* following NOP) */
2370 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2371 gen_nullptr_check(s1);
2373 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2374 uf = iptr->sx.s23.s3.uf;
2375 fieldtype = uf->fieldref->parseddesc.fd->type;
2378 /* PROFILE_CYCLE_STOP; */
2380 codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
2382 /* PROFILE_CYCLE_START; */
2385 fi = iptr->sx.s23.s3.fmiref->p.field;
2386 fieldtype = fi->type;
2390 switch (fieldtype) {
2393 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2398 /* XXX why no check for IS_IMM32? */
2399 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2400 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2407 /* branch operations **************************************************/
2409 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2411 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2412 M_INTMOVE(s1, REG_ITMP1_XPTR);
2416 #ifdef ENABLE_VERIFIER
2417 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2418 uc = iptr->sx.s23.s2.uc;
2420 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2422 #endif /* ENABLE_VERIFIER */
2424 disp = dseg_add_functionptr(cd, asm_handle_exception);
2425 M_ALD(REG_ITMP2, REG_PV, disp);
2426 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2431 case ICMD_GOTO: /* ... ==> ... */
2432 case ICMD_RET: /* ... ==> ... */
2435 codegen_add_branch_ref(cd, iptr->dst.block);
2439 case ICMD_JSR: /* ... ==> ... */
2443 codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2447 case ICMD_IFNULL: /* ..., value ==> ... */
2448 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2451 codegen_add_branch_ref(cd, iptr->dst.block);
2454 case ICMD_IFNONNULL: /* ..., value ==> ... */
2455 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2458 codegen_add_branch_ref(cd, iptr->dst.block);
2461 case ICMD_IFEQ: /* ..., value ==> ... */
2462 case ICMD_IFLT: /* ..., value ==> ... */
2463 case ICMD_IFLE: /* ..., value ==> ... */
2464 case ICMD_IFNE: /* ..., value ==> ... */
2465 case ICMD_IFGT: /* ..., value ==> ... */
2466 case ICMD_IFGE: /* ..., value ==> ... */
2468 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2470 if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
2471 N_CHI(s1, iptr->sx.val.i);
2473 disp = dseg_add_s4(cd, iptr->sx.val.i);
2474 N_LHI(REG_ITMP2, disp);
2475 N_CL(s1, 0, REG_ITMP2, REG_PV);
2478 switch (iptr->opc) {
2498 codegen_add_branch_ref(cd, iptr->dst.block);
2502 case ICMD_IF_LEQ: /* ..., value ==> ... */
2505 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2506 if (IS_IMM32(iptr->sx.val.l))
2507 M_LCMP_IMM(iptr->sx.val.l, s1);
2509 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2510 M_LCMP(REG_ITMP2, s1);
2513 codegen_add_branch_ref(cd, iptr->dst.block);
2517 case ICMD_IF_LLT: /* ..., value ==> ... */
2521 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2522 if (IS_IMM32(iptr->sx.val.l))
2523 M_LCMP_IMM(iptr->sx.val.l, s1);
2525 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2526 M_LCMP(REG_ITMP2, s1);
2529 codegen_add_branch_ref(cd, iptr->dst.block);
2533 case ICMD_IF_LLE: /* ..., value ==> ... */
2537 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2538 if (IS_IMM32(iptr->sx.val.l))
2539 M_LCMP_IMM(iptr->sx.val.l, s1);
2541 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2542 M_LCMP(REG_ITMP2, s1);
2545 codegen_add_branch_ref(cd, iptr->dst.block);
2549 case ICMD_IF_LNE: /* ..., value ==> ... */
2553 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2554 if (IS_IMM32(iptr->sx.val.l))
2555 M_LCMP_IMM(iptr->sx.val.l, s1);
2557 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2558 M_LCMP(REG_ITMP2, s1);
2561 codegen_add_branch_ref(cd, iptr->dst.block);
2565 case ICMD_IF_LGT: /* ..., value ==> ... */
2569 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2570 if (IS_IMM32(iptr->sx.val.l))
2571 M_LCMP_IMM(iptr->sx.val.l, s1);
2573 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2574 M_LCMP(REG_ITMP2, s1);
2577 codegen_add_branch_ref(cd, iptr->dst.block);
2581 case ICMD_IF_LGE: /* ..., value ==> ... */
2585 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2586 if (IS_IMM32(iptr->sx.val.l))
2587 M_LCMP_IMM(iptr->sx.val.l, s1);
2589 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2590 M_LCMP(REG_ITMP2, s1);
2593 codegen_add_branch_ref(cd, iptr->dst.block);
2597 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2598 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2600 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2601 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2604 codegen_add_branch_ref(cd, iptr->dst.block);
2607 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2609 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2610 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2612 /* load low-bits before the branch, so we know the distance */
2613 /* TODO do the loads modify the condition code?
2614 * lr, l, la, lhi dont
2616 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2617 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2618 M_BNE(SZ_BRC + SZ_CR + SZ_BRC);
2621 codegen_add_branch_ref(cd, iptr->dst.block);
2624 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2625 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2627 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2628 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2631 codegen_add_branch_ref(cd, iptr->dst.block);
2635 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2639 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2640 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2643 codegen_add_branch_ref(cd, iptr->dst.block);
2647 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2649 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2650 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2653 codegen_add_branch_ref(cd, iptr->dst.block);
2657 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2661 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2662 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2665 codegen_add_branch_ref(cd, iptr->dst.block);
2669 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2671 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2672 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2675 codegen_add_branch_ref(cd, iptr->dst.block);
2679 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2683 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2684 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2687 codegen_add_branch_ref(cd, iptr->dst.block);
2691 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2693 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2694 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2697 codegen_add_branch_ref(cd, iptr->dst.block);
2701 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2703 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2704 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2707 codegen_add_branch_ref(cd, iptr->dst.block);
2708 /* load low-bits before the branch, so we know the distance */
2709 /* TODO: the loads should not touch the condition code. */
2710 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2711 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2712 M_BGT(SZ_BRC + SZ_CR + SZ_BRC);
2715 codegen_add_branch_ref(cd, iptr->dst.block);
2718 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2720 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2721 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2724 codegen_add_branch_ref(cd, iptr->dst.block);
2728 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2732 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2733 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2736 codegen_add_branch_ref(cd, iptr->dst.block);
2740 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2742 REPLACEMENT_POINT_RETURN(cd, iptr);
2743 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2744 M_INTMOVE(s1, REG_RESULT);
2745 goto nowperformreturn;
2747 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2749 REPLACEMENT_POINT_RETURN(cd, iptr);
2750 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2751 M_INTMOVE(s1, REG_RESULT);
2753 #ifdef ENABLE_VERIFIER
2754 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2755 unresolved_class *uc = iptr->sx.s23.s2.uc;
2757 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2759 #endif /* ENABLE_VERIFIER */
2760 goto nowperformreturn;
2762 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2764 REPLACEMENT_POINT_RETURN(cd, iptr);
2765 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2766 M_LNGMOVE(s1, REG_RESULT_PACKED);
2767 goto nowperformreturn;
2769 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2772 REPLACEMENT_POINT_RETURN(cd, iptr);
2773 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2774 M_FLTMOVE(s1, REG_FRESULT);
2775 goto nowperformreturn;
2777 case ICMD_RETURN: /* ... ==> ... */
2779 REPLACEMENT_POINT_RETURN(cd, iptr);
2785 p = cd->stackframesize;
2787 /* call trace function */
2789 /*emit_verbosecall_exit(jd); TODO */
2791 #if defined(ENABLE_THREADS)
2792 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2793 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2794 M_ALD(REG_ITMP3, REG_PV, disp);
2797 /* we need to save the proper return value */
2799 switch (iptr->opc) {
2801 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2805 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2808 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2811 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2815 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2818 /* and now restore the proper return value */
2820 switch (iptr->opc) {
2822 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2826 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2829 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2832 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2838 /* restore return address */
2840 p--; M_ALD(REG_RA, REG_SP, p * 4);
2842 /* restore saved registers */
2844 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2845 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2847 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2848 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2851 /* deallocate stack */
2853 if (cd->stackframesize)
2854 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2861 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2866 branch_target_t *table;
2868 table = iptr->dst.table;
2870 l = iptr->sx.s23.s2.tablelow;
2871 i = iptr->sx.s23.s3.tablehigh;
2873 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2874 M_INTMOVE(s1, REG_ITMP1);
2877 M_ISUB_IMM(l, REG_ITMP1);
2879 /* number of targets */
2883 M_ICMP_IMM(i - 1, REG_ITMP1);
2886 codegen_add_branch_ref(cd, table[0].block); /* default target */
2888 /* build jump table top down and use address of lowest entry */
2893 dseg_add_target(cd, table->block);
2897 /* length of dataseg after last dseg_add_target is used
2900 M_MOV_IMM(0, REG_ITMP2);
2902 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2909 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2914 lookup_target_t *lookup;
2916 lookup = iptr->dst.lookup;
2918 i = iptr->sx.s23.s2.lookupcount;
2920 MCODECHECK(8 + ((7 + 6) * i) + 5);
2921 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2924 M_ICMP_IMM(lookup->value, s1);
2926 codegen_add_branch_ref(cd, lookup->target.block);
2932 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2938 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2940 bte = iptr->sx.s23.s3.bte;
2944 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2945 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2946 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2947 case ICMD_INVOKEINTERFACE:
2949 REPLACEMENT_POINT_INVOKE(cd, iptr);
2951 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2953 um = iptr->sx.s23.s3.um;
2954 md = um->methodref->parseddesc.md;
2957 lm = iptr->sx.s23.s3.fmiref->p.method;
2959 md = lm->parseddesc;
2963 s3 = md->paramcount;
2965 MCODECHECK((s3 << 1) + 64);
2967 /* copy arguments to registers or stack location */
2969 for (s3 = s3 - 1; s3 >= 0; s3--) {
2970 var = VAR(iptr->sx.s23.s2.args[s3]);
2972 /* Already Preallocated? */
2973 if (var->flags & PREALLOC)
2976 if (IS_INT_LNG_TYPE(var->type)) {
2977 if (!md->params[s3].inmemory) {
2978 if (IS_2_WORD_TYPE(var->type)) {
2980 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2981 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2983 d = emit_load(jd, iptr, var, s1);
2987 s1 = rd->argintregs[md->params[s3].regoff];
2988 d = emit_load(jd, iptr, var, s1);
2993 if (IS_2_WORD_TYPE(var->type)) {
2994 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2995 M_LST(d, REG_SP, md->params[s3].regoff * 4);
2998 d = emit_load(jd, iptr, var, REG_ITMP1);
2999 M_IST(d, REG_SP, md->params[s3].regoff * 4);
3004 if (!md->params[s3].inmemory) {
3005 s1 = rd->argfltregs[md->params[s3].regoff];
3006 d = emit_load(jd, iptr, var, s1);
3010 d = emit_load(jd, iptr, var, REG_FTMP1);
3011 if (IS_2_WORD_TYPE(var->type))
3012 M_DST(d, REG_SP, md->params[s3].regoff * 4);
3014 M_FST(d, REG_SP, md->params[s3].regoff * 4);
3019 switch (iptr->opc) {
3021 disp = dseg_add_functionptr(cd, bte->fp);
3023 N_AHI(REG_SP, -96); /* register save are required by C abi */
3024 N_LHI(REG_ITMP1, disp);
3025 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3028 case ICMD_INVOKESPECIAL:
3029 emit_nullpointer_check(cd, iptr, REG_A0);
3030 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
3033 case ICMD_INVOKESTATIC:
3035 disp = dseg_add_unique_address(cd, um);
3037 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3041 disp = dseg_add_address(cd, lm->stubroutine);
3043 N_LHI(REG_ITMP1, disp);
3044 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3047 case ICMD_INVOKEVIRTUAL:
3048 emit_nullpointer_check(cd, iptr, REG_A0);
3051 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3056 s1 = OFFSET(vftbl_t, table[0]) +
3057 sizeof(methodptr) * lm->vftblindex;
3060 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
3061 M_ALD(REG_PV, REG_METHODPTR, s1);
3064 case ICMD_INVOKEINTERFACE:
3065 emit_nullpointer_check(cd, iptr, REG_A0);
3068 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3074 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3075 sizeof(methodptr*) * lm->class->index;
3077 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3080 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
3081 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3082 M_ALD(REG_PV, REG_METHODPTR, s2);
3086 /* generate the actual call */
3089 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
3090 N_BASR(REG_ITMP1, RN);
3091 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3092 M_LDA(REG_PV, REG_ITMP1, -disp);
3094 /* post call finalization */
3096 if (iptr->opc == ICMD_BUILTIN) {
3097 N_AHI(REG_SP, 96); /* remove C abi register save area */
3100 /* actually only used for ICMD_BUILTIN */
3102 if (INSTRUCTION_MUST_CHECK(iptr)) {
3105 codegen_add_fillinstacktrace_ref(cd);
3108 /* store return value */
3110 d = md->returntype.type;
3112 if (d != TYPE_VOID) {
3113 if (IS_INT_LNG_TYPE(d)) {
3114 if (IS_2_WORD_TYPE(d)) {
3115 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
3116 M_LNGMOVE(REG_RESULT_PACKED, s1);
3119 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3120 M_INTMOVE(REG_RESULT, s1);
3124 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
3125 M_FLTMOVE(REG_FRESULT, s1);
3127 emit_store_dst(jd, iptr, s1);
3133 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3135 /* val.a: (classinfo*) superclass */
3137 /* superclass is an interface:
3139 * OK if ((sub == NULL) ||
3140 * (sub->vftbl->interfacetablelength > super->index) &&
3141 * (sub->vftbl->interfacetable[-super->index] != NULL));
3143 * superclass is a class:
3145 * OK if ((sub == NULL) || (0
3146 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3147 * super->vftbl->diffval));
3150 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
3151 /* object type cast-check */
3154 vftbl_t *supervftbl;
3157 u1 *class_label_refs[] = { 0 }, *class_label;
3158 u1 *exit_label_refs[] = { 0, 0, 0, 0 };
3160 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3166 super = iptr->sx.s23.s3.c.cls;
3167 superindex = super->index;
3168 supervftbl = super->vftbl;
3171 #if defined(ENABLE_THREADS)
3172 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3174 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3176 /* if class is not resolved, check which code to call */
3178 if (super == NULL) {
3180 exit_label_refs[0] = cd->mcodeptr;
3183 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3185 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3186 iptr->sx.s23.s3.c.ref,
3189 ICONST(REG_ITMP2, ACC_INTERFACE);
3190 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3191 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3192 class_label_refs[0] = cd->mcodeptr;
3196 /* interface checkcast code */
3198 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3199 if (super == NULL) {
3200 codegen_add_patch_ref(cd,
3201 PATCHER_checkcast_instanceof_interface,
3202 iptr->sx.s23.s3.c.ref,
3206 exit_label_refs[1] = cd->mcodeptr;
3210 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3211 M_ILD(REG_ITMP3, REG_ITMP2,
3212 OFFSET(vftbl_t, interfacetablelength));
3213 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3216 codegen_add_classcastexception_ref(cd, s1);
3217 M_ALD(REG_ITMP3, REG_ITMP2,
3218 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3219 superindex * sizeof(methodptr*)));
3222 codegen_add_classcastexception_ref(cd, s1);
3224 if (super == NULL) {
3225 exit_label_refs[2] = cd->mcodeptr;
3230 /* class checkcast code */
3232 class_label = cd->mcodeptr;
3234 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3235 if (super == NULL) {
3236 disp = dseg_add_unique_address(cd, NULL);
3238 codegen_add_patch_ref(cd,
3239 PATCHER_resolve_classref_to_vftbl,
3240 iptr->sx.s23.s3.c.ref,
3244 disp = dseg_add_address(cd, supervftbl);
3246 exit_label_refs[3] = cd->mcodeptr;
3250 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3251 M_ALD(REG_ITMP3, REG_PV, disp);
3252 #if defined(ENABLE_THREADS)
3253 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3255 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3256 /* if (s1 != REG_ITMP1) { */
3257 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3258 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3259 /* #if defined(ENABLE_THREADS) */
3260 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3262 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3265 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3266 M_ISUB(REG_ITMP2, REG_ITMP3);
3267 M_ALD(REG_ITMP3, REG_PV, disp);
3268 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3269 #if defined(ENABLE_THREADS)
3270 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3273 N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3274 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3275 M_BGT(0); /* Branch if greater then */
3276 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3277 codegen_add_classcastexception_ref(cd, s1);
3280 /* resolve labels by adding the correct displacement */
3282 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3283 if (exit_label_refs[s2])
3284 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3287 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3288 if (class_label_refs[s2])
3289 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3292 d = codegen_reg_of_dst(jd, iptr, s1);
3295 /* array type cast-check */
3297 s1 = emit_load_s1(jd, iptr, REG_A0);
3298 M_INTMOVE(s1, REG_A0);
3300 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3301 disp = dseg_add_unique_address(cd, NULL);
3303 codegen_add_patch_ref(cd,
3304 PATCHER_resolve_classref_to_classinfo,
3305 iptr->sx.s23.s3.c.ref,
3309 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3311 M_ALD(REG_A1, REG_PV, disp);
3312 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3313 ICONST(REG_ITMP1, disp); /* TODO negative displacement */
3314 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3315 M_JSR(REG_RA, REG_PV);
3316 N_BASR(REG_ITMP1, RN);
3317 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3318 M_LDA(REG_PV, REG_ITMP1, -disp);
3320 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3323 codegen_add_classcastexception_ref(cd, s1);
3325 d = codegen_reg_of_dst(jd, iptr, s1);
3329 emit_store_dst(jd, iptr, d);
3332 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3335 /* val.a: (classinfo*) superclass */
3337 /* superclass is an interface:
3339 * return (sub != NULL) &&
3340 * (sub->vftbl->interfacetablelength > super->index) &&
3341 * (sub->vftbl->interfacetable[-super->index] != NULL);
3343 * superclass is a class:
3345 * return ((sub != NULL) && (0
3346 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3347 * super->vftbl->diffvall));
3352 vftbl_t *supervftbl;
3355 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3361 super = iptr->sx.s23.s3.c.cls;
3362 superindex = super->index;
3363 supervftbl = super->vftbl;
3366 #if defined(ENABLE_THREADS)
3367 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3369 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3370 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3372 M_MOV(s1, REG_ITMP1);
3376 /* calculate interface instanceof code size */
3380 s2 += (d == REG_ITMP2 ? 1 : 0) + (opt_shownops ? 1 : 0);
3382 /* calculate class instanceof code size */
3386 s3 += (opt_shownops ? 1 : 0);
3388 /* if class is not resolved, check which code to call */
3390 if (super == NULL) {
3392 M_BEQZ(s1, 4 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
3394 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3396 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3397 iptr->sx.s23.s3.c.ref, disp);
3399 M_ILD(REG_ITMP3, REG_PV, disp);
3401 disp = dseg_add_s4(cd, ACC_INTERFACE);
3402 M_ILD(REG_ITMP2, REG_PV, disp);
3403 M_AND(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3404 M_BEQZ(REG_ITMP3, s2 + 1);
3407 /* interface instanceof code */
3409 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3410 if (super == NULL) {
3411 /* If d == REG_ITMP2, then it's destroyed in check
3416 codegen_add_patch_ref(cd,
3417 PATCHER_checkcast_instanceof_interface,
3418 iptr->sx.s23.s3.c.ref, 0);
3425 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3426 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3427 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3428 M_BLEZ(REG_ITMP3, 2);
3429 M_ALD(REG_ITMP1, REG_ITMP1,
3430 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3431 superindex * sizeof(methodptr*)));
3432 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3438 /* class instanceof code */
3440 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3441 if (super == NULL) {
3442 disp = dseg_add_unique_address(cd, NULL);
3444 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3445 iptr->sx.s23.s3.c.ref,
3449 disp = dseg_add_address(cd, supervftbl);
3455 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3456 M_ALD(REG_ITMP2, REG_PV, disp);
3457 #if defined(ENABLE_THREADS)
3458 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3460 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3461 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3462 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3463 #if defined(ENABLE_THREADS)
3464 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3466 M_ISUB(REG_ITMP1, REG_ITMP3);
3467 N_CLR(REG_ITMP1, REG_ITMP2);
3468 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3470 emit_store_dst(jd, iptr, d);
3475 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3479 /* check for negative sizes and copy sizes to stack if necessary */
3481 MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3483 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3485 /* copy SAVEDVAR sizes to stack */
3486 var = VAR(iptr->sx.s23.s2.args[s1]);
3488 /* Already Preallocated? */
3489 if (!(var->flags & PREALLOC)) {
3490 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3491 M_LST(s2, REG_SP, s1 * 8);
3495 /* is a patcher function set? */
3497 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3498 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
3499 iptr->sx.s23.s3.c.ref, 0);
3502 /* a0 = dimension count */
3504 M_MOV_IMM(iptr->s1.argcount, REG_A0);
3506 /* a1 = classinfo */
3508 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3510 /* a2 = pointer to dimensions = stack pointer */
3512 M_MOV(REG_SP, REG_A2);
3514 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3517 /* check for exception before result assignment */
3521 codegen_add_fillinstacktrace_ref(cd);
3523 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3524 M_INTMOVE(REG_RESULT, s1);
3525 emit_store_dst(jd, iptr, s1);
3530 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3534 } /* for instruction */
3536 MCODECHECK(512); /* XXX require a lower number? */
3538 /* At the end of a basic block we may have to append some nops,
3539 because the patcher stub calling code might be longer than the
3540 actual instruction. So codepatching does not change the
3541 following block unintentionally. */
3543 if (cd->mcodeptr < cd->lastmcodeptr) {
3544 while (cd->mcodeptr < cd->lastmcodeptr) {
3549 } /* if (bptr -> flags >= BBREACHED) */
3550 } /* for basic block */
3552 dseg_createlinenumbertable(cd);
3554 /* generate stubs */
3556 emit_exception_stubs(jd);
3557 emit_patcher_stubs(jd);
3559 emit_replacement_stubs(jd);
3564 /* everything's ok */
3570 /* createcompilerstub **********************************************************
3572 Creates a stub routine which calls the compiler.
3574 *******************************************************************************/
3576 #define COMPILERSTUB_DATASIZE (3 * SIZEOF_VOID_P)
3577 #define COMPILERSTUB_CODESIZE (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
3579 #define COMPILERSTUB_SIZE (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE)
3582 u1 *createcompilerstub(methodinfo *m)
3584 u1 *s; /* memory to hold the stub */
3590 s = CNEW(u1, COMPILERSTUB_SIZE);
3592 /* set data pointer and code pointer */
3595 s = s + COMPILERSTUB_DATASIZE;
3597 /* mark start of dump memory area */
3599 dumpsize = dump_size();
3601 cd = DNEW(codegendata);
3604 /* Store the codeinfo pointer in the same place as in the
3605 methodheader for compiled methods. */
3607 code = code_codeinfo_new(m);
3609 d[0] = (ptrint) asm_call_jit_compiler;
3611 d[2] = (ptrint) code;
3613 /* code for the stub */
3615 /* don't touch ITMP3 as it cointains the return address */
3617 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3619 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3620 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3621 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3624 #if defined(ENABLE_STATISTICS)
3626 count_cstub_len += COMPILERSTUB_SIZE;
3629 /* release dump area */
3631 dump_release(dumpsize);
3637 /* createnativestub ************************************************************
3639 Creates a stub routine which calls a native method.
3641 *******************************************************************************/
3644 arguments on stack \
3645 -------------------------------------------------| <- SP on nativestub entry
3647 callee saved int regs (none) |
3648 callee saved float regs (none) | stack frame like in cacao
3649 local variable slots (none) |
3650 arguments for calling methods (none) /
3651 ------------------------------------------------------------------ <- datasp
3656 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3657 0 - 96 register save area for callee /
3658 -------------------------------------------------------- <- SP native method
3660 SP after method entry
3663 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3671 s4 i, j; /* count variables */
3676 /* get required compiler data */
3683 /* initialize variables */
3686 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3688 /* calculate stack frame size */
3690 cd->stackframesize =
3691 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3692 sizeof(localref_table) / SIZEOF_VOID_P +
3693 INT_ARG_CNT + FLT_ARG_CNT +
3694 1 + /* functionptr, TODO: store in data segment */
3697 cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */
3700 cd->stackframesize =
3701 1 + /* r14 - return address */ +
3702 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3703 sizeof(localref_table) / SIZEOF_VOID_P +
3705 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3706 nmd->memuse + /* parameter passing */
3707 96 / SIZEOF_VOID_P /* required by ABI */;
3709 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3712 /* create method header */
3714 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3715 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3716 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3717 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3718 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3719 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3720 (void) dseg_addlinenumbertablesize(cd);
3721 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3723 /* generate native method profiling code */
3725 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3726 /* count frequency */
3728 M_MOV_IMM(code, REG_ITMP3);
3729 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3733 /* generate stub code */
3735 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3737 /* save return address */
3739 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3742 #if !defined(NDEBUG)
3743 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3744 emit_verbosecall_enter(jd);
3748 /* get function address (this must happen before the stackframeinfo) */
3750 disp = dseg_add_functionptr(cd, f);
3752 #if !defined(WITH_STATIC_CLASSPATH)
3754 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3757 M_ILD(REG_ITMP1, REG_PV, disp);
3759 j = 96 + (nmd->memuse * 4);
3761 /* todo some arg registers are not volatile in C-abi terms */
3763 /* save integer and float argument registers */
3765 for (i = 0; i < md->paramcount; i++) {
3766 if (! md->params[i].inmemory) {
3767 s1 = md->params[i].regoff;
3769 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3770 if (IS_2_WORD_TYPE(t)) {
3771 /* todo store multiple */
3772 N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3773 N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3775 N_ST(rd->argintregs[s1], j, RN, REG_SP);
3778 if (IS_2_WORD_TYPE(t)) {
3779 N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3781 N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3789 N_ST(REG_ITMP1, j, RN, REG_SP);
3791 /* create dynamic stack info */
3793 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3794 N_LR(REG_A1, REG_PV); /* pv */
3795 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3796 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3798 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3799 M_ILD(REG_ITMP1, REG_PV, disp);
3801 M_CALL(REG_ITMP1); /* call */
3803 /* restore integer and float argument registers */
3805 j = 96 + (nmd->memuse * 4);
3807 for (i = 0; i < md->paramcount; i++) {
3808 if (! md->params[i].inmemory) {
3809 s1 = md->params[i].regoff;
3811 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3812 if (IS_2_WORD_TYPE(t)) {
3813 /* todo load multiple ! */
3814 N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3815 N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3817 N_L(rd->argintregs[s1], j, RN, REG_SP);
3820 if (IS_2_WORD_TYPE(t)) {
3821 N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3823 N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3831 N_L(REG_ITMP1, j, RN, REG_SP);
3833 /* copy or spill arguments to new locations */
3835 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3836 t = md->paramtypes[i].type;
3838 if (IS_INT_LNG_TYPE(t)) {
3840 if (!md->params[i].inmemory) {
3842 s1 = rd->argintregs[md->params[i].regoff];
3844 if (!nmd->params[j].inmemory) {
3845 s2 = rd->argintregs[nmd->params[j].regoff];
3846 if (IS_2_WORD_TYPE(t)) {
3847 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3848 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3853 s2 = nmd->params[j].regoff;
3854 if (IS_2_WORD_TYPE(t)) {
3855 N_LM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3857 N_L(s1, 96 + (s2 * 4), RN, REG_SP);
3862 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3863 s2 = nmd->params[j].regoff;
3865 if (IS_2_WORD_TYPE(t)) {
3866 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3868 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3873 /* We only copy spilled float arguments, as the float argument */
3874 /* registers keep unchanged. */
3876 if (md->params[i].inmemory) {
3877 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3878 s2 = nmd->params[j].regoff;
3880 if (IS_2_WORD_TYPE(t)) {
3881 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3883 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3889 /* put class into second argument register */
3891 if (m->flags & ACC_STATIC) {
3892 disp = dseg_add_address(cd, m->class);
3893 M_ILD(REG_A1, REG_PV, disp);
3896 /* put env into first argument register */
3898 disp = dseg_add_address(cd, _Jv_env);
3899 M_ILD(REG_A0, REG_PV, disp);
3901 /* do the native function call */
3903 M_CALL(REG_ITMP1); /* call */
3905 /* save return value */
3907 t = md->returntype.type;
3909 if (t != TYPE_VOID) {
3910 if (IS_INT_LNG_TYPE(t)) {
3911 if (IS_2_WORD_TYPE(t)) {
3912 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3914 N_ST(REG_RESULT, 96, RN, REG_SP);
3917 if (IS_2_WORD_TYPE(t)) {
3918 N_STD(REG_FRESULT, 96, RN, REG_SP);
3920 N_STE(REG_FRESULT, 96, RN, REG_SP);
3926 #if !defined(NDEBUG)
3927 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3928 emit_verbosecall_exit(jd);
3932 /* remove native stackframe info */
3934 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3935 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3936 M_ILD(REG_ITMP1, REG_PV, disp);
3938 N_LR(REG_ITMP3, REG_RESULT);
3940 /* restore return value */
3942 if (t != TYPE_VOID) {
3943 if (IS_INT_LNG_TYPE(t)) {
3944 if (IS_2_WORD_TYPE(t)) {
3945 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3947 N_L(REG_RESULT, 96, RN, REG_SP);
3950 if (IS_2_WORD_TYPE(t)) {
3951 N_LD(REG_FRESULT, 96, RN, REG_SP);
3953 N_LE(REG_FRESULT, 96, RN, REG_SP);
3958 /* load return address */
3960 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3962 /* remove stackframe */
3964 N_AHI(REG_SP, cd->stackframesize * 4);
3966 /* test for exception */
3968 N_LTR(REG_ITMP3, REG_ITMP3);
3969 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3973 N_BCR(DD_ANY, REG_ITMP2);
3975 /* handle exception */
3980 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3981 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
3982 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3984 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
3988 /* generate patcher stubs */
3990 emit_patcher_stubs(jd);
3994 return code->entrypoint;
4001 * These are local overrides for various environment variables in Emacs.
4002 * Please do not remove this and leave it at the end of the file, where
4003 * Emacs will automagically detect them.
4004 * ---------------------------------------------------------------------
4007 * indent-tabs-mode: t
4011 * vim:noexpandtab:sw=4:ts=4: