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 7534 2007-03-16 23:00:18Z 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 */
1202 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1203 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1204 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1211 emit_store_dst(jd, iptr, d);
1215 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1216 /* sx.val.i = constant */
1219 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1220 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1222 M_IAND_IMM(iptr->sx.val.i, d);
1223 emit_store_dst(jd, iptr, d);
1227 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1230 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1231 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1232 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1239 emit_store_dst(jd, iptr, d);
1243 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1244 /* sx.val.l = constant */
1247 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1248 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1250 if (IS_IMM32(iptr->sx.val.l))
1251 M_LAND_IMM(iptr->sx.val.l, d);
1253 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1254 M_LAND(REG_ITMP2, d);
1256 emit_store_dst(jd, iptr, d);
1260 case ICMD_IOR: /* ..., 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_IORCONST: /* ..., 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_IOR_IMM(iptr->sx.val.i, d);
1284 emit_store_dst(jd, iptr, d);
1288 case ICMD_LOR: /* ..., 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_LORCONST: /* ..., 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_LOR_IMM(iptr->sx.val.l, d);
1314 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1315 M_LOR(REG_ITMP2, d);
1317 emit_store_dst(jd, iptr, d);
1321 case ICMD_IXOR: /* ..., 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_IXORCONST: /* ..., 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_IXOR_IMM(iptr->sx.val.i, d);
1345 emit_store_dst(jd, iptr, d);
1349 case ICMD_LXOR: /* ..., 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_LXORCONST: /* ..., 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_LXOR_IMM(iptr->sx.val.l, d);
1375 M_MOV_IMM(iptr->sx.val.l, REG_ITMP2);
1376 M_LXOR(REG_ITMP2, d);
1378 emit_store_dst(jd, iptr, d);
1383 /* floating operations ************************************************/
1385 case ICMD_FNEG: /* ..., value ==> ..., - value */
1388 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1389 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1390 disp = dseg_add_s4(cd, 0x80000000);
1392 emit_movss_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1393 emit_xorps_reg_reg(cd, REG_FTMP2, d);
1394 emit_store_dst(jd, iptr, d);
1398 case ICMD_DNEG: /* ..., value ==> ..., - value */
1401 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1402 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1403 disp = dseg_add_s8(cd, 0x8000000000000000);
1405 emit_movd_membase_reg(cd, RIP, -((cd->mcodeptr + 9) - cd->mcodebase) + disp, REG_FTMP2);
1406 emit_xorpd_reg_reg(cd, REG_FTMP2, d);
1407 emit_store_dst(jd, iptr, d);
1411 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1414 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1415 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1416 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1423 emit_store_dst(jd, iptr, d);
1427 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1430 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1431 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1432 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1439 emit_store_dst(jd, iptr, d);
1443 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1446 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1447 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1448 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1450 M_FLTMOVE(s2, REG_FTMP2);
1455 emit_store_dst(jd, iptr, d);
1459 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1462 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1463 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1464 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1466 M_FLTMOVE(s2, REG_FTMP2);
1471 emit_store_dst(jd, iptr, d);
1475 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1476 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1477 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1478 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1485 emit_store_dst(jd, iptr, d);
1489 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1492 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1493 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1494 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1501 emit_store_dst(jd, iptr, d);
1505 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1508 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1509 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1510 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1512 M_FLTMOVE(s2, REG_FTMP2);
1517 emit_store_dst(jd, iptr, d);
1521 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1524 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1525 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1526 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1528 M_FLTMOVE(s2, REG_FTMP2);
1533 emit_store_dst(jd, iptr, d);
1537 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1538 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1539 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1541 emit_store_dst(jd, iptr, d);
1544 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1545 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1546 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1548 emit_store_dst(jd, iptr, d);
1551 case ICMD_L2F: /* ..., value ==> ..., (float) value */
1554 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1555 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1557 emit_store_dst(jd, iptr, d);
1561 case ICMD_L2D: /* ..., value ==> ..., (double) value */
1564 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1565 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1567 emit_store_dst(jd, iptr, d);
1571 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1572 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1573 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1575 emit_store_dst(jd, iptr, d);
1576 /* TODO: corner cases ? */
1579 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1582 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1583 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1585 M_ICMP_IMM(0x80000000, d); /* corner cases */
1586 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1587 ((REG_RESULT == d) ? 0 : 3);
1589 M_FLTMOVE(s1, REG_FTMP1);
1590 M_MOV_IMM(asm_builtin_d2i, REG_ITMP2);
1592 M_INTMOVE(REG_RESULT, d);
1593 emit_store_dst(jd, iptr, d);
1597 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1600 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1601 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1603 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1604 M_LCMP(REG_ITMP2, d); /* corner cases */
1605 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1606 ((REG_RESULT == d) ? 0 : 3);
1608 M_FLTMOVE(s1, REG_FTMP1);
1609 M_MOV_IMM(asm_builtin_f2l, REG_ITMP2);
1611 M_INTMOVE(REG_RESULT, d);
1612 emit_store_dst(jd, iptr, d);
1616 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1619 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1620 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1622 M_MOV_IMM(0x8000000000000000, REG_ITMP2);
1623 M_LCMP(REG_ITMP2, d); /* corner cases */
1624 disp = ((s1 == REG_FTMP1) ? 0 : 5) + 10 + 3 +
1625 ((REG_RESULT == d) ? 0 : 3);
1627 M_FLTMOVE(s1, REG_FTMP1);
1628 M_MOV_IMM(asm_builtin_d2l, REG_ITMP2);
1630 M_INTMOVE(REG_RESULT, d);
1631 emit_store_dst(jd, iptr, d);
1635 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1636 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1637 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1639 emit_store_dst(jd, iptr, d);
1642 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1645 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1646 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1648 emit_store_dst(jd, iptr, d);
1652 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1653 /* == => 0, < => 1, > => -1 */
1657 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1658 /* == => 0, < => 1, > => -1 */
1661 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1662 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1663 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1665 switch (iptr->opc) {
1677 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1678 SZ_BRC + SZ_BRC + SZ_BRC
1681 N_BRC( /* load -1 */
1682 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1683 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1688 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1691 N_LHI(d, 1); /* GT */
1692 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1693 N_LHI(d, -1); /* LT */
1694 M_BR(SZ_BRC + SZ_LHI);
1695 N_LHI(d, 0); /* EQ */
1697 emit_store_dst(jd, iptr, d);
1702 /* memory operations **************************************************/
1704 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1706 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1707 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1708 gen_nullptr_check(s1);
1709 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1710 emit_store_dst(jd, iptr, d);
1714 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1717 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1718 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1719 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1720 if (INSTRUCTION_MUST_CHECK(iptr)) {
1721 gen_nullptr_check(s1);
1724 emit_movsbq_memindex_reg(cd, OFFSET(java_bytearray, data[0]), s1, s2, 0, d);
1725 emit_store_dst(jd, iptr, d);
1729 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1731 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1732 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1733 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1735 emit_array_checks(cd, iptr, s1, s2);
1737 M_INTMOVE(s2, REG_ITMP2);
1738 M_ISLL_IMM(1, REG_ITMP2);
1740 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1741 emit_store_dst(jd, iptr, d);
1744 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1747 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1748 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1749 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1750 if (INSTRUCTION_MUST_CHECK(iptr)) {
1751 gen_nullptr_check(s1);
1754 emit_movswq_memindex_reg(cd, OFFSET(java_shortarray, data[0]), s1, s2, 1, d);
1755 emit_store_dst(jd, iptr, d);
1759 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1762 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1763 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1764 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1765 if (INSTRUCTION_MUST_CHECK(iptr)) {
1766 gen_nullptr_check(s1);
1769 emit_movl_memindex_reg(cd, OFFSET(java_intarray, data[0]), s1, s2, 2, d);
1770 emit_store_dst(jd, iptr, d);
1774 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1777 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1778 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1779 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1780 if (INSTRUCTION_MUST_CHECK(iptr)) {
1781 gen_nullptr_check(s1);
1784 emit_mov_memindex_reg(cd, OFFSET(java_longarray, data[0]), s1, s2, 3, d);
1785 emit_store_dst(jd, iptr, d);
1789 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1792 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1793 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1794 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1795 if (INSTRUCTION_MUST_CHECK(iptr)) {
1796 gen_nullptr_check(s1);
1799 emit_movss_memindex_reg(cd, OFFSET(java_floatarray, data[0]), s1, s2, 2, d);
1800 emit_store_dst(jd, iptr, d);
1804 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1807 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1808 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1809 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1810 if (INSTRUCTION_MUST_CHECK(iptr)) {
1811 gen_nullptr_check(s1);
1814 emit_movsd_memindex_reg(cd, OFFSET(java_doublearray, data[0]), s1, s2, 3, d);
1815 emit_store_dst(jd, iptr, d);
1819 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1820 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1821 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1822 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1823 emit_array_checks(cd, iptr, s1, s2);
1825 M_INTMOVE(s2, REG_ITMP2);
1826 M_ISLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1827 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1828 emit_store_dst(jd, iptr, d);
1831 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1834 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1835 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1836 if (INSTRUCTION_MUST_CHECK(iptr)) {
1837 gen_nullptr_check(s1);
1840 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1841 emit_movb_reg_memindex(cd, s3, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1845 case ICMD_CASTORE: /* ..., 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(1, REG_ITMP2);
1855 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1859 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1862 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1863 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1864 if (INSTRUCTION_MUST_CHECK(iptr)) {
1865 gen_nullptr_check(s1);
1868 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1869 emit_movw_reg_memindex(cd, s3, OFFSET(java_shortarray, data[0]), s1, s2, 1);
1873 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1876 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1877 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1878 if (INSTRUCTION_MUST_CHECK(iptr)) {
1879 gen_nullptr_check(s1);
1882 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1883 emit_movl_reg_memindex(cd, s3, OFFSET(java_intarray, data[0]), s1, s2, 2);
1887 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1890 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1891 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1892 if (INSTRUCTION_MUST_CHECK(iptr)) {
1893 gen_nullptr_check(s1);
1896 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1897 emit_mov_reg_memindex(cd, s3, OFFSET(java_longarray, data[0]), s1, s2, 3);
1901 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1904 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1905 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1906 if (INSTRUCTION_MUST_CHECK(iptr)) {
1907 gen_nullptr_check(s1);
1910 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1911 emit_movss_reg_memindex(cd, s3, OFFSET(java_floatarray, data[0]), s1, s2, 2);
1915 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1918 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1919 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1920 if (INSTRUCTION_MUST_CHECK(iptr)) {
1921 gen_nullptr_check(s1);
1924 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1925 emit_movsd_reg_memindex(cd, s3, OFFSET(java_doublearray, data[0]), s1, s2, 3);
1929 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1931 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1932 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1933 emit_array_checks(cd, iptr, s1, s2);
1934 s3 = emit_load_s3(jd, iptr, REG_A1);
1936 M_INTMOVE(s1, REG_A0);
1937 M_INTMOVE(s3, REG_A1);
1939 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1940 ICONST(REG_ITMP3, disp);
1941 N_L(REG_PV, 0, REG_ITMP3, REG_PV);
1942 M_ISUB_IMM(96, REG_SP);
1943 M_JSR(REG_RA, REG_PV);
1944 M_IADD_IMM(96, REG_SP);
1945 N_BASR(REG_ITMP1, RN);
1946 disp = (s4) (cd->mcodeptr - cd->mcodebase);
1947 M_LDA(REG_PV, REG_ITMP1, -disp);
1951 codegen_add_arraystoreexception_ref(cd);
1953 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1954 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1955 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1957 M_INTMOVE(s2, REG_ITMP2);
1958 M_ISLL_IMM(2, REG_ITMP2);
1959 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1962 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1963 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1968 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1971 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1972 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1973 if (INSTRUCTION_MUST_CHECK(iptr)) {
1974 gen_nullptr_check(s1);
1977 emit_movb_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_bytearray, data[0]), s1, s2, 0);
1981 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1984 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1985 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1986 if (INSTRUCTION_MUST_CHECK(iptr)) {
1987 gen_nullptr_check(s1);
1990 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_chararray, data[0]), s1, s2, 1);
1994 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
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 emit_movw_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_shortarray, data[0]), s1, s2, 1);
2007 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
2010 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2011 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2012 if (INSTRUCTION_MUST_CHECK(iptr)) {
2013 gen_nullptr_check(s1);
2016 emit_movl_imm_memindex(cd, iptr->sx.s23.s3.constval, OFFSET(java_intarray, data[0]), s1, s2, 2);
2020 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
2023 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2024 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2025 if (INSTRUCTION_MUST_CHECK(iptr)) {
2026 gen_nullptr_check(s1);
2030 if (IS_IMM32(iptr->sx.s23.s3.constval)) {
2031 emit_mov_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2033 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval & 0x00000000ffffffff), OFFSET(java_longarray, data[0]), s1, s2, 3);
2034 emit_movl_imm_memindex(cd, (u4) (iptr->sx.s23.s3.constval >> 32), OFFSET(java_longarray, data[0]) + 4, s1, s2, 3);
2039 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
2042 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2043 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2044 if (INSTRUCTION_MUST_CHECK(iptr)) {
2045 gen_nullptr_check(s1);
2048 emit_mov_imm_memindex(cd, 0, OFFSET(java_objectarray, data[0]), s1, s2, 3);
2053 case ICMD_GETSTATIC: /* ... ==> ..., value */
2055 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2056 uf = iptr->sx.s23.s3.uf;
2057 fieldtype = uf->fieldref->parseddesc.fd->type;
2058 disp = dseg_add_unique_address(cd, NULL);
2060 /* PROFILE_CYCLE_STOP; */
2062 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2064 /* PROFILE_CYCLE_START; */
2067 fi = iptr->sx.s23.s3.fmiref->p.field;
2068 fieldtype = fi->type;
2069 disp = dseg_add_address(cd, &(fi->value));
2071 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
2074 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
2076 PROFILE_CYCLE_START;
2080 M_ALD(REG_ITMP1, REG_PV, disp);
2082 switch (fieldtype) {
2084 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2085 M_ILD(d, REG_ITMP1, 0);
2088 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2089 M_LLD(d, REG_ITMP1, 0);
2092 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2093 M_ALD(d, REG_ITMP1, 0);
2096 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2097 M_FLD(d, REG_ITMP1, 0);
2100 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2101 M_DLD(d, REG_ITMP1, 0);
2105 emit_store_dst(jd, iptr, d);
2109 case ICMD_PUTSTATIC: /* ..., value ==> ... */
2111 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2112 uf = iptr->sx.s23.s3.uf;
2113 fieldtype = uf->fieldref->parseddesc.fd->type;
2114 disp = dseg_add_unique_address(cd, uf);
2116 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
2119 fi = iptr->sx.s23.s3.fmiref->p.field;
2120 fieldtype = fi->type;
2121 disp = dseg_add_address(cd, &(fi->value));
2123 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2124 codegen_addpatchref(cd, PATCHER_clinit,
2128 M_ALD(REG_ITMP1, REG_PV, disp);
2129 switch (fieldtype) {
2131 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2132 M_IST(s1, REG_ITMP1, 0);
2135 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
2136 M_LST(s1, REG_ITMP1, 0);
2139 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
2140 M_AST(s1, REG_ITMP1, 0);
2143 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2144 M_FST(s1, REG_ITMP1, 0);
2147 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
2148 M_DST(s1, REG_ITMP1, 0);
2153 case ICMD_PUTSTATICCONST: /* ... ==> ... */
2154 /* val = value (in current instruction) */
2155 /* following NOP) */
2158 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2159 uf = iptr->sx.s23.s3.uf;
2160 fieldtype = uf->fieldref->parseddesc.fd->type;
2161 disp = dseg_add_unique_address(cd, uf);
2163 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
2166 fi = iptr->sx.s23.s3.fmiref->p.field;
2167 fieldtype = fi->type;
2168 disp = dseg_add_address(cd, &(fi->value));
2170 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
2171 codegen_add_patch_ref(cd, PATCHER_initialize_class, fi->class,
2175 M_ALD(REG_ITMP1, REG_PV, disp);
2177 switch (fieldtype) {
2179 M_IST(REG_ZERO, REG_ITMP1, 0);
2182 M_LST(REG_ZERO, REG_ITMP1, 0);
2185 M_AST(REG_ZERO, REG_ITMP1, 0);
2188 M_FST(REG_ZERO, REG_ITMP1, 0);
2191 M_DST(REG_ZERO, REG_ITMP1, 0);
2197 case ICMD_GETFIELD: /* ... ==> ..., value */
2199 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2200 emit_nullpointer_check(cd, iptr, s1);
2202 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2203 uf = iptr->sx.s23.s3.uf;
2204 fieldtype = uf->fieldref->parseddesc.fd->type;
2207 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2210 fi = iptr->sx.s23.s3.fmiref->p.field;
2211 fieldtype = fi->type;
2215 switch (fieldtype) {
2217 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2221 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
2222 if (GET_HIGH_REG(d) == s1) {
2223 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2224 M_ILD(GET_HIGH_REG(d), s1, disp);
2227 M_ILD(GET_LOW_REG(d), s1, disp + 4);
2228 M_ILD(GET_HIGH_REG(d), s1, disp);
2232 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2236 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2240 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
2244 emit_store_dst(jd, iptr, d);
2247 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
2249 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2250 gen_nullptr_check(s1);
2252 s2 = emit_load_s2(jd, iptr, REG_IFTMP);
2254 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2255 uf = iptr->sx.s23.s3.uf;
2256 fieldtype = uf->fieldref->parseddesc.fd->type;
2260 fi = iptr->sx.s23.s3.fmiref->p.field;
2261 fieldtype = fi->type;
2265 if (IS_INT_LNG_TYPE(fieldtype)) {
2266 if (IS_2_WORD_TYPE(fieldtype))
2267 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
2269 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2272 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
2274 if (INSTRUCTION_IS_UNRESOLVED(iptr))
2275 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
2277 switch (fieldtype) {
2279 M_IST(s2, s1, disp);
2282 /* TODO really order */
2283 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2284 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2287 M_AST(s2, s1, disp);
2290 M_FST(s2, s1, disp);
2293 M_DST(s2, s1, disp);
2298 case ICMD_PUTFIELDCONST: /* ..., objectref, value ==> ... */
2299 /* val = value (in current instruction) */
2300 /* following NOP) */
2303 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2304 gen_nullptr_check(s1);
2306 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2307 uf = iptr->sx.s23.s3.uf;
2308 fieldtype = uf->fieldref->parseddesc.fd->type;
2311 /* PROFILE_CYCLE_STOP; */
2313 codegen_add_patch_ref(cd, PATCHER_putfieldconst, uf, 0);
2315 /* PROFILE_CYCLE_START; */
2318 fi = iptr->sx.s23.s3.fmiref->p.field;
2319 fieldtype = fi->type;
2323 switch (fieldtype) {
2326 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2331 /* XXX why no check for IS_IMM32? */
2332 M_IST32_IMM(iptr->sx.s23.s2.constval, s1, disp);
2333 M_IST32_IMM(iptr->sx.s23.s2.constval >> 32, s1, disp + 4);
2340 /* branch operations **************************************************/
2342 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2344 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2345 M_INTMOVE(s1, REG_ITMP1_XPTR);
2349 #ifdef ENABLE_VERIFIER
2350 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2351 uc = iptr->sx.s23.s2.uc;
2353 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2355 #endif /* ENABLE_VERIFIER */
2357 disp = dseg_add_functionptr(cd, asm_handle_exception);
2358 M_ALD(REG_ITMP2, REG_PV, disp);
2359 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2364 case ICMD_GOTO: /* ... ==> ... */
2365 case ICMD_RET: /* ... ==> ... */
2368 codegen_add_branch_ref(cd, iptr->dst.block);
2372 case ICMD_JSR: /* ... ==> ... */
2376 codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2380 case ICMD_IFNULL: /* ..., value ==> ... */
2381 case ICMD_IFNONNULL: /* ..., value ==> ... */
2382 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2384 switch (iptr->opc) {
2388 case ICMD_IFNONNULL:
2392 codegen_add_branch_ref(cd, iptr->dst.block);
2395 case ICMD_IFEQ: /* ..., value ==> ... */
2396 case ICMD_IFLT: /* ..., value ==> ... */
2397 case ICMD_IFLE: /* ..., value ==> ... */
2398 case ICMD_IFNE: /* ..., value ==> ... */
2399 case ICMD_IFGT: /* ..., value ==> ... */
2400 case ICMD_IFGE: /* ..., value ==> ... */
2402 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2404 if (N_VALID_IMM(iptr->sx.val.i))
2405 N_CHI(s1, iptr->sx.val.i);
2407 disp = dseg_add_s4(cd, iptr->sx.val.i);
2408 N_LHI(REG_ITMP2, disp);
2409 N_C(s1, 0, REG_ITMP2, REG_PV);
2412 switch (iptr->opc) {
2432 codegen_add_branch_ref(cd, iptr->dst.block);
2436 case ICMD_IF_LLT: /* ..., value ==> ... */
2437 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2446 /* ATTENTION: compare high words signed and low words unsigned */
2448 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2450 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2451 N_CHI(s1, iptr->sx.val.l >> 32);
2453 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2454 N_LHI(REG_ITMP2, disp);
2455 N_C(s1, 0, REG_ITMP2, REG_PV);
2462 codegen_addreference(cd, iptr->dst.block);
2463 /* EQ ... fall through */
2464 out_ref = cd->mcodeptr;
2470 codegen_addreference(cd, iptr->dst.block);
2471 /* EQ ... fall through */
2472 out_ref = cd->mcodeptr;
2476 /* EQ ... fall through */
2477 out_ref = cd->mcodeptr;
2481 /* EQ ... fall through */
2483 codegen_addreference(cd, iptr->dst.block);
2489 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2491 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2492 N_LHI(REG_ITMP2, disp);
2493 N_CL(s1, 0, REG_ITMP2, REG_PV);
2517 codegen_addreference(cd, iptr->dst.block);
2519 if (out_ref != NULL) {
2520 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2526 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2527 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2529 /* Compare addresses as 31 bit unsigned integers */
2531 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2532 N_LA(REG_ITMP1, 0, RN, s1);
2534 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2535 N_LA(REG_ITMP2, 0, RN, s2);
2537 M_CMP(REG_ITMP1, REG_ITMP2);
2539 switch (iptr->opc) {
2540 case ICMD_IF_ACMPEQ:
2543 case ICMD_IF_ACMPNE:
2548 codegen_add_branch_ref(cd, iptr->dst.block);
2552 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2553 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2554 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2555 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2556 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2557 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2559 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2560 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2562 switch (iptr->opc) {
2563 case ICMD_IF_ICMPEQ:
2566 case ICMD_IF_ICMPNE:
2569 case ICMD_IF_ICMPLT:
2572 case ICMD_IF_ICMPGT:
2575 case ICMD_IF_ICMPLE:
2578 case ICMD_IF_ICMPGE:
2582 codegen_add_branch_ref(cd, iptr->dst.block);
2586 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2587 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2588 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2589 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2590 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2591 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2596 /* ATTENTION: compare high words signed and low words unsigned */
2598 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2599 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2604 case ICMD_IF_LCMPLT:
2605 case ICMD_IF_LCMPLE:
2607 codegen_addreference(cd, iptr->dst.block);
2608 /* EQ ... fall through */
2609 out_ref = cd->mcodeptr;
2612 case ICMD_IF_LCMPGT:
2613 case ICMD_IF_LCMPGE:
2615 codegen_addreference(cd, iptr->dst.block);
2616 /* EQ ... fall through */
2617 out_ref = cd->mcodeptr;
2620 case ICMD_IF_LCMPEQ:
2621 /* EQ ... fall through */
2622 out_ref = cd->mcodeptr;
2625 case ICMD_IF_LCMPNE:
2626 /* EQ ... fall through */
2628 codegen_addreference(cd, iptr->dst.block);
2634 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2635 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2640 case ICMD_IF_LCMPLT:
2643 case ICMD_IF_LCMPLE:
2646 case ICMD_IF_LCMPGT:
2649 case ICMD_IF_LCMPGE:
2652 case ICMD_IF_LCMPEQ:
2655 case ICMD_IF_LCMPNE:
2662 codegen_addreference(cd, iptr->dst.block);
2664 if (out_ref != NULL) {
2665 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2671 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2673 REPLACEMENT_POINT_RETURN(cd, iptr);
2674 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2675 M_INTMOVE(s1, REG_RESULT);
2676 goto nowperformreturn;
2678 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2680 REPLACEMENT_POINT_RETURN(cd, iptr);
2681 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2682 M_INTMOVE(s1, REG_RESULT);
2684 #ifdef ENABLE_VERIFIER
2685 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2686 unresolved_class *uc = iptr->sx.s23.s2.uc;
2688 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2690 #endif /* ENABLE_VERIFIER */
2691 goto nowperformreturn;
2693 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2695 REPLACEMENT_POINT_RETURN(cd, iptr);
2696 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2697 M_LNGMOVE(s1, REG_RESULT_PACKED);
2698 goto nowperformreturn;
2700 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2703 REPLACEMENT_POINT_RETURN(cd, iptr);
2704 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2705 M_FLTMOVE(s1, REG_FRESULT);
2706 goto nowperformreturn;
2708 case ICMD_RETURN: /* ... ==> ... */
2710 REPLACEMENT_POINT_RETURN(cd, iptr);
2716 p = cd->stackframesize;
2718 /* call trace function */
2720 #if !defined(NDEBUG)
2721 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2722 emit_verbosecall_exit(jd);
2723 #endif /* !defined(NDEBUG) */
2725 #if defined(ENABLE_THREADS)
2726 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2727 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2728 M_ALD(REG_ITMP3, REG_PV, disp);
2731 /* we need to save the proper return value */
2733 switch (iptr->opc) {
2735 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2739 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2742 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2745 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2749 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2752 /* and now restore the proper return value */
2754 switch (iptr->opc) {
2756 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2760 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2763 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2766 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2772 /* restore return address */
2774 p--; M_ALD(REG_RA, REG_SP, p * 4);
2776 /* restore saved registers */
2778 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2779 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2781 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2782 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2785 /* deallocate stack */
2787 if (cd->stackframesize)
2788 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2795 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2800 branch_target_t *table;
2802 table = iptr->dst.table;
2804 l = iptr->sx.s23.s2.tablelow;
2805 i = iptr->sx.s23.s3.tablehigh;
2807 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2808 M_INTMOVE(s1, REG_ITMP1);
2811 M_ISUB_IMM(l, REG_ITMP1);
2813 /* number of targets */
2817 M_ICMP_IMM(i - 1, REG_ITMP1);
2820 codegen_add_branch_ref(cd, table[0].block); /* default target */
2822 /* build jump table top down and use address of lowest entry */
2827 dseg_add_target(cd, table->block);
2831 /* length of dataseg after last dseg_add_target is used
2834 M_MOV_IMM(0, REG_ITMP2);
2836 emit_mov_memindex_reg(cd, -(cd->dseglen), REG_ITMP2, REG_ITMP1, 3, REG_ITMP1);
2843 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2848 lookup_target_t *lookup;
2850 lookup = iptr->dst.lookup;
2852 i = iptr->sx.s23.s2.lookupcount;
2854 MCODECHECK(8 + ((7 + 6) * i) + 5);
2855 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2858 M_ICMP_IMM(lookup->value, s1);
2860 codegen_add_branch_ref(cd, lookup->target.block);
2866 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2872 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2874 bte = iptr->sx.s23.s3.bte;
2878 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2879 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2880 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2881 case ICMD_INVOKEINTERFACE:
2883 REPLACEMENT_POINT_INVOKE(cd, iptr);
2885 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2887 um = iptr->sx.s23.s3.um;
2888 md = um->methodref->parseddesc.md;
2891 lm = iptr->sx.s23.s3.fmiref->p.method;
2893 md = lm->parseddesc;
2897 s3 = md->paramcount;
2899 MCODECHECK((s3 << 1) + 64);
2901 /* copy arguments to registers or stack location */
2903 for (s3 = s3 - 1; s3 >= 0; s3--) {
2904 var = VAR(iptr->sx.s23.s2.args[s3]);
2906 /* Already Preallocated? */
2907 if (var->flags & PREALLOC)
2910 if (IS_INT_LNG_TYPE(var->type)) {
2911 if (!md->params[s3].inmemory) {
2912 if (IS_2_WORD_TYPE(var->type)) {
2914 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2915 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2917 d = emit_load(jd, iptr, var, s1);
2921 s1 = rd->argintregs[md->params[s3].regoff];
2922 d = emit_load(jd, iptr, var, s1);
2927 if (IS_2_WORD_TYPE(var->type)) {
2928 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2929 M_LST(d, REG_SP, md->params[s3].regoff * 4);
2932 d = emit_load(jd, iptr, var, REG_ITMP1);
2933 M_IST(d, REG_SP, md->params[s3].regoff * 4);
2938 if (!md->params[s3].inmemory) {
2939 s1 = rd->argfltregs[md->params[s3].regoff];
2940 d = emit_load(jd, iptr, var, s1);
2944 d = emit_load(jd, iptr, var, REG_FTMP1);
2945 if (IS_2_WORD_TYPE(var->type))
2946 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2948 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2953 switch (iptr->opc) {
2955 disp = dseg_add_functionptr(cd, bte->fp);
2957 N_AHI(REG_SP, -96); /* register save area as required by C abi */
2958 N_LHI(REG_ITMP1, disp);
2959 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2962 case ICMD_INVOKESPECIAL:
2963 emit_nullpointer_check(cd, iptr, REG_A0);
2964 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
2967 case ICMD_INVOKESTATIC:
2969 disp = dseg_add_unique_address(cd, um);
2971 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2975 disp = dseg_add_address(cd, lm->stubroutine);
2977 N_LHI(REG_ITMP1, disp);
2978 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2981 case ICMD_INVOKEVIRTUAL:
2982 emit_nullpointer_check(cd, iptr, REG_A0);
2985 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2990 s1 = OFFSET(vftbl_t, table[0]) +
2991 sizeof(methodptr) * lm->vftblindex;
2994 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2995 M_ALD(REG_PV, REG_METHODPTR, s1);
2998 case ICMD_INVOKEINTERFACE:
2999 emit_nullpointer_check(cd, iptr, REG_A0);
3001 /* s1 will be negative here, so use (0xFFF + s1) as displacement
3002 * and -0xFFF in index register (itmp1)
3005 N_LHI(REG_ITMP1, -N_DISP_MAX);
3008 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
3014 s1 = OFFSET(vftbl_t, interfacetable[0]) -
3015 sizeof(methodptr*) * lm->class->index +
3018 s2 = sizeof(methodptr) * (lm - lm->class->methods);
3021 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
3022 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
3023 M_ALD(REG_PV, REG_METHODPTR, s2);
3027 /* generate the actual call */
3030 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
3031 N_BASR(REG_ITMP1, RN);
3032 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3033 M_LDA(REG_PV, REG_ITMP1, -disp);
3035 /* post call finalization */
3037 if (iptr->opc == ICMD_BUILTIN) {
3038 N_AHI(REG_SP, 96); /* remove C abi register save area */
3041 /* actually only used for ICMD_BUILTIN */
3043 if (INSTRUCTION_MUST_CHECK(iptr)) {
3046 codegen_add_fillinstacktrace_ref(cd);
3049 /* store return value */
3051 d = md->returntype.type;
3053 if (d != TYPE_VOID) {
3054 if (IS_INT_LNG_TYPE(d)) {
3055 if (IS_2_WORD_TYPE(d)) {
3056 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
3057 M_LNGMOVE(REG_RESULT_PACKED, s1);
3060 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3061 M_INTMOVE(REG_RESULT, s1);
3065 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
3066 M_FLTMOVE(REG_FRESULT, s1);
3068 emit_store_dst(jd, iptr, s1);
3074 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
3076 /* val.a: (classinfo*) superclass */
3078 /* superclass is an interface:
3080 * OK if ((sub == NULL) ||
3081 * (sub->vftbl->interfacetablelength > super->index) &&
3082 * (sub->vftbl->interfacetable[-super->index] != NULL));
3084 * superclass is a class:
3086 * OK if ((sub == NULL) || (0
3087 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3088 * super->vftbl->diffval));
3091 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
3092 /* object type cast-check */
3095 vftbl_t *supervftbl;
3098 u1 *class_label_refs[] = { 0 }, *class_label;
3099 u1 *exit_label_refs[] = { 0, 0, 0, 0 };
3101 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3107 super = iptr->sx.s23.s3.c.cls;
3108 superindex = super->index;
3109 supervftbl = super->vftbl;
3112 #if defined(ENABLE_THREADS)
3113 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3115 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3117 /* if class is not resolved, check which code to call */
3119 if (super == NULL) {
3121 exit_label_refs[0] = cd->mcodeptr;
3124 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3126 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3127 iptr->sx.s23.s3.c.ref,
3130 ICONST(REG_ITMP2, ACC_INTERFACE);
3131 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3132 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3133 class_label_refs[0] = cd->mcodeptr;
3137 /* interface checkcast code */
3139 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3140 if (super == NULL) {
3141 codegen_add_patch_ref(cd,
3142 PATCHER_checkcast_instanceof_interface,
3143 iptr->sx.s23.s3.c.ref,
3147 exit_label_refs[1] = cd->mcodeptr;
3151 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3152 M_ILD(REG_ITMP3, REG_ITMP2,
3153 OFFSET(vftbl_t, interfacetablelength));
3154 M_LDA(REG_ITMP3, REG_ITMP3, -superindex);
3157 codegen_add_classcastexception_ref(cd, s1);
3158 M_ALD(REG_ITMP3, REG_ITMP2,
3159 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3160 superindex * sizeof(methodptr*)));
3163 codegen_add_classcastexception_ref(cd, s1);
3165 if (super == NULL) {
3166 exit_label_refs[2] = cd->mcodeptr;
3171 /* class checkcast code */
3173 class_label = cd->mcodeptr;
3175 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3176 if (super == NULL) {
3177 disp = dseg_add_unique_address(cd, NULL);
3179 codegen_add_patch_ref(cd,
3180 PATCHER_resolve_classref_to_vftbl,
3181 iptr->sx.s23.s3.c.ref,
3185 disp = dseg_add_address(cd, supervftbl);
3187 exit_label_refs[3] = cd->mcodeptr;
3191 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
3192 M_ALD(REG_ITMP3, REG_PV, disp);
3193 #if defined(ENABLE_THREADS)
3194 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3196 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
3197 /* if (s1 != REG_ITMP1) { */
3198 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
3199 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
3200 /* #if defined(ENABLE_THREADS) */
3201 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
3203 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
3206 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
3207 M_ISUB(REG_ITMP3, REG_ITMP2);
3208 M_ALD(REG_ITMP3, REG_PV, disp);
3209 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
3210 #if defined(ENABLE_THREADS)
3211 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3214 N_CLR(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
3215 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
3216 M_BGT(0); /* Branch if greater then */
3217 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
3218 codegen_add_classcastexception_ref(cd, s1);
3221 /* resolve labels by adding the correct displacement */
3223 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3224 if (exit_label_refs[s2])
3225 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3228 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3229 if (class_label_refs[s2])
3230 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3233 d = codegen_reg_of_dst(jd, iptr, s1);
3236 /* array type cast-check */
3238 s1 = emit_load_s1(jd, iptr, REG_A0);
3239 M_INTMOVE(s1, REG_A0);
3241 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3242 disp = dseg_add_unique_address(cd, NULL);
3244 codegen_add_patch_ref(cd,
3245 PATCHER_resolve_classref_to_classinfo,
3246 iptr->sx.s23.s3.c.ref,
3250 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3252 M_ALD(REG_A1, REG_PV, disp);
3253 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
3254 ICONST(REG_ITMP1, disp); /* TODO negative displacement */
3255 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
3256 M_JSR(REG_RA, REG_PV);
3257 N_BASR(REG_ITMP1, RN);
3258 disp = (s4) (cd->mcodeptr - cd->mcodebase);
3259 M_LDA(REG_PV, REG_ITMP1, -disp);
3261 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3264 codegen_add_classcastexception_ref(cd, s1);
3266 d = codegen_reg_of_dst(jd, iptr, s1);
3270 emit_store_dst(jd, iptr, d);
3273 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
3274 /* val.a: (classinfo*) superclass */
3276 /* superclass is an interface:
3278 * return (sub != NULL) &&
3279 * (sub->vftbl->interfacetablelength > super->index) &&
3280 * (sub->vftbl->interfacetable[-super->index] != NULL);
3282 * superclass is a class:
3284 * return ((sub != NULL) && (0
3285 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
3286 * super->vftbl->diffvall));
3291 vftbl_t *supervftbl;
3294 u1 *class_label, *class_label_refs[1] = { 0 };
3295 u1 *exit_label_refs[4] = { 0, 0, 0, 0 };
3296 u1 *label1, *label1_refs[1] = { 0 };
3298 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3304 super = iptr->sx.s23.s3.c.cls;
3305 superindex = super->index;
3306 supervftbl = super->vftbl;
3309 #if defined(ENABLE_THREADS)
3310 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
3312 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
3313 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3315 M_MOV(s1, REG_ITMP1);
3319 /* if class is not resolved, check which code to call */
3321 if (super == NULL) {
3325 exit_label_refs[0] = cd->mcodeptr;
3328 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3330 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3331 iptr->sx.s23.s3.c.ref, disp);
3333 ICONST(REG_ITMP2, ACC_INTERFACE);
3334 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3335 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3336 class_label_refs[0] = cd->mcodeptr;
3340 /* interface instanceof code */
3342 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3343 if (super == NULL) {
3344 /* If d == REG_ITMP2, then it's destroyed in check
3349 codegen_add_patch_ref(cd,
3350 PATCHER_checkcast_instanceof_interface,
3351 iptr->sx.s23.s3.c.ref, 0);
3356 exit_label_refs[1] = cd->mcodeptr;
3360 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3361 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3362 M_ASUB_IMM(superindex, REG_ITMP3);
3363 label1_refs[0] = cd->mcodeptr;
3367 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3368 superindex * sizeof(methodptr*))
3370 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3372 /* d := (REG_ITMP1 != 0) */
3374 N_LTR(d, REG_ITMP1);
3378 label1 = cd->mcodeptr;
3380 if (super == NULL) {
3381 exit_label_refs[2] = cd->mcodeptr;
3386 /* class instanceof code */
3388 class_label = cd->mcodeptr;
3390 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3391 if (super == NULL) {
3392 disp = dseg_add_unique_address(cd, NULL);
3394 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3395 iptr->sx.s23.s3.c.ref,
3399 disp = dseg_add_address(cd, supervftbl);
3404 exit_label_refs[3] = cd->mcodeptr;
3408 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3409 M_ALD(REG_ITMP2, REG_PV, disp);
3410 #if defined(ENABLE_THREADS)
3411 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3413 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3414 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3415 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3416 #if defined(ENABLE_THREADS)
3417 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3419 M_ISUB(REG_ITMP1, REG_ITMP3);
3421 N_CLR(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3427 /* resolve labels by adding the correct displacement */
3429 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3430 if (exit_label_refs[s2])
3431 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3434 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3435 if (class_label_refs[s2])
3436 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3439 for (s2 = 0; s2 < sizeof(label1_refs) / sizeof(label1_refs[0]); ++s2) {
3440 if (label1_refs[s2])
3441 *(u4 *)label1_refs[s2] |= (u4)(label1 - label1_refs[s2]) / 2;
3444 emit_store_dst(jd, iptr, d);
3450 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3454 /* check for negative sizes and copy sizes to stack if necessary */
3456 MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);
3458 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3460 /* copy SAVEDVAR sizes to stack */
3461 var = VAR(iptr->sx.s23.s2.args[s1]);
3463 /* Already Preallocated? */
3464 if (!(var->flags & PREALLOC)) {
3465 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3466 M_LST(s2, REG_SP, s1 * 8);
3470 /* is a patcher function set? */
3472 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3473 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
3474 iptr->sx.s23.s3.c.ref, 0);
3477 /* a0 = dimension count */
3479 M_MOV_IMM(iptr->s1.argcount, REG_A0);
3481 /* a1 = classinfo */
3483 M_MOV_IMM(iptr->sx.s23.s3.c.cls, REG_A1);
3485 /* a2 = pointer to dimensions = stack pointer */
3487 M_MOV(REG_SP, REG_A2);
3489 M_MOV_IMM(BUILTIN_multianewarray, REG_ITMP1);
3492 /* check for exception before result assignment */
3496 codegen_add_fillinstacktrace_ref(cd);
3498 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3499 M_INTMOVE(REG_RESULT, s1);
3500 emit_store_dst(jd, iptr, s1);
3505 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3509 } /* for instruction */
3511 MCODECHECK(512); /* XXX require a lower number? */
3513 /* At the end of a basic block we may have to append some nops,
3514 because the patcher stub calling code might be longer than the
3515 actual instruction. So codepatching does not change the
3516 following block unintentionally. */
3518 if (cd->mcodeptr < cd->lastmcodeptr) {
3519 while (cd->mcodeptr < cd->lastmcodeptr) {
3524 } /* if (bptr -> flags >= BBREACHED) */
3525 } /* for basic block */
3527 dseg_createlinenumbertable(cd);
3529 /* generate stubs */
3531 emit_exception_stubs(jd);
3532 emit_patcher_stubs(jd);
3534 emit_replacement_stubs(jd);
3539 /* everything's ok */
3545 /* createcompilerstub **********************************************************
3547 Creates a stub routine which calls the compiler.
3549 *******************************************************************************/
3551 #define COMPILERSTUB_DATASIZE (3 * SIZEOF_VOID_P)
3552 #define COMPILERSTUB_CODESIZE (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
3554 #define COMPILERSTUB_SIZE (COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE)
3557 u1 *createcompilerstub(methodinfo *m)
3559 u1 *s; /* memory to hold the stub */
3565 s = CNEW(u1, COMPILERSTUB_SIZE);
3567 /* set data pointer and code pointer */
3570 s = s + COMPILERSTUB_DATASIZE;
3572 /* mark start of dump memory area */
3574 dumpsize = dump_size();
3576 cd = DNEW(codegendata);
3579 /* Store the codeinfo pointer in the same place as in the
3580 methodheader for compiled methods. */
3582 code = code_codeinfo_new(m);
3584 d[0] = (ptrint) asm_call_jit_compiler;
3586 d[2] = (ptrint) code;
3588 /* code for the stub */
3590 /* don't touch ITMP3 as it cointains the return address */
3592 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3594 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3595 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3596 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3599 #if defined(ENABLE_STATISTICS)
3601 count_cstub_len += COMPILERSTUB_SIZE;
3604 /* release dump area */
3606 dump_release(dumpsize);
3612 /* createnativestub ************************************************************
3614 Creates a stub routine which calls a native method.
3616 *******************************************************************************/
3619 arguments on stack \
3620 -------------------------------------------------| <- SP on nativestub entry
3622 callee saved int regs (none) |
3623 callee saved float regs (none) | stack frame like in cacao
3624 local variable slots (none) |
3625 arguments for calling methods (none) /
3626 ------------------------------------------------------------------ <- datasp
3631 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3632 0 - 96 register save area for callee /
3633 -------------------------------------------------------- <- SP native method
3635 SP after method entry
3638 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3646 s4 i, j; /* count variables */
3651 /* get required compiler data */
3658 /* initialize variables */
3661 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3663 /* calculate stack frame size */
3665 cd->stackframesize =
3666 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3667 sizeof(localref_table) / SIZEOF_VOID_P +
3668 INT_ARG_CNT + FLT_ARG_CNT +
3669 1 + /* functionptr, TODO: store in data segment */
3672 cd->stackframesize |= 0x1; /* keep stack 16-byte aligned */
3675 cd->stackframesize =
3676 1 + /* r14 - return address */ +
3677 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3678 sizeof(localref_table) / SIZEOF_VOID_P +
3680 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3681 nmd->memuse + /* parameter passing */
3682 96 / SIZEOF_VOID_P /* required by ABI */;
3684 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3687 /* create method header */
3689 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3690 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3691 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3692 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3693 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3694 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3695 (void) dseg_addlinenumbertablesize(cd);
3696 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3698 /* generate native method profiling code */
3700 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3701 /* count frequency */
3703 M_MOV_IMM(code, REG_ITMP3);
3704 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3708 /* generate stub code */
3710 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3712 /* save return address */
3714 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3717 #if !defined(NDEBUG)
3718 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3719 emit_verbosecall_enter(jd);
3723 /* get function address (this must happen before the stackframeinfo) */
3725 disp = dseg_add_functionptr(cd, f);
3727 #if !defined(WITH_STATIC_CLASSPATH)
3729 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3732 M_ILD(REG_ITMP1, REG_PV, disp);
3734 j = 96 + (nmd->memuse * 4);
3736 /* todo some arg registers are not volatile in C-abi terms */
3738 /* save integer and float argument registers */
3740 for (i = 0; i < md->paramcount; i++) {
3741 if (! md->params[i].inmemory) {
3742 s1 = md->params[i].regoff;
3744 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3745 if (IS_2_WORD_TYPE(t)) {
3746 /* todo store multiple */
3747 N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3748 N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3750 N_ST(rd->argintregs[s1], j, RN, REG_SP);
3753 if (IS_2_WORD_TYPE(t)) {
3754 N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3756 N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3764 N_ST(REG_ITMP1, j, RN, REG_SP);
3766 /* create dynamic stack info */
3768 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3769 N_LR(REG_A1, REG_PV); /* pv */
3770 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3771 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3773 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3774 M_ILD(REG_ITMP1, REG_PV, disp);
3776 M_CALL(REG_ITMP1); /* call */
3778 /* restore integer and float argument registers */
3780 j = 96 + (nmd->memuse * 4);
3782 for (i = 0; i < md->paramcount; i++) {
3783 if (! md->params[i].inmemory) {
3784 s1 = md->params[i].regoff;
3786 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3787 if (IS_2_WORD_TYPE(t)) {
3788 /* todo load multiple ! */
3789 N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3790 N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3792 N_L(rd->argintregs[s1], j, RN, REG_SP);
3795 if (IS_2_WORD_TYPE(t)) {
3796 N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3798 N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3806 N_L(REG_ITMP1, j, RN, REG_SP);
3808 /* copy or spill arguments to new locations */
3810 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3811 t = md->paramtypes[i].type;
3813 if (IS_INT_LNG_TYPE(t)) {
3815 if (!md->params[i].inmemory) {
3817 s1 = rd->argintregs[md->params[i].regoff];
3819 if (!nmd->params[j].inmemory) {
3820 s2 = rd->argintregs[nmd->params[j].regoff];
3821 if (IS_2_WORD_TYPE(t)) {
3822 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3823 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3828 s2 = nmd->params[j].regoff;
3829 if (IS_2_WORD_TYPE(t)) {
3830 N_STM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3832 N_ST(s1, 96 + (s2 * 4), RN, REG_SP);
3837 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3838 s2 = nmd->params[j].regoff;
3840 if (IS_2_WORD_TYPE(t)) {
3841 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3843 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3848 /* We only copy spilled float arguments, as the float argument */
3849 /* registers keep unchanged. */
3851 if (md->params[i].inmemory) {
3852 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3853 s2 = nmd->params[j].regoff;
3855 if (IS_2_WORD_TYPE(t)) {
3856 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3858 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3864 /* put class into second argument register */
3866 if (m->flags & ACC_STATIC) {
3867 disp = dseg_add_address(cd, m->class);
3868 M_ILD(REG_A1, REG_PV, disp);
3871 /* put env into first argument register */
3873 disp = dseg_add_address(cd, _Jv_env);
3874 M_ILD(REG_A0, REG_PV, disp);
3876 /* do the native function call */
3878 M_CALL(REG_ITMP1); /* call */
3880 /* save return value */
3882 t = md->returntype.type;
3884 if (t != TYPE_VOID) {
3885 if (IS_INT_LNG_TYPE(t)) {
3886 if (IS_2_WORD_TYPE(t)) {
3887 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3889 N_ST(REG_RESULT, 96, RN, REG_SP);
3892 if (IS_2_WORD_TYPE(t)) {
3893 N_STD(REG_FRESULT, 96, RN, REG_SP);
3895 N_STE(REG_FRESULT, 96, RN, REG_SP);
3901 #if !defined(NDEBUG)
3902 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3903 emit_verbosecall_exit(jd);
3907 /* remove native stackframe info */
3909 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3910 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3911 M_ILD(REG_ITMP1, REG_PV, disp);
3913 N_LR(REG_ITMP3, REG_RESULT);
3915 /* restore return value */
3917 if (t != TYPE_VOID) {
3918 if (IS_INT_LNG_TYPE(t)) {
3919 if (IS_2_WORD_TYPE(t)) {
3920 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3922 N_L(REG_RESULT, 96, RN, REG_SP);
3925 if (IS_2_WORD_TYPE(t)) {
3926 N_LD(REG_FRESULT, 96, RN, REG_SP);
3928 N_LE(REG_FRESULT, 96, RN, REG_SP);
3933 /* load return address */
3935 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3937 /* remove stackframe */
3939 N_AHI(REG_SP, cd->stackframesize * 4);
3941 /* test for exception */
3943 N_LTR(REG_ITMP3, REG_ITMP3);
3944 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3948 N_BCR(DD_ANY, REG_ITMP2);
3950 /* handle exception */
3952 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3953 M_ALD(REG_ITMP2_XPC, REG_SP, (cd->stackframesize - 1) * 4); /* get return address from stack */
3956 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3958 disp = dseg_add_functionptr(cd, /*asm_handle_nat_exception*/ panic);
3960 M_ALD(REG_ITMP3, REG_PV, disp);
3961 M_JMP(RN, REG_ITMP3);
3963 /* generate patcher stubs */
3965 emit_patcher_stubs(jd);
3969 return code->entrypoint;
3973 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3974 codegendata *cd = jd->cd;
3975 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3977 M_MOV(reg, tempregnum);
3985 * These are local overrides for various environment variables in Emacs.
3986 * Please do not remove this and leave it at the end of the file, where
3987 * Emacs will automagically detect them.
3988 * ---------------------------------------------------------------------
3991 * indent-tabs-mode: t
3995 * vim:noexpandtab:sw=4:ts=4: