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 7581 2007-03-26 07:23:16Z 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);
87 u1 *createcompilerstub(methodinfo *m) {
96 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd) {
98 return createcompilerstub(NULL);
104 /* codegen *********************************************************************
106 Generates machine code.
108 *******************************************************************************/
111 bool codegen(jitdata *jd)
117 s4 len, s1, s2, s3, d, disp;
120 varinfo *var, *var1, *var2, *dst;
124 constant_classref *cr;
125 unresolved_class *uc;
126 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
127 unresolved_method *um;
128 builtintable_entry *bte;
131 unresolved_field *uf;
134 rplpoint *replacementpoint;
138 /* get required compiler data */
145 /* prevent compiler warnings */
158 /* space to save used callee saved registers */
160 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
161 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
163 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
166 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
169 #if defined(ENABLE_THREADS)
170 /* space to save argument of monitor_enter */
171 OOPS(); /* see powerpc */
173 if (checksync && (m->flags & ACC_SYNCHRONIZED))
174 cd->stackframesize++;
178 /* Keep stack of non-leaf functions 16-byte aligned for calls into
179 native code e.g. libc or jni (alignment problems with
182 if (!jd->isleafmethod || opt_verbosecall )
183 /* TODO really 16 bytes ? */
184 cd->stackframesize = (cd->stackframesize + 3) & ~3;
186 /* create method header */
188 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
189 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
191 #if defined(ENABLE_THREADS)
192 /* IsSync contains the offset relative to the stack pointer for the
193 argument of monitor_exit used in the exception handler. Since the
194 offset could be zero and give a wrong meaning of the flag it is
198 if (checksync && (m->flags & ACC_SYNCHRONIZED))
199 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
203 (void) dseg_add_unique_s4(cd, 0);*/ /* IsSync */
205 disp = dseg_add_unique_address(cd, 0);
207 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
208 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
209 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
211 (void) dseg_addlinenumbertablesize(cd);
213 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
215 /* create exception table */
217 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
218 dseg_add_target(cd, ex->start);
219 dseg_add_target(cd, ex->end);
220 dseg_add_target(cd, ex->handler);
221 (void) dseg_add_unique_address(cd, ex->catchtype.any);
224 /* generate method profiling code */
226 #if defined(ENABLE_PROFILING)
227 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
228 /* count frequency */
230 M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
231 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
232 M_IADD_IMM(1, REG_ITMP2);
233 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
235 /* PROFILE_CYCLE_START; */
239 /* create stack frame (if necessary) */
241 if (cd->stackframesize)
242 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
244 N_LHI(REG_ITMP2, disp);
245 N_ST(REG_SP, 0, REG_ITMP2, REG_PV);
247 /* save used callee saved registers and return address */
249 p = cd->stackframesize;
250 p--; M_AST(REG_RA, REG_SP, p * 4);
252 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
253 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
255 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
256 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
259 /* take arguments out of register or stack frame */
263 for (p = 0, l = 0; p < md->paramcount; p++) {
264 t = md->paramtypes[p].type;
265 varindex = jd->local_map[l * 5 + t];
268 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
271 if (varindex == UNUSED)
276 s1 = md->params[p].regoff;
277 if (IS_INT_LNG_TYPE(t)) { /* integer args */
278 if (IS_2_WORD_TYPE(t))
279 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
280 rd->argintregs[GET_HIGH_REG(s1)]);
282 s2 = rd->argintregs[s1];
283 if (!md->params[p].inmemory) { /* register arguments */
284 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
285 if (IS_2_WORD_TYPE(t))
286 M_LNGMOVE(s2, var->vv.regoff);
288 M_INTMOVE(s2, var->vv.regoff);
290 } else { /* reg arg -> spilled */
291 if (IS_2_WORD_TYPE(t))
292 M_LST(s2, REG_SP, var->vv.regoff * 4);
294 M_IST(s2, REG_SP, var->vv.regoff * 4);
297 } else { /* stack arguments */
298 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
299 if (IS_2_WORD_TYPE(t))
300 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
302 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
304 } else { /* stack arg -> spilled */
305 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
306 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
307 if (IS_2_WORD_TYPE(t)) {
308 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4);
309 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
314 } else { /* floating args */
315 if (!md->params[p].inmemory) { /* register arguments */
316 s2 = rd->argfltregs[s1];
317 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
318 M_FLTMOVE(s2, var->vv.regoff);
320 } else { /* reg arg -> spilled */
321 if (IS_2_WORD_TYPE(t))
322 M_DST(s2, REG_SP, var->vv.regoff * 4);
324 M_FST(s2, REG_SP, var->vv.regoff * 4);
327 } else { /* stack arguments */
328 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
329 if (IS_2_WORD_TYPE(t))
330 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
333 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
335 } else { /* stack-arg -> spilled */
336 if (IS_2_WORD_TYPE(t)) {
337 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
338 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
339 var->vv.regoff = cd->stackframesize + s1;
342 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
343 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
350 /* save monitorenter argument */
352 #if defined(ENABLE_THREADS)
353 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
354 /* stack offset for monitor argument */
358 if (opt_verbosecall) {
359 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
361 for (p = 0; p < INT_ARG_CNT; p++)
362 M_LST(rd->argintregs[p], REG_SP, p * 8);
364 for (p = 0; p < FLT_ARG_CNT; p++)
365 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
367 s1 += INT_ARG_CNT + FLT_ARG_CNT;
370 /* decide which monitor enter function to call */
372 if (m->flags & ACC_STATIC) {
373 M_MOV_IMM(&m->class->object.header, REG_A0);
378 codegen_add_nullpointerexception_ref(cd);
381 M_AST(REG_A0, REG_SP, s1 * 8);
382 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
385 if (opt_verbosecall) {
386 for (p = 0; p < INT_ARG_CNT; p++)
387 M_LLD(rd->argintregs[p], REG_SP, p * 8);
389 for (p = 0; p < FLT_ARG_CNT; p++)
390 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
392 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
398 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
399 emit_verbosecall_enter(jd);
400 #endif /* !defined(NDEBUG) */
404 /* end of header generation */
406 replacementpoint = jd->code->rplpoints;
409 /* walk through all basic blocks */
411 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
413 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
415 if (bptr->flags >= BBREACHED) {
417 /* branch resolving */
419 codegen_resolve_branchrefs(cd, bptr);
421 /* handle replacement points */
424 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
425 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
429 assert(cd->lastmcodeptr <= cd->mcodeptr);
430 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
434 /* copy interface registers to their destination */
439 /* generate basicblock profiling code */
441 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
442 /* count frequency */
444 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
445 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
447 /* if this is an exception handler, start profiling again */
449 if (bptr->type == BBTYPE_EXH)
453 #if defined(ENABLE_LSRA)
457 src = bptr->invars[len];
458 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
459 if (bptr->type == BBTYPE_EXH) {
460 /* d = reg_of_var(rd, src, REG_ITMP1); */
461 if (!IS_INMEMORY(src->flags))
465 M_INTMOVE(REG_ITMP1, d);
466 emit_store(jd, NULL, src, d);
476 var = VAR(bptr->invars[len]);
477 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
478 if (bptr->type == BBTYPE_EXH) {
479 d = codegen_reg_of_var(0, var, REG_ITMP1);
480 M_INTMOVE(REG_ITMP1, d);
481 emit_store(jd, NULL, var, d);
485 assert((var->flags & INOUT));
488 #if defined(ENABLE_LSRA)
491 /* walk through all instructions */
496 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
497 if (iptr->line != currentline) {
498 dseg_addlinenumber(cd, iptr->line);
499 currentline = iptr->line;
502 MCODECHECK(1024); /* 1KB should be enough */
505 case ICMD_NOP: /* ... ==> ... */
506 case ICMD_POP: /* ..., value ==> ... */
507 case ICMD_POP2: /* ..., value, value ==> ... */
508 case ICMD_INLINE_START: /* internal ICMDs */
509 case ICMD_INLINE_END:
512 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
513 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
516 codegen_add_nullpointerexception_ref(cd);
519 /* constant operations ************************************************/
521 case ICMD_ICONST: /* ... ==> ..., constant */
522 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
523 ICONST(d, iptr->sx.val.i);
524 emit_store_dst(jd, iptr, d);
527 case ICMD_LCONST: /* ... ==> ..., constant */
529 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
530 LCONST(d, iptr->sx.val.l);
531 emit_store_dst(jd, iptr, d);
534 case ICMD_FCONST: /* ... ==> ..., constant */
535 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
536 disp = dseg_add_float(cd, iptr->sx.val.f);
537 M_FLDN(d, REG_PV, disp, REG_ITMP1);
538 emit_store_dst(jd, iptr, d);
541 case ICMD_DCONST: /* ... ==> ..., constant */
542 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
543 disp = dseg_add_double(cd, iptr->sx.val.d);
544 M_DLDN(d, REG_PV, disp, REG_ITMP1);
545 emit_store_dst(jd, iptr, d);
548 case ICMD_ACONST: /* ... ==> ..., constant */
549 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
551 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
552 cr = iptr->sx.val.c.ref;
553 disp = dseg_add_unique_address(cd, cr);
555 /* PROFILE_CYCLE_STOP; */
557 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
560 /* PROFILE_CYCLE_START; */
562 M_ALD(d, REG_PV, disp);
564 if (iptr->sx.val.anyptr == 0) {
567 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
568 M_ALD(d, REG_PV, disp);
571 emit_store_dst(jd, iptr, d);
575 /* load/store/copy/move operations ************************************/
577 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
578 case ICMD_ALOAD: /* s1 = local variable */
582 case ICMD_ISTORE: /* ..., value ==> ... */
588 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
592 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
593 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
596 /* integer operations *************************************************/
598 case ICMD_INEG: /* ..., value ==> ..., - value */
600 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
601 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
603 emit_store_dst(jd, iptr, d);
607 case ICMD_LNEG: /* ..., value ==> ..., - value */
610 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
611 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
614 emit_store_dst(jd, iptr, d);
618 case ICMD_I2L: /* ..., value ==> ..., value */
621 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
622 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
624 emit_store_dst(jd, iptr, d);
628 case ICMD_L2I: /* ..., value ==> ..., value */
631 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
632 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
634 emit_store_dst(jd, iptr, d);
638 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
641 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
642 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
644 emit_store_dst(jd, iptr, d);
648 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
649 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
650 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
654 emit_store_dst(jd, iptr, d);
657 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
660 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
661 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
663 emit_store_dst(jd, iptr, d);
668 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
670 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
671 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
672 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
679 emit_store_dst(jd, iptr, d);
684 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
685 /* sx.val.i = constant */
686 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
687 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
690 if (N_VALID_IMM(iptr->sx.val.i)) {
691 M_IADD_IMM(iptr->sx.val.i, d);
693 disp = dseg_add_s4(cd, iptr->sx.val.i);
694 M_ILD(REG_ITMP2, REG_PV, disp);
695 M_IADD(REG_ITMP2, d);
697 emit_store_dst(jd, iptr, d);
700 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
703 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
704 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
705 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
712 emit_store_dst(jd, iptr, d);
716 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
717 /* sx.val.l = constant */
720 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
721 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
723 if (IS_IMM32(iptr->sx.val.l))
724 M_LADD_IMM(iptr->sx.val.l, d);
726 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
727 M_LADD(REG_ITMP2, d);
729 emit_store_dst(jd, iptr, d);
733 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
735 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
736 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
737 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
739 M_INTMOVE(s1, REG_ITMP1);
740 M_ISUB(s2, REG_ITMP1);
741 M_INTMOVE(REG_ITMP1, d);
746 emit_store_dst(jd, iptr, d);
750 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
751 /* sx.val.i = constant */
753 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
754 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
757 if (N_VALID_IMM(iptr->sx.val.i)) {
758 M_ISUB_IMM(iptr->sx.val.i, d);
760 disp = dseg_add_s4(cd, iptr->sx.val.i);
761 M_ILD(REG_ITMP2, REG_PV, disp);
762 M_ISUB(REG_ITMP2, d);
764 emit_store_dst(jd, iptr, d);
768 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
771 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
772 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
773 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
775 M_INTMOVE(s1, REG_ITMP1);
776 M_LSUB(s2, REG_ITMP1);
777 M_INTMOVE(REG_ITMP1, d);
782 emit_store_dst(jd, iptr, d);
786 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
787 /* sx.val.l = constant */
790 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
791 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
793 if (IS_IMM32(iptr->sx.val.l))
794 M_LSUB_IMM(iptr->sx.val.l, d);
796 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
797 M_LSUB(REG_ITMP2, d);
799 emit_store_dst(jd, iptr, d);
803 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
806 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
807 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
808 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
815 emit_store_dst(jd, iptr, d);
819 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
820 /* sx.val.i = constant */
821 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
822 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
824 if (iptr->sx.val.i == 2) {
826 } else if (N_VALID_IMM(iptr->sx.val.i)) {
827 M_IMUL_IMM(iptr->sx.val.i, d);
829 disp = dseg_add_s4(cd, iptr->sx.val.i);
830 M_ILD(REG_ITMP2, REG_PV, disp);
831 M_IMUL(REG_ITMP2, d);
833 emit_store_dst(jd, iptr, d);
836 case ICMD_LMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
839 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
840 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
841 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
848 emit_store_dst(jd, iptr, d);
852 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
853 /* sx.val.l = constant */
856 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
857 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
858 if (IS_IMM32(iptr->sx.val.l))
859 M_LMUL_IMM(s1, iptr->sx.val.l, d);
861 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
863 M_LMUL(REG_ITMP2, d);
865 emit_store_dst(jd, iptr, d);
869 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
870 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
872 /* For this operation we need a register pair.
873 * We will use r0 and itmp1 and will backup r0.
876 M_INTMOVE(R0, REG_ITMP3);
878 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
880 s1 = emit_load_s1(jd, iptr, R0);
887 if (iptr->opc == ICMD_IREM) {
888 d = codegen_reg_of_dst(jd, iptr, R0);
891 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
892 M_INTMOVE(REG_ITMP1, d);
895 emit_store_dst(jd, iptr, d);
897 M_INTMOVE(REG_ITMP3, R0);
901 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
902 /* sx.val.i = constant */
905 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
906 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
907 M_INTMOVE(s1, REG_ITMP1);
908 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
909 emit_leal_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
910 emit_cmovccl_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
911 emit_shiftl_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
912 emit_mov_reg_reg(cd, REG_ITMP1, d);
913 emit_store_dst(jd, iptr, d);
917 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
918 /* sx.val.i = constant */
921 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
922 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
923 M_INTMOVE(s1, REG_ITMP1);
924 emit_alul_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
925 emit_leal_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
926 emit_cmovccl_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
927 emit_alul_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
928 emit_alul_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
929 emit_mov_reg_reg(cd, REG_ITMP1, d);
930 emit_store_dst(jd, iptr, d);
935 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
938 var1 = VAROP(iptr->s1);
939 var2 = VAROP(iptr->sx.s23.s2);
940 dst = VAROP(iptr->dst);
942 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
944 if (IS_INMEMORY(var1->flags))
945 M_LLD(RAX, REG_SP, var1->vv.regoff * 8);
947 M_INTMOVE(var1->vv.regoff, RAX);
949 if (IS_INMEMORY(var2->flags))
950 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
952 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
957 codegen_add_arithmeticexception_ref(cd);
960 /* check as described in jvm spec */
961 disp = dseg_add_s8(cd, 0x8000000000000000LL);
962 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, RAX);
964 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
965 M_BEQ(3 + 2 + 3); /* 6 bytes */
967 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
969 emit_idiv_reg(cd, REG_ITMP3);
971 if (IS_INMEMORY(dst->flags)) {
972 M_LST(RAX, REG_SP, dst->vv.regoff * 8);
973 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
976 M_INTMOVE(RAX, dst->vv.regoff);
978 if (dst->vv.regoff != RDX) {
979 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
985 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
988 var1 = VAROP(iptr->s1);
989 var2 = VAROP(iptr->sx.s23.s2);
990 dst = VAROP(iptr->dst);
992 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
994 if (IS_INMEMORY(var1->flags))
995 M_LLD(REG_ITMP1, REG_SP, var1->vv.regoff * 8);
997 M_INTMOVE(var1->vv.regoff, REG_ITMP1);
999 if (IS_INMEMORY(var2->flags))
1000 M_LLD(REG_ITMP3, REG_SP, var2->vv.regoff * 8);
1002 M_INTMOVE(var2->vv.regoff, REG_ITMP3);
1004 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1005 M_INTMOVE(s1, REG_ITMP1);
1006 s2 = emit_load_s2(jd, iptr, REG_ITMP3);
1007 M_INTMOVE(s2, REG_ITMP3);
1012 codegen_add_arithmeticexception_ref(cd);
1015 M_MOV(RDX, REG_ITMP2); /* save %rdx, cause it's an argument register */
1017 /* check as described in jvm spec */
1018 disp = dseg_add_s8(cd, 0x8000000000000000LL);
1019 M_LCMP_MEMBASE(RIP, -((cd->mcodeptr + 7) - cd->mcodebase) + disp, REG_ITMP1);
1023 emit_alul_reg_reg(cd, ALU_XOR, RDX, RDX); /* 2 bytes */
1025 M_LXOR(RDX, RDX); /* 3 bytes */
1026 M_LCMP_IMM(-1, REG_ITMP3); /* 4 bytes */
1027 M_BEQ(2 + 3); /* 6 bytes */
1030 emit_idiv_reg(cd, REG_ITMP3);
1032 if (IS_INMEMORY(dst->flags)) {
1033 M_LST(RDX, REG_SP, dst->vv.regoff * 8);
1034 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1037 M_INTMOVE(RDX, dst->vv.regoff);
1039 if (dst->vv.regoff != RDX) {
1040 M_MOV(REG_ITMP2, RDX); /* restore %rdx */
1046 case ICMD_LDIVPOW2: /* ..., value ==> ..., value >> constant */
1047 /* sx.val.i = constant */
1050 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1051 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1052 M_INTMOVE(s1, REG_ITMP1);
1053 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1054 emit_lea_membase_reg(cd, REG_ITMP1, (1 << iptr->sx.val.i) - 1, REG_ITMP2);
1055 emit_cmovcc_reg_reg(cd, CC_LE, REG_ITMP2, REG_ITMP1);
1056 emit_shift_imm_reg(cd, SHIFT_SAR, iptr->sx.val.i, REG_ITMP1);
1057 emit_mov_reg_reg(cd, REG_ITMP1, d);
1058 emit_store_dst(jd, iptr, d);
1062 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
1063 /* sx.val.l = constant */
1066 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1067 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1068 M_INTMOVE(s1, REG_ITMP1);
1069 emit_alu_imm_reg(cd, ALU_CMP, -1, REG_ITMP1);
1070 emit_lea_membase_reg(cd, REG_ITMP1, iptr->sx.val.i, REG_ITMP2);
1071 emit_cmovcc_reg_reg(cd, CC_G, REG_ITMP1, REG_ITMP2);
1072 emit_alu_imm_reg(cd, ALU_AND, -1 - (iptr->sx.val.i), REG_ITMP2);
1073 emit_alu_reg_reg(cd, ALU_SUB, REG_ITMP2, REG_ITMP1);
1074 emit_mov_reg_reg(cd, REG_ITMP1, d);
1075 emit_store_dst(jd, iptr, d);
1079 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1082 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1083 emit_ishift(jd, SHIFT_SHL, iptr);
1087 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1088 /* sx.val.i = constant */
1091 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1092 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1094 M_ISLL_IMM(iptr->sx.val.i, d);
1095 emit_store_dst(jd, iptr, d);
1099 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1102 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1103 emit_ishift(jd, SHIFT_SAR, iptr);
1107 case ICMD_ISHRCONST: /* ..., 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_ITMP2);
1114 M_ISRA_IMM(iptr->sx.val.i, d);
1115 emit_store_dst(jd, iptr, d);
1119 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1122 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1123 emit_ishift(jd, SHIFT_SHR, iptr);
1127 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1128 /* sx.val.i = constant */
1131 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1132 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1134 M_ISRL_IMM(iptr->sx.val.i, d);
1135 emit_store_dst(jd, iptr, d);
1139 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1142 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1143 emit_lshift(jd, SHIFT_SHL, iptr);
1147 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1148 /* sx.val.i = constant */
1151 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1152 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1154 M_LSLL_IMM(iptr->sx.val.i, d);
1155 emit_store_dst(jd, iptr, d);
1159 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1162 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1163 emit_lshift(jd, SHIFT_SAR, iptr);
1167 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1168 /* sx.val.i = constant */
1171 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1172 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1174 M_LSRA_IMM(iptr->sx.val.i, d);
1175 emit_store_dst(jd, iptr, d);
1179 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1182 d = codegen_reg_of_dst(jd, iptr, REG_NULL);
1183 emit_lshift(jd, SHIFT_SHR, iptr);
1187 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1188 /* sx.val.l = constant */
1191 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1192 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1194 M_LSRL_IMM(iptr->sx.val.i, d);
1195 emit_store_dst(jd, iptr, d);
1199 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1201 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1202 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1203 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1210 emit_store_dst(jd, iptr, d);
1214 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1216 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1217 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1218 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1225 emit_store_dst(jd, iptr, d);
1229 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1231 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1232 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1233 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1240 emit_store_dst(jd, iptr, d);
1246 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1247 /* sx.val.i = constant */
1250 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1251 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1253 M_IAND_IMM(iptr->sx.val.i, d);
1254 emit_store_dst(jd, iptr, d);
1258 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1261 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1262 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1263 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1270 emit_store_dst(jd, iptr, d);
1274 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1275 /* sx.val.l = constant */
1277 s3 = iptr->sx.val.l & 0xffffffff;
1278 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
1279 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1280 if ((s3 >= 0) && (s3 <= 65535))
1281 M_AND_IMM(s1, s3, GET_LOW_REG(d));
1283 ICONST(REG_ITMP3, s3);
1284 M_AND(s1, REG_ITMP3, GET_LOW_REG(d));
1286 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
1287 s3 = iptr->sx.val.l >> 32;
1288 if ((s3 >= 0) && (s3 <= 65535))
1289 M_AND_IMM(s1, s3, GET_HIGH_REG(d));
1291 ICONST(REG_ITMP3, s3); /* don't use REG_ITMP2 */
1292 M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
1294 emit_store_dst(jd, iptr, d);
1298 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1299 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1301 if (IS_IMM32(iptr->sx.val.l))
1302 M_LAND_IMM(iptr->sx.val.l, d);
1304 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1305 M_LAND(REG_ITMP2, d);
1307 emit_store_dst(jd, iptr, d);
1311 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1312 /* sx.val.i = constant */
1315 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1316 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1318 M_IOR_IMM(iptr->sx.val.i, d);
1319 emit_store_dst(jd, iptr, d);
1323 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1326 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1327 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1328 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1335 emit_store_dst(jd, iptr, d);
1339 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1340 /* sx.val.l = constant */
1343 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1344 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1346 if (IS_IMM32(iptr->sx.val.l))
1347 M_LOR_IMM(iptr->sx.val.l, d);
1349 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1350 M_LOR(REG_ITMP2, d);
1352 emit_store_dst(jd, iptr, d);
1356 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1357 /* sx.val.i = constant */
1360 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1361 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1363 M_IXOR_IMM(iptr->sx.val.i, d);
1364 emit_store_dst(jd, iptr, d);
1368 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1371 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1372 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1373 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1380 emit_store_dst(jd, iptr, d);
1384 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1385 /* sx.val.l = constant */
1388 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1389 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1391 if (IS_IMM32(iptr->sx.val.l))
1392 M_LXOR_IMM(iptr->sx.val.l, d);
1394 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1395 M_LXOR(REG_ITMP2, d);
1397 emit_store_dst(jd, iptr, d);
1402 /* floating operations ************************************************/
1404 case ICMD_FNEG: /* ..., value ==> ..., - value */
1407 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1408 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1409 disp = dseg_add_s4(cd, 0x80000000);
1411 emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1412 emit_xorps_reg_reg(cd, REG_FTMP2, d);
1413 emit_store_dst(jd, iptr, d);
1417 case ICMD_DNEG: /* ..., value ==> ..., - value */
1420 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1421 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1422 disp = dseg_add_s8(cd, 0x8000000000000000);
1424 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1425 emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1426 emit_store_dst(jd, iptr, d);
1430 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1431 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1432 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1433 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1440 emit_store_dst(jd, iptr, d);
1443 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1444 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1445 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1446 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1453 emit_store_dst(jd, iptr, d);
1456 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1457 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1458 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1459 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1463 emit_store_dst(jd, iptr, d);
1466 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1467 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1468 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1469 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1473 emit_store_dst(jd, iptr, d);
1476 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1477 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1478 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1479 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1486 emit_store_dst(jd, iptr, d);
1489 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1490 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1491 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1492 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1499 emit_store_dst(jd, iptr, d);
1502 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1503 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1504 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1505 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1509 emit_store_dst(jd, iptr, d);
1512 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1513 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1514 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1515 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1519 emit_store_dst(jd, iptr, d);
1522 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1523 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1524 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1526 emit_store_dst(jd, iptr, d);
1529 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1530 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1531 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1533 emit_store_dst(jd, iptr, d);
1536 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1539 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1540 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1542 emit_store_dst(jd, iptr, d);
1546 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1549 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1550 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1552 emit_store_dst(jd, iptr, d);
1556 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1557 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1558 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1560 emit_store_dst(jd, iptr, d);
1561 /* TODO: corner cases ? */
1564 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1567 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1568 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1570 M_ICMP_IMM(0x80000000, d); /* corner cases */
1571 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1572 ((REG_RESULT == d) ? 0 : 3);
1574 M_FLTMOVE(s1, REG_FTMP1);
1575 M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1577 M_INTMOVE(REG_RESULT, d);
1578 emit_store_dst(jd, iptr, d);
1582 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1585 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1586 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1588 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1589 M_LCMP(REG_ITMP2, d); /* corner cases */
1590 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1591 ((REG_RESULT == d) ? 0 : 3);
1593 M_FLTMOVE(s1, REG_FTMP1);
1594 M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1596 M_INTMOVE(REG_RESULT, d);
1597 emit_store_dst(jd, iptr, d);
1601 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1604 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1605 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1607 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1608 M_LCMP(REG_ITMP2, d); /* corner cases */
1609 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1610 ((REG_RESULT == d) ? 0 : 3);
1612 M_FLTMOVE(s1, REG_FTMP1);
1613 M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1615 M_INTMOVE(REG_RESULT, d);
1616 emit_store_dst(jd, iptr, d);
1620 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1621 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1622 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1624 emit_store_dst(jd, iptr, d);
1627 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1630 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1631 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1633 emit_store_dst(jd, iptr, d);
1637 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1638 /* == => 0, < => 1, > => -1 */
1642 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1643 /* == => 0, < => 1, > => -1 */
1646 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1647 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1648 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1650 switch (iptr->opc) {
1662 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1663 SZ_BRC + SZ_BRC + SZ_BRC
1666 N_BRC( /* load -1 */
1667 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1668 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1673 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1676 N_LHI(d, 1); /* GT */
1677 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1678 N_LHI(d, -1); /* LT */
1679 M_BR(SZ_BRC + SZ_LHI);
1680 N_LHI(d, 0); /* EQ */
1682 emit_store_dst(jd, iptr, d);
1687 /* memory operations **************************************************/
1689 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1691 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1692 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1693 gen_nullptr_check(s1);
1694 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1695 emit_store_dst(jd, iptr, d);
1699 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1700 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1701 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1702 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1704 emit_array_checks(cd, iptr, s1, s2);
1706 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1707 /* TODO improove this */
1710 emit_store_dst(jd, iptr, d);
1713 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1715 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1716 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1717 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1719 emit_array_checks(cd, iptr, s1, s2);
1721 M_INTMOVE(s2, REG_ITMP2);
1722 M_ISLL_IMM(1, REG_ITMP2);
1724 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1725 emit_store_dst(jd, iptr, d);
1728 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1729 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1730 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1731 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1733 emit_array_checks(cd, iptr, s1, s2);
1735 M_INTMOVE(s2, REG_ITMP2);
1736 M_ISLL_IMM(1, REG_ITMP2);
1738 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1739 emit_store_dst(jd, iptr, d);
1742 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1743 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1744 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1745 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1746 emit_array_checks(cd, iptr, s1, s2);
1748 M_INTMOVE(s2, REG_ITMP2);
1749 M_ISLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1750 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1751 emit_store_dst(jd, iptr, d);
1754 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1757 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1758 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1759 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1760 if (INSTRUCTION_MUST_CHECK(iptr)) {
1761 gen_nullptr_check(s1);
1764 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1765 emit_store_dst(jd, iptr, d);
1769 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1772 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1773 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1774 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1775 if (INSTRUCTION_MUST_CHECK(iptr)) {
1776 gen_nullptr_check(s1);
1779 emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1780 emit_store_dst(jd, iptr, d);
1784 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1787 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1788 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1789 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1790 if (INSTRUCTION_MUST_CHECK(iptr)) {
1791 gen_nullptr_check(s1);
1794 emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1795 emit_store_dst(jd, iptr, d);
1799 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1800 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1801 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1802 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1803 emit_array_checks(cd, iptr, s1, s2);
1805 M_INTMOVE(s2, REG_ITMP2);
1806 M_ISLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1807 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1808 emit_store_dst(jd, iptr, d);
1811 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1812 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1813 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1814 emit_array_checks(cd, iptr, s1, s2);
1815 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1817 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1820 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1822 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1823 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1824 emit_array_checks(cd, iptr, s1, s2);
1825 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1827 M_INTMOVE(s2, REG_ITMP2);
1828 M_ISLL_IMM(1, REG_ITMP2);
1830 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1834 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1835 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1836 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1837 emit_array_checks(cd, iptr, s1, s2);
1838 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1840 M_INTMOVE(s2, REG_ITMP2);
1841 M_ISLL_IMM(1, REG_ITMP2);
1843 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1846 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1847 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1848 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1849 emit_array_checks(cd, iptr, s1, s2);
1850 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1852 M_INTMOVE(s2, REG_ITMP2);
1853 M_ISLL_IMM(2, REG_ITMP2);
1855 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1858 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1859 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1860 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1861 emit_array_checks(cd, iptr, s1, s2);
1863 M_INTMOVE(s2, REG_ITMP2);
1864 M_ISLL_IMM(3, REG_ITMP2);
1866 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1867 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1868 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1869 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1872 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1873 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1874 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1875 emit_array_checks(cd, iptr, s1, s2);
1876 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1878 M_INTMOVE(s2, REG_ITMP2);
1879 M_ISLL_IMM(2, REG_ITMP2);
1881 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1884 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1885 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1886 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1887 emit_array_checks(cd, iptr, s1, s2);
1888 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1890 M_INTMOVE(s2, REG_ITMP2);
1891 M_ISLL_IMM(3, REG_ITMP2);
1893 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1896 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1898 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1899 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1900 emit_array_checks(cd, iptr, s1, s2);
1901 s3 = emit_load_s3(jd, iptr, REG_A1);
1903 M_INTMOVE(s1, REG_A0);
1904 M_INTMOVE(s3, REG_A1);
1906 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1907 ICONST(REG_ITMP3, disp);
1908 N_L(REG_PV, 0, REG_ITMP3, REG_PV);
1909 M_ISUB_IMM(96, REG_SP);
1910 M_JSR(REG_RA, REG_PV);
1911 M_IADD_IMM(96, REG_SP);
1912 N_BASR(REG_ITMP1, RN);
1913 disp = (s4) (cd->mcodeptr - cd->mcodebase);
1914 M_LDA(REG_PV, REG_ITMP1, -disp);
1918 codegen_add_arraystoreexception_ref(cd);
1920 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1921 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1922 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1924 M_INTMOVE(s2, REG_ITMP2);
1925 M_ISLL_IMM(2, REG_ITMP2);
1926 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1929 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1930 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1935 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1938 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1939 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1940 if (INSTRUCTION_MUST_CHECK(iptr)) {
1941 gen_nullptr_check(s1);
1944 emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1948 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1951 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1952 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1953 if (INSTRUCTION_MUST_CHECK(iptr)) {
1954 gen_nullptr_check(s1);
1957 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
1961 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1964 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1965 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1966 if (INSTRUCTION_MUST_CHECK(iptr)) {
1967 gen_nullptr_check(s1);
1970 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1974 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1977 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1978 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1979 if (INSTRUCTION_MUST_CHECK(iptr)) {
1980 gen_nullptr_check(s1);
1983 emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
1987 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1990 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1991 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1992 if (INSTRUCTION_MUST_CHECK(iptr)) {
1993 gen_nullptr_check(s1);
1997 if (IS_IMM32(iptr->sx.s23.s3.constval)) {
1998 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2000 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2001 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2006 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2009 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2010 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2011 if (INSTRUCTION_MUST_CHECK(iptr)) {
2012 gen_nullptr_check(s1);
2015 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2020 case ICMD_GETSTATIC: /* ... ==> ..., value */
2022 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2023 uf = iptr->sx.s23.s3.uf;
2024 fieldtype = uf->fieldref->parseddesc.fd->type;
2025 disp = dseg_add_unique_address(cd, NULL);
2027 /* PROFILE_CYCLE_STOP; */
2029 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2031 /* PROFILE_CYCLE_START; */
2034 fi = iptr->sx.s23.s3.fmiref->p.field;
2035 fieldtype = fi->type;
2036 disp = dseg_add_address(cd, &(fi->value));
2038 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2041 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
2043 PROFILE_CYCLE_START;
2047 M_ALD(REG_ITMP1, REG_PV, disp);
2049 switch (fieldtype) {
2051 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2052 M_ILD(d, REG_ITMP1, 0);
2055 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2056 M_LLD(d, REG_ITMP1, 0);
2059 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2060 M_ALD(d, REG_ITMP1, 0);
2063 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2064 M_FLD(d, REG_ITMP1, 0);
2067 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2068 M_DLD(d, REG_ITMP1, 0);
2072 emit_store_dst(jd, iptr, d);
2076 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2078 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2079 uf = iptr->sx.s23.s3.uf;
2080 fieldtype = uf->fieldref->parseddesc.fd->type;
2081 disp = dseg_add_unique_address(cd, uf);
2083 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2086 fi = iptr->sx.s23.s3.fmiref->p.field;
2087 fieldtype = fi->type;
2088 disp = dseg_add_address(cd, &(fi->value));
2090 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2091 codegen_addpatchref(cd, PATCHER_clinit,
2095 M_ALD(REG_ITMP1, REG_PV, disp);
2096 switch (fieldtype) {
2098 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2099 M_IST(s1, REG_ITMP1, 0);
2102 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2103 M_LST(s1, REG_ITMP1, 0);
2106 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2107 M_AST(s1, REG_ITMP1, 0);
2110 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2111 M_FST(s1, REG_ITMP1, 0);
2114 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2115 M_DST(s1, REG_ITMP1, 0);
2120 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2121 /* val = value (in current instruction) */
2122 /* following NOP) */
2125 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2126 uf = iptr->sx.s23.s3.uf;
2127 fieldtype = uf->fieldref->parseddesc.fd->type;
2128 disp = dseg_add_unique_address(cd, uf);
2130 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2133 fi = iptr->sx.s23.s3.fmiref->p.field;
2134 fieldtype = fi->type;
2135 disp = dseg_add_address(cd, &(fi->value));
2137 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2138 codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class,
2142 M_ALD(REG_ITMP1, REG_PV, disp);
2144 switch (fieldtype) {
2146 M_IST(REG_ZERO, REG_ITMP1, 0);
2149 M_LST(REG_ZERO, REG_ITMP1, 0);
2152 M_AST(REG_ZERO, REG_ITMP1, 0);
2155 M_FST(REG_ZERO, REG_ITMP1, 0);
2158 M_DST(REG_ZERO, REG_ITMP1, 0);
2164 case ICMD_GETFIELD: /* ... ==> ..., value */
2166 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2167 emit_nullpointer_check(cd, iptr, s1);
2169 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2170 uf = iptr->sx.s23.s3.uf;
2171 fieldtype = uf->fieldref->parseddesc.fd->type;
2174 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2177 fi = iptr->sx.s23.s3.fmiref->p.field;
2178 fieldtype = fi->type;
2182 switch (fieldtype) {
2184 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2188 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2189 if (GET_HIGH_REG(d) == s1) {
2190 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2191 M_ILD(GET_HIGH_REG(d), s1, disp);
2194 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2195 M_ILD(GET_HIGH_REG(d), s1, disp);
2199 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2203 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2207 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2211 emit_store_dst(jd, iptr, d);
2214 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2216 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2217 gen_nullptr_check(s1);
2219 s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2221 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2222 uf = iptr->sx.s23.s3.uf;
2223 fieldtype = uf->fieldref->parseddesc.fd->type;
2227 fi = iptr->sx.s23.s3.fmiref->p.field;
2228 fieldtype = fi->type;
2232 if (IS_INT_LNG_TYPE(fieldtype)) {
2233 if (IS_2_WORD_TYPE(fieldtype))
2234 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2236 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2239 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2241 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2242 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2244 switch (fieldtype) {
2246 M_IST(s2, s1, disp);
2249 /* TODO really order */
2250 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2251 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2254 M_AST(s2, s1, disp);
2257 M_FST(s2, s1, disp);
2260 M_DST(s2, s1, disp);
2265 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2266 /* val = value (in current instruction) */
2267 /* following NOP) */
2270 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2271 gen_nullptr_check(s1);
2273 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2274 uf = iptr->sx.s23.s3.uf;
2275 fieldtype = uf->fieldref->parseddesc.fd->type;
2278 /* PROFILE_CYCLE_STOP; */
2280 codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
2282 /* PROFILE_CYCLE_START; */
2285 fi = iptr->sx.s23.s3.fmiref->p.field;
2286 fieldtype = fi->type;
2290 switch (fieldtype) {
2293 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2298 /* XXX why no check for IS_IMM32? */
2299 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2300 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2307 /* branch operations **************************************************/
2309 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2311 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2312 M_INTMOVE(s1, REG_ITMP1_XPTR);
2316 #ifdef ENABLE_VERIFIER
2317 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2318 uc = iptr->sx.s23.s2.uc;
2320 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2322 #endif /* ENABLE_VERIFIER */
2324 disp = dseg_add_functionptr(cd, asm_handle_exception);
2325 M_ALD(REG_ITMP2, REG_PV, disp);
2326 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2331 case ICMD_GOTO: /* ... ==> ... */
2332 case ICMD_RET: /* ... ==> ... */
2335 codegen_add_branch_ref(cd, iptr->dst.block);
2339 case ICMD_JSR: /* ... ==> ... */
2343 codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2347 case ICMD_IFNULL: /* ..., value ==> ... */
2348 case ICMD_IFNONNULL: /* ..., value ==> ... */
2349 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2351 switch (iptr->opc) {
2355 case ICMD_IFNONNULL:
2359 codegen_add_branch_ref(cd, iptr->dst.block);
2362 case ICMD_IFEQ: /* ..., value ==> ... */
2363 case ICMD_IFLT: /* ..., value ==> ... */
2364 case ICMD_IFLE: /* ..., value ==> ... */
2365 case ICMD_IFNE: /* ..., value ==> ... */
2366 case ICMD_IFGT: /* ..., value ==> ... */
2367 case ICMD_IFGE: /* ..., value ==> ... */
2369 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2371 if (N_VALID_IMM(iptr->sx.val.i))
2372 N_CHI(s1, iptr->sx.val.i);
2374 disp = dseg_add_s4(cd, iptr->sx.val.i);
2375 N_LHI(REG_ITMP2, disp);
2376 N_C(s1, 0, REG_ITMP2, REG_PV);
2379 switch (iptr->opc) {
2399 codegen_add_branch_ref(cd, iptr->dst.block);
2403 case ICMD_IF_LLT: /* ..., value ==> ... */
2404 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2413 /* ATTENTION: compare high words signed and low words unsigned */
2415 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2417 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2418 N_CHI(s1, iptr->sx.val.l >> 32);
2420 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2421 N_LHI(REG_ITMP2, disp);
2422 N_C(s1, 0, REG_ITMP2, REG_PV);
2429 codegen_addreference(cd, iptr->dst.block);
2430 /* EQ ... fall through */
2431 out_ref = cd->mcodeptr;
2437 codegen_addreference(cd, iptr->dst.block);
2438 /* EQ ... fall through */
2439 out_ref = cd->mcodeptr;
2443 /* EQ ... fall through */
2444 out_ref = cd->mcodeptr;
2448 /* EQ ... fall through */
2450 codegen_addreference(cd, iptr->dst.block);
2456 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2458 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2459 N_LHI(REG_ITMP2, disp);
2460 N_CL(s1, 0, REG_ITMP2, REG_PV);
2484 codegen_addreference(cd, iptr->dst.block);
2486 if (out_ref != NULL) {
2487 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2493 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2494 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2496 /* Compare addresses as 31 bit unsigned integers */
2498 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2499 N_LA(REG_ITMP1, 0, RN, s1);
2501 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2502 N_LA(REG_ITMP2, 0, RN, s2);
2504 M_CMP(REG_ITMP1, REG_ITMP2);
2506 switch (iptr->opc) {
2507 case ICMD_IF_ACMPEQ:
2510 case ICMD_IF_ACMPNE:
2515 codegen_add_branch_ref(cd, iptr->dst.block);
2519 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2520 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2521 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2522 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2523 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2524 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2526 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2527 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2529 switch (iptr->opc) {
2530 case ICMD_IF_ICMPEQ:
2533 case ICMD_IF_ICMPNE:
2536 case ICMD_IF_ICMPLT:
2539 case ICMD_IF_ICMPGT:
2542 case ICMD_IF_ICMPLE:
2545 case ICMD_IF_ICMPGE:
2549 codegen_add_branch_ref(cd, iptr->dst.block);
2553 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2554 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2555 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2556 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2557 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2558 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2563 /* ATTENTION: compare high words signed and low words unsigned */
2565 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2566 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2571 case ICMD_IF_LCMPLT:
2572 case ICMD_IF_LCMPLE:
2574 codegen_addreference(cd, iptr->dst.block);
2575 /* EQ ... fall through */
2576 out_ref = cd->mcodeptr;
2579 case ICMD_IF_LCMPGT:
2580 case ICMD_IF_LCMPGE:
2582 codegen_addreference(cd, iptr->dst.block);
2583 /* EQ ... fall through */
2584 out_ref = cd->mcodeptr;
2587 case ICMD_IF_LCMPEQ:
2588 /* EQ ... fall through */
2589 out_ref = cd->mcodeptr;
2592 case ICMD_IF_LCMPNE:
2593 /* EQ ... fall through */
2595 codegen_addreference(cd, iptr->dst.block);
2601 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2602 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2607 case ICMD_IF_LCMPLT:
2610 case ICMD_IF_LCMPLE:
2613 case ICMD_IF_LCMPGT:
2616 case ICMD_IF_LCMPGE:
2619 case ICMD_IF_LCMPEQ:
2622 case ICMD_IF_LCMPNE:
2629 codegen_addreference(cd, iptr->dst.block);
2631 if (out_ref != NULL) {
2632 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2638 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2640 REPLACEMENT_POINT_RETURN(cd, iptr);
2641 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2642 M_INTMOVE(s1, REG_RESULT);
2643 goto nowperformreturn;
2645 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2647 REPLACEMENT_POINT_RETURN(cd, iptr);
2648 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2649 M_INTMOVE(s1, REG_RESULT);
2651 #ifdef ENABLE_VERIFIER
2652 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2653 unresolved_class *uc = iptr->sx.s23.s2.uc;
2655 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2657 #endif /* ENABLE_VERIFIER */
2658 goto nowperformreturn;
2660 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2662 REPLACEMENT_POINT_RETURN(cd, iptr);
2663 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2664 M_LNGMOVE(s1, REG_RESULT_PACKED);
2665 goto nowperformreturn;
2667 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2670 REPLACEMENT_POINT_RETURN(cd, iptr);
2671 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2672 M_FLTMOVE(s1, REG_FRESULT);
2673 goto nowperformreturn;
2675 case ICMD_RETURN: /* ... ==> ... */
2677 REPLACEMENT_POINT_RETURN(cd, iptr);
2683 p = cd->stackframesize;
2685 /* call trace function */
2687 #if !defined(NDEBUG)
2688 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2689 emit_verbosecall_exit(jd);
2690 #endif /* !defined(NDEBUG) */
2692 #if defined(ENABLE_THREADS)
2693 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2694 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2695 M_ALD(REG_ITMP3, REG_PV, disp);
2698 /* we need to save the proper return value */
2700 switch (iptr->opc) {
2702 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2706 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2709 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2712 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2716 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2719 /* and now restore the proper return value */
2721 switch (iptr->opc) {
2723 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2727 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2730 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2733 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2739 /* restore return address */
2741 p--; M_ALD(REG_RA, REG_SP, p * 4);
2743 /* restore saved registers */
2745 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2746 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2748 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2749 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2752 /* deallocate stack */
2754 if (cd->stackframesize)
2755 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2762 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2767 branch_target_t *table;
2769 table = iptr->dst.table;
2771 l = iptr->sx.s23.s2.tablelow;
2772 i = iptr->sx.s23.s3.tablehigh;
2774 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2775 M_INTMOVE(s1, REG_ITMP1);
2778 M_ISUB_IMM(l, REG_ITMP1);
2780 /* number of targets */
2784 M_ICMP_IMM(i - 1, REG_ITMP1);
2787 codegen_add_branch_ref(cd, table[0].block); /* default target */
2789 /* build jump table top down and use address of lowest entry */
2794 dseg_add_target(cd, table->block);
2798 /* length of dataseg after last dseg_add_target is used
2801 M_MOV_IMM(0, REG_ITMP2);
2803 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2810 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2815 lookup_target_t *lookup;
2817 lookup = iptr->dst.lookup;
2819 i = iptr->sx.s23.s2.lookupcount;
2821 MCODECHECK(8 + ((7 + 6) * i) + 5);
2822 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2825 M_ICMP_IMM(lookup->value, s1);
2827 codegen_add_branch_ref(cd, lookup->target.block);
2833 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2839 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2841 bte = iptr->sx.s23.s3.bte;
2845 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2846 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2847 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2848 case ICMD_INVOKEINTERFACE:
2850 REPLACEMENT_POINT_INVOKE(cd, iptr);
2852 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2854 um = iptr->sx.s23.s3.um;
2855 md = um->methodref->parseddesc.md;
2858 lm = iptr->sx.s23.s3.fmiref->p.method;
2860 md = lm->parseddesc;
2864 s3 = md->paramcount;
2866 MCODECHECK((s3 << 1) + 64);
2868 /* copy arguments to registers or stack location */
2870 for (s3 = s3 - 1; s3 >= 0; s3--) {
2871 var = VAR(iptr->sx.s23.s2.args[s3]);
2873 /* Already Preallocated? */
2874 if (var->flags & PREALLOC)
2877 if (IS_INT_LNG_TYPE(var->type)) {
2878 if (!md->params[s3].inmemory) {
2879 if (IS_2_WORD_TYPE(var->type)) {
2881 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2882 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2884 d = emit_load(jd, iptr, var, s1);
2888 s1 = rd->argintregs[md->params[s3].regoff];
2889 d = emit_load(jd, iptr, var, s1);
2894 if (IS_2_WORD_TYPE(var->type)) {
2895 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2896 M_LST(d, REG_SP, md->params[s3].regoff * 4);
2899 d = emit_load(jd, iptr, var, REG_ITMP1);
2900 M_IST(d, REG_SP, md->params[s3].regoff * 4);
2905 if (!md->params[s3].inmemory) {
2906 s1 = rd->argfltregs[md->params[s3].regoff];
2907 d = emit_load(jd, iptr, var, s1);
2911 d = emit_load(jd, iptr, var, REG_FTMP1);
2912 if (IS_2_WORD_TYPE(var->type))
2913 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2915 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2920 switch (iptr->opc) {
2922 disp = dseg_add_functionptr(cd, bte->fp);
2924 N_AHI(REG_SP, -96); /* register save area as required by C abi */
2925 N_LHI(REG_ITMP1, disp);
2926 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2929 case ICMD_INVOKESPECIAL:
2930 emit_nullpointer_check(cd, iptr, REG_A0);
2931 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
2934 case ICMD_INVOKESTATIC:
2936 disp = dseg_add_unique_address(cd, um);
2938 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2942 disp = dseg_add_address(cd, lm->stubroutine);
2944 N_LHI(REG_ITMP1, disp);
2945 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2948 case ICMD_INVOKEVIRTUAL:
2949 emit_nullpointer_check(cd, iptr, REG_A0);
2952 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2957 s1 = OFFSET(vftbl_t, table[0]) +
2958 sizeof(methodptr) * lm->vftblindex;
2961 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2962 M_ALD(REG_PV, REG_METHODPTR, s1);
2965 case ICMD_INVOKEINTERFACE:
2966 emit_nullpointer_check(cd, iptr, REG_A0);
2968 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2969 * and -0xFFF in index register (itmp1)
2972 N_LHI(REG_ITMP1, -N_DISP_MAX);
2975 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2981 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2982 sizeof(methodptr*) * lm->class->index +
2985 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2988 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2989 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
2990 M_ALD(REG_PV, REG_METHODPTR, s2);
2994 /* generate the actual call */
2997 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2998 N_BASR(REG_ITMP1, RN);
2999 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3000 M_LDA(REG_PV, REG_ITMP1, -disp);
3002 /* post call finalization */
3004 if (iptr->opc == ICMD_BUILTIN) {
3005 N_AHI(REG_SP, 96); /* remove C abi register save area */
3008 /* actually only used for ICMD_BUILTIN */
3010 if (INSTRUCTION_MUST_CHECK(iptr)) {
3013 codegen_add_fillinstacktrace_ref(cd);
3016 /* store return value */
3018 d = md->returntype.type;
3020 if (d != TYPE_VOID) {
3021 if (IS_INT_LNG_TYPE(d)) {
3022 if (IS_2_WORD_TYPE(d)) {
3023 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
3024 M_LNGMOVE(REG_RESULT_PACKED, s1);
3027 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3028 M_INTMOVE(REG_RESULT, s1);
3032 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
3033 M_FLTMOVE(REG_FRESULT, s1);
3035 emit_store_dst(jd, iptr, s1);
3041 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3043 /* val.a: (classinfo*) superclass */
3045 /* superclass is an interface:
3047 * OK if ((sub == NULL) ||
3048 * (sub->vftbl->interfacetablelength > super->index) &&
3049 * (sub->vftbl->interfacetable[-super->index] != NULL));
3051 * superclass is a class:
3053 * OK if ((sub == NULL) || (0
3054 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3055 * super->vftbl->diffval));
3058 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
3059 /* object type cast-check */
3062 vftbl_t *supervftbl;
3065 u1 *class_label_refs[] = { 0 }, *class_label;
3066 u1 *exit_label_refs[] = { 0, 0, 0, 0 };
3068 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3074 super = iptr->sx.s23.s3.c.cls;
3075 superindex = super->index;
3076 supervftbl = super->vftbl;
3079 #if defined(ENABLE_THREADS)
3080 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3082 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3084 /* if class is not resolved, check which code to call */
3086 if (super == NULL) {
3088 exit_label_refs[0] = cd->mcodeptr;
3091 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3093 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3094 iptr->sx.s23.s3.c.ref,
3097 ICONST(REG_ITMP2, ACC_INTERFACE);
3098 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3099 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3100 class_label_refs[0] = cd->mcodeptr;
3104 /* interface checkcast code */
3106 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3107 if (super == NULL) {
3108 codegen_add_patch_ref(cd,
3109 PATCHER_checkcast_instanceof_interface,
3110 iptr->sx.s23.s3.c.ref,
3114 exit_label_refs[1] = cd->mcodeptr;
3118 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3119 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
3120 M_ISUB_IMM(superindex, REG_ITMP3);
3122 codegen_add_classcastexception_ref(cd, s1);
3125 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3126 superindex * sizeof(methodptr*))
3128 M_ALD(REG_ITMP2, REG_ITMP2, 0);
3131 codegen_add_classcastexception_ref(cd, s1);
3133 if (super == NULL) {
3134 exit_label_refs[2] = cd->mcodeptr;
3139 /* class checkcast code */
3141 class_label = cd->mcodeptr;
3143 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3144 if (super == NULL) {
3145 disp = dseg_add_unique_address(cd, NULL);
3147 codegen_add_patch_ref(cd,
3148 PATCHER_resolve_classref_to_vftbl,
3149 iptr->sx.s23.s3.c.ref,
3153 disp = dseg_add_address(cd, supervftbl);
3155 exit_label_refs[3] = cd->mcodeptr;
3159 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3160 M_ALD(REG_ITMP3, REG_PV, disp);
3161 #if defined(ENABLE_THREADS)
3162 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3164 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3165 /* if (s1 != REG_ITMP1) { */
3166 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3167 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3168 /* #if defined(ENABLE_THREADS) */
3169 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3171 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3174 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3175 M_ISUB(REG_ITMP3, REG_ITMP2);
3176 M_ALD(REG_ITMP3, REG_PV, disp);
3177 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3178 #if defined(ENABLE_THREADS)
3179 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3182 N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3183 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3184 M_BGT(0); /* Branch if greater then */
3185 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3186 codegen_add_classcastexception_ref(cd, s1);
3189 /* resolve labels by adding the correct displacement */
3191 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3192 if (exit_label_refs[s2])
3193 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3196 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3197 if (class_label_refs[s2])
3198 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3201 d = codegen_reg_of_dst(jd, iptr, s1);
3204 /* array type cast-check */
3206 s1 = emit_load_s1(jd, iptr, REG_A0);
3207 M_INTMOVE(s1, REG_A0);
3209 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3210 disp = dseg_add_unique_address(cd, NULL);
3212 codegen_add_patch_ref(cd,
3213 PATCHER_resolve_classref_to_classinfo,
3214 iptr->sx.s23.s3.c.ref,
3218 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3220 M_ALD(REG_A1, REG_PV, disp);
3221 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3222 ICONST(REG_ITMP1, disp); /* TODO negative displacement */
3223 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3224 M_JSR(REG_RA, REG_PV);
3225 N_BASR(REG_ITMP1, RN);
3226 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3227 M_LDA(REG_PV, REG_ITMP1, -disp);
3229 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3232 codegen_add_classcastexception_ref(cd, s1);
3234 d = codegen_reg_of_dst(jd, iptr, s1);
3238 emit_store_dst(jd, iptr, d);
3241 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3242 /* val.a: (classinfo*) superclass */
3244 /* superclass is an interface:
3246 * return (sub != NULL) &&
3247 * (sub->vftbl->interfacetablelength > super->index) &&
3248 * (sub->vftbl->interfacetable[-super->index] != NULL);
3250 * superclass is a class:
3252 * return ((sub != NULL) && (0
3253 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3254 * super->vftbl->diffvall));
3259 vftbl_t *supervftbl;
3262 u1 *class_label, *class_label_refs[1] = { 0 };
3263 u1 *exit_label_refs[4] = { 0, 0, 0, 0 };
3264 u1 *label1, *label1_refs[1] = { 0 };
3266 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3272 super = iptr->sx.s23.s3.c.cls;
3273 superindex = super->index;
3274 supervftbl = super->vftbl;
3277 #if defined(ENABLE_THREADS)
3278 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3280 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3281 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3283 M_MOV(s1, REG_ITMP1);
3287 /* if class is not resolved, check which code to call */
3289 if (super == NULL) {
3293 exit_label_refs[0] = cd->mcodeptr;
3296 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3298 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3299 iptr->sx.s23.s3.c.ref, disp);
3301 ICONST(REG_ITMP2, ACC_INTERFACE);
3302 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3303 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3304 class_label_refs[0] = cd->mcodeptr;
3308 /* interface instanceof code */
3310 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3311 if (super == NULL) {
3312 /* If d == REG_ITMP2, then it's destroyed in check
3317 codegen_add_patch_ref(cd,
3318 PATCHER_checkcast_instanceof_interface,
3319 iptr->sx.s23.s3.c.ref, 0);
3324 exit_label_refs[1] = cd->mcodeptr;
3328 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3329 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3330 M_ISUB_IMM(superindex, REG_ITMP3);
3331 label1_refs[0] = cd->mcodeptr;
3335 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3336 superindex * sizeof(methodptr*))
3338 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3340 /* d := (REG_ITMP1 != 0) */
3342 N_LTR(d, REG_ITMP1);
3343 M_BEQ(SZ_BRC + SZ_LHI);
3346 label1 = cd->mcodeptr;
3348 if (super == NULL) {
3349 exit_label_refs[2] = cd->mcodeptr;
3354 /* class instanceof code */
3356 class_label = cd->mcodeptr;
3358 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3359 if (super == NULL) {
3360 disp = dseg_add_unique_address(cd, NULL);
3362 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3363 iptr->sx.s23.s3.c.ref,
3367 disp = dseg_add_address(cd, supervftbl);
3372 exit_label_refs[3] = cd->mcodeptr;
3376 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3377 M_ALD(REG_ITMP2, REG_PV, disp);
3378 #if defined(ENABLE_THREADS)
3379 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3381 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3382 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3383 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3384 #if defined(ENABLE_THREADS)
3385 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3387 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3389 N_CLR(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3391 M_BGT(SZ_BRC + SZ_LHI);
3395 /* resolve labels by adding the correct displacement */
3397 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3398 if (exit_label_refs[s2])
3399 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3402 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3403 if (class_label_refs[s2])
3404 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3407 for (s2 = 0; s2 < sizeof(label1_refs) / sizeof(label1_refs[0]); ++s2) {
3408 if (label1_refs[s2])
3409 *(u4 *)label1_refs[s2] |= (u4)(label1 - label1_refs[s2]) / 2;
3412 emit_store_dst(jd, iptr, d);
3418 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3422 /* check for negative sizes and copy sizes to stack if necessary */
3424 MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3426 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3428 /* copy SAVEDVAR sizes to stack */
3429 var = VAR(iptr->sx.s23.s2.args[s1]);
3431 /* Already Preallocated? */
3432 if (!(var->flags & PREALLOC)) {
3433 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3434 M_LST(s2, REG_SP, s1 * 8);
3438 /* is a patcher function set? */
3440 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3441 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
3442 iptr->sx.s23.s3.c.ref, 0);
3445 /* a0 = dimension count */
3447 M_MOV_IMM(iptr->s1.argcount, REG_A0);
3449 /* a1 = classinfo */
3451 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3453 /* a2 = pointer to dimensions = stack pointer */
3455 M_MOV(REG_SP, REG_A2);
3457 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3460 /* check for exception before result assignment */
3464 codegen_add_fillinstacktrace_ref(cd);
3466 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3467 M_INTMOVE(REG_RESULT, s1);
3468 emit_store_dst(jd, iptr, s1);
3473 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3477 } /* for instruction */
3479 MCODECHECK(512); /* XXX require a lower number? */
3481 /* At the end of a basic block we may have to append some nops,
3482 because the patcher stub calling code might be longer than the
3483 actual instruction. So codepatching does not change the
3484 following block unintentionally. */
3486 if (cd->mcodeptr < cd->lastmcodeptr) {
3487 while (cd->mcodeptr < cd->lastmcodeptr) {
3492 } /* if (bptr -> flags >= BBREACHED) */
3493 } /* for basic block */
3495 dseg_createlinenumbertable(cd);
3497 /* generate stubs */
3499 emit_exception_stubs(jd);
3500 emit_patcher_stubs(jd);
3502 emit_replacement_stubs(jd);
3507 /* everything's ok */
3513 /* createcompilerstub **********************************************************
3515 Creates a stub routine which calls the compiler.
3517 *******************************************************************************/
3519 #define COMPILERSTUB_DATASIZE (3 * SIZEOF_VOID_P)
3520 #define COMPILERSTUB_CODESIZE (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
3522 #define COMPILERSTUB_SIZE (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE)
3525 u1 *createcompilerstub(methodinfo *m)
3527 u1 *s; /* memory to hold the stub */
3533 s = CNEW(u1, COMPILERSTUB_SIZE);
3535 /* set data pointer and code pointer */
3538 s = s + COMPILERSTUB_DATASIZE;
3540 /* mark start of dump memory area */
3542 dumpsize = dump_size();
3544 cd = DNEW(codegendata);
3547 /* Store the codeinfo pointer in the same place as in the
3548 methodheader for compiled methods. */
3550 code = code_codeinfo_new(m);
3552 d[0] = (ptrint) asm_call_jit_compiler;
3554 d[2] = (ptrint) code;
3556 /* code for the stub */
3558 /* don't touch ITMP3 as it cointains the return address */
3560 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3562 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3563 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3564 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3567 #if defined(ENABLE_STATISTICS)
3569 count_cstub_len += COMPILERSTUB_SIZE;
3572 /* release dump area */
3574 dump_release(dumpsize);
3580 /* createnativestub ************************************************************
3582 Creates a stub routine which calls a native method.
3584 *******************************************************************************/
3587 arguments on stack \
3588 -------------------------------------------------| <- SP on nativestub entry
3590 callee saved int regs (none) |
3591 callee saved float regs (none) | stack frame like in cacao
3592 local variable slots (none) |
3593 arguments for calling methods (none) /
3594 ------------------------------------------------------------------ <- datasp
3599 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3600 0 - 96 register save area for callee /
3601 -------------------------------------------------------- <- SP native method
3603 SP after method entry
3606 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3614 s4 i, j; /* count variables */
3619 /* get required compiler data */
3626 /* initialize variables */
3629 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3631 /* calculate stack frame size */
3633 cd->stackframesize =
3634 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3635 sizeof(localref_table) / SIZEOF_VOID_P +
3636 INT_ARG_CNT + FLT_ARG_CNT +
3637 1 + /* functionptr, TODO: store in data segment */
3640 cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */
3643 cd->stackframesize =
3644 1 + /* r14 - return address */ +
3645 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3646 sizeof(localref_table) / SIZEOF_VOID_P +
3648 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3649 nmd->memuse + /* parameter passing */
3650 96 / SIZEOF_VOID_P /* required by ABI */;
3652 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3655 /* create method header */
3657 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3658 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3659 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3660 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3661 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3662 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3663 (void) dseg_addlinenumbertablesize(cd);
3664 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3666 /* generate native method profiling code */
3668 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3669 /* count frequency */
3671 M_MOV_IMM(code, REG_ITMP3);
3672 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3676 /* generate stub code */
3678 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3680 /* save return address */
3682 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3685 #if !defined(NDEBUG)
3686 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3687 emit_verbosecall_enter(jd);
3691 /* get function address (this must happen before the stackframeinfo) */
3693 disp = dseg_add_functionptr(cd, f);
3695 #if !defined(WITH_STATIC_CLASSPATH)
3697 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3700 M_ILD(REG_ITMP1, REG_PV, disp);
3702 j = 96 + (nmd->memuse * 4);
3704 /* todo some arg registers are not volatile in C-abi terms */
3706 /* save integer and float argument registers */
3708 for (i = 0; i < md->paramcount; i++) {
3709 if (! md->params[i].inmemory) {
3710 s1 = md->params[i].regoff;
3712 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3713 if (IS_2_WORD_TYPE(t)) {
3714 /* todo store multiple */
3715 N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3716 N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3718 N_ST(rd->argintregs[s1], j, RN, REG_SP);
3721 if (IS_2_WORD_TYPE(t)) {
3722 N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3724 N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3732 N_ST(REG_ITMP1, j, RN, REG_SP);
3734 /* create dynamic stack info */
3736 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3737 N_LR(REG_A1, REG_PV); /* pv */
3738 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3739 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3741 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3742 M_ILD(REG_ITMP1, REG_PV, disp);
3744 M_CALL(REG_ITMP1); /* call */
3746 /* restore integer and float argument registers */
3748 j = 96 + (nmd->memuse * 4);
3750 for (i = 0; i < md->paramcount; i++) {
3751 if (! md->params[i].inmemory) {
3752 s1 = md->params[i].regoff;
3754 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3755 if (IS_2_WORD_TYPE(t)) {
3756 /* todo load multiple ! */
3757 N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3758 N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3760 N_L(rd->argintregs[s1], j, RN, REG_SP);
3763 if (IS_2_WORD_TYPE(t)) {
3764 N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3766 N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3774 N_L(REG_ITMP1, j, RN, REG_SP);
3776 /* copy or spill arguments to new locations */
3778 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3779 t = md->paramtypes[i].type;
3781 if (IS_INT_LNG_TYPE(t)) {
3783 if (!md->params[i].inmemory) {
3785 s1 = rd->argintregs[md->params[i].regoff];
3787 if (!nmd->params[j].inmemory) {
3788 s2 = rd->argintregs[nmd->params[j].regoff];
3789 if (IS_2_WORD_TYPE(t)) {
3790 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3791 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3796 s2 = nmd->params[j].regoff;
3797 if (IS_2_WORD_TYPE(t)) {
3798 N_STM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3800 N_ST(s1, 96 + (s2 * 4), RN, REG_SP);
3805 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3806 s2 = nmd->params[j].regoff;
3808 if (IS_2_WORD_TYPE(t)) {
3809 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3811 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3816 /* We only copy spilled float arguments, as the float argument */
3817 /* registers keep unchanged. */
3819 if (md->params[i].inmemory) {
3820 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3821 s2 = nmd->params[j].regoff;
3823 if (IS_2_WORD_TYPE(t)) {
3824 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3826 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3832 /* put class into second argument register */
3834 if (m->flags & ACC_STATIC) {
3835 disp = dseg_add_address(cd, m->class);
3836 M_ILD(REG_A1, REG_PV, disp);
3839 /* put env into first argument register */
3841 disp = dseg_add_address(cd, _Jv_env);
3842 M_ILD(REG_A0, REG_PV, disp);
3844 /* do the native function call */
3846 M_CALL(REG_ITMP1); /* call */
3848 /* save return value */
3850 t = md->returntype.type;
3852 if (t != TYPE_VOID) {
3853 if (IS_INT_LNG_TYPE(t)) {
3854 if (IS_2_WORD_TYPE(t)) {
3855 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3857 N_ST(REG_RESULT, 96, RN, REG_SP);
3860 if (IS_2_WORD_TYPE(t)) {
3861 N_STD(REG_FRESULT, 96, RN, REG_SP);
3863 N_STE(REG_FRESULT, 96, RN, REG_SP);
3869 #if !defined(NDEBUG)
3870 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3871 emit_verbosecall_exit(jd);
3875 /* remove native stackframe info */
3877 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3878 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3879 M_ILD(REG_ITMP1, REG_PV, disp);
3881 N_LR(REG_ITMP3, REG_RESULT);
3883 /* restore return value */
3885 if (t != TYPE_VOID) {
3886 if (IS_INT_LNG_TYPE(t)) {
3887 if (IS_2_WORD_TYPE(t)) {
3888 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3890 N_L(REG_RESULT, 96, RN, REG_SP);
3893 if (IS_2_WORD_TYPE(t)) {
3894 N_LD(REG_FRESULT, 96, RN, REG_SP);
3896 N_LE(REG_FRESULT, 96, RN, REG_SP);
3901 /* load return address */
3903 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3905 /* remove stackframe */
3907 N_AHI(REG_SP, cd->stackframesize * 4);
3909 /* test for exception */
3911 N_LTR(REG_ITMP3, REG_ITMP3);
3912 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3916 N_BCR(DD_ANY, REG_ITMP2);
3918 /* handle exception */
3920 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3921 M_ALD(REG_ITMP2_XPC, REG_SP, (cd->stackframesize - 1) * 4); /* get return address from stack */
3924 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3926 disp = dseg_add_functionptr(cd, /*asm_handle_nat_exception*/ panic);
3928 M_ALD(REG_ITMP3, REG_PV, disp);
3929 M_JMP(RN, REG_ITMP3);
3931 /* generate patcher stubs */
3933 emit_patcher_stubs(jd);
3937 return code->entrypoint;
3941 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3942 codegendata *cd = jd->cd;
3943 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3945 M_MOV(reg, tempregnum);
3953 * These are local overrides for various environment variables in Emacs.
3954 * Please do not remove this and leave it at the end of the file, where
3955 * Emacs will automagically detect them.
3956 * ---------------------------------------------------------------------
3959 * indent-tabs-mode: t
3963 * vim:noexpandtab:sw=4:ts=4: