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
25 $Id: codegen.c 4644 2006-03-16 18:44:46Z edwin $
39 /* #include "vm/jit/sparc64/arch.h" */
40 #include "vm/jit/sparc64/codegen.h"
42 #include "mm/memory.h"
44 #include "native/jni.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 /* codegen_emit ****************************************************************
103 Generates machine code.
105 *******************************************************************************/
107 bool codegen_emit(jitdata *jd)
113 s4 len, s1, s2, s3, d, disp, slots;
119 constant_classref *cr;
120 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
121 unresolved_method *um;
122 builtintable_entry *bte;
125 unresolved_field *uf;
129 /* get required compiler data */
136 /* prevent compiler warnings */
147 #if 0 /* no leaf optimization yet */
148 savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the RA */
150 savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */
153 /* space to save used callee saved registers */
155 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
156 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
158 cd->stackframesize = rd->memuse + savedregs_num;
160 #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
161 if (checksync && (m->flags & ACC_SYNCHRONIZED))
162 cd->stackframesize++;
165 /* keep stack 16-byte aligned (ABI requirement) */
167 if (cd->stackframesize & 1)
168 cd->stackframesize++;
170 /* create method header */
172 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
173 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
175 #if defined(ENABLE_THREADS)
176 /* IsSync contains the offset relative to the stack pointer for the
177 argument of monitor_exit used in the exception handler. Since the
178 offset could be zero and give a wrong meaning of the flag it is
182 if (checksync && (m->flags & ACC_SYNCHRONIZED))
183 (void) dseg_add_unique_s4(cd, JITSTACK + (rd->memuse + 1) * 8); /* IsSync */
186 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
188 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
189 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
190 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
191 dseg_addlinenumbertablesize(cd);
192 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
194 /* create exception table */
196 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
197 dseg_add_target(cd, ex->start);
198 dseg_add_target(cd, ex->end);
199 dseg_add_target(cd, ex->handler);
200 (void) dseg_add_unique_address(cd, ex->catchtype.any);
203 /* save register window and create stack frame (if necessary) */
205 if (cd->stackframesize)
206 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
209 /* save callee saved float registers (none right now) */
211 p = cd->stackframesize;
212 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
213 p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
218 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
219 emit_verbosecall_enter(jd);
223 /* call monitorenter function */
224 #if defined(ENABLE_THREADS)
225 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
226 /* stack offset for monitor argument */
230 /* save float argument registers */
234 ALIGN_STACK_SLOTS(slots);
236 M_LDA(REG_SP, REG_SP, -(slots * 8));
237 for (i = 0; i < FLT_ARG_CNT; i++)
238 M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
242 /* get correct lock object */
244 if (m->flags & ACC_STATIC) {
245 disp = dseg_add_address(cd, &m->class->object.header);
246 M_ALD(REG_OUT0, REG_PV, disp);
247 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
248 M_ALD(REG_ITMP3, REG_PV, disp);
251 /* copy class pointer: $i0 -> $o0 */
252 M_MOV(REG_RESULT_CALLEE, REG_OUT0);
254 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
255 M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
256 M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
259 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
260 M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */
262 /* restore float argument registers */
264 for (i = 0; i < FLT_ARG_CNT; i++)
265 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
267 M_LDA(REG_SP, REG_SP, slots * 8);
272 /* take arguments out of register or stack frame */
276 for (p = 0, l = 0; p < md->paramcount; p++) {
277 t = md->paramtypes[p].type;
279 varindex = jd->local_map[l * 5 + t];
282 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
285 if (varindex == UNUSED)
289 s1 = md->params[p].regoff;
291 if (IS_INT_LNG_TYPE(t)) { /* integer args */
295 if (!md->params[p].inmemory) { /* register arguments */
296 s1 = REG_WINDOW_TRANSPOSE(s1);
298 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
300 /* the register allocator does not know about the window. */
301 /* avoid copying the locals from save to save regs by */
302 /* swapping variables. */
305 int old_dest = var->vv.regoff;
306 int new_dest = p + 24;
308 /* run through all variables */
310 for (i = 0; i < jd->varcount; i++) {
311 varinfo* uvar = VAR(i);
313 if (IS_FLT_DBL_TYPE(uvar->type))
316 s2 = uvar->vv.regoff;
318 /* free the in reg by moving all other references */
320 if (s2 == new_dest) {
321 uvar->vv.regoff = old_dest;
322 /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
325 /* move all variables to the in reg */
327 if (s2 == old_dest) {
328 uvar->vv.regoff = new_dest;
329 /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
337 else { /* reg arg -> spilled */
338 M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
341 } else { /* stack arguments */
342 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
343 M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1);
345 } else { /* stack arg -> spilled */
346 /* add the callers window save registers */
347 var->vv.regoff = cd->stackframesize * 8 + s1;
351 } else { /* floating args */
352 if (!md->params[p].inmemory) { /* register arguments */
353 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
354 M_FLTMOVE(s1, var->vv.regoff);
356 } else { /* reg arg -> spilled */
357 M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
360 } else { /* stack arguments */
361 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
362 M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1);
364 } else { /* stack-arg -> spilled */
365 var->vv.regoff = cd->stackframesize * 8 + s1;
374 /* end of header generation */
376 /* create replacement points */
378 REPLACEMENT_POINTS_INIT(cd, jd);
380 /* walk through all basic blocks */
382 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
384 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
386 if (bptr->flags >= BBREACHED) {
388 /* branch resolving */
390 codegen_resolve_branchrefs(cd, bptr);
392 /* handle replacement points */
394 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
397 /* copy interface registers to their destination */
402 #if defined(ENABLE_LSRA)
403 #error XXX LSRA not tested yet
407 src = bptr->invars[len];
408 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
409 /* d = reg_of_var(m, src, REG_ITMP1); */
410 if (!(src->flags & INMEMORY))
414 M_INTMOVE(REG_ITMP1, d);
415 emit_store(jd, NULL, src, d);
422 var = VAR(bptr->invars[len]);
423 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
424 d = codegen_reg_of_var(0, var, REG_ITMP1);
425 M_INTMOVE(REG_ITMP2_XPTR, d);
426 emit_store(jd, NULL, var, d);
429 assert((var->flags & INOUT));
432 #if defined(ENABLE_LSRA)
435 /* walk through all instructions */
439 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
440 if (iptr->line != currentline) {
441 dseg_addlinenumber(cd, iptr->line);
442 currentline = iptr->line;
445 MCODECHECK(64); /* an instruction usually needs < 64 words */
449 case ICMD_INLINE_START:
450 case ICMD_INLINE_END:
453 case ICMD_NOP: /* ... ==> ... */
456 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
458 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
459 emit_nullpointer_check(cd, iptr, s1);
462 /* constant operations ************************************************/
464 case ICMD_ICONST: /* ... ==> ..., constant */
466 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
467 ICONST(d, iptr->sx.val.i);
468 emit_store_dst(jd, iptr, d);
471 case ICMD_LCONST: /* ... ==> ..., constant */
473 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
474 LCONST(d, iptr->sx.val.l);
475 emit_store_dst(jd, iptr, d);
478 case ICMD_FCONST: /* ... ==> ..., constant */
480 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
481 disp = dseg_add_float(cd, iptr->sx.val.f);
482 M_FLD(d, REG_PV, disp);
483 emit_store_dst(jd, iptr, d);
486 case ICMD_DCONST: /* ... ==> ..., constant */
488 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
489 disp = dseg_add_double(cd, iptr->sx.val.d);
490 M_DLD(d, REG_PV, disp);
491 emit_store_dst(jd, iptr, d);
494 case ICMD_ACONST: /* ... ==> ..., constant */
496 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
498 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
499 cr = iptr->sx.val.c.ref;
500 disp = dseg_add_unique_address(cd, cr);
502 codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
504 M_ALD(d, REG_PV, disp);
508 if (iptr->sx.val.anyptr == NULL) {
509 M_INTMOVE(REG_ZERO, d);
512 disp = dseg_add_address(cd, iptr->sx.val.anyptr);
513 M_ALD(d, REG_PV, disp);
516 emit_store_dst(jd, iptr, d);
520 /* load/store/copy/move operations ************************************/
522 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
527 case ICMD_ISTORE: /* ..., value ==> ... */
538 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
543 /* pop/dup/swap operations ********************************************/
545 /* attention: double and longs are only one entry in CACAO ICMDs */
547 case ICMD_POP: /* ..., value ==> ... */
548 case ICMD_POP2: /* ..., value, value ==> ... */
552 /* integer operations *************************************************/
554 case ICMD_INEG: /* ..., value ==> ..., - value */
557 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
558 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
559 M_SUB(REG_ZERO, s1, d);
560 emit_store_dst(jd, iptr, d);
563 case ICMD_I2L: /* ..., value ==> ..., value */
565 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
566 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
568 emit_store_dst(jd, iptr, d);
571 case ICMD_L2I: /* ..., value ==> ..., value */
573 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
574 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
575 M_SRA_IMM(s1, 0, d); /* sign extend upper 32 bits */
576 emit_store_dst(jd, iptr, d);
579 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
581 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
582 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
583 M_SLLX_IMM(s1, 56, d);
584 M_SRAX_IMM( d, 56, d);
585 emit_store_dst(jd, iptr, d);
588 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
590 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
591 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
592 M_SLLX_IMM(s1, 48, d);
593 M_SRLX_IMM( d, 48, d);
594 emit_store_dst(jd, iptr, d);
597 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
599 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
600 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
601 M_SLLX_IMM(s1, 48, d);
602 M_SRAX_IMM( d, 48, d);
603 emit_store_dst(jd, iptr, d);
606 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
609 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
610 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
611 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
613 emit_store_dst(jd, iptr, d);
617 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
618 /* sx.val.i = constant */
620 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
621 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
622 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
623 M_ADD_IMM(s1, iptr->sx.val.i, d);
625 ICONST(REG_ITMP2, iptr->sx.val.i);
626 M_ADD(s1, REG_ITMP2, d);
628 emit_store_dst(jd, iptr, d);
631 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
632 /* sx.val.l = constant */
634 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
635 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
636 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
637 M_ADD_IMM(s1, iptr->sx.val.l, d);
639 LCONST(REG_ITMP2, iptr->sx.val.l);
640 M_ADD(s1, REG_ITMP2, d);
642 emit_store_dst(jd, iptr, d);
645 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
648 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
649 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
650 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
652 emit_store_dst(jd, iptr, d);
655 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
656 /* sx.val.i = constant */
658 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
659 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
660 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
661 M_SUB_IMM(s1, iptr->sx.val.i, d);
663 ICONST(REG_ITMP2, iptr->sx.val.i);
664 M_SUB(s1, REG_ITMP2, d);
666 emit_store_dst(jd, iptr, d);
669 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
670 /* sx.val.l = constant */
672 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
673 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
674 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
675 M_SUB_IMM(s1, iptr->sx.val.l, d);
677 LCONST(REG_ITMP2, iptr->sx.val.l);
678 M_SUB(s1, REG_ITMP2, d);
680 emit_store_dst(jd, iptr, d);
683 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
686 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
687 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
688 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
690 emit_store_dst(jd, iptr, d);
693 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
694 /* sx.val.i = constant */
696 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
697 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
698 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
699 M_MULX_IMM(s1, iptr->sx.val.i, d);
701 ICONST(REG_ITMP2, iptr->sx.val.i);
702 M_MULX(s1, REG_ITMP2, d);
704 emit_store_dst(jd, iptr, d);
707 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
708 /* sx.val.l = constant */
710 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
711 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
712 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
713 M_MULX_IMM(s1, iptr->sx.val.l, d);
715 LCONST(REG_ITMP2, iptr->sx.val.l);
716 M_MULX(s1, REG_ITMP2, d);
718 emit_store_dst(jd, iptr, d);
721 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
722 /* XXX could also clear Y and use 32bit div */
723 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
724 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
725 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
726 emit_arithmetic_check(cd, iptr, s2);
728 /* XXX trim s2 like s1 ? */
730 emit_store_dst(jd, iptr, d);
733 case ICMD_LDIV: /* ..., 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);
738 emit_arithmetic_check(cd, iptr, s2);
740 emit_store_dst(jd, iptr, d);
743 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
745 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
746 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
747 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
748 emit_arithmetic_check(cd, iptr, s2);
750 /* XXX trim s2 like s1 ? */
751 M_DIVX(s1, s2, REG_ITMP3);
752 M_MULX(s2, REG_ITMP3, REG_ITMP3);
753 M_SUB(s1, REG_ITMP3, d);
754 emit_store_dst(jd, iptr, d);
757 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
759 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
760 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
761 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
762 emit_arithmetic_check(cd, iptr, s2);
763 M_DIVX(s1, s2, REG_ITMP3);
764 M_MULX(s2, REG_ITMP3, REG_ITMP3);
765 M_SUB(s1, REG_ITMP3, d);
766 emit_store_dst(jd, iptr, d);
769 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
770 case ICMD_LDIVPOW2: /* val.i = constant */
772 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
773 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
774 M_SRAX_IMM(s1, 63, REG_ITMP2);
775 M_SRLX_IMM(REG_ITMP2, 64 - iptr->sx.val.i, REG_ITMP2);
776 M_ADD(s1, REG_ITMP2, REG_ITMP2);
777 M_SRAX_IMM(REG_ITMP2, iptr->sx.val.i, d);
778 emit_store_dst(jd, iptr, d);
781 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
783 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
784 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
785 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
787 emit_store_dst(jd, iptr, d);
790 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
792 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
793 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
794 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
796 emit_store_dst(jd, iptr, d);
799 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
800 /* val.i = constant */
802 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
803 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
804 M_SLL_IMM(s1, iptr->sx.val.i, d);
805 emit_store_dst(jd, iptr, d);
808 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
809 /* val.i = constant */
811 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
812 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
813 M_SLLX_IMM(s1, iptr->sx.val.i, d);
814 emit_store_dst(jd, iptr, d);
817 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
819 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
820 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
821 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
823 emit_store_dst(jd, iptr, d);
826 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
827 /* sx.val.i = constant */
829 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
830 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
831 M_SRA_IMM(s1, iptr->sx.val.i, d);
832 emit_store_dst(jd, iptr, d);
835 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
837 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
838 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
839 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
841 emit_store_dst(jd, iptr, d);
844 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
845 /* sx.val.i = constant */
847 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
848 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
849 M_SRL_IMM(s1, iptr->sx.val.i, d);
850 emit_store_dst(jd, iptr, d);
853 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
855 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
856 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
857 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
859 emit_store_dst(jd, iptr, d);
862 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
863 /* sx.val.i = constant */
865 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
866 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
867 M_SRAX_IMM(s1, iptr->sx.val.i, d);
868 emit_store_dst(jd, iptr, d);
871 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
873 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
874 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
875 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
877 emit_store_dst(jd, iptr, d);
880 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
881 /* sx.val.i = constant */
883 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
884 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
885 M_SRLX_IMM(s1, iptr->sx.val.i, d);
886 emit_store_dst(jd, iptr, d);
889 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
892 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
893 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
894 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
896 emit_store_dst(jd, iptr, d);
899 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
900 /* sx.val.i = constant */
902 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
903 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
904 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
905 M_AND_IMM(s1, iptr->sx.val.i, d);
907 ICONST(REG_ITMP2, iptr->sx.val.i);
908 M_AND(s1, REG_ITMP2, d);
910 emit_store_dst(jd, iptr, d);
913 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
914 /* sx.val.i = constant */
915 /* constant is actually constant - 1 */
917 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
918 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
920 M_MOV(s1, REG_ITMP1);
923 M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
924 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
925 M_AND_IMM(s1, iptr->sx.val.i, d);
928 M_SUB(REG_ZERO, s1, d);
929 M_AND_IMM(d, iptr->sx.val.i, d);
931 ICONST(REG_ITMP2, iptr->sx.val.i);
932 M_AND(s1, REG_ITMP2, d);
935 M_SUB(REG_ZERO, s1, d);
936 M_AND(d, REG_ITMP2, d);
938 M_SUB(REG_ZERO, d, d);
939 emit_store_dst(jd, iptr, d);
942 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
943 /* sx.val.l = constant */
945 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
946 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
947 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
948 M_AND_IMM(s1, iptr->sx.val.l, d);
950 LCONST(REG_ITMP2, iptr->sx.val.l);
951 M_AND(s1, REG_ITMP2, d);
953 emit_store_dst(jd, iptr, d);
956 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
957 /* sx.val.l = constant */
959 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
960 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
962 M_MOV(s1, REG_ITMP1);
965 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
966 M_AND_IMM(s1, iptr->sx.val.l, d);
969 M_SUB(REG_ZERO, s1, d);
970 M_AND_IMM(d, iptr->sx.val.l, d);
972 LCONST(REG_ITMP2, iptr->sx.val.l);
973 M_AND(s1, REG_ITMP2, d);
976 M_SUB(REG_ZERO, s1, d);
977 M_AND(d, REG_ITMP2, d);
979 M_SUB(REG_ZERO, d, d);
980 emit_store_dst(jd, iptr, d);
983 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
986 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
987 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
988 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
990 emit_store_dst(jd, iptr, d);
993 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
994 /* sx.val.i = constant */
996 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
997 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
998 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
999 M_OR_IMM(s1, iptr->sx.val.i, d);
1001 ICONST(REG_ITMP2, iptr->sx.val.i);
1002 M_OR(s1, REG_ITMP2, d);
1004 emit_store_dst(jd, iptr, d);
1007 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1008 /* sx.val.l = constant */
1010 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1011 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1012 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1013 M_OR_IMM(s1, iptr->sx.val.l, d);
1015 LCONST(REG_ITMP2, iptr->sx.val.l);
1016 M_OR(s1, REG_ITMP2, d);
1018 emit_store_dst(jd, iptr, d);
1021 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1024 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1025 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1026 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1028 emit_store_dst(jd, iptr, d);
1031 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1032 /* sx.val.i = constant */
1034 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1035 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1036 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1037 M_XOR_IMM(s1, iptr->sx.val.i, d);
1039 ICONST(REG_ITMP2, iptr->sx.val.i);
1040 M_XOR(s1, REG_ITMP2, d);
1042 emit_store_dst(jd, iptr, d);
1045 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1046 /* sx.val.l = constant */
1048 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1049 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1050 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1051 M_XOR_IMM(s1, iptr->sx.val.l, d);
1053 LCONST(REG_ITMP2, iptr->sx.val.l);
1054 M_XOR(s1, REG_ITMP2, d);
1056 emit_store_dst(jd, iptr, d);
1060 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1062 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1063 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1064 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1067 M_XCMOVLT_IMM(-1, d);
1068 M_XCMOVGT_IMM(1, d);
1069 emit_store_dst(jd, iptr, d);
1073 /* floating operations ************************************************/
1075 case ICMD_FNEG: /* ..., value ==> ..., - value */
1077 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1078 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1080 emit_store_dst(jd, iptr, d);
1083 case ICMD_DNEG: /* ..., value ==> ..., - value */
1085 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1086 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1088 emit_store_dst(jd, iptr, d);
1091 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1093 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1094 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1095 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1097 emit_store_dst(jd, iptr, d);
1100 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1102 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1103 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1104 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1106 emit_store_dst(jd, iptr, d);
1109 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1111 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1112 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1113 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1115 emit_store_dst(jd, iptr, d);
1118 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1120 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1121 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1122 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1124 emit_store_dst(jd, iptr, d);
1127 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1129 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1130 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1131 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1133 emit_store_dst(jd, iptr, d);
1136 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1138 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1139 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1140 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1142 emit_store_dst(jd, iptr, d);
1145 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1147 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1148 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1149 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1151 emit_store_dst(jd, iptr, d);
1154 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1156 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1157 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1158 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1160 emit_store_dst(jd, iptr, d);
1164 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1165 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1166 disp = dseg_add_unique_float(cd, 0.0);
1167 M_IST (s1, REG_PV_CALLEE, disp);
1168 M_FLD (d, REG_PV_CALLEE, disp);
1169 M_CVTIF (d, d); /* rd gets translated to double target register */
1170 emit_store_dst(jd, iptr, d);
1174 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1175 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1176 disp = dseg_add_unique_float(cd, 0.0);
1177 M_IST(s1, REG_PV_CALLEE, disp);
1178 M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
1179 M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
1180 emit_store_dst(jd, iptr, d);
1184 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1185 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1186 disp = dseg_add_unique_double(cd, 0.0);
1187 M_STX(s1, REG_PV_CALLEE, disp);
1188 M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
1189 M_CVTLF(REG_FTMP3, d);
1190 emit_store_dst(jd, iptr, d);
1194 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1195 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1196 disp = dseg_add_unique_double(cd, 0.0);
1197 M_STX(s1, REG_PV_CALLEE, disp);
1198 M_DLD(d, REG_PV_CALLEE, disp);
1200 emit_store_dst(jd, iptr, d);
1203 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1204 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1205 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1206 disp = dseg_add_unique_float(cd, 0.0);
1208 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1211 M_MOV(REG_ZERO, d); /* delay slot */
1213 M_CVTFI(s1, REG_FTMP2);
1214 M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
1215 M_ILD(d, REG_PV, disp);
1216 emit_store_dst(jd, iptr, d);
1220 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1221 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1222 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1223 disp = dseg_add_unique_float(cd, 0.0);
1225 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1228 M_MOV(REG_ZERO, d); /* delay slot */
1230 M_CVTDI(s1, REG_FTMP2);
1231 M_FST(REG_FTMP2, REG_PV, disp);
1232 M_ILD(d, REG_PV, disp);
1233 emit_store_dst(jd, iptr, d);
1236 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1237 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1238 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1239 disp = dseg_add_unique_double(cd, 0.0);
1241 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1244 M_MOV(REG_ZERO, d); /* delay slot */
1246 M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1247 M_DST(REG_FTMP2, REG_PV, disp);
1248 M_LDX(d, REG_PV, disp);
1249 emit_store_dst(jd, iptr, d);
1252 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1253 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1254 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1255 disp = dseg_add_unique_double(cd, 0.0);
1257 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1260 M_MOV(REG_ZERO, d); /* delay slot */
1262 M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1263 M_DST(REG_FTMP2, REG_PV, disp);
1264 M_LDX(d, REG_PV, disp);
1265 emit_store_dst(jd, iptr, d);
1268 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1270 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1271 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1273 emit_store_dst(jd, iptr, d);
1276 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1278 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1279 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1281 emit_store_dst(jd, iptr, d);
1284 /* XXX merge F/D versions? only compare instr. is different */
1285 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1287 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1288 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1289 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1291 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1292 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1293 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1294 emit_store_dst(jd, iptr, d);
1297 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1299 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1300 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1301 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1303 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1304 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1305 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1306 emit_store_dst(jd, iptr, d);
1309 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1311 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1312 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1313 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1315 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1316 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1317 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1318 emit_store_dst(jd, iptr, d);
1321 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1323 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1324 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1325 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1327 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1328 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1329 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1330 emit_store_dst(jd, iptr, d);
1334 /* memory operations **************************************************/
1336 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1338 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1339 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1340 emit_nullpointer_check(cd, iptr, s1);
1341 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1342 emit_store_dst(jd, iptr, d);
1345 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1347 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1348 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1349 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1350 /* implicit null-pointer check */
1351 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1352 M_AADD(s2, s1, REG_ITMP3);
1353 M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
1354 emit_store_dst(jd, iptr, d);
1357 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1359 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1360 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1361 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1362 /* implicit null-pointer check */
1363 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1364 M_AADD(s2, s1, REG_ITMP3);
1365 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1366 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1367 emit_store_dst(jd, iptr, d);
1370 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1372 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1373 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1374 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1375 /* implicit null-pointer check */
1376 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1377 M_AADD(s2, s1, REG_ITMP3);
1378 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1379 M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
1380 emit_store_dst(jd, iptr, d);
1383 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1385 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1386 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1387 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1388 /* implicit null-pointer check */
1389 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1390 M_ASLL_IMM(s2, 2, REG_ITMP3);
1391 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1392 M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
1393 emit_store_dst(jd, iptr, d);
1396 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1398 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1399 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1400 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1401 /* implicit null-pointer check */
1402 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1403 M_ASLL_IMM(s2, 3, REG_ITMP3);
1404 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1405 M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
1406 emit_store_dst(jd, iptr, d);
1409 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1411 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1412 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1413 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1414 /* implicit null-pointer check */
1415 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1416 M_ASLL_IMM(s2, 2, REG_ITMP3);
1417 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1418 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
1419 emit_store_dst(jd, iptr, d);
1422 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1424 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1425 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1426 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1427 /* implicit null-pointer check */
1428 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1429 M_ASLL_IMM(s2, 3, REG_ITMP3);
1430 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1431 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
1432 emit_store_dst(jd, iptr, d);
1435 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1437 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1438 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1439 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1440 /* implicit null-pointer check */
1441 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1442 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1443 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1444 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
1445 emit_store_dst(jd, iptr, d);
1449 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1451 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1452 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1453 /* implicit null-pointer check */
1454 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1455 M_AADD(s2, s1, REG_ITMP1);
1456 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1457 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1460 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1461 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1463 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1464 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1465 /* implicit null-pointer check */
1466 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1467 M_AADD(s2, s1, REG_ITMP1);
1468 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1469 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1470 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1473 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1475 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1476 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1477 /* implicit null-pointer check */
1478 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1479 M_ASLL_IMM(s2, 2, REG_ITMP2);
1480 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1481 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1482 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1485 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1487 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1488 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1489 /* implicit null-pointer check */
1490 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1491 M_ASLL_IMM(s2, 3, REG_ITMP2);
1492 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1493 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1494 M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1497 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1499 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1500 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1501 /* implicit null-pointer check */
1502 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1503 M_ASLL_IMM(s2, 2, REG_ITMP2);
1504 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1505 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1506 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1509 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1511 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1512 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1513 /* implicit null-pointer check */
1514 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1515 M_ASLL_IMM(s2, 3, REG_ITMP2);
1516 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1517 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1518 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1522 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1524 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1525 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1526 /* implicit null-pointer check */
1527 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1528 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1530 M_MOV(s1, REG_OUT0);
1531 M_MOV(s3, REG_OUT1);
1532 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1533 M_ALD(REG_ITMP3, REG_PV, disp);
1534 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
1536 emit_exception_check(cd, iptr);
1538 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1539 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1540 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1541 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1542 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1543 /* implicit null-pointer check */
1544 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1548 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1550 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1551 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1552 /* implicit null-pointer check */
1553 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1554 M_AADD(s2, s1, REG_ITMP1);
1555 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1558 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1559 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1561 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1562 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1563 /* implicit null-pointer check */
1564 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1565 M_AADD(s2, s1, REG_ITMP1);
1566 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1567 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1570 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1572 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1573 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1574 /* implicit null-pointer check */
1575 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1576 M_ASLL_IMM(s2, 2, REG_ITMP2);
1577 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1578 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1581 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1583 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1584 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1585 /* implicit null-pointer check */
1586 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1587 M_ASLL_IMM(s2, 3, REG_ITMP2);
1588 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1589 M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1592 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1594 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1595 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1596 /* implicit null-pointer check */
1597 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1598 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1599 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1600 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1604 case ICMD_GETSTATIC: /* ... ==> ..., value */
1606 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1607 uf = iptr->sx.s23.s3.uf;
1608 fieldtype = uf->fieldref->parseddesc.fd->type;
1609 disp = dseg_add_unique_address(cd, uf);
1611 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1614 fi = iptr->sx.s23.s3.fmiref->p.field;
1615 fieldtype = fi->type;
1616 disp = dseg_add_address(cd, &(fi->value));
1618 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1619 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1622 M_ALD(REG_ITMP1, REG_PV, disp);
1624 switch (fieldtype) {
1626 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1627 M_ILD_INTERN(d, REG_ITMP1, 0);
1630 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1631 M_LDX_INTERN(d, REG_ITMP1, 0);
1634 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1635 M_ALD_INTERN(d, REG_ITMP1, 0);
1638 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1639 M_FLD_INTERN(d, REG_ITMP1, 0);
1642 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1643 M_DLD_INTERN(d, REG_ITMP1, 0);
1646 emit_store_dst(jd, iptr, d);
1649 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1651 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1652 uf = iptr->sx.s23.s3.uf;
1653 fieldtype = uf->fieldref->parseddesc.fd->type;
1654 disp = dseg_add_unique_address(cd, uf);
1656 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1659 fi = iptr->sx.s23.s3.fmiref->p.field;
1660 fieldtype = fi->type;
1661 disp = dseg_add_address(cd, &(fi->value));
1663 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1664 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1667 M_ALD(REG_ITMP1, REG_PV, disp);
1669 switch (fieldtype) {
1671 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1672 M_IST_INTERN(s1, REG_ITMP1, 0);
1675 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1676 M_STX_INTERN(s1, REG_ITMP1, 0);
1679 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1680 M_AST_INTERN(s1, REG_ITMP1, 0);
1683 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1684 M_FST_INTERN(s1, REG_ITMP1, 0);
1687 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1688 M_DST_INTERN(s1, REG_ITMP1, 0);
1693 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1694 /* val = value (in current instruction) */
1695 /* following NOP) */
1697 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1698 uf = iptr->sx.s23.s3.uf;
1699 fieldtype = uf->fieldref->parseddesc.fd->type;
1700 disp = dseg_add_unique_address(cd, uf);
1702 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1705 fi = iptr->sx.s23.s3.fmiref->p.field;
1706 fieldtype = fi->type;
1707 disp = dseg_add_address(cd, &(fi->value));
1709 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1710 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1713 M_ALD(REG_ITMP1, REG_PV, disp);
1715 switch (fieldtype) {
1717 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1720 M_STX_INTERN(REG_ZERO, REG_ITMP1, 0);
1723 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1726 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1729 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1735 case ICMD_GETFIELD: /* ... ==> ..., value */
1737 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1738 emit_nullpointer_check(cd, iptr, s1);
1740 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1741 uf = iptr->sx.s23.s3.uf;
1743 fieldtype = uf->fieldref->parseddesc.fd->type;
1746 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1749 fi = iptr->sx.s23.s3.fmiref->p.field;
1750 fieldtype = fi->type;
1754 switch (fieldtype) {
1756 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1760 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1764 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1768 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1772 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1779 emit_store_dst(jd, iptr, d);
1782 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1784 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1785 emit_nullpointer_check(cd, iptr, s1);
1787 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1788 uf = iptr->sx.s23.s3.uf;
1789 fieldtype = uf->fieldref->parseddesc.fd->type;
1794 fi = iptr->sx.s23.s3.fmiref->p.field;
1795 fieldtype = fi->type;
1799 if (IS_INT_LNG_TYPE(fieldtype))
1800 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1802 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1804 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1805 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1807 switch (fieldtype) {
1809 M_IST(s2, s1, disp);
1812 M_STX(s2, s1, disp);
1815 M_AST(s2, s1, disp);
1818 M_FST(s2, s1, disp);
1821 M_DST(s2, s1, disp);
1829 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
1830 /* val = value (in current instruction) */
1831 /* following NOP) */
1833 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1834 emit_nullpointer_check(cd, iptr, s1);
1836 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1837 unresolved_field *uf = iptr->sx.s23.s3.uf;
1839 fieldtype = uf->fieldref->parseddesc.fd->type;
1841 codegen_addpatchref(cd, PATCHER_get_putfield,
1844 if (opt_showdisassemble) {
1852 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1854 fieldtype = fi->type;
1860 switch (fieldtype) {
1862 M_IST(REG_ZERO, s1, disp);
1865 M_STX(REG_ZERO, s1, disp);
1868 M_AST(REG_ZERO, s1, disp);
1871 M_FST(REG_ZERO, s1, disp);
1874 M_DST(REG_ZERO, s1, disp);
1880 /* branch operations **************************************************/
1882 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1884 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1885 M_INTMOVE(s1, REG_ITMP2_XPTR);
1887 #ifdef ENABLE_VERIFIER
1888 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1889 unresolved_class *uc = iptr->sx.s23.s2.uc;
1891 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
1893 #endif /* ENABLE_VERIFIER */
1895 disp = dseg_add_functionptr(cd, asm_handle_exception);
1896 M_ALD(REG_ITMP1, REG_PV, disp);
1897 M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
1899 M_NOP; /* nop ensures that XPC is less than the end */
1900 /* of basic block */
1904 case ICMD_GOTO: /* ... ==> ... */
1905 case ICMD_RET: /* ... ==> ... */
1907 emit_br(cd, iptr->dst.block);
1911 case ICMD_JSR: /* ... ==> ... */
1913 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1917 case ICMD_IFNULL: /* ..., value ==> ... */
1918 case ICMD_IFNONNULL:
1920 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1921 emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
1924 /* Note: int compares must not branch on the register directly. */
1925 /* Reason is, that register content is not 32-bit clean. */
1927 case ICMD_IFEQ: /* ..., value ==> ... */
1929 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1931 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1932 M_CMP_IMM(s1, iptr->sx.val.i);
1935 ICONST(REG_ITMP2, iptr->sx.val.i);
1936 M_CMP(s1, REG_ITMP2);
1938 emit_beq(cd, iptr->dst.block);
1941 case ICMD_IFLT: /* ..., value ==> ... */
1943 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1945 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1946 M_CMP_IMM(s1, iptr->sx.val.i);
1949 ICONST(REG_ITMP2, iptr->sx.val.i);
1950 M_CMP(s1, REG_ITMP2);
1952 emit_blt(cd, iptr->dst.block);
1955 case ICMD_IFLE: /* ..., value ==> ... */
1957 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1959 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1960 M_CMP_IMM(s1, iptr->sx.val.i);
1963 ICONST(REG_ITMP2, iptr->sx.val.i);
1964 M_CMP(s1, REG_ITMP2);
1966 emit_ble(cd, iptr->dst.block);
1969 case ICMD_IFNE: /* ..., value ==> ... */
1971 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1973 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1974 M_CMP_IMM(s1, iptr->sx.val.i);
1977 ICONST(REG_ITMP2, iptr->sx.val.i);
1978 M_CMP(s1, REG_ITMP2);
1980 emit_bne(cd, iptr->dst.block);
1983 case ICMD_IFGT: /* ..., value ==> ... */
1985 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1987 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1988 M_CMP_IMM(s1, iptr->sx.val.i);
1991 ICONST(REG_ITMP2, iptr->sx.val.i);
1992 M_CMP(s1, REG_ITMP2);
1994 emit_bgt(cd, iptr->dst.block);
1997 case ICMD_IFGE: /* ..., value ==> ... */
1999 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2001 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2002 M_CMP_IMM(s1, iptr->sx.val.i);
2005 ICONST(REG_ITMP2, iptr->sx.val.i);
2006 M_CMP(s1, REG_ITMP2);
2008 emit_bge(cd, iptr->dst.block);
2011 case ICMD_IF_LEQ: /* ..., value ==> ... */
2013 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2014 if (iptr->sx.val.l == 0)
2015 emit_beqz(cd, iptr->dst.block, s1);
2017 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2018 M_CMP_IMM(s1, iptr->sx.val.l);
2021 LCONST(REG_ITMP2, iptr->sx.val.l);
2022 M_CMP(s1, REG_ITMP2);
2024 emit_beq_xcc(cd, iptr->dst.block);
2028 case ICMD_IF_LLT: /* ..., value ==> ... */
2030 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2031 if (iptr->sx.val.l == 0)
2032 emit_bltz(cd, iptr->dst.block, s1);
2034 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2035 M_CMP_IMM(s1, iptr->sx.val.l);
2038 LCONST(REG_ITMP2, iptr->sx.val.l);
2039 M_CMP(s1, REG_ITMP2);
2041 emit_blt_xcc(cd, iptr->dst.block);
2045 case ICMD_IF_LLE: /* ..., value ==> ... */
2047 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2048 if (iptr->sx.val.l == 0)
2049 emit_blez(cd, iptr->dst.block, s1);
2051 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2052 M_CMP_IMM(s1, iptr->sx.val.l);
2055 LCONST(REG_ITMP2, iptr->sx.val.l);
2056 M_CMP(s1, REG_ITMP2);
2058 emit_ble_xcc(cd, iptr->dst.block);
2062 case ICMD_IF_LNE: /* ..., value ==> ... */
2064 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2065 if (iptr->sx.val.l == 0)
2066 emit_bnez(cd, iptr->dst.block, s1);
2068 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2069 M_CMP_IMM(s1, iptr->sx.val.l);
2072 LCONST(REG_ITMP2, iptr->sx.val.l);
2073 M_CMP(s1, REG_ITMP2);
2075 emit_bne_xcc(cd, iptr->dst.block);
2079 case ICMD_IF_LGT: /* ..., value ==> ... */
2081 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2082 if (iptr->sx.val.l == 0)
2083 emit_bgtz(cd, iptr->dst.block, s1);
2085 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2086 M_CMP_IMM(s1, iptr->sx.val.l);
2089 LCONST(REG_ITMP2, iptr->sx.val.l);
2090 M_CMP(s1, REG_ITMP2);
2092 emit_bgt_xcc(cd, iptr->dst.block);
2096 case ICMD_IF_LGE: /* ..., value ==> ... */
2098 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2099 if (iptr->sx.val.l == 0)
2100 emit_bgez(cd, iptr->dst.block, s1);
2102 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2103 M_CMP_IMM(s1, iptr->sx.val.l);
2106 LCONST(REG_ITMP2, iptr->sx.val.l);
2107 M_CMP(s1, REG_ITMP2);
2109 emit_bge_xcc(cd, iptr->dst.block);
2114 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2115 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2117 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2118 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2120 emit_beq_xcc(cd, iptr->dst.block);
2123 case ICMD_IF_ICMPEQ: /* 32-bit compare */
2125 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2126 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2128 emit_beq(cd, iptr->dst.block);
2131 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
2132 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2134 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2135 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2137 emit_bne_xcc(cd, iptr->dst.block);
2140 case ICMD_IF_ICMPNE: /* 32-bit compare */
2142 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2143 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2145 emit_bne(cd, iptr->dst.block);
2148 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2150 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2151 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2153 emit_blt_xcc(cd, iptr->dst.block);
2156 case ICMD_IF_ICMPLT: /* 32-bit compare */
2158 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2159 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2161 emit_blt(cd, iptr->dst.block);
2164 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2166 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2167 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2169 emit_bgt_xcc(cd, iptr->dst.block);
2172 case ICMD_IF_ICMPGT: /* 32-bit compare */
2174 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2175 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2177 emit_bgt(cd, iptr->dst.block);
2180 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2182 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2183 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2185 emit_ble_xcc(cd, iptr->dst.block);
2188 case ICMD_IF_ICMPLE: /* 32-bit compare */
2190 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2191 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2193 emit_ble(cd, iptr->dst.block);
2197 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2199 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2200 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2202 emit_bge_xcc(cd, iptr->dst.block);
2205 case ICMD_IF_ICMPGE: /* 32-bit compare */
2207 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2208 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2210 emit_bge(cd, iptr->dst.block);
2214 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2217 REPLACEMENT_POINT_RETURN(cd, iptr);
2219 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2220 M_INTMOVE(s1, REG_RESULT_CALLEE);
2221 goto nowperformreturn;
2223 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2225 REPLACEMENT_POINT_RETURN(cd, iptr);
2227 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2228 M_INTMOVE(s1, REG_RESULT_CALLEE);
2230 #ifdef ENABLE_VERIFIER
2231 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2232 unresolved_class *uc = iptr->sx.s23.s2.uc;
2234 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2236 #endif /* ENABLE_VERIFIER */
2237 goto nowperformreturn;
2239 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2242 REPLACEMENT_POINT_RETURN(cd, iptr);
2244 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2245 M_DBLMOVE(s1, REG_FRESULT);
2246 goto nowperformreturn;
2248 case ICMD_RETURN: /* ... ==> ... */
2250 REPLACEMENT_POINT_RETURN(cd, iptr);
2256 p = cd->stackframesize;
2258 #if !defined(NDEBUG)
2259 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2260 emit_verbosecall_exit(jd);
2263 #if defined(ENABLE_THREADS)
2264 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2265 /* XXX jit-c-call */
2266 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2267 M_ALD(REG_ITMP3, REG_PV, disp);
2269 /* we need to save fp return value (int saved by window) */
2271 switch (iptr->opc) {
2274 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
2275 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2276 M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2278 /* restore the fp return value */
2280 M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
2286 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2287 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2298 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
2304 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2307 branch_target_t *table;
2309 table = iptr->dst.table;
2311 l = iptr->sx.s23.s2.tablelow;
2312 i = iptr->sx.s23.s3.tablehigh;
2314 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2316 M_INTMOVE(s1, REG_ITMP1);
2318 else if (l <= 4095) {
2319 M_ADD_IMM(s1, -l, REG_ITMP1);
2322 ICONST(REG_ITMP2, l);
2323 /* XXX: do I need to truncate s1 to 32-bit ? */
2324 M_SUB(s1, REG_ITMP2, REG_ITMP1);
2332 M_CMP_IMM(REG_ITMP1, i - 1);
2335 ICONST(REG_ITMP2, i - 1);
2336 M_CMP(REG_ITMP1, REG_ITMP2);
2338 emit_bugt(cd, table[0].block); /* default target */
2340 /* build jump table top down and use address of lowest entry */
2345 dseg_add_target(cd, table->block);
2350 /* length of dataseg after last dseg_addtarget is used by load */
2352 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
2353 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2354 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2355 M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
2360 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2363 lookup_target_t *lookup;
2365 lookup = iptr->dst.lookup;
2367 i = iptr->sx.s23.s2.lookupcount;
2369 MCODECHECK((i<<2)+8);
2370 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2373 if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
2374 M_CMP_IMM(s1, lookup->value);
2376 ICONST(REG_ITMP2, lookup->value);
2377 M_CMP(s1, REG_ITMP2);
2379 emit_beq(cd, lookup->target.block);
2383 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2389 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
2391 REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
2393 bte = iptr->sx.s23.s3.bte;
2396 /* XXX: builtin calling with stack arguments not implemented */
2397 assert(md->paramcount <= 4 && md->argfltreguse <= 16);
2399 s3 = md->paramcount;
2401 MCODECHECK((s3 << 1) + 64);
2403 #ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
2405 /* copy float arguments according to ABI convention */
2407 int num_fltregargs = 0;
2408 int fltregarg_inswap[16];
2410 for (s3 = s3 - 1; s3 >= 0; s3--) {
2411 var = VAR(iptr->sx.s23.s2.args[s3]);
2413 if (IS_FLT_DBL_TYPE(var->type)) {
2414 if (!md->params[s3].inmemory) {
2415 s1 = s3; /*native flt args use argument index directly*/
2416 d = emit_load(jd, iptr, var, REG_FTMP1);
2419 fltregarg_inswap[num_fltregargs] = s1;
2421 /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
2430 /* move swapped float args to target regs */
2431 for (i = 0; i < num_fltregargs; i++) {
2432 s1 = fltregarg_inswap[i];
2433 M_DMOV(s1 + 16, s1);
2434 /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
2438 assert(md->argfltreguse == 0);
2443 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2444 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2445 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2446 case ICMD_INVOKEINTERFACE:
2448 REPLACEMENT_POINT_INVOKE(cd, iptr);
2450 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2452 um = iptr->sx.s23.s3.um;
2453 md = um->methodref->parseddesc.md;
2456 lm = iptr->sx.s23.s3.fmiref->p.method;
2458 md = lm->parseddesc;
2462 s3 = md->paramcount;
2464 MCODECHECK((s3 << 1) + 64);
2466 /* copy arguments to registers or stack location */
2468 for (s3 = s3 - 1; s3 >= 0; s3--) {
2469 var = VAR(iptr->sx.s23.s2.args[s3]);
2470 d = md->params[s3].regoff;
2472 if (var->flags & PREALLOC)
2475 if (IS_INT_LNG_TYPE(var->type)) {
2476 if (!md->params[s3].inmemory) {
2477 s1 = emit_load(jd, iptr, var, d);
2481 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2482 M_STX(s1, REG_SP, JITSTACK + d);
2486 #ifdef BUILTIN_FLOAT_ARGS
2487 if (iptr->opc == ICMD_BUILTIN)
2491 if (!md->params[s3].inmemory) {
2492 s1 = emit_load(jd, iptr, var, d);
2493 if (IS_2_WORD_TYPE(var->type))
2499 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2500 M_DST(s1, REG_SP, JITSTACK + d);
2505 switch (iptr->opc) {
2507 if (bte->stub == NULL) {
2508 disp = dseg_add_functionptr(cd, bte->fp);
2511 disp = dseg_add_functionptr(cd, bte->stub);
2514 M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
2516 /* XXX jit-c-call */
2517 /* generate the actual call */
2519 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2521 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2522 REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
2523 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2524 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2525 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2527 emit_exception_check(cd, iptr);
2528 if (md->returntype.type == TYPE_FLT) {
2529 /* special handling for float return value in %f0 */
2534 case ICMD_INVOKESPECIAL:
2535 emit_nullpointer_check(cd, iptr, REG_OUT0);
2538 case ICMD_INVOKESTATIC:
2540 disp = dseg_add_unique_address(cd, NULL);
2542 codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
2546 disp = dseg_add_address(cd, lm->stubroutine);
2548 M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
2550 /* generate the actual call */
2552 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2554 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2555 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2556 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2557 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2560 case ICMD_INVOKEVIRTUAL:
2561 emit_nullpointer_check(cd, iptr, REG_OUT0);
2564 codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
2569 s1 = OFFSET(vftbl_t, table[0]) +
2570 sizeof(methodptr) * lm->vftblindex;
2572 /* implicit null-pointer check */
2573 M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_objectheader, vftbl));
2574 M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
2576 /* generate the actual call */
2578 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2580 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2581 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2582 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2583 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2586 case ICMD_INVOKEINTERFACE:
2587 emit_nullpointer_check(cd, iptr, REG_OUT0);
2590 codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
2596 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2597 sizeof(methodptr*) * lm->class->index;
2599 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2602 /* implicit null-pointer check */
2603 M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_objectheader, vftbl));
2604 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2605 M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
2607 /* generate the actual call */
2609 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2611 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2612 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2613 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2614 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2618 /* store return value */
2620 d = md->returntype.type;
2622 if (d != TYPE_VOID) {
2623 if (IS_INT_LNG_TYPE(d)) {
2624 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2625 M_INTMOVE(REG_RESULT_CALLER, s1);
2628 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2629 if (IS_2_WORD_TYPE(d)) {
2630 M_DBLMOVE(REG_FRESULT, s1);
2632 M_FLTMOVE(REG_FRESULT, s1);
2635 emit_store_dst(jd, iptr, s1);
2640 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2641 /* val.a: (classinfo*) superclass */
2643 /* superclass is an interface:
2645 * OK if ((sub == NULL) ||
2646 * (sub->vftbl->interfacetablelength > super->index) &&
2647 * (sub->vftbl->interfacetable[-super->index] != NULL));
2649 * superclass is a class:
2651 * OK if ((sub == NULL) || (0
2652 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2653 * super->vftbl->diffvall));
2656 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2660 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2665 super = iptr->sx.s23.s3.c.cls;
2666 superindex = super->index;
2669 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2670 CODEGEN_CRITICAL_SECTION_NEW;
2672 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2674 /* if class is not resolved, check which code to call */
2676 if (super == NULL) {
2677 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2679 cr = iptr->sx.s23.s3.c.ref;
2680 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2682 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2685 M_ILD(REG_ITMP2, REG_PV, disp);
2686 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2687 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
2690 /* interface checkcast code */
2692 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2693 if (super == NULL) {
2694 cr = iptr->sx.s23.s3.c.ref;
2696 codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
2700 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2703 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2704 M_ILD(REG_ITMP3, REG_ITMP2,
2705 OFFSET(vftbl_t, interfacetablelength));
2706 M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
2707 emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
2709 M_ALD(REG_ITMP3, REG_ITMP2,
2710 OFFSET(vftbl_t, interfacetable[0]) -
2711 superindex * sizeof(methodptr*));
2712 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
2715 emit_label_br(cd, BRANCH_LABEL_4);
2717 emit_label(cd, BRANCH_LABEL_3);
2720 /* class checkcast code */
2722 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2723 if (super == NULL) {
2724 emit_label(cd, BRANCH_LABEL_2);
2726 cr = iptr->sx.s23.s3.c.ref;
2727 disp = dseg_add_unique_address(cd, NULL);
2729 codegen_add_patch_ref(cd,
2730 PATCHER_checkcast_instanceof_class,
2734 disp = dseg_add_address(cd, super->vftbl);
2736 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2739 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2740 M_ALD(REG_ITMP3, REG_PV, disp);
2742 CODEGEN_CRITICAL_SECTION_START;
2744 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2745 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2746 M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2747 M_ALD(REG_ITMP3, REG_PV, disp);
2748 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2750 CODEGEN_CRITICAL_SECTION_END;
2753 M_CMP(REG_ITMP3, REG_ITMP2);
2754 emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
2757 emit_label(cd, BRANCH_LABEL_5);
2760 if (super == NULL) {
2761 emit_label(cd, BRANCH_LABEL_1);
2762 emit_label(cd, BRANCH_LABEL_4);
2765 d = codegen_reg_of_dst(jd, iptr, s1);
2768 /* array type cast-check */
2770 s1 = emit_load_s1(jd, iptr, REG_OUT0);
2771 M_INTMOVE(s1, REG_OUT0);
2773 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2775 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2776 cr = iptr->sx.s23.s3.c.ref;
2777 disp = dseg_add_unique_address(cd, NULL);
2779 codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
2783 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2785 M_ALD(REG_OUT1, REG_PV, disp);
2786 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2787 M_ALD(REG_ITMP3, REG_PV, disp);
2788 /* XXX jit-c-call */
2789 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2792 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2793 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
2795 d = codegen_reg_of_dst(jd, iptr, s1);
2799 emit_store_dst(jd, iptr, d);
2802 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2803 /* val.a: (classinfo*) superclass */
2805 /* superclass is an interface:
2807 * return (sub != NULL) &&
2808 * (sub->vftbl->interfacetablelength > super->index) &&
2809 * (sub->vftbl->interfacetable[-super->index] != NULL);
2811 * superclass is a class:
2813 * return ((sub != NULL) && (0
2814 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2815 * super->vftbl->diffvall));
2820 vftbl_t *supervftbl;
2823 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2829 super = iptr->sx.s23.s3.c.cls;
2830 superindex = super->index;
2831 supervftbl = super->vftbl;
2834 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2835 CODEGEN_CRITICAL_SECTION_NEW;
2837 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2838 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2840 M_MOV(s1, REG_ITMP1);
2846 /* if class is not resolved, check which code to call */
2848 if (super == NULL) {
2849 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2851 cr = iptr->sx.s23.s3.c.ref;
2852 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2854 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2857 M_ILD(REG_ITMP3, REG_PV, disp);
2858 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2859 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
2862 /* interface instanceof code */
2864 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2865 if (super == NULL) {
2866 cr = iptr->sx.s23.s3.c.ref;
2868 codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
2872 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2875 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2876 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2877 M_CMP_IMM(REG_ITMP3, superindex);
2880 M_ALD(REG_ITMP1, REG_ITMP1,
2881 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2882 superindex * sizeof(methodptr*)));
2883 M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
2886 emit_label_br(cd, BRANCH_LABEL_4);
2888 emit_label(cd, BRANCH_LABEL_3);
2891 /* class instanceof code */
2893 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2894 if (super == NULL) {
2895 emit_label(cd, BRANCH_LABEL_2);
2897 cr = iptr->sx.s23.s3.c.ref;
2898 disp = dseg_add_unique_address(cd, NULL);
2900 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
2904 disp = dseg_add_address(cd, supervftbl);
2906 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2909 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2910 M_ALD(REG_ITMP2, REG_PV, disp);
2912 CODEGEN_CRITICAL_SECTION_START;
2914 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2915 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2916 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2918 CODEGEN_CRITICAL_SECTION_END;
2920 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2921 M_CMP(REG_ITMP1, REG_ITMP2);
2922 M_XCMOVULE_IMM(1, d);
2925 emit_label(cd, BRANCH_LABEL_5);
2928 if (super == NULL) {
2929 emit_label(cd, BRANCH_LABEL_1);
2930 emit_label(cd, BRANCH_LABEL_4);
2933 emit_store_dst(jd, iptr, d);
2937 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2939 /* check for negative sizes and copy sizes to stack if necessary */
2941 MCODECHECK((iptr->s1.argcount << 1) + 64);
2943 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2945 var = VAR(iptr->sx.s23.s2.args[s1]);
2947 /* copy SAVEDVAR sizes to stack */
2949 /* Already Preallocated? */
2951 if (!(var->flags & PREALLOC)) {
2952 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2953 M_STX(s2, REG_SP, CSTACK + (s1 * 8));
2957 /* arg 0 = dimension count */
2959 ICONST(REG_OUT0, iptr->s1.argcount);
2961 /* is patcher function set? */
2963 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2964 disp = dseg_add_unique_address(cd, 0);
2966 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
2967 iptr->sx.s23.s3.c.ref,
2971 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2973 /* arg 1 = arraydescriptor */
2975 M_ALD(REG_OUT1, REG_PV, disp);
2977 /* arg 2 = pointer to dimensions = stack pointer (absolute) */
2979 M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
2981 /* XXX c abi call */
2982 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2983 M_ALD(REG_ITMP3, REG_PV, disp);
2984 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2987 /* check for exception before result assignment */
2989 emit_exception_check(cd, iptr);
2991 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2992 M_INTMOVE(REG_RESULT_CALLER, d);
2993 emit_store_dst(jd, iptr, d);
2997 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
3003 } /* for instruction */
3007 /* At the end of a basic block we may have to append some nops,
3008 because the patcher stub calling code might be longer than the
3009 actual instruction. So codepatching does not change the
3010 following block unintentionally. */
3012 if (cd->mcodeptr < cd->lastmcodeptr) {
3013 while (cd->mcodeptr < cd->lastmcodeptr) {
3018 } /* if (bptr -> flags >= BBREACHED) */
3019 } /* for basic block */
3021 dseg_createlinenumbertable(cd);
3023 /* generate stubs */
3025 emit_patcher_stubs(jd);
3027 /* everything's ok */
3033 /* codegen_emit_stub_compiler **************************************************
3035 Emits a stub routine which calls the compiler.
3037 *******************************************************************************/
3039 void codegen_emit_stub_compiler(jitdata *jd)
3044 /* get required compiler data */
3049 /* code for the stub */
3051 /* no window save yet, user caller's PV */
3052 M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */
3053 M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */
3054 M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */
3059 /* codegen_emit_stub_builtin ***************************************************
3061 Creates a stub routine which calls a builtin function.
3063 *******************************************************************************/
3065 void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
3074 /* get required compiler data */
3078 /* set some variables */
3081 /* calculate stack frame size */
3082 cd->stackframesize =
3086 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3087 4; /* 4 arguments or return value */
3090 /* keep stack 16-byte aligned (ABI requirement) */
3092 if (cd->stackframesize & 1)
3093 cd->stackframesize++;
3095 /* create method header */
3096 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3097 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3098 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3099 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3100 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3101 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3102 (void) dseg_addlinenumbertablesize(cd);
3103 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3106 /* generate stub code */
3107 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3109 #if defined(ENABLE_GC_CACAO)
3110 /* Save callee saved integer registers in stackframeinfo (GC may
3111 need to recover them during a collection). */
3113 disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
3114 OFFSET(stackframeinfo, intregs) + BIAS;
3116 for (i = 0; i < INT_SAV_CNT; i++)
3117 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3120 for (i = 0; i < md->paramcount; i++) {
3121 s1 = md->params[i].regoff;
3123 switch (md->paramtypes[i].type) {
3130 M_DST(s1, REG_SP, JITSTACK + i * 8);
3135 /* create dynamic stack info */
3137 M_AADD_IMM(REG_SP, BIAS + cd->stackframesize * 8, REG_OUT0); /* data sp*/
3138 M_MOV(REG_PV_CALLEE, REG_OUT1); /* PV */
3139 M_MOV(REG_FP, REG_OUT2); /* java sp */
3140 M_MOV(REG_RA_CALLEE, REG_OUT3); /* ra */
3142 disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
3143 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3144 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3145 M_NOP; /* XXX fill me! */
3148 /* builtins are allowed to have 5 arguments max */
3150 assert(md->paramcount <= 5);
3152 /* copy arguments into position */
3154 for (i = 0; i < md->paramcount; i++) {
3155 assert(!md->params[i].inmemory);
3157 s1 = md->params[i].regoff;
3159 switch (md->paramtypes[i].type) {
3163 M_MOV(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[i]), s1);
3167 M_DLD(s1, REG_SP, JITSTACK + i * 8);
3173 /* call the builtin function */
3175 disp = dseg_add_functionptr(cd, bte->fp);
3176 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); /* load adress of builtin */
3177 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call builtin */
3178 M_NOP; /* delay slot */
3181 /* save return value */
3183 if (md->returntype.type != TYPE_VOID) {
3184 if (IS_INT_LNG_TYPE(md->returntype.type))
3185 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3187 M_DST(REG_FRESULT, REG_SP, CSTACK);
3191 /* remove native stackframe info */
3193 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3194 disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
3195 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3196 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3199 /* restore float return value, int return value already in our return reg */
3201 if (md->returntype.type != TYPE_VOID) {
3202 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3203 if (IS_2_WORD_TYPE(md->returntype.type))
3204 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3206 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3211 #if defined(ENABLE_GC_CACAO)
3212 /* Restore callee saved integer registers from stackframeinfo (GC
3213 might have modified them during a collection). */
3215 disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
3216 OFFSET(stackframeinfo, intregs) + BIAS;
3218 for (i = 0; i < INT_SAV_CNT; i++)
3219 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3223 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3230 /* codegen_emit_stub_native ****************************************************
3232 Emits a stub routine which calls a native method.
3234 *******************************************************************************/
3236 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3243 s4 i, j; /* count variables */
3246 s4 funcdisp; /* displacement of the function */
3247 s4 fltregarg_offset[FLT_ARG_CNT];
3249 /* get required compiler data */
3255 /* initialize variables */
3258 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3260 /* calculate stack frame size */
3262 cd->stackframesize =
3263 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3264 sizeof(localref_table) / SIZEOF_VOID_P +
3265 md->paramcount + /* for saving arguments over calls */
3266 nmd->memuse + /* nmd knows about the native stackframe layout */
3270 /* keep stack 16-byte aligned (ABI requirement) */
3272 if (cd->stackframesize & 1)
3273 cd->stackframesize++;
3275 /* create method header */
3277 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3278 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3279 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3280 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3281 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3282 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3283 (void) dseg_addlinenumbertablesize(cd);
3284 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3286 /* generate stub code */
3288 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3290 #if !defined(NDEBUG)
3291 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3292 emit_verbosecall_enter(jd);
3295 /* get function address (this must happen before the stackframeinfo) */
3297 funcdisp = dseg_add_functionptr(cd, f);
3299 #if !defined(WITH_STATIC_CLASSPATH)
3301 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
3305 /* save float argument registers (into abi parameter slots) */
3307 assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
3309 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3310 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3311 s1 = WINSAVE_CNT + nmd->memuse + j;
3312 M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
3313 fltregarg_offset[i] = s1; /* remember stack offset */
3318 /* prepare data structures for native function call */
3320 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */
3321 M_MOV(REG_PV_CALLEE, REG_OUT1);
3322 M_MOV(REG_FP, REG_OUT2); /* java sp */
3323 M_MOV(REG_RA_CALLEE, REG_OUT3);
3324 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3325 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3326 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3327 M_NOP; /* XXX fill me! */
3329 /* keep float arguments on stack */
3331 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3332 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3333 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
3339 /* copy or spill arguments to new locations */
3341 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3342 t = md->paramtypes[i].type;
3344 if (IS_INT_LNG_TYPE(t)) {
3346 /* integral types */
3348 if (!md->params[i].inmemory) {
3349 s1 = md->params[i].regoff;
3350 /* s1 refers to the old window, transpose */
3351 s1 = REG_WINDOW_TRANSPOSE(s1);
3353 if (!nmd->params[j].inmemory) {
3354 s2 = nat_argintregs[nmd->params[j].regoff];
3357 /* nmd's regoff is relative to the start of the param array */
3358 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3359 M_AST(s1, REG_SP, s2);
3363 if (!nmd->params[j].inmemory) {
3364 /* JIT stack arg -> NAT reg arg */
3366 /* Due to the Env pointer that is always passed, the 6th JIT arg */
3367 /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */
3369 assert(false); /* path never taken */
3372 s1 = md->params[i].regoff + cd->stackframesize * 8;
3373 s2 = BIAS + WINSAVE_CNT + 8 + nmd->params[j].regoff;
3374 M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
3375 M_AST(REG_ITMP1, REG_SP, s2);
3380 /* floating point types */
3382 if (!md->params[i].inmemory) {
3383 s1 = md->params[i].regoff;
3385 if (!nmd->params[j].inmemory) {
3387 /* no mapping to regs needed, native flt args use regoff */
3388 s2 = nmd->params[j].regoff;
3390 /* JIT float regs are still on the stack */
3391 M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8));
3394 /* not supposed to happen with 16 NAT flt args */
3397 s2 = nmd->params[j].regoff;
3398 if (IS_2_WORD_TYPE(t))
3399 M_DST(s1, REG_SP, CSTACK + (s2 * 8));
3401 M_FST(s1, REG_SP, CSTACK + (s2 * 8));
3407 s1 = md->params[i].regoff + cd->stackframesize * 8;
3409 if (!nmd->params[j].inmemory) {
3411 /* JIT stack -> NAT reg */
3413 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3414 M_DLD(s2, REG_SP, s1);
3418 /* JIT stack -> NAT stack */
3420 s2 = nmd->params[j].regoff - 6 * 8;
3422 /* The FTMP register may already be loaded with args */
3423 /* we know $f0 is unused because of the env pointer */
3424 M_DLD(REG_F0, REG_SP, CSTACK + s1);
3425 M_DST(REG_F0, REG_SP, CSTACK + s2);
3432 /* put class into second argument register */
3434 if (m->flags & ACC_STATIC) {
3435 disp = dseg_add_address(cd, m->class);
3436 M_ALD(REG_OUT1, REG_PV_CALLEE, disp);
3439 /* put env into first argument register */
3441 disp = dseg_add_address(cd, _Jv_env);
3442 M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
3444 /* do the native function call */
3446 M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method */
3447 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method */
3448 M_NOP; /* delay slot */
3450 /* save return value */
3452 if (md->returntype.type != TYPE_VOID) {
3453 if (IS_INT_LNG_TYPE(md->returntype.type))
3454 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3456 M_DST(REG_FRESULT, REG_SP, CSTACK);
3459 /* Note: native functions return float values in %f0 (see ABI) */
3460 /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
3462 #if !defined(NDEBUG)
3463 /* But for the trace function we need to put a flt result into %f1 */
3464 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3465 if (!IS_2_WORD_TYPE(md->returntype.type))
3466 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3467 emit_verbosecall_exit(jd);
3471 /* remove native stackframe info */
3473 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3474 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3475 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3476 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3477 M_NOP; /* XXX fill me! */
3478 M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
3480 /* restore float return value, int return value already in our return reg */
3482 if (md->returntype.type != TYPE_VOID) {
3483 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3484 if (IS_2_WORD_TYPE(md->returntype.type))
3485 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3487 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3491 /* check for exception */
3492 M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
3495 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3498 /* handle exception */
3500 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3501 M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */
3502 M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */
3503 M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */
3504 M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
3506 /* generate patcher stubs */
3508 emit_patcher_stubs(jd);
3512 * These are local overrides for various environment variables in Emacs.
3513 * Please do not remove this and leave it at the end of the file, where
3514 * Emacs will automagically detect them.
3515 * ---------------------------------------------------------------------
3518 * indent-tabs-mode: t
3522 * vim:noexpandtab:sw=4:ts=4: