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"
40 #include "vm/jit/sparc64/emit.h"
42 #include "mm/memory.h"
44 #include "native/jni.h"
45 #include "native/localref.h"
46 #include "native/native.h"
47 #include "vm/builtin.h"
48 #include "vm/exceptions.h"
49 #include "vm/global.h"
51 #include "vm/jit/abi.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/codegen-common.h"
54 #include "vm/jit/dseg.h"
55 #include "vm/jit/emit-common.h"
56 #include "vm/jit/jit.h"
57 #include "vm/jit/linenumbertable.h"
58 #include "vm/jit/parse.h"
59 #include "vm/jit/patcher.h"
60 #include "vm/jit/reg.h"
61 #include "vm/jit/replace.h"
62 #include "vm/jit/stacktrace.h"
64 #include "vmcore/loader.h"
65 #include "vmcore/options.h"
67 #include "vm/jit/sparc64/solaris/macro_rename.h"
69 #define BUILTIN_FLOAT_ARGS 1
71 /* XXX use something like this for window control ?
72 * #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER)
74 #define REG_PV REG_PV_CALLEE
79 if ((disp < -4096) || (disp > 4095))
80 printf("disp %d\n", disp);
83 return (disp >= -4096) && (disp <= 4095);
86 s4 get_lopart_disp(disp)
91 lodisp = setlo_part(disp);
93 if (setlo_part(disp) == 0)
96 lodisp = setlo_part(disp) | 0x1c00;
103 bool check_13bit_imm(s8 imm)
105 s4 sign = (imm >> 12) & 0x1;
108 if ((imm & ~0xfff) == 0) return true; /* pos imm. */
111 if ((imm & ~0xfff) + 0xfff == -1) return true; /* neg imm. */
113 printf("immediate out-of-bounds: %ld\n", imm);
119 /* codegen_emit ****************************************************************
121 Generates machine code.
123 *******************************************************************************/
125 bool codegen_emit(jitdata *jd)
131 s4 len, s1, s2, s3, d, disp, slots;
136 constant_classref *cr;
137 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
138 unresolved_method *um;
139 builtintable_entry *bte;
142 unresolved_field *uf;
146 /* get required compiler data */
153 /* prevent compiler warnings */
165 #if 0 /* no leaf optimization yet */
166 savedregs_num = (code_is_leafmethod(code)) ? 0 : 1; /* space to save the RA */
168 savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */
171 /* space to save used callee saved registers */
173 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
174 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
176 cd->stackframesize = rd->memuse + savedregs_num;
178 #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
179 if (checksync && code_is_synchronized(code))
180 cd->stackframesize++;
183 /* keep stack 16-byte aligned (ABI requirement) */
185 if (cd->stackframesize & 1)
186 cd->stackframesize++;
188 /* create method header */
190 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
191 framesize_disp = dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
193 code->synchronizedoffset = JITSTACK + rd->memuse * 8;
195 /* REMOVEME: We still need it for exception handling in assembler. */
197 if (code_is_leafmethod(code))
198 (void) dseg_add_unique_s4(cd, 1);
200 (void) dseg_add_unique_s4(cd, 0);
202 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
203 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
205 /* save register window and create stack frame (if necessary) */
207 if (cd->stackframesize) {
208 if (cd->stackframesize <= 4095)
209 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
211 M_ILD_INTERN(REG_ITMP3, REG_PV_CALLER, framesize_disp);
212 M_SUB(REG_ZERO, REG_ITMP3, REG_ITMP3);
213 M_SAVE_REG(REG_SP, REG_ITMP3, REG_SP);
217 /* save callee saved float registers (none right now) */
219 p = cd->stackframesize;
220 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
221 p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
226 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
227 emit_verbosecall_enter(jd);
231 /* call monitorenter function */
232 #if defined(ENABLE_THREADS)
233 if (checksync && code_is_synchronized(code)) {
234 /* stack offset for monitor argument */
238 /* save float argument registers */
242 ALIGN_STACK_SLOTS(slots);
244 M_LDA(REG_SP, REG_SP, -(slots * 8));
245 for (i = 0; i < FLT_ARG_CNT; i++)
246 M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
250 /* get correct lock object */
252 if (m->flags & ACC_STATIC) {
253 disp = dseg_add_address(cd, &m->class->object.header);
254 M_ALD(REG_OUT0, REG_PV, disp);
255 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
256 M_ALD(REG_ITMP3, REG_PV, disp);
259 /* copy class pointer: $i0 -> $o0 */
260 M_MOV(REG_RESULT_CALLEE, REG_OUT0);
262 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
263 M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
264 M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
267 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
268 M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */
270 /* restore float argument registers */
272 for (i = 0; i < FLT_ARG_CNT; i++)
273 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
275 M_LDA(REG_SP, REG_SP, slots * 8);
280 /* take arguments out of register or stack frame */
284 for (p = 0, l = 0; p < md->paramcount; p++) {
285 t = md->paramtypes[p].type;
287 varindex = jd->local_map[l * 5 + t];
290 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
293 if (varindex == UNUSED)
297 s1 = md->params[p].regoff;
299 if (IS_INT_LNG_TYPE(t)) { /* integer args */
303 if (!md->params[p].inmemory) { /* register arguments */
304 s1 = REG_WINDOW_TRANSPOSE(s1);
306 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
308 /* the register allocator does not know about the window. */
309 /* avoid copying the locals from save to save regs by */
310 /* swapping variables. */
313 int old_dest = var->vv.regoff;
314 int new_dest = p + 24;
316 /* run through all variables */
318 for (i = 0; i < jd->varcount; i++) {
319 varinfo* uvar = VAR(i);
321 if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags))
324 s2 = uvar->vv.regoff;
326 /* free the in reg by moving all other references */
328 if (s2 == new_dest) {
329 uvar->vv.regoff = old_dest;
330 /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
333 /* move all variables to the in reg */
335 if (s2 == old_dest) {
336 uvar->vv.regoff = new_dest;
337 /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
345 else { /* reg arg -> spilled */
346 M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
349 } else { /* stack arguments */
350 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
351 M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1);
353 } else { /* stack arg -> spilled */
354 /* add the callers window save registers */
355 var->vv.regoff = cd->stackframesize * 8 + s1;
359 } else { /* floating args */
360 if (!md->params[p].inmemory) { /* register arguments */
361 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
362 M_FLTMOVE(s1, var->vv.regoff);
364 } else { /* reg arg -> spilled */
365 M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
368 } else { /* stack arguments */
369 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
370 M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1);
372 } else { /* stack-arg -> spilled */
373 var->vv.regoff = cd->stackframesize * 8 + s1;
382 /* end of header generation */
384 /* create replacement points */
386 REPLACEMENT_POINTS_INIT(cd, jd);
388 /* walk through all basic blocks */
390 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
392 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
394 if (bptr->flags >= BBREACHED) {
396 /* branch resolving */
398 codegen_resolve_branchrefs(cd, bptr);
400 /* handle replacement points */
402 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
405 /* copy interface registers to their destination */
410 #if defined(ENABLE_LSRA)
411 #error XXX LSRA not tested yet
415 src = bptr->invars[len];
416 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
417 /* d = reg_of_var(m, src, REG_ITMP1); */
418 if (!(src->flags & INMEMORY))
422 M_INTMOVE(REG_ITMP1, d);
423 emit_store(jd, NULL, src, d);
430 var = VAR(bptr->invars[len]);
431 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
432 d = codegen_reg_of_var(0, var, REG_ITMP1);
433 M_INTMOVE(REG_ITMP2_XPTR, d);
434 emit_store(jd, NULL, var, d);
437 assert((var->flags & INOUT));
440 #if defined(ENABLE_LSRA)
443 /* walk through all instructions */
447 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
448 if (iptr->line != currentline) {
449 linenumbertable_list_entry_add(cd, iptr->line);
450 currentline = iptr->line;
453 MCODECHECK(64); /* an instruction usually needs < 64 words */
457 case ICMD_INLINE_START:
458 case ICMD_INLINE_END:
461 case ICMD_NOP: /* ... ==> ... */
464 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
466 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
467 emit_nullpointer_check(cd, iptr, s1);
470 /* constant operations ************************************************/
472 case ICMD_ICONST: /* ... ==> ..., constant */
474 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
475 ICONST(d, iptr->sx.val.i);
476 emit_store_dst(jd, iptr, d);
479 case ICMD_LCONST: /* ... ==> ..., constant */
481 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
482 LCONST(d, iptr->sx.val.l);
483 emit_store_dst(jd, iptr, d);
486 case ICMD_FCONST: /* ... ==> ..., constant */
488 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
489 disp = dseg_add_float(cd, iptr->sx.val.f);
490 M_FLD(d, REG_PV, disp);
491 emit_store_dst(jd, iptr, d);
494 case ICMD_DCONST: /* ... ==> ..., constant */
496 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
497 disp = dseg_add_double(cd, iptr->sx.val.d);
498 M_DLD(d, REG_PV, disp);
499 emit_store_dst(jd, iptr, d);
502 case ICMD_ACONST: /* ... ==> ..., constant */
504 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
506 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
507 cr = iptr->sx.val.c.ref;
508 disp = dseg_add_unique_address(cd, cr);
510 codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
512 M_ALD(d, REG_PV, disp);
516 if (iptr->sx.val.anyptr == NULL) {
517 M_INTMOVE(REG_ZERO, d);
520 disp = dseg_add_address(cd, iptr->sx.val.anyptr);
521 M_ALD(d, REG_PV, disp);
524 emit_store_dst(jd, iptr, d);
528 /* load/store/copy/move operations ************************************/
530 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
535 case ICMD_ISTORE: /* ..., value ==> ... */
546 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
551 /* pop/dup/swap operations ********************************************/
553 /* attention: double and longs are only one entry in CACAO ICMDs */
555 case ICMD_POP: /* ..., value ==> ... */
556 case ICMD_POP2: /* ..., value, value ==> ... */
560 /* integer operations *************************************************/
562 case ICMD_INEG: /* ..., value ==> ..., - value */
565 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
566 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
567 M_SUB(REG_ZERO, s1, d);
568 emit_store_dst(jd, iptr, d);
571 case ICMD_I2L: /* ..., value ==> ..., value */
573 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
574 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
576 emit_store_dst(jd, iptr, d);
579 case ICMD_L2I: /* ..., value ==> ..., value */
581 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
582 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
583 M_SRA_IMM(s1, 0, d); /* sign extend upper 32 bits */
584 emit_store_dst(jd, iptr, d);
587 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
589 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
590 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
591 M_SLLX_IMM(s1, 56, d);
592 M_SRAX_IMM( d, 56, d);
593 emit_store_dst(jd, iptr, d);
596 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
598 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
599 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
600 M_SLLX_IMM(s1, 48, d);
601 M_SRLX_IMM( d, 48, d);
602 emit_store_dst(jd, iptr, d);
605 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
607 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
608 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
609 M_SLLX_IMM(s1, 48, d);
610 M_SRAX_IMM( d, 48, d);
611 emit_store_dst(jd, iptr, d);
614 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
617 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
618 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
619 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
621 emit_store_dst(jd, iptr, d);
625 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
626 /* sx.val.i = constant */
628 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
629 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
630 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
631 M_ADD_IMM(s1, iptr->sx.val.i, d);
633 ICONST(REG_ITMP2, iptr->sx.val.i);
634 M_ADD(s1, REG_ITMP2, d);
636 emit_store_dst(jd, iptr, d);
639 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
640 /* sx.val.l = constant */
642 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
643 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
644 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
645 M_ADD_IMM(s1, iptr->sx.val.l, d);
647 LCONST(REG_ITMP2, iptr->sx.val.l);
648 M_ADD(s1, REG_ITMP2, d);
650 emit_store_dst(jd, iptr, d);
653 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
656 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
657 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
658 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
660 emit_store_dst(jd, iptr, d);
663 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
664 /* sx.val.i = constant */
666 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
667 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
668 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
669 M_SUB_IMM(s1, iptr->sx.val.i, d);
671 ICONST(REG_ITMP2, iptr->sx.val.i);
672 M_SUB(s1, REG_ITMP2, d);
674 emit_store_dst(jd, iptr, d);
677 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
678 /* sx.val.l = constant */
680 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
681 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
682 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
683 M_SUB_IMM(s1, iptr->sx.val.l, d);
685 LCONST(REG_ITMP2, iptr->sx.val.l);
686 M_SUB(s1, REG_ITMP2, d);
688 emit_store_dst(jd, iptr, d);
691 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
694 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
695 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
696 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
698 emit_store_dst(jd, iptr, d);
701 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
702 /* sx.val.i = constant */
704 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
705 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
706 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
707 M_MULX_IMM(s1, iptr->sx.val.i, d);
709 ICONST(REG_ITMP2, iptr->sx.val.i);
710 M_MULX(s1, REG_ITMP2, d);
712 emit_store_dst(jd, iptr, d);
715 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
716 /* sx.val.l = constant */
718 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
719 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
720 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
721 M_MULX_IMM(s1, iptr->sx.val.l, d);
723 LCONST(REG_ITMP2, iptr->sx.val.l);
724 M_MULX(s1, REG_ITMP2, d);
726 emit_store_dst(jd, iptr, d);
729 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
730 /* XXX could also clear Y and use 32bit div */
731 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
732 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
733 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
734 emit_arithmetic_check(cd, iptr, s2);
736 /* XXX trim s2 like s1 ? */
738 emit_store_dst(jd, iptr, d);
741 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
743 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
744 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
745 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
746 emit_arithmetic_check(cd, iptr, s2);
748 emit_store_dst(jd, iptr, d);
751 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
753 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
754 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
755 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
756 emit_arithmetic_check(cd, iptr, s2);
758 /* XXX trim s2 like s1 ? */
759 M_DIVX(s1, s2, REG_ITMP3);
760 M_MULX(s2, REG_ITMP3, REG_ITMP3);
761 M_SUB(s1, REG_ITMP3, d);
762 emit_store_dst(jd, iptr, d);
765 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
767 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
768 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
769 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
770 emit_arithmetic_check(cd, iptr, s2);
771 M_DIVX(s1, s2, REG_ITMP3);
772 M_MULX(s2, REG_ITMP3, REG_ITMP3);
773 M_SUB(s1, REG_ITMP3, d);
774 emit_store_dst(jd, iptr, d);
777 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
778 case ICMD_LDIVPOW2: /* val.i = constant */
780 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
781 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
782 M_SRAX_IMM(s1, 63, REG_ITMP2);
783 M_SRLX_IMM(REG_ITMP2, 64 - iptr->sx.val.i, REG_ITMP2);
784 M_ADD(s1, REG_ITMP2, REG_ITMP2);
785 M_SRAX_IMM(REG_ITMP2, iptr->sx.val.i, d);
786 emit_store_dst(jd, iptr, d);
789 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
791 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
792 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
793 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
795 emit_store_dst(jd, iptr, d);
798 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
800 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
801 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
802 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
804 emit_store_dst(jd, iptr, d);
807 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
808 /* val.i = constant */
810 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
811 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
812 M_SLL_IMM(s1, iptr->sx.val.i, d);
813 emit_store_dst(jd, iptr, d);
816 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
817 /* val.i = constant */
819 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
820 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
821 M_SLLX_IMM(s1, iptr->sx.val.i, d);
822 emit_store_dst(jd, iptr, d);
825 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
827 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
828 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
829 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
831 emit_store_dst(jd, iptr, d);
834 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
835 /* sx.val.i = constant */
837 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
838 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
839 M_SRA_IMM(s1, iptr->sx.val.i, d);
840 emit_store_dst(jd, iptr, d);
843 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
845 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
846 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
847 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
849 emit_store_dst(jd, iptr, d);
852 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
853 /* sx.val.i = constant */
855 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
856 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
857 M_SRL_IMM(s1, iptr->sx.val.i, d);
858 emit_store_dst(jd, iptr, d);
861 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
863 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
864 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
865 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
867 emit_store_dst(jd, iptr, d);
870 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
871 /* sx.val.i = constant */
873 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
874 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
875 M_SRAX_IMM(s1, iptr->sx.val.i, d);
876 emit_store_dst(jd, iptr, d);
879 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
881 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
882 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
883 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
885 emit_store_dst(jd, iptr, d);
888 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
889 /* sx.val.i = constant */
891 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
892 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
893 M_SRLX_IMM(s1, iptr->sx.val.i, d);
894 emit_store_dst(jd, iptr, d);
897 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
900 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
901 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
902 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
904 emit_store_dst(jd, iptr, d);
907 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
908 /* sx.val.i = constant */
910 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
911 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
912 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
913 M_AND_IMM(s1, iptr->sx.val.i, d);
915 ICONST(REG_ITMP2, iptr->sx.val.i);
916 M_AND(s1, REG_ITMP2, d);
918 emit_store_dst(jd, iptr, d);
921 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
922 /* sx.val.i = constant */
923 /* constant is actually constant - 1 */
925 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
926 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
928 M_MOV(s1, REG_ITMP1);
931 M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
932 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
933 M_AND_IMM(s1, iptr->sx.val.i, d);
936 M_SUB(REG_ZERO, s1, d);
937 M_AND_IMM(d, iptr->sx.val.i, d);
939 ICONST(REG_ITMP2, iptr->sx.val.i);
940 M_AND(s1, REG_ITMP2, d);
943 M_SUB(REG_ZERO, s1, d);
944 M_AND(d, REG_ITMP2, d);
946 M_SUB(REG_ZERO, d, d);
947 emit_store_dst(jd, iptr, d);
950 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
951 /* sx.val.l = constant */
953 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
954 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
955 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
956 M_AND_IMM(s1, iptr->sx.val.l, d);
958 LCONST(REG_ITMP2, iptr->sx.val.l);
959 M_AND(s1, REG_ITMP2, d);
961 emit_store_dst(jd, iptr, d);
964 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
965 /* sx.val.l = constant */
967 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
968 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
970 M_MOV(s1, REG_ITMP1);
973 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
974 M_AND_IMM(s1, iptr->sx.val.l, d);
977 M_SUB(REG_ZERO, s1, d);
978 M_AND_IMM(d, iptr->sx.val.l, d);
980 LCONST(REG_ITMP2, iptr->sx.val.l);
981 M_AND(s1, REG_ITMP2, d);
984 M_SUB(REG_ZERO, s1, d);
985 M_AND(d, REG_ITMP2, d);
987 M_SUB(REG_ZERO, d, d);
988 emit_store_dst(jd, iptr, d);
991 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
994 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
995 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
996 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
998 emit_store_dst(jd, iptr, d);
1001 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1002 /* sx.val.i = constant */
1004 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1005 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1006 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1007 M_OR_IMM(s1, iptr->sx.val.i, d);
1009 ICONST(REG_ITMP2, iptr->sx.val.i);
1010 M_OR(s1, REG_ITMP2, d);
1012 emit_store_dst(jd, iptr, d);
1015 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1016 /* sx.val.l = constant */
1018 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1019 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1020 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1021 M_OR_IMM(s1, iptr->sx.val.l, d);
1023 LCONST(REG_ITMP2, iptr->sx.val.l);
1024 M_OR(s1, REG_ITMP2, d);
1026 emit_store_dst(jd, iptr, d);
1029 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1032 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1033 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1034 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1036 emit_store_dst(jd, iptr, d);
1039 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1040 /* sx.val.i = constant */
1042 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1043 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1044 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1045 M_XOR_IMM(s1, iptr->sx.val.i, d);
1047 ICONST(REG_ITMP2, iptr->sx.val.i);
1048 M_XOR(s1, REG_ITMP2, d);
1050 emit_store_dst(jd, iptr, d);
1053 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1054 /* sx.val.l = constant */
1056 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1057 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1058 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1059 M_XOR_IMM(s1, iptr->sx.val.l, d);
1061 LCONST(REG_ITMP2, iptr->sx.val.l);
1062 M_XOR(s1, REG_ITMP2, d);
1064 emit_store_dst(jd, iptr, d);
1068 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1070 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1071 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1072 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1075 M_XCMOVLT_IMM(-1, d);
1076 M_XCMOVGT_IMM(1, d);
1077 emit_store_dst(jd, iptr, d);
1081 /* floating operations ************************************************/
1083 case ICMD_FNEG: /* ..., 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_DNEG: /* ..., value ==> ..., - value */
1093 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1094 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1096 emit_store_dst(jd, iptr, d);
1099 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1101 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1102 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1103 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1105 emit_store_dst(jd, iptr, d);
1108 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1110 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1111 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1112 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1114 emit_store_dst(jd, iptr, d);
1117 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1119 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1120 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1121 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1123 emit_store_dst(jd, iptr, d);
1126 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1128 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1129 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1130 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1132 emit_store_dst(jd, iptr, d);
1135 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1137 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1138 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1139 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1141 emit_store_dst(jd, iptr, d);
1144 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1146 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1147 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1148 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1150 emit_store_dst(jd, iptr, d);
1153 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1155 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1156 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1157 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1159 emit_store_dst(jd, iptr, d);
1162 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1164 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1165 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1166 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1168 emit_store_dst(jd, iptr, d);
1172 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1173 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1174 disp = dseg_add_unique_float(cd, 0.0);
1175 M_IST (s1, REG_PV_CALLEE, disp);
1176 M_FLD (d, REG_PV_CALLEE, disp);
1177 M_CVTIF (d, d); /* rd gets translated to double target register */
1178 emit_store_dst(jd, iptr, d);
1182 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1183 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1184 disp = dseg_add_unique_float(cd, 0.0);
1185 M_IST(s1, REG_PV_CALLEE, disp);
1186 M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
1187 M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
1188 emit_store_dst(jd, iptr, d);
1192 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1193 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1194 disp = dseg_add_unique_double(cd, 0.0);
1195 M_STX(s1, REG_PV_CALLEE, disp);
1196 M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
1197 M_CVTLF(REG_FTMP3, d);
1198 emit_store_dst(jd, iptr, d);
1202 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1203 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1204 disp = dseg_add_unique_double(cd, 0.0);
1205 M_STX(s1, REG_PV_CALLEE, disp);
1206 M_DLD(d, REG_PV_CALLEE, disp);
1208 emit_store_dst(jd, iptr, d);
1211 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1212 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1213 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1214 disp = dseg_add_unique_float(cd, 0.0);
1216 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1219 M_MOV(REG_ZERO, d); /* delay slot */
1221 M_CVTFI(s1, REG_FTMP2);
1222 M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
1223 M_ILD(d, REG_PV, disp);
1224 emit_store_dst(jd, iptr, d);
1228 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1229 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1230 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1231 disp = dseg_add_unique_float(cd, 0.0);
1233 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1236 M_MOV(REG_ZERO, d); /* delay slot */
1238 M_CVTDI(s1, REG_FTMP2);
1239 M_FST(REG_FTMP2, REG_PV, disp);
1240 M_ILD(d, REG_PV, disp);
1241 emit_store_dst(jd, iptr, d);
1244 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1245 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1246 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1247 disp = dseg_add_unique_double(cd, 0.0);
1249 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1252 M_MOV(REG_ZERO, d); /* delay slot */
1254 M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1255 M_DST(REG_FTMP2, REG_PV, disp);
1256 M_LDX(d, REG_PV, disp);
1257 emit_store_dst(jd, iptr, d);
1260 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1261 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1262 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1263 disp = dseg_add_unique_double(cd, 0.0);
1265 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1268 M_MOV(REG_ZERO, d); /* delay slot */
1270 M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1271 M_DST(REG_FTMP2, REG_PV, disp);
1272 M_LDX(d, REG_PV, disp);
1273 emit_store_dst(jd, iptr, d);
1276 case ICMD_F2D: /* ..., value ==> ..., (double) 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 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1286 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1287 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1289 emit_store_dst(jd, iptr, d);
1292 /* XXX merge F/D versions? only compare instr. is different */
1293 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1295 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1296 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1297 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1299 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1300 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1301 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1302 emit_store_dst(jd, iptr, d);
1305 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1307 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1308 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1309 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1311 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1312 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1313 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1314 emit_store_dst(jd, iptr, d);
1317 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1319 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1320 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1321 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1323 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1324 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1325 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1326 emit_store_dst(jd, iptr, d);
1329 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1331 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1332 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1333 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1335 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1336 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1337 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1338 emit_store_dst(jd, iptr, d);
1342 /* memory operations **************************************************/
1344 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1346 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1347 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1348 emit_nullpointer_check(cd, iptr, s1);
1349 M_ILD(d, s1, OFFSET(java_array_t, size));
1350 emit_store_dst(jd, iptr, d);
1353 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1355 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1356 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1357 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1358 /* implicit null-pointer check */
1359 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1360 M_AADD(s2, s1, REG_ITMP3);
1361 M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray_t, data[0]));
1362 emit_store_dst(jd, iptr, d);
1365 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1367 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1368 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1369 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1370 /* implicit null-pointer check */
1371 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1372 M_AADD(s2, s1, REG_ITMP3);
1373 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1374 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray_t, data[0]));
1375 emit_store_dst(jd, iptr, d);
1378 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1380 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1381 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1382 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1383 /* implicit null-pointer check */
1384 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1385 M_AADD(s2, s1, REG_ITMP3);
1386 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1387 M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray_t, data[0]));
1388 emit_store_dst(jd, iptr, d);
1391 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1393 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1394 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1395 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1396 /* implicit null-pointer check */
1397 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1398 M_ASLL_IMM(s2, 2, REG_ITMP3);
1399 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1400 M_ILD(d, REG_ITMP3, OFFSET(java_intarray_t, data[0]));
1401 emit_store_dst(jd, iptr, d);
1404 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1406 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1407 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1408 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1409 /* implicit null-pointer check */
1410 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1411 M_ASLL_IMM(s2, 3, REG_ITMP3);
1412 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1413 M_LDX(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1414 emit_store_dst(jd, iptr, d);
1417 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1419 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1420 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1421 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1422 /* implicit null-pointer check */
1423 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1424 M_ASLL_IMM(s2, 2, REG_ITMP3);
1425 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1426 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray_t, data[0]));
1427 emit_store_dst(jd, iptr, d);
1430 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1432 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1433 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1434 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1435 /* implicit null-pointer check */
1436 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1437 M_ASLL_IMM(s2, 3, REG_ITMP3);
1438 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1439 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1440 emit_store_dst(jd, iptr, d);
1443 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1445 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1446 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1447 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1448 /* implicit null-pointer check */
1449 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1450 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1451 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1452 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray_t, data[0]));
1453 emit_store_dst(jd, iptr, d);
1457 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1459 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1460 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1461 /* implicit null-pointer check */
1462 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1463 M_AADD(s2, s1, REG_ITMP1);
1464 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1465 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1468 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1469 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1471 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1472 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1473 /* implicit null-pointer check */
1474 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1475 M_AADD(s2, s1, REG_ITMP1);
1476 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1477 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1478 M_SST(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1481 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1483 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1484 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1485 /* implicit null-pointer check */
1486 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1487 M_ASLL_IMM(s2, 2, REG_ITMP2);
1488 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1489 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1490 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1493 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1495 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1496 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1497 /* implicit null-pointer check */
1498 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1499 M_ASLL_IMM(s2, 3, REG_ITMP2);
1500 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1501 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1502 M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1505 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1507 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1508 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1509 /* implicit null-pointer check */
1510 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1511 M_ASLL_IMM(s2, 2, REG_ITMP2);
1512 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1513 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1514 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1517 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1519 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1520 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1521 /* implicit null-pointer check */
1522 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1523 M_ASLL_IMM(s2, 3, REG_ITMP2);
1524 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1525 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1526 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1530 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1532 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1533 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1534 /* implicit null-pointer check */
1535 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1536 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1538 M_MOV(s1, REG_OUT0);
1539 M_MOV(s3, REG_OUT1);
1540 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1541 M_ALD(REG_ITMP3, REG_PV, disp);
1542 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
1544 emit_arraystore_check(cd, iptr);
1546 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1547 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1548 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1549 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1550 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1551 /* implicit null-pointer check */
1552 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1556 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1558 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1559 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1560 /* implicit null-pointer check */
1561 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1562 M_AADD(s2, s1, REG_ITMP1);
1563 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1566 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1567 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1569 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1570 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1571 /* implicit null-pointer check */
1572 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1573 M_AADD(s2, s1, REG_ITMP1);
1574 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1575 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1578 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1580 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1581 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1582 /* implicit null-pointer check */
1583 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1584 M_ASLL_IMM(s2, 2, REG_ITMP2);
1585 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1586 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1589 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1591 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1592 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1593 /* implicit null-pointer check */
1594 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1595 M_ASLL_IMM(s2, 3, REG_ITMP2);
1596 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1597 M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1600 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1602 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1603 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1604 /* implicit null-pointer check */
1605 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1606 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1607 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1608 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1612 case ICMD_GETSTATIC: /* ... ==> ..., value */
1614 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1615 uf = iptr->sx.s23.s3.uf;
1616 fieldtype = uf->fieldref->parseddesc.fd->type;
1617 disp = dseg_add_unique_address(cd, uf);
1619 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1622 fi = iptr->sx.s23.s3.fmiref->p.field;
1623 fieldtype = fi->type;
1624 disp = dseg_add_address(cd, fi->value);
1626 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1627 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1630 M_ALD(REG_ITMP1, REG_PV, disp);
1632 switch (fieldtype) {
1634 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1635 M_ILD_INTERN(d, REG_ITMP1, 0);
1638 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1639 M_LDX_INTERN(d, REG_ITMP1, 0);
1642 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1643 M_ALD_INTERN(d, REG_ITMP1, 0);
1646 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1647 M_FLD_INTERN(d, REG_ITMP1, 0);
1650 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1651 M_DLD_INTERN(d, REG_ITMP1, 0);
1654 emit_store_dst(jd, iptr, d);
1657 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1659 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1660 uf = iptr->sx.s23.s3.uf;
1661 fieldtype = uf->fieldref->parseddesc.fd->type;
1662 disp = dseg_add_unique_address(cd, uf);
1664 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1667 fi = iptr->sx.s23.s3.fmiref->p.field;
1668 fieldtype = fi->type;
1669 disp = dseg_add_address(cd, fi->value);
1671 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1672 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1675 M_ALD(REG_ITMP1, REG_PV, disp);
1677 switch (fieldtype) {
1679 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1680 M_IST_INTERN(s1, REG_ITMP1, 0);
1683 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1684 M_STX_INTERN(s1, REG_ITMP1, 0);
1687 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1688 M_AST_INTERN(s1, REG_ITMP1, 0);
1691 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1692 M_FST_INTERN(s1, REG_ITMP1, 0);
1695 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1696 M_DST_INTERN(s1, REG_ITMP1, 0);
1701 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1702 /* val = value (in current instruction) */
1703 /* following NOP) */
1705 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1706 uf = iptr->sx.s23.s3.uf;
1707 fieldtype = uf->fieldref->parseddesc.fd->type;
1708 disp = dseg_add_unique_address(cd, uf);
1710 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1713 fi = iptr->sx.s23.s3.fmiref->p.field;
1714 fieldtype = fi->type;
1715 disp = dseg_add_address(cd, fi->value);
1717 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1718 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1721 M_ALD(REG_ITMP1, REG_PV, disp);
1723 switch (fieldtype) {
1725 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1728 M_STX_INTERN(REG_ZERO, REG_ITMP1, 0);
1731 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1734 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1737 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1743 case ICMD_GETFIELD: /* ... ==> ..., value */
1745 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1746 emit_nullpointer_check(cd, iptr, s1);
1748 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1749 uf = iptr->sx.s23.s3.uf;
1751 fieldtype = uf->fieldref->parseddesc.fd->type;
1754 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1757 fi = iptr->sx.s23.s3.fmiref->p.field;
1758 fieldtype = fi->type;
1762 switch (fieldtype) {
1764 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1768 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1772 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1776 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1780 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1787 emit_store_dst(jd, iptr, d);
1790 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1792 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1793 emit_nullpointer_check(cd, iptr, s1);
1795 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1796 uf = iptr->sx.s23.s3.uf;
1797 fieldtype = uf->fieldref->parseddesc.fd->type;
1802 fi = iptr->sx.s23.s3.fmiref->p.field;
1803 fieldtype = fi->type;
1807 if (IS_INT_LNG_TYPE(fieldtype))
1808 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1810 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1812 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1813 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1815 switch (fieldtype) {
1817 M_IST(s2, s1, disp);
1820 M_STX(s2, s1, disp);
1823 M_AST(s2, s1, disp);
1826 M_FST(s2, s1, disp);
1829 M_DST(s2, s1, disp);
1837 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
1838 /* val = value (in current instruction) */
1839 /* following NOP) */
1841 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1842 emit_nullpointer_check(cd, iptr, s1);
1844 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1845 unresolved_field *uf = iptr->sx.s23.s3.uf;
1847 fieldtype = uf->fieldref->parseddesc.fd->type;
1849 codegen_addpatchref(cd, PATCHER_get_putfield,
1852 if (opt_showdisassemble) {
1860 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1862 fieldtype = fi->type;
1868 switch (fieldtype) {
1870 M_IST(REG_ZERO, s1, disp);
1873 M_STX(REG_ZERO, s1, disp);
1876 M_AST(REG_ZERO, s1, disp);
1879 M_FST(REG_ZERO, s1, disp);
1882 M_DST(REG_ZERO, s1, disp);
1888 /* branch operations **************************************************/
1890 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1892 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1893 M_INTMOVE(s1, REG_ITMP2_XPTR);
1895 #ifdef ENABLE_VERIFIER
1896 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1897 unresolved_class *uc = iptr->sx.s23.s2.uc;
1899 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
1901 #endif /* ENABLE_VERIFIER */
1903 disp = dseg_add_functionptr(cd, asm_handle_exception);
1904 M_ALD(REG_ITMP1, REG_PV, disp);
1905 M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
1907 M_NOP; /* nop ensures that XPC is less than the end */
1908 /* of basic block */
1912 case ICMD_GOTO: /* ... ==> ... */
1913 case ICMD_RET: /* ... ==> ... */
1915 emit_br(cd, iptr->dst.block);
1919 case ICMD_JSR: /* ... ==> ... */
1921 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1925 case ICMD_IFNULL: /* ..., value ==> ... */
1926 case ICMD_IFNONNULL:
1928 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1929 emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
1932 /* Note: int compares must not branch on the register directly. */
1933 /* Reason is, that register content is not 32-bit clean. */
1935 case ICMD_IFEQ: /* ..., value ==> ... */
1937 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1939 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1940 M_CMP_IMM(s1, iptr->sx.val.i);
1943 ICONST(REG_ITMP2, iptr->sx.val.i);
1944 M_CMP(s1, REG_ITMP2);
1946 emit_beq(cd, iptr->dst.block);
1949 case ICMD_IFLT: /* ..., value ==> ... */
1951 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1953 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1954 M_CMP_IMM(s1, iptr->sx.val.i);
1957 ICONST(REG_ITMP2, iptr->sx.val.i);
1958 M_CMP(s1, REG_ITMP2);
1960 emit_blt(cd, iptr->dst.block);
1963 case ICMD_IFLE: /* ..., value ==> ... */
1965 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1967 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1968 M_CMP_IMM(s1, iptr->sx.val.i);
1971 ICONST(REG_ITMP2, iptr->sx.val.i);
1972 M_CMP(s1, REG_ITMP2);
1974 emit_ble(cd, iptr->dst.block);
1977 case ICMD_IFNE: /* ..., value ==> ... */
1979 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1981 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1982 M_CMP_IMM(s1, iptr->sx.val.i);
1985 ICONST(REG_ITMP2, iptr->sx.val.i);
1986 M_CMP(s1, REG_ITMP2);
1988 emit_bne(cd, iptr->dst.block);
1991 case ICMD_IFGT: /* ..., value ==> ... */
1993 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1995 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1996 M_CMP_IMM(s1, iptr->sx.val.i);
1999 ICONST(REG_ITMP2, iptr->sx.val.i);
2000 M_CMP(s1, REG_ITMP2);
2002 emit_bgt(cd, iptr->dst.block);
2005 case ICMD_IFGE: /* ..., value ==> ... */
2007 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2009 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2010 M_CMP_IMM(s1, iptr->sx.val.i);
2013 ICONST(REG_ITMP2, iptr->sx.val.i);
2014 M_CMP(s1, REG_ITMP2);
2016 emit_bge(cd, iptr->dst.block);
2019 case ICMD_IF_LEQ: /* ..., value ==> ... */
2021 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2022 if (iptr->sx.val.l == 0)
2023 emit_beqz(cd, iptr->dst.block, s1);
2025 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2026 M_CMP_IMM(s1, iptr->sx.val.l);
2029 LCONST(REG_ITMP2, iptr->sx.val.l);
2030 M_CMP(s1, REG_ITMP2);
2032 emit_beq_xcc(cd, iptr->dst.block);
2036 case ICMD_IF_LLT: /* ..., value ==> ... */
2038 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2039 if (iptr->sx.val.l == 0)
2040 emit_bltz(cd, iptr->dst.block, s1);
2042 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2043 M_CMP_IMM(s1, iptr->sx.val.l);
2046 LCONST(REG_ITMP2, iptr->sx.val.l);
2047 M_CMP(s1, REG_ITMP2);
2049 emit_blt_xcc(cd, iptr->dst.block);
2053 case ICMD_IF_LLE: /* ..., value ==> ... */
2055 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2056 if (iptr->sx.val.l == 0)
2057 emit_blez(cd, iptr->dst.block, s1);
2059 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2060 M_CMP_IMM(s1, iptr->sx.val.l);
2063 LCONST(REG_ITMP2, iptr->sx.val.l);
2064 M_CMP(s1, REG_ITMP2);
2066 emit_ble_xcc(cd, iptr->dst.block);
2070 case ICMD_IF_LNE: /* ..., value ==> ... */
2072 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2073 if (iptr->sx.val.l == 0)
2074 emit_bnez(cd, iptr->dst.block, s1);
2076 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2077 M_CMP_IMM(s1, iptr->sx.val.l);
2080 LCONST(REG_ITMP2, iptr->sx.val.l);
2081 M_CMP(s1, REG_ITMP2);
2083 emit_bne_xcc(cd, iptr->dst.block);
2087 case ICMD_IF_LGT: /* ..., value ==> ... */
2089 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2090 if (iptr->sx.val.l == 0)
2091 emit_bgtz(cd, iptr->dst.block, s1);
2093 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2094 M_CMP_IMM(s1, iptr->sx.val.l);
2097 LCONST(REG_ITMP2, iptr->sx.val.l);
2098 M_CMP(s1, REG_ITMP2);
2100 emit_bgt_xcc(cd, iptr->dst.block);
2104 case ICMD_IF_LGE: /* ..., value ==> ... */
2106 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2107 if (iptr->sx.val.l == 0)
2108 emit_bgez(cd, iptr->dst.block, s1);
2110 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2111 M_CMP_IMM(s1, iptr->sx.val.l);
2114 LCONST(REG_ITMP2, iptr->sx.val.l);
2115 M_CMP(s1, REG_ITMP2);
2117 emit_bge_xcc(cd, iptr->dst.block);
2122 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2123 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2125 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2126 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2128 emit_beq_xcc(cd, iptr->dst.block);
2131 case ICMD_IF_ICMPEQ: /* 32-bit compare */
2133 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2134 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2136 emit_beq(cd, iptr->dst.block);
2139 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
2140 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2142 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2143 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2145 emit_bne_xcc(cd, iptr->dst.block);
2148 case ICMD_IF_ICMPNE: /* 32-bit compare */
2150 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2151 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2153 emit_bne(cd, iptr->dst.block);
2156 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2158 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2159 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2161 emit_blt_xcc(cd, iptr->dst.block);
2164 case ICMD_IF_ICMPLT: /* 32-bit compare */
2166 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2167 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2169 emit_blt(cd, iptr->dst.block);
2172 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2174 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2175 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2177 emit_bgt_xcc(cd, iptr->dst.block);
2180 case ICMD_IF_ICMPGT: /* 32-bit compare */
2182 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2183 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2185 emit_bgt(cd, iptr->dst.block);
2188 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2190 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2191 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2193 emit_ble_xcc(cd, iptr->dst.block);
2196 case ICMD_IF_ICMPLE: /* 32-bit compare */
2198 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2199 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2201 emit_ble(cd, iptr->dst.block);
2205 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2207 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2208 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2210 emit_bge_xcc(cd, iptr->dst.block);
2213 case ICMD_IF_ICMPGE: /* 32-bit compare */
2215 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2216 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2218 emit_bge(cd, iptr->dst.block);
2222 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2225 REPLACEMENT_POINT_RETURN(cd, iptr);
2227 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2228 M_INTMOVE(s1, REG_RESULT_CALLEE);
2229 goto nowperformreturn;
2231 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2233 REPLACEMENT_POINT_RETURN(cd, iptr);
2235 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2236 M_INTMOVE(s1, REG_RESULT_CALLEE);
2238 #ifdef ENABLE_VERIFIER
2239 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2240 unresolved_class *uc = iptr->sx.s23.s2.uc;
2242 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2244 #endif /* ENABLE_VERIFIER */
2245 goto nowperformreturn;
2247 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2250 REPLACEMENT_POINT_RETURN(cd, iptr);
2252 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2253 M_DBLMOVE(s1, REG_FRESULT);
2254 goto nowperformreturn;
2256 case ICMD_RETURN: /* ... ==> ... */
2258 REPLACEMENT_POINT_RETURN(cd, iptr);
2264 p = cd->stackframesize;
2266 #if !defined(NDEBUG)
2267 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2268 emit_verbosecall_exit(jd);
2271 #if defined(ENABLE_THREADS)
2272 if (checksync && code_is_synchronized(code)) {
2273 /* XXX jit-c-call */
2274 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2275 M_ALD(REG_ITMP3, REG_PV, disp);
2277 /* we need to save fp return value (int saved by window) */
2279 switch (iptr->opc) {
2282 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
2283 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2284 M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2286 /* restore the fp return value */
2288 M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
2294 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2295 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2306 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
2312 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2315 branch_target_t *table;
2317 table = iptr->dst.table;
2319 l = iptr->sx.s23.s2.tablelow;
2320 i = iptr->sx.s23.s3.tablehigh;
2322 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2324 M_INTMOVE(s1, REG_ITMP1);
2326 else if (-l >= 4096 && -l <= 4095) {
2327 M_ADD_IMM(s1, -l, REG_ITMP1);
2330 ICONST(REG_ITMP2, l);
2331 M_SUB(s1, REG_ITMP2, REG_ITMP1);
2334 i = i - l + 1; /* number of targets (>0) */
2340 M_CMP_IMM(REG_ITMP1, i - 1);
2343 ICONST(REG_ITMP2, i - 1);
2344 M_CMP(REG_ITMP1, REG_ITMP2);
2346 emit_bugt(cd, table[0].block); /* default target */
2348 /* build jump table top down and use address of lowest entry */
2353 dseg_add_target(cd, table->block);
2358 /* length of dataseg after last dseg_addtarget is used by load */
2360 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
2361 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2362 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2363 M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
2368 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2371 lookup_target_t *lookup;
2373 lookup = iptr->dst.lookup;
2375 i = iptr->sx.s23.s2.lookupcount;
2377 MCODECHECK((i<<2)+8);
2378 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2381 if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
2382 M_CMP_IMM(s1, lookup->value);
2384 ICONST(REG_ITMP2, lookup->value);
2385 M_CMP(s1, REG_ITMP2);
2387 emit_beq(cd, lookup->target.block);
2391 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2397 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
2399 REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
2401 bte = iptr->sx.s23.s3.bte;
2404 /* XXX: builtin calling with stack arguments not implemented */
2405 assert(md->paramcount <= 5 && md->argfltreguse <= 16);
2407 s3 = md->paramcount;
2409 MCODECHECK((s3 << 1) + 64);
2411 #ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
2413 /* copy float arguments according to ABI convention */
2415 int num_fltregargs = 0;
2416 int fltregarg_inswap[16];
2418 for (s3 = s3 - 1; s3 >= 0; s3--) {
2419 var = VAR(iptr->sx.s23.s2.args[s3]);
2421 if (IS_FLT_DBL_TYPE(var->type)) {
2422 if (!md->params[s3].inmemory) {
2423 s1 = s3; /*native flt args use argument index directly*/
2424 d = emit_load(jd, iptr, var, REG_FTMP1);
2427 fltregarg_inswap[num_fltregargs] = s1;
2429 /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
2438 /* move swapped float args to target regs */
2439 for (i = 0; i < num_fltregargs; i++) {
2440 s1 = fltregarg_inswap[i];
2441 M_DMOV(s1 + 16, s1);
2442 /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
2446 assert(md->argfltreguse == 0);
2451 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2452 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2453 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2454 case ICMD_INVOKEINTERFACE:
2456 REPLACEMENT_POINT_INVOKE(cd, iptr);
2458 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2460 um = iptr->sx.s23.s3.um;
2461 md = um->methodref->parseddesc.md;
2464 lm = iptr->sx.s23.s3.fmiref->p.method;
2466 md = lm->parseddesc;
2470 s3 = md->paramcount;
2472 MCODECHECK((s3 << 1) + 64);
2474 /* copy arguments to registers or stack location */
2476 for (s3 = s3 - 1; s3 >= 0; s3--) {
2477 var = VAR(iptr->sx.s23.s2.args[s3]);
2478 d = md->params[s3].regoff;
2480 if (var->flags & PREALLOC)
2483 if (IS_INT_LNG_TYPE(var->type)) {
2484 if (!md->params[s3].inmemory) {
2485 s1 = emit_load(jd, iptr, var, d);
2489 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2490 M_STX(s1, REG_SP, JITSTACK + d);
2494 #ifdef BUILTIN_FLOAT_ARGS
2495 if (iptr->opc == ICMD_BUILTIN)
2499 if (!md->params[s3].inmemory) {
2500 s1 = emit_load(jd, iptr, var, d);
2501 if (IS_2_WORD_TYPE(var->type))
2507 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2508 M_DST(s1, REG_SP, JITSTACK + d);
2513 switch (iptr->opc) {
2515 if (bte->stub == NULL) {
2516 disp = dseg_add_functionptr(cd, bte->fp);
2519 disp = dseg_add_functionptr(cd, bte->stub);
2522 M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
2524 /* XXX jit-c-call */
2525 /* generate the actual call */
2527 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2529 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2530 REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
2531 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2532 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2533 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2535 if (md->returntype.type == TYPE_FLT) {
2536 /* special handling for float return value in %f0 */
2541 case ICMD_INVOKESPECIAL:
2542 emit_nullpointer_check(cd, iptr, REG_OUT0);
2545 case ICMD_INVOKESTATIC:
2547 disp = dseg_add_unique_address(cd, NULL);
2549 codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
2553 disp = dseg_add_address(cd, lm->stubroutine);
2555 M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
2557 /* generate the actual call */
2559 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2561 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2562 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2563 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2564 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2567 case ICMD_INVOKEVIRTUAL:
2568 emit_nullpointer_check(cd, iptr, REG_OUT0);
2571 codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
2576 s1 = OFFSET(vftbl_t, table[0]) +
2577 sizeof(methodptr) * lm->vftblindex;
2579 /* implicit null-pointer check */
2580 M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
2581 M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
2583 /* generate the actual call */
2585 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2587 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2588 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2589 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2590 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2593 case ICMD_INVOKEINTERFACE:
2594 emit_nullpointer_check(cd, iptr, REG_OUT0);
2597 codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
2603 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2604 sizeof(methodptr*) * lm->class->index;
2606 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2609 /* implicit null-pointer check */
2610 M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
2611 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2612 M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
2614 /* generate the actual call */
2616 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2618 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2619 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2620 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2621 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2625 /* store return value */
2627 d = md->returntype.type;
2629 if (d != TYPE_VOID) {
2630 if (IS_INT_LNG_TYPE(d)) {
2631 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2632 M_INTMOVE(REG_RESULT_CALLER, s1);
2635 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2636 if (IS_2_WORD_TYPE(d)) {
2637 M_DBLMOVE(REG_FRESULT, s1);
2639 M_FLTMOVE(REG_FRESULT, s1);
2642 emit_store_dst(jd, iptr, s1);
2647 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2648 /* val.a: (classinfo*) superclass */
2650 /* superclass is an interface:
2652 * OK if ((sub == NULL) ||
2653 * (sub->vftbl->interfacetablelength > super->index) &&
2654 * (sub->vftbl->interfacetable[-super->index] != NULL));
2656 * superclass is a class:
2658 * OK if ((sub == NULL) || (0
2659 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2660 * super->vftbl->diffvall));
2663 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2667 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2672 super = iptr->sx.s23.s3.c.cls;
2673 superindex = super->index;
2676 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2677 CODEGEN_CRITICAL_SECTION_NEW;
2679 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2681 /* if class is not resolved, check which code to call */
2683 if (super == NULL) {
2684 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2686 cr = iptr->sx.s23.s3.c.ref;
2687 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2689 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2692 M_ILD(REG_ITMP2, REG_PV, disp);
2693 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2694 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
2697 /* interface checkcast code */
2699 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2700 if (super == NULL) {
2701 cr = iptr->sx.s23.s3.c.ref;
2703 codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
2707 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2710 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2711 M_ILD(REG_ITMP3, REG_ITMP2,
2712 OFFSET(vftbl_t, interfacetablelength));
2713 M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
2714 emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
2716 M_ALD(REG_ITMP3, REG_ITMP2,
2717 OFFSET(vftbl_t, interfacetable[0]) -
2718 superindex * sizeof(methodptr*));
2719 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
2722 emit_label_br(cd, BRANCH_LABEL_4);
2724 emit_label(cd, BRANCH_LABEL_3);
2727 /* class checkcast code */
2729 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2730 if (super == NULL) {
2731 emit_label(cd, BRANCH_LABEL_2);
2733 cr = iptr->sx.s23.s3.c.ref;
2734 disp = dseg_add_unique_address(cd, NULL);
2736 codegen_add_patch_ref(cd,
2737 PATCHER_checkcast_instanceof_class,
2741 disp = dseg_add_address(cd, super->vftbl);
2743 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2746 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2747 M_ALD(REG_ITMP3, REG_PV, disp);
2749 CODEGEN_CRITICAL_SECTION_START;
2751 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2752 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2753 M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2754 M_ALD(REG_ITMP3, REG_PV, disp);
2755 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2757 CODEGEN_CRITICAL_SECTION_END;
2760 M_CMP(REG_ITMP3, REG_ITMP2);
2761 emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
2764 emit_label(cd, BRANCH_LABEL_5);
2767 if (super == NULL) {
2768 emit_label(cd, BRANCH_LABEL_1);
2769 emit_label(cd, BRANCH_LABEL_4);
2772 d = codegen_reg_of_dst(jd, iptr, s1);
2775 /* array type cast-check */
2777 s1 = emit_load_s1(jd, iptr, REG_OUT0);
2778 M_INTMOVE(s1, REG_OUT0);
2780 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2782 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2783 cr = iptr->sx.s23.s3.c.ref;
2784 disp = dseg_add_unique_address(cd, NULL);
2786 codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
2790 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2792 M_ALD(REG_OUT1, REG_PV, disp);
2793 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2794 M_ALD(REG_ITMP3, REG_PV, disp);
2795 /* XXX jit-c-call */
2796 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2799 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2800 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
2802 d = codegen_reg_of_dst(jd, iptr, s1);
2806 emit_store_dst(jd, iptr, d);
2809 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2810 /* val.a: (classinfo*) superclass */
2812 /* superclass is an interface:
2814 * return (sub != NULL) &&
2815 * (sub->vftbl->interfacetablelength > super->index) &&
2816 * (sub->vftbl->interfacetable[-super->index] != NULL);
2818 * superclass is a class:
2820 * return ((sub != NULL) && (0
2821 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2822 * super->vftbl->diffvall));
2827 vftbl_t *supervftbl;
2830 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2836 super = iptr->sx.s23.s3.c.cls;
2837 superindex = super->index;
2838 supervftbl = super->vftbl;
2841 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2842 CODEGEN_CRITICAL_SECTION_NEW;
2844 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2845 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2847 M_MOV(s1, REG_ITMP1);
2853 /* if class is not resolved, check which code to call */
2855 if (super == NULL) {
2856 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2858 cr = iptr->sx.s23.s3.c.ref;
2859 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2861 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2864 M_ILD(REG_ITMP3, REG_PV, disp);
2865 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2866 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
2869 /* interface instanceof code */
2871 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2872 if (super == NULL) {
2873 cr = iptr->sx.s23.s3.c.ref;
2875 codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
2879 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2882 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2883 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2884 M_CMP_IMM(REG_ITMP3, superindex);
2887 M_ALD(REG_ITMP1, REG_ITMP1,
2888 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2889 superindex * sizeof(methodptr*)));
2890 M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
2893 emit_label_br(cd, BRANCH_LABEL_4);
2895 emit_label(cd, BRANCH_LABEL_3);
2898 /* class instanceof code */
2900 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2901 if (super == NULL) {
2902 emit_label(cd, BRANCH_LABEL_2);
2904 cr = iptr->sx.s23.s3.c.ref;
2905 disp = dseg_add_unique_address(cd, NULL);
2907 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
2911 disp = dseg_add_address(cd, supervftbl);
2913 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2916 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2917 M_ALD(REG_ITMP2, REG_PV, disp);
2919 CODEGEN_CRITICAL_SECTION_START;
2921 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2922 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2923 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2925 CODEGEN_CRITICAL_SECTION_END;
2927 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2928 M_CMP(REG_ITMP1, REG_ITMP2);
2929 M_XCMOVULE_IMM(1, d);
2932 emit_label(cd, BRANCH_LABEL_5);
2935 if (super == NULL) {
2936 emit_label(cd, BRANCH_LABEL_1);
2937 emit_label(cd, BRANCH_LABEL_4);
2940 emit_store_dst(jd, iptr, d);
2944 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2946 /* check for negative sizes and copy sizes to stack if necessary */
2948 MCODECHECK((iptr->s1.argcount << 1) + 64);
2950 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2952 var = VAR(iptr->sx.s23.s2.args[s1]);
2954 /* copy SAVEDVAR sizes to stack */
2956 /* Already Preallocated? */
2958 if (!(var->flags & PREALLOC)) {
2959 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2960 M_STX(s2, REG_SP, CSTACK + (s1 * 8));
2964 /* arg 0 = dimension count */
2966 ICONST(REG_OUT0, iptr->s1.argcount);
2968 /* is patcher function set? */
2970 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2971 disp = dseg_add_unique_address(cd, 0);
2973 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
2974 iptr->sx.s23.s3.c.ref,
2978 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2980 /* arg 1 = arraydescriptor */
2982 M_ALD(REG_OUT1, REG_PV, disp);
2984 /* arg 2 = pointer to dimensions = stack pointer (absolute) */
2986 M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
2988 /* XXX c abi call */
2989 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2990 M_ALD(REG_ITMP3, REG_PV, disp);
2991 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2994 /* check for exception before result assignment */
2996 emit_exception_check(cd, iptr);
2998 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2999 M_INTMOVE(REG_RESULT_CALLER, d);
3000 emit_store_dst(jd, iptr, d);
3004 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
3010 } /* for instruction */
3014 /* At the end of a basic block we may have to append some nops,
3015 because the patcher stub calling code might be longer than the
3016 actual instruction. So codepatching does not change the
3017 following block unintentionally. */
3019 if (cd->mcodeptr < cd->lastmcodeptr) {
3020 while (cd->mcodeptr < cd->lastmcodeptr) {
3025 } /* if (bptr -> flags >= BBREACHED) */
3026 } /* for basic block */
3028 /* generate stubs */
3030 emit_patcher_stubs(jd);
3032 /* everything's ok */
3038 /* codegen_emit_stub_compiler **************************************************
3040 Emits a stub routine which calls the compiler.
3042 *******************************************************************************/
3044 void codegen_emit_stub_compiler(jitdata *jd)
3049 /* get required compiler data */
3054 /* code for the stub */
3056 /* no window save yet, user caller's PV */
3057 M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */
3058 M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */
3059 M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */
3064 /* codegen_emit_stub_builtin ***************************************************
3066 Creates a stub routine which calls a builtin function.
3068 *******************************************************************************/
3070 void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
3079 /* get required compiler data */
3083 /* set some variables */
3086 /* calculate stack frame size */
3087 cd->stackframesize =
3091 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
3092 4; /* 4 arguments or return value */
3095 /* keep stack 16-byte aligned (ABI requirement) */
3097 if (cd->stackframesize & 1)
3098 cd->stackframesize++;
3100 /* create method header */
3101 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3102 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3103 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3104 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3105 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3107 /* generate stub code */
3108 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3110 #if defined(ENABLE_GC_CACAO)
3111 /* Save callee saved integer registers in stackframeinfo (GC may
3112 need to recover them during a collection). */
3114 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3115 OFFSET(stackframeinfo_t, intregs) + BIAS;
3117 for (i = 0; i < INT_SAV_CNT; i++)
3118 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3121 for (i = 0; i < md->paramcount; i++) {
3122 s1 = md->params[i].regoff;
3124 switch (md->paramtypes[i].type) {
3131 M_DST(s1, REG_SP, JITSTACK + i * 8);
3136 /* create dynamic stack info */
3138 M_AADD_IMM(REG_SP, BIAS + cd->stackframesize * 8, REG_OUT0); /* data sp*/
3139 M_MOV(REG_PV_CALLEE, REG_OUT1); /* PV */
3140 M_MOV(REG_FP, REG_OUT2); /* java sp */
3141 M_MOV(REG_RA_CALLEE, REG_OUT3); /* ra */
3143 disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
3144 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3145 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3146 M_NOP; /* XXX fill me! */
3149 /* builtins are allowed to have 5 arguments max */
3151 assert(md->paramcount <= 5);
3153 /* copy arguments into position */
3155 for (i = 0; i < md->paramcount; i++) {
3156 assert(!md->params[i].inmemory);
3158 s1 = md->params[i].regoff;
3160 switch (md->paramtypes[i].type) {
3164 M_MOV(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[i]), s1);
3168 M_DLD(s1, REG_SP, JITSTACK + i * 8);
3174 /* call the builtin function */
3176 disp = dseg_add_functionptr(cd, bte->fp);
3177 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); /* load adress of builtin */
3178 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call builtin */
3179 M_NOP; /* delay slot */
3182 /* save return value */
3184 if (md->returntype.type != TYPE_VOID) {
3185 if (IS_INT_LNG_TYPE(md->returntype.type))
3186 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3188 M_DST(REG_FRESULT, REG_SP, CSTACK);
3192 /* remove native stackframe info */
3194 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3195 disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
3196 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3197 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3200 /* restore float return value, int return value already in our return reg */
3202 if (md->returntype.type != TYPE_VOID) {
3203 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3204 if (IS_2_WORD_TYPE(md->returntype.type))
3205 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3207 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3212 #if defined(ENABLE_GC_CACAO)
3213 /* Restore callee saved integer registers from stackframeinfo (GC
3214 might have modified them during a collection). */
3216 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3217 OFFSET(stackframeinfo_t, intregs) + BIAS;
3219 for (i = 0; i < INT_SAV_CNT; i++)
3220 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3224 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3231 /* codegen_emit_stub_native ****************************************************
3233 Emits a stub routine which calls a native method.
3235 *******************************************************************************/
3237 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3244 s4 i, j; /* count variables */
3247 s4 funcdisp; /* displacement of the function */
3248 s4 fltregarg_offset[FLT_ARG_CNT];
3250 /* get required compiler data */
3256 /* initialize variables */
3259 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3261 /* calculate stack frame size */
3263 cd->stackframesize =
3264 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3265 sizeof(localref_table) / SIZEOF_VOID_P +
3266 md->paramcount + /* for saving arguments over calls */
3267 nmd->memuse + /* nmd->memuse includes the (6) abi params */
3271 /* keep stack 16-byte aligned (ABI requirement) */
3273 if (cd->stackframesize & 1)
3274 cd->stackframesize++;
3276 /* create method header */
3278 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3279 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
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 */
3284 /* generate stub code */
3286 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3288 #if !defined(NDEBUG)
3289 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3290 emit_verbosecall_enter(jd);
3293 /* get function address (this must happen before the stackframeinfo) */
3295 funcdisp = dseg_add_functionptr(cd, f);
3298 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
3300 /* save float argument registers */
3302 assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
3304 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3305 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3306 s1 = WINSAVE_CNT + nmd->memuse + j;
3307 M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
3308 fltregarg_offset[i] = s1; /* remember stack offset */
3313 /* prepare data structures for native function call */
3315 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */
3316 M_MOV(REG_PV_CALLEE, REG_OUT1);
3317 M_MOV(REG_FP, REG_OUT2); /* java sp */
3318 M_MOV(REG_RA_CALLEE, REG_OUT3);
3319 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3320 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3321 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3322 M_NOP; /* XXX fill me! */
3324 /* remember class argument */
3326 if (m->flags & ACC_STATIC)
3327 M_MOV(REG_RESULT_CALLER, REG_ITMP3);
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 = 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;
3409 if (!nmd->params[j].inmemory) {
3411 /* JIT stack -> NAT reg */
3413 s2 = nmd->params[j].regoff;
3414 M_DLD(s2, REG_FP, JITSTACK + s1);
3418 /* JIT stack -> NAT stack */
3420 s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff;
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_FP, JITSTACK + s1);
3425 M_DST(REG_F0, REG_SP, BIAS + s2);
3432 /* put class into second argument register */
3434 if (m->flags & ACC_STATIC)
3435 M_MOV(REG_ITMP3, REG_OUT1);
3437 /* put env into first argument register */
3439 disp = dseg_add_address(cd, _Jv_env);
3440 M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
3442 /* do the native function call */
3444 M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method */
3445 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method */
3446 M_NOP; /* delay slot */
3448 /* save return value */
3450 if (md->returntype.type != TYPE_VOID) {
3451 if (IS_INT_LNG_TYPE(md->returntype.type))
3452 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3454 M_DST(REG_FRESULT, REG_SP, CSTACK);
3457 /* Note: native functions return float values in %f0 (see ABI) */
3458 /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
3460 #if !defined(NDEBUG)
3461 /* But for the trace function we need to put a flt result into %f1 */
3462 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3463 if (!IS_2_WORD_TYPE(md->returntype.type))
3464 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3465 emit_verbosecall_exit(jd);
3469 /* remove native stackframe info */
3471 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3472 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3473 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3474 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3475 M_NOP; /* XXX fill me! */
3476 M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
3478 /* restore float return value, int return value already in our return reg */
3480 if (md->returntype.type != TYPE_VOID) {
3481 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3482 if (IS_2_WORD_TYPE(md->returntype.type))
3483 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3485 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3489 /* check for exception */
3490 M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
3493 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3496 /* handle exception */
3498 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3499 M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */
3500 M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */
3501 M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */
3502 M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
3504 /* generate patcher stubs */
3506 emit_patcher_stubs(jd);
3510 * These are local overrides for various environment variables in Emacs.
3511 * Please do not remove this and leave it at the end of the file, where
3512 * Emacs will automagically detect them.
3513 * ---------------------------------------------------------------------
3516 * indent-tabs-mode: t
3520 * vim:noexpandtab:sw=4:ts=4: