1 /* src/vm/jit/sparc64/codegen.c - machine code generator for Sparc
3 Copyright (C) 1996-2005, 2006, 2007 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
38 /* #include "vm/jit/sparc64/arch.h" */
39 #include "vm/jit/sparc64/codegen.h"
41 #include "mm/memory.h"
43 #include "native/jni.h"
44 #include "native/localref.h"
45 #include "native/native.h"
46 #include "vm/builtin.h"
47 #include "vm/exceptions.h"
48 #include "vm/global.h"
50 #include "vm/jit/abi.h"
51 #include "vm/jit/asmpart.h"
52 #include "vm/jit/codegen-common.h"
53 #include "vm/jit/dseg.h"
54 #include "vm/jit/emit-common.h"
55 #include "vm/jit/sparc64/emit.h"
56 #include "vm/jit/jit.h"
57 #include "vm/jit/parse.h"
58 #include "vm/jit/patcher.h"
59 #include "vm/jit/reg.h"
60 #include "vm/jit/replace.h"
61 #include "vm/jit/stacktrace.h"
62 #include "vmcore/loader.h"
63 #include "vmcore/options.h"
65 #include "vm/jit/sparc64/solaris/macro_rename.h"
67 #define BUILTIN_FLOAT_ARGS 1
69 /* XXX use something like this for window control ?
70 * #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER)
72 #define REG_PV REG_PV_CALLEE
77 if ((disp < -4096) || (disp > 4095))
78 printf("disp %d\n", disp);
81 return (disp >= -4096) && (disp <= 4095);
84 s4 get_lopart_disp(disp)
89 lodisp = setlo_part(disp);
91 if (setlo_part(disp) == 0)
94 lodisp = setlo_part(disp) | 0x1c00;
101 bool check_13bit_imm(s8 imm)
103 s4 sign = (imm >> 12) & 0x1;
106 if ((imm & ~0xfff) == 0) return true; /* pos imm. */
109 if ((imm & ~0xfff) + 0xfff == -1) return true; /* neg imm. */
111 printf("immediate out-of-bounds: %ld\n", imm);
117 /* codegen_emit ****************************************************************
119 Generates machine code.
121 *******************************************************************************/
123 bool codegen_emit(jitdata *jd)
129 s4 len, s1, s2, s3, d, disp, slots;
135 constant_classref *cr;
136 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
137 unresolved_method *um;
138 builtintable_entry *bte;
141 unresolved_field *uf;
145 /* get required compiler data */
152 /* prevent compiler warnings */
164 #if 0 /* no leaf optimization yet */
165 savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the RA */
167 savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */
170 /* space to save used callee saved registers */
172 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
173 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
175 cd->stackframesize = rd->memuse + savedregs_num;
177 #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
178 if (checksync && (m->flags & ACC_SYNCHRONIZED))
179 cd->stackframesize++;
182 /* keep stack 16-byte aligned (ABI requirement) */
184 if (cd->stackframesize & 1)
185 cd->stackframesize++;
187 /* create method header */
189 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
190 framesize_disp = dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
192 #if defined(ENABLE_THREADS)
193 /* IsSync contains the offset relative to the stack pointer for the
194 argument of monitor_exit used in the exception handler. Since the
195 offset could be zero and give a wrong meaning of the flag it is
199 if (checksync && (m->flags & ACC_SYNCHRONIZED))
200 (void) dseg_add_unique_s4(cd, JITSTACK + (rd->memuse + 1) * 8); /* IsSync */
203 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
205 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
206 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
207 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
208 dseg_addlinenumbertablesize(cd);
209 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
211 /* create exception table */
213 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
214 dseg_add_target(cd, ex->start);
215 dseg_add_target(cd, ex->end);
216 dseg_add_target(cd, ex->handler);
217 (void) dseg_add_unique_address(cd, ex->catchtype.any);
220 /* save register window and create stack frame (if necessary) */
222 if (cd->stackframesize) {
223 if (cd->stackframesize <= 4095)
224 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
226 M_ILD_INTERN(REG_ITMP3, REG_PV_CALLER, framesize_disp);
227 M_SUB(REG_ZERO, REG_ITMP3, REG_ITMP3);
228 M_SAVE_REG(REG_SP, REG_ITMP3, REG_SP);
232 /* save callee saved float registers (none right now) */
234 p = cd->stackframesize;
235 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
236 p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
241 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
242 emit_verbosecall_enter(jd);
246 /* call monitorenter function */
247 #if defined(ENABLE_THREADS)
248 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
249 /* stack offset for monitor argument */
253 /* save float argument registers */
257 ALIGN_STACK_SLOTS(slots);
259 M_LDA(REG_SP, REG_SP, -(slots * 8));
260 for (i = 0; i < FLT_ARG_CNT; i++)
261 M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
265 /* get correct lock object */
267 if (m->flags & ACC_STATIC) {
268 disp = dseg_add_address(cd, &m->class->object.header);
269 M_ALD(REG_OUT0, REG_PV, disp);
270 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
271 M_ALD(REG_ITMP3, REG_PV, disp);
274 /* copy class pointer: $i0 -> $o0 */
275 M_MOV(REG_RESULT_CALLEE, REG_OUT0);
277 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
278 M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
279 M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
282 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
283 M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */
285 /* restore float argument registers */
287 for (i = 0; i < FLT_ARG_CNT; i++)
288 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
290 M_LDA(REG_SP, REG_SP, slots * 8);
295 /* take arguments out of register or stack frame */
299 for (p = 0, l = 0; p < md->paramcount; p++) {
300 t = md->paramtypes[p].type;
302 varindex = jd->local_map[l * 5 + t];
305 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
308 if (varindex == UNUSED)
312 s1 = md->params[p].regoff;
314 if (IS_INT_LNG_TYPE(t)) { /* integer args */
318 if (!md->params[p].inmemory) { /* register arguments */
319 s1 = REG_WINDOW_TRANSPOSE(s1);
321 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
323 /* the register allocator does not know about the window. */
324 /* avoid copying the locals from save to save regs by */
325 /* swapping variables. */
328 int old_dest = var->vv.regoff;
329 int new_dest = p + 24;
331 /* run through all variables */
333 for (i = 0; i < jd->varcount; i++) {
334 varinfo* uvar = VAR(i);
336 if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags))
339 s2 = uvar->vv.regoff;
341 /* free the in reg by moving all other references */
343 if (s2 == new_dest) {
344 uvar->vv.regoff = old_dest;
345 /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
348 /* move all variables to the in reg */
350 if (s2 == old_dest) {
351 uvar->vv.regoff = new_dest;
352 /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
360 else { /* reg arg -> spilled */
361 M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
364 } else { /* stack arguments */
365 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
366 M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1);
368 } else { /* stack arg -> spilled */
369 /* add the callers window save registers */
370 var->vv.regoff = cd->stackframesize * 8 + s1;
374 } else { /* floating args */
375 if (!md->params[p].inmemory) { /* register arguments */
376 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
377 M_FLTMOVE(s1, var->vv.regoff);
379 } else { /* reg arg -> spilled */
380 M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
383 } else { /* stack arguments */
384 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
385 M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1);
387 } else { /* stack-arg -> spilled */
388 var->vv.regoff = cd->stackframesize * 8 + s1;
397 /* end of header generation */
399 /* create replacement points */
401 REPLACEMENT_POINTS_INIT(cd, jd);
403 /* walk through all basic blocks */
405 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
407 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
409 if (bptr->flags >= BBREACHED) {
411 /* branch resolving */
413 codegen_resolve_branchrefs(cd, bptr);
415 /* handle replacement points */
417 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
420 /* copy interface registers to their destination */
425 #if defined(ENABLE_LSRA)
426 #error XXX LSRA not tested yet
430 src = bptr->invars[len];
431 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
432 /* d = reg_of_var(m, src, REG_ITMP1); */
433 if (!(src->flags & INMEMORY))
437 M_INTMOVE(REG_ITMP1, d);
438 emit_store(jd, NULL, src, d);
445 var = VAR(bptr->invars[len]);
446 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
447 d = codegen_reg_of_var(0, var, REG_ITMP1);
448 M_INTMOVE(REG_ITMP2_XPTR, d);
449 emit_store(jd, NULL, var, d);
452 assert((var->flags & INOUT));
455 #if defined(ENABLE_LSRA)
458 /* walk through all instructions */
462 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
463 if (iptr->line != currentline) {
464 dseg_addlinenumber(cd, iptr->line);
465 currentline = iptr->line;
468 MCODECHECK(64); /* an instruction usually needs < 64 words */
472 case ICMD_INLINE_START:
473 case ICMD_INLINE_END:
476 case ICMD_NOP: /* ... ==> ... */
479 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
481 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
482 emit_nullpointer_check(cd, iptr, s1);
485 /* constant operations ************************************************/
487 case ICMD_ICONST: /* ... ==> ..., constant */
489 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
490 ICONST(d, iptr->sx.val.i);
491 emit_store_dst(jd, iptr, d);
494 case ICMD_LCONST: /* ... ==> ..., constant */
496 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
497 LCONST(d, iptr->sx.val.l);
498 emit_store_dst(jd, iptr, d);
501 case ICMD_FCONST: /* ... ==> ..., constant */
503 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
504 disp = dseg_add_float(cd, iptr->sx.val.f);
505 M_FLD(d, REG_PV, disp);
506 emit_store_dst(jd, iptr, d);
509 case ICMD_DCONST: /* ... ==> ..., constant */
511 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
512 disp = dseg_add_double(cd, iptr->sx.val.d);
513 M_DLD(d, REG_PV, disp);
514 emit_store_dst(jd, iptr, d);
517 case ICMD_ACONST: /* ... ==> ..., constant */
519 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
521 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
522 cr = iptr->sx.val.c.ref;
523 disp = dseg_add_unique_address(cd, cr);
525 codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
527 M_ALD(d, REG_PV, disp);
531 if (iptr->sx.val.anyptr == NULL) {
532 M_INTMOVE(REG_ZERO, d);
535 disp = dseg_add_address(cd, iptr->sx.val.anyptr);
536 M_ALD(d, REG_PV, disp);
539 emit_store_dst(jd, iptr, d);
543 /* load/store/copy/move operations ************************************/
545 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
550 case ICMD_ISTORE: /* ..., value ==> ... */
561 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
566 /* pop/dup/swap operations ********************************************/
568 /* attention: double and longs are only one entry in CACAO ICMDs */
570 case ICMD_POP: /* ..., value ==> ... */
571 case ICMD_POP2: /* ..., value, value ==> ... */
575 /* integer operations *************************************************/
577 case ICMD_INEG: /* ..., value ==> ..., - value */
580 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
581 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
582 M_SUB(REG_ZERO, s1, d);
583 emit_store_dst(jd, iptr, d);
586 case ICMD_I2L: /* ..., value ==> ..., value */
588 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
589 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
591 emit_store_dst(jd, iptr, d);
594 case ICMD_L2I: /* ..., value ==> ..., value */
596 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
597 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
598 M_SRA_IMM(s1, 0, d); /* sign extend upper 32 bits */
599 emit_store_dst(jd, iptr, d);
602 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
604 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
605 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
606 M_SLLX_IMM(s1, 56, d);
607 M_SRAX_IMM( d, 56, d);
608 emit_store_dst(jd, iptr, d);
611 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
613 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
614 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
615 M_SLLX_IMM(s1, 48, d);
616 M_SRLX_IMM( d, 48, d);
617 emit_store_dst(jd, iptr, d);
620 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
622 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
623 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
624 M_SLLX_IMM(s1, 48, d);
625 M_SRAX_IMM( d, 48, d);
626 emit_store_dst(jd, iptr, d);
629 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
632 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
633 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
634 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
636 emit_store_dst(jd, iptr, d);
640 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
641 /* sx.val.i = constant */
643 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
644 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
645 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
646 M_ADD_IMM(s1, iptr->sx.val.i, d);
648 ICONST(REG_ITMP2, iptr->sx.val.i);
649 M_ADD(s1, REG_ITMP2, d);
651 emit_store_dst(jd, iptr, d);
654 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
655 /* sx.val.l = constant */
657 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
658 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
659 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
660 M_ADD_IMM(s1, iptr->sx.val.l, d);
662 LCONST(REG_ITMP2, iptr->sx.val.l);
663 M_ADD(s1, REG_ITMP2, d);
665 emit_store_dst(jd, iptr, d);
668 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
671 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
672 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
673 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
675 emit_store_dst(jd, iptr, d);
678 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
679 /* sx.val.i = constant */
681 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
682 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
683 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
684 M_SUB_IMM(s1, iptr->sx.val.i, d);
686 ICONST(REG_ITMP2, iptr->sx.val.i);
687 M_SUB(s1, REG_ITMP2, d);
689 emit_store_dst(jd, iptr, d);
692 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
693 /* sx.val.l = constant */
695 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
696 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
697 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
698 M_SUB_IMM(s1, iptr->sx.val.l, d);
700 LCONST(REG_ITMP2, iptr->sx.val.l);
701 M_SUB(s1, REG_ITMP2, d);
703 emit_store_dst(jd, iptr, d);
706 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
709 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
710 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
711 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
713 emit_store_dst(jd, iptr, d);
716 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
717 /* sx.val.i = constant */
719 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
720 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
721 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
722 M_MULX_IMM(s1, iptr->sx.val.i, d);
724 ICONST(REG_ITMP2, iptr->sx.val.i);
725 M_MULX(s1, REG_ITMP2, d);
727 emit_store_dst(jd, iptr, d);
730 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
731 /* sx.val.l = constant */
733 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
734 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
735 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
736 M_MULX_IMM(s1, iptr->sx.val.l, d);
738 LCONST(REG_ITMP2, iptr->sx.val.l);
739 M_MULX(s1, REG_ITMP2, d);
741 emit_store_dst(jd, iptr, d);
744 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
745 /* XXX could also clear Y and use 32bit div */
746 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
747 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
748 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
749 emit_arithmetic_check(cd, iptr, s2);
751 /* XXX trim s2 like s1 ? */
753 emit_store_dst(jd, iptr, d);
756 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
758 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
759 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
760 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
761 emit_arithmetic_check(cd, iptr, s2);
763 emit_store_dst(jd, iptr, d);
766 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
768 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
769 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
770 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
771 emit_arithmetic_check(cd, iptr, s2);
773 /* XXX trim s2 like s1 ? */
774 M_DIVX(s1, s2, REG_ITMP3);
775 M_MULX(s2, REG_ITMP3, REG_ITMP3);
776 M_SUB(s1, REG_ITMP3, d);
777 emit_store_dst(jd, iptr, d);
780 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
782 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
783 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
784 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
785 emit_arithmetic_check(cd, iptr, s2);
786 M_DIVX(s1, s2, REG_ITMP3);
787 M_MULX(s2, REG_ITMP3, REG_ITMP3);
788 M_SUB(s1, REG_ITMP3, d);
789 emit_store_dst(jd, iptr, d);
792 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
793 case ICMD_LDIVPOW2: /* val.i = constant */
795 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
796 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
797 M_SRAX_IMM(s1, 63, REG_ITMP2);
798 M_SRLX_IMM(REG_ITMP2, 64 - iptr->sx.val.i, REG_ITMP2);
799 M_ADD(s1, REG_ITMP2, REG_ITMP2);
800 M_SRAX_IMM(REG_ITMP2, iptr->sx.val.i, d);
801 emit_store_dst(jd, iptr, d);
804 case ICMD_ISHL: /* ..., 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);
810 emit_store_dst(jd, iptr, d);
813 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
815 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
816 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
817 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
819 emit_store_dst(jd, iptr, d);
822 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
823 /* val.i = constant */
825 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
826 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
827 M_SLL_IMM(s1, iptr->sx.val.i, d);
828 emit_store_dst(jd, iptr, d);
831 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
832 /* val.i = constant */
834 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
835 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
836 M_SLLX_IMM(s1, iptr->sx.val.i, d);
837 emit_store_dst(jd, iptr, d);
840 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
842 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
843 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
844 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
846 emit_store_dst(jd, iptr, d);
849 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
850 /* sx.val.i = constant */
852 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
853 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
854 M_SRA_IMM(s1, iptr->sx.val.i, d);
855 emit_store_dst(jd, iptr, d);
858 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
860 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
861 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
862 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
864 emit_store_dst(jd, iptr, d);
867 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
868 /* sx.val.i = constant */
870 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
871 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
872 M_SRL_IMM(s1, iptr->sx.val.i, d);
873 emit_store_dst(jd, iptr, d);
876 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
878 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
879 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
880 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
882 emit_store_dst(jd, iptr, d);
885 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
886 /* sx.val.i = constant */
888 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
889 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
890 M_SRAX_IMM(s1, iptr->sx.val.i, d);
891 emit_store_dst(jd, iptr, d);
894 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
896 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
897 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
898 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
900 emit_store_dst(jd, iptr, d);
903 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
904 /* sx.val.i = constant */
906 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
907 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
908 M_SRLX_IMM(s1, iptr->sx.val.i, d);
909 emit_store_dst(jd, iptr, d);
912 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
915 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
916 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
917 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
919 emit_store_dst(jd, iptr, d);
922 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
923 /* sx.val.i = constant */
925 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
926 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
927 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
928 M_AND_IMM(s1, iptr->sx.val.i, d);
930 ICONST(REG_ITMP2, iptr->sx.val.i);
931 M_AND(s1, REG_ITMP2, d);
933 emit_store_dst(jd, iptr, d);
936 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
937 /* sx.val.i = constant */
938 /* constant is actually constant - 1 */
940 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
941 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
943 M_MOV(s1, REG_ITMP1);
946 M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
947 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
948 M_AND_IMM(s1, iptr->sx.val.i, d);
951 M_SUB(REG_ZERO, s1, d);
952 M_AND_IMM(d, iptr->sx.val.i, d);
954 ICONST(REG_ITMP2, iptr->sx.val.i);
955 M_AND(s1, REG_ITMP2, d);
958 M_SUB(REG_ZERO, s1, d);
959 M_AND(d, REG_ITMP2, d);
961 M_SUB(REG_ZERO, d, d);
962 emit_store_dst(jd, iptr, d);
965 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
966 /* sx.val.l = constant */
968 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
969 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
970 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
971 M_AND_IMM(s1, iptr->sx.val.l, d);
973 LCONST(REG_ITMP2, iptr->sx.val.l);
974 M_AND(s1, REG_ITMP2, d);
976 emit_store_dst(jd, iptr, d);
979 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
980 /* sx.val.l = constant */
982 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
983 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
985 M_MOV(s1, REG_ITMP1);
988 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
989 M_AND_IMM(s1, iptr->sx.val.l, d);
992 M_SUB(REG_ZERO, s1, d);
993 M_AND_IMM(d, iptr->sx.val.l, d);
995 LCONST(REG_ITMP2, iptr->sx.val.l);
996 M_AND(s1, REG_ITMP2, d);
999 M_SUB(REG_ZERO, s1, d);
1000 M_AND(d, REG_ITMP2, d);
1002 M_SUB(REG_ZERO, d, d);
1003 emit_store_dst(jd, iptr, d);
1006 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1009 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1010 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1011 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1013 emit_store_dst(jd, iptr, d);
1016 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1017 /* sx.val.i = constant */
1019 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1020 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1021 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1022 M_OR_IMM(s1, iptr->sx.val.i, d);
1024 ICONST(REG_ITMP2, iptr->sx.val.i);
1025 M_OR(s1, REG_ITMP2, d);
1027 emit_store_dst(jd, iptr, d);
1030 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1031 /* sx.val.l = constant */
1033 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1034 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1035 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1036 M_OR_IMM(s1, iptr->sx.val.l, d);
1038 LCONST(REG_ITMP2, iptr->sx.val.l);
1039 M_OR(s1, REG_ITMP2, d);
1041 emit_store_dst(jd, iptr, d);
1044 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1047 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1048 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1049 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1051 emit_store_dst(jd, iptr, d);
1054 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1055 /* sx.val.i = constant */
1057 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1058 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1059 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1060 M_XOR_IMM(s1, iptr->sx.val.i, d);
1062 ICONST(REG_ITMP2, iptr->sx.val.i);
1063 M_XOR(s1, REG_ITMP2, d);
1065 emit_store_dst(jd, iptr, d);
1068 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1069 /* sx.val.l = constant */
1071 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1072 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1073 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1074 M_XOR_IMM(s1, iptr->sx.val.l, d);
1076 LCONST(REG_ITMP2, iptr->sx.val.l);
1077 M_XOR(s1, REG_ITMP2, d);
1079 emit_store_dst(jd, iptr, d);
1083 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1085 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1086 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1087 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1090 M_XCMOVLT_IMM(-1, d);
1091 M_XCMOVGT_IMM(1, d);
1092 emit_store_dst(jd, iptr, d);
1096 /* floating operations ************************************************/
1098 case ICMD_FNEG: /* ..., value ==> ..., - value */
1100 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1101 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1103 emit_store_dst(jd, iptr, d);
1106 case ICMD_DNEG: /* ..., value ==> ..., - value */
1108 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1109 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1111 emit_store_dst(jd, iptr, d);
1114 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1116 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1117 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1118 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1120 emit_store_dst(jd, iptr, d);
1123 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1125 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1126 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1127 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1129 emit_store_dst(jd, iptr, d);
1132 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1134 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1135 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1136 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1138 emit_store_dst(jd, iptr, d);
1141 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1143 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1144 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1145 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1147 emit_store_dst(jd, iptr, d);
1150 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1152 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1153 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1154 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1156 emit_store_dst(jd, iptr, d);
1159 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1161 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1162 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1163 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1165 emit_store_dst(jd, iptr, d);
1168 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1170 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1171 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1172 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1174 emit_store_dst(jd, iptr, d);
1177 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1179 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1180 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1181 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1183 emit_store_dst(jd, iptr, d);
1187 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1188 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1189 disp = dseg_add_unique_float(cd, 0.0);
1190 M_IST (s1, REG_PV_CALLEE, disp);
1191 M_FLD (d, REG_PV_CALLEE, disp);
1192 M_CVTIF (d, d); /* rd gets translated to double target register */
1193 emit_store_dst(jd, iptr, d);
1197 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1198 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1199 disp = dseg_add_unique_float(cd, 0.0);
1200 M_IST(s1, REG_PV_CALLEE, disp);
1201 M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
1202 M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
1203 emit_store_dst(jd, iptr, d);
1207 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1208 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1209 disp = dseg_add_unique_double(cd, 0.0);
1210 M_STX(s1, REG_PV_CALLEE, disp);
1211 M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
1212 M_CVTLF(REG_FTMP3, d);
1213 emit_store_dst(jd, iptr, d);
1217 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1218 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1219 disp = dseg_add_unique_double(cd, 0.0);
1220 M_STX(s1, REG_PV_CALLEE, disp);
1221 M_DLD(d, REG_PV_CALLEE, disp);
1223 emit_store_dst(jd, iptr, d);
1226 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1227 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1228 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1229 disp = dseg_add_unique_float(cd, 0.0);
1231 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1234 M_MOV(REG_ZERO, d); /* delay slot */
1236 M_CVTFI(s1, REG_FTMP2);
1237 M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
1238 M_ILD(d, REG_PV, disp);
1239 emit_store_dst(jd, iptr, d);
1243 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1244 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1245 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1246 disp = dseg_add_unique_float(cd, 0.0);
1248 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1251 M_MOV(REG_ZERO, d); /* delay slot */
1253 M_CVTDI(s1, REG_FTMP2);
1254 M_FST(REG_FTMP2, REG_PV, disp);
1255 M_ILD(d, REG_PV, disp);
1256 emit_store_dst(jd, iptr, d);
1259 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1260 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1261 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1262 disp = dseg_add_unique_double(cd, 0.0);
1264 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1267 M_MOV(REG_ZERO, d); /* delay slot */
1269 M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1270 M_DST(REG_FTMP2, REG_PV, disp);
1271 M_LDX(d, REG_PV, disp);
1272 emit_store_dst(jd, iptr, d);
1275 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1276 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1277 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1278 disp = dseg_add_unique_double(cd, 0.0);
1280 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1283 M_MOV(REG_ZERO, d); /* delay slot */
1285 M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1286 M_DST(REG_FTMP2, REG_PV, disp);
1287 M_LDX(d, REG_PV, disp);
1288 emit_store_dst(jd, iptr, d);
1291 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1293 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1294 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1296 emit_store_dst(jd, iptr, d);
1299 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1301 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1302 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1304 emit_store_dst(jd, iptr, d);
1307 /* XXX merge F/D versions? only compare instr. is different */
1308 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1310 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1311 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1312 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1314 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1315 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1316 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1317 emit_store_dst(jd, iptr, d);
1320 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1322 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1323 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1324 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1326 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1327 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1328 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1329 emit_store_dst(jd, iptr, d);
1332 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1334 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1335 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1336 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1338 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1339 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1340 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1341 emit_store_dst(jd, iptr, d);
1344 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1346 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1347 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1348 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1350 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1351 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1352 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1353 emit_store_dst(jd, iptr, d);
1357 /* memory operations **************************************************/
1359 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1361 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1362 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1363 emit_nullpointer_check(cd, iptr, s1);
1364 M_ILD(d, s1, OFFSET(java_array_t, size));
1365 emit_store_dst(jd, iptr, d);
1368 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1370 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1371 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1372 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1373 /* implicit null-pointer check */
1374 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1375 M_AADD(s2, s1, REG_ITMP3);
1376 M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray_t, data[0]));
1377 emit_store_dst(jd, iptr, d);
1380 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1382 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1383 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1384 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1385 /* implicit null-pointer check */
1386 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1387 M_AADD(s2, s1, REG_ITMP3);
1388 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1389 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray_t, data[0]));
1390 emit_store_dst(jd, iptr, d);
1393 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1395 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1396 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1397 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1398 /* implicit null-pointer check */
1399 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1400 M_AADD(s2, s1, REG_ITMP3);
1401 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1402 M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray_t, data[0]));
1403 emit_store_dst(jd, iptr, d);
1406 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1408 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1409 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1410 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1411 /* implicit null-pointer check */
1412 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1413 M_ASLL_IMM(s2, 2, REG_ITMP3);
1414 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1415 M_ILD(d, REG_ITMP3, OFFSET(java_intarray_t, data[0]));
1416 emit_store_dst(jd, iptr, d);
1419 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1421 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1422 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1423 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1424 /* implicit null-pointer check */
1425 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1426 M_ASLL_IMM(s2, 3, REG_ITMP3);
1427 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1428 M_LDX(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1429 emit_store_dst(jd, iptr, d);
1432 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1434 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1435 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1436 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1437 /* implicit null-pointer check */
1438 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1439 M_ASLL_IMM(s2, 2, REG_ITMP3);
1440 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1441 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray_t, data[0]));
1442 emit_store_dst(jd, iptr, d);
1445 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1447 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1448 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1449 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1450 /* implicit null-pointer check */
1451 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1452 M_ASLL_IMM(s2, 3, REG_ITMP3);
1453 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1454 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1455 emit_store_dst(jd, iptr, d);
1458 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1460 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1461 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1462 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1463 /* implicit null-pointer check */
1464 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1465 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1466 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1467 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray_t, data[0]));
1468 emit_store_dst(jd, iptr, d);
1472 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1474 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1475 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1476 /* implicit null-pointer check */
1477 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1478 M_AADD(s2, s1, REG_ITMP1);
1479 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1480 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1483 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1484 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1486 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1487 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1488 /* implicit null-pointer check */
1489 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1490 M_AADD(s2, s1, REG_ITMP1);
1491 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1492 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1493 M_SST(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1496 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1498 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1499 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1500 /* implicit null-pointer check */
1501 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1502 M_ASLL_IMM(s2, 2, REG_ITMP2);
1503 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1504 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1505 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1508 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1510 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1511 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1512 /* implicit null-pointer check */
1513 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1514 M_ASLL_IMM(s2, 3, REG_ITMP2);
1515 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1516 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1517 M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1520 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1522 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1523 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1524 /* implicit null-pointer check */
1525 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1526 M_ASLL_IMM(s2, 2, REG_ITMP2);
1527 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1528 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1529 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1532 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1534 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1535 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1536 /* implicit null-pointer check */
1537 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1538 M_ASLL_IMM(s2, 3, REG_ITMP2);
1539 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1540 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1541 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1545 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1547 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1548 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1549 /* implicit null-pointer check */
1550 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1551 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1553 M_MOV(s1, REG_OUT0);
1554 M_MOV(s3, REG_OUT1);
1555 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1556 M_ALD(REG_ITMP3, REG_PV, disp);
1557 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
1559 emit_arraystore_check(cd, iptr);
1561 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1562 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1563 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1564 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1565 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1566 /* implicit null-pointer check */
1567 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1571 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1573 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1574 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1575 /* implicit null-pointer check */
1576 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1577 M_AADD(s2, s1, REG_ITMP1);
1578 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1581 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1582 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1584 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1585 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1586 /* implicit null-pointer check */
1587 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1588 M_AADD(s2, s1, REG_ITMP1);
1589 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1590 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1593 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1595 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1596 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1597 /* implicit null-pointer check */
1598 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1599 M_ASLL_IMM(s2, 2, REG_ITMP2);
1600 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1601 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1604 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1606 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1607 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1608 /* implicit null-pointer check */
1609 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1610 M_ASLL_IMM(s2, 3, REG_ITMP2);
1611 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1612 M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1615 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1617 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1618 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1619 /* implicit null-pointer check */
1620 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1621 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1622 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1623 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1627 case ICMD_GETSTATIC: /* ... ==> ..., value */
1629 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1630 uf = iptr->sx.s23.s3.uf;
1631 fieldtype = uf->fieldref->parseddesc.fd->type;
1632 disp = dseg_add_unique_address(cd, uf);
1634 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1637 fi = iptr->sx.s23.s3.fmiref->p.field;
1638 fieldtype = fi->type;
1639 disp = dseg_add_address(cd, fi->value);
1641 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1642 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1645 M_ALD(REG_ITMP1, REG_PV, disp);
1647 switch (fieldtype) {
1649 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1650 M_ILD_INTERN(d, REG_ITMP1, 0);
1653 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1654 M_LDX_INTERN(d, REG_ITMP1, 0);
1657 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1658 M_ALD_INTERN(d, REG_ITMP1, 0);
1661 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1662 M_FLD_INTERN(d, REG_ITMP1, 0);
1665 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1666 M_DLD_INTERN(d, REG_ITMP1, 0);
1669 emit_store_dst(jd, iptr, d);
1672 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1674 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1675 uf = iptr->sx.s23.s3.uf;
1676 fieldtype = uf->fieldref->parseddesc.fd->type;
1677 disp = dseg_add_unique_address(cd, uf);
1679 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1682 fi = iptr->sx.s23.s3.fmiref->p.field;
1683 fieldtype = fi->type;
1684 disp = dseg_add_address(cd, fi->value);
1686 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1687 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1690 M_ALD(REG_ITMP1, REG_PV, disp);
1692 switch (fieldtype) {
1694 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1695 M_IST_INTERN(s1, REG_ITMP1, 0);
1698 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1699 M_STX_INTERN(s1, REG_ITMP1, 0);
1702 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1703 M_AST_INTERN(s1, REG_ITMP1, 0);
1706 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1707 M_FST_INTERN(s1, REG_ITMP1, 0);
1710 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1711 M_DST_INTERN(s1, REG_ITMP1, 0);
1716 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1717 /* val = value (in current instruction) */
1718 /* following NOP) */
1720 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1721 uf = iptr->sx.s23.s3.uf;
1722 fieldtype = uf->fieldref->parseddesc.fd->type;
1723 disp = dseg_add_unique_address(cd, uf);
1725 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1728 fi = iptr->sx.s23.s3.fmiref->p.field;
1729 fieldtype = fi->type;
1730 disp = dseg_add_address(cd, fi->value);
1732 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1733 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1736 M_ALD(REG_ITMP1, REG_PV, disp);
1738 switch (fieldtype) {
1740 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1743 M_STX_INTERN(REG_ZERO, REG_ITMP1, 0);
1746 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1749 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1752 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1758 case ICMD_GETFIELD: /* ... ==> ..., value */
1760 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1761 emit_nullpointer_check(cd, iptr, s1);
1763 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1764 uf = iptr->sx.s23.s3.uf;
1766 fieldtype = uf->fieldref->parseddesc.fd->type;
1769 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1772 fi = iptr->sx.s23.s3.fmiref->p.field;
1773 fieldtype = fi->type;
1777 switch (fieldtype) {
1779 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1783 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1787 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1791 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1795 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1802 emit_store_dst(jd, iptr, d);
1805 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1807 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1808 emit_nullpointer_check(cd, iptr, s1);
1810 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1811 uf = iptr->sx.s23.s3.uf;
1812 fieldtype = uf->fieldref->parseddesc.fd->type;
1817 fi = iptr->sx.s23.s3.fmiref->p.field;
1818 fieldtype = fi->type;
1822 if (IS_INT_LNG_TYPE(fieldtype))
1823 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1825 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1827 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1828 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1830 switch (fieldtype) {
1832 M_IST(s2, s1, disp);
1835 M_STX(s2, s1, disp);
1838 M_AST(s2, s1, disp);
1841 M_FST(s2, s1, disp);
1844 M_DST(s2, s1, disp);
1852 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
1853 /* val = value (in current instruction) */
1854 /* following NOP) */
1856 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1857 emit_nullpointer_check(cd, iptr, s1);
1859 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1860 unresolved_field *uf = iptr->sx.s23.s3.uf;
1862 fieldtype = uf->fieldref->parseddesc.fd->type;
1864 codegen_addpatchref(cd, PATCHER_get_putfield,
1867 if (opt_showdisassemble) {
1875 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1877 fieldtype = fi->type;
1883 switch (fieldtype) {
1885 M_IST(REG_ZERO, s1, disp);
1888 M_STX(REG_ZERO, s1, disp);
1891 M_AST(REG_ZERO, s1, disp);
1894 M_FST(REG_ZERO, s1, disp);
1897 M_DST(REG_ZERO, s1, disp);
1903 /* branch operations **************************************************/
1905 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1907 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1908 M_INTMOVE(s1, REG_ITMP2_XPTR);
1910 #ifdef ENABLE_VERIFIER
1911 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1912 unresolved_class *uc = iptr->sx.s23.s2.uc;
1914 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
1916 #endif /* ENABLE_VERIFIER */
1918 disp = dseg_add_functionptr(cd, asm_handle_exception);
1919 M_ALD(REG_ITMP1, REG_PV, disp);
1920 M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
1922 M_NOP; /* nop ensures that XPC is less than the end */
1923 /* of basic block */
1927 case ICMD_GOTO: /* ... ==> ... */
1928 case ICMD_RET: /* ... ==> ... */
1930 emit_br(cd, iptr->dst.block);
1934 case ICMD_JSR: /* ... ==> ... */
1936 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1940 case ICMD_IFNULL: /* ..., value ==> ... */
1941 case ICMD_IFNONNULL:
1943 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1944 emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
1947 /* Note: int compares must not branch on the register directly. */
1948 /* Reason is, that register content is not 32-bit clean. */
1950 case ICMD_IFEQ: /* ..., value ==> ... */
1952 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1954 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1955 M_CMP_IMM(s1, iptr->sx.val.i);
1958 ICONST(REG_ITMP2, iptr->sx.val.i);
1959 M_CMP(s1, REG_ITMP2);
1961 emit_beq(cd, iptr->dst.block);
1964 case ICMD_IFLT: /* ..., value ==> ... */
1966 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1968 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1969 M_CMP_IMM(s1, iptr->sx.val.i);
1972 ICONST(REG_ITMP2, iptr->sx.val.i);
1973 M_CMP(s1, REG_ITMP2);
1975 emit_blt(cd, iptr->dst.block);
1978 case ICMD_IFLE: /* ..., value ==> ... */
1980 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1982 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1983 M_CMP_IMM(s1, iptr->sx.val.i);
1986 ICONST(REG_ITMP2, iptr->sx.val.i);
1987 M_CMP(s1, REG_ITMP2);
1989 emit_ble(cd, iptr->dst.block);
1992 case ICMD_IFNE: /* ..., value ==> ... */
1994 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1996 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1997 M_CMP_IMM(s1, iptr->sx.val.i);
2000 ICONST(REG_ITMP2, iptr->sx.val.i);
2001 M_CMP(s1, REG_ITMP2);
2003 emit_bne(cd, iptr->dst.block);
2006 case ICMD_IFGT: /* ..., value ==> ... */
2008 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2010 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2011 M_CMP_IMM(s1, iptr->sx.val.i);
2014 ICONST(REG_ITMP2, iptr->sx.val.i);
2015 M_CMP(s1, REG_ITMP2);
2017 emit_bgt(cd, iptr->dst.block);
2020 case ICMD_IFGE: /* ..., value ==> ... */
2022 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2024 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2025 M_CMP_IMM(s1, iptr->sx.val.i);
2028 ICONST(REG_ITMP2, iptr->sx.val.i);
2029 M_CMP(s1, REG_ITMP2);
2031 emit_bge(cd, iptr->dst.block);
2034 case ICMD_IF_LEQ: /* ..., value ==> ... */
2036 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2037 if (iptr->sx.val.l == 0)
2038 emit_beqz(cd, iptr->dst.block, s1);
2040 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2041 M_CMP_IMM(s1, iptr->sx.val.l);
2044 LCONST(REG_ITMP2, iptr->sx.val.l);
2045 M_CMP(s1, REG_ITMP2);
2047 emit_beq_xcc(cd, iptr->dst.block);
2051 case ICMD_IF_LLT: /* ..., value ==> ... */
2053 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2054 if (iptr->sx.val.l == 0)
2055 emit_bltz(cd, iptr->dst.block, s1);
2057 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2058 M_CMP_IMM(s1, iptr->sx.val.l);
2061 LCONST(REG_ITMP2, iptr->sx.val.l);
2062 M_CMP(s1, REG_ITMP2);
2064 emit_blt_xcc(cd, iptr->dst.block);
2068 case ICMD_IF_LLE: /* ..., value ==> ... */
2070 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2071 if (iptr->sx.val.l == 0)
2072 emit_blez(cd, iptr->dst.block, s1);
2074 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2075 M_CMP_IMM(s1, iptr->sx.val.l);
2078 LCONST(REG_ITMP2, iptr->sx.val.l);
2079 M_CMP(s1, REG_ITMP2);
2081 emit_ble_xcc(cd, iptr->dst.block);
2085 case ICMD_IF_LNE: /* ..., value ==> ... */
2087 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2088 if (iptr->sx.val.l == 0)
2089 emit_bnez(cd, iptr->dst.block, s1);
2091 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2092 M_CMP_IMM(s1, iptr->sx.val.l);
2095 LCONST(REG_ITMP2, iptr->sx.val.l);
2096 M_CMP(s1, REG_ITMP2);
2098 emit_bne_xcc(cd, iptr->dst.block);
2102 case ICMD_IF_LGT: /* ..., value ==> ... */
2104 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2105 if (iptr->sx.val.l == 0)
2106 emit_bgtz(cd, iptr->dst.block, s1);
2108 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2109 M_CMP_IMM(s1, iptr->sx.val.l);
2112 LCONST(REG_ITMP2, iptr->sx.val.l);
2113 M_CMP(s1, REG_ITMP2);
2115 emit_bgt_xcc(cd, iptr->dst.block);
2119 case ICMD_IF_LGE: /* ..., value ==> ... */
2121 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2122 if (iptr->sx.val.l == 0)
2123 emit_bgez(cd, iptr->dst.block, s1);
2125 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2126 M_CMP_IMM(s1, iptr->sx.val.l);
2129 LCONST(REG_ITMP2, iptr->sx.val.l);
2130 M_CMP(s1, REG_ITMP2);
2132 emit_bge_xcc(cd, iptr->dst.block);
2137 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2138 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2140 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2141 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2143 emit_beq_xcc(cd, iptr->dst.block);
2146 case ICMD_IF_ICMPEQ: /* 32-bit compare */
2148 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2149 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2151 emit_beq(cd, iptr->dst.block);
2154 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
2155 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2157 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2158 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2160 emit_bne_xcc(cd, iptr->dst.block);
2163 case ICMD_IF_ICMPNE: /* 32-bit compare */
2165 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2166 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2168 emit_bne(cd, iptr->dst.block);
2171 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2173 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2174 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2176 emit_blt_xcc(cd, iptr->dst.block);
2179 case ICMD_IF_ICMPLT: /* 32-bit compare */
2181 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2182 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2184 emit_blt(cd, iptr->dst.block);
2187 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2189 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2190 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2192 emit_bgt_xcc(cd, iptr->dst.block);
2195 case ICMD_IF_ICMPGT: /* 32-bit compare */
2197 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2198 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2200 emit_bgt(cd, iptr->dst.block);
2203 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2205 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2206 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2208 emit_ble_xcc(cd, iptr->dst.block);
2211 case ICMD_IF_ICMPLE: /* 32-bit compare */
2213 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2214 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2216 emit_ble(cd, iptr->dst.block);
2220 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2222 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2223 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2225 emit_bge_xcc(cd, iptr->dst.block);
2228 case ICMD_IF_ICMPGE: /* 32-bit compare */
2230 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2231 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2233 emit_bge(cd, iptr->dst.block);
2237 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2240 REPLACEMENT_POINT_RETURN(cd, iptr);
2242 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2243 M_INTMOVE(s1, REG_RESULT_CALLEE);
2244 goto nowperformreturn;
2246 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2248 REPLACEMENT_POINT_RETURN(cd, iptr);
2250 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2251 M_INTMOVE(s1, REG_RESULT_CALLEE);
2253 #ifdef ENABLE_VERIFIER
2254 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2255 unresolved_class *uc = iptr->sx.s23.s2.uc;
2257 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2259 #endif /* ENABLE_VERIFIER */
2260 goto nowperformreturn;
2262 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2265 REPLACEMENT_POINT_RETURN(cd, iptr);
2267 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2268 M_DBLMOVE(s1, REG_FRESULT);
2269 goto nowperformreturn;
2271 case ICMD_RETURN: /* ... ==> ... */
2273 REPLACEMENT_POINT_RETURN(cd, iptr);
2279 p = cd->stackframesize;
2281 #if !defined(NDEBUG)
2282 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2283 emit_verbosecall_exit(jd);
2286 #if defined(ENABLE_THREADS)
2287 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2288 /* XXX jit-c-call */
2289 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2290 M_ALD(REG_ITMP3, REG_PV, disp);
2292 /* we need to save fp return value (int saved by window) */
2294 switch (iptr->opc) {
2297 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
2298 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2299 M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2301 /* restore the fp return value */
2303 M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
2309 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2310 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2321 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
2327 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2330 branch_target_t *table;
2332 table = iptr->dst.table;
2334 l = iptr->sx.s23.s2.tablelow;
2335 i = iptr->sx.s23.s3.tablehigh;
2337 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2339 M_INTMOVE(s1, REG_ITMP1);
2341 else if (-l >= 4096 && -l <= 4095) {
2342 M_ADD_IMM(s1, -l, REG_ITMP1);
2345 ICONST(REG_ITMP2, l);
2346 M_SUB(s1, REG_ITMP2, REG_ITMP1);
2349 i = i - l + 1; /* number of targets (>0) */
2355 M_CMP_IMM(REG_ITMP1, i - 1);
2358 ICONST(REG_ITMP2, i - 1);
2359 M_CMP(REG_ITMP1, REG_ITMP2);
2361 emit_bugt(cd, table[0].block); /* default target */
2363 /* build jump table top down and use address of lowest entry */
2368 dseg_add_target(cd, table->block);
2373 /* length of dataseg after last dseg_addtarget is used by load */
2375 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
2376 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2377 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2378 M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
2383 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2386 lookup_target_t *lookup;
2388 lookup = iptr->dst.lookup;
2390 i = iptr->sx.s23.s2.lookupcount;
2392 MCODECHECK((i<<2)+8);
2393 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2396 if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
2397 M_CMP_IMM(s1, lookup->value);
2399 ICONST(REG_ITMP2, lookup->value);
2400 M_CMP(s1, REG_ITMP2);
2402 emit_beq(cd, lookup->target.block);
2406 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2412 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
2414 REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
2416 bte = iptr->sx.s23.s3.bte;
2419 /* XXX: builtin calling with stack arguments not implemented */
2420 assert(md->paramcount <= 5 && md->argfltreguse <= 16);
2422 s3 = md->paramcount;
2424 MCODECHECK((s3 << 1) + 64);
2426 #ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
2428 /* copy float arguments according to ABI convention */
2430 int num_fltregargs = 0;
2431 int fltregarg_inswap[16];
2433 for (s3 = s3 - 1; s3 >= 0; s3--) {
2434 var = VAR(iptr->sx.s23.s2.args[s3]);
2436 if (IS_FLT_DBL_TYPE(var->type)) {
2437 if (!md->params[s3].inmemory) {
2438 s1 = s3; /*native flt args use argument index directly*/
2439 d = emit_load(jd, iptr, var, REG_FTMP1);
2442 fltregarg_inswap[num_fltregargs] = s1;
2444 /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
2453 /* move swapped float args to target regs */
2454 for (i = 0; i < num_fltregargs; i++) {
2455 s1 = fltregarg_inswap[i];
2456 M_DMOV(s1 + 16, s1);
2457 /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
2461 assert(md->argfltreguse == 0);
2466 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2467 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2468 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2469 case ICMD_INVOKEINTERFACE:
2471 REPLACEMENT_POINT_INVOKE(cd, iptr);
2473 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2475 um = iptr->sx.s23.s3.um;
2476 md = um->methodref->parseddesc.md;
2479 lm = iptr->sx.s23.s3.fmiref->p.method;
2481 md = lm->parseddesc;
2485 s3 = md->paramcount;
2487 MCODECHECK((s3 << 1) + 64);
2489 /* copy arguments to registers or stack location */
2491 for (s3 = s3 - 1; s3 >= 0; s3--) {
2492 var = VAR(iptr->sx.s23.s2.args[s3]);
2493 d = md->params[s3].regoff;
2495 if (var->flags & PREALLOC)
2498 if (IS_INT_LNG_TYPE(var->type)) {
2499 if (!md->params[s3].inmemory) {
2500 s1 = emit_load(jd, iptr, var, d);
2504 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2505 M_STX(s1, REG_SP, JITSTACK + d);
2509 #ifdef BUILTIN_FLOAT_ARGS
2510 if (iptr->opc == ICMD_BUILTIN)
2514 if (!md->params[s3].inmemory) {
2515 s1 = emit_load(jd, iptr, var, d);
2516 if (IS_2_WORD_TYPE(var->type))
2522 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2523 M_DST(s1, REG_SP, JITSTACK + d);
2528 switch (iptr->opc) {
2530 if (bte->stub == NULL) {
2531 disp = dseg_add_functionptr(cd, bte->fp);
2534 disp = dseg_add_functionptr(cd, bte->stub);
2537 M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
2539 /* XXX jit-c-call */
2540 /* generate the actual call */
2542 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2544 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2545 REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
2546 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2547 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2548 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2550 emit_exception_check(cd, iptr);
2551 if (md->returntype.type == TYPE_FLT) {
2552 /* special handling for float return value in %f0 */
2557 case ICMD_INVOKESPECIAL:
2558 emit_nullpointer_check(cd, iptr, REG_OUT0);
2561 case ICMD_INVOKESTATIC:
2563 disp = dseg_add_unique_address(cd, NULL);
2565 codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
2569 disp = dseg_add_address(cd, lm->stubroutine);
2571 M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
2573 /* generate the actual call */
2575 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2577 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2578 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2579 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2580 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2583 case ICMD_INVOKEVIRTUAL:
2584 emit_nullpointer_check(cd, iptr, REG_OUT0);
2587 codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
2592 s1 = OFFSET(vftbl_t, table[0]) +
2593 sizeof(methodptr) * lm->vftblindex;
2595 /* implicit null-pointer check */
2596 M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
2597 M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
2599 /* generate the actual call */
2601 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2603 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2604 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2605 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2606 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2609 case ICMD_INVOKEINTERFACE:
2610 emit_nullpointer_check(cd, iptr, REG_OUT0);
2613 codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
2619 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2620 sizeof(methodptr*) * lm->class->index;
2622 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2625 /* implicit null-pointer check */
2626 M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
2627 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2628 M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
2630 /* generate the actual call */
2632 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2634 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2635 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2636 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2637 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2641 /* store return value */
2643 d = md->returntype.type;
2645 if (d != TYPE_VOID) {
2646 if (IS_INT_LNG_TYPE(d)) {
2647 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2648 M_INTMOVE(REG_RESULT_CALLER, s1);
2651 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2652 if (IS_2_WORD_TYPE(d)) {
2653 M_DBLMOVE(REG_FRESULT, s1);
2655 M_FLTMOVE(REG_FRESULT, s1);
2658 emit_store_dst(jd, iptr, s1);
2663 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2664 /* val.a: (classinfo*) superclass */
2666 /* superclass is an interface:
2668 * OK if ((sub == NULL) ||
2669 * (sub->vftbl->interfacetablelength > super->index) &&
2670 * (sub->vftbl->interfacetable[-super->index] != NULL));
2672 * superclass is a class:
2674 * OK if ((sub == NULL) || (0
2675 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2676 * super->vftbl->diffvall));
2679 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2683 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2688 super = iptr->sx.s23.s3.c.cls;
2689 superindex = super->index;
2692 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2693 CODEGEN_CRITICAL_SECTION_NEW;
2695 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2697 /* if class is not resolved, check which code to call */
2699 if (super == NULL) {
2700 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2702 cr = iptr->sx.s23.s3.c.ref;
2703 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2705 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2708 M_ILD(REG_ITMP2, REG_PV, disp);
2709 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2710 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
2713 /* interface checkcast code */
2715 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2716 if (super == NULL) {
2717 cr = iptr->sx.s23.s3.c.ref;
2719 codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
2723 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2726 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2727 M_ILD(REG_ITMP3, REG_ITMP2,
2728 OFFSET(vftbl_t, interfacetablelength));
2729 M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
2730 emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
2732 M_ALD(REG_ITMP3, REG_ITMP2,
2733 OFFSET(vftbl_t, interfacetable[0]) -
2734 superindex * sizeof(methodptr*));
2735 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
2738 emit_label_br(cd, BRANCH_LABEL_4);
2740 emit_label(cd, BRANCH_LABEL_3);
2743 /* class checkcast code */
2745 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2746 if (super == NULL) {
2747 emit_label(cd, BRANCH_LABEL_2);
2749 cr = iptr->sx.s23.s3.c.ref;
2750 disp = dseg_add_unique_address(cd, NULL);
2752 codegen_add_patch_ref(cd,
2753 PATCHER_checkcast_instanceof_class,
2757 disp = dseg_add_address(cd, super->vftbl);
2759 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2762 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2763 M_ALD(REG_ITMP3, REG_PV, disp);
2765 CODEGEN_CRITICAL_SECTION_START;
2767 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2768 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2769 M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2770 M_ALD(REG_ITMP3, REG_PV, disp);
2771 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2773 CODEGEN_CRITICAL_SECTION_END;
2776 M_CMP(REG_ITMP3, REG_ITMP2);
2777 emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
2780 emit_label(cd, BRANCH_LABEL_5);
2783 if (super == NULL) {
2784 emit_label(cd, BRANCH_LABEL_1);
2785 emit_label(cd, BRANCH_LABEL_4);
2788 d = codegen_reg_of_dst(jd, iptr, s1);
2791 /* array type cast-check */
2793 s1 = emit_load_s1(jd, iptr, REG_OUT0);
2794 M_INTMOVE(s1, REG_OUT0);
2796 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2798 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2799 cr = iptr->sx.s23.s3.c.ref;
2800 disp = dseg_add_unique_address(cd, NULL);
2802 codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
2806 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2808 M_ALD(REG_OUT1, REG_PV, disp);
2809 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2810 M_ALD(REG_ITMP3, REG_PV, disp);
2811 /* XXX jit-c-call */
2812 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2815 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2816 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
2818 d = codegen_reg_of_dst(jd, iptr, s1);
2822 emit_store_dst(jd, iptr, d);
2825 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2826 /* val.a: (classinfo*) superclass */
2828 /* superclass is an interface:
2830 * return (sub != NULL) &&
2831 * (sub->vftbl->interfacetablelength > super->index) &&
2832 * (sub->vftbl->interfacetable[-super->index] != NULL);
2834 * superclass is a class:
2836 * return ((sub != NULL) && (0
2837 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2838 * super->vftbl->diffvall));
2843 vftbl_t *supervftbl;
2846 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2852 super = iptr->sx.s23.s3.c.cls;
2853 superindex = super->index;
2854 supervftbl = super->vftbl;
2857 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2858 CODEGEN_CRITICAL_SECTION_NEW;
2860 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2861 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2863 M_MOV(s1, REG_ITMP1);
2869 /* if class is not resolved, check which code to call */
2871 if (super == NULL) {
2872 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2874 cr = iptr->sx.s23.s3.c.ref;
2875 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2877 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2880 M_ILD(REG_ITMP3, REG_PV, disp);
2881 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2882 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
2885 /* interface instanceof code */
2887 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2888 if (super == NULL) {
2889 cr = iptr->sx.s23.s3.c.ref;
2891 codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
2895 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2898 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2899 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2900 M_CMP_IMM(REG_ITMP3, superindex);
2903 M_ALD(REG_ITMP1, REG_ITMP1,
2904 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2905 superindex * sizeof(methodptr*)));
2906 M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
2909 emit_label_br(cd, BRANCH_LABEL_4);
2911 emit_label(cd, BRANCH_LABEL_3);
2914 /* class instanceof code */
2916 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2917 if (super == NULL) {
2918 emit_label(cd, BRANCH_LABEL_2);
2920 cr = iptr->sx.s23.s3.c.ref;
2921 disp = dseg_add_unique_address(cd, NULL);
2923 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
2927 disp = dseg_add_address(cd, supervftbl);
2929 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2932 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2933 M_ALD(REG_ITMP2, REG_PV, disp);
2935 CODEGEN_CRITICAL_SECTION_START;
2937 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2938 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2939 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2941 CODEGEN_CRITICAL_SECTION_END;
2943 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2944 M_CMP(REG_ITMP1, REG_ITMP2);
2945 M_XCMOVULE_IMM(1, d);
2948 emit_label(cd, BRANCH_LABEL_5);
2951 if (super == NULL) {
2952 emit_label(cd, BRANCH_LABEL_1);
2953 emit_label(cd, BRANCH_LABEL_4);
2956 emit_store_dst(jd, iptr, d);
2960 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2962 /* check for negative sizes and copy sizes to stack if necessary */
2964 MCODECHECK((iptr->s1.argcount << 1) + 64);
2966 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2968 var = VAR(iptr->sx.s23.s2.args[s1]);
2970 /* copy SAVEDVAR sizes to stack */
2972 /* Already Preallocated? */
2974 if (!(var->flags & PREALLOC)) {
2975 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2976 M_STX(s2, REG_SP, CSTACK + (s1 * 8));
2980 /* arg 0 = dimension count */
2982 ICONST(REG_OUT0, iptr->s1.argcount);
2984 /* is patcher function set? */
2986 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2987 disp = dseg_add_unique_address(cd, 0);
2989 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
2990 iptr->sx.s23.s3.c.ref,
2994 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2996 /* arg 1 = arraydescriptor */
2998 M_ALD(REG_OUT1, REG_PV, disp);
3000 /* arg 2 = pointer to dimensions = stack pointer (absolute) */
3002 M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
3004 /* XXX c abi call */
3005 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3006 M_ALD(REG_ITMP3, REG_PV, disp);
3007 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3010 /* check for exception before result assignment */
3012 emit_exception_check(cd, iptr);
3014 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
3015 M_INTMOVE(REG_RESULT_CALLER, d);
3016 emit_store_dst(jd, iptr, d);
3020 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
3026 } /* for instruction */
3030 /* At the end of a basic block we may have to append some nops,
3031 because the patcher stub calling code might be longer than the
3032 actual instruction. So codepatching does not change the
3033 following block unintentionally. */
3035 if (cd->mcodeptr < cd->lastmcodeptr) {
3036 while (cd->mcodeptr < cd->lastmcodeptr) {
3041 } /* if (bptr -> flags >= BBREACHED) */
3042 } /* for basic block */
3044 dseg_createlinenumbertable(cd);
3046 /* generate stubs */
3048 emit_patcher_stubs(jd);
3050 /* everything's ok */
3056 /* codegen_emit_stub_compiler **************************************************
3058 Emits a stub routine which calls the compiler.
3060 *******************************************************************************/
3062 void codegen_emit_stub_compiler(jitdata *jd)
3067 /* get required compiler data */
3072 /* code for the stub */
3074 /* no window save yet, user caller's PV */
3075 M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */
3076 M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */
3077 M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */
3082 /* codegen_emit_stub_builtin ***************************************************
3084 Creates a stub routine which calls a builtin function.
3086 *******************************************************************************/
3088 void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
3097 /* get required compiler data */
3101 /* set some variables */
3104 /* calculate stack frame size */
3105 cd->stackframesize =
3109 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3110 4; /* 4 arguments or return value */
3113 /* keep stack 16-byte aligned (ABI requirement) */
3115 if (cd->stackframesize & 1)
3116 cd->stackframesize++;
3118 /* create method header */
3119 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3120 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3121 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3122 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3123 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3124 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3125 (void) dseg_addlinenumbertablesize(cd);
3126 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3129 /* generate stub code */
3130 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3132 #if defined(ENABLE_GC_CACAO)
3133 /* Save callee saved integer registers in stackframeinfo (GC may
3134 need to recover them during a collection). */
3136 disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
3137 OFFSET(stackframeinfo, intregs) + BIAS;
3139 for (i = 0; i < INT_SAV_CNT; i++)
3140 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3143 for (i = 0; i < md->paramcount; i++) {
3144 s1 = md->params[i].regoff;
3146 switch (md->paramtypes[i].type) {
3153 M_DST(s1, REG_SP, JITSTACK + i * 8);
3158 /* create dynamic stack info */
3160 M_AADD_IMM(REG_SP, BIAS + cd->stackframesize * 8, REG_OUT0); /* data sp*/
3161 M_MOV(REG_PV_CALLEE, REG_OUT1); /* PV */
3162 M_MOV(REG_FP, REG_OUT2); /* java sp */
3163 M_MOV(REG_RA_CALLEE, REG_OUT3); /* ra */
3165 disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
3166 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3167 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3168 M_NOP; /* XXX fill me! */
3171 /* builtins are allowed to have 5 arguments max */
3173 assert(md->paramcount <= 5);
3175 /* copy arguments into position */
3177 for (i = 0; i < md->paramcount; i++) {
3178 assert(!md->params[i].inmemory);
3180 s1 = md->params[i].regoff;
3182 switch (md->paramtypes[i].type) {
3186 M_MOV(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[i]), s1);
3190 M_DLD(s1, REG_SP, JITSTACK + i * 8);
3196 /* call the builtin function */
3198 disp = dseg_add_functionptr(cd, bte->fp);
3199 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); /* load adress of builtin */
3200 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call builtin */
3201 M_NOP; /* delay slot */
3204 /* save return value */
3206 if (md->returntype.type != TYPE_VOID) {
3207 if (IS_INT_LNG_TYPE(md->returntype.type))
3208 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3210 M_DST(REG_FRESULT, REG_SP, CSTACK);
3214 /* remove native stackframe info */
3216 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3217 disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
3218 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3219 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3222 /* restore float return value, int return value already in our return reg */
3224 if (md->returntype.type != TYPE_VOID) {
3225 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3226 if (IS_2_WORD_TYPE(md->returntype.type))
3227 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3229 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3234 #if defined(ENABLE_GC_CACAO)
3235 /* Restore callee saved integer registers from stackframeinfo (GC
3236 might have modified them during a collection). */
3238 disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
3239 OFFSET(stackframeinfo, intregs) + BIAS;
3241 for (i = 0; i < INT_SAV_CNT; i++)
3242 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3246 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3253 /* codegen_emit_stub_native ****************************************************
3255 Emits a stub routine which calls a native method.
3257 *******************************************************************************/
3259 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3266 s4 i, j; /* count variables */
3269 s4 funcdisp; /* displacement of the function */
3270 s4 fltregarg_offset[FLT_ARG_CNT];
3272 /* get required compiler data */
3278 /* initialize variables */
3281 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3283 /* calculate stack frame size */
3285 cd->stackframesize =
3286 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3287 sizeof(localref_table) / SIZEOF_VOID_P +
3288 md->paramcount + /* for saving arguments over calls */
3289 nmd->memuse + /* nmd->memuse includes the (6) abi params */
3293 /* keep stack 16-byte aligned (ABI requirement) */
3295 if (cd->stackframesize & 1)
3296 cd->stackframesize++;
3298 /* create method header */
3300 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3301 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3302 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3303 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3304 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3305 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3306 (void) dseg_addlinenumbertablesize(cd);
3307 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3309 /* generate stub code */
3311 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3313 #if !defined(NDEBUG)
3314 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3315 emit_verbosecall_enter(jd);
3318 /* get function address (this must happen before the stackframeinfo) */
3320 funcdisp = dseg_add_functionptr(cd, f);
3322 #if !defined(WITH_STATIC_CLASSPATH)
3324 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
3328 /* save float argument registers */
3330 assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
3332 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3333 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3334 s1 = WINSAVE_CNT + nmd->memuse + j;
3335 M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
3336 fltregarg_offset[i] = s1; /* remember stack offset */
3341 /* prepare data structures for native function call */
3343 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */
3344 M_MOV(REG_PV_CALLEE, REG_OUT1);
3345 M_MOV(REG_FP, REG_OUT2); /* java sp */
3346 M_MOV(REG_RA_CALLEE, REG_OUT3);
3347 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3348 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3349 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3350 M_NOP; /* XXX fill me! */
3352 /* remember class argument */
3354 if (m->flags & ACC_STATIC)
3355 M_MOV(REG_RESULT_CALLER, REG_ITMP3);
3357 /* keep float arguments on stack */
3359 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3360 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3361 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
3367 /* copy or spill arguments to new locations */
3369 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3370 t = md->paramtypes[i].type;
3372 if (IS_INT_LNG_TYPE(t)) {
3374 /* integral types */
3376 if (!md->params[i].inmemory) {
3377 s1 = md->params[i].regoff;
3378 /* s1 refers to the old window, transpose */
3379 s1 = REG_WINDOW_TRANSPOSE(s1);
3381 if (!nmd->params[j].inmemory) {
3382 s2 = nmd->params[j].regoff;
3385 /* nmd's regoff is relative to the start of the param array */
3386 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3387 M_AST(s1, REG_SP, s2);
3391 if (!nmd->params[j].inmemory) {
3392 /* JIT stack arg -> NAT reg arg */
3394 /* Due to the Env pointer that is always passed, the 6th JIT arg */
3395 /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */
3397 assert(false); /* path never taken */
3400 s1 = md->params[i].regoff + cd->stackframesize * 8;
3401 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3402 M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
3403 M_AST(REG_ITMP1, REG_SP, s2);
3408 /* floating point types */
3410 if (!md->params[i].inmemory) {
3411 s1 = md->params[i].regoff;
3413 if (!nmd->params[j].inmemory) {
3415 /* no mapping to regs needed, native flt args use regoff */
3416 s2 = nmd->params[j].regoff;
3418 /* JIT float regs are still on the stack */
3419 M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8));
3422 /* not supposed to happen with 16 NAT flt args */
3425 s2 = nmd->params[j].regoff;
3426 if (IS_2_WORD_TYPE(t))
3427 M_DST(s1, REG_SP, CSTACK + (s2 * 8));
3429 M_FST(s1, REG_SP, CSTACK + (s2 * 8));
3435 s1 = md->params[i].regoff;
3437 if (!nmd->params[j].inmemory) {
3439 /* JIT stack -> NAT reg */
3441 s2 = nmd->params[j].regoff;
3442 M_DLD(s2, REG_FP, JITSTACK + s1);
3446 /* JIT stack -> NAT stack */
3448 s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff;
3450 /* The FTMP register may already be loaded with args */
3451 /* we know $f0 is unused because of the env pointer */
3452 M_DLD(REG_F0, REG_FP, JITSTACK + s1);
3453 M_DST(REG_F0, REG_SP, BIAS + s2);
3460 /* put class into second argument register */
3462 if (m->flags & ACC_STATIC)
3463 M_MOV(REG_ITMP3, REG_OUT1);
3465 /* put env into first argument register */
3467 disp = dseg_add_address(cd, _Jv_env);
3468 M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
3470 /* do the native function call */
3472 M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method */
3473 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method */
3474 M_NOP; /* delay slot */
3476 /* save return value */
3478 if (md->returntype.type != TYPE_VOID) {
3479 if (IS_INT_LNG_TYPE(md->returntype.type))
3480 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3482 M_DST(REG_FRESULT, REG_SP, CSTACK);
3485 /* Note: native functions return float values in %f0 (see ABI) */
3486 /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
3488 #if !defined(NDEBUG)
3489 /* But for the trace function we need to put a flt result into %f1 */
3490 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3491 if (!IS_2_WORD_TYPE(md->returntype.type))
3492 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3493 emit_verbosecall_exit(jd);
3497 /* remove native stackframe info */
3499 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3500 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3501 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3502 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3503 M_NOP; /* XXX fill me! */
3504 M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
3506 /* restore float return value, int return value already in our return reg */
3508 if (md->returntype.type != TYPE_VOID) {
3509 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3510 if (IS_2_WORD_TYPE(md->returntype.type))
3511 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3513 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3517 /* check for exception */
3518 M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
3521 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3524 /* handle exception */
3526 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3527 M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */
3528 M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */
3529 M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */
3530 M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
3532 /* generate patcher stubs */
3534 emit_patcher_stubs(jd);
3538 * These are local overrides for various environment variables in Emacs.
3539 * Please do not remove this and leave it at the end of the file, where
3540 * Emacs will automagically detect them.
3541 * ---------------------------------------------------------------------
3544 * indent-tabs-mode: t
3548 * vim:noexpandtab:sw=4:ts=4: