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 = (code_is_leafmethod(code)) ? 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 /* REMOVEME: We still need it for exception handling in assembler. */
207 if (code_is_leafmethod(code))
208 (void) dseg_add_unique_s4(cd, 1);
210 (void) dseg_add_unique_s4(cd, 0);
212 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
213 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
214 dseg_addlinenumbertablesize(cd);
215 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
217 /* create exception table */
219 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
220 dseg_add_target(cd, ex->start);
221 dseg_add_target(cd, ex->end);
222 dseg_add_target(cd, ex->handler);
223 (void) dseg_add_unique_address(cd, ex->catchtype.any);
226 /* save register window and create stack frame (if necessary) */
228 if (cd->stackframesize) {
229 if (cd->stackframesize <= 4095)
230 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
232 M_ILD_INTERN(REG_ITMP3, REG_PV_CALLER, framesize_disp);
233 M_SUB(REG_ZERO, REG_ITMP3, REG_ITMP3);
234 M_SAVE_REG(REG_SP, REG_ITMP3, REG_SP);
238 /* save callee saved float registers (none right now) */
240 p = cd->stackframesize;
241 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
242 p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
247 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
248 emit_verbosecall_enter(jd);
252 /* call monitorenter function */
253 #if defined(ENABLE_THREADS)
254 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
255 /* stack offset for monitor argument */
259 /* save float argument registers */
263 ALIGN_STACK_SLOTS(slots);
265 M_LDA(REG_SP, REG_SP, -(slots * 8));
266 for (i = 0; i < FLT_ARG_CNT; i++)
267 M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
271 /* get correct lock object */
273 if (m->flags & ACC_STATIC) {
274 disp = dseg_add_address(cd, &m->class->object.header);
275 M_ALD(REG_OUT0, REG_PV, disp);
276 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
277 M_ALD(REG_ITMP3, REG_PV, disp);
280 /* copy class pointer: $i0 -> $o0 */
281 M_MOV(REG_RESULT_CALLEE, REG_OUT0);
283 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
284 M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
285 M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
288 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
289 M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */
291 /* restore float argument registers */
293 for (i = 0; i < FLT_ARG_CNT; i++)
294 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
296 M_LDA(REG_SP, REG_SP, slots * 8);
301 /* take arguments out of register or stack frame */
305 for (p = 0, l = 0; p < md->paramcount; p++) {
306 t = md->paramtypes[p].type;
308 varindex = jd->local_map[l * 5 + t];
311 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
314 if (varindex == UNUSED)
318 s1 = md->params[p].regoff;
320 if (IS_INT_LNG_TYPE(t)) { /* integer args */
324 if (!md->params[p].inmemory) { /* register arguments */
325 s1 = REG_WINDOW_TRANSPOSE(s1);
327 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
329 /* the register allocator does not know about the window. */
330 /* avoid copying the locals from save to save regs by */
331 /* swapping variables. */
334 int old_dest = var->vv.regoff;
335 int new_dest = p + 24;
337 /* run through all variables */
339 for (i = 0; i < jd->varcount; i++) {
340 varinfo* uvar = VAR(i);
342 if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags))
345 s2 = uvar->vv.regoff;
347 /* free the in reg by moving all other references */
349 if (s2 == new_dest) {
350 uvar->vv.regoff = old_dest;
351 /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
354 /* move all variables to the in reg */
356 if (s2 == old_dest) {
357 uvar->vv.regoff = new_dest;
358 /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
366 else { /* reg arg -> spilled */
367 M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
370 } else { /* stack arguments */
371 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
372 M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1);
374 } else { /* stack arg -> spilled */
375 /* add the callers window save registers */
376 var->vv.regoff = cd->stackframesize * 8 + s1;
380 } else { /* floating args */
381 if (!md->params[p].inmemory) { /* register arguments */
382 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
383 M_FLTMOVE(s1, var->vv.regoff);
385 } else { /* reg arg -> spilled */
386 M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
389 } else { /* stack arguments */
390 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
391 M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1);
393 } else { /* stack-arg -> spilled */
394 var->vv.regoff = cd->stackframesize * 8 + s1;
403 /* end of header generation */
405 /* create replacement points */
407 REPLACEMENT_POINTS_INIT(cd, jd);
409 /* walk through all basic blocks */
411 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
413 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
415 if (bptr->flags >= BBREACHED) {
417 /* branch resolving */
419 codegen_resolve_branchrefs(cd, bptr);
421 /* handle replacement points */
423 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
426 /* copy interface registers to their destination */
431 #if defined(ENABLE_LSRA)
432 #error XXX LSRA not tested yet
436 src = bptr->invars[len];
437 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
438 /* d = reg_of_var(m, src, REG_ITMP1); */
439 if (!(src->flags & INMEMORY))
443 M_INTMOVE(REG_ITMP1, d);
444 emit_store(jd, NULL, src, d);
451 var = VAR(bptr->invars[len]);
452 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
453 d = codegen_reg_of_var(0, var, REG_ITMP1);
454 M_INTMOVE(REG_ITMP2_XPTR, d);
455 emit_store(jd, NULL, var, d);
458 assert((var->flags & INOUT));
461 #if defined(ENABLE_LSRA)
464 /* walk through all instructions */
468 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
469 if (iptr->line != currentline) {
470 dseg_addlinenumber(cd, iptr->line);
471 currentline = iptr->line;
474 MCODECHECK(64); /* an instruction usually needs < 64 words */
478 case ICMD_INLINE_START:
479 case ICMD_INLINE_END:
482 case ICMD_NOP: /* ... ==> ... */
485 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
487 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
488 emit_nullpointer_check(cd, iptr, s1);
491 /* constant operations ************************************************/
493 case ICMD_ICONST: /* ... ==> ..., constant */
495 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
496 ICONST(d, iptr->sx.val.i);
497 emit_store_dst(jd, iptr, d);
500 case ICMD_LCONST: /* ... ==> ..., constant */
502 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
503 LCONST(d, iptr->sx.val.l);
504 emit_store_dst(jd, iptr, d);
507 case ICMD_FCONST: /* ... ==> ..., constant */
509 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
510 disp = dseg_add_float(cd, iptr->sx.val.f);
511 M_FLD(d, REG_PV, disp);
512 emit_store_dst(jd, iptr, d);
515 case ICMD_DCONST: /* ... ==> ..., constant */
517 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
518 disp = dseg_add_double(cd, iptr->sx.val.d);
519 M_DLD(d, REG_PV, disp);
520 emit_store_dst(jd, iptr, d);
523 case ICMD_ACONST: /* ... ==> ..., constant */
525 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
527 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
528 cr = iptr->sx.val.c.ref;
529 disp = dseg_add_unique_address(cd, cr);
531 codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
533 M_ALD(d, REG_PV, disp);
537 if (iptr->sx.val.anyptr == NULL) {
538 M_INTMOVE(REG_ZERO, d);
541 disp = dseg_add_address(cd, iptr->sx.val.anyptr);
542 M_ALD(d, REG_PV, disp);
545 emit_store_dst(jd, iptr, d);
549 /* load/store/copy/move operations ************************************/
551 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
556 case ICMD_ISTORE: /* ..., value ==> ... */
567 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
572 /* pop/dup/swap operations ********************************************/
574 /* attention: double and longs are only one entry in CACAO ICMDs */
576 case ICMD_POP: /* ..., value ==> ... */
577 case ICMD_POP2: /* ..., value, value ==> ... */
581 /* integer operations *************************************************/
583 case ICMD_INEG: /* ..., value ==> ..., - value */
586 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
587 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
588 M_SUB(REG_ZERO, s1, d);
589 emit_store_dst(jd, iptr, d);
592 case ICMD_I2L: /* ..., value ==> ..., value */
594 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
595 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
597 emit_store_dst(jd, iptr, d);
600 case ICMD_L2I: /* ..., value ==> ..., value */
602 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
603 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
604 M_SRA_IMM(s1, 0, d); /* sign extend upper 32 bits */
605 emit_store_dst(jd, iptr, d);
608 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
610 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
611 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
612 M_SLLX_IMM(s1, 56, d);
613 M_SRAX_IMM( d, 56, d);
614 emit_store_dst(jd, iptr, d);
617 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
619 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
620 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
621 M_SLLX_IMM(s1, 48, d);
622 M_SRLX_IMM( d, 48, d);
623 emit_store_dst(jd, iptr, d);
626 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
628 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
629 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
630 M_SLLX_IMM(s1, 48, d);
631 M_SRAX_IMM( d, 48, d);
632 emit_store_dst(jd, iptr, d);
635 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
638 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
639 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
640 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
642 emit_store_dst(jd, iptr, d);
646 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
647 /* sx.val.i = constant */
649 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
650 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
651 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
652 M_ADD_IMM(s1, iptr->sx.val.i, d);
654 ICONST(REG_ITMP2, iptr->sx.val.i);
655 M_ADD(s1, REG_ITMP2, d);
657 emit_store_dst(jd, iptr, d);
660 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
661 /* sx.val.l = constant */
663 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
664 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
665 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
666 M_ADD_IMM(s1, iptr->sx.val.l, d);
668 LCONST(REG_ITMP2, iptr->sx.val.l);
669 M_ADD(s1, REG_ITMP2, d);
671 emit_store_dst(jd, iptr, d);
674 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
677 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
678 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
679 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
681 emit_store_dst(jd, iptr, d);
684 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
685 /* sx.val.i = constant */
687 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
688 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
689 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
690 M_SUB_IMM(s1, iptr->sx.val.i, d);
692 ICONST(REG_ITMP2, iptr->sx.val.i);
693 M_SUB(s1, REG_ITMP2, d);
695 emit_store_dst(jd, iptr, d);
698 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
699 /* sx.val.l = constant */
701 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
702 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
703 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
704 M_SUB_IMM(s1, iptr->sx.val.l, d);
706 LCONST(REG_ITMP2, iptr->sx.val.l);
707 M_SUB(s1, REG_ITMP2, d);
709 emit_store_dst(jd, iptr, d);
712 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
715 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
716 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
717 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
719 emit_store_dst(jd, iptr, d);
722 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
723 /* sx.val.i = constant */
725 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
726 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
727 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
728 M_MULX_IMM(s1, iptr->sx.val.i, d);
730 ICONST(REG_ITMP2, iptr->sx.val.i);
731 M_MULX(s1, REG_ITMP2, d);
733 emit_store_dst(jd, iptr, d);
736 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
737 /* sx.val.l = constant */
739 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
740 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
741 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
742 M_MULX_IMM(s1, iptr->sx.val.l, d);
744 LCONST(REG_ITMP2, iptr->sx.val.l);
745 M_MULX(s1, REG_ITMP2, d);
747 emit_store_dst(jd, iptr, d);
750 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
751 /* XXX could also clear Y and use 32bit div */
752 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
753 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
754 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
755 emit_arithmetic_check(cd, iptr, s2);
757 /* XXX trim s2 like s1 ? */
759 emit_store_dst(jd, iptr, d);
762 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
764 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
765 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
766 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
767 emit_arithmetic_check(cd, iptr, s2);
769 emit_store_dst(jd, iptr, d);
772 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
774 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
775 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
776 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
777 emit_arithmetic_check(cd, iptr, s2);
779 /* XXX trim s2 like s1 ? */
780 M_DIVX(s1, s2, REG_ITMP3);
781 M_MULX(s2, REG_ITMP3, REG_ITMP3);
782 M_SUB(s1, REG_ITMP3, d);
783 emit_store_dst(jd, iptr, d);
786 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
788 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
789 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
790 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
791 emit_arithmetic_check(cd, iptr, s2);
792 M_DIVX(s1, s2, REG_ITMP3);
793 M_MULX(s2, REG_ITMP3, REG_ITMP3);
794 M_SUB(s1, REG_ITMP3, d);
795 emit_store_dst(jd, iptr, d);
798 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
799 case ICMD_LDIVPOW2: /* val.i = constant */
801 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
802 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
803 M_SRAX_IMM(s1, 63, REG_ITMP2);
804 M_SRLX_IMM(REG_ITMP2, 64 - iptr->sx.val.i, REG_ITMP2);
805 M_ADD(s1, REG_ITMP2, REG_ITMP2);
806 M_SRAX_IMM(REG_ITMP2, iptr->sx.val.i, d);
807 emit_store_dst(jd, iptr, d);
810 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
812 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
813 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
814 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
816 emit_store_dst(jd, iptr, d);
819 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
821 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
822 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
823 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
825 emit_store_dst(jd, iptr, d);
828 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
829 /* val.i = constant */
831 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
832 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
833 M_SLL_IMM(s1, iptr->sx.val.i, d);
834 emit_store_dst(jd, iptr, d);
837 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
838 /* val.i = constant */
840 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
841 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
842 M_SLLX_IMM(s1, iptr->sx.val.i, d);
843 emit_store_dst(jd, iptr, d);
846 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
848 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
849 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
850 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
852 emit_store_dst(jd, iptr, d);
855 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
856 /* sx.val.i = constant */
858 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
859 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
860 M_SRA_IMM(s1, iptr->sx.val.i, d);
861 emit_store_dst(jd, iptr, d);
864 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
866 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
867 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
868 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
870 emit_store_dst(jd, iptr, d);
873 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
874 /* sx.val.i = constant */
876 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
877 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
878 M_SRL_IMM(s1, iptr->sx.val.i, d);
879 emit_store_dst(jd, iptr, d);
882 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
884 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
885 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
886 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
888 emit_store_dst(jd, iptr, d);
891 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
892 /* sx.val.i = constant */
894 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
895 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
896 M_SRAX_IMM(s1, iptr->sx.val.i, d);
897 emit_store_dst(jd, iptr, d);
900 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
902 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
903 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
904 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
906 emit_store_dst(jd, iptr, d);
909 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
910 /* sx.val.i = constant */
912 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
913 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
914 M_SRLX_IMM(s1, iptr->sx.val.i, d);
915 emit_store_dst(jd, iptr, d);
918 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
921 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
922 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
923 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
925 emit_store_dst(jd, iptr, d);
928 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
929 /* sx.val.i = constant */
931 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
932 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
933 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
934 M_AND_IMM(s1, iptr->sx.val.i, d);
936 ICONST(REG_ITMP2, iptr->sx.val.i);
937 M_AND(s1, REG_ITMP2, d);
939 emit_store_dst(jd, iptr, d);
942 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
943 /* sx.val.i = constant */
944 /* constant is actually constant - 1 */
946 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
947 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
949 M_MOV(s1, REG_ITMP1);
952 M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
953 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
954 M_AND_IMM(s1, iptr->sx.val.i, d);
957 M_SUB(REG_ZERO, s1, d);
958 M_AND_IMM(d, iptr->sx.val.i, d);
960 ICONST(REG_ITMP2, iptr->sx.val.i);
961 M_AND(s1, REG_ITMP2, d);
964 M_SUB(REG_ZERO, s1, d);
965 M_AND(d, REG_ITMP2, d);
967 M_SUB(REG_ZERO, d, d);
968 emit_store_dst(jd, iptr, d);
971 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
972 /* sx.val.l = constant */
974 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
975 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
976 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
977 M_AND_IMM(s1, iptr->sx.val.l, d);
979 LCONST(REG_ITMP2, iptr->sx.val.l);
980 M_AND(s1, REG_ITMP2, d);
982 emit_store_dst(jd, iptr, d);
985 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
986 /* sx.val.l = constant */
988 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
989 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
991 M_MOV(s1, REG_ITMP1);
994 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
995 M_AND_IMM(s1, iptr->sx.val.l, d);
998 M_SUB(REG_ZERO, s1, d);
999 M_AND_IMM(d, iptr->sx.val.l, d);
1001 LCONST(REG_ITMP2, iptr->sx.val.l);
1002 M_AND(s1, REG_ITMP2, d);
1005 M_SUB(REG_ZERO, s1, d);
1006 M_AND(d, REG_ITMP2, d);
1008 M_SUB(REG_ZERO, d, d);
1009 emit_store_dst(jd, iptr, d);
1012 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1015 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1016 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1017 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1019 emit_store_dst(jd, iptr, d);
1022 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1023 /* sx.val.i = constant */
1025 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1026 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1027 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1028 M_OR_IMM(s1, iptr->sx.val.i, d);
1030 ICONST(REG_ITMP2, iptr->sx.val.i);
1031 M_OR(s1, REG_ITMP2, d);
1033 emit_store_dst(jd, iptr, d);
1036 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1037 /* sx.val.l = constant */
1039 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1040 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1041 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1042 M_OR_IMM(s1, iptr->sx.val.l, d);
1044 LCONST(REG_ITMP2, iptr->sx.val.l);
1045 M_OR(s1, REG_ITMP2, d);
1047 emit_store_dst(jd, iptr, d);
1050 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1053 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1054 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1055 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1057 emit_store_dst(jd, iptr, d);
1060 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1061 /* sx.val.i = constant */
1063 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1064 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1065 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1066 M_XOR_IMM(s1, iptr->sx.val.i, d);
1068 ICONST(REG_ITMP2, iptr->sx.val.i);
1069 M_XOR(s1, REG_ITMP2, d);
1071 emit_store_dst(jd, iptr, d);
1074 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1075 /* sx.val.l = constant */
1077 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1078 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1079 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1080 M_XOR_IMM(s1, iptr->sx.val.l, d);
1082 LCONST(REG_ITMP2, iptr->sx.val.l);
1083 M_XOR(s1, REG_ITMP2, d);
1085 emit_store_dst(jd, iptr, d);
1089 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1091 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1092 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1093 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1096 M_XCMOVLT_IMM(-1, d);
1097 M_XCMOVGT_IMM(1, d);
1098 emit_store_dst(jd, iptr, d);
1102 /* floating operations ************************************************/
1104 case ICMD_FNEG: /* ..., value ==> ..., - value */
1106 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1107 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1109 emit_store_dst(jd, iptr, d);
1112 case ICMD_DNEG: /* ..., value ==> ..., - value */
1114 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1115 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1117 emit_store_dst(jd, iptr, d);
1120 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1122 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1123 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1124 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1126 emit_store_dst(jd, iptr, d);
1129 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1131 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1132 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1133 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1135 emit_store_dst(jd, iptr, d);
1138 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1140 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1141 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1142 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1144 emit_store_dst(jd, iptr, d);
1147 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1149 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1150 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1151 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1153 emit_store_dst(jd, iptr, d);
1156 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1158 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1159 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1160 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1162 emit_store_dst(jd, iptr, d);
1165 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1167 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1168 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1169 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1171 emit_store_dst(jd, iptr, d);
1174 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1176 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1177 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1178 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1180 emit_store_dst(jd, iptr, d);
1183 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1185 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1186 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1187 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1189 emit_store_dst(jd, iptr, d);
1193 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1194 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1195 disp = dseg_add_unique_float(cd, 0.0);
1196 M_IST (s1, REG_PV_CALLEE, disp);
1197 M_FLD (d, REG_PV_CALLEE, disp);
1198 M_CVTIF (d, d); /* rd gets translated to double target register */
1199 emit_store_dst(jd, iptr, d);
1203 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1204 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1205 disp = dseg_add_unique_float(cd, 0.0);
1206 M_IST(s1, REG_PV_CALLEE, disp);
1207 M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
1208 M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
1209 emit_store_dst(jd, iptr, d);
1213 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1214 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1215 disp = dseg_add_unique_double(cd, 0.0);
1216 M_STX(s1, REG_PV_CALLEE, disp);
1217 M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
1218 M_CVTLF(REG_FTMP3, d);
1219 emit_store_dst(jd, iptr, d);
1223 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1224 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1225 disp = dseg_add_unique_double(cd, 0.0);
1226 M_STX(s1, REG_PV_CALLEE, disp);
1227 M_DLD(d, REG_PV_CALLEE, disp);
1229 emit_store_dst(jd, iptr, d);
1232 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1233 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1234 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1235 disp = dseg_add_unique_float(cd, 0.0);
1237 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1240 M_MOV(REG_ZERO, d); /* delay slot */
1242 M_CVTFI(s1, REG_FTMP2);
1243 M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
1244 M_ILD(d, REG_PV, disp);
1245 emit_store_dst(jd, iptr, d);
1249 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1250 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1251 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1252 disp = dseg_add_unique_float(cd, 0.0);
1254 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1257 M_MOV(REG_ZERO, d); /* delay slot */
1259 M_CVTDI(s1, REG_FTMP2);
1260 M_FST(REG_FTMP2, REG_PV, disp);
1261 M_ILD(d, REG_PV, disp);
1262 emit_store_dst(jd, iptr, d);
1265 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1266 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1267 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1268 disp = dseg_add_unique_double(cd, 0.0);
1270 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1273 M_MOV(REG_ZERO, d); /* delay slot */
1275 M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1276 M_DST(REG_FTMP2, REG_PV, disp);
1277 M_LDX(d, REG_PV, disp);
1278 emit_store_dst(jd, iptr, d);
1281 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1282 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1283 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1284 disp = dseg_add_unique_double(cd, 0.0);
1286 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1289 M_MOV(REG_ZERO, d); /* delay slot */
1291 M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1292 M_DST(REG_FTMP2, REG_PV, disp);
1293 M_LDX(d, REG_PV, disp);
1294 emit_store_dst(jd, iptr, d);
1297 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1299 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1300 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1302 emit_store_dst(jd, iptr, d);
1305 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1307 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1308 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1310 emit_store_dst(jd, iptr, d);
1313 /* XXX merge F/D versions? only compare instr. is different */
1314 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1316 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1317 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1318 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1320 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1321 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1322 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1323 emit_store_dst(jd, iptr, d);
1326 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1328 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1329 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1330 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1332 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1333 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1334 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1335 emit_store_dst(jd, iptr, d);
1338 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1340 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1341 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1342 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1344 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1345 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1346 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1347 emit_store_dst(jd, iptr, d);
1350 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1352 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1353 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1354 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1356 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1357 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1358 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1359 emit_store_dst(jd, iptr, d);
1363 /* memory operations **************************************************/
1365 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1367 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1368 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1369 emit_nullpointer_check(cd, iptr, s1);
1370 M_ILD(d, s1, OFFSET(java_array_t, size));
1371 emit_store_dst(jd, iptr, d);
1374 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1376 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1377 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1378 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1379 /* implicit null-pointer check */
1380 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1381 M_AADD(s2, s1, REG_ITMP3);
1382 M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray_t, data[0]));
1383 emit_store_dst(jd, iptr, d);
1386 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1388 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1389 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1390 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1391 /* implicit null-pointer check */
1392 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1393 M_AADD(s2, s1, REG_ITMP3);
1394 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1395 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray_t, data[0]));
1396 emit_store_dst(jd, iptr, d);
1399 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1401 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1402 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1403 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1404 /* implicit null-pointer check */
1405 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1406 M_AADD(s2, s1, REG_ITMP3);
1407 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1408 M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray_t, data[0]));
1409 emit_store_dst(jd, iptr, d);
1412 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1414 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1415 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1416 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1417 /* implicit null-pointer check */
1418 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1419 M_ASLL_IMM(s2, 2, REG_ITMP3);
1420 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1421 M_ILD(d, REG_ITMP3, OFFSET(java_intarray_t, data[0]));
1422 emit_store_dst(jd, iptr, d);
1425 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1427 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1428 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1429 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1430 /* implicit null-pointer check */
1431 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1432 M_ASLL_IMM(s2, 3, REG_ITMP3);
1433 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1434 M_LDX(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1435 emit_store_dst(jd, iptr, d);
1438 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1440 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1441 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1442 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1443 /* implicit null-pointer check */
1444 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1445 M_ASLL_IMM(s2, 2, REG_ITMP3);
1446 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1447 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray_t, data[0]));
1448 emit_store_dst(jd, iptr, d);
1451 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1453 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1454 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1455 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1456 /* implicit null-pointer check */
1457 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1458 M_ASLL_IMM(s2, 3, REG_ITMP3);
1459 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1460 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1461 emit_store_dst(jd, iptr, d);
1464 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1466 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1467 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1468 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1469 /* implicit null-pointer check */
1470 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1471 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1472 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1473 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray_t, data[0]));
1474 emit_store_dst(jd, iptr, d);
1478 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1480 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1481 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1482 /* implicit null-pointer check */
1483 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1484 M_AADD(s2, s1, REG_ITMP1);
1485 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1486 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1489 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1490 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1492 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1493 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1494 /* implicit null-pointer check */
1495 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1496 M_AADD(s2, s1, REG_ITMP1);
1497 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1498 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1499 M_SST(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1502 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1504 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1505 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1506 /* implicit null-pointer check */
1507 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1508 M_ASLL_IMM(s2, 2, REG_ITMP2);
1509 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1510 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1511 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1514 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1516 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1517 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1518 /* implicit null-pointer check */
1519 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1520 M_ASLL_IMM(s2, 3, REG_ITMP2);
1521 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1522 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1523 M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1526 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1528 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1529 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1530 /* implicit null-pointer check */
1531 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1532 M_ASLL_IMM(s2, 2, REG_ITMP2);
1533 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1534 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1535 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1538 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1540 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1541 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1542 /* implicit null-pointer check */
1543 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1544 M_ASLL_IMM(s2, 3, REG_ITMP2);
1545 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1546 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1547 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1551 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1553 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1554 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1555 /* implicit null-pointer check */
1556 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1557 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1559 M_MOV(s1, REG_OUT0);
1560 M_MOV(s3, REG_OUT1);
1561 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1562 M_ALD(REG_ITMP3, REG_PV, disp);
1563 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
1565 emit_arraystore_check(cd, iptr);
1567 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1568 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1569 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1570 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1571 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1572 /* implicit null-pointer check */
1573 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1577 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1579 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1580 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1581 /* implicit null-pointer check */
1582 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1583 M_AADD(s2, s1, REG_ITMP1);
1584 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1587 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1588 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1590 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1591 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1592 /* implicit null-pointer check */
1593 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1594 M_AADD(s2, s1, REG_ITMP1);
1595 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1596 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1599 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1601 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1602 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1603 /* implicit null-pointer check */
1604 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1605 M_ASLL_IMM(s2, 2, REG_ITMP2);
1606 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1607 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1610 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1612 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1613 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1614 /* implicit null-pointer check */
1615 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1616 M_ASLL_IMM(s2, 3, REG_ITMP2);
1617 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1618 M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1621 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1623 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1624 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1625 /* implicit null-pointer check */
1626 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1627 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1628 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1629 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1633 case ICMD_GETSTATIC: /* ... ==> ..., value */
1635 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1636 uf = iptr->sx.s23.s3.uf;
1637 fieldtype = uf->fieldref->parseddesc.fd->type;
1638 disp = dseg_add_unique_address(cd, uf);
1640 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1643 fi = iptr->sx.s23.s3.fmiref->p.field;
1644 fieldtype = fi->type;
1645 disp = dseg_add_address(cd, fi->value);
1647 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1648 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1651 M_ALD(REG_ITMP1, REG_PV, disp);
1653 switch (fieldtype) {
1655 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1656 M_ILD_INTERN(d, REG_ITMP1, 0);
1659 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1660 M_LDX_INTERN(d, REG_ITMP1, 0);
1663 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1664 M_ALD_INTERN(d, REG_ITMP1, 0);
1667 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1668 M_FLD_INTERN(d, REG_ITMP1, 0);
1671 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1672 M_DLD_INTERN(d, REG_ITMP1, 0);
1675 emit_store_dst(jd, iptr, d);
1678 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1680 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1681 uf = iptr->sx.s23.s3.uf;
1682 fieldtype = uf->fieldref->parseddesc.fd->type;
1683 disp = dseg_add_unique_address(cd, uf);
1685 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1688 fi = iptr->sx.s23.s3.fmiref->p.field;
1689 fieldtype = fi->type;
1690 disp = dseg_add_address(cd, fi->value);
1692 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1693 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1696 M_ALD(REG_ITMP1, REG_PV, disp);
1698 switch (fieldtype) {
1700 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1701 M_IST_INTERN(s1, REG_ITMP1, 0);
1704 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1705 M_STX_INTERN(s1, REG_ITMP1, 0);
1708 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1709 M_AST_INTERN(s1, REG_ITMP1, 0);
1712 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1713 M_FST_INTERN(s1, REG_ITMP1, 0);
1716 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1717 M_DST_INTERN(s1, REG_ITMP1, 0);
1722 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1723 /* val = value (in current instruction) */
1724 /* following NOP) */
1726 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1727 uf = iptr->sx.s23.s3.uf;
1728 fieldtype = uf->fieldref->parseddesc.fd->type;
1729 disp = dseg_add_unique_address(cd, uf);
1731 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1734 fi = iptr->sx.s23.s3.fmiref->p.field;
1735 fieldtype = fi->type;
1736 disp = dseg_add_address(cd, fi->value);
1738 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1739 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1742 M_ALD(REG_ITMP1, REG_PV, disp);
1744 switch (fieldtype) {
1746 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1749 M_STX_INTERN(REG_ZERO, REG_ITMP1, 0);
1752 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1755 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1758 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1764 case ICMD_GETFIELD: /* ... ==> ..., value */
1766 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1767 emit_nullpointer_check(cd, iptr, s1);
1769 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1770 uf = iptr->sx.s23.s3.uf;
1772 fieldtype = uf->fieldref->parseddesc.fd->type;
1775 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1778 fi = iptr->sx.s23.s3.fmiref->p.field;
1779 fieldtype = fi->type;
1783 switch (fieldtype) {
1785 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1789 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1793 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1797 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1801 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1808 emit_store_dst(jd, iptr, d);
1811 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1813 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1814 emit_nullpointer_check(cd, iptr, s1);
1816 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1817 uf = iptr->sx.s23.s3.uf;
1818 fieldtype = uf->fieldref->parseddesc.fd->type;
1823 fi = iptr->sx.s23.s3.fmiref->p.field;
1824 fieldtype = fi->type;
1828 if (IS_INT_LNG_TYPE(fieldtype))
1829 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1831 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1833 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1834 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1836 switch (fieldtype) {
1838 M_IST(s2, s1, disp);
1841 M_STX(s2, s1, disp);
1844 M_AST(s2, s1, disp);
1847 M_FST(s2, s1, disp);
1850 M_DST(s2, s1, disp);
1858 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
1859 /* val = value (in current instruction) */
1860 /* following NOP) */
1862 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1863 emit_nullpointer_check(cd, iptr, s1);
1865 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1866 unresolved_field *uf = iptr->sx.s23.s3.uf;
1868 fieldtype = uf->fieldref->parseddesc.fd->type;
1870 codegen_addpatchref(cd, PATCHER_get_putfield,
1873 if (opt_showdisassemble) {
1881 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1883 fieldtype = fi->type;
1889 switch (fieldtype) {
1891 M_IST(REG_ZERO, s1, disp);
1894 M_STX(REG_ZERO, s1, disp);
1897 M_AST(REG_ZERO, s1, disp);
1900 M_FST(REG_ZERO, s1, disp);
1903 M_DST(REG_ZERO, s1, disp);
1909 /* branch operations **************************************************/
1911 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1913 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1914 M_INTMOVE(s1, REG_ITMP2_XPTR);
1916 #ifdef ENABLE_VERIFIER
1917 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1918 unresolved_class *uc = iptr->sx.s23.s2.uc;
1920 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
1922 #endif /* ENABLE_VERIFIER */
1924 disp = dseg_add_functionptr(cd, asm_handle_exception);
1925 M_ALD(REG_ITMP1, REG_PV, disp);
1926 M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
1928 M_NOP; /* nop ensures that XPC is less than the end */
1929 /* of basic block */
1933 case ICMD_GOTO: /* ... ==> ... */
1934 case ICMD_RET: /* ... ==> ... */
1936 emit_br(cd, iptr->dst.block);
1940 case ICMD_JSR: /* ... ==> ... */
1942 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1946 case ICMD_IFNULL: /* ..., value ==> ... */
1947 case ICMD_IFNONNULL:
1949 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1950 emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
1953 /* Note: int compares must not branch on the register directly. */
1954 /* Reason is, that register content is not 32-bit clean. */
1956 case ICMD_IFEQ: /* ..., value ==> ... */
1958 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1960 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1961 M_CMP_IMM(s1, iptr->sx.val.i);
1964 ICONST(REG_ITMP2, iptr->sx.val.i);
1965 M_CMP(s1, REG_ITMP2);
1967 emit_beq(cd, iptr->dst.block);
1970 case ICMD_IFLT: /* ..., value ==> ... */
1972 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1974 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1975 M_CMP_IMM(s1, iptr->sx.val.i);
1978 ICONST(REG_ITMP2, iptr->sx.val.i);
1979 M_CMP(s1, REG_ITMP2);
1981 emit_blt(cd, iptr->dst.block);
1984 case ICMD_IFLE: /* ..., value ==> ... */
1986 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1988 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1989 M_CMP_IMM(s1, iptr->sx.val.i);
1992 ICONST(REG_ITMP2, iptr->sx.val.i);
1993 M_CMP(s1, REG_ITMP2);
1995 emit_ble(cd, iptr->dst.block);
1998 case ICMD_IFNE: /* ..., value ==> ... */
2000 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2002 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2003 M_CMP_IMM(s1, iptr->sx.val.i);
2006 ICONST(REG_ITMP2, iptr->sx.val.i);
2007 M_CMP(s1, REG_ITMP2);
2009 emit_bne(cd, iptr->dst.block);
2012 case ICMD_IFGT: /* ..., value ==> ... */
2014 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2016 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2017 M_CMP_IMM(s1, iptr->sx.val.i);
2020 ICONST(REG_ITMP2, iptr->sx.val.i);
2021 M_CMP(s1, REG_ITMP2);
2023 emit_bgt(cd, iptr->dst.block);
2026 case ICMD_IFGE: /* ..., value ==> ... */
2028 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2030 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2031 M_CMP_IMM(s1, iptr->sx.val.i);
2034 ICONST(REG_ITMP2, iptr->sx.val.i);
2035 M_CMP(s1, REG_ITMP2);
2037 emit_bge(cd, iptr->dst.block);
2040 case ICMD_IF_LEQ: /* ..., value ==> ... */
2042 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2043 if (iptr->sx.val.l == 0)
2044 emit_beqz(cd, iptr->dst.block, s1);
2046 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2047 M_CMP_IMM(s1, iptr->sx.val.l);
2050 LCONST(REG_ITMP2, iptr->sx.val.l);
2051 M_CMP(s1, REG_ITMP2);
2053 emit_beq_xcc(cd, iptr->dst.block);
2057 case ICMD_IF_LLT: /* ..., value ==> ... */
2059 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2060 if (iptr->sx.val.l == 0)
2061 emit_bltz(cd, iptr->dst.block, s1);
2063 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2064 M_CMP_IMM(s1, iptr->sx.val.l);
2067 LCONST(REG_ITMP2, iptr->sx.val.l);
2068 M_CMP(s1, REG_ITMP2);
2070 emit_blt_xcc(cd, iptr->dst.block);
2074 case ICMD_IF_LLE: /* ..., value ==> ... */
2076 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2077 if (iptr->sx.val.l == 0)
2078 emit_blez(cd, iptr->dst.block, s1);
2080 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2081 M_CMP_IMM(s1, iptr->sx.val.l);
2084 LCONST(REG_ITMP2, iptr->sx.val.l);
2085 M_CMP(s1, REG_ITMP2);
2087 emit_ble_xcc(cd, iptr->dst.block);
2091 case ICMD_IF_LNE: /* ..., value ==> ... */
2093 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2094 if (iptr->sx.val.l == 0)
2095 emit_bnez(cd, iptr->dst.block, s1);
2097 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2098 M_CMP_IMM(s1, iptr->sx.val.l);
2101 LCONST(REG_ITMP2, iptr->sx.val.l);
2102 M_CMP(s1, REG_ITMP2);
2104 emit_bne_xcc(cd, iptr->dst.block);
2108 case ICMD_IF_LGT: /* ..., value ==> ... */
2110 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2111 if (iptr->sx.val.l == 0)
2112 emit_bgtz(cd, iptr->dst.block, s1);
2114 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2115 M_CMP_IMM(s1, iptr->sx.val.l);
2118 LCONST(REG_ITMP2, iptr->sx.val.l);
2119 M_CMP(s1, REG_ITMP2);
2121 emit_bgt_xcc(cd, iptr->dst.block);
2125 case ICMD_IF_LGE: /* ..., value ==> ... */
2127 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2128 if (iptr->sx.val.l == 0)
2129 emit_bgez(cd, iptr->dst.block, s1);
2131 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2132 M_CMP_IMM(s1, iptr->sx.val.l);
2135 LCONST(REG_ITMP2, iptr->sx.val.l);
2136 M_CMP(s1, REG_ITMP2);
2138 emit_bge_xcc(cd, iptr->dst.block);
2143 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2144 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2146 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2147 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2149 emit_beq_xcc(cd, iptr->dst.block);
2152 case ICMD_IF_ICMPEQ: /* 32-bit compare */
2154 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2155 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2157 emit_beq(cd, iptr->dst.block);
2160 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
2161 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2163 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2164 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2166 emit_bne_xcc(cd, iptr->dst.block);
2169 case ICMD_IF_ICMPNE: /* 32-bit compare */
2171 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2172 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2174 emit_bne(cd, iptr->dst.block);
2177 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2179 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2180 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2182 emit_blt_xcc(cd, iptr->dst.block);
2185 case ICMD_IF_ICMPLT: /* 32-bit compare */
2187 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2188 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2190 emit_blt(cd, iptr->dst.block);
2193 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2195 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2196 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2198 emit_bgt_xcc(cd, iptr->dst.block);
2201 case ICMD_IF_ICMPGT: /* 32-bit compare */
2203 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2204 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2206 emit_bgt(cd, iptr->dst.block);
2209 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2211 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2212 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2214 emit_ble_xcc(cd, iptr->dst.block);
2217 case ICMD_IF_ICMPLE: /* 32-bit compare */
2219 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2220 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2222 emit_ble(cd, iptr->dst.block);
2226 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2228 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2229 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2231 emit_bge_xcc(cd, iptr->dst.block);
2234 case ICMD_IF_ICMPGE: /* 32-bit compare */
2236 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2237 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2239 emit_bge(cd, iptr->dst.block);
2243 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2246 REPLACEMENT_POINT_RETURN(cd, iptr);
2248 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2249 M_INTMOVE(s1, REG_RESULT_CALLEE);
2250 goto nowperformreturn;
2252 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2254 REPLACEMENT_POINT_RETURN(cd, iptr);
2256 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2257 M_INTMOVE(s1, REG_RESULT_CALLEE);
2259 #ifdef ENABLE_VERIFIER
2260 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2261 unresolved_class *uc = iptr->sx.s23.s2.uc;
2263 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2265 #endif /* ENABLE_VERIFIER */
2266 goto nowperformreturn;
2268 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2271 REPLACEMENT_POINT_RETURN(cd, iptr);
2273 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2274 M_DBLMOVE(s1, REG_FRESULT);
2275 goto nowperformreturn;
2277 case ICMD_RETURN: /* ... ==> ... */
2279 REPLACEMENT_POINT_RETURN(cd, iptr);
2285 p = cd->stackframesize;
2287 #if !defined(NDEBUG)
2288 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2289 emit_verbosecall_exit(jd);
2292 #if defined(ENABLE_THREADS)
2293 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2294 /* XXX jit-c-call */
2295 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2296 M_ALD(REG_ITMP3, REG_PV, disp);
2298 /* we need to save fp return value (int saved by window) */
2300 switch (iptr->opc) {
2303 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
2304 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2305 M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2307 /* restore the fp return value */
2309 M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
2315 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2316 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2327 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
2333 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2336 branch_target_t *table;
2338 table = iptr->dst.table;
2340 l = iptr->sx.s23.s2.tablelow;
2341 i = iptr->sx.s23.s3.tablehigh;
2343 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2345 M_INTMOVE(s1, REG_ITMP1);
2347 else if (-l >= 4096 && -l <= 4095) {
2348 M_ADD_IMM(s1, -l, REG_ITMP1);
2351 ICONST(REG_ITMP2, l);
2352 M_SUB(s1, REG_ITMP2, REG_ITMP1);
2355 i = i - l + 1; /* number of targets (>0) */
2361 M_CMP_IMM(REG_ITMP1, i - 1);
2364 ICONST(REG_ITMP2, i - 1);
2365 M_CMP(REG_ITMP1, REG_ITMP2);
2367 emit_bugt(cd, table[0].block); /* default target */
2369 /* build jump table top down and use address of lowest entry */
2374 dseg_add_target(cd, table->block);
2379 /* length of dataseg after last dseg_addtarget is used by load */
2381 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
2382 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2383 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2384 M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
2389 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2392 lookup_target_t *lookup;
2394 lookup = iptr->dst.lookup;
2396 i = iptr->sx.s23.s2.lookupcount;
2398 MCODECHECK((i<<2)+8);
2399 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2402 if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
2403 M_CMP_IMM(s1, lookup->value);
2405 ICONST(REG_ITMP2, lookup->value);
2406 M_CMP(s1, REG_ITMP2);
2408 emit_beq(cd, lookup->target.block);
2412 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2418 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
2420 REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
2422 bte = iptr->sx.s23.s3.bte;
2425 /* XXX: builtin calling with stack arguments not implemented */
2426 assert(md->paramcount <= 5 && md->argfltreguse <= 16);
2428 s3 = md->paramcount;
2430 MCODECHECK((s3 << 1) + 64);
2432 #ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
2434 /* copy float arguments according to ABI convention */
2436 int num_fltregargs = 0;
2437 int fltregarg_inswap[16];
2439 for (s3 = s3 - 1; s3 >= 0; s3--) {
2440 var = VAR(iptr->sx.s23.s2.args[s3]);
2442 if (IS_FLT_DBL_TYPE(var->type)) {
2443 if (!md->params[s3].inmemory) {
2444 s1 = s3; /*native flt args use argument index directly*/
2445 d = emit_load(jd, iptr, var, REG_FTMP1);
2448 fltregarg_inswap[num_fltregargs] = s1;
2450 /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
2459 /* move swapped float args to target regs */
2460 for (i = 0; i < num_fltregargs; i++) {
2461 s1 = fltregarg_inswap[i];
2462 M_DMOV(s1 + 16, s1);
2463 /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
2467 assert(md->argfltreguse == 0);
2472 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2473 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2474 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2475 case ICMD_INVOKEINTERFACE:
2477 REPLACEMENT_POINT_INVOKE(cd, iptr);
2479 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2481 um = iptr->sx.s23.s3.um;
2482 md = um->methodref->parseddesc.md;
2485 lm = iptr->sx.s23.s3.fmiref->p.method;
2487 md = lm->parseddesc;
2491 s3 = md->paramcount;
2493 MCODECHECK((s3 << 1) + 64);
2495 /* copy arguments to registers or stack location */
2497 for (s3 = s3 - 1; s3 >= 0; s3--) {
2498 var = VAR(iptr->sx.s23.s2.args[s3]);
2499 d = md->params[s3].regoff;
2501 if (var->flags & PREALLOC)
2504 if (IS_INT_LNG_TYPE(var->type)) {
2505 if (!md->params[s3].inmemory) {
2506 s1 = emit_load(jd, iptr, var, d);
2510 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2511 M_STX(s1, REG_SP, JITSTACK + d);
2515 #ifdef BUILTIN_FLOAT_ARGS
2516 if (iptr->opc == ICMD_BUILTIN)
2520 if (!md->params[s3].inmemory) {
2521 s1 = emit_load(jd, iptr, var, d);
2522 if (IS_2_WORD_TYPE(var->type))
2528 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2529 M_DST(s1, REG_SP, JITSTACK + d);
2534 switch (iptr->opc) {
2536 if (bte->stub == NULL) {
2537 disp = dseg_add_functionptr(cd, bte->fp);
2540 disp = dseg_add_functionptr(cd, bte->stub);
2543 M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
2545 /* XXX jit-c-call */
2546 /* generate the actual call */
2548 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2550 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2551 REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
2552 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2553 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2554 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2556 if (md->returntype.type == TYPE_FLT) {
2557 /* special handling for float return value in %f0 */
2562 case ICMD_INVOKESPECIAL:
2563 emit_nullpointer_check(cd, iptr, REG_OUT0);
2566 case ICMD_INVOKESTATIC:
2568 disp = dseg_add_unique_address(cd, NULL);
2570 codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
2574 disp = dseg_add_address(cd, lm->stubroutine);
2576 M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
2578 /* generate the actual call */
2580 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2582 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2583 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2584 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2585 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2588 case ICMD_INVOKEVIRTUAL:
2589 emit_nullpointer_check(cd, iptr, REG_OUT0);
2592 codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
2597 s1 = OFFSET(vftbl_t, table[0]) +
2598 sizeof(methodptr) * lm->vftblindex;
2600 /* implicit null-pointer check */
2601 M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
2602 M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
2604 /* generate the actual call */
2606 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2608 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2609 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2610 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2611 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2614 case ICMD_INVOKEINTERFACE:
2615 emit_nullpointer_check(cd, iptr, REG_OUT0);
2618 codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
2624 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2625 sizeof(methodptr*) * lm->class->index;
2627 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2630 /* implicit null-pointer check */
2631 M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
2632 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2633 M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
2635 /* generate the actual call */
2637 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2639 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2640 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2641 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2642 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2646 /* store return value */
2648 d = md->returntype.type;
2650 if (d != TYPE_VOID) {
2651 if (IS_INT_LNG_TYPE(d)) {
2652 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2653 M_INTMOVE(REG_RESULT_CALLER, s1);
2656 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2657 if (IS_2_WORD_TYPE(d)) {
2658 M_DBLMOVE(REG_FRESULT, s1);
2660 M_FLTMOVE(REG_FRESULT, s1);
2663 emit_store_dst(jd, iptr, s1);
2668 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2669 /* val.a: (classinfo*) superclass */
2671 /* superclass is an interface:
2673 * OK if ((sub == NULL) ||
2674 * (sub->vftbl->interfacetablelength > super->index) &&
2675 * (sub->vftbl->interfacetable[-super->index] != NULL));
2677 * superclass is a class:
2679 * OK if ((sub == NULL) || (0
2680 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2681 * super->vftbl->diffvall));
2684 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2688 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2693 super = iptr->sx.s23.s3.c.cls;
2694 superindex = super->index;
2697 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2698 CODEGEN_CRITICAL_SECTION_NEW;
2700 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2702 /* if class is not resolved, check which code to call */
2704 if (super == NULL) {
2705 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2707 cr = iptr->sx.s23.s3.c.ref;
2708 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2710 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2713 M_ILD(REG_ITMP2, REG_PV, disp);
2714 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2715 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
2718 /* interface checkcast code */
2720 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2721 if (super == NULL) {
2722 cr = iptr->sx.s23.s3.c.ref;
2724 codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
2728 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2731 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2732 M_ILD(REG_ITMP3, REG_ITMP2,
2733 OFFSET(vftbl_t, interfacetablelength));
2734 M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
2735 emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
2737 M_ALD(REG_ITMP3, REG_ITMP2,
2738 OFFSET(vftbl_t, interfacetable[0]) -
2739 superindex * sizeof(methodptr*));
2740 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
2743 emit_label_br(cd, BRANCH_LABEL_4);
2745 emit_label(cd, BRANCH_LABEL_3);
2748 /* class checkcast code */
2750 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2751 if (super == NULL) {
2752 emit_label(cd, BRANCH_LABEL_2);
2754 cr = iptr->sx.s23.s3.c.ref;
2755 disp = dseg_add_unique_address(cd, NULL);
2757 codegen_add_patch_ref(cd,
2758 PATCHER_checkcast_instanceof_class,
2762 disp = dseg_add_address(cd, super->vftbl);
2764 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2767 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2768 M_ALD(REG_ITMP3, REG_PV, disp);
2770 CODEGEN_CRITICAL_SECTION_START;
2772 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2773 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2774 M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2775 M_ALD(REG_ITMP3, REG_PV, disp);
2776 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2778 CODEGEN_CRITICAL_SECTION_END;
2781 M_CMP(REG_ITMP3, REG_ITMP2);
2782 emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
2785 emit_label(cd, BRANCH_LABEL_5);
2788 if (super == NULL) {
2789 emit_label(cd, BRANCH_LABEL_1);
2790 emit_label(cd, BRANCH_LABEL_4);
2793 d = codegen_reg_of_dst(jd, iptr, s1);
2796 /* array type cast-check */
2798 s1 = emit_load_s1(jd, iptr, REG_OUT0);
2799 M_INTMOVE(s1, REG_OUT0);
2801 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2803 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2804 cr = iptr->sx.s23.s3.c.ref;
2805 disp = dseg_add_unique_address(cd, NULL);
2807 codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
2811 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2813 M_ALD(REG_OUT1, REG_PV, disp);
2814 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2815 M_ALD(REG_ITMP3, REG_PV, disp);
2816 /* XXX jit-c-call */
2817 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2820 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2821 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
2823 d = codegen_reg_of_dst(jd, iptr, s1);
2827 emit_store_dst(jd, iptr, d);
2830 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2831 /* val.a: (classinfo*) superclass */
2833 /* superclass is an interface:
2835 * return (sub != NULL) &&
2836 * (sub->vftbl->interfacetablelength > super->index) &&
2837 * (sub->vftbl->interfacetable[-super->index] != NULL);
2839 * superclass is a class:
2841 * return ((sub != NULL) && (0
2842 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2843 * super->vftbl->diffvall));
2848 vftbl_t *supervftbl;
2851 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2857 super = iptr->sx.s23.s3.c.cls;
2858 superindex = super->index;
2859 supervftbl = super->vftbl;
2862 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2863 CODEGEN_CRITICAL_SECTION_NEW;
2865 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2866 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2868 M_MOV(s1, REG_ITMP1);
2874 /* if class is not resolved, check which code to call */
2876 if (super == NULL) {
2877 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2879 cr = iptr->sx.s23.s3.c.ref;
2880 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2882 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2885 M_ILD(REG_ITMP3, REG_PV, disp);
2886 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2887 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
2890 /* interface instanceof code */
2892 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2893 if (super == NULL) {
2894 cr = iptr->sx.s23.s3.c.ref;
2896 codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
2900 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2903 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2904 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2905 M_CMP_IMM(REG_ITMP3, superindex);
2908 M_ALD(REG_ITMP1, REG_ITMP1,
2909 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2910 superindex * sizeof(methodptr*)));
2911 M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
2914 emit_label_br(cd, BRANCH_LABEL_4);
2916 emit_label(cd, BRANCH_LABEL_3);
2919 /* class instanceof code */
2921 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2922 if (super == NULL) {
2923 emit_label(cd, BRANCH_LABEL_2);
2925 cr = iptr->sx.s23.s3.c.ref;
2926 disp = dseg_add_unique_address(cd, NULL);
2928 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
2932 disp = dseg_add_address(cd, supervftbl);
2934 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2937 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2938 M_ALD(REG_ITMP2, REG_PV, disp);
2940 CODEGEN_CRITICAL_SECTION_START;
2942 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2943 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2944 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2946 CODEGEN_CRITICAL_SECTION_END;
2948 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2949 M_CMP(REG_ITMP1, REG_ITMP2);
2950 M_XCMOVULE_IMM(1, d);
2953 emit_label(cd, BRANCH_LABEL_5);
2956 if (super == NULL) {
2957 emit_label(cd, BRANCH_LABEL_1);
2958 emit_label(cd, BRANCH_LABEL_4);
2961 emit_store_dst(jd, iptr, d);
2965 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2967 /* check for negative sizes and copy sizes to stack if necessary */
2969 MCODECHECK((iptr->s1.argcount << 1) + 64);
2971 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2973 var = VAR(iptr->sx.s23.s2.args[s1]);
2975 /* copy SAVEDVAR sizes to stack */
2977 /* Already Preallocated? */
2979 if (!(var->flags & PREALLOC)) {
2980 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2981 M_STX(s2, REG_SP, CSTACK + (s1 * 8));
2985 /* arg 0 = dimension count */
2987 ICONST(REG_OUT0, iptr->s1.argcount);
2989 /* is patcher function set? */
2991 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2992 disp = dseg_add_unique_address(cd, 0);
2994 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
2995 iptr->sx.s23.s3.c.ref,
2999 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3001 /* arg 1 = arraydescriptor */
3003 M_ALD(REG_OUT1, REG_PV, disp);
3005 /* arg 2 = pointer to dimensions = stack pointer (absolute) */
3007 M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
3009 /* XXX c abi call */
3010 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3011 M_ALD(REG_ITMP3, REG_PV, disp);
3012 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3015 /* check for exception before result assignment */
3017 emit_exception_check(cd, iptr);
3019 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
3020 M_INTMOVE(REG_RESULT_CALLER, d);
3021 emit_store_dst(jd, iptr, d);
3025 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
3031 } /* for instruction */
3035 /* At the end of a basic block we may have to append some nops,
3036 because the patcher stub calling code might be longer than the
3037 actual instruction. So codepatching does not change the
3038 following block unintentionally. */
3040 if (cd->mcodeptr < cd->lastmcodeptr) {
3041 while (cd->mcodeptr < cd->lastmcodeptr) {
3046 } /* if (bptr -> flags >= BBREACHED) */
3047 } /* for basic block */
3049 dseg_createlinenumbertable(cd);
3051 /* generate stubs */
3053 emit_patcher_stubs(jd);
3055 /* everything's ok */
3061 /* codegen_emit_stub_compiler **************************************************
3063 Emits a stub routine which calls the compiler.
3065 *******************************************************************************/
3067 void codegen_emit_stub_compiler(jitdata *jd)
3072 /* get required compiler data */
3077 /* code for the stub */
3079 /* no window save yet, user caller's PV */
3080 M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */
3081 M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */
3082 M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */
3087 /* codegen_emit_stub_builtin ***************************************************
3089 Creates a stub routine which calls a builtin function.
3091 *******************************************************************************/
3093 void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
3102 /* get required compiler data */
3106 /* set some variables */
3109 /* calculate stack frame size */
3110 cd->stackframesize =
3114 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
3115 4; /* 4 arguments or return value */
3118 /* keep stack 16-byte aligned (ABI requirement) */
3120 if (cd->stackframesize & 1)
3121 cd->stackframesize++;
3123 /* create method header */
3124 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3125 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3126 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3127 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3128 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3129 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3130 (void) dseg_addlinenumbertablesize(cd);
3131 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3134 /* generate stub code */
3135 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3137 #if defined(ENABLE_GC_CACAO)
3138 /* Save callee saved integer registers in stackframeinfo (GC may
3139 need to recover them during a collection). */
3141 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3142 OFFSET(stackframeinfo_t, intregs) + BIAS;
3144 for (i = 0; i < INT_SAV_CNT; i++)
3145 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3148 for (i = 0; i < md->paramcount; i++) {
3149 s1 = md->params[i].regoff;
3151 switch (md->paramtypes[i].type) {
3158 M_DST(s1, REG_SP, JITSTACK + i * 8);
3163 /* create dynamic stack info */
3165 M_AADD_IMM(REG_SP, BIAS + cd->stackframesize * 8, REG_OUT0); /* data sp*/
3166 M_MOV(REG_PV_CALLEE, REG_OUT1); /* PV */
3167 M_MOV(REG_FP, REG_OUT2); /* java sp */
3168 M_MOV(REG_RA_CALLEE, REG_OUT3); /* ra */
3170 disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
3171 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3172 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3173 M_NOP; /* XXX fill me! */
3176 /* builtins are allowed to have 5 arguments max */
3178 assert(md->paramcount <= 5);
3180 /* copy arguments into position */
3182 for (i = 0; i < md->paramcount; i++) {
3183 assert(!md->params[i].inmemory);
3185 s1 = md->params[i].regoff;
3187 switch (md->paramtypes[i].type) {
3191 M_MOV(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[i]), s1);
3195 M_DLD(s1, REG_SP, JITSTACK + i * 8);
3201 /* call the builtin function */
3203 disp = dseg_add_functionptr(cd, bte->fp);
3204 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); /* load adress of builtin */
3205 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call builtin */
3206 M_NOP; /* delay slot */
3209 /* save return value */
3211 if (md->returntype.type != TYPE_VOID) {
3212 if (IS_INT_LNG_TYPE(md->returntype.type))
3213 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3215 M_DST(REG_FRESULT, REG_SP, CSTACK);
3219 /* remove native stackframe info */
3221 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3222 disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
3223 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3224 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3227 /* restore float return value, int return value already in our return reg */
3229 if (md->returntype.type != TYPE_VOID) {
3230 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3231 if (IS_2_WORD_TYPE(md->returntype.type))
3232 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3234 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3239 #if defined(ENABLE_GC_CACAO)
3240 /* Restore callee saved integer registers from stackframeinfo (GC
3241 might have modified them during a collection). */
3243 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3244 OFFSET(stackframeinfo_t, intregs) + BIAS;
3246 for (i = 0; i < INT_SAV_CNT; i++)
3247 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3251 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3258 /* codegen_emit_stub_native ****************************************************
3260 Emits a stub routine which calls a native method.
3262 *******************************************************************************/
3264 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3271 s4 i, j; /* count variables */
3274 s4 funcdisp; /* displacement of the function */
3275 s4 fltregarg_offset[FLT_ARG_CNT];
3277 /* get required compiler data */
3283 /* initialize variables */
3286 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3288 /* calculate stack frame size */
3290 cd->stackframesize =
3291 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3292 sizeof(localref_table) / SIZEOF_VOID_P +
3293 md->paramcount + /* for saving arguments over calls */
3294 nmd->memuse + /* nmd->memuse includes the (6) abi params */
3298 /* keep stack 16-byte aligned (ABI requirement) */
3300 if (cd->stackframesize & 1)
3301 cd->stackframesize++;
3303 /* create method header */
3305 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3306 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3307 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3308 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3309 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3310 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3311 (void) dseg_addlinenumbertablesize(cd);
3312 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3314 /* generate stub code */
3316 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3318 #if !defined(NDEBUG)
3319 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3320 emit_verbosecall_enter(jd);
3323 /* get function address (this must happen before the stackframeinfo) */
3325 funcdisp = dseg_add_functionptr(cd, f);
3328 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
3330 /* save float argument registers */
3332 assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
3334 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3335 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3336 s1 = WINSAVE_CNT + nmd->memuse + j;
3337 M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
3338 fltregarg_offset[i] = s1; /* remember stack offset */
3343 /* prepare data structures for native function call */
3345 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */
3346 M_MOV(REG_PV_CALLEE, REG_OUT1);
3347 M_MOV(REG_FP, REG_OUT2); /* java sp */
3348 M_MOV(REG_RA_CALLEE, REG_OUT3);
3349 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3350 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3351 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3352 M_NOP; /* XXX fill me! */
3354 /* remember class argument */
3356 if (m->flags & ACC_STATIC)
3357 M_MOV(REG_RESULT_CALLER, REG_ITMP3);
3359 /* keep float arguments on stack */
3361 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3362 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3363 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
3369 /* copy or spill arguments to new locations */
3371 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3372 t = md->paramtypes[i].type;
3374 if (IS_INT_LNG_TYPE(t)) {
3376 /* integral types */
3378 if (!md->params[i].inmemory) {
3379 s1 = md->params[i].regoff;
3380 /* s1 refers to the old window, transpose */
3381 s1 = REG_WINDOW_TRANSPOSE(s1);
3383 if (!nmd->params[j].inmemory) {
3384 s2 = nmd->params[j].regoff;
3387 /* nmd's regoff is relative to the start of the param array */
3388 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3389 M_AST(s1, REG_SP, s2);
3393 if (!nmd->params[j].inmemory) {
3394 /* JIT stack arg -> NAT reg arg */
3396 /* Due to the Env pointer that is always passed, the 6th JIT arg */
3397 /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */
3399 assert(false); /* path never taken */
3402 s1 = md->params[i].regoff + cd->stackframesize * 8;
3403 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3404 M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
3405 M_AST(REG_ITMP1, REG_SP, s2);
3410 /* floating point types */
3412 if (!md->params[i].inmemory) {
3413 s1 = md->params[i].regoff;
3415 if (!nmd->params[j].inmemory) {
3417 /* no mapping to regs needed, native flt args use regoff */
3418 s2 = nmd->params[j].regoff;
3420 /* JIT float regs are still on the stack */
3421 M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8));
3424 /* not supposed to happen with 16 NAT flt args */
3427 s2 = nmd->params[j].regoff;
3428 if (IS_2_WORD_TYPE(t))
3429 M_DST(s1, REG_SP, CSTACK + (s2 * 8));
3431 M_FST(s1, REG_SP, CSTACK + (s2 * 8));
3437 s1 = md->params[i].regoff;
3439 if (!nmd->params[j].inmemory) {
3441 /* JIT stack -> NAT reg */
3443 s2 = nmd->params[j].regoff;
3444 M_DLD(s2, REG_FP, JITSTACK + s1);
3448 /* JIT stack -> NAT stack */
3450 s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff;
3452 /* The FTMP register may already be loaded with args */
3453 /* we know $f0 is unused because of the env pointer */
3454 M_DLD(REG_F0, REG_FP, JITSTACK + s1);
3455 M_DST(REG_F0, REG_SP, BIAS + s2);
3462 /* put class into second argument register */
3464 if (m->flags & ACC_STATIC)
3465 M_MOV(REG_ITMP3, REG_OUT1);
3467 /* put env into first argument register */
3469 disp = dseg_add_address(cd, _Jv_env);
3470 M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
3472 /* do the native function call */
3474 M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method */
3475 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method */
3476 M_NOP; /* delay slot */
3478 /* save return value */
3480 if (md->returntype.type != TYPE_VOID) {
3481 if (IS_INT_LNG_TYPE(md->returntype.type))
3482 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3484 M_DST(REG_FRESULT, REG_SP, CSTACK);
3487 /* Note: native functions return float values in %f0 (see ABI) */
3488 /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
3490 #if !defined(NDEBUG)
3491 /* But for the trace function we need to put a flt result into %f1 */
3492 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3493 if (!IS_2_WORD_TYPE(md->returntype.type))
3494 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3495 emit_verbosecall_exit(jd);
3499 /* remove native stackframe info */
3501 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3502 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3503 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3504 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3505 M_NOP; /* XXX fill me! */
3506 M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
3508 /* restore float return value, int return value already in our return reg */
3510 if (md->returntype.type != TYPE_VOID) {
3511 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3512 if (IS_2_WORD_TYPE(md->returntype.type))
3513 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3515 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3519 /* check for exception */
3520 M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
3523 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3526 /* handle exception */
3528 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3529 M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */
3530 M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */
3531 M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */
3532 M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
3534 /* generate patcher stubs */
3536 emit_patcher_stubs(jd);
3540 * These are local overrides for various environment variables in Emacs.
3541 * Please do not remove this and leave it at the end of the file, where
3542 * Emacs will automagically detect them.
3543 * ---------------------------------------------------------------------
3546 * indent-tabs-mode: t
3550 * vim:noexpandtab:sw=4:ts=4: