1 /* src/vm/jit/sparc64/codegen.c - machine code generator for Sparc
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
36 /* #include "vm/jit/sparc64/arch.h" */
37 #include "vm/jit/sparc64/codegen.h"
38 #include "vm/jit/sparc64/emit.h"
40 #include "mm/memory.h"
42 #include "native/jni.h"
43 #include "native/localref.h"
44 #include "native/native.h"
45 #include "vm/builtin.h"
46 #include "vm/exceptions.h"
47 #include "vm/global.h"
49 #include "vm/jit/abi.h"
50 #include "vm/jit/asmpart.h"
51 #include "vm/jit/codegen-common.h"
52 #include "vm/jit/dseg.h"
53 #include "vm/jit/emit-common.h"
54 #include "vm/jit/jit.h"
55 #include "vm/jit/linenumbertable.h"
56 #include "vm/jit/parse.h"
57 #include "vm/jit/patcher.h"
58 #include "vm/jit/reg.h"
59 #include "vm/jit/replace.h"
60 #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;
134 constant_classref *cr;
135 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
136 unresolved_method *um;
137 builtintable_entry *bte;
140 unresolved_field *uf;
144 /* get required compiler data */
151 /* prevent compiler warnings */
163 #if 0 /* no leaf optimization yet */
164 savedregs_num = (code_is_leafmethod(code)) ? 0 : 1; /* space to save the RA */
166 savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */
169 /* space to save used callee saved registers */
171 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
172 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
174 cd->stackframesize = rd->memuse + savedregs_num;
176 #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
177 if (checksync && code_is_synchronized(code))
178 cd->stackframesize++;
181 /* keep stack 16-byte aligned (ABI requirement) */
183 if (cd->stackframesize & 1)
184 cd->stackframesize++;
186 /* create method header */
188 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
189 framesize_disp = dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
191 code->synchronizedoffset = JITSTACK + rd->memuse * 8;
193 /* REMOVEME: We still need it for exception handling in assembler. */
195 if (code_is_leafmethod(code))
196 (void) dseg_add_unique_s4(cd, 1);
198 (void) dseg_add_unique_s4(cd, 0);
200 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
201 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
203 /* save register window and create stack frame (if necessary) */
205 if (cd->stackframesize) {
206 if (cd->stackframesize <= 4095)
207 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
209 M_ILD_INTERN(REG_ITMP3, REG_PV_CALLER, framesize_disp);
210 M_SUB(REG_ZERO, REG_ITMP3, REG_ITMP3);
211 M_SAVE_REG(REG_SP, REG_ITMP3, REG_SP);
215 /* save callee saved float registers (none right now) */
217 p = cd->stackframesize;
218 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
219 p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
224 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
225 emit_verbosecall_enter(jd);
229 /* call monitorenter function */
230 #if defined(ENABLE_THREADS)
231 if (checksync && code_is_synchronized(code)) {
232 /* stack offset for monitor argument */
236 /* save float argument registers */
240 ALIGN_STACK_SLOTS(slots);
242 M_LDA(REG_SP, REG_SP, -(slots * 8));
243 for (i = 0; i < FLT_ARG_CNT; i++)
244 M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
248 /* get correct lock object */
250 if (m->flags & ACC_STATIC) {
251 disp = dseg_add_address(cd, &m->clazz->object.header);
252 M_ALD(REG_OUT0, REG_PV, disp);
253 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
254 M_ALD(REG_ITMP3, REG_PV, disp);
257 /* copy class pointer: $i0 -> $o0 */
258 M_MOV(REG_RESULT_CALLEE, REG_OUT0);
260 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
261 M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
262 M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
265 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
266 M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */
268 /* restore float argument registers */
270 for (i = 0; i < FLT_ARG_CNT; i++)
271 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
273 M_LDA(REG_SP, REG_SP, slots * 8);
278 /* take arguments out of register or stack frame */
282 for (p = 0, l = 0; p < md->paramcount; p++) {
283 t = md->paramtypes[p].type;
285 varindex = jd->local_map[l * 5 + t];
288 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
291 if (varindex == UNUSED)
295 s1 = md->params[p].regoff;
297 if (IS_INT_LNG_TYPE(t)) { /* integer args */
301 if (!md->params[p].inmemory) { /* register arguments */
302 s1 = REG_WINDOW_TRANSPOSE(s1);
304 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
306 /* the register allocator does not know about the window. */
307 /* avoid copying the locals from save to save regs by */
308 /* swapping variables. */
311 int old_dest = var->vv.regoff;
312 int new_dest = p + 24;
314 /* run through all variables */
316 for (i = 0; i < jd->varcount; i++) {
317 varinfo* uvar = VAR(i);
319 if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags))
322 s2 = uvar->vv.regoff;
324 /* free the in reg by moving all other references */
326 if (s2 == new_dest) {
327 uvar->vv.regoff = old_dest;
328 /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
331 /* move all variables to the in reg */
333 if (s2 == old_dest) {
334 uvar->vv.regoff = new_dest;
335 /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
343 else { /* reg arg -> spilled */
344 M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
347 } else { /* stack arguments */
348 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
349 M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1);
351 } else { /* stack arg -> spilled */
352 /* add the callers window save registers */
353 var->vv.regoff = cd->stackframesize * 8 + s1;
357 } else { /* floating args */
358 if (!md->params[p].inmemory) { /* register arguments */
359 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
360 M_FLTMOVE(s1, var->vv.regoff);
362 } else { /* reg arg -> spilled */
363 M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
366 } else { /* stack arguments */
367 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
368 M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1);
370 } else { /* stack-arg -> spilled */
371 var->vv.regoff = cd->stackframesize * 8 + s1;
380 /* end of header generation */
382 /* create replacement points */
384 REPLACEMENT_POINTS_INIT(cd, jd);
386 /* walk through all basic blocks */
388 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
390 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
392 if (bptr->flags >= BBREACHED) {
394 /* branch resolving */
396 codegen_resolve_branchrefs(cd, bptr);
398 /* handle replacement points */
400 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
403 /* copy interface registers to their destination */
408 #if defined(ENABLE_LSRA)
409 #error XXX LSRA not tested yet
413 src = bptr->invars[len];
414 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
415 /* d = reg_of_var(m, src, REG_ITMP1); */
416 if (!(src->flags & INMEMORY))
420 M_INTMOVE(REG_ITMP1, d);
421 emit_store(jd, NULL, src, d);
428 var = VAR(bptr->invars[len]);
429 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
430 d = codegen_reg_of_var(0, var, REG_ITMP1);
431 M_INTMOVE(REG_ITMP2_XPTR, d);
432 emit_store(jd, NULL, var, d);
435 assert((var->flags & INOUT));
438 #if defined(ENABLE_LSRA)
441 /* walk through all instructions */
445 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
446 if (iptr->line != currentline) {
447 linenumbertable_list_entry_add(cd, iptr->line);
448 currentline = iptr->line;
451 MCODECHECK(64); /* an instruction usually needs < 64 words */
455 case ICMD_INLINE_START:
456 case ICMD_INLINE_END:
459 case ICMD_NOP: /* ... ==> ... */
462 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
464 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
465 emit_nullpointer_check(cd, iptr, s1);
468 /* constant operations ************************************************/
470 case ICMD_ICONST: /* ... ==> ..., constant */
472 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
473 ICONST(d, iptr->sx.val.i);
474 emit_store_dst(jd, iptr, d);
477 case ICMD_LCONST: /* ... ==> ..., constant */
479 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
480 LCONST(d, iptr->sx.val.l);
481 emit_store_dst(jd, iptr, d);
484 case ICMD_FCONST: /* ... ==> ..., constant */
486 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
487 disp = dseg_add_float(cd, iptr->sx.val.f);
488 M_FLD(d, REG_PV, disp);
489 emit_store_dst(jd, iptr, d);
492 case ICMD_DCONST: /* ... ==> ..., constant */
494 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
495 disp = dseg_add_double(cd, iptr->sx.val.d);
496 M_DLD(d, REG_PV, disp);
497 emit_store_dst(jd, iptr, d);
500 case ICMD_ACONST: /* ... ==> ..., constant */
502 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
504 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
505 cr = iptr->sx.val.c.ref;
506 disp = dseg_add_unique_address(cd, cr);
508 codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
510 M_ALD(d, REG_PV, disp);
514 if (iptr->sx.val.anyptr == NULL) {
515 M_INTMOVE(REG_ZERO, d);
518 disp = dseg_add_address(cd, iptr->sx.val.anyptr);
519 M_ALD(d, REG_PV, disp);
522 emit_store_dst(jd, iptr, d);
526 /* load/store/copy/move operations ************************************/
528 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
533 case ICMD_ISTORE: /* ..., value ==> ... */
544 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
549 /* pop/dup/swap operations ********************************************/
551 /* attention: double and longs are only one entry in CACAO ICMDs */
553 case ICMD_POP: /* ..., value ==> ... */
554 case ICMD_POP2: /* ..., value, value ==> ... */
558 /* integer operations *************************************************/
560 case ICMD_INEG: /* ..., value ==> ..., - value */
563 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
564 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
565 M_SUB(REG_ZERO, s1, d);
566 emit_store_dst(jd, iptr, d);
569 case ICMD_I2L: /* ..., value ==> ..., value */
571 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
572 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
574 emit_store_dst(jd, iptr, d);
577 case ICMD_L2I: /* ..., value ==> ..., value */
579 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
580 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
581 M_SRA_IMM(s1, 0, d); /* sign extend upper 32 bits */
582 emit_store_dst(jd, iptr, d);
585 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
587 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
588 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
589 M_SLLX_IMM(s1, 56, d);
590 M_SRAX_IMM( d, 56, d);
591 emit_store_dst(jd, iptr, d);
594 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
596 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
597 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
598 M_SLLX_IMM(s1, 48, d);
599 M_SRLX_IMM( d, 48, d);
600 emit_store_dst(jd, iptr, d);
603 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
605 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
606 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
607 M_SLLX_IMM(s1, 48, d);
608 M_SRAX_IMM( d, 48, d);
609 emit_store_dst(jd, iptr, d);
612 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
615 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
616 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
617 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
619 emit_store_dst(jd, iptr, d);
623 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
624 /* sx.val.i = constant */
626 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
627 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
628 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
629 M_ADD_IMM(s1, iptr->sx.val.i, d);
631 ICONST(REG_ITMP2, iptr->sx.val.i);
632 M_ADD(s1, REG_ITMP2, d);
634 emit_store_dst(jd, iptr, d);
637 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
638 /* sx.val.l = constant */
640 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
641 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
642 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
643 M_ADD_IMM(s1, iptr->sx.val.l, d);
645 LCONST(REG_ITMP2, iptr->sx.val.l);
646 M_ADD(s1, REG_ITMP2, d);
648 emit_store_dst(jd, iptr, d);
651 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
654 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
655 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
656 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
658 emit_store_dst(jd, iptr, d);
661 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
662 /* sx.val.i = constant */
664 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
665 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
666 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
667 M_SUB_IMM(s1, iptr->sx.val.i, d);
669 ICONST(REG_ITMP2, iptr->sx.val.i);
670 M_SUB(s1, REG_ITMP2, d);
672 emit_store_dst(jd, iptr, d);
675 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
676 /* sx.val.l = constant */
678 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
679 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
680 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
681 M_SUB_IMM(s1, iptr->sx.val.l, d);
683 LCONST(REG_ITMP2, iptr->sx.val.l);
684 M_SUB(s1, REG_ITMP2, d);
686 emit_store_dst(jd, iptr, d);
689 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
692 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
693 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
694 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
696 emit_store_dst(jd, iptr, d);
699 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
700 /* sx.val.i = constant */
702 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
703 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
704 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
705 M_MULX_IMM(s1, iptr->sx.val.i, d);
707 ICONST(REG_ITMP2, iptr->sx.val.i);
708 M_MULX(s1, REG_ITMP2, d);
710 emit_store_dst(jd, iptr, d);
713 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
714 /* sx.val.l = constant */
716 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
717 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
718 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
719 M_MULX_IMM(s1, iptr->sx.val.l, d);
721 LCONST(REG_ITMP2, iptr->sx.val.l);
722 M_MULX(s1, REG_ITMP2, d);
724 emit_store_dst(jd, iptr, d);
727 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
728 /* XXX could also clear Y and use 32bit div */
729 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
730 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
731 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
732 emit_arithmetic_check(cd, iptr, s2);
734 /* XXX trim s2 like s1 ? */
736 emit_store_dst(jd, iptr, d);
739 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
741 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
742 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
743 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
744 emit_arithmetic_check(cd, iptr, s2);
746 emit_store_dst(jd, iptr, d);
749 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
751 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
752 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
753 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
754 emit_arithmetic_check(cd, iptr, s2);
756 /* XXX trim s2 like s1 ? */
757 M_DIVX(s1, s2, REG_ITMP3);
758 M_MULX(s2, REG_ITMP3, REG_ITMP3);
759 M_SUB(s1, REG_ITMP3, d);
760 emit_store_dst(jd, iptr, d);
763 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
765 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
766 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
767 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
768 emit_arithmetic_check(cd, iptr, s2);
769 M_DIVX(s1, s2, REG_ITMP3);
770 M_MULX(s2, REG_ITMP3, REG_ITMP3);
771 M_SUB(s1, REG_ITMP3, d);
772 emit_store_dst(jd, iptr, d);
775 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
776 case ICMD_LDIVPOW2: /* val.i = constant */
778 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
779 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
780 M_SRAX_IMM(s1, 63, REG_ITMP2);
781 M_SRLX_IMM(REG_ITMP2, 64 - iptr->sx.val.i, REG_ITMP2);
782 M_ADD(s1, REG_ITMP2, REG_ITMP2);
783 M_SRAX_IMM(REG_ITMP2, iptr->sx.val.i, d);
784 emit_store_dst(jd, iptr, d);
787 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
789 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
790 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
791 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
793 emit_store_dst(jd, iptr, d);
796 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
798 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
799 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
800 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
802 emit_store_dst(jd, iptr, d);
805 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
806 /* val.i = constant */
808 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
809 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
810 M_SLL_IMM(s1, iptr->sx.val.i, d);
811 emit_store_dst(jd, iptr, d);
814 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
815 /* val.i = constant */
817 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
818 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
819 M_SLLX_IMM(s1, iptr->sx.val.i, d);
820 emit_store_dst(jd, iptr, d);
823 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
825 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
826 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
827 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
829 emit_store_dst(jd, iptr, d);
832 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
833 /* sx.val.i = constant */
835 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
836 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
837 M_SRA_IMM(s1, iptr->sx.val.i, d);
838 emit_store_dst(jd, iptr, d);
841 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
843 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
844 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
845 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
847 emit_store_dst(jd, iptr, d);
850 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
851 /* sx.val.i = constant */
853 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
854 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
855 M_SRL_IMM(s1, iptr->sx.val.i, d);
856 emit_store_dst(jd, iptr, d);
859 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
861 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
862 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
863 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
865 emit_store_dst(jd, iptr, d);
868 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
869 /* sx.val.i = constant */
871 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
872 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
873 M_SRAX_IMM(s1, iptr->sx.val.i, d);
874 emit_store_dst(jd, iptr, d);
877 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
879 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
880 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
881 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
883 emit_store_dst(jd, iptr, d);
886 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
887 /* sx.val.i = constant */
889 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
890 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
891 M_SRLX_IMM(s1, iptr->sx.val.i, d);
892 emit_store_dst(jd, iptr, d);
895 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
898 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
899 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
900 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
902 emit_store_dst(jd, iptr, d);
905 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
906 /* sx.val.i = constant */
908 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
909 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
910 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
911 M_AND_IMM(s1, iptr->sx.val.i, d);
913 ICONST(REG_ITMP2, iptr->sx.val.i);
914 M_AND(s1, REG_ITMP2, d);
916 emit_store_dst(jd, iptr, d);
919 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
920 /* sx.val.i = constant */
921 /* constant is actually constant - 1 */
923 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
924 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
926 M_MOV(s1, REG_ITMP1);
929 M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
930 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
931 M_AND_IMM(s1, iptr->sx.val.i, d);
934 M_SUB(REG_ZERO, s1, d);
935 M_AND_IMM(d, iptr->sx.val.i, d);
937 ICONST(REG_ITMP2, iptr->sx.val.i);
938 M_AND(s1, REG_ITMP2, d);
941 M_SUB(REG_ZERO, s1, d);
942 M_AND(d, REG_ITMP2, d);
944 M_SUB(REG_ZERO, d, d);
945 emit_store_dst(jd, iptr, d);
948 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
949 /* sx.val.l = constant */
951 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
952 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
953 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
954 M_AND_IMM(s1, iptr->sx.val.l, d);
956 LCONST(REG_ITMP2, iptr->sx.val.l);
957 M_AND(s1, REG_ITMP2, d);
959 emit_store_dst(jd, iptr, d);
962 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
963 /* sx.val.l = constant */
965 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
966 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
968 M_MOV(s1, REG_ITMP1);
971 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
972 M_AND_IMM(s1, iptr->sx.val.l, d);
975 M_SUB(REG_ZERO, s1, d);
976 M_AND_IMM(d, iptr->sx.val.l, d);
978 LCONST(REG_ITMP2, iptr->sx.val.l);
979 M_AND(s1, REG_ITMP2, d);
982 M_SUB(REG_ZERO, s1, d);
983 M_AND(d, REG_ITMP2, d);
985 M_SUB(REG_ZERO, d, d);
986 emit_store_dst(jd, iptr, d);
989 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
992 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
993 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
994 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
996 emit_store_dst(jd, iptr, d);
999 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1000 /* sx.val.i = constant */
1002 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1003 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1004 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1005 M_OR_IMM(s1, iptr->sx.val.i, d);
1007 ICONST(REG_ITMP2, iptr->sx.val.i);
1008 M_OR(s1, REG_ITMP2, d);
1010 emit_store_dst(jd, iptr, d);
1013 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1014 /* sx.val.l = constant */
1016 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1017 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1018 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1019 M_OR_IMM(s1, iptr->sx.val.l, d);
1021 LCONST(REG_ITMP2, iptr->sx.val.l);
1022 M_OR(s1, REG_ITMP2, d);
1024 emit_store_dst(jd, iptr, d);
1027 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1030 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1031 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1032 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1034 emit_store_dst(jd, iptr, d);
1037 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1038 /* sx.val.i = constant */
1040 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1041 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1042 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1043 M_XOR_IMM(s1, iptr->sx.val.i, d);
1045 ICONST(REG_ITMP2, iptr->sx.val.i);
1046 M_XOR(s1, REG_ITMP2, d);
1048 emit_store_dst(jd, iptr, d);
1051 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1052 /* sx.val.l = constant */
1054 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1055 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1056 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1057 M_XOR_IMM(s1, iptr->sx.val.l, d);
1059 LCONST(REG_ITMP2, iptr->sx.val.l);
1060 M_XOR(s1, REG_ITMP2, d);
1062 emit_store_dst(jd, iptr, d);
1066 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1068 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1069 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1070 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1073 M_XCMOVLT_IMM(-1, d);
1074 M_XCMOVGT_IMM(1, d);
1075 emit_store_dst(jd, iptr, d);
1079 /* floating operations ************************************************/
1081 case ICMD_FNEG: /* ..., value ==> ..., - value */
1083 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1084 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1086 emit_store_dst(jd, iptr, d);
1089 case ICMD_DNEG: /* ..., value ==> ..., - value */
1091 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1092 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1094 emit_store_dst(jd, iptr, d);
1097 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1099 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1100 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1101 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1103 emit_store_dst(jd, iptr, d);
1106 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1108 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1109 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1110 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1112 emit_store_dst(jd, iptr, d);
1115 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1117 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1118 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1119 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1121 emit_store_dst(jd, iptr, d);
1124 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1126 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1127 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1128 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1130 emit_store_dst(jd, iptr, d);
1133 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1135 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1136 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1137 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1139 emit_store_dst(jd, iptr, d);
1142 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1144 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1145 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1146 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1148 emit_store_dst(jd, iptr, d);
1151 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1153 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1154 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1155 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1157 emit_store_dst(jd, iptr, d);
1160 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1162 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1163 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1164 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1166 emit_store_dst(jd, iptr, d);
1170 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1171 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1172 disp = dseg_add_unique_float(cd, 0.0);
1173 M_IST (s1, REG_PV_CALLEE, disp);
1174 M_FLD (d, REG_PV_CALLEE, disp);
1175 M_CVTIF (d, d); /* rd gets translated to double target register */
1176 emit_store_dst(jd, iptr, d);
1180 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1181 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1182 disp = dseg_add_unique_float(cd, 0.0);
1183 M_IST(s1, REG_PV_CALLEE, disp);
1184 M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
1185 M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
1186 emit_store_dst(jd, iptr, d);
1190 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1191 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1192 disp = dseg_add_unique_double(cd, 0.0);
1193 M_STX(s1, REG_PV_CALLEE, disp);
1194 M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
1195 M_CVTLF(REG_FTMP3, d);
1196 emit_store_dst(jd, iptr, d);
1200 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1201 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1202 disp = dseg_add_unique_double(cd, 0.0);
1203 M_STX(s1, REG_PV_CALLEE, disp);
1204 M_DLD(d, REG_PV_CALLEE, disp);
1206 emit_store_dst(jd, iptr, d);
1209 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1210 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1211 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1212 disp = dseg_add_unique_float(cd, 0.0);
1214 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1217 M_MOV(REG_ZERO, d); /* delay slot */
1219 M_CVTFI(s1, REG_FTMP2);
1220 M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
1221 M_ILD(d, REG_PV, disp);
1222 emit_store_dst(jd, iptr, d);
1226 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1227 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1228 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1229 disp = dseg_add_unique_float(cd, 0.0);
1231 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1234 M_MOV(REG_ZERO, d); /* delay slot */
1236 M_CVTDI(s1, REG_FTMP2);
1237 M_FST(REG_FTMP2, REG_PV, disp);
1238 M_ILD(d, REG_PV, disp);
1239 emit_store_dst(jd, iptr, d);
1242 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1243 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1244 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1245 disp = dseg_add_unique_double(cd, 0.0);
1247 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1250 M_MOV(REG_ZERO, d); /* delay slot */
1252 M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1253 M_DST(REG_FTMP2, REG_PV, disp);
1254 M_LDX(d, REG_PV, disp);
1255 emit_store_dst(jd, iptr, d);
1258 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1259 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1260 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1261 disp = dseg_add_unique_double(cd, 0.0);
1263 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1266 M_MOV(REG_ZERO, d); /* delay slot */
1268 M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1269 M_DST(REG_FTMP2, REG_PV, disp);
1270 M_LDX(d, REG_PV, disp);
1271 emit_store_dst(jd, iptr, d);
1274 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1276 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1277 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1279 emit_store_dst(jd, iptr, d);
1282 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1284 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1285 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1287 emit_store_dst(jd, iptr, d);
1290 /* XXX merge F/D versions? only compare instr. is different */
1291 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1293 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1294 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1295 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1297 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1298 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1299 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1300 emit_store_dst(jd, iptr, d);
1303 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1305 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1306 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1307 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1309 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1310 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1311 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1312 emit_store_dst(jd, iptr, d);
1315 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1317 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1318 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1319 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1321 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1322 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1323 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1324 emit_store_dst(jd, iptr, d);
1327 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1329 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1330 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1331 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1333 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1334 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1335 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1336 emit_store_dst(jd, iptr, d);
1340 /* memory operations **************************************************/
1342 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1344 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1345 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1346 emit_nullpointer_check(cd, iptr, s1);
1347 M_ILD(d, s1, OFFSET(java_array_t, size));
1348 emit_store_dst(jd, iptr, d);
1351 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1353 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1354 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1355 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1356 /* implicit null-pointer check */
1357 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1358 M_AADD(s2, s1, REG_ITMP3);
1359 M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray_t, data[0]));
1360 emit_store_dst(jd, iptr, d);
1363 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1365 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1366 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1367 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1368 /* implicit null-pointer check */
1369 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1370 M_AADD(s2, s1, REG_ITMP3);
1371 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1372 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray_t, data[0]));
1373 emit_store_dst(jd, iptr, d);
1376 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1378 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1379 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1380 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1381 /* implicit null-pointer check */
1382 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1383 M_AADD(s2, s1, REG_ITMP3);
1384 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1385 M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray_t, data[0]));
1386 emit_store_dst(jd, iptr, d);
1389 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1391 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1392 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1393 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1394 /* implicit null-pointer check */
1395 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1396 M_ASLL_IMM(s2, 2, REG_ITMP3);
1397 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1398 M_ILD(d, REG_ITMP3, OFFSET(java_intarray_t, data[0]));
1399 emit_store_dst(jd, iptr, d);
1402 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1404 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1405 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1406 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1407 /* implicit null-pointer check */
1408 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1409 M_ASLL_IMM(s2, 3, REG_ITMP3);
1410 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1411 M_LDX(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1412 emit_store_dst(jd, iptr, d);
1415 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1417 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1418 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1419 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1420 /* implicit null-pointer check */
1421 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1422 M_ASLL_IMM(s2, 2, REG_ITMP3);
1423 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1424 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray_t, data[0]));
1425 emit_store_dst(jd, iptr, d);
1428 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1430 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1431 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1432 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1433 /* implicit null-pointer check */
1434 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1435 M_ASLL_IMM(s2, 3, REG_ITMP3);
1436 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1437 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1438 emit_store_dst(jd, iptr, d);
1441 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1443 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1444 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1445 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1446 /* implicit null-pointer check */
1447 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1448 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1449 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1450 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray_t, data[0]));
1451 emit_store_dst(jd, iptr, d);
1455 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1457 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1458 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1459 /* implicit null-pointer check */
1460 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1461 M_AADD(s2, s1, REG_ITMP1);
1462 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1463 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1466 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1467 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1469 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1470 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1471 /* implicit null-pointer check */
1472 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1473 M_AADD(s2, s1, REG_ITMP1);
1474 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1475 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1476 M_SST(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1479 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1481 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1482 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1483 /* implicit null-pointer check */
1484 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1485 M_ASLL_IMM(s2, 2, REG_ITMP2);
1486 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1487 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1488 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1491 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1493 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1494 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1495 /* implicit null-pointer check */
1496 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1497 M_ASLL_IMM(s2, 3, REG_ITMP2);
1498 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1499 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1500 M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1503 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1505 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1506 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1507 /* implicit null-pointer check */
1508 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1509 M_ASLL_IMM(s2, 2, REG_ITMP2);
1510 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1511 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1512 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1515 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1517 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1518 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1519 /* implicit null-pointer check */
1520 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1521 M_ASLL_IMM(s2, 3, REG_ITMP2);
1522 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1523 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1524 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1528 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1530 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1531 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1532 /* implicit null-pointer check */
1533 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1534 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1536 M_MOV(s1, REG_OUT0);
1537 M_MOV(s3, REG_OUT1);
1538 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1539 M_ALD(REG_ITMP3, REG_PV, disp);
1540 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
1542 emit_arraystore_check(cd, iptr);
1544 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1545 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1546 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1547 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1548 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1549 /* implicit null-pointer check */
1550 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1554 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1556 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1557 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1558 /* implicit null-pointer check */
1559 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1560 M_AADD(s2, s1, REG_ITMP1);
1561 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1564 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1565 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1567 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1568 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1569 /* implicit null-pointer check */
1570 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1571 M_AADD(s2, s1, REG_ITMP1);
1572 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1573 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1576 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1578 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1579 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1580 /* implicit null-pointer check */
1581 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1582 M_ASLL_IMM(s2, 2, REG_ITMP2);
1583 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1584 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1587 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1589 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1590 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1591 /* implicit null-pointer check */
1592 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1593 M_ASLL_IMM(s2, 3, REG_ITMP2);
1594 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1595 M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1598 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1600 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1601 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1602 /* implicit null-pointer check */
1603 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1604 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1605 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1606 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1610 case ICMD_GETSTATIC: /* ... ==> ..., value */
1612 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1613 uf = iptr->sx.s23.s3.uf;
1614 fieldtype = uf->fieldref->parseddesc.fd->type;
1615 disp = dseg_add_unique_address(cd, uf);
1617 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1620 fi = iptr->sx.s23.s3.fmiref->p.field;
1621 fieldtype = fi->type;
1622 disp = dseg_add_address(cd, fi->value);
1624 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1625 codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
1628 M_ALD(REG_ITMP1, REG_PV, disp);
1630 switch (fieldtype) {
1632 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1633 M_ILD_INTERN(d, REG_ITMP1, 0);
1636 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1637 M_LDX_INTERN(d, REG_ITMP1, 0);
1640 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1641 M_ALD_INTERN(d, REG_ITMP1, 0);
1644 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1645 M_FLD_INTERN(d, REG_ITMP1, 0);
1648 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1649 M_DLD_INTERN(d, REG_ITMP1, 0);
1652 emit_store_dst(jd, iptr, d);
1655 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1657 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1658 uf = iptr->sx.s23.s3.uf;
1659 fieldtype = uf->fieldref->parseddesc.fd->type;
1660 disp = dseg_add_unique_address(cd, uf);
1662 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1665 fi = iptr->sx.s23.s3.fmiref->p.field;
1666 fieldtype = fi->type;
1667 disp = dseg_add_address(cd, fi->value);
1669 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1670 codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
1673 M_ALD(REG_ITMP1, REG_PV, disp);
1675 switch (fieldtype) {
1677 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1678 M_IST_INTERN(s1, REG_ITMP1, 0);
1681 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1682 M_STX_INTERN(s1, REG_ITMP1, 0);
1685 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1686 M_AST_INTERN(s1, REG_ITMP1, 0);
1689 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1690 M_FST_INTERN(s1, REG_ITMP1, 0);
1693 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1694 M_DST_INTERN(s1, REG_ITMP1, 0);
1699 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1700 /* val = value (in current instruction) */
1701 /* following NOP) */
1703 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1704 uf = iptr->sx.s23.s3.uf;
1705 fieldtype = uf->fieldref->parseddesc.fd->type;
1706 disp = dseg_add_unique_address(cd, uf);
1708 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1711 fi = iptr->sx.s23.s3.fmiref->p.field;
1712 fieldtype = fi->type;
1713 disp = dseg_add_address(cd, fi->value);
1715 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1716 codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
1719 M_ALD(REG_ITMP1, REG_PV, disp);
1721 switch (fieldtype) {
1723 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1726 M_STX_INTERN(REG_ZERO, REG_ITMP1, 0);
1729 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1732 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1735 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1741 case ICMD_GETFIELD: /* ... ==> ..., value */
1743 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1744 emit_nullpointer_check(cd, iptr, s1);
1746 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1747 uf = iptr->sx.s23.s3.uf;
1749 fieldtype = uf->fieldref->parseddesc.fd->type;
1752 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1755 fi = iptr->sx.s23.s3.fmiref->p.field;
1756 fieldtype = fi->type;
1760 switch (fieldtype) {
1762 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1766 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1770 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1774 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1778 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1785 emit_store_dst(jd, iptr, d);
1788 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1790 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1791 emit_nullpointer_check(cd, iptr, s1);
1793 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1794 uf = iptr->sx.s23.s3.uf;
1795 fieldtype = uf->fieldref->parseddesc.fd->type;
1800 fi = iptr->sx.s23.s3.fmiref->p.field;
1801 fieldtype = fi->type;
1805 if (IS_INT_LNG_TYPE(fieldtype))
1806 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1808 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1810 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1811 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1813 switch (fieldtype) {
1815 M_IST(s2, s1, disp);
1818 M_STX(s2, s1, disp);
1821 M_AST(s2, s1, disp);
1824 M_FST(s2, s1, disp);
1827 M_DST(s2, s1, disp);
1835 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
1836 /* val = value (in current instruction) */
1837 /* following NOP) */
1839 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1840 emit_nullpointer_check(cd, iptr, s1);
1842 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1843 unresolved_field *uf = iptr->sx.s23.s3.uf;
1845 fieldtype = uf->fieldref->parseddesc.fd->type;
1847 codegen_addpatchref(cd, PATCHER_get_putfield,
1850 if (opt_showdisassemble) {
1858 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1860 fieldtype = fi->type;
1866 switch (fieldtype) {
1868 M_IST(REG_ZERO, s1, disp);
1871 M_STX(REG_ZERO, s1, disp);
1874 M_AST(REG_ZERO, s1, disp);
1877 M_FST(REG_ZERO, s1, disp);
1880 M_DST(REG_ZERO, s1, disp);
1886 /* branch operations **************************************************/
1888 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1890 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1891 M_INTMOVE(s1, REG_ITMP2_XPTR);
1893 #ifdef ENABLE_VERIFIER
1894 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1895 unresolved_class *uc = iptr->sx.s23.s2.uc;
1897 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
1899 #endif /* ENABLE_VERIFIER */
1901 disp = dseg_add_functionptr(cd, asm_handle_exception);
1902 M_ALD(REG_ITMP1, REG_PV, disp);
1903 M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
1905 M_NOP; /* nop ensures that XPC is less than the end */
1906 /* of basic block */
1910 case ICMD_GOTO: /* ... ==> ... */
1911 case ICMD_RET: /* ... ==> ... */
1913 emit_br(cd, iptr->dst.block);
1917 case ICMD_JSR: /* ... ==> ... */
1919 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1923 case ICMD_IFNULL: /* ..., value ==> ... */
1924 case ICMD_IFNONNULL:
1926 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1927 emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
1930 /* Note: int compares must not branch on the register directly. */
1931 /* Reason is, that register content is not 32-bit clean. */
1933 case ICMD_IFEQ: /* ..., value ==> ... */
1935 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1937 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1938 M_CMP_IMM(s1, iptr->sx.val.i);
1941 ICONST(REG_ITMP2, iptr->sx.val.i);
1942 M_CMP(s1, REG_ITMP2);
1944 emit_beq(cd, iptr->dst.block);
1947 case ICMD_IFLT: /* ..., value ==> ... */
1949 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1951 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1952 M_CMP_IMM(s1, iptr->sx.val.i);
1955 ICONST(REG_ITMP2, iptr->sx.val.i);
1956 M_CMP(s1, REG_ITMP2);
1958 emit_blt(cd, iptr->dst.block);
1961 case ICMD_IFLE: /* ..., value ==> ... */
1963 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1965 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1966 M_CMP_IMM(s1, iptr->sx.val.i);
1969 ICONST(REG_ITMP2, iptr->sx.val.i);
1970 M_CMP(s1, REG_ITMP2);
1972 emit_ble(cd, iptr->dst.block);
1975 case ICMD_IFNE: /* ..., value ==> ... */
1977 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1979 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1980 M_CMP_IMM(s1, iptr->sx.val.i);
1983 ICONST(REG_ITMP2, iptr->sx.val.i);
1984 M_CMP(s1, REG_ITMP2);
1986 emit_bne(cd, iptr->dst.block);
1989 case ICMD_IFGT: /* ..., value ==> ... */
1991 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1993 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1994 M_CMP_IMM(s1, iptr->sx.val.i);
1997 ICONST(REG_ITMP2, iptr->sx.val.i);
1998 M_CMP(s1, REG_ITMP2);
2000 emit_bgt(cd, iptr->dst.block);
2003 case ICMD_IFGE: /* ..., value ==> ... */
2005 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2007 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2008 M_CMP_IMM(s1, iptr->sx.val.i);
2011 ICONST(REG_ITMP2, iptr->sx.val.i);
2012 M_CMP(s1, REG_ITMP2);
2014 emit_bge(cd, iptr->dst.block);
2017 case ICMD_IF_LEQ: /* ..., value ==> ... */
2019 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2020 if (iptr->sx.val.l == 0)
2021 emit_beqz(cd, iptr->dst.block, s1);
2023 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2024 M_CMP_IMM(s1, iptr->sx.val.l);
2027 LCONST(REG_ITMP2, iptr->sx.val.l);
2028 M_CMP(s1, REG_ITMP2);
2030 emit_beq_xcc(cd, iptr->dst.block);
2034 case ICMD_IF_LLT: /* ..., value ==> ... */
2036 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2037 if (iptr->sx.val.l == 0)
2038 emit_bltz(cd, iptr->dst.block, s1);
2040 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2041 M_CMP_IMM(s1, iptr->sx.val.l);
2044 LCONST(REG_ITMP2, iptr->sx.val.l);
2045 M_CMP(s1, REG_ITMP2);
2047 emit_blt_xcc(cd, iptr->dst.block);
2051 case ICMD_IF_LLE: /* ..., value ==> ... */
2053 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2054 if (iptr->sx.val.l == 0)
2055 emit_blez(cd, iptr->dst.block, s1);
2057 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2058 M_CMP_IMM(s1, iptr->sx.val.l);
2061 LCONST(REG_ITMP2, iptr->sx.val.l);
2062 M_CMP(s1, REG_ITMP2);
2064 emit_ble_xcc(cd, iptr->dst.block);
2068 case ICMD_IF_LNE: /* ..., value ==> ... */
2070 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2071 if (iptr->sx.val.l == 0)
2072 emit_bnez(cd, iptr->dst.block, s1);
2074 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2075 M_CMP_IMM(s1, iptr->sx.val.l);
2078 LCONST(REG_ITMP2, iptr->sx.val.l);
2079 M_CMP(s1, REG_ITMP2);
2081 emit_bne_xcc(cd, iptr->dst.block);
2085 case ICMD_IF_LGT: /* ..., value ==> ... */
2087 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2088 if (iptr->sx.val.l == 0)
2089 emit_bgtz(cd, iptr->dst.block, s1);
2091 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2092 M_CMP_IMM(s1, iptr->sx.val.l);
2095 LCONST(REG_ITMP2, iptr->sx.val.l);
2096 M_CMP(s1, REG_ITMP2);
2098 emit_bgt_xcc(cd, iptr->dst.block);
2102 case ICMD_IF_LGE: /* ..., value ==> ... */
2104 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2105 if (iptr->sx.val.l == 0)
2106 emit_bgez(cd, iptr->dst.block, s1);
2108 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2109 M_CMP_IMM(s1, iptr->sx.val.l);
2112 LCONST(REG_ITMP2, iptr->sx.val.l);
2113 M_CMP(s1, REG_ITMP2);
2115 emit_bge_xcc(cd, iptr->dst.block);
2120 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2121 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2123 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2124 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2126 emit_beq_xcc(cd, iptr->dst.block);
2129 case ICMD_IF_ICMPEQ: /* 32-bit compare */
2131 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2132 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2134 emit_beq(cd, iptr->dst.block);
2137 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
2138 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2140 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2141 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2143 emit_bne_xcc(cd, iptr->dst.block);
2146 case ICMD_IF_ICMPNE: /* 32-bit compare */
2148 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2149 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2151 emit_bne(cd, iptr->dst.block);
2154 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2156 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2157 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2159 emit_blt_xcc(cd, iptr->dst.block);
2162 case ICMD_IF_ICMPLT: /* 32-bit compare */
2164 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2165 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2167 emit_blt(cd, iptr->dst.block);
2170 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2172 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2173 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2175 emit_bgt_xcc(cd, iptr->dst.block);
2178 case ICMD_IF_ICMPGT: /* 32-bit compare */
2180 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2181 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2183 emit_bgt(cd, iptr->dst.block);
2186 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2188 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2189 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2191 emit_ble_xcc(cd, iptr->dst.block);
2194 case ICMD_IF_ICMPLE: /* 32-bit compare */
2196 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2197 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2199 emit_ble(cd, iptr->dst.block);
2203 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2205 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2206 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2208 emit_bge_xcc(cd, iptr->dst.block);
2211 case ICMD_IF_ICMPGE: /* 32-bit compare */
2213 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2214 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2216 emit_bge(cd, iptr->dst.block);
2220 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2223 REPLACEMENT_POINT_RETURN(cd, iptr);
2225 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2226 M_INTMOVE(s1, REG_RESULT_CALLEE);
2227 goto nowperformreturn;
2229 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2231 REPLACEMENT_POINT_RETURN(cd, iptr);
2233 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2234 M_INTMOVE(s1, REG_RESULT_CALLEE);
2236 #ifdef ENABLE_VERIFIER
2237 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2238 unresolved_class *uc = iptr->sx.s23.s2.uc;
2240 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2242 #endif /* ENABLE_VERIFIER */
2243 goto nowperformreturn;
2245 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2248 REPLACEMENT_POINT_RETURN(cd, iptr);
2250 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2251 M_DBLMOVE(s1, REG_FRESULT);
2252 goto nowperformreturn;
2254 case ICMD_RETURN: /* ... ==> ... */
2256 REPLACEMENT_POINT_RETURN(cd, iptr);
2262 p = cd->stackframesize;
2264 #if !defined(NDEBUG)
2265 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2266 emit_verbosecall_exit(jd);
2269 #if defined(ENABLE_THREADS)
2270 if (checksync && code_is_synchronized(code)) {
2271 /* XXX jit-c-call */
2272 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2273 M_ALD(REG_ITMP3, REG_PV, disp);
2275 /* we need to save fp return value (int saved by window) */
2277 switch (iptr->opc) {
2280 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
2281 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2282 M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2284 /* restore the fp return value */
2286 M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
2292 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2293 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2304 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
2310 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2313 branch_target_t *table;
2315 table = iptr->dst.table;
2317 l = iptr->sx.s23.s2.tablelow;
2318 i = iptr->sx.s23.s3.tablehigh;
2320 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2322 M_INTMOVE(s1, REG_ITMP1);
2324 else if (-l >= 4096 && -l <= 4095) {
2325 M_ADD_IMM(s1, -l, REG_ITMP1);
2328 ICONST(REG_ITMP2, l);
2329 M_SUB(s1, REG_ITMP2, REG_ITMP1);
2332 i = i - l + 1; /* number of targets (>0) */
2338 M_CMP_IMM(REG_ITMP1, i - 1);
2341 ICONST(REG_ITMP2, i - 1);
2342 M_CMP(REG_ITMP1, REG_ITMP2);
2344 emit_bugt(cd, table[0].block); /* default target */
2346 /* build jump table top down and use address of lowest entry */
2351 dseg_add_target(cd, table->block);
2356 /* length of dataseg after last dseg_addtarget is used by load */
2358 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
2359 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2360 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2361 M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
2366 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2369 lookup_target_t *lookup;
2371 lookup = iptr->dst.lookup;
2373 i = iptr->sx.s23.s2.lookupcount;
2375 MCODECHECK((i<<2)+8);
2376 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2379 if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
2380 M_CMP_IMM(s1, lookup->value);
2382 ICONST(REG_ITMP2, lookup->value);
2383 M_CMP(s1, REG_ITMP2);
2385 emit_beq(cd, lookup->target.block);
2389 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2395 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
2397 REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
2399 bte = iptr->sx.s23.s3.bte;
2402 /* XXX: builtin calling with stack arguments not implemented */
2403 assert(md->paramcount <= 5 && md->argfltreguse <= 16);
2405 s3 = md->paramcount;
2407 MCODECHECK((s3 << 1) + 64);
2409 #ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
2411 /* copy float arguments according to ABI convention */
2413 int num_fltregargs = 0;
2414 int fltregarg_inswap[16];
2416 for (s3 = s3 - 1; s3 >= 0; s3--) {
2417 var = VAR(iptr->sx.s23.s2.args[s3]);
2419 if (IS_FLT_DBL_TYPE(var->type)) {
2420 if (!md->params[s3].inmemory) {
2421 s1 = s3; /*native flt args use argument index directly*/
2422 d = emit_load(jd, iptr, var, REG_FTMP1);
2425 fltregarg_inswap[num_fltregargs] = s1;
2427 /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
2436 /* move swapped float args to target regs */
2437 for (i = 0; i < num_fltregargs; i++) {
2438 s1 = fltregarg_inswap[i];
2439 M_DMOV(s1 + 16, s1);
2440 /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
2444 assert(md->argfltreguse == 0);
2449 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2450 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2451 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2452 case ICMD_INVOKEINTERFACE:
2454 REPLACEMENT_POINT_INVOKE(cd, iptr);
2456 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2458 um = iptr->sx.s23.s3.um;
2459 md = um->methodref->parseddesc.md;
2462 lm = iptr->sx.s23.s3.fmiref->p.method;
2464 md = lm->parseddesc;
2468 s3 = md->paramcount;
2470 MCODECHECK((s3 << 1) + 64);
2472 /* copy arguments to registers or stack location */
2474 for (s3 = s3 - 1; s3 >= 0; s3--) {
2475 var = VAR(iptr->sx.s23.s2.args[s3]);
2476 d = md->params[s3].regoff;
2478 if (var->flags & PREALLOC)
2481 if (IS_INT_LNG_TYPE(var->type)) {
2482 if (!md->params[s3].inmemory) {
2483 s1 = emit_load(jd, iptr, var, d);
2487 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2488 M_STX(s1, REG_SP, JITSTACK + d);
2492 #ifdef BUILTIN_FLOAT_ARGS
2493 if (iptr->opc == ICMD_BUILTIN)
2497 if (!md->params[s3].inmemory) {
2498 s1 = emit_load(jd, iptr, var, d);
2499 if (IS_2_WORD_TYPE(var->type))
2505 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2506 M_DST(s1, REG_SP, JITSTACK + d);
2511 switch (iptr->opc) {
2513 if (bte->stub == NULL) {
2514 disp = dseg_add_functionptr(cd, bte->fp);
2517 disp = dseg_add_functionptr(cd, bte->stub);
2520 M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
2522 /* XXX jit-c-call */
2523 /* generate the actual call */
2525 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2527 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2528 REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
2529 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2530 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2531 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2533 if (md->returntype.type == TYPE_FLT) {
2534 /* special handling for float return value in %f0 */
2539 case ICMD_INVOKESPECIAL:
2540 emit_nullpointer_check(cd, iptr, REG_OUT0);
2543 case ICMD_INVOKESTATIC:
2545 disp = dseg_add_unique_address(cd, NULL);
2547 codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
2551 disp = dseg_add_address(cd, lm->stubroutine);
2553 M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
2555 /* generate the actual call */
2557 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2559 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2560 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2561 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2562 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2565 case ICMD_INVOKEVIRTUAL:
2566 emit_nullpointer_check(cd, iptr, REG_OUT0);
2569 codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
2574 s1 = OFFSET(vftbl_t, table[0]) +
2575 sizeof(methodptr) * lm->vftblindex;
2577 /* implicit null-pointer check */
2578 M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
2579 M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
2581 /* generate the actual call */
2583 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2585 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2586 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2587 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2588 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2591 case ICMD_INVOKEINTERFACE:
2592 emit_nullpointer_check(cd, iptr, REG_OUT0);
2595 codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
2601 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2602 sizeof(methodptr*) * lm->clazz->index;
2604 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2607 /* implicit null-pointer check */
2608 M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
2609 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2610 M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
2612 /* generate the actual call */
2614 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2616 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2617 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2618 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2619 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2623 /* store return value */
2625 d = md->returntype.type;
2627 if (d != TYPE_VOID) {
2628 if (IS_INT_LNG_TYPE(d)) {
2629 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2630 M_INTMOVE(REG_RESULT_CALLER, s1);
2633 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2634 if (IS_2_WORD_TYPE(d)) {
2635 M_DBLMOVE(REG_FRESULT, s1);
2637 M_FLTMOVE(REG_FRESULT, s1);
2640 emit_store_dst(jd, iptr, s1);
2645 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2646 /* val.a: (classinfo*) superclass */
2648 /* superclass is an interface:
2650 * OK if ((sub == NULL) ||
2651 * (sub->vftbl->interfacetablelength > super->index) &&
2652 * (sub->vftbl->interfacetable[-super->index] != NULL));
2654 * superclass is a class:
2656 * OK if ((sub == NULL) || (0
2657 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2658 * super->vftbl->diffvall));
2661 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2665 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2670 super = iptr->sx.s23.s3.c.cls;
2671 superindex = super->index;
2674 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2675 CODEGEN_CRITICAL_SECTION_NEW;
2677 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2679 /* if class is not resolved, check which code to call */
2681 if (super == NULL) {
2682 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2684 cr = iptr->sx.s23.s3.c.ref;
2685 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2687 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2690 M_ILD(REG_ITMP2, REG_PV, disp);
2691 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2692 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
2695 /* interface checkcast code */
2697 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2698 if (super == NULL) {
2699 cr = iptr->sx.s23.s3.c.ref;
2701 codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
2705 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2708 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2709 M_ILD(REG_ITMP3, REG_ITMP2,
2710 OFFSET(vftbl_t, interfacetablelength));
2711 M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
2712 emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
2714 M_ALD(REG_ITMP3, REG_ITMP2,
2715 OFFSET(vftbl_t, interfacetable[0]) -
2716 superindex * sizeof(methodptr*));
2717 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
2720 emit_label_br(cd, BRANCH_LABEL_4);
2722 emit_label(cd, BRANCH_LABEL_3);
2725 /* class checkcast code */
2727 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2728 if (super == NULL) {
2729 emit_label(cd, BRANCH_LABEL_2);
2731 cr = iptr->sx.s23.s3.c.ref;
2732 disp = dseg_add_unique_address(cd, NULL);
2734 codegen_add_patch_ref(cd,
2735 PATCHER_checkcast_instanceof_class,
2739 disp = dseg_add_address(cd, super->vftbl);
2741 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2744 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2745 M_ALD(REG_ITMP3, REG_PV, disp);
2747 CODEGEN_CRITICAL_SECTION_START;
2749 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2750 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2751 M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2752 M_ALD(REG_ITMP3, REG_PV, disp);
2753 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2755 CODEGEN_CRITICAL_SECTION_END;
2758 M_CMP(REG_ITMP3, REG_ITMP2);
2759 emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
2762 emit_label(cd, BRANCH_LABEL_5);
2765 if (super == NULL) {
2766 emit_label(cd, BRANCH_LABEL_1);
2767 emit_label(cd, BRANCH_LABEL_4);
2770 d = codegen_reg_of_dst(jd, iptr, s1);
2773 /* array type cast-check */
2775 s1 = emit_load_s1(jd, iptr, REG_OUT0);
2776 M_INTMOVE(s1, REG_OUT0);
2778 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2780 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2781 cr = iptr->sx.s23.s3.c.ref;
2782 disp = dseg_add_unique_address(cd, NULL);
2784 codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
2788 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2790 M_ALD(REG_OUT1, REG_PV, disp);
2791 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2792 M_ALD(REG_ITMP3, REG_PV, disp);
2793 /* XXX jit-c-call */
2794 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2797 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2798 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
2800 d = codegen_reg_of_dst(jd, iptr, s1);
2804 emit_store_dst(jd, iptr, d);
2807 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2808 /* val.a: (classinfo*) superclass */
2810 /* superclass is an interface:
2812 * return (sub != NULL) &&
2813 * (sub->vftbl->interfacetablelength > super->index) &&
2814 * (sub->vftbl->interfacetable[-super->index] != NULL);
2816 * superclass is a class:
2818 * return ((sub != NULL) && (0
2819 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2820 * super->vftbl->diffvall));
2825 vftbl_t *supervftbl;
2828 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2834 super = iptr->sx.s23.s3.c.cls;
2835 superindex = super->index;
2836 supervftbl = super->vftbl;
2839 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2840 CODEGEN_CRITICAL_SECTION_NEW;
2842 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2843 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2845 M_MOV(s1, REG_ITMP1);
2851 /* if class is not resolved, check which code to call */
2853 if (super == NULL) {
2854 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2856 cr = iptr->sx.s23.s3.c.ref;
2857 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2859 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2862 M_ILD(REG_ITMP3, REG_PV, disp);
2863 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2864 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
2867 /* interface instanceof code */
2869 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2870 if (super == NULL) {
2871 cr = iptr->sx.s23.s3.c.ref;
2873 codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
2877 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2880 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2881 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2882 M_CMP_IMM(REG_ITMP3, superindex);
2885 M_ALD(REG_ITMP1, REG_ITMP1,
2886 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2887 superindex * sizeof(methodptr*)));
2888 M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
2891 emit_label_br(cd, BRANCH_LABEL_4);
2893 emit_label(cd, BRANCH_LABEL_3);
2896 /* class instanceof code */
2898 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2899 if (super == NULL) {
2900 emit_label(cd, BRANCH_LABEL_2);
2902 cr = iptr->sx.s23.s3.c.ref;
2903 disp = dseg_add_unique_address(cd, NULL);
2905 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
2909 disp = dseg_add_address(cd, supervftbl);
2911 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2914 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2915 M_ALD(REG_ITMP2, REG_PV, disp);
2917 CODEGEN_CRITICAL_SECTION_START;
2919 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2920 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2921 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2923 CODEGEN_CRITICAL_SECTION_END;
2925 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2926 M_CMP(REG_ITMP1, REG_ITMP2);
2927 M_XCMOVULE_IMM(1, d);
2930 emit_label(cd, BRANCH_LABEL_5);
2933 if (super == NULL) {
2934 emit_label(cd, BRANCH_LABEL_1);
2935 emit_label(cd, BRANCH_LABEL_4);
2938 emit_store_dst(jd, iptr, d);
2942 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2944 /* check for negative sizes and copy sizes to stack if necessary */
2946 MCODECHECK((iptr->s1.argcount << 1) + 64);
2948 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2950 var = VAR(iptr->sx.s23.s2.args[s1]);
2952 /* copy SAVEDVAR sizes to stack */
2954 /* Already Preallocated? */
2956 if (!(var->flags & PREALLOC)) {
2957 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2958 M_STX(s2, REG_SP, CSTACK + (s1 * 8));
2962 /* arg 0 = dimension count */
2964 ICONST(REG_OUT0, iptr->s1.argcount);
2966 /* is patcher function set? */
2968 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2969 disp = dseg_add_unique_address(cd, 0);
2971 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
2972 iptr->sx.s23.s3.c.ref,
2976 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2978 /* arg 1 = arraydescriptor */
2980 M_ALD(REG_OUT1, REG_PV, disp);
2982 /* arg 2 = pointer to dimensions = stack pointer (absolute) */
2984 M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
2986 /* XXX c abi call */
2987 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2988 M_ALD(REG_ITMP3, REG_PV, disp);
2989 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2992 /* check for exception before result assignment */
2994 emit_exception_check(cd, iptr);
2996 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2997 M_INTMOVE(REG_RESULT_CALLER, d);
2998 emit_store_dst(jd, iptr, d);
3002 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
3008 } /* for instruction */
3012 /* At the end of a basic block we may have to append some nops,
3013 because the patcher stub calling code might be longer than the
3014 actual instruction. So codepatching does not change the
3015 following block unintentionally. */
3017 if (cd->mcodeptr < cd->lastmcodeptr) {
3018 while (cd->mcodeptr < cd->lastmcodeptr) {
3023 } /* if (bptr -> flags >= BBREACHED) */
3024 } /* for basic block */
3026 /* generate stubs */
3028 emit_patcher_stubs(jd);
3030 /* everything's ok */
3036 /* codegen_emit_stub_compiler **************************************************
3038 Emits a stub routine which calls the compiler.
3040 *******************************************************************************/
3042 void codegen_emit_stub_compiler(jitdata *jd)
3047 /* get required compiler data */
3052 /* code for the stub */
3054 /* no window save yet, user caller's PV */
3055 M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */
3056 M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */
3057 M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */
3062 /* codegen_emit_stub_builtin ***************************************************
3064 Creates a stub routine which calls a builtin function.
3066 *******************************************************************************/
3068 void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
3077 /* get required compiler data */
3081 /* set some variables */
3084 /* calculate stack frame size */
3085 cd->stackframesize =
3089 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
3090 4; /* 4 arguments or return value */
3093 /* keep stack 16-byte aligned (ABI requirement) */
3095 if (cd->stackframesize & 1)
3096 cd->stackframesize++;
3098 /* create method header */
3099 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3100 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3101 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3102 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3103 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3105 /* generate stub code */
3106 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3108 #if defined(ENABLE_GC_CACAO)
3109 /* Save callee saved integer registers in stackframeinfo (GC may
3110 need to recover them during a collection). */
3112 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3113 OFFSET(stackframeinfo_t, intregs) + BIAS;
3115 for (i = 0; i < INT_SAV_CNT; i++)
3116 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3119 for (i = 0; i < md->paramcount; i++) {
3120 s1 = md->params[i].regoff;
3122 switch (md->paramtypes[i].type) {
3129 M_DST(s1, REG_SP, JITSTACK + i * 8);
3134 /* create dynamic stack info */
3136 M_AADD_IMM(REG_SP, BIAS + cd->stackframesize * 8, REG_OUT0); /* data sp*/
3137 M_MOV(REG_PV_CALLEE, REG_OUT1); /* PV */
3138 M_MOV(REG_FP, REG_OUT2); /* java sp */
3139 M_MOV(REG_RA_CALLEE, REG_OUT3); /* ra */
3141 disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
3142 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3143 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3144 M_NOP; /* XXX fill me! */
3147 /* builtins are allowed to have 5 arguments max */
3149 assert(md->paramcount <= 5);
3151 /* copy arguments into position */
3153 for (i = 0; i < md->paramcount; i++) {
3154 assert(!md->params[i].inmemory);
3156 s1 = md->params[i].regoff;
3158 switch (md->paramtypes[i].type) {
3162 M_MOV(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[i]), s1);
3166 M_DLD(s1, REG_SP, JITSTACK + i * 8);
3172 /* call the builtin function */
3174 disp = dseg_add_functionptr(cd, bte->fp);
3175 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); /* load adress of builtin */
3176 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call builtin */
3177 M_NOP; /* delay slot */
3180 /* save return value */
3182 if (md->returntype.type != TYPE_VOID) {
3183 if (IS_INT_LNG_TYPE(md->returntype.type))
3184 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3186 M_DST(REG_FRESULT, REG_SP, CSTACK);
3190 /* remove native stackframe info */
3192 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3193 disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
3194 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3195 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3198 /* restore float return value, int return value already in our return reg */
3200 if (md->returntype.type != TYPE_VOID) {
3201 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3202 if (IS_2_WORD_TYPE(md->returntype.type))
3203 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3205 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3210 #if defined(ENABLE_GC_CACAO)
3211 /* Restore callee saved integer registers from stackframeinfo (GC
3212 might have modified them during a collection). */
3214 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3215 OFFSET(stackframeinfo_t, intregs) + BIAS;
3217 for (i = 0; i < INT_SAV_CNT; i++)
3218 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3222 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3229 /* codegen_emit_stub_native ****************************************************
3231 Emits a stub routine which calls a native method.
3233 *******************************************************************************/
3235 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3242 s4 i, j; /* count variables */
3245 s4 funcdisp; /* displacement of the function */
3246 s4 fltregarg_offset[FLT_ARG_CNT];
3248 /* get required compiler data */
3254 /* initialize variables */
3257 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3259 /* calculate stack frame size */
3261 cd->stackframesize =
3262 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3263 sizeof(localref_table) / SIZEOF_VOID_P +
3264 md->paramcount + /* for saving arguments over calls */
3265 nmd->memuse + /* nmd->memuse includes the (6) abi params */
3269 /* keep stack 16-byte aligned (ABI requirement) */
3271 if (cd->stackframesize & 1)
3272 cd->stackframesize++;
3274 /* create method header */
3276 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3277 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3278 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3279 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3280 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3282 /* generate stub code */
3284 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3286 #if !defined(NDEBUG)
3287 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3288 emit_verbosecall_enter(jd);
3291 /* get function address (this must happen before the stackframeinfo) */
3293 funcdisp = dseg_add_functionptr(cd, f);
3296 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
3298 /* save float argument registers */
3300 assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
3302 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3303 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3304 s1 = WINSAVE_CNT + nmd->memuse + j;
3305 M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
3306 fltregarg_offset[i] = s1; /* remember stack offset */
3311 /* prepare data structures for native function call */
3313 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */
3314 M_MOV(REG_PV_CALLEE, REG_OUT1);
3315 M_MOV(REG_FP, REG_OUT2); /* java sp */
3316 M_MOV(REG_RA_CALLEE, REG_OUT3);
3317 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3318 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3319 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3320 M_NOP; /* XXX fill me! */
3322 /* remember class argument */
3324 if (m->flags & ACC_STATIC)
3325 M_MOV(REG_RESULT_CALLER, REG_ITMP3);
3327 /* keep float arguments on stack */
3329 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3330 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3331 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
3337 /* copy or spill arguments to new locations */
3339 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3340 t = md->paramtypes[i].type;
3342 if (IS_INT_LNG_TYPE(t)) {
3344 /* integral types */
3346 if (!md->params[i].inmemory) {
3347 s1 = md->params[i].regoff;
3348 /* s1 refers to the old window, transpose */
3349 s1 = REG_WINDOW_TRANSPOSE(s1);
3351 if (!nmd->params[j].inmemory) {
3352 s2 = nmd->params[j].regoff;
3355 /* nmd's regoff is relative to the start of the param array */
3356 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3357 M_AST(s1, REG_SP, s2);
3361 if (!nmd->params[j].inmemory) {
3362 /* JIT stack arg -> NAT reg arg */
3364 /* Due to the Env pointer that is always passed, the 6th JIT arg */
3365 /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */
3367 assert(false); /* path never taken */
3370 s1 = md->params[i].regoff + cd->stackframesize * 8;
3371 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3372 M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
3373 M_AST(REG_ITMP1, REG_SP, s2);
3378 /* floating point types */
3380 if (!md->params[i].inmemory) {
3381 s1 = md->params[i].regoff;
3383 if (!nmd->params[j].inmemory) {
3385 /* no mapping to regs needed, native flt args use regoff */
3386 s2 = nmd->params[j].regoff;
3388 /* JIT float regs are still on the stack */
3389 M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8));
3392 /* not supposed to happen with 16 NAT flt args */
3395 s2 = nmd->params[j].regoff;
3396 if (IS_2_WORD_TYPE(t))
3397 M_DST(s1, REG_SP, CSTACK + (s2 * 8));
3399 M_FST(s1, REG_SP, CSTACK + (s2 * 8));
3405 s1 = md->params[i].regoff;
3407 if (!nmd->params[j].inmemory) {
3409 /* JIT stack -> NAT reg */
3411 s2 = nmd->params[j].regoff;
3412 M_DLD(s2, REG_FP, JITSTACK + s1);
3416 /* JIT stack -> NAT stack */
3418 s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff;
3420 /* The FTMP register may already be loaded with args */
3421 /* we know $f0 is unused because of the env pointer */
3422 M_DLD(REG_F0, REG_FP, JITSTACK + s1);
3423 M_DST(REG_F0, REG_SP, BIAS + s2);
3430 /* put class into second argument register */
3432 if (m->flags & ACC_STATIC)
3433 M_MOV(REG_ITMP3, REG_OUT1);
3435 /* put env into first argument register */
3437 disp = dseg_add_address(cd, _Jv_env);
3438 M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
3440 /* do the native function call */
3442 M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method */
3443 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method */
3444 M_NOP; /* delay slot */
3446 /* save return value */
3448 if (md->returntype.type != TYPE_VOID) {
3449 if (IS_INT_LNG_TYPE(md->returntype.type))
3450 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3452 M_DST(REG_FRESULT, REG_SP, CSTACK);
3455 /* Note: native functions return float values in %f0 (see ABI) */
3456 /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
3458 #if !defined(NDEBUG)
3459 /* But for the trace function we need to put a flt result into %f1 */
3460 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3461 if (!IS_2_WORD_TYPE(md->returntype.type))
3462 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3463 emit_verbosecall_exit(jd);
3467 /* remove native stackframe info */
3469 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3470 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3471 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3472 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3473 M_NOP; /* XXX fill me! */
3474 M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
3476 /* restore float return value, int return value already in our return reg */
3478 if (md->returntype.type != TYPE_VOID) {
3479 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3480 if (IS_2_WORD_TYPE(md->returntype.type))
3481 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3483 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3487 /* check for exception */
3488 M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
3491 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3494 /* handle exception */
3496 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3497 M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */
3498 M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */
3499 M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */
3500 M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
3502 /* generate patcher stubs */
3504 emit_patcher_stubs(jd);
3508 * These are local overrides for various environment variables in Emacs.
3509 * Please do not remove this and leave it at the end of the file, where
3510 * Emacs will automagically detect them.
3511 * ---------------------------------------------------------------------
3514 * indent-tabs-mode: t
3518 * vim:noexpandtab:sw=4:ts=4: