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/localref.hpp"
43 #include "native/native.hpp"
45 #include "vm/jit/builtin.hpp"
46 #include "vm/exceptions.hpp"
47 #include "vm/global.h"
48 #include "vm/loader.hpp"
49 #include "vm/options.h"
51 #include "vm/jit/abi.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/codegen-common.hpp"
54 #include "vm/jit/dseg.h"
55 #include "vm/jit/emit-common.hpp"
56 #include "vm/jit/jit.hpp"
57 #include "vm/jit/linenumbertable.hpp"
58 #include "vm/jit/parse.h"
59 #include "vm/jit/patcher.h"
60 #include "vm/jit/reg.h"
61 #include "vm/jit/replace.hpp"
62 #include "vm/jit/stacktrace.hpp"
64 #include "vm/jit/sparc64/solaris/macro_rename.h"
66 #define BUILTIN_FLOAT_ARGS 1
68 /* XXX use something like this for window control ?
69 * #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER)
71 #define REG_PV REG_PV_CALLEE
76 if ((disp < -4096) || (disp > 4095))
77 printf("disp %d\n", disp);
80 return (disp >= -4096) && (disp <= 4095);
83 s4 get_lopart_disp(disp)
88 lodisp = setlo_part(disp);
90 if (setlo_part(disp) == 0)
93 lodisp = setlo_part(disp) | 0x1c00;
100 bool check_13bit_imm(s8 imm)
102 s4 sign = (imm >> 12) & 0x1;
105 if ((imm & ~0xfff) == 0) return true; /* pos imm. */
108 if ((imm & ~0xfff) + 0xfff == -1) return true; /* neg imm. */
110 printf("immediate out-of-bounds: %ld\n", imm);
116 /* codegen_emit ****************************************************************
118 Generates machine code.
120 *******************************************************************************/
122 bool codegen_emit(jitdata *jd)
128 s4 len, s1, s2, s3, d, disp, slots;
133 constant_classref *cr;
134 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
135 unresolved_method *um;
136 builtintable_entry *bte;
139 unresolved_field *uf;
143 /* get required compiler data */
150 /* prevent compiler warnings */
162 #if 0 /* no leaf optimization yet */
163 savedregs_num = (code_is_leafmethod(code)) ? 0 : 1; /* space to save the RA */
165 savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */
168 /* space to save used callee saved registers */
170 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
171 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
173 cd->stackframesize = rd->memuse + savedregs_num;
175 #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
176 if (checksync && code_is_synchronized(code))
177 cd->stackframesize++;
180 /* keep stack 16-byte aligned (ABI requirement) */
182 if (cd->stackframesize & 1)
183 cd->stackframesize++;
185 /* create method header */
187 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
188 framesize_disp = dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
190 code->synchronizedoffset = JITSTACK + rd->memuse * 8;
192 /* REMOVEME: We still need it for exception handling in assembler. */
194 if (code_is_leafmethod(code))
195 (void) dseg_add_unique_s4(cd, 1);
197 (void) dseg_add_unique_s4(cd, 0);
199 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
200 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
202 /* save register window and create stack frame (if necessary) */
204 if (cd->stackframesize) {
205 if (cd->stackframesize <= 4095)
206 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
208 M_ILD_INTERN(REG_ITMP3, REG_PV_CALLER, framesize_disp);
209 M_SUB(REG_ZERO, REG_ITMP3, REG_ITMP3);
210 M_SAVE_REG(REG_SP, REG_ITMP3, REG_SP);
214 /* save callee saved float registers (none right now) */
216 p = cd->stackframesize;
217 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
218 p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
223 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
224 emit_verbosecall_enter(jd);
228 /* call monitorenter function */
229 #if defined(ENABLE_THREADS)
230 if (checksync && code_is_synchronized(code)) {
231 /* stack offset for monitor argument */
235 /* save float argument registers */
239 ALIGN_STACK_SLOTS(slots);
241 M_LDA(REG_SP, REG_SP, -(slots * 8));
242 for (i = 0; i < FLT_ARG_CNT; i++)
243 M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
247 /* get correct lock object */
249 if (m->flags & ACC_STATIC) {
250 disp = dseg_add_address(cd, &m->clazz->object.header);
251 M_ALD(REG_OUT0, REG_PV, disp);
252 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
253 M_ALD(REG_ITMP3, REG_PV, disp);
256 /* copy class pointer: $i0 -> $o0 */
257 M_MOV(REG_RESULT_CALLEE, REG_OUT0);
259 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
260 M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
261 M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
264 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
265 M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */
267 /* restore float argument registers */
269 for (i = 0; i < FLT_ARG_CNT; i++)
270 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
272 M_LDA(REG_SP, REG_SP, slots * 8);
277 /* take arguments out of register or stack frame */
281 for (p = 0, l = 0; p < md->paramcount; p++) {
282 t = md->paramtypes[p].type;
284 varindex = jd->local_map[l * 5 + t];
287 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
290 if (varindex == UNUSED)
294 s1 = md->params[p].regoff;
296 if (IS_INT_LNG_TYPE(t)) { /* integer args */
300 if (!md->params[p].inmemory) { /* register arguments */
301 s1 = REG_WINDOW_TRANSPOSE(s1);
303 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
305 /* the register allocator does not know about the window. */
306 /* avoid copying the locals from save to save regs by */
307 /* swapping variables. */
310 int old_dest = var->vv.regoff;
311 int new_dest = p + 24;
313 /* run through all variables */
315 for (i = 0; i < jd->varcount; i++) {
316 varinfo* uvar = VAR(i);
318 if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags))
321 s2 = uvar->vv.regoff;
323 /* free the in reg by moving all other references */
325 if (s2 == new_dest) {
326 uvar->vv.regoff = old_dest;
327 /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
330 /* move all variables to the in reg */
332 if (s2 == old_dest) {
333 uvar->vv.regoff = new_dest;
334 /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
342 else { /* reg arg -> spilled */
343 M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
346 } else { /* stack arguments */
347 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
348 M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1);
350 } else { /* stack arg -> spilled */
351 /* add the callers window save registers */
352 var->vv.regoff = cd->stackframesize * 8 + s1;
356 } else { /* floating args */
357 if (!md->params[p].inmemory) { /* register arguments */
358 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
359 M_FLTMOVE(s1, var->vv.regoff);
361 } else { /* reg arg -> spilled */
362 M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
365 } else { /* stack arguments */
366 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
367 M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1);
369 } else { /* stack-arg -> spilled */
370 var->vv.regoff = cd->stackframesize * 8 + s1;
379 /* end of header generation */
381 /* create replacement points */
383 REPLACEMENT_POINTS_INIT(cd, jd);
385 /* walk through all basic blocks */
387 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
389 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
391 if (bptr->flags >= BBREACHED) {
393 /* branch resolving */
395 codegen_resolve_branchrefs(cd, bptr);
397 /* handle replacement points */
399 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
402 /* copy interface registers to their destination */
407 #if defined(ENABLE_LSRA)
408 #error XXX LSRA not tested yet
412 src = bptr->invars[len];
413 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
414 /* d = reg_of_var(m, src, REG_ITMP1); */
415 if (!(src->flags & INMEMORY))
419 M_INTMOVE(REG_ITMP1, d);
420 emit_store(jd, NULL, src, d);
427 var = VAR(bptr->invars[len]);
428 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
429 d = codegen_reg_of_var(0, var, REG_ITMP1);
430 M_INTMOVE(REG_ITMP2_XPTR, d);
431 emit_store(jd, NULL, var, d);
434 assert((var->flags & INOUT));
437 #if defined(ENABLE_LSRA)
440 /* walk through all instructions */
444 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
445 if (iptr->line != currentline) {
446 linenumbertable_list_entry_add(cd, iptr->line);
447 currentline = iptr->line;
450 MCODECHECK(64); /* an instruction usually needs < 64 words */
454 case ICMD_INLINE_START:
455 case ICMD_INLINE_END:
458 case ICMD_NOP: /* ... ==> ... */
461 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
463 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
464 emit_nullpointer_check(cd, iptr, s1);
467 /* constant operations ************************************************/
469 case ICMD_ICONST: /* ... ==> ..., constant */
471 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
472 ICONST(d, iptr->sx.val.i);
473 emit_store_dst(jd, iptr, d);
476 case ICMD_LCONST: /* ... ==> ..., constant */
478 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
479 LCONST(d, iptr->sx.val.l);
480 emit_store_dst(jd, iptr, d);
483 case ICMD_FCONST: /* ... ==> ..., constant */
485 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
486 disp = dseg_add_float(cd, iptr->sx.val.f);
487 M_FLD(d, REG_PV, disp);
488 emit_store_dst(jd, iptr, d);
491 case ICMD_DCONST: /* ... ==> ..., constant */
493 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
494 disp = dseg_add_double(cd, iptr->sx.val.d);
495 M_DLD(d, REG_PV, disp);
496 emit_store_dst(jd, iptr, d);
499 case ICMD_ACONST: /* ... ==> ..., constant */
501 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
503 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
504 cr = iptr->sx.val.c.ref;
505 disp = dseg_add_unique_address(cd, cr);
507 codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
509 M_ALD(d, REG_PV, disp);
513 if (iptr->sx.val.anyptr == NULL) {
514 M_INTMOVE(REG_ZERO, d);
517 disp = dseg_add_address(cd, iptr->sx.val.anyptr);
518 M_ALD(d, REG_PV, disp);
521 emit_store_dst(jd, iptr, d);
525 /* load/store/copy/move operations ************************************/
527 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
532 case ICMD_ISTORE: /* ..., value ==> ... */
543 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
548 /* pop/dup/swap operations ********************************************/
550 /* attention: double and longs are only one entry in CACAO ICMDs */
552 case ICMD_POP: /* ..., value ==> ... */
553 case ICMD_POP2: /* ..., value, value ==> ... */
557 /* integer operations *************************************************/
559 case ICMD_INEG: /* ..., value ==> ..., - value */
562 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
563 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
564 M_SUB(REG_ZERO, s1, d);
565 emit_store_dst(jd, iptr, d);
568 case ICMD_I2L: /* ..., value ==> ..., value */
570 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
571 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
573 emit_store_dst(jd, iptr, d);
576 case ICMD_L2I: /* ..., value ==> ..., value */
578 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
579 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
580 M_SRA_IMM(s1, 0, d); /* sign extend upper 32 bits */
581 emit_store_dst(jd, iptr, d);
584 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
586 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
587 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
588 M_SLLX_IMM(s1, 56, d);
589 M_SRAX_IMM( d, 56, d);
590 emit_store_dst(jd, iptr, d);
593 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
595 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
596 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
597 M_SLLX_IMM(s1, 48, d);
598 M_SRLX_IMM( d, 48, d);
599 emit_store_dst(jd, iptr, d);
602 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
604 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
605 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
606 M_SLLX_IMM(s1, 48, d);
607 M_SRAX_IMM( d, 48, d);
608 emit_store_dst(jd, iptr, d);
611 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
614 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
615 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
616 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
618 emit_store_dst(jd, iptr, d);
622 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
623 /* sx.val.i = constant */
625 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
626 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
627 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
628 M_ADD_IMM(s1, iptr->sx.val.i, d);
630 ICONST(REG_ITMP2, iptr->sx.val.i);
631 M_ADD(s1, REG_ITMP2, d);
633 emit_store_dst(jd, iptr, d);
636 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
637 /* sx.val.l = constant */
639 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
640 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
641 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
642 M_ADD_IMM(s1, iptr->sx.val.l, d);
644 LCONST(REG_ITMP2, iptr->sx.val.l);
645 M_ADD(s1, REG_ITMP2, d);
647 emit_store_dst(jd, iptr, d);
650 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
653 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
654 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
655 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
657 emit_store_dst(jd, iptr, d);
660 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
661 /* sx.val.i = constant */
663 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
664 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
665 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
666 M_SUB_IMM(s1, iptr->sx.val.i, d);
668 ICONST(REG_ITMP2, iptr->sx.val.i);
669 M_SUB(s1, REG_ITMP2, d);
671 emit_store_dst(jd, iptr, d);
674 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
675 /* sx.val.l = constant */
677 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
678 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
679 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
680 M_SUB_IMM(s1, iptr->sx.val.l, d);
682 LCONST(REG_ITMP2, iptr->sx.val.l);
683 M_SUB(s1, REG_ITMP2, d);
685 emit_store_dst(jd, iptr, d);
688 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
691 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
692 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
693 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
695 emit_store_dst(jd, iptr, d);
698 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
699 /* sx.val.i = constant */
701 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
702 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
703 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
704 M_MULX_IMM(s1, iptr->sx.val.i, d);
706 ICONST(REG_ITMP2, iptr->sx.val.i);
707 M_MULX(s1, REG_ITMP2, d);
709 emit_store_dst(jd, iptr, d);
712 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
713 /* sx.val.l = constant */
715 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
716 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
717 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
718 M_MULX_IMM(s1, iptr->sx.val.l, d);
720 LCONST(REG_ITMP2, iptr->sx.val.l);
721 M_MULX(s1, REG_ITMP2, d);
723 emit_store_dst(jd, iptr, d);
726 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
727 /* XXX could also clear Y and use 32bit div */
728 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
729 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
730 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
731 emit_arithmetic_check(cd, iptr, s2);
733 /* XXX trim s2 like s1 ? */
735 emit_store_dst(jd, iptr, d);
738 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
740 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
741 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
742 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
743 emit_arithmetic_check(cd, iptr, s2);
745 emit_store_dst(jd, iptr, d);
748 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
750 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
751 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
752 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
753 emit_arithmetic_check(cd, iptr, s2);
755 /* XXX trim s2 like s1 ? */
756 M_DIVX(s1, s2, REG_ITMP3);
757 M_MULX(s2, REG_ITMP3, REG_ITMP3);
758 M_SUB(s1, REG_ITMP3, d);
759 emit_store_dst(jd, iptr, d);
762 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
764 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
765 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
766 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
767 emit_arithmetic_check(cd, iptr, s2);
768 M_DIVX(s1, s2, REG_ITMP3);
769 M_MULX(s2, REG_ITMP3, REG_ITMP3);
770 M_SUB(s1, REG_ITMP3, d);
771 emit_store_dst(jd, iptr, d);
774 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
775 case ICMD_LDIVPOW2: /* val.i = constant */
777 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
778 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
779 M_SRAX_IMM(s1, 63, REG_ITMP2);
780 M_SRLX_IMM(REG_ITMP2, 64 - iptr->sx.val.i, REG_ITMP2);
781 M_ADD(s1, REG_ITMP2, REG_ITMP2);
782 M_SRAX_IMM(REG_ITMP2, iptr->sx.val.i, d);
783 emit_store_dst(jd, iptr, d);
786 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
788 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
789 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
790 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
792 emit_store_dst(jd, iptr, d);
795 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
797 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
798 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
799 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
801 emit_store_dst(jd, iptr, d);
804 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
805 /* val.i = constant */
807 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
808 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
809 M_SLL_IMM(s1, iptr->sx.val.i, d);
810 emit_store_dst(jd, iptr, d);
813 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
814 /* val.i = constant */
816 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
817 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
818 M_SLLX_IMM(s1, iptr->sx.val.i, d);
819 emit_store_dst(jd, iptr, d);
822 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
824 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
825 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
826 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
828 emit_store_dst(jd, iptr, d);
831 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
832 /* sx.val.i = constant */
834 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
835 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
836 M_SRA_IMM(s1, iptr->sx.val.i, d);
837 emit_store_dst(jd, iptr, d);
840 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
842 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
843 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
844 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
846 emit_store_dst(jd, iptr, d);
849 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
850 /* sx.val.i = constant */
852 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
853 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
854 M_SRL_IMM(s1, iptr->sx.val.i, d);
855 emit_store_dst(jd, iptr, d);
858 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
860 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
861 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
862 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
864 emit_store_dst(jd, iptr, d);
867 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
868 /* sx.val.i = constant */
870 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
871 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
872 M_SRAX_IMM(s1, iptr->sx.val.i, d);
873 emit_store_dst(jd, iptr, d);
876 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
878 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
879 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
880 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
882 emit_store_dst(jd, iptr, d);
885 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
886 /* sx.val.i = constant */
888 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
889 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
890 M_SRLX_IMM(s1, iptr->sx.val.i, d);
891 emit_store_dst(jd, iptr, d);
894 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
897 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
898 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
899 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
901 emit_store_dst(jd, iptr, d);
904 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
905 /* sx.val.i = constant */
907 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
908 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
909 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
910 M_AND_IMM(s1, iptr->sx.val.i, d);
912 ICONST(REG_ITMP2, iptr->sx.val.i);
913 M_AND(s1, REG_ITMP2, d);
915 emit_store_dst(jd, iptr, d);
918 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
919 /* sx.val.i = constant */
920 /* constant is actually constant - 1 */
922 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
923 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
925 M_MOV(s1, REG_ITMP1);
928 M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
929 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
930 M_AND_IMM(s1, iptr->sx.val.i, d);
933 M_SUB(REG_ZERO, s1, d);
934 M_AND_IMM(d, iptr->sx.val.i, d);
936 ICONST(REG_ITMP2, iptr->sx.val.i);
937 M_AND(s1, REG_ITMP2, d);
940 M_SUB(REG_ZERO, s1, d);
941 M_AND(d, REG_ITMP2, d);
943 M_SUB(REG_ZERO, d, d);
944 emit_store_dst(jd, iptr, d);
947 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
948 /* sx.val.l = constant */
950 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
951 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
952 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
953 M_AND_IMM(s1, iptr->sx.val.l, d);
955 LCONST(REG_ITMP2, iptr->sx.val.l);
956 M_AND(s1, REG_ITMP2, d);
958 emit_store_dst(jd, iptr, d);
961 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
962 /* sx.val.l = constant */
964 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
965 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
967 M_MOV(s1, REG_ITMP1);
970 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
971 M_AND_IMM(s1, iptr->sx.val.l, d);
974 M_SUB(REG_ZERO, s1, d);
975 M_AND_IMM(d, iptr->sx.val.l, d);
977 LCONST(REG_ITMP2, iptr->sx.val.l);
978 M_AND(s1, REG_ITMP2, d);
981 M_SUB(REG_ZERO, s1, d);
982 M_AND(d, REG_ITMP2, d);
984 M_SUB(REG_ZERO, d, d);
985 emit_store_dst(jd, iptr, d);
988 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
991 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
992 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
993 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
995 emit_store_dst(jd, iptr, d);
998 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
999 /* sx.val.i = constant */
1001 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1002 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1003 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1004 M_OR_IMM(s1, iptr->sx.val.i, d);
1006 ICONST(REG_ITMP2, iptr->sx.val.i);
1007 M_OR(s1, REG_ITMP2, d);
1009 emit_store_dst(jd, iptr, d);
1012 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1013 /* sx.val.l = constant */
1015 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1016 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1017 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1018 M_OR_IMM(s1, iptr->sx.val.l, d);
1020 LCONST(REG_ITMP2, iptr->sx.val.l);
1021 M_OR(s1, REG_ITMP2, d);
1023 emit_store_dst(jd, iptr, d);
1026 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1029 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1030 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1031 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1033 emit_store_dst(jd, iptr, d);
1036 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1037 /* sx.val.i = constant */
1039 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1040 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1041 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1042 M_XOR_IMM(s1, iptr->sx.val.i, d);
1044 ICONST(REG_ITMP2, iptr->sx.val.i);
1045 M_XOR(s1, REG_ITMP2, d);
1047 emit_store_dst(jd, iptr, d);
1050 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1051 /* sx.val.l = constant */
1053 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1054 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1055 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1056 M_XOR_IMM(s1, iptr->sx.val.l, d);
1058 LCONST(REG_ITMP2, iptr->sx.val.l);
1059 M_XOR(s1, REG_ITMP2, d);
1061 emit_store_dst(jd, iptr, d);
1065 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1067 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1068 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1069 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1072 M_XCMOVLT_IMM(-1, d);
1073 M_XCMOVGT_IMM(1, d);
1074 emit_store_dst(jd, iptr, d);
1078 /* floating operations ************************************************/
1080 case ICMD_FNEG: /* ..., value ==> ..., - value */
1082 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1083 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1085 emit_store_dst(jd, iptr, d);
1088 case ICMD_DNEG: /* ..., value ==> ..., - value */
1090 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1091 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1093 emit_store_dst(jd, iptr, d);
1096 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1098 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1099 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1100 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1102 emit_store_dst(jd, iptr, d);
1105 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1107 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1108 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1109 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1111 emit_store_dst(jd, iptr, d);
1114 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1116 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1117 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1118 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1120 emit_store_dst(jd, iptr, d);
1123 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1125 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1126 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1127 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1129 emit_store_dst(jd, iptr, d);
1132 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1134 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1135 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1136 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1138 emit_store_dst(jd, iptr, d);
1141 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1143 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1144 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1145 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1147 emit_store_dst(jd, iptr, d);
1150 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1152 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1153 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1154 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1156 emit_store_dst(jd, iptr, d);
1159 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1161 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1162 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1163 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1165 emit_store_dst(jd, iptr, d);
1169 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1170 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1171 disp = dseg_add_unique_float(cd, 0.0);
1172 M_IST (s1, REG_PV_CALLEE, disp);
1173 M_FLD (d, REG_PV_CALLEE, disp);
1174 M_CVTIF (d, d); /* rd gets translated to double target register */
1175 emit_store_dst(jd, iptr, d);
1179 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1180 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1181 disp = dseg_add_unique_float(cd, 0.0);
1182 M_IST(s1, REG_PV_CALLEE, disp);
1183 M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
1184 M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
1185 emit_store_dst(jd, iptr, d);
1189 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1190 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1191 disp = dseg_add_unique_double(cd, 0.0);
1192 M_STX(s1, REG_PV_CALLEE, disp);
1193 M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
1194 M_CVTLF(REG_FTMP3, d);
1195 emit_store_dst(jd, iptr, d);
1199 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1200 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1201 disp = dseg_add_unique_double(cd, 0.0);
1202 M_STX(s1, REG_PV_CALLEE, disp);
1203 M_DLD(d, REG_PV_CALLEE, disp);
1205 emit_store_dst(jd, iptr, d);
1208 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1209 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1210 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1211 disp = dseg_add_unique_float(cd, 0.0);
1213 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1216 M_MOV(REG_ZERO, d); /* delay slot */
1218 M_CVTFI(s1, REG_FTMP2);
1219 M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
1220 M_ILD(d, REG_PV, disp);
1221 emit_store_dst(jd, iptr, d);
1225 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1226 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1227 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1228 disp = dseg_add_unique_float(cd, 0.0);
1230 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1233 M_MOV(REG_ZERO, d); /* delay slot */
1235 M_CVTDI(s1, REG_FTMP2);
1236 M_FST(REG_FTMP2, REG_PV, disp);
1237 M_ILD(d, REG_PV, disp);
1238 emit_store_dst(jd, iptr, d);
1241 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1242 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1243 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1244 disp = dseg_add_unique_double(cd, 0.0);
1246 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1249 M_MOV(REG_ZERO, d); /* delay slot */
1251 M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1252 M_DST(REG_FTMP2, REG_PV, disp);
1253 M_LDX(d, REG_PV, disp);
1254 emit_store_dst(jd, iptr, d);
1257 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1258 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1259 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1260 disp = dseg_add_unique_double(cd, 0.0);
1262 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1265 M_MOV(REG_ZERO, d); /* delay slot */
1267 M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1268 M_DST(REG_FTMP2, REG_PV, disp);
1269 M_LDX(d, REG_PV, disp);
1270 emit_store_dst(jd, iptr, d);
1273 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1275 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1276 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1278 emit_store_dst(jd, iptr, d);
1281 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1283 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1284 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1286 emit_store_dst(jd, iptr, d);
1289 /* XXX merge F/D versions? only compare instr. is different */
1290 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1292 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1293 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1294 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1296 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1297 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1298 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1299 emit_store_dst(jd, iptr, d);
1302 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1304 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1305 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1306 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1308 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1309 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1310 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1311 emit_store_dst(jd, iptr, d);
1314 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1316 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1317 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1318 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1320 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1321 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1322 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1323 emit_store_dst(jd, iptr, d);
1326 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1328 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1329 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1330 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1332 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1333 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1334 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1335 emit_store_dst(jd, iptr, d);
1339 /* memory operations **************************************************/
1341 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1343 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1344 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1345 emit_nullpointer_check(cd, iptr, s1);
1346 M_ILD(d, s1, OFFSET(java_array_t, size));
1347 emit_store_dst(jd, iptr, d);
1350 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1352 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1353 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1354 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1355 /* implicit null-pointer check */
1356 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1357 M_AADD(s2, s1, REG_ITMP3);
1358 M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray_t, data[0]));
1359 emit_store_dst(jd, iptr, d);
1362 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1364 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1365 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1366 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1367 /* implicit null-pointer check */
1368 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1369 M_AADD(s2, s1, REG_ITMP3);
1370 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1371 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray_t, data[0]));
1372 emit_store_dst(jd, iptr, d);
1375 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1377 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1378 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1379 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1380 /* implicit null-pointer check */
1381 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1382 M_AADD(s2, s1, REG_ITMP3);
1383 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1384 M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray_t, data[0]));
1385 emit_store_dst(jd, iptr, d);
1388 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1390 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1391 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1392 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1393 /* implicit null-pointer check */
1394 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1395 M_ASLL_IMM(s2, 2, REG_ITMP3);
1396 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1397 M_ILD(d, REG_ITMP3, OFFSET(java_intarray_t, data[0]));
1398 emit_store_dst(jd, iptr, d);
1401 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1403 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1404 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1405 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1406 /* implicit null-pointer check */
1407 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1408 M_ASLL_IMM(s2, 3, REG_ITMP3);
1409 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1410 M_LDX(d, REG_ITMP3, OFFSET(java_longarray_t, data[0]));
1411 emit_store_dst(jd, iptr, d);
1414 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1416 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1417 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1418 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1419 /* implicit null-pointer check */
1420 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1421 M_ASLL_IMM(s2, 2, REG_ITMP3);
1422 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1423 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray_t, data[0]));
1424 emit_store_dst(jd, iptr, d);
1427 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1429 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1430 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1431 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1432 /* implicit null-pointer check */
1433 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1434 M_ASLL_IMM(s2, 3, REG_ITMP3);
1435 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1436 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray_t, data[0]));
1437 emit_store_dst(jd, iptr, d);
1440 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1442 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1443 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1444 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1445 /* implicit null-pointer check */
1446 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1447 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1448 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1449 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray_t, data[0]));
1450 emit_store_dst(jd, iptr, d);
1454 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1456 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1457 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1458 /* implicit null-pointer check */
1459 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1460 M_AADD(s2, s1, REG_ITMP1);
1461 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1462 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1465 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1466 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1468 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1469 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1470 /* implicit null-pointer check */
1471 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1472 M_AADD(s2, s1, REG_ITMP1);
1473 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1474 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1475 M_SST(s3, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1478 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1480 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1481 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1482 /* implicit null-pointer check */
1483 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1484 M_ASLL_IMM(s2, 2, REG_ITMP2);
1485 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1486 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1487 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1490 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1492 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1493 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1494 /* implicit null-pointer check */
1495 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1496 M_ASLL_IMM(s2, 3, REG_ITMP2);
1497 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1498 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1499 M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1502 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1504 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1505 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1506 /* implicit null-pointer check */
1507 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1508 M_ASLL_IMM(s2, 2, REG_ITMP2);
1509 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1510 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1511 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray_t, data[0]));
1514 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1516 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1517 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1518 /* implicit null-pointer check */
1519 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1520 M_ASLL_IMM(s2, 3, REG_ITMP2);
1521 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1522 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1523 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray_t, data[0]));
1527 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1529 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1530 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1531 /* implicit null-pointer check */
1532 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1533 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1535 M_MOV(s1, REG_OUT0);
1536 M_MOV(s3, REG_OUT1);
1537 disp = dseg_add_functionptr(cd, BUILTIN_FAST_canstore);
1538 M_ALD(REG_ITMP3, REG_PV, disp);
1539 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
1541 emit_arraystore_check(cd, iptr);
1543 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1544 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1545 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1546 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1547 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1548 /* implicit null-pointer check */
1549 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1553 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1555 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1556 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1557 /* implicit null-pointer check */
1558 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1559 M_AADD(s2, s1, REG_ITMP1);
1560 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray_t, data[0]));
1563 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1564 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1566 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1567 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1568 /* implicit null-pointer check */
1569 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1570 M_AADD(s2, s1, REG_ITMP1);
1571 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1572 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray_t, data[0]));
1575 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1577 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1578 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1579 /* implicit null-pointer check */
1580 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1581 M_ASLL_IMM(s2, 2, REG_ITMP2);
1582 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1583 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray_t, data[0]));
1586 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1588 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1589 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1590 /* implicit null-pointer check */
1591 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1592 M_ASLL_IMM(s2, 3, REG_ITMP2);
1593 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1594 M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray_t, data[0]));
1597 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1599 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1600 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1601 /* implicit null-pointer check */
1602 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1603 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1604 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1605 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray_t, data[0]));
1609 case ICMD_GETSTATIC: /* ... ==> ..., value */
1611 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1612 uf = iptr->sx.s23.s3.uf;
1613 fieldtype = uf->fieldref->parseddesc.fd->type;
1614 disp = dseg_add_unique_address(cd, uf);
1616 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1619 fi = iptr->sx.s23.s3.fmiref->p.field;
1620 fieldtype = fi->type;
1621 disp = dseg_add_address(cd, fi->value);
1623 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1624 codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
1627 M_ALD(REG_ITMP1, REG_PV, disp);
1629 switch (fieldtype) {
1631 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1632 M_ILD_INTERN(d, REG_ITMP1, 0);
1635 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1636 M_LDX_INTERN(d, REG_ITMP1, 0);
1639 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1640 M_ALD_INTERN(d, REG_ITMP1, 0);
1643 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1644 M_FLD_INTERN(d, REG_ITMP1, 0);
1647 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1648 M_DLD_INTERN(d, REG_ITMP1, 0);
1651 emit_store_dst(jd, iptr, d);
1654 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1656 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1657 uf = iptr->sx.s23.s3.uf;
1658 fieldtype = uf->fieldref->parseddesc.fd->type;
1659 disp = dseg_add_unique_address(cd, uf);
1661 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1664 fi = iptr->sx.s23.s3.fmiref->p.field;
1665 fieldtype = fi->type;
1666 disp = dseg_add_address(cd, fi->value);
1668 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1669 codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
1672 M_ALD(REG_ITMP1, REG_PV, disp);
1674 switch (fieldtype) {
1676 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1677 M_IST_INTERN(s1, REG_ITMP1, 0);
1680 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1681 M_STX_INTERN(s1, REG_ITMP1, 0);
1684 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1685 M_AST_INTERN(s1, REG_ITMP1, 0);
1688 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1689 M_FST_INTERN(s1, REG_ITMP1, 0);
1692 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1693 M_DST_INTERN(s1, REG_ITMP1, 0);
1698 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1699 /* val = value (in current instruction) */
1700 /* following NOP) */
1702 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1703 uf = iptr->sx.s23.s3.uf;
1704 fieldtype = uf->fieldref->parseddesc.fd->type;
1705 disp = dseg_add_unique_address(cd, uf);
1707 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1710 fi = iptr->sx.s23.s3.fmiref->p.field;
1711 fieldtype = fi->type;
1712 disp = dseg_add_address(cd, fi->value);
1714 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
1715 codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
1718 M_ALD(REG_ITMP1, REG_PV, disp);
1720 switch (fieldtype) {
1722 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1725 M_STX_INTERN(REG_ZERO, REG_ITMP1, 0);
1728 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1731 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1734 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1740 case ICMD_GETFIELD: /* ... ==> ..., value */
1742 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1743 emit_nullpointer_check(cd, iptr, s1);
1745 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1746 uf = iptr->sx.s23.s3.uf;
1748 fieldtype = uf->fieldref->parseddesc.fd->type;
1751 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1754 fi = iptr->sx.s23.s3.fmiref->p.field;
1755 fieldtype = fi->type;
1759 switch (fieldtype) {
1761 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1765 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1769 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1773 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1777 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1784 emit_store_dst(jd, iptr, d);
1787 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1789 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1790 emit_nullpointer_check(cd, iptr, s1);
1792 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1793 uf = iptr->sx.s23.s3.uf;
1794 fieldtype = uf->fieldref->parseddesc.fd->type;
1799 fi = iptr->sx.s23.s3.fmiref->p.field;
1800 fieldtype = fi->type;
1804 if (IS_INT_LNG_TYPE(fieldtype))
1805 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1807 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1809 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1810 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1812 switch (fieldtype) {
1814 M_IST(s2, s1, disp);
1817 M_STX(s2, s1, disp);
1820 M_AST(s2, s1, disp);
1823 M_FST(s2, s1, disp);
1826 M_DST(s2, s1, disp);
1834 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
1835 /* val = value (in current instruction) */
1836 /* following NOP) */
1838 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1839 emit_nullpointer_check(cd, iptr, s1);
1841 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1842 unresolved_field *uf = iptr->sx.s23.s3.uf;
1844 fieldtype = uf->fieldref->parseddesc.fd->type;
1846 codegen_addpatchref(cd, PATCHER_get_putfield,
1849 if (opt_showdisassemble) {
1857 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1859 fieldtype = fi->type;
1865 switch (fieldtype) {
1867 M_IST(REG_ZERO, s1, disp);
1870 M_STX(REG_ZERO, s1, disp);
1873 M_AST(REG_ZERO, s1, disp);
1876 M_FST(REG_ZERO, s1, disp);
1879 M_DST(REG_ZERO, s1, disp);
1885 /* branch operations **************************************************/
1887 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1889 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1890 M_INTMOVE(s1, REG_ITMP2_XPTR);
1892 #ifdef ENABLE_VERIFIER
1893 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1894 unresolved_class *uc = iptr->sx.s23.s2.uc;
1896 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
1898 #endif /* ENABLE_VERIFIER */
1900 disp = dseg_add_functionptr(cd, asm_handle_exception);
1901 M_ALD(REG_ITMP1, REG_PV, disp);
1902 M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
1904 M_NOP; /* nop ensures that XPC is less than the end */
1905 /* of basic block */
1909 case ICMD_GOTO: /* ... ==> ... */
1910 case ICMD_RET: /* ... ==> ... */
1912 emit_br(cd, iptr->dst.block);
1916 case ICMD_JSR: /* ... ==> ... */
1918 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1922 case ICMD_IFNULL: /* ..., value ==> ... */
1923 case ICMD_IFNONNULL:
1925 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1926 emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
1929 /* Note: int compares must not branch on the register directly. */
1930 /* Reason is, that register content is not 32-bit clean. */
1932 case ICMD_IFEQ: /* ..., value ==> ... */
1934 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1936 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1937 M_CMP_IMM(s1, iptr->sx.val.i);
1940 ICONST(REG_ITMP2, iptr->sx.val.i);
1941 M_CMP(s1, REG_ITMP2);
1943 emit_beq(cd, iptr->dst.block);
1946 case ICMD_IFLT: /* ..., value ==> ... */
1948 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1950 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1951 M_CMP_IMM(s1, iptr->sx.val.i);
1954 ICONST(REG_ITMP2, iptr->sx.val.i);
1955 M_CMP(s1, REG_ITMP2);
1957 emit_blt(cd, iptr->dst.block);
1960 case ICMD_IFLE: /* ..., value ==> ... */
1962 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1964 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1965 M_CMP_IMM(s1, iptr->sx.val.i);
1968 ICONST(REG_ITMP2, iptr->sx.val.i);
1969 M_CMP(s1, REG_ITMP2);
1971 emit_ble(cd, iptr->dst.block);
1974 case ICMD_IFNE: /* ..., value ==> ... */
1976 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1978 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1979 M_CMP_IMM(s1, iptr->sx.val.i);
1982 ICONST(REG_ITMP2, iptr->sx.val.i);
1983 M_CMP(s1, REG_ITMP2);
1985 emit_bne(cd, iptr->dst.block);
1988 case ICMD_IFGT: /* ..., value ==> ... */
1990 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1992 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1993 M_CMP_IMM(s1, iptr->sx.val.i);
1996 ICONST(REG_ITMP2, iptr->sx.val.i);
1997 M_CMP(s1, REG_ITMP2);
1999 emit_bgt(cd, iptr->dst.block);
2002 case ICMD_IFGE: /* ..., value ==> ... */
2004 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2006 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2007 M_CMP_IMM(s1, iptr->sx.val.i);
2010 ICONST(REG_ITMP2, iptr->sx.val.i);
2011 M_CMP(s1, REG_ITMP2);
2013 emit_bge(cd, iptr->dst.block);
2016 case ICMD_IF_LEQ: /* ..., value ==> ... */
2018 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2019 if (iptr->sx.val.l == 0)
2020 emit_beqz(cd, iptr->dst.block, s1);
2022 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2023 M_CMP_IMM(s1, iptr->sx.val.l);
2026 LCONST(REG_ITMP2, iptr->sx.val.l);
2027 M_CMP(s1, REG_ITMP2);
2029 emit_beq_xcc(cd, iptr->dst.block);
2033 case ICMD_IF_LLT: /* ..., value ==> ... */
2035 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2036 if (iptr->sx.val.l == 0)
2037 emit_bltz(cd, iptr->dst.block, s1);
2039 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2040 M_CMP_IMM(s1, iptr->sx.val.l);
2043 LCONST(REG_ITMP2, iptr->sx.val.l);
2044 M_CMP(s1, REG_ITMP2);
2046 emit_blt_xcc(cd, iptr->dst.block);
2050 case ICMD_IF_LLE: /* ..., value ==> ... */
2052 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2053 if (iptr->sx.val.l == 0)
2054 emit_blez(cd, iptr->dst.block, s1);
2056 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2057 M_CMP_IMM(s1, iptr->sx.val.l);
2060 LCONST(REG_ITMP2, iptr->sx.val.l);
2061 M_CMP(s1, REG_ITMP2);
2063 emit_ble_xcc(cd, iptr->dst.block);
2067 case ICMD_IF_LNE: /* ..., value ==> ... */
2069 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2070 if (iptr->sx.val.l == 0)
2071 emit_bnez(cd, iptr->dst.block, s1);
2073 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2074 M_CMP_IMM(s1, iptr->sx.val.l);
2077 LCONST(REG_ITMP2, iptr->sx.val.l);
2078 M_CMP(s1, REG_ITMP2);
2080 emit_bne_xcc(cd, iptr->dst.block);
2084 case ICMD_IF_LGT: /* ..., value ==> ... */
2086 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2087 if (iptr->sx.val.l == 0)
2088 emit_bgtz(cd, iptr->dst.block, s1);
2090 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2091 M_CMP_IMM(s1, iptr->sx.val.l);
2094 LCONST(REG_ITMP2, iptr->sx.val.l);
2095 M_CMP(s1, REG_ITMP2);
2097 emit_bgt_xcc(cd, iptr->dst.block);
2101 case ICMD_IF_LGE: /* ..., value ==> ... */
2103 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2104 if (iptr->sx.val.l == 0)
2105 emit_bgez(cd, iptr->dst.block, s1);
2107 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2108 M_CMP_IMM(s1, iptr->sx.val.l);
2111 LCONST(REG_ITMP2, iptr->sx.val.l);
2112 M_CMP(s1, REG_ITMP2);
2114 emit_bge_xcc(cd, iptr->dst.block);
2119 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2120 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2122 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2123 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2125 emit_beq_xcc(cd, iptr->dst.block);
2128 case ICMD_IF_ICMPEQ: /* 32-bit compare */
2130 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2131 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2133 emit_beq(cd, iptr->dst.block);
2136 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
2137 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2139 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2140 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2142 emit_bne_xcc(cd, iptr->dst.block);
2145 case ICMD_IF_ICMPNE: /* 32-bit compare */
2147 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2148 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2150 emit_bne(cd, iptr->dst.block);
2153 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2155 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2156 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2158 emit_blt_xcc(cd, iptr->dst.block);
2161 case ICMD_IF_ICMPLT: /* 32-bit compare */
2163 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2164 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2166 emit_blt(cd, iptr->dst.block);
2169 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2171 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2172 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2174 emit_bgt_xcc(cd, iptr->dst.block);
2177 case ICMD_IF_ICMPGT: /* 32-bit compare */
2179 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2180 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2182 emit_bgt(cd, iptr->dst.block);
2185 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2187 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2188 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2190 emit_ble_xcc(cd, iptr->dst.block);
2193 case ICMD_IF_ICMPLE: /* 32-bit compare */
2195 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2196 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2198 emit_ble(cd, iptr->dst.block);
2202 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2204 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2205 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2207 emit_bge_xcc(cd, iptr->dst.block);
2210 case ICMD_IF_ICMPGE: /* 32-bit compare */
2212 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2213 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2215 emit_bge(cd, iptr->dst.block);
2219 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2222 REPLACEMENT_POINT_RETURN(cd, iptr);
2224 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2225 M_INTMOVE(s1, REG_RESULT_CALLEE);
2226 goto nowperformreturn;
2228 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2230 REPLACEMENT_POINT_RETURN(cd, iptr);
2232 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2233 M_INTMOVE(s1, REG_RESULT_CALLEE);
2235 #ifdef ENABLE_VERIFIER
2236 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2237 unresolved_class *uc = iptr->sx.s23.s2.uc;
2239 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2241 #endif /* ENABLE_VERIFIER */
2242 goto nowperformreturn;
2244 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2247 REPLACEMENT_POINT_RETURN(cd, iptr);
2249 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2250 M_DBLMOVE(s1, REG_FRESULT);
2251 goto nowperformreturn;
2253 case ICMD_RETURN: /* ... ==> ... */
2255 REPLACEMENT_POINT_RETURN(cd, iptr);
2261 p = cd->stackframesize;
2263 #if !defined(NDEBUG)
2264 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2265 emit_verbosecall_exit(jd);
2268 #if defined(ENABLE_THREADS)
2269 if (checksync && code_is_synchronized(code)) {
2270 /* XXX jit-c-call */
2271 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2272 M_ALD(REG_ITMP3, REG_PV, disp);
2274 /* we need to save fp return value (int saved by window) */
2276 switch (iptr->opc) {
2279 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
2280 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2281 M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2283 /* restore the fp return value */
2285 M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
2291 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2292 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2303 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
2309 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2312 branch_target_t *table;
2314 table = iptr->dst.table;
2316 l = iptr->sx.s23.s2.tablelow;
2317 i = iptr->sx.s23.s3.tablehigh;
2319 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2321 M_INTMOVE(s1, REG_ITMP1);
2323 else if (-l >= 4096 && -l <= 4095) {
2324 M_ADD_IMM(s1, -l, REG_ITMP1);
2327 ICONST(REG_ITMP2, l);
2328 M_SUB(s1, REG_ITMP2, REG_ITMP1);
2331 i = i - l + 1; /* number of targets (>0) */
2337 M_CMP_IMM(REG_ITMP1, i - 1);
2340 ICONST(REG_ITMP2, i - 1);
2341 M_CMP(REG_ITMP1, REG_ITMP2);
2343 emit_bugt(cd, table[0].block); /* default target */
2345 /* build jump table top down and use address of lowest entry */
2350 dseg_add_target(cd, table->block);
2355 /* length of dataseg after last dseg_addtarget is used by load */
2357 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
2358 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2359 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2360 M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
2365 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2368 lookup_target_t *lookup;
2370 lookup = iptr->dst.lookup;
2372 i = iptr->sx.s23.s2.lookupcount;
2374 MCODECHECK((i<<2)+8);
2375 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2378 if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
2379 M_CMP_IMM(s1, lookup->value);
2381 ICONST(REG_ITMP2, lookup->value);
2382 M_CMP(s1, REG_ITMP2);
2384 emit_beq(cd, lookup->target.block);
2388 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2394 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
2396 REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
2398 bte = iptr->sx.s23.s3.bte;
2401 /* XXX: builtin calling with stack arguments not implemented */
2402 assert(md->paramcount <= 5 && md->argfltreguse <= 16);
2404 s3 = md->paramcount;
2406 MCODECHECK((s3 << 1) + 64);
2408 #ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
2410 /* copy float arguments according to ABI convention */
2412 int num_fltregargs = 0;
2413 int fltregarg_inswap[16];
2415 for (s3 = s3 - 1; s3 >= 0; s3--) {
2416 var = VAR(iptr->sx.s23.s2.args[s3]);
2418 if (IS_FLT_DBL_TYPE(var->type)) {
2419 if (!md->params[s3].inmemory) {
2420 s1 = s3; /*native flt args use argument index directly*/
2421 d = emit_load(jd, iptr, var, REG_FTMP1);
2424 fltregarg_inswap[num_fltregargs] = s1;
2426 /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
2435 /* move swapped float args to target regs */
2436 for (i = 0; i < num_fltregargs; i++) {
2437 s1 = fltregarg_inswap[i];
2438 M_DMOV(s1 + 16, s1);
2439 /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
2443 assert(md->argfltreguse == 0);
2448 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2449 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2450 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2451 case ICMD_INVOKEINTERFACE:
2453 REPLACEMENT_POINT_INVOKE(cd, iptr);
2455 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2457 um = iptr->sx.s23.s3.um;
2458 md = um->methodref->parseddesc.md;
2461 lm = iptr->sx.s23.s3.fmiref->p.method;
2463 md = lm->parseddesc;
2467 s3 = md->paramcount;
2469 MCODECHECK((s3 << 1) + 64);
2471 /* copy arguments to registers or stack location */
2473 for (s3 = s3 - 1; s3 >= 0; s3--) {
2474 var = VAR(iptr->sx.s23.s2.args[s3]);
2475 d = md->params[s3].regoff;
2477 if (var->flags & PREALLOC)
2480 if (IS_INT_LNG_TYPE(var->type)) {
2481 if (!md->params[s3].inmemory) {
2482 s1 = emit_load(jd, iptr, var, d);
2486 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2487 M_STX(s1, REG_SP, JITSTACK + d);
2491 #ifdef BUILTIN_FLOAT_ARGS
2492 if (iptr->opc == ICMD_BUILTIN)
2496 if (!md->params[s3].inmemory) {
2497 s1 = emit_load(jd, iptr, var, d);
2498 if (IS_2_WORD_TYPE(var->type))
2504 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2505 M_DST(s1, REG_SP, JITSTACK + d);
2510 switch (iptr->opc) {
2512 if (bte->stub == NULL) {
2513 disp = dseg_add_functionptr(cd, bte->fp);
2516 disp = dseg_add_functionptr(cd, bte->stub);
2519 M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
2521 /* XXX jit-c-call */
2522 /* generate the actual call */
2524 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2526 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2527 REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
2528 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2529 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2530 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2532 if (md->returntype.type == TYPE_FLT) {
2533 /* special handling for float return value in %f0 */
2538 case ICMD_INVOKESPECIAL:
2539 emit_nullpointer_check(cd, iptr, REG_OUT0);
2542 case ICMD_INVOKESTATIC:
2544 disp = dseg_add_unique_address(cd, NULL);
2546 codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
2550 disp = dseg_add_address(cd, lm->stubroutine);
2552 M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
2554 /* generate the actual call */
2556 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2558 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2559 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2560 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2561 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2564 case ICMD_INVOKEVIRTUAL:
2565 emit_nullpointer_check(cd, iptr, REG_OUT0);
2568 codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
2573 s1 = OFFSET(vftbl_t, table[0]) +
2574 sizeof(methodptr) * lm->vftblindex;
2576 /* implicit null-pointer check */
2577 M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
2578 M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
2580 /* generate the actual call */
2582 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2584 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2585 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2586 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2587 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2590 case ICMD_INVOKEINTERFACE:
2591 emit_nullpointer_check(cd, iptr, REG_OUT0);
2594 codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
2600 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2601 sizeof(methodptr*) * lm->clazz->index;
2603 s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
2606 /* implicit null-pointer check */
2607 M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
2608 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2609 M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
2611 /* generate the actual call */
2613 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2615 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2616 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2617 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2618 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2622 /* store return value */
2624 d = md->returntype.type;
2626 if (d != TYPE_VOID) {
2627 if (IS_INT_LNG_TYPE(d)) {
2628 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2629 M_INTMOVE(REG_RESULT_CALLER, s1);
2632 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2633 if (IS_2_WORD_TYPE(d)) {
2634 M_DBLMOVE(REG_FRESULT, s1);
2636 M_FLTMOVE(REG_FRESULT, s1);
2639 emit_store_dst(jd, iptr, s1);
2644 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2645 /* val.a: (classinfo*) superclass */
2647 /* superclass is an interface:
2649 * OK if ((sub == NULL) ||
2650 * (sub->vftbl->interfacetablelength > super->index) &&
2651 * (sub->vftbl->interfacetable[-super->index] != NULL));
2653 * superclass is a class:
2655 * OK if ((sub == NULL) || (0
2656 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2657 * super->vftbl->diffvall));
2660 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2664 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2669 super = iptr->sx.s23.s3.c.cls;
2670 superindex = super->index;
2673 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2675 /* if class is not resolved, check which code to call */
2677 if (super == NULL) {
2678 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2680 cr = iptr->sx.s23.s3.c.ref;
2681 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2683 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2686 M_ILD(REG_ITMP2, REG_PV, disp);
2687 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2688 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
2691 /* interface checkcast code */
2693 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2694 if (super == NULL) {
2695 cr = iptr->sx.s23.s3.c.ref;
2697 codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
2701 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2704 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2705 M_ILD(REG_ITMP3, REG_ITMP2,
2706 OFFSET(vftbl_t, interfacetablelength));
2707 M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
2708 emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
2710 M_ALD(REG_ITMP3, REG_ITMP2,
2711 OFFSET(vftbl_t, interfacetable[0]) -
2712 superindex * sizeof(methodptr*));
2713 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
2716 emit_label_br(cd, BRANCH_LABEL_4);
2718 emit_label(cd, BRANCH_LABEL_3);
2721 /* class checkcast code */
2723 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2724 if (super == NULL) {
2725 emit_label(cd, BRANCH_LABEL_2);
2727 cr = iptr->sx.s23.s3.c.ref;
2728 disp = dseg_add_unique_address(cd, NULL);
2730 codegen_add_patch_ref(cd,
2731 PATCHER_checkcast_instanceof_class,
2735 disp = dseg_add_address(cd, super->vftbl);
2737 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2740 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2741 M_ALD(REG_ITMP3, REG_PV, disp);
2743 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2744 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2745 M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2746 M_ALD(REG_ITMP3, REG_PV, disp);
2747 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2750 M_CMP(REG_ITMP3, REG_ITMP2);
2751 emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
2754 emit_label(cd, BRANCH_LABEL_5);
2757 if (super == NULL) {
2758 emit_label(cd, BRANCH_LABEL_1);
2759 emit_label(cd, BRANCH_LABEL_4);
2762 d = codegen_reg_of_dst(jd, iptr, s1);
2765 /* array type cast-check */
2767 s1 = emit_load_s1(jd, iptr, REG_OUT0);
2768 M_INTMOVE(s1, REG_OUT0);
2770 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2772 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2773 cr = iptr->sx.s23.s3.c.ref;
2774 disp = dseg_add_unique_address(cd, NULL);
2776 codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
2780 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2782 M_ALD(REG_OUT1, REG_PV, disp);
2783 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2784 M_ALD(REG_ITMP3, REG_PV, disp);
2785 /* XXX jit-c-call */
2786 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2789 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2790 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
2792 d = codegen_reg_of_dst(jd, iptr, s1);
2796 emit_store_dst(jd, iptr, d);
2799 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2800 /* val.a: (classinfo*) superclass */
2802 /* superclass is an interface:
2804 * return (sub != NULL) &&
2805 * (sub->vftbl->interfacetablelength > super->index) &&
2806 * (sub->vftbl->interfacetable[-super->index] != NULL);
2808 * superclass is a class:
2810 * return ((sub != NULL) && (0
2811 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2812 * super->vftbl->diffvall));
2817 vftbl_t *supervftbl;
2820 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2826 super = iptr->sx.s23.s3.c.cls;
2827 superindex = super->index;
2828 supervftbl = super->vftbl;
2831 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2832 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2834 M_MOV(s1, REG_ITMP1);
2840 /* if class is not resolved, check which code to call */
2842 if (super == NULL) {
2843 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2845 cr = iptr->sx.s23.s3.c.ref;
2846 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2848 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2851 M_ILD(REG_ITMP3, REG_PV, disp);
2852 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2853 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
2856 /* interface instanceof code */
2858 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2859 if (super == NULL) {
2860 cr = iptr->sx.s23.s3.c.ref;
2862 codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
2866 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2869 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2870 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2871 M_CMP_IMM(REG_ITMP3, superindex);
2874 M_ALD(REG_ITMP1, REG_ITMP1,
2875 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2876 superindex * sizeof(methodptr*)));
2877 M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
2880 emit_label_br(cd, BRANCH_LABEL_4);
2882 emit_label(cd, BRANCH_LABEL_3);
2885 /* class instanceof code */
2887 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2888 if (super == NULL) {
2889 emit_label(cd, BRANCH_LABEL_2);
2891 cr = iptr->sx.s23.s3.c.ref;
2892 disp = dseg_add_unique_address(cd, NULL);
2894 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
2898 disp = dseg_add_address(cd, supervftbl);
2900 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2903 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2904 M_ALD(REG_ITMP2, REG_PV, disp);
2906 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2907 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2908 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2910 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2911 M_CMP(REG_ITMP1, REG_ITMP2);
2912 M_XCMOVULE_IMM(1, d);
2915 emit_label(cd, BRANCH_LABEL_5);
2918 if (super == NULL) {
2919 emit_label(cd, BRANCH_LABEL_1);
2920 emit_label(cd, BRANCH_LABEL_4);
2923 emit_store_dst(jd, iptr, d);
2927 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2929 /* check for negative sizes and copy sizes to stack if necessary */
2931 MCODECHECK((iptr->s1.argcount << 1) + 64);
2933 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2935 var = VAR(iptr->sx.s23.s2.args[s1]);
2937 /* copy SAVEDVAR sizes to stack */
2939 /* Already Preallocated? */
2941 if (!(var->flags & PREALLOC)) {
2942 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2943 M_STX(s2, REG_SP, CSTACK + (s1 * 8));
2947 /* arg 0 = dimension count */
2949 ICONST(REG_OUT0, iptr->s1.argcount);
2951 /* is patcher function set? */
2953 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2954 disp = dseg_add_unique_address(cd, 0);
2956 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
2957 iptr->sx.s23.s3.c.ref,
2961 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2963 /* arg 1 = arraydescriptor */
2965 M_ALD(REG_OUT1, REG_PV, disp);
2967 /* arg 2 = pointer to dimensions = stack pointer (absolute) */
2969 M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
2971 /* XXX c abi call */
2972 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2973 M_ALD(REG_ITMP3, REG_PV, disp);
2974 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2977 /* check for exception before result assignment */
2979 emit_exception_check(cd, iptr);
2981 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2982 M_INTMOVE(REG_RESULT_CALLER, d);
2983 emit_store_dst(jd, iptr, d);
2987 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
2993 } /* for instruction */
2997 /* At the end of a basic block we may have to append some nops,
2998 because the patcher stub calling code might be longer than the
2999 actual instruction. So codepatching does not change the
3000 following block unintentionally. */
3002 if (cd->mcodeptr < cd->lastmcodeptr) {
3003 while (cd->mcodeptr < cd->lastmcodeptr) {
3008 } /* if (bptr -> flags >= BBREACHED) */
3009 } /* for basic block */
3011 /* generate stubs */
3013 emit_patcher_stubs(jd);
3015 /* everything's ok */
3021 /* codegen_emit_stub_compiler **************************************************
3023 Emits a stub routine which calls the compiler.
3025 *******************************************************************************/
3027 void codegen_emit_stub_compiler(jitdata *jd)
3032 /* get required compiler data */
3037 /* code for the stub */
3039 /* no window save yet, user caller's PV */
3040 M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */
3041 M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */
3042 M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */
3047 /* codegen_emit_stub_builtin ***************************************************
3049 Creates a stub routine which calls a builtin function.
3051 *******************************************************************************/
3053 void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
3062 /* get required compiler data */
3066 /* set some variables */
3069 /* calculate stack frame size */
3070 cd->stackframesize =
3074 sizeof(stackframeinfo_t) / SIZEOF_VOID_P +
3075 4; /* 4 arguments or return value */
3078 /* keep stack 16-byte aligned (ABI requirement) */
3080 if (cd->stackframesize & 1)
3081 cd->stackframesize++;
3083 /* create method header */
3084 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3085 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3086 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3087 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3088 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3090 /* generate stub code */
3091 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3093 #if defined(ENABLE_GC_CACAO)
3094 /* Save callee saved integer registers in stackframeinfo (GC may
3095 need to recover them during a collection). */
3097 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3098 OFFSET(stackframeinfo_t, intregs) + BIAS;
3100 for (i = 0; i < INT_SAV_CNT; i++)
3101 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3104 for (i = 0; i < md->paramcount; i++) {
3105 s1 = md->params[i].regoff;
3107 switch (md->paramtypes[i].type) {
3114 M_DST(s1, REG_SP, JITSTACK + i * 8);
3119 /* create dynamic stack info */
3121 M_AADD_IMM(REG_SP, BIAS + cd->stackframesize * 8, REG_OUT0); /* data sp*/
3122 M_MOV(REG_PV_CALLEE, REG_OUT1); /* PV */
3123 M_MOV(REG_FP, REG_OUT2); /* java sp */
3124 M_MOV(REG_RA_CALLEE, REG_OUT3); /* ra */
3126 disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
3127 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3128 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3129 M_NOP; /* XXX fill me! */
3132 /* builtins are allowed to have 5 arguments max */
3134 assert(md->paramcount <= 5);
3136 /* copy arguments into position */
3138 for (i = 0; i < md->paramcount; i++) {
3139 assert(!md->params[i].inmemory);
3141 s1 = md->params[i].regoff;
3143 switch (md->paramtypes[i].type) {
3147 M_MOV(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[i]), s1);
3151 M_DLD(s1, REG_SP, JITSTACK + i * 8);
3157 /* call the builtin function */
3159 disp = dseg_add_functionptr(cd, bte->fp);
3160 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); /* load adress of builtin */
3161 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call builtin */
3162 M_NOP; /* delay slot */
3165 /* save return value */
3167 if (md->returntype.type != TYPE_VOID) {
3168 if (IS_INT_LNG_TYPE(md->returntype.type))
3169 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3171 M_DST(REG_FRESULT, REG_SP, CSTACK);
3175 /* remove native stackframe info */
3177 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3178 disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
3179 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3180 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3183 /* restore float return value, int return value already in our return reg */
3185 if (md->returntype.type != TYPE_VOID) {
3186 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3187 if (IS_2_WORD_TYPE(md->returntype.type))
3188 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3190 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3195 #if defined(ENABLE_GC_CACAO)
3196 /* Restore callee saved integer registers from stackframeinfo (GC
3197 might have modified them during a collection). */
3199 disp = cd->stackframesize * 8 - sizeof(stackframeinfo_t) +
3200 OFFSET(stackframeinfo_t, intregs) + BIAS;
3202 for (i = 0; i < INT_SAV_CNT; i++)
3203 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3207 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3214 /* codegen_emit_stub_native ****************************************************
3216 Emits a stub routine which calls a native method.
3218 *******************************************************************************/
3220 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3227 s4 i, j; /* count variables */
3230 s4 funcdisp; /* displacement of the function */
3231 s4 fltregarg_offset[FLT_ARG_CNT];
3233 /* get required compiler data */
3239 /* initialize variables */
3242 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3244 /* calculate stack frame size */
3246 cd->stackframesize =
3247 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3248 sizeof(localref_table) / SIZEOF_VOID_P +
3249 md->paramcount + /* for saving arguments over calls */
3250 nmd->memuse + /* nmd->memuse includes the (6) abi params */
3254 /* keep stack 16-byte aligned (ABI requirement) */
3256 if (cd->stackframesize & 1)
3257 cd->stackframesize++;
3259 /* create method header */
3261 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3262 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3263 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3264 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3265 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3267 /* generate stub code */
3269 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3271 #if !defined(NDEBUG)
3272 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3273 emit_verbosecall_enter(jd);
3276 /* get function address (this must happen before the stackframeinfo) */
3278 funcdisp = dseg_add_functionptr(cd, f);
3281 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
3283 /* save float argument registers */
3285 assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
3287 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3288 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3289 s1 = WINSAVE_CNT + nmd->memuse + j;
3290 M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
3291 fltregarg_offset[i] = s1; /* remember stack offset */
3296 /* prepare data structures for native function call */
3298 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */
3299 M_MOV(REG_PV_CALLEE, REG_OUT1);
3300 M_MOV(REG_FP, REG_OUT2); /* java sp */
3301 M_MOV(REG_RA_CALLEE, REG_OUT3);
3302 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3303 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3304 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3305 M_NOP; /* XXX fill me! */
3307 /* remember class argument */
3309 if (m->flags & ACC_STATIC)
3310 M_MOV(REG_RESULT_CALLER, REG_ITMP3);
3312 /* keep float arguments on stack */
3314 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3315 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3316 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
3322 /* copy or spill arguments to new locations */
3324 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3325 t = md->paramtypes[i].type;
3327 if (IS_INT_LNG_TYPE(t)) {
3329 /* integral types */
3331 if (!md->params[i].inmemory) {
3332 s1 = md->params[i].regoff;
3333 /* s1 refers to the old window, transpose */
3334 s1 = REG_WINDOW_TRANSPOSE(s1);
3336 if (!nmd->params[j].inmemory) {
3337 s2 = nmd->params[j].regoff;
3340 /* nmd's regoff is relative to the start of the param array */
3341 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3342 M_AST(s1, REG_SP, s2);
3346 if (!nmd->params[j].inmemory) {
3347 /* JIT stack arg -> NAT reg arg */
3349 /* Due to the Env pointer that is always passed, the 6th JIT arg */
3350 /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */
3352 assert(false); /* path never taken */
3355 s1 = md->params[i].regoff + cd->stackframesize * 8;
3356 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3357 M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
3358 M_AST(REG_ITMP1, REG_SP, s2);
3363 /* floating point types */
3365 if (!md->params[i].inmemory) {
3366 s1 = md->params[i].regoff;
3368 if (!nmd->params[j].inmemory) {
3370 /* no mapping to regs needed, native flt args use regoff */
3371 s2 = nmd->params[j].regoff;
3373 /* JIT float regs are still on the stack */
3374 M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8));
3377 /* not supposed to happen with 16 NAT flt args */
3380 s2 = nmd->params[j].regoff;
3381 if (IS_2_WORD_TYPE(t))
3382 M_DST(s1, REG_SP, CSTACK + (s2 * 8));
3384 M_FST(s1, REG_SP, CSTACK + (s2 * 8));
3390 s1 = md->params[i].regoff;
3392 if (!nmd->params[j].inmemory) {
3394 /* JIT stack -> NAT reg */
3396 s2 = nmd->params[j].regoff;
3397 M_DLD(s2, REG_FP, JITSTACK + s1);
3401 /* JIT stack -> NAT stack */
3403 s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff;
3405 /* The FTMP register may already be loaded with args */
3406 /* we know $f0 is unused because of the env pointer */
3407 M_DLD(REG_F0, REG_FP, JITSTACK + s1);
3408 M_DST(REG_F0, REG_SP, BIAS + s2);
3415 /* put class into second argument register */
3417 if (m->flags & ACC_STATIC)
3418 M_MOV(REG_ITMP3, REG_OUT1);
3420 /* put env into first argument register */
3422 disp = dseg_add_address(cd, VM_get_jnienv());
3423 M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
3425 /* do the native function call */
3427 M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method */
3428 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method */
3429 M_NOP; /* delay slot */
3431 /* save return value */
3433 if (md->returntype.type != TYPE_VOID) {
3434 if (IS_INT_LNG_TYPE(md->returntype.type))
3435 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3437 M_DST(REG_FRESULT, REG_SP, CSTACK);
3440 /* Note: native functions return float values in %f0 (see ABI) */
3441 /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
3443 #if !defined(NDEBUG)
3444 /* But for the trace function we need to put a flt result into %f1 */
3445 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3446 if (!IS_2_WORD_TYPE(md->returntype.type))
3447 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3448 emit_verbosecall_exit(jd);
3452 /* remove native stackframe info */
3454 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3455 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3456 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3457 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3458 M_NOP; /* XXX fill me! */
3459 M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
3461 /* restore float return value, int return value already in our return reg */
3463 if (md->returntype.type != TYPE_VOID) {
3464 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3465 if (IS_2_WORD_TYPE(md->returntype.type))
3466 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3468 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3472 /* check for exception */
3473 M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
3476 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3479 /* handle exception */
3481 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3482 M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */
3483 M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */
3484 M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */
3485 M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
3487 /* generate patcher stubs */
3489 emit_patcher_stubs(jd);
3493 * These are local overrides for various environment variables in Emacs.
3494 * Please do not remove this and leave it at the end of the file, where
3495 * Emacs will automagically detect them.
3496 * ---------------------------------------------------------------------
3499 * indent-tabs-mode: t
3503 * vim:noexpandtab:sw=4:ts=4: