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 7429 2007-03-01 12:42:16Z 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 "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 ==> ... */
2010 s1 = emit_load_s1(jd, iptr, REG_A0);
2011 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2012 emit_array_checks(cd, iptr, s1, s2);
2013 s3 = emit_load_s3(jd, iptr, REG_A1);
2015 M_INTMOVE(s1, REG_A0);
2016 M_INTMOVE(s3, REG_A1);
2018 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
2019 ICONST(REG_ITMP3, disp);
2020 N_L(REG_PV, 0, REG_ITMP3, REG_PV);
2021 M_ISUB_IMM(96, REG_SP);
2022 M_JSR(REG_RA, REG_PV);
2023 M_IADD_IMM(96, REG_SP);
2024 N_BASR(REG_ITMP1, RN);
2025 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2026 M_LDA(REG_PV, REG_ITMP1, -disp);
2030 codegen_add_arraystoreexception_ref(cd);
2032 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2033 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2034 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
2036 M_INTMOVE(s2, REG_ITMP2);
2037 N_SLL(REG_ITMP2, 2, RN);
2038 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
2041 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
2042 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
2047 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
2050 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2051 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2052 if (INSTRUCTION_MUST_CHECK(iptr)) {
2053 gen_nullptr_check(s1);
2056 emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
2060 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
2063 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2064 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2065 if (INSTRUCTION_MUST_CHECK(iptr)) {
2066 gen_nullptr_check(s1);
2069 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
2073 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
2076 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2077 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2078 if (INSTRUCTION_MUST_CHECK(iptr)) {
2079 gen_nullptr_check(s1);
2082 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2086 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2089 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2090 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2091 if (INSTRUCTION_MUST_CHECK(iptr)) {
2092 gen_nullptr_check(s1);
2095 emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
2099 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2102 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2103 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2104 if (INSTRUCTION_MUST_CHECK(iptr)) {
2105 gen_nullptr_check(s1);
2109 if (IS_IMM32(iptr->sx.s23.s3.constval)) {
2110 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2112 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2113 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2118 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2121 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2122 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2123 if (INSTRUCTION_MUST_CHECK(iptr)) {
2124 gen_nullptr_check(s1);
2127 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2132 case ICMD_GETSTATIC: /* ... ==> ..., value */
2134 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2135 uf = iptr->sx.s23.s3.uf;
2136 fieldtype = uf->fieldref->parseddesc.fd->type;
2137 disp = dseg_add_unique_address(cd, NULL);
2139 /* PROFILE_CYCLE_STOP; */
2141 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2143 /* PROFILE_CYCLE_START; */
2146 fi = iptr->sx.s23.s3.fmiref->p.field;
2147 fieldtype = fi->type;
2148 disp = dseg_add_address(cd, &(fi->value));
2150 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2153 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
2155 PROFILE_CYCLE_START;
2159 M_ALD(REG_ITMP1, REG_PV, disp);
2161 switch (fieldtype) {
2163 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2164 M_ILD(d, REG_ITMP1, 0);
2167 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2168 M_LLD(d, REG_ITMP1, 0);
2171 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2172 M_ALD(d, REG_ITMP1, 0);
2175 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2176 M_FLD(d, REG_ITMP1, 0);
2179 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2180 M_DLD(d, REG_ITMP1, 0);
2184 emit_store_dst(jd, iptr, d);
2188 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2190 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2191 uf = iptr->sx.s23.s3.uf;
2192 fieldtype = uf->fieldref->parseddesc.fd->type;
2193 disp = dseg_add_unique_address(cd, uf);
2195 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2198 fi = iptr->sx.s23.s3.fmiref->p.field;
2199 fieldtype = fi->type;
2200 disp = dseg_add_address(cd, &(fi->value));
2202 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2203 codegen_addpatchref(cd, PATCHER_clinit,
2207 M_ALD(REG_ITMP1, REG_PV, disp);
2208 switch (fieldtype) {
2210 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2211 M_IST(s1, REG_ITMP1, 0);
2214 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2215 M_LST(s1, REG_ITMP1, 0);
2218 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2219 M_AST(s1, REG_ITMP1, 0);
2222 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2223 M_FST(s1, REG_ITMP1, 0);
2226 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2227 M_DST(s1, REG_ITMP1, 0);
2232 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2233 /* val = value (in current instruction) */
2234 /* following NOP) */
2237 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2238 uf = iptr->sx.s23.s3.uf;
2239 fieldtype = uf->fieldref->parseddesc.fd->type;
2240 disp = dseg_add_unique_address(cd, uf);
2242 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2245 fi = iptr->sx.s23.s3.fmiref->p.field;
2246 fieldtype = fi->type;
2247 disp = dseg_add_address(cd, &(fi->value));
2249 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2250 codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class,
2254 M_ALD(REG_ITMP1, REG_PV, disp);
2256 switch (fieldtype) {
2258 M_IST(REG_ZERO, REG_ITMP1, 0);
2261 M_LST(REG_ZERO, REG_ITMP1, 0);
2264 M_AST(REG_ZERO, REG_ITMP1, 0);
2267 M_FST(REG_ZERO, REG_ITMP1, 0);
2270 M_DST(REG_ZERO, REG_ITMP1, 0);
2276 case ICMD_GETFIELD: /* ... ==> ..., value */
2278 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2279 emit_nullpointer_check(cd, iptr, s1);
2281 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2282 uf = iptr->sx.s23.s3.uf;
2283 fieldtype = uf->fieldref->parseddesc.fd->type;
2286 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2289 fi = iptr->sx.s23.s3.fmiref->p.field;
2290 fieldtype = fi->type;
2294 switch (fieldtype) {
2296 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2300 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2301 if (GET_HIGH_REG(d) == s1) {
2302 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2303 M_ILD(GET_HIGH_REG(d), s1, disp);
2306 M_ILD(GET_HIGH_REG(d), s1, disp);
2307 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2311 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2315 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2319 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2323 emit_store_dst(jd, iptr, d);
2326 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2328 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2329 gen_nullptr_check(s1);
2331 s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2333 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2334 uf = iptr->sx.s23.s3.uf;
2335 fieldtype = uf->fieldref->parseddesc.fd->type;
2339 fi = iptr->sx.s23.s3.fmiref->p.field;
2340 fieldtype = fi->type;
2344 if (IS_INT_LNG_TYPE(fieldtype)) {
2345 if (IS_2_WORD_TYPE(fieldtype))
2346 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2348 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2351 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2353 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2354 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2356 switch (fieldtype) {
2358 M_IST(s2, s1, disp);
2361 /* TODO really order */
2362 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2363 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2366 M_AST(s2, s1, disp);
2369 M_FST(s2, s1, disp);
2372 M_DST(s2, s1, disp);
2377 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2378 /* val = value (in current instruction) */
2379 /* following NOP) */
2382 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2383 gen_nullptr_check(s1);
2385 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2386 uf = iptr->sx.s23.s3.uf;
2387 fieldtype = uf->fieldref->parseddesc.fd->type;
2390 /* PROFILE_CYCLE_STOP; */
2392 codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
2394 /* PROFILE_CYCLE_START; */
2397 fi = iptr->sx.s23.s3.fmiref->p.field;
2398 fieldtype = fi->type;
2402 switch (fieldtype) {
2405 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2410 /* XXX why no check for IS_IMM32? */
2411 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2412 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2419 /* branch operations **************************************************/
2421 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2423 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2424 M_INTMOVE(s1, REG_ITMP1_XPTR);
2428 #ifdef ENABLE_VERIFIER
2429 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2430 uc = iptr->sx.s23.s2.uc;
2432 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2434 #endif /* ENABLE_VERIFIER */
2436 disp = dseg_add_functionptr(cd, asm_handle_exception);
2437 M_ALD(REG_ITMP2, REG_PV, disp);
2438 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2443 case ICMD_GOTO: /* ... ==> ... */
2444 case ICMD_RET: /* ... ==> ... */
2447 codegen_add_branch_ref(cd, iptr->dst.block);
2451 case ICMD_JSR: /* ... ==> ... */
2455 codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2459 case ICMD_IFNULL: /* ..., value ==> ... */
2460 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2463 codegen_add_branch_ref(cd, iptr->dst.block);
2466 case ICMD_IFNONNULL: /* ..., value ==> ... */
2467 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2470 codegen_add_branch_ref(cd, iptr->dst.block);
2473 case ICMD_IFEQ: /* ..., value ==> ... */
2474 case ICMD_IFLT: /* ..., value ==> ... */
2475 case ICMD_IFLE: /* ..., value ==> ... */
2476 case ICMD_IFNE: /* ..., value ==> ... */
2477 case ICMD_IFGT: /* ..., value ==> ... */
2478 case ICMD_IFGE: /* ..., value ==> ... */
2480 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2482 if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
2483 N_CHI(s1, iptr->sx.val.i);
2485 disp = dseg_add_s4(cd, iptr->sx.val.i);
2486 N_LHI(REG_ITMP2, disp);
2487 N_CL(s1, 0, REG_ITMP2, REG_PV);
2490 switch (iptr->opc) {
2510 codegen_add_branch_ref(cd, iptr->dst.block);
2514 case ICMD_IF_LEQ: /* ..., 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_LLT: /* ..., 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_LLE: /* ..., 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_LNE: /* ..., 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_LGT: /* ..., 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_LGE: /* ..., value ==> ... */
2597 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2598 if (IS_IMM32(iptr->sx.val.l))
2599 M_LCMP_IMM(iptr->sx.val.l, s1);
2601 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
2602 M_LCMP(REG_ITMP2, s1);
2605 codegen_add_branch_ref(cd, iptr->dst.block);
2609 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2610 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
2612 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2613 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2616 codegen_add_branch_ref(cd, iptr->dst.block);
2619 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2621 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2622 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2624 /* load low-bits before the branch, so we know the distance */
2625 /* TODO do the loads modify the condition code?
2626 * lr, l, la, lhi dont
2628 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2629 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2630 M_BNE(SZ_BRC + SZ_CR + SZ_BRC);
2633 codegen_add_branch_ref(cd, iptr->dst.block);
2636 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2637 case ICMD_IF_ICMPNE: /* ..., 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_LCMPNE: /* ..., value, value ==> ... */
2651 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2652 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2655 codegen_add_branch_ref(cd, iptr->dst.block);
2659 case ICMD_IF_ICMPLT: /* ..., 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_LCMPLT: /* ..., value, value ==> ... */
2673 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2674 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2677 codegen_add_branch_ref(cd, iptr->dst.block);
2681 case ICMD_IF_ICMPGT: /* ..., 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_LCMPGT: /* ..., value, value ==> ... */
2695 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2696 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2699 codegen_add_branch_ref(cd, iptr->dst.block);
2703 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2705 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2706 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2709 codegen_add_branch_ref(cd, iptr->dst.block);
2713 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2715 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2716 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2719 codegen_add_branch_ref(cd, iptr->dst.block);
2720 /* load low-bits before the branch, so we know the distance */
2721 /* TODO: the loads should not touch the condition code. */
2722 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2723 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2724 M_BGT(SZ_BRC + SZ_CR + SZ_BRC);
2727 codegen_add_branch_ref(cd, iptr->dst.block);
2730 case ICMD_IF_ICMPGE: /* ..., 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_IF_LCMPGE: /* ..., value, value ==> ... */
2744 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2745 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2748 codegen_add_branch_ref(cd, iptr->dst.block);
2752 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2754 REPLACEMENT_POINT_RETURN(cd, iptr);
2755 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2756 M_INTMOVE(s1, REG_RESULT);
2757 goto nowperformreturn;
2759 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2761 REPLACEMENT_POINT_RETURN(cd, iptr);
2762 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2763 M_INTMOVE(s1, REG_RESULT);
2765 #ifdef ENABLE_VERIFIER
2766 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2767 unresolved_class *uc = iptr->sx.s23.s2.uc;
2769 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2771 #endif /* ENABLE_VERIFIER */
2772 goto nowperformreturn;
2774 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2776 REPLACEMENT_POINT_RETURN(cd, iptr);
2777 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2778 M_LNGMOVE(s1, REG_RESULT_PACKED);
2779 goto nowperformreturn;
2781 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2784 REPLACEMENT_POINT_RETURN(cd, iptr);
2785 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2786 M_FLTMOVE(s1, REG_FRESULT);
2787 goto nowperformreturn;
2789 case ICMD_RETURN: /* ... ==> ... */
2791 REPLACEMENT_POINT_RETURN(cd, iptr);
2797 p = cd->stackframesize;
2799 /* call trace function */
2801 /*emit_verbosecall_exit(jd); TODO */
2803 #if defined(ENABLE_THREADS)
2804 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2805 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2806 M_ALD(REG_ITMP3, REG_PV, disp);
2809 /* we need to save the proper return value */
2811 switch (iptr->opc) {
2813 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2817 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2820 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2823 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2827 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2830 /* and now restore the proper return value */
2832 switch (iptr->opc) {
2834 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2838 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2841 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2844 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2850 /* restore return address */
2852 p--; M_ALD(REG_RA, REG_SP, p * 4);
2854 /* restore saved registers */
2856 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2857 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2859 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2860 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2863 /* deallocate stack */
2865 if (cd->stackframesize)
2866 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2873 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2878 branch_target_t *table;
2880 table = iptr->dst.table;
2882 l = iptr->sx.s23.s2.tablelow;
2883 i = iptr->sx.s23.s3.tablehigh;
2885 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2886 M_INTMOVE(s1, REG_ITMP1);
2889 M_ISUB_IMM(l, REG_ITMP1);
2891 /* number of targets */
2895 M_ICMP_IMM(i - 1, REG_ITMP1);
2898 codegen_add_branch_ref(cd, table[0].block); /* default target */
2900 /* build jump table top down and use address of lowest entry */
2905 dseg_add_target(cd, table->block);
2909 /* length of dataseg after last dseg_add_target is used
2912 M_MOV_IMM(0, REG_ITMP2);
2914 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2921 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2926 lookup_target_t *lookup;
2928 lookup = iptr->dst.lookup;
2930 i = iptr->sx.s23.s2.lookupcount;
2932 MCODECHECK(8 + ((7 + 6) * i) + 5);
2933 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2936 M_ICMP_IMM(lookup->value, s1);
2938 codegen_add_branch_ref(cd, lookup->target.block);
2944 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2950 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2952 bte = iptr->sx.s23.s3.bte;
2956 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2957 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2958 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2959 case ICMD_INVOKEINTERFACE:
2961 REPLACEMENT_POINT_INVOKE(cd, iptr);
2963 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2965 um = iptr->sx.s23.s3.um;
2966 md = um->methodref->parseddesc.md;
2969 lm = iptr->sx.s23.s3.fmiref->p.method;
2971 md = lm->parseddesc;
2975 s3 = md->paramcount;
2977 MCODECHECK((s3 << 1) + 64);
2979 /* copy arguments to registers or stack location */
2981 for (s3 = s3 - 1; s3 >= 0; s3--) {
2982 var = VAR(iptr->sx.s23.s2.args[s3]);
2984 /* Already Preallocated? */
2985 if (var->flags & PREALLOC)
2988 if (IS_INT_LNG_TYPE(var->type)) {
2989 if (!md->params[s3].inmemory) {
2990 if (IS_2_WORD_TYPE(var->type)) {
2992 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2993 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2995 d = emit_load(jd, iptr, var, s1);
2999 s1 = rd->argintregs[md->params[s3].regoff];
3000 d = emit_load(jd, iptr, var, s1);
3005 if (IS_2_WORD_TYPE(var->type)) {
3006 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
3007 M_LST(d, REG_SP, md->params[s3].regoff * 4);
3010 d = emit_load(jd, iptr, var, REG_ITMP1);
3011 M_IST(d, REG_SP, md->params[s3].regoff * 4);
3016 if (!md->params[s3].inmemory) {
3017 s1 = rd->argfltregs[md->params[s3].regoff];
3018 d = emit_load(jd, iptr, var, s1);
3022 d = emit_load(jd, iptr, var, REG_FTMP1);
3023 if (IS_2_WORD_TYPE(var->type))
3024 M_DST(d, REG_SP, md->params[s3].regoff * 4);
3026 M_FST(d, REG_SP, md->params[s3].regoff * 4);
3031 switch (iptr->opc) {
3033 disp = dseg_add_functionptr(cd, bte->fp);
3035 N_AHI(REG_SP, -96); /* register save are required by C abi */
3036 N_LHI(REG_ITMP1, disp);
3037 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3040 case ICMD_INVOKESPECIAL:
3041 emit_nullpointer_check(cd, iptr, REG_A0);
3042 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
3045 case ICMD_INVOKESTATIC:
3047 disp = dseg_add_unique_address(cd, um);
3049 codegen_addpatchref(cd, PATCHER_invokestatic_special,
3053 disp = dseg_add_address(cd, lm->stubroutine);
3055 N_LHI(REG_ITMP1, disp);
3056 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3059 case ICMD_INVOKEVIRTUAL:
3060 emit_nullpointer_check(cd, iptr, REG_A0);
3063 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
3068 s1 = OFFSET(vftbl_t, table[0]) +
3069 sizeof(methodptr) * lm->vftblindex;
3072 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
3073 M_ALD(REG_PV, REG_METHODPTR, s1);
3076 case ICMD_INVOKEINTERFACE:
3077 emit_nullpointer_check(cd, iptr, REG_A0);
3080 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3086 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3087 sizeof(methodptr*) * lm->class->index;
3089 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3092 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
3093 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
3094 M_ALD(REG_PV, REG_METHODPTR, s2);
3098 /* generate the actual call */
3101 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
3102 N_BASR(REG_ITMP1, RN);
3103 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3104 M_LDA(REG_PV, REG_ITMP1, -disp);
3106 /* post call finalization */
3108 if (iptr->opc == ICMD_BUILTIN) {
3109 N_AHI(REG_SP, 96); /* remove C abi register save area */
3112 /* actually only used for ICMD_BUILTIN */
3114 if (INSTRUCTION_MUST_CHECK(iptr)) {
3117 codegen_add_fillinstacktrace_ref(cd);
3120 /* store return value */
3122 d = md->returntype.type;
3124 if (d != TYPE_VOID) {
3125 if (IS_INT_LNG_TYPE(d)) {
3126 if (IS_2_WORD_TYPE(d)) {
3127 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
3128 M_LNGMOVE(REG_RESULT_PACKED, s1);
3131 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3132 M_INTMOVE(REG_RESULT, s1);
3136 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
3137 M_FLTMOVE(REG_FRESULT, s1);
3139 emit_store_dst(jd, iptr, s1);
3145 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3147 /* val.a: (classinfo*) superclass */
3149 /* superclass is an interface:
3151 * OK if ((sub == NULL) ||
3152 * (sub->vftbl->interfacetablelength > super->index) &&
3153 * (sub->vftbl->interfacetable[-super->index] != NULL));
3155 * superclass is a class:
3157 * OK if ((sub == NULL) || (0
3158 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3159 * super->vftbl->diffval));
3162 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
3163 /* object type cast-check */
3166 vftbl_t *supervftbl;
3169 u1 *class_label_refs[] = { 0 }, *class_label;
3170 u1 *exit_label_refs[] = { 0, 0, 0, 0 };
3172 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3178 super = iptr->sx.s23.s3.c.cls;
3179 superindex = super->index;
3180 supervftbl = super->vftbl;
3183 #if defined(ENABLE_THREADS)
3184 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3186 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3188 /* if class is not resolved, check which code to call */
3190 if (super == NULL) {
3192 exit_label_refs[0] = cd->mcodeptr;
3195 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3197 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3198 iptr->sx.s23.s3.c.ref,
3201 ICONST(REG_ITMP2, ACC_INTERFACE);
3202 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3203 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3204 class_label_refs[0] = cd->mcodeptr;
3208 /* interface checkcast code */
3210 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3211 if (super == NULL) {
3212 codegen_add_patch_ref(cd,
3213 PATCHER_checkcast_instanceof_interface,
3214 iptr->sx.s23.s3.c.ref,
3218 exit_label_refs[1] = cd->mcodeptr;
3222 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3223 M_ILD(REG_ITMP3, REG_ITMP2,
3224 OFFSET(vftbl_t, interfacetablelength));
3225 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3228 codegen_add_classcastexception_ref(cd, s1);
3229 M_ALD(REG_ITMP3, REG_ITMP2,
3230 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3231 superindex * sizeof(methodptr*)));
3234 codegen_add_classcastexception_ref(cd, s1);
3236 if (super == NULL) {
3237 exit_label_refs[2] = cd->mcodeptr;
3242 /* class checkcast code */
3244 class_label = cd->mcodeptr;
3246 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3247 if (super == NULL) {
3248 disp = dseg_add_unique_address(cd, NULL);
3250 codegen_add_patch_ref(cd,
3251 PATCHER_resolve_classref_to_vftbl,
3252 iptr->sx.s23.s3.c.ref,
3256 disp = dseg_add_address(cd, supervftbl);
3258 exit_label_refs[3] = cd->mcodeptr;
3262 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3263 M_ALD(REG_ITMP3, REG_PV, disp);
3264 #if defined(ENABLE_THREADS)
3265 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3267 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3268 /* if (s1 != REG_ITMP1) { */
3269 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3270 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3271 /* #if defined(ENABLE_THREADS) */
3272 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3274 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3277 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3278 M_ISUB(REG_ITMP2, REG_ITMP3);
3279 M_ALD(REG_ITMP3, REG_PV, disp);
3280 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3281 #if defined(ENABLE_THREADS)
3282 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3285 N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3286 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3287 M_BGT(0); /* Branch if greater then */
3288 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3289 codegen_add_classcastexception_ref(cd, s1);
3292 /* resolve labels by adding the correct displacement */
3294 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3295 if (exit_label_refs[s2])
3296 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3299 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3300 if (class_label_refs[s2])
3301 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3304 d = codegen_reg_of_dst(jd, iptr, s1);
3307 /* array type cast-check */
3309 s1 = emit_load_s1(jd, iptr, REG_A0);
3310 M_INTMOVE(s1, REG_A0);
3312 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3313 disp = dseg_add_unique_address(cd, NULL);
3315 codegen_add_patch_ref(cd,
3316 PATCHER_resolve_classref_to_classinfo,
3317 iptr->sx.s23.s3.c.ref,
3321 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3323 M_ALD(REG_A1, REG_PV, disp);
3324 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3325 ICONST(REG_ITMP1, disp); /* TODO negative displacement */
3326 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3327 M_JSR(REG_RA, REG_PV);
3328 N_BASR(REG_ITMP1, RN);
3329 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3330 M_LDA(REG_PV, REG_ITMP1, -disp);
3332 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3335 codegen_add_classcastexception_ref(cd, s1);
3337 d = codegen_reg_of_dst(jd, iptr, s1);
3341 emit_store_dst(jd, iptr, d);
3344 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3347 /* val.a: (classinfo*) superclass */
3349 /* superclass is an interface:
3351 * return (sub != NULL) &&
3352 * (sub->vftbl->interfacetablelength > super->index) &&
3353 * (sub->vftbl->interfacetable[-super->index] != NULL);
3355 * superclass is a class:
3357 * return ((sub != NULL) && (0
3358 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3359 * super->vftbl->diffvall));
3364 vftbl_t *supervftbl;
3367 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3373 super = iptr->sx.s23.s3.c.cls;
3374 superindex = super->index;
3375 supervftbl = super->vftbl;
3378 #if defined(ENABLE_THREADS)
3379 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3381 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3382 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3384 M_MOV(s1, REG_ITMP1);
3388 /* calculate interface instanceof code size */
3392 s2 += (d == REG_ITMP2 ? 1 : 0) + (opt_shownops ? 1 : 0);
3394 /* calculate class instanceof code size */
3398 s3 += (opt_shownops ? 1 : 0);
3400 /* if class is not resolved, check which code to call */
3402 if (super == NULL) {
3404 M_BEQZ(s1, 4 + (opt_shownops ? 1 : 0) + s2 + 1 + s3);
3406 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3408 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3409 iptr->sx.s23.s3.c.ref, disp);
3411 M_ILD(REG_ITMP3, REG_PV, disp);
3413 disp = dseg_add_s4(cd, ACC_INTERFACE);
3414 M_ILD(REG_ITMP2, REG_PV, disp);
3415 M_AND(REG_ITMP3, REG_ITMP2, REG_ITMP3);
3416 M_BEQZ(REG_ITMP3, s2 + 1);
3419 /* interface instanceof code */
3421 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3422 if (super == NULL) {
3423 /* If d == REG_ITMP2, then it's destroyed in check
3428 codegen_add_patch_ref(cd,
3429 PATCHER_checkcast_instanceof_interface,
3430 iptr->sx.s23.s3.c.ref, 0);
3437 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3438 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3439 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3440 M_BLEZ(REG_ITMP3, 2);
3441 M_ALD(REG_ITMP1, REG_ITMP1,
3442 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3443 superindex * sizeof(methodptr*)));
3444 M_CMPULT(REG_ZERO, REG_ITMP1, d); /* REG_ITMP1 != 0 */
3450 /* class instanceof code */
3452 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3453 if (super == NULL) {
3454 disp = dseg_add_unique_address(cd, NULL);
3456 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3457 iptr->sx.s23.s3.c.ref,
3461 disp = dseg_add_address(cd, supervftbl);
3467 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3468 M_ALD(REG_ITMP2, REG_PV, disp);
3469 #if defined(ENABLE_THREADS)
3470 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3472 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3473 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3474 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3475 #if defined(ENABLE_THREADS)
3476 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3478 M_ISUB(REG_ITMP1, REG_ITMP3);
3479 N_CLR(REG_ITMP1, REG_ITMP2);
3480 M_CMPULE(REG_ITMP1, REG_ITMP2, d);
3482 emit_store_dst(jd, iptr, d);
3487 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3491 /* check for negative sizes and copy sizes to stack if necessary */
3493 MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3495 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3497 /* copy SAVEDVAR sizes to stack */
3498 var = VAR(iptr->sx.s23.s2.args[s1]);
3500 /* Already Preallocated? */
3501 if (!(var->flags & PREALLOC)) {
3502 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3503 M_LST(s2, REG_SP, s1 * 8);
3507 /* is a patcher function set? */
3509 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3510 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
3511 iptr->sx.s23.s3.c.ref, 0);
3514 /* a0 = dimension count */
3516 M_MOV_IMM(iptr->s1.argcount, REG_A0);
3518 /* a1 = classinfo */
3520 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3522 /* a2 = pointer to dimensions = stack pointer */
3524 M_MOV(REG_SP, REG_A2);
3526 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3529 /* check for exception before result assignment */
3533 codegen_add_fillinstacktrace_ref(cd);
3535 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3536 M_INTMOVE(REG_RESULT, s1);
3537 emit_store_dst(jd, iptr, s1);
3542 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3546 } /* for instruction */
3548 MCODECHECK(512); /* XXX require a lower number? */
3550 /* At the end of a basic block we may have to append some nops,
3551 because the patcher stub calling code might be longer than the
3552 actual instruction. So codepatching does not change the
3553 following block unintentionally. */
3555 if (cd->mcodeptr < cd->lastmcodeptr) {
3556 while (cd->mcodeptr < cd->lastmcodeptr) {
3561 } /* if (bptr -> flags >= BBREACHED) */
3562 } /* for basic block */
3564 dseg_createlinenumbertable(cd);
3566 /* generate stubs */
3568 emit_exception_stubs(jd);
3569 emit_patcher_stubs(jd);
3571 emit_replacement_stubs(jd);
3576 /* everything's ok */
3582 /* createcompilerstub **********************************************************
3584 Creates a stub routine which calls the compiler.
3586 *******************************************************************************/
3588 #define COMPILERSTUB_DATASIZE (3 * SIZEOF_VOID_P)
3589 #define COMPILERSTUB_CODESIZE (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
3591 #define COMPILERSTUB_SIZE (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE)
3594 u1 *createcompilerstub(methodinfo *m)
3596 u1 *s; /* memory to hold the stub */
3602 s = CNEW(u1, COMPILERSTUB_SIZE);
3604 /* set data pointer and code pointer */
3607 s = s + COMPILERSTUB_DATASIZE;
3609 /* mark start of dump memory area */
3611 dumpsize = dump_size();
3613 cd = DNEW(codegendata);
3616 /* Store the codeinfo pointer in the same place as in the
3617 methodheader for compiled methods. */
3619 code = code_codeinfo_new(m);
3621 d[0] = (ptrint) asm_call_jit_compiler;
3623 d[2] = (ptrint) code;
3625 /* code for the stub */
3627 /* don't touch ITMP3 as it cointains the return address */
3629 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3631 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3632 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3633 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3636 #if defined(ENABLE_STATISTICS)
3638 count_cstub_len += COMPILERSTUB_SIZE;
3641 /* release dump area */
3643 dump_release(dumpsize);
3649 /* createnativestub ************************************************************
3651 Creates a stub routine which calls a native method.
3653 *******************************************************************************/
3656 arguments on stack \
3657 -------------------------------------------------| <- SP on nativestub entry
3659 callee saved int regs (none) |
3660 callee saved float regs (none) | stack frame like in cacao
3661 local variable slots (none) |
3662 arguments for calling methods (none) /
3663 ------------------------------------------------------------------ <- datasp
3668 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3669 0 - 96 register save area for callee /
3670 -------------------------------------------------------- <- SP native method
3672 SP after method entry
3675 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3683 s4 i, j; /* count variables */
3688 /* get required compiler data */
3695 /* initialize variables */
3698 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3700 /* calculate stack frame size */
3702 cd->stackframesize =
3703 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3704 sizeof(localref_table) / SIZEOF_VOID_P +
3705 INT_ARG_CNT + FLT_ARG_CNT +
3706 1 + /* functionptr, TODO: store in data segment */
3709 cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */
3712 cd->stackframesize =
3713 1 + /* r14 - return address */ +
3714 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3715 sizeof(localref_table) / SIZEOF_VOID_P +
3717 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3718 nmd->memuse + /* parameter passing */
3719 96 / SIZEOF_VOID_P /* required by ABI */;
3721 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3724 /* create method header */
3726 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3727 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3728 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3729 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3730 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3731 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3732 (void) dseg_addlinenumbertablesize(cd);
3733 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3735 /* generate native method profiling code */
3737 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3738 /* count frequency */
3740 M_MOV_IMM(code, REG_ITMP3);
3741 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3745 /* generate stub code */
3747 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3749 /* save return address */
3751 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3754 #if !defined(NDEBUG)
3755 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3756 emit_verbosecall_enter(jd);
3760 /* get function address (this must happen before the stackframeinfo) */
3762 disp = dseg_add_functionptr(cd, f);
3764 #if !defined(WITH_STATIC_CLASSPATH)
3766 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3769 M_ILD(REG_ITMP1, REG_PV, disp);
3771 j = 96 + (nmd->memuse * 4);
3773 /* todo some arg registers are not volatile in C-abi terms */
3775 /* save integer and float argument registers */
3777 for (i = 0; i < md->paramcount; i++) {
3778 if (! md->params[i].inmemory) {
3779 s1 = md->params[i].regoff;
3781 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3782 if (IS_2_WORD_TYPE(t)) {
3783 /* todo store multiple */
3784 N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3785 N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3787 N_ST(rd->argintregs[s1], j, RN, REG_SP);
3790 if (IS_2_WORD_TYPE(t)) {
3791 N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3793 N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3801 N_ST(REG_ITMP1, j, RN, REG_SP);
3803 /* create dynamic stack info */
3805 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3806 N_LR(REG_A1, REG_PV); /* pv */
3807 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3808 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3810 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3811 M_ILD(REG_ITMP1, REG_PV, disp);
3813 M_CALL(REG_ITMP1); /* call */
3815 /* restore integer and float argument registers */
3817 j = 96 + (nmd->memuse * 4);
3819 for (i = 0; i < md->paramcount; i++) {
3820 if (! md->params[i].inmemory) {
3821 s1 = md->params[i].regoff;
3823 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3824 if (IS_2_WORD_TYPE(t)) {
3825 /* todo load multiple ! */
3826 N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3827 N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3829 N_L(rd->argintregs[s1], j, RN, REG_SP);
3832 if (IS_2_WORD_TYPE(t)) {
3833 N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3835 N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3843 N_L(REG_ITMP1, j, RN, REG_SP);
3845 /* copy or spill arguments to new locations */
3847 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3848 t = md->paramtypes[i].type;
3850 if (IS_INT_LNG_TYPE(t)) {
3852 if (!md->params[i].inmemory) {
3854 s1 = rd->argintregs[md->params[i].regoff];
3856 if (!nmd->params[j].inmemory) {
3857 s2 = rd->argintregs[nmd->params[j].regoff];
3858 if (IS_2_WORD_TYPE(t)) {
3859 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3860 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3865 s2 = nmd->params[j].regoff;
3866 if (IS_2_WORD_TYPE(t)) {
3867 N_LM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3869 N_L(s1, 96 + (s2 * 4), RN, REG_SP);
3874 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3875 s2 = nmd->params[j].regoff;
3877 if (IS_2_WORD_TYPE(t)) {
3878 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3880 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3885 /* We only copy spilled float arguments, as the float argument */
3886 /* registers keep unchanged. */
3888 if (md->params[i].inmemory) {
3889 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3890 s2 = nmd->params[j].regoff;
3892 if (IS_2_WORD_TYPE(t)) {
3893 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3895 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3901 /* put class into second argument register */
3903 if (m->flags & ACC_STATIC) {
3904 disp = dseg_add_address(cd, m->class);
3905 M_ILD(REG_A1, REG_PV, disp);
3908 /* put env into first argument register */
3910 disp = dseg_add_address(cd, _Jv_env);
3911 M_ILD(REG_A0, REG_PV, disp);
3913 /* do the native function call */
3915 M_CALL(REG_ITMP1); /* call */
3917 /* save return value */
3919 t = md->returntype.type;
3921 if (t != TYPE_VOID) {
3922 if (IS_INT_LNG_TYPE(t)) {
3923 if (IS_2_WORD_TYPE(t)) {
3924 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3926 N_ST(REG_RESULT, 96, RN, REG_SP);
3929 if (IS_2_WORD_TYPE(t)) {
3930 N_STD(REG_FRESULT, 96, RN, REG_SP);
3932 N_STE(REG_FRESULT, 96, RN, REG_SP);
3938 #if !defined(NDEBUG)
3939 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3940 emit_verbosecall_exit(jd);
3944 /* remove native stackframe info */
3946 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3947 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3948 M_ILD(REG_ITMP1, REG_PV, disp);
3950 N_LR(REG_ITMP3, REG_RESULT);
3952 /* restore return value */
3954 if (t != TYPE_VOID) {
3955 if (IS_INT_LNG_TYPE(t)) {
3956 if (IS_2_WORD_TYPE(t)) {
3957 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3959 N_L(REG_RESULT, 96, RN, REG_SP);
3962 if (IS_2_WORD_TYPE(t)) {
3963 N_LD(REG_FRESULT, 96, RN, REG_SP);
3965 N_LE(REG_FRESULT, 96, RN, REG_SP);
3970 /* load return address */
3972 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3974 /* remove stackframe */
3976 N_AHI(REG_SP, cd->stackframesize * 4);
3978 /* test for exception */
3980 N_LTR(REG_ITMP3, REG_ITMP3);
3981 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3985 N_BCR(DD_ANY, REG_ITMP2);
3987 /* handle exception */
3992 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3993 M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8); /* get return address from stack */
3994 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3996 M_MOV_IMM(asm_handle_nat_exception, REG_ITMP3);
4000 /* generate patcher stubs */
4002 emit_patcher_stubs(jd);
4006 return code->entrypoint;
4013 * These are local overrides for various environment variables in Emacs.
4014 * Please do not remove this and leave it at the end of the file, where
4015 * Emacs will automagically detect them.
4016 * ---------------------------------------------------------------------
4019 * indent-tabs-mode: t
4023 * vim:noexpandtab:sw=4:ts=4: