1 /* src/vm/jit/sparc64/codegen.c - machine code generator for Sparc
3 Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 $Id: codegen.c 4644 2006-03-16 18:44:46Z edwin $
40 /* #include "vm/jit/sparc64/arch.h" */
41 #include "vm/jit/sparc64/codegen.h"
43 #include "mm/memory.h"
45 #include "native/jni.h"
46 #include "native/localref.h"
47 #include "native/native.h"
48 #include "vm/builtin.h"
49 #include "vm/exceptions.h"
50 #include "vm/global.h"
52 #include "vm/jit/abi.h"
53 #include "vm/jit/asmpart.h"
54 #include "vm/jit/codegen-common.h"
55 #include "vm/jit/dseg.h"
56 #include "vm/jit/emit-common.h"
57 #include "vm/jit/sparc64/emit.h"
58 #include "vm/jit/jit.h"
59 #include "vm/jit/parse.h"
60 #include "vm/jit/patcher.h"
61 #include "vm/jit/reg.h"
62 #include "vm/jit/replace.h"
63 #include "vm/jit/stacktrace.h"
64 #include "vmcore/loader.h"
65 #include "vmcore/options.h"
67 #include "vm/jit/sparc64/solaris/macro_rename.h"
69 #define BUILTIN_FLOAT_ARGS 1
71 /* XXX use something like this for window control ?
72 * #define REG_PV (own_window?REG_PV_CALLEE:REG_PV_CALLER)
74 #define REG_PV REG_PV_CALLEE
79 if ((disp < -4096) || (disp > 4095))
80 printf("disp %d\n", disp);
83 return (disp >= -4096) && (disp <= 4095);
86 s4 get_lopart_disp(disp)
91 lodisp = setlo_part(disp);
93 if (setlo_part(disp) == 0)
96 lodisp = setlo_part(disp) | 0x1c00;
103 /* codegen_emit ****************************************************************
105 Generates machine code.
107 *******************************************************************************/
109 bool codegen_emit(jitdata *jd)
115 s4 len, s1, s2, s3, d, disp, slots;
121 constant_classref *cr;
122 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
123 unresolved_method *um;
124 builtintable_entry *bte;
127 unresolved_field *uf;
131 /* get required compiler data */
138 /* prevent compiler warnings */
149 #if 0 /* no leaf optimization yet */
150 savedregs_num = (jd->isleafmethod) ? 0 : 1; /* space to save the RA */
152 savedregs_num = WINSAVE_CNT + ABIPARAMS_CNT; /* register-window save area */
155 /* space to save used callee saved registers */
157 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
158 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
160 cd->stackframesize = rd->memuse + savedregs_num;
162 #if defined(ENABLE_THREADS) /* space to save argument of monitor_enter */
163 if (checksync && (m->flags & ACC_SYNCHRONIZED))
164 cd->stackframesize++;
167 /* keep stack 16-byte aligned (ABI requirement) */
169 if (cd->stackframesize & 1)
170 cd->stackframesize++;
172 /* create method header */
174 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
175 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
177 #if defined(ENABLE_THREADS)
178 /* IsSync contains the offset relative to the stack pointer for the
179 argument of monitor_exit used in the exception handler. Since the
180 offset could be zero and give a wrong meaning of the flag it is
184 if (checksync && (m->flags & ACC_SYNCHRONIZED))
185 (void) dseg_add_unique_s4(cd, JITSTACK + (rd->memuse + 1) * 8); /* IsSync */
188 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
190 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
191 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
192 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
193 dseg_addlinenumbertablesize(cd);
194 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
196 /* create exception table */
198 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
199 dseg_add_target(cd, ex->start);
200 dseg_add_target(cd, ex->end);
201 dseg_add_target(cd, ex->handler);
202 (void) dseg_add_unique_address(cd, ex->catchtype.any);
205 /* save register window and create stack frame (if necessary) */
207 if (cd->stackframesize)
208 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP);
211 /* save callee saved float registers (none right now) */
213 p = cd->stackframesize;
214 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
215 p--; M_DST(rd->savfltregs[i], REG_SP, USESTACK + (p * 8));
220 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
221 emit_verbosecall_enter(jd);
225 /* call monitorenter function */
226 #if defined(ENABLE_THREADS)
227 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
228 /* stack offset for monitor argument */
232 /* save float argument registers */
236 ALIGN_STACK_SLOTS(slots);
238 M_LDA(REG_SP, REG_SP, -(slots * 8));
239 for (i = 0; i < FLT_ARG_CNT; i++)
240 M_DST(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
244 /* get correct lock object */
246 if (m->flags & ACC_STATIC) {
247 disp = dseg_add_address(cd, &m->class->object.header);
248 M_ALD(REG_OUT0, REG_PV, disp);
249 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
250 M_ALD(REG_ITMP3, REG_PV, disp);
253 /* copy class pointer: $i0 -> $o0 */
254 M_MOV(REG_RESULT_CALLEE, REG_OUT0);
256 disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
257 M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
258 M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
261 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
262 M_AST(REG_OUT0, REG_SP, CSTACK + s1 * 8); /* branch delay */
264 /* restore float argument registers */
266 for (i = 0; i < FLT_ARG_CNT; i++)
267 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + i * 8);
269 M_LDA(REG_SP, REG_SP, slots * 8);
274 /* take arguments out of register or stack frame */
278 for (p = 0, l = 0; p < md->paramcount; p++) {
279 t = md->paramtypes[p].type;
281 varindex = jd->local_map[l * 5 + t];
284 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
287 if (varindex == UNUSED)
291 s1 = md->params[p].regoff;
293 if (IS_INT_LNG_TYPE(t)) { /* integer args */
297 if (!md->params[p].inmemory) { /* register arguments */
298 s1 = REG_WINDOW_TRANSPOSE(s1);
300 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
302 /* the register allocator does not know about the window. */
303 /* avoid copying the locals from save to save regs by */
304 /* swapping variables. */
307 int old_dest = var->vv.regoff;
308 int new_dest = p + 24;
310 /* run through all variables */
312 for (i = 0; i < jd->varcount; i++) {
313 varinfo* uvar = VAR(i);
315 if (IS_FLT_DBL_TYPE(uvar->type) || IS_INMEMORY(uvar->flags))
318 s2 = uvar->vv.regoff;
320 /* free the in reg by moving all other references */
322 if (s2 == new_dest) {
323 uvar->vv.regoff = old_dest;
324 /*printf("p%d-var[%d]: moved %d -> %d (to free save reg)\n", p, i, s2, old_dest);*/
327 /* move all variables to the in reg */
329 if (s2 == old_dest) {
330 uvar->vv.regoff = new_dest;
331 /*printf("p%d-var[%d]: moved %d -> %d (to avoid copy)\n", p, i, s2, new_dest);*/
339 else { /* reg arg -> spilled */
340 M_STX(s1, REG_SP, JITSTACK + var->vv.regoff);
343 } else { /* stack arguments */
344 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
345 M_LDX(var->vv.regoff, REG_FP, JITSTACK + s1);
347 } else { /* stack arg -> spilled */
348 /* add the callers window save registers */
349 var->vv.regoff = cd->stackframesize * 8 + s1;
353 } else { /* floating args */
354 if (!md->params[p].inmemory) { /* register arguments */
355 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
356 M_FLTMOVE(s1, var->vv.regoff);
358 } else { /* reg arg -> spilled */
359 M_DST(s1, REG_SP, JITSTACK + var->vv.regoff);
362 } else { /* stack arguments */
363 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
364 M_DLD(var->vv.regoff, REG_FP, JITSTACK + s1);
366 } else { /* stack-arg -> spilled */
367 var->vv.regoff = cd->stackframesize * 8 + s1;
376 /* end of header generation */
378 /* create replacement points */
380 REPLACEMENT_POINTS_INIT(cd, jd);
382 /* walk through all basic blocks */
384 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
386 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
388 if (bptr->flags >= BBREACHED) {
390 /* branch resolving */
392 codegen_resolve_branchrefs(cd, bptr);
394 /* handle replacement points */
396 REPLACEMENT_POINT_BLOCK_START(cd, bptr);
399 /* copy interface registers to their destination */
404 #if defined(ENABLE_LSRA)
405 #error XXX LSRA not tested yet
409 src = bptr->invars[len];
410 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
411 /* d = reg_of_var(m, src, REG_ITMP1); */
412 if (!(src->flags & INMEMORY))
416 M_INTMOVE(REG_ITMP1, d);
417 emit_store(jd, NULL, src, d);
424 var = VAR(bptr->invars[len]);
425 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
426 d = codegen_reg_of_var(0, var, REG_ITMP1);
427 M_INTMOVE(REG_ITMP2_XPTR, d);
428 emit_store(jd, NULL, var, d);
431 assert((var->flags & INOUT));
434 #if defined(ENABLE_LSRA)
437 /* walk through all instructions */
441 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
442 if (iptr->line != currentline) {
443 dseg_addlinenumber(cd, iptr->line);
444 currentline = iptr->line;
447 MCODECHECK(64); /* an instruction usually needs < 64 words */
451 case ICMD_INLINE_START:
452 case ICMD_INLINE_END:
455 case ICMD_NOP: /* ... ==> ... */
458 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
460 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
461 emit_nullpointer_check(cd, iptr, s1);
464 /* constant operations ************************************************/
466 case ICMD_ICONST: /* ... ==> ..., constant */
468 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
469 ICONST(d, iptr->sx.val.i);
470 emit_store_dst(jd, iptr, d);
473 case ICMD_LCONST: /* ... ==> ..., constant */
475 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
476 LCONST(d, iptr->sx.val.l);
477 emit_store_dst(jd, iptr, d);
480 case ICMD_FCONST: /* ... ==> ..., constant */
482 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
483 disp = dseg_add_float(cd, iptr->sx.val.f);
484 M_FLD(d, REG_PV, disp);
485 emit_store_dst(jd, iptr, d);
488 case ICMD_DCONST: /* ... ==> ..., constant */
490 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
491 disp = dseg_add_double(cd, iptr->sx.val.d);
492 M_DLD(d, REG_PV, disp);
493 emit_store_dst(jd, iptr, d);
496 case ICMD_ACONST: /* ... ==> ..., constant */
498 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
500 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
501 cr = iptr->sx.val.c.ref;
502 disp = dseg_add_unique_address(cd, cr);
504 codegen_add_patch_ref(cd, PATCHER_aconst, cr, disp);
506 M_ALD(d, REG_PV, disp);
510 if (iptr->sx.val.anyptr == NULL) {
511 M_INTMOVE(REG_ZERO, d);
514 disp = dseg_add_address(cd, iptr->sx.val.anyptr);
515 M_ALD(d, REG_PV, disp);
518 emit_store_dst(jd, iptr, d);
522 /* load/store/copy/move operations ************************************/
524 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
529 case ICMD_ISTORE: /* ..., value ==> ... */
540 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
545 /* pop/dup/swap operations ********************************************/
547 /* attention: double and longs are only one entry in CACAO ICMDs */
549 case ICMD_POP: /* ..., value ==> ... */
550 case ICMD_POP2: /* ..., value, value ==> ... */
554 /* integer operations *************************************************/
556 case ICMD_INEG: /* ..., value ==> ..., - value */
559 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
560 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
561 M_SUB(REG_ZERO, s1, d);
562 emit_store_dst(jd, iptr, d);
565 case ICMD_I2L: /* ..., value ==> ..., value */
567 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
568 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
570 emit_store_dst(jd, iptr, d);
573 case ICMD_L2I: /* ..., value ==> ..., value */
575 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
576 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
577 M_SRA_IMM(s1, 0, d); /* sign extend upper 32 bits */
578 emit_store_dst(jd, iptr, d);
581 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
583 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
584 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
585 M_SLLX_IMM(s1, 56, d);
586 M_SRAX_IMM( d, 56, d);
587 emit_store_dst(jd, iptr, d);
590 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
592 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
593 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
594 M_SLLX_IMM(s1, 48, d);
595 M_SRLX_IMM( d, 48, d);
596 emit_store_dst(jd, iptr, d);
599 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
601 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
602 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
603 M_SLLX_IMM(s1, 48, d);
604 M_SRAX_IMM( d, 48, d);
605 emit_store_dst(jd, iptr, d);
608 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
611 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
612 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
613 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
615 emit_store_dst(jd, iptr, d);
619 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
620 /* sx.val.i = constant */
622 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
623 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
624 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
625 M_ADD_IMM(s1, iptr->sx.val.i, d);
627 ICONST(REG_ITMP2, iptr->sx.val.i);
628 M_ADD(s1, REG_ITMP2, d);
630 emit_store_dst(jd, iptr, d);
633 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
634 /* sx.val.l = constant */
636 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
637 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
638 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
639 M_ADD_IMM(s1, iptr->sx.val.l, d);
641 LCONST(REG_ITMP2, iptr->sx.val.l);
642 M_ADD(s1, REG_ITMP2, d);
644 emit_store_dst(jd, iptr, d);
647 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
650 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
651 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
652 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
654 emit_store_dst(jd, iptr, d);
657 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
658 /* sx.val.i = constant */
660 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
661 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
662 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
663 M_SUB_IMM(s1, iptr->sx.val.i, d);
665 ICONST(REG_ITMP2, iptr->sx.val.i);
666 M_SUB(s1, REG_ITMP2, d);
668 emit_store_dst(jd, iptr, d);
671 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
672 /* sx.val.l = constant */
674 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
675 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
676 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
677 M_SUB_IMM(s1, iptr->sx.val.l, d);
679 LCONST(REG_ITMP2, iptr->sx.val.l);
680 M_SUB(s1, REG_ITMP2, d);
682 emit_store_dst(jd, iptr, d);
685 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
688 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
689 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
690 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
692 emit_store_dst(jd, iptr, d);
695 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
696 /* sx.val.i = constant */
698 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
699 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
700 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
701 M_MULX_IMM(s1, iptr->sx.val.i, d);
703 ICONST(REG_ITMP2, iptr->sx.val.i);
704 M_MULX(s1, REG_ITMP2, d);
706 emit_store_dst(jd, iptr, d);
709 case ICMD_LMULCONST: /* ..., value ==> ..., value * constant */
710 /* sx.val.l = constant */
712 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
713 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
714 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
715 M_MULX_IMM(s1, iptr->sx.val.l, d);
717 LCONST(REG_ITMP2, iptr->sx.val.l);
718 M_MULX(s1, REG_ITMP2, d);
720 emit_store_dst(jd, iptr, d);
723 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
724 /* XXX could also clear Y and use 32bit div */
725 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
726 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
727 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
728 emit_arithmetic_check(cd, iptr, s2);
730 /* XXX trim s2 like s1 ? */
732 emit_store_dst(jd, iptr, d);
735 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
737 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
738 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
739 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
740 emit_arithmetic_check(cd, iptr, s2);
742 emit_store_dst(jd, iptr, d);
745 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
747 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
748 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
749 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
750 emit_arithmetic_check(cd, iptr, s2);
752 /* XXX trim s2 like s1 ? */
753 M_DIVX(s1, s2, REG_ITMP3);
754 M_MULX(s2, REG_ITMP3, REG_ITMP3);
755 M_SUB(s1, REG_ITMP3, d);
756 emit_store_dst(jd, iptr, d);
759 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
761 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
762 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
763 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
764 emit_arithmetic_check(cd, iptr, s2);
765 M_DIVX(s1, s2, REG_ITMP3);
766 M_MULX(s2, REG_ITMP3, REG_ITMP3);
767 M_SUB(s1, REG_ITMP3, d);
768 emit_store_dst(jd, iptr, d);
771 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
772 case ICMD_LDIVPOW2: /* val.i = constant */
774 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
775 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
776 M_SRAX_IMM(s1, 63, REG_ITMP2);
777 M_SRLX_IMM(REG_ITMP2, 64 - iptr->sx.val.i, REG_ITMP2);
778 M_ADD(s1, REG_ITMP2, REG_ITMP2);
779 M_SRAX_IMM(REG_ITMP2, iptr->sx.val.i, d);
780 emit_store_dst(jd, iptr, d);
783 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
785 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
786 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
787 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
789 emit_store_dst(jd, iptr, d);
792 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
794 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
795 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
796 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
798 emit_store_dst(jd, iptr, d);
801 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
802 /* val.i = constant */
804 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
805 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
806 M_SLL_IMM(s1, iptr->sx.val.i, d);
807 emit_store_dst(jd, iptr, d);
810 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
811 /* val.i = constant */
813 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
814 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
815 M_SLLX_IMM(s1, iptr->sx.val.i, d);
816 emit_store_dst(jd, iptr, d);
819 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
821 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
822 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
823 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
825 emit_store_dst(jd, iptr, d);
828 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
829 /* sx.val.i = constant */
831 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
832 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
833 M_SRA_IMM(s1, iptr->sx.val.i, d);
834 emit_store_dst(jd, iptr, d);
837 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
839 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
840 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
841 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
843 emit_store_dst(jd, iptr, d);
846 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
847 /* sx.val.i = constant */
849 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
850 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
851 M_SRL_IMM(s1, iptr->sx.val.i, d);
852 emit_store_dst(jd, iptr, d);
855 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
857 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
858 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
859 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
861 emit_store_dst(jd, iptr, d);
864 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
865 /* sx.val.i = constant */
867 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
868 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
869 M_SRAX_IMM(s1, iptr->sx.val.i, d);
870 emit_store_dst(jd, iptr, d);
873 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
875 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
876 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
877 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
879 emit_store_dst(jd, iptr, d);
882 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
883 /* sx.val.i = constant */
885 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
886 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
887 M_SRLX_IMM(s1, iptr->sx.val.i, d);
888 emit_store_dst(jd, iptr, d);
891 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
894 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
895 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
896 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
898 emit_store_dst(jd, iptr, d);
901 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
902 /* sx.val.i = constant */
904 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
905 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
906 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
907 M_AND_IMM(s1, iptr->sx.val.i, d);
909 ICONST(REG_ITMP2, iptr->sx.val.i);
910 M_AND(s1, REG_ITMP2, d);
912 emit_store_dst(jd, iptr, d);
915 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
916 /* sx.val.i = constant */
917 /* constant is actually constant - 1 */
919 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
920 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
922 M_MOV(s1, REG_ITMP1);
925 M_ISEXT(s1, s1); /* trim for 32-bit compare (BGEZ) */
926 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 4095)) {
927 M_AND_IMM(s1, iptr->sx.val.i, d);
930 M_SUB(REG_ZERO, s1, d);
931 M_AND_IMM(d, iptr->sx.val.i, d);
933 ICONST(REG_ITMP2, iptr->sx.val.i);
934 M_AND(s1, REG_ITMP2, d);
937 M_SUB(REG_ZERO, s1, d);
938 M_AND(d, REG_ITMP2, d);
940 M_SUB(REG_ZERO, d, d);
941 emit_store_dst(jd, iptr, d);
944 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
945 /* sx.val.l = constant */
947 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
948 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
949 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
950 M_AND_IMM(s1, iptr->sx.val.l, d);
952 LCONST(REG_ITMP2, iptr->sx.val.l);
953 M_AND(s1, REG_ITMP2, d);
955 emit_store_dst(jd, iptr, d);
958 case ICMD_LREMPOW2: /* ..., value ==> ..., value % constant */
959 /* sx.val.l = constant */
961 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
962 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
964 M_MOV(s1, REG_ITMP1);
967 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
968 M_AND_IMM(s1, iptr->sx.val.l, d);
971 M_SUB(REG_ZERO, s1, d);
972 M_AND_IMM(d, iptr->sx.val.l, d);
974 LCONST(REG_ITMP2, iptr->sx.val.l);
975 M_AND(s1, REG_ITMP2, d);
978 M_SUB(REG_ZERO, s1, d);
979 M_AND(d, REG_ITMP2, d);
981 M_SUB(REG_ZERO, d, d);
982 emit_store_dst(jd, iptr, d);
985 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
988 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
989 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
990 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
992 emit_store_dst(jd, iptr, d);
995 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
996 /* sx.val.i = constant */
998 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
999 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1000 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1001 M_OR_IMM(s1, iptr->sx.val.i, d);
1003 ICONST(REG_ITMP2, iptr->sx.val.i);
1004 M_OR(s1, REG_ITMP2, d);
1006 emit_store_dst(jd, iptr, d);
1009 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1010 /* sx.val.l = constant */
1012 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1013 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1014 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1015 M_OR_IMM(s1, iptr->sx.val.l, d);
1017 LCONST(REG_ITMP2, iptr->sx.val.l);
1018 M_OR(s1, REG_ITMP2, d);
1020 emit_store_dst(jd, iptr, d);
1023 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1026 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1027 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1028 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1030 emit_store_dst(jd, iptr, d);
1033 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1034 /* sx.val.i = constant */
1036 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1037 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1038 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1039 M_XOR_IMM(s1, iptr->sx.val.i, d);
1041 ICONST(REG_ITMP2, iptr->sx.val.i);
1042 M_XOR(s1, REG_ITMP2, d);
1044 emit_store_dst(jd, iptr, d);
1047 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1048 /* sx.val.l = constant */
1050 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1051 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1052 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
1053 M_XOR_IMM(s1, iptr->sx.val.l, d);
1055 LCONST(REG_ITMP2, iptr->sx.val.l);
1056 M_XOR(s1, REG_ITMP2, d);
1058 emit_store_dst(jd, iptr, d);
1062 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1064 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1065 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1066 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1069 M_XCMOVLT_IMM(-1, d);
1070 M_XCMOVGT_IMM(1, d);
1071 emit_store_dst(jd, iptr, d);
1075 /* floating operations ************************************************/
1077 case ICMD_FNEG: /* ..., value ==> ..., - value */
1079 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1080 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1082 emit_store_dst(jd, iptr, d);
1085 case ICMD_DNEG: /* ..., value ==> ..., - value */
1087 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1088 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1090 emit_store_dst(jd, iptr, d);
1093 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1095 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1096 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1097 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1099 emit_store_dst(jd, iptr, d);
1102 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1104 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1105 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1106 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1108 emit_store_dst(jd, iptr, d);
1111 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1113 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1114 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1115 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1117 emit_store_dst(jd, iptr, d);
1120 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1122 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1123 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1124 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1126 emit_store_dst(jd, iptr, d);
1129 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1131 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1132 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1133 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1135 emit_store_dst(jd, iptr, d);
1138 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1140 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1141 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1142 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1144 emit_store_dst(jd, iptr, d);
1147 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1149 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1150 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1151 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1153 emit_store_dst(jd, iptr, d);
1156 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1158 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1159 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1160 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1162 emit_store_dst(jd, iptr, d);
1166 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1167 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1168 disp = dseg_add_unique_float(cd, 0.0);
1169 M_IST (s1, REG_PV_CALLEE, disp);
1170 M_FLD (d, REG_PV_CALLEE, disp);
1171 M_CVTIF (d, d); /* rd gets translated to double target register */
1172 emit_store_dst(jd, iptr, d);
1176 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1177 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1178 disp = dseg_add_unique_float(cd, 0.0);
1179 M_IST(s1, REG_PV_CALLEE, disp);
1180 M_FLD(REG_FTMP2, REG_PV_CALLEE, disp); /* REG_FTMP2 needs to be a double temp */
1181 M_CVTID (REG_FTMP2, d); /* rd gets translated to double target register */
1182 emit_store_dst(jd, iptr, d);
1186 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1187 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1188 disp = dseg_add_unique_double(cd, 0.0);
1189 M_STX(s1, REG_PV_CALLEE, disp);
1190 M_DLD(REG_FTMP3, REG_PV_CALLEE, disp);
1191 M_CVTLF(REG_FTMP3, d);
1192 emit_store_dst(jd, iptr, d);
1196 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1197 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1198 disp = dseg_add_unique_double(cd, 0.0);
1199 M_STX(s1, REG_PV_CALLEE, disp);
1200 M_DLD(d, REG_PV_CALLEE, disp);
1202 emit_store_dst(jd, iptr, d);
1205 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1206 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1207 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1208 disp = dseg_add_unique_float(cd, 0.0);
1210 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1213 M_MOV(REG_ZERO, d); /* delay slot */
1215 M_CVTFI(s1, REG_FTMP2);
1216 M_FST(REG_FTMP2, REG_PV_CALLEE, disp);
1217 M_ILD(d, REG_PV, disp);
1218 emit_store_dst(jd, iptr, d);
1222 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1223 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1224 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1225 disp = dseg_add_unique_float(cd, 0.0);
1227 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1230 M_MOV(REG_ZERO, d); /* delay slot */
1232 M_CVTDI(s1, REG_FTMP2);
1233 M_FST(REG_FTMP2, REG_PV, disp);
1234 M_ILD(d, REG_PV, disp);
1235 emit_store_dst(jd, iptr, d);
1238 case ICMD_F2L: /* ..., value ==> ..., (long) value */
1239 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1240 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1241 disp = dseg_add_unique_double(cd, 0.0);
1243 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1246 M_MOV(REG_ZERO, d); /* delay slot */
1248 M_CVTFL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1249 M_DST(REG_FTMP2, REG_PV, disp);
1250 M_LDX(d, REG_PV, disp);
1251 emit_store_dst(jd, iptr, d);
1254 case ICMD_D2L: /* ..., value ==> ..., (long) value */
1255 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1256 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1257 disp = dseg_add_unique_double(cd, 0.0);
1259 /* check for NaN, SPARC overflow is noncompliant (see V9 spec B.5) */
1262 M_MOV(REG_ZERO, d); /* delay slot */
1264 M_CVTDL(s1, REG_FTMP2); /* FTMP2 needs to be double reg */
1265 M_DST(REG_FTMP2, REG_PV, disp);
1266 M_LDX(d, REG_PV, disp);
1267 emit_store_dst(jd, iptr, d);
1270 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1272 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1273 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1275 emit_store_dst(jd, iptr, d);
1278 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1280 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1281 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1283 emit_store_dst(jd, iptr, d);
1286 /* XXX merge F/D versions? only compare instr. is different */
1287 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1289 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1290 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1291 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1293 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1294 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1295 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1296 emit_store_dst(jd, iptr, d);
1299 case ICMD_DCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1301 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1302 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1303 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1305 M_OR_IMM(REG_ZERO, -1, d); /* less by default (less or unordered) */
1306 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1307 M_CMOVFGT_IMM(1, d); /* 1 if greater */
1308 emit_store_dst(jd, iptr, d);
1311 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1313 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1314 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1315 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1317 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1318 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1319 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1320 emit_store_dst(jd, iptr, d);
1323 case ICMD_DCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1325 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1326 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1327 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1329 M_OR_IMM(REG_ZERO, 1, d); /* greater by default (greater or unordered) */
1330 M_CMOVFEQ_IMM(0, d); /* 0 if equal */
1331 M_CMOVFLT_IMM(-1, d); /* -1 if less */
1332 emit_store_dst(jd, iptr, d);
1336 /* memory operations **************************************************/
1338 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1340 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1341 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1342 emit_nullpointer_check(cd, iptr, s1);
1343 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1344 emit_store_dst(jd, iptr, d);
1347 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1349 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1350 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1351 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1352 /* implicit null-pointer check */
1353 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1354 M_AADD(s2, s1, REG_ITMP3);
1355 M_BLDS(d, REG_ITMP3, OFFSET(java_bytearray, data[0]));
1356 emit_store_dst(jd, iptr, d);
1359 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1361 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1362 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1363 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1364 /* implicit null-pointer check */
1365 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1366 M_AADD(s2, s1, REG_ITMP3);
1367 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1368 M_SLDU(d, REG_ITMP3, OFFSET(java_chararray, data[0]));
1369 emit_store_dst(jd, iptr, d);
1372 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1374 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1375 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1376 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1377 /* implicit null-pointer check */
1378 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1379 M_AADD(s2, s1, REG_ITMP3);
1380 M_AADD(s2, REG_ITMP3, REG_ITMP3);
1381 M_SLDS(d, REG_ITMP3, OFFSET(java_shortarray, data[0]));
1382 emit_store_dst(jd, iptr, d);
1385 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1387 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1388 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1389 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1390 /* implicit null-pointer check */
1391 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1392 M_ASLL_IMM(s2, 2, REG_ITMP3);
1393 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1394 M_ILD(d, REG_ITMP3, OFFSET(java_intarray, data[0]));
1395 emit_store_dst(jd, iptr, d);
1398 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1400 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1401 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1402 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1403 /* implicit null-pointer check */
1404 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1405 M_ASLL_IMM(s2, 3, REG_ITMP3);
1406 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1407 M_LDX(d, REG_ITMP3, OFFSET(java_longarray, data[0]));
1408 emit_store_dst(jd, iptr, d);
1411 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1413 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1414 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1415 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1416 /* implicit null-pointer check */
1417 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1418 M_ASLL_IMM(s2, 2, REG_ITMP3);
1419 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1420 M_FLD(d, REG_ITMP3, OFFSET(java_floatarray, data[0]));
1421 emit_store_dst(jd, iptr, d);
1424 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1426 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1427 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1428 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1429 /* implicit null-pointer check */
1430 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1431 M_ASLL_IMM(s2, 3, REG_ITMP3);
1432 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1433 M_DLD(d, REG_ITMP3, OFFSET(java_doublearray, data[0]));
1434 emit_store_dst(jd, iptr, d);
1437 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1439 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1440 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1441 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1442 /* implicit null-pointer check */
1443 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1444 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP3);
1445 M_AADD(REG_ITMP3, s1, REG_ITMP3);
1446 M_ALD(d, REG_ITMP3, OFFSET(java_objectarray, data[0]));
1447 emit_store_dst(jd, iptr, d);
1451 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1453 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1454 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1455 /* implicit null-pointer check */
1456 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1457 M_AADD(s2, s1, REG_ITMP1);
1458 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1459 M_BST(s3, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1462 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1463 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1465 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1466 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1467 /* implicit null-pointer check */
1468 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1469 M_AADD(s2, s1, REG_ITMP1);
1470 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1471 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1472 M_SST(s3, REG_ITMP1, OFFSET(java_chararray, data[0]));
1475 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1477 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1478 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1479 /* implicit null-pointer check */
1480 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1481 M_ASLL_IMM(s2, 2, REG_ITMP2);
1482 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1483 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1484 M_IST_INTERN(s3, REG_ITMP1, OFFSET(java_intarray, data[0]));
1487 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1489 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1490 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1491 /* implicit null-pointer check */
1492 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1493 M_ASLL_IMM(s2, 3, REG_ITMP2);
1494 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1495 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1496 M_STX_INTERN(s3, REG_ITMP1, OFFSET(java_longarray, data[0]));
1499 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1501 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1502 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1503 /* implicit null-pointer check */
1504 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1505 M_ASLL_IMM(s2, 2, REG_ITMP2);
1506 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1507 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1508 M_FST_INTERN(s3, REG_ITMP1, OFFSET(java_floatarray, data[0]));
1511 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1513 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1514 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1515 /* implicit null-pointer check */
1516 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1517 M_ASLL_IMM(s2, 3, REG_ITMP2);
1518 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1519 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1520 M_DST_INTERN(s3, REG_ITMP1, OFFSET(java_doublearray, data[0]));
1524 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1526 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1527 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1528 /* implicit null-pointer check */
1529 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1530 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1532 M_MOV(s1, REG_OUT0);
1533 M_MOV(s3, REG_OUT1);
1534 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1535 M_ALD(REG_ITMP3, REG_PV, disp);
1536 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
1538 emit_exception_check(cd, iptr);
1540 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1541 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1542 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1543 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1544 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1545 /* implicit null-pointer check */
1546 M_AST_INTERN(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1550 case ICMD_BASTORECONST: /* ..., arrayref, index ==> ... */
1552 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1553 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1554 /* implicit null-pointer check */
1555 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1556 M_AADD(s2, s1, REG_ITMP1);
1557 M_BST(REG_ZERO, REG_ITMP1, OFFSET(java_bytearray, data[0]));
1560 case ICMD_CASTORECONST: /* ..., arrayref, index ==> ... */
1561 case ICMD_SASTORECONST: /* ..., arrayref, index ==> ... */
1563 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1564 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1565 /* implicit null-pointer check */
1566 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1567 M_AADD(s2, s1, REG_ITMP1);
1568 M_AADD(s2, REG_ITMP1, REG_ITMP1);
1569 M_SST(REG_ZERO, REG_ITMP1, OFFSET(java_chararray, data[0]));
1572 case ICMD_IASTORECONST: /* ..., arrayref, index ==> ... */
1574 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1575 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1576 /* implicit null-pointer check */
1577 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1578 M_ASLL_IMM(s2, 2, REG_ITMP2);
1579 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1580 M_IST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_intarray, data[0]));
1583 case ICMD_LASTORECONST: /* ..., arrayref, index ==> ... */
1585 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1586 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1587 /* implicit null-pointer check */
1588 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1589 M_ASLL_IMM(s2, 3, REG_ITMP2);
1590 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1591 M_STX_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_longarray, data[0]));
1594 case ICMD_AASTORECONST: /* ..., arrayref, index ==> ... */
1596 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1597 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1598 /* implicit null-pointer check */
1599 emit_arrayindexoutofbounds_check(cd, iptr, s1, s2);
1600 M_ASLL_IMM(s2, POINTERSHIFT, REG_ITMP2);
1601 M_AADD(REG_ITMP2, s1, REG_ITMP1);
1602 M_AST_INTERN(REG_ZERO, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1606 case ICMD_GETSTATIC: /* ... ==> ..., value */
1608 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1609 uf = iptr->sx.s23.s3.uf;
1610 fieldtype = uf->fieldref->parseddesc.fd->type;
1611 disp = dseg_add_unique_address(cd, uf);
1613 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1616 fi = iptr->sx.s23.s3.fmiref->p.field;
1617 fieldtype = fi->type;
1618 disp = dseg_add_address(cd, fi->value);
1620 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1621 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1624 M_ALD(REG_ITMP1, REG_PV, disp);
1626 switch (fieldtype) {
1628 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1629 M_ILD_INTERN(d, REG_ITMP1, 0);
1632 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1633 M_LDX_INTERN(d, REG_ITMP1, 0);
1636 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1637 M_ALD_INTERN(d, REG_ITMP1, 0);
1640 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1641 M_FLD_INTERN(d, REG_ITMP1, 0);
1644 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1645 M_DLD_INTERN(d, REG_ITMP1, 0);
1648 emit_store_dst(jd, iptr, d);
1651 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1653 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1654 uf = iptr->sx.s23.s3.uf;
1655 fieldtype = uf->fieldref->parseddesc.fd->type;
1656 disp = dseg_add_unique_address(cd, uf);
1658 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1661 fi = iptr->sx.s23.s3.fmiref->p.field;
1662 fieldtype = fi->type;
1663 disp = dseg_add_address(cd, fi->value);
1665 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1666 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1669 M_ALD(REG_ITMP1, REG_PV, disp);
1671 switch (fieldtype) {
1673 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1674 M_IST_INTERN(s1, REG_ITMP1, 0);
1677 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1678 M_STX_INTERN(s1, REG_ITMP1, 0);
1681 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1682 M_AST_INTERN(s1, REG_ITMP1, 0);
1685 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1686 M_FST_INTERN(s1, REG_ITMP1, 0);
1689 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1690 M_DST_INTERN(s1, REG_ITMP1, 0);
1695 case ICMD_PUTSTATICCONST: /* ... ==> ... */
1696 /* val = value (in current instruction) */
1697 /* following NOP) */
1699 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1700 uf = iptr->sx.s23.s3.uf;
1701 fieldtype = uf->fieldref->parseddesc.fd->type;
1702 disp = dseg_add_unique_address(cd, uf);
1704 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1707 fi = iptr->sx.s23.s3.fmiref->p.field;
1708 fieldtype = fi->type;
1709 disp = dseg_add_address(cd, fi->value);
1711 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1712 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
1715 M_ALD(REG_ITMP1, REG_PV, disp);
1717 switch (fieldtype) {
1719 M_IST_INTERN(REG_ZERO, REG_ITMP1, 0);
1722 M_STX_INTERN(REG_ZERO, REG_ITMP1, 0);
1725 M_AST_INTERN(REG_ZERO, REG_ITMP1, 0);
1728 M_FST_INTERN(REG_ZERO, REG_ITMP1, 0);
1731 M_DST_INTERN(REG_ZERO, REG_ITMP1, 0);
1737 case ICMD_GETFIELD: /* ... ==> ..., value */
1739 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1740 emit_nullpointer_check(cd, iptr, s1);
1742 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1743 uf = iptr->sx.s23.s3.uf;
1745 fieldtype = uf->fieldref->parseddesc.fd->type;
1748 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1751 fi = iptr->sx.s23.s3.fmiref->p.field;
1752 fieldtype = fi->type;
1756 switch (fieldtype) {
1758 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
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_FTMP1);
1774 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1781 emit_store_dst(jd, iptr, d);
1784 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1786 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1787 emit_nullpointer_check(cd, iptr, s1);
1789 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1790 uf = iptr->sx.s23.s3.uf;
1791 fieldtype = uf->fieldref->parseddesc.fd->type;
1796 fi = iptr->sx.s23.s3.fmiref->p.field;
1797 fieldtype = fi->type;
1801 if (IS_INT_LNG_TYPE(fieldtype))
1802 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1804 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1806 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1807 codegen_add_patch_ref(cd, PATCHER_get_putfield, uf, 0);
1809 switch (fieldtype) {
1811 M_IST(s2, s1, disp);
1814 M_STX(s2, s1, disp);
1817 M_AST(s2, s1, disp);
1820 M_FST(s2, s1, disp);
1823 M_DST(s2, s1, disp);
1831 case ICMD_PUTFIELDCONST: /* ..., objectref ==> ... */
1832 /* val = value (in current instruction) */
1833 /* following NOP) */
1835 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1836 emit_nullpointer_check(cd, iptr, s1);
1838 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1839 unresolved_field *uf = iptr->sx.s23.s3.uf;
1841 fieldtype = uf->fieldref->parseddesc.fd->type;
1843 codegen_addpatchref(cd, PATCHER_get_putfield,
1846 if (opt_showdisassemble) {
1854 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1856 fieldtype = fi->type;
1862 switch (fieldtype) {
1864 M_IST(REG_ZERO, s1, disp);
1867 M_STX(REG_ZERO, s1, disp);
1870 M_AST(REG_ZERO, s1, disp);
1873 M_FST(REG_ZERO, s1, disp);
1876 M_DST(REG_ZERO, s1, disp);
1882 /* branch operations **************************************************/
1884 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1886 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1887 M_INTMOVE(s1, REG_ITMP2_XPTR);
1889 #ifdef ENABLE_VERIFIER
1890 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1891 unresolved_class *uc = iptr->sx.s23.s2.uc;
1893 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
1895 #endif /* ENABLE_VERIFIER */
1897 disp = dseg_add_functionptr(cd, asm_handle_exception);
1898 M_ALD(REG_ITMP1, REG_PV, disp);
1899 M_JMP(REG_ITMP3_XPC, REG_ITMP1, REG_ZERO);
1901 M_NOP; /* nop ensures that XPC is less than the end */
1902 /* of basic block */
1906 case ICMD_GOTO: /* ... ==> ... */
1907 case ICMD_RET: /* ... ==> ... */
1909 emit_br(cd, iptr->dst.block);
1913 case ICMD_JSR: /* ... ==> ... */
1915 emit_br(cd, iptr->sx.s23.s3.jsrtarget.block);
1919 case ICMD_IFNULL: /* ..., value ==> ... */
1920 case ICMD_IFNONNULL:
1922 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1923 emit_bccz(cd, iptr->dst.block, iptr->opc - ICMD_IFNULL, s1, BRANCH_OPT_NONE);
1926 /* Note: int compares must not branch on the register directly. */
1927 /* Reason is, that register content is not 32-bit clean. */
1929 case ICMD_IFEQ: /* ..., value ==> ... */
1931 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1933 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1934 M_CMP_IMM(s1, iptr->sx.val.i);
1937 ICONST(REG_ITMP2, iptr->sx.val.i);
1938 M_CMP(s1, REG_ITMP2);
1940 emit_beq(cd, iptr->dst.block);
1943 case ICMD_IFLT: /* ..., value ==> ... */
1945 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1947 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1948 M_CMP_IMM(s1, iptr->sx.val.i);
1951 ICONST(REG_ITMP2, iptr->sx.val.i);
1952 M_CMP(s1, REG_ITMP2);
1954 emit_blt(cd, iptr->dst.block);
1957 case ICMD_IFLE: /* ..., value ==> ... */
1959 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1961 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1962 M_CMP_IMM(s1, iptr->sx.val.i);
1965 ICONST(REG_ITMP2, iptr->sx.val.i);
1966 M_CMP(s1, REG_ITMP2);
1968 emit_ble(cd, iptr->dst.block);
1971 case ICMD_IFNE: /* ..., value ==> ... */
1973 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1975 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1976 M_CMP_IMM(s1, iptr->sx.val.i);
1979 ICONST(REG_ITMP2, iptr->sx.val.i);
1980 M_CMP(s1, REG_ITMP2);
1982 emit_bne(cd, iptr->dst.block);
1985 case ICMD_IFGT: /* ..., value ==> ... */
1987 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1989 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
1990 M_CMP_IMM(s1, iptr->sx.val.i);
1993 ICONST(REG_ITMP2, iptr->sx.val.i);
1994 M_CMP(s1, REG_ITMP2);
1996 emit_bgt(cd, iptr->dst.block);
1999 case ICMD_IFGE: /* ..., value ==> ... */
2001 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2003 if ((iptr->sx.val.i >= -4096) && (iptr->sx.val.i <= 4095)) {
2004 M_CMP_IMM(s1, iptr->sx.val.i);
2007 ICONST(REG_ITMP2, iptr->sx.val.i);
2008 M_CMP(s1, REG_ITMP2);
2010 emit_bge(cd, iptr->dst.block);
2013 case ICMD_IF_LEQ: /* ..., value ==> ... */
2015 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2016 if (iptr->sx.val.l == 0)
2017 emit_beqz(cd, iptr->dst.block, s1);
2019 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2020 M_CMP_IMM(s1, iptr->sx.val.l);
2023 LCONST(REG_ITMP2, iptr->sx.val.l);
2024 M_CMP(s1, REG_ITMP2);
2026 emit_beq_xcc(cd, iptr->dst.block);
2030 case ICMD_IF_LLT: /* ..., value ==> ... */
2032 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2033 if (iptr->sx.val.l == 0)
2034 emit_bltz(cd, iptr->dst.block, s1);
2036 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2037 M_CMP_IMM(s1, iptr->sx.val.l);
2040 LCONST(REG_ITMP2, iptr->sx.val.l);
2041 M_CMP(s1, REG_ITMP2);
2043 emit_blt_xcc(cd, iptr->dst.block);
2047 case ICMD_IF_LLE: /* ..., value ==> ... */
2049 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2050 if (iptr->sx.val.l == 0)
2051 emit_blez(cd, iptr->dst.block, s1);
2053 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2054 M_CMP_IMM(s1, iptr->sx.val.l);
2057 LCONST(REG_ITMP2, iptr->sx.val.l);
2058 M_CMP(s1, REG_ITMP2);
2060 emit_ble_xcc(cd, iptr->dst.block);
2064 case ICMD_IF_LNE: /* ..., value ==> ... */
2066 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2067 if (iptr->sx.val.l == 0)
2068 emit_bnez(cd, iptr->dst.block, s1);
2070 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2071 M_CMP_IMM(s1, iptr->sx.val.l);
2074 LCONST(REG_ITMP2, iptr->sx.val.l);
2075 M_CMP(s1, REG_ITMP2);
2077 emit_bne_xcc(cd, iptr->dst.block);
2081 case ICMD_IF_LGT: /* ..., value ==> ... */
2083 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2084 if (iptr->sx.val.l == 0)
2085 emit_bgtz(cd, iptr->dst.block, s1);
2087 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2088 M_CMP_IMM(s1, iptr->sx.val.l);
2091 LCONST(REG_ITMP2, iptr->sx.val.l);
2092 M_CMP(s1, REG_ITMP2);
2094 emit_bgt_xcc(cd, iptr->dst.block);
2098 case ICMD_IF_LGE: /* ..., value ==> ... */
2100 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2101 if (iptr->sx.val.l == 0)
2102 emit_bgez(cd, iptr->dst.block, s1);
2104 if ((iptr->sx.val.l >= -4096) && (iptr->sx.val.l <= 4095)) {
2105 M_CMP_IMM(s1, iptr->sx.val.l);
2108 LCONST(REG_ITMP2, iptr->sx.val.l);
2109 M_CMP(s1, REG_ITMP2);
2111 emit_bge_xcc(cd, iptr->dst.block);
2116 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2117 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2119 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2120 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2122 emit_beq_xcc(cd, iptr->dst.block);
2125 case ICMD_IF_ICMPEQ: /* 32-bit compare */
2127 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2128 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2130 emit_beq(cd, iptr->dst.block);
2133 case ICMD_IF_ACMPNE: /* ..., value, value ==> ... */
2134 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2136 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2137 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2139 emit_bne_xcc(cd, iptr->dst.block);
2142 case ICMD_IF_ICMPNE: /* 32-bit compare */
2144 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2145 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2147 emit_bne(cd, iptr->dst.block);
2150 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2152 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2153 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2155 emit_blt_xcc(cd, iptr->dst.block);
2158 case ICMD_IF_ICMPLT: /* 32-bit compare */
2160 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2161 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2163 emit_blt(cd, iptr->dst.block);
2166 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2168 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2169 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2171 emit_bgt_xcc(cd, iptr->dst.block);
2174 case ICMD_IF_ICMPGT: /* 32-bit compare */
2176 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2177 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2179 emit_bgt(cd, iptr->dst.block);
2182 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2184 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2185 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2187 emit_ble_xcc(cd, iptr->dst.block);
2190 case ICMD_IF_ICMPLE: /* 32-bit compare */
2192 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2193 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2195 emit_ble(cd, iptr->dst.block);
2199 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2201 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2202 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2204 emit_bge_xcc(cd, iptr->dst.block);
2207 case ICMD_IF_ICMPGE: /* 32-bit compare */
2209 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2210 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2212 emit_bge(cd, iptr->dst.block);
2216 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2219 REPLACEMENT_POINT_RETURN(cd, iptr);
2221 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2222 M_INTMOVE(s1, REG_RESULT_CALLEE);
2223 goto nowperformreturn;
2225 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2227 REPLACEMENT_POINT_RETURN(cd, iptr);
2229 s1 = emit_load_s1(jd, iptr, REG_RESULT_CALLEE);
2230 M_INTMOVE(s1, REG_RESULT_CALLEE);
2232 #ifdef ENABLE_VERIFIER
2233 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2234 unresolved_class *uc = iptr->sx.s23.s2.uc;
2236 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2238 #endif /* ENABLE_VERIFIER */
2239 goto nowperformreturn;
2241 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2244 REPLACEMENT_POINT_RETURN(cd, iptr);
2246 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2247 M_DBLMOVE(s1, REG_FRESULT);
2248 goto nowperformreturn;
2250 case ICMD_RETURN: /* ... ==> ... */
2252 REPLACEMENT_POINT_RETURN(cd, iptr);
2258 p = cd->stackframesize;
2260 #if !defined(NDEBUG)
2261 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2262 emit_verbosecall_exit(jd);
2265 #if defined(ENABLE_THREADS)
2266 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2267 /* XXX jit-c-call */
2268 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2269 M_ALD(REG_ITMP3, REG_PV, disp);
2271 /* we need to save fp return value (int saved by window) */
2273 switch (iptr->opc) {
2276 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8);
2277 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2278 M_DST(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2280 /* restore the fp return value */
2282 M_DLD(REG_FRESULT, REG_SP, CSTACK + rd->memuse * 8);
2288 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2289 M_ALD(REG_OUT0, REG_SP, CSTACK + rd->memuse * 8); /* delay */
2300 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
2306 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2309 branch_target_t *table;
2311 table = iptr->dst.table;
2313 l = iptr->sx.s23.s2.tablelow;
2314 i = iptr->sx.s23.s3.tablehigh;
2316 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2318 M_INTMOVE(s1, REG_ITMP1);
2320 else if (l <= 4095) {
2321 M_ADD_IMM(s1, -l, REG_ITMP1);
2324 ICONST(REG_ITMP2, l);
2325 /* XXX: do I need to truncate s1 to 32-bit ? */
2326 M_SUB(s1, REG_ITMP2, REG_ITMP1);
2334 M_CMP_IMM(REG_ITMP1, i - 1);
2337 ICONST(REG_ITMP2, i - 1);
2338 M_CMP(REG_ITMP1, REG_ITMP2);
2340 emit_bugt(cd, table[0].block); /* default target */
2342 /* build jump table top down and use address of lowest entry */
2347 dseg_add_target(cd, table->block);
2352 /* length of dataseg after last dseg_addtarget is used by load */
2354 M_ASLL_IMM(REG_ITMP1, POINTERSHIFT, REG_ITMP1);
2355 M_AADD(REG_ITMP1, REG_PV, REG_ITMP2);
2356 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2357 M_JMP(REG_ZERO, REG_ITMP2, REG_ZERO);
2362 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2365 lookup_target_t *lookup;
2367 lookup = iptr->dst.lookup;
2369 i = iptr->sx.s23.s2.lookupcount;
2371 MCODECHECK((i<<2)+8);
2372 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2375 if ((lookup->value >= -4096) && (lookup->value <= 4095)) {
2376 M_CMP_IMM(s1, lookup->value);
2378 ICONST(REG_ITMP2, lookup->value);
2379 M_CMP(s1, REG_ITMP2);
2381 emit_beq(cd, lookup->target.block);
2385 emit_br(cd, iptr->sx.s23.s3.lookupdefault.block);
2391 case ICMD_BUILTIN: /* ..., arg1, arg2, arg3 ==> ... */
2393 REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr);
2395 bte = iptr->sx.s23.s3.bte;
2398 /* XXX: builtin calling with stack arguments not implemented */
2399 assert(md->paramcount <= 4 && md->argfltreguse <= 16);
2401 s3 = md->paramcount;
2403 MCODECHECK((s3 << 1) + 64);
2405 #ifdef BUILTIN_FLOAT_ARGS /* float args for builtins disabled */
2407 /* copy float arguments according to ABI convention */
2409 int num_fltregargs = 0;
2410 int fltregarg_inswap[16];
2412 for (s3 = s3 - 1; s3 >= 0; s3--) {
2413 var = VAR(iptr->sx.s23.s2.args[s3]);
2415 if (IS_FLT_DBL_TYPE(var->type)) {
2416 if (!md->params[s3].inmemory) {
2417 s1 = s3; /*native flt args use argument index directly*/
2418 d = emit_load(jd, iptr, var, REG_FTMP1);
2421 fltregarg_inswap[num_fltregargs] = s1;
2423 /*printf("builtin: flt arg swap to %d\n", s1 + 16);*/
2432 /* move swapped float args to target regs */
2433 for (i = 0; i < num_fltregargs; i++) {
2434 s1 = fltregarg_inswap[i];
2435 M_DMOV(s1 + 16, s1);
2436 /*printf("builtin float arg to target reg: %d ==> %d\n", s1+16, s1);*/
2440 assert(md->argfltreguse == 0);
2445 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2446 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2447 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2448 case ICMD_INVOKEINTERFACE:
2450 REPLACEMENT_POINT_INVOKE(cd, iptr);
2452 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2454 um = iptr->sx.s23.s3.um;
2455 md = um->methodref->parseddesc.md;
2458 lm = iptr->sx.s23.s3.fmiref->p.method;
2460 md = lm->parseddesc;
2464 s3 = md->paramcount;
2466 MCODECHECK((s3 << 1) + 64);
2468 /* copy arguments to registers or stack location */
2470 for (s3 = s3 - 1; s3 >= 0; s3--) {
2471 var = VAR(iptr->sx.s23.s2.args[s3]);
2472 d = md->params[s3].regoff;
2474 if (var->flags & PREALLOC)
2477 if (IS_INT_LNG_TYPE(var->type)) {
2478 if (!md->params[s3].inmemory) {
2479 s1 = emit_load(jd, iptr, var, d);
2483 s1 = emit_load(jd, iptr, var, REG_ITMP1);
2484 M_STX(s1, REG_SP, JITSTACK + d);
2488 #ifdef BUILTIN_FLOAT_ARGS
2489 if (iptr->opc == ICMD_BUILTIN)
2493 if (!md->params[s3].inmemory) {
2494 s1 = emit_load(jd, iptr, var, d);
2495 if (IS_2_WORD_TYPE(var->type))
2501 s1 = emit_load(jd, iptr, var, REG_FTMP1);
2502 M_DST(s1, REG_SP, JITSTACK + d);
2507 switch (iptr->opc) {
2509 if (bte->stub == NULL) {
2510 disp = dseg_add_functionptr(cd, bte->fp);
2513 disp = dseg_add_functionptr(cd, bte->stub);
2516 M_ALD(REG_PV_CALLER, REG_PV, disp); /* built-in-function pointer */
2518 /* XXX jit-c-call */
2519 /* generate the actual call */
2521 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2523 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2524 REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr);
2525 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2526 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2527 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2529 emit_exception_check(cd, iptr);
2530 if (md->returntype.type == TYPE_FLT) {
2531 /* special handling for float return value in %f0 */
2536 case ICMD_INVOKESPECIAL:
2537 emit_nullpointer_check(cd, iptr, REG_OUT0);
2540 case ICMD_INVOKESTATIC:
2542 disp = dseg_add_unique_address(cd, NULL);
2544 codegen_add_patch_ref(cd, PATCHER_invokestatic_special,
2548 disp = dseg_add_address(cd, lm->stubroutine);
2550 M_ALD(REG_PV_CALLER, REG_PV, disp); /* method pointer in pv */
2552 /* generate the actual call */
2554 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2556 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2557 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2558 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2559 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2562 case ICMD_INVOKEVIRTUAL:
2563 emit_nullpointer_check(cd, iptr, REG_OUT0);
2566 codegen_add_patch_ref(cd, PATCHER_invokevirtual, um, 0);
2571 s1 = OFFSET(vftbl_t, table[0]) +
2572 sizeof(methodptr) * lm->vftblindex;
2574 /* implicit null-pointer check */
2575 M_ALD(REG_METHODPTR, REG_OUT0,OFFSET(java_object_t, vftbl));
2576 M_ALD(REG_PV_CALLER, REG_METHODPTR, s1);
2578 /* generate the actual call */
2580 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2582 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2583 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2584 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2585 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2588 case ICMD_INVOKEINTERFACE:
2589 emit_nullpointer_check(cd, iptr, REG_OUT0);
2592 codegen_add_patch_ref(cd, PATCHER_invokeinterface, um, 0);
2598 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2599 sizeof(methodptr*) * lm->class->index;
2601 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2604 /* implicit null-pointer check */
2605 M_ALD(REG_METHODPTR, REG_OUT0, OFFSET(java_object_t, vftbl));
2606 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2607 M_ALD(REG_PV_CALLER, REG_METHODPTR, s2);
2609 /* generate the actual call */
2611 M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
2613 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2614 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2615 /* REG_RA holds the value of the jmp instruction, therefore +8 */
2616 M_LDA(REG_ZERO, REG_RA_CALLER, -disp + 8);
2620 /* store return value */
2622 d = md->returntype.type;
2624 if (d != TYPE_VOID) {
2625 if (IS_INT_LNG_TYPE(d)) {
2626 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2627 M_INTMOVE(REG_RESULT_CALLER, s1);
2630 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2631 if (IS_2_WORD_TYPE(d)) {
2632 M_DBLMOVE(REG_FRESULT, s1);
2634 M_FLTMOVE(REG_FRESULT, s1);
2637 emit_store_dst(jd, iptr, s1);
2642 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2643 /* val.a: (classinfo*) superclass */
2645 /* superclass is an interface:
2647 * OK if ((sub == NULL) ||
2648 * (sub->vftbl->interfacetablelength > super->index) &&
2649 * (sub->vftbl->interfacetable[-super->index] != NULL));
2651 * superclass is a class:
2653 * OK if ((sub == NULL) || (0
2654 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2655 * super->vftbl->diffvall));
2658 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2662 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2667 super = iptr->sx.s23.s3.c.cls;
2668 superindex = super->index;
2671 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2672 CODEGEN_CRITICAL_SECTION_NEW;
2674 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2676 /* if class is not resolved, check which code to call */
2678 if (super == NULL) {
2679 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2681 cr = iptr->sx.s23.s3.c.ref;
2682 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2684 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2687 M_ILD(REG_ITMP2, REG_PV, disp);
2688 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2689 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP2);
2692 /* interface checkcast code */
2694 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2695 if (super == NULL) {
2696 cr = iptr->sx.s23.s3.c.ref;
2698 codegen_add_patch_ref(cd, PATCHER_checkcast_interface,
2702 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2705 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2706 M_ILD(REG_ITMP3, REG_ITMP2,
2707 OFFSET(vftbl_t, interfacetablelength));
2708 M_ADD_IMM(REG_ITMP3, -superindex, REG_ITMP3);
2709 emit_classcast_check(cd, iptr, ICMD_IFLE, REG_ITMP3, s1);
2711 M_ALD(REG_ITMP3, REG_ITMP2,
2712 OFFSET(vftbl_t, interfacetable[0]) -
2713 superindex * sizeof(methodptr*));
2714 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_ITMP3, s1);
2717 emit_label_br(cd, BRANCH_LABEL_4);
2719 emit_label(cd, BRANCH_LABEL_3);
2722 /* class checkcast code */
2724 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2725 if (super == NULL) {
2726 emit_label(cd, BRANCH_LABEL_2);
2728 cr = iptr->sx.s23.s3.c.ref;
2729 disp = dseg_add_unique_address(cd, NULL);
2731 codegen_add_patch_ref(cd,
2732 PATCHER_checkcast_instanceof_class,
2736 disp = dseg_add_address(cd, super->vftbl);
2738 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2741 M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
2742 M_ALD(REG_ITMP3, REG_PV, disp);
2744 CODEGEN_CRITICAL_SECTION_START;
2746 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2747 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2748 M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
2749 M_ALD(REG_ITMP3, REG_PV, disp);
2750 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2752 CODEGEN_CRITICAL_SECTION_END;
2755 M_CMP(REG_ITMP3, REG_ITMP2);
2756 emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
2759 emit_label(cd, BRANCH_LABEL_5);
2762 if (super == NULL) {
2763 emit_label(cd, BRANCH_LABEL_1);
2764 emit_label(cd, BRANCH_LABEL_4);
2767 d = codegen_reg_of_dst(jd, iptr, s1);
2770 /* array type cast-check */
2772 s1 = emit_load_s1(jd, iptr, REG_OUT0);
2773 M_INTMOVE(s1, REG_OUT0);
2775 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2777 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2778 cr = iptr->sx.s23.s3.c.ref;
2779 disp = dseg_add_unique_address(cd, NULL);
2781 codegen_add_patch_ref(cd, PATCHER_builtin_arraycheckcast,
2785 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2787 M_ALD(REG_OUT1, REG_PV, disp);
2788 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2789 M_ALD(REG_ITMP3, REG_PV, disp);
2790 /* XXX jit-c-call */
2791 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2794 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2795 emit_classcast_check(cd, iptr, ICMD_IFEQ, REG_RESULT_CALLER, s1);
2797 d = codegen_reg_of_dst(jd, iptr, s1);
2801 emit_store_dst(jd, iptr, d);
2804 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2805 /* val.a: (classinfo*) superclass */
2807 /* superclass is an interface:
2809 * return (sub != NULL) &&
2810 * (sub->vftbl->interfacetablelength > super->index) &&
2811 * (sub->vftbl->interfacetable[-super->index] != NULL);
2813 * superclass is a class:
2815 * return ((sub != NULL) && (0
2816 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2817 * super->vftbl->diffvall));
2822 vftbl_t *supervftbl;
2825 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2831 super = iptr->sx.s23.s3.c.cls;
2832 superindex = super->index;
2833 supervftbl = super->vftbl;
2836 if ((super == NULL) || !(super->flags & ACC_INTERFACE))
2837 CODEGEN_CRITICAL_SECTION_NEW;
2839 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2840 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2842 M_MOV(s1, REG_ITMP1);
2848 /* if class is not resolved, check which code to call */
2850 if (super == NULL) {
2851 emit_label_beqz(cd, BRANCH_LABEL_1, s1);
2853 cr = iptr->sx.s23.s3.c.ref;
2854 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2856 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_flags,
2859 M_ILD(REG_ITMP3, REG_PV, disp);
2860 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2861 emit_label_beqz(cd, BRANCH_LABEL_2, REG_ITMP3);
2864 /* interface instanceof code */
2866 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2867 if (super == NULL) {
2868 cr = iptr->sx.s23.s3.c.ref;
2870 codegen_add_patch_ref(cd, PATCHER_instanceof_interface,
2874 emit_label_beqz(cd, BRANCH_LABEL_3, s1);
2877 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2878 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2879 M_CMP_IMM(REG_ITMP3, superindex);
2882 M_ALD(REG_ITMP1, REG_ITMP1,
2883 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2884 superindex * sizeof(methodptr*)));
2885 M_CMOVRNE_IMM(REG_ITMP1, 1, d); /* REG_ITMP1 != 0 */
2888 emit_label_br(cd, BRANCH_LABEL_4);
2890 emit_label(cd, BRANCH_LABEL_3);
2893 /* class instanceof code */
2895 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2896 if (super == NULL) {
2897 emit_label(cd, BRANCH_LABEL_2);
2899 cr = iptr->sx.s23.s3.c.ref;
2900 disp = dseg_add_unique_address(cd, NULL);
2902 codegen_add_patch_ref(cd, PATCHER_checkcast_instanceof_class,
2906 disp = dseg_add_address(cd, supervftbl);
2908 emit_label_beqz(cd, BRANCH_LABEL_5, s1);
2911 M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
2912 M_ALD(REG_ITMP2, REG_PV, disp);
2914 CODEGEN_CRITICAL_SECTION_START;
2916 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2917 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2918 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2920 CODEGEN_CRITICAL_SECTION_END;
2922 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2923 M_CMP(REG_ITMP1, REG_ITMP2);
2924 M_XCMOVULE_IMM(1, d);
2927 emit_label(cd, BRANCH_LABEL_5);
2930 if (super == NULL) {
2931 emit_label(cd, BRANCH_LABEL_1);
2932 emit_label(cd, BRANCH_LABEL_4);
2935 emit_store_dst(jd, iptr, d);
2939 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2941 /* check for negative sizes and copy sizes to stack if necessary */
2943 MCODECHECK((iptr->s1.argcount << 1) + 64);
2945 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2947 var = VAR(iptr->sx.s23.s2.args[s1]);
2949 /* copy SAVEDVAR sizes to stack */
2951 /* Already Preallocated? */
2953 if (!(var->flags & PREALLOC)) {
2954 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2955 M_STX(s2, REG_SP, CSTACK + (s1 * 8));
2959 /* arg 0 = dimension count */
2961 ICONST(REG_OUT0, iptr->s1.argcount);
2963 /* is patcher function set? */
2965 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2966 disp = dseg_add_unique_address(cd, 0);
2968 codegen_add_patch_ref(cd, PATCHER_builtin_multianewarray,
2969 iptr->sx.s23.s3.c.ref,
2973 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2975 /* arg 1 = arraydescriptor */
2977 M_ALD(REG_OUT1, REG_PV, disp);
2979 /* arg 2 = pointer to dimensions = stack pointer (absolute) */
2981 M_ADD_IMM(REG_SP, CSTACK, REG_OUT2);
2983 /* XXX c abi call */
2984 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
2985 M_ALD(REG_ITMP3, REG_PV, disp);
2986 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
2989 /* check for exception before result assignment */
2991 emit_exception_check(cd, iptr);
2993 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_CALLER);
2994 M_INTMOVE(REG_RESULT_CALLER, d);
2995 emit_store_dst(jd, iptr, d);
2999 exceptions_throw_internalerror("Unknown ICMD %d during code generation",
3005 } /* for instruction */
3009 /* At the end of a basic block we may have to append some nops,
3010 because the patcher stub calling code might be longer than the
3011 actual instruction. So codepatching does not change the
3012 following block unintentionally. */
3014 if (cd->mcodeptr < cd->lastmcodeptr) {
3015 while (cd->mcodeptr < cd->lastmcodeptr) {
3020 } /* if (bptr -> flags >= BBREACHED) */
3021 } /* for basic block */
3023 dseg_createlinenumbertable(cd);
3025 /* generate stubs */
3027 emit_patcher_stubs(jd);
3029 /* everything's ok */
3035 /* codegen_emit_stub_compiler **************************************************
3037 Emits a stub routine which calls the compiler.
3039 *******************************************************************************/
3041 void codegen_emit_stub_compiler(jitdata *jd)
3046 /* get required compiler data */
3051 /* code for the stub */
3053 /* no window save yet, user caller's PV */
3054 M_ALD_INTERN(REG_ITMP1, REG_PV_CALLER, -2 * SIZEOF_VOID_P); /* codeinfo pointer */
3055 M_ALD_INTERN(REG_PV_CALLER, REG_PV_CALLER, -3 * SIZEOF_VOID_P); /* pointer to compiler */
3056 M_JMP(REG_ZERO, REG_PV_CALLER, REG_ZERO); /* jump to the compiler, RA is wasted */
3061 /* codegen_emit_stub_builtin ***************************************************
3063 Creates a stub routine which calls a builtin function.
3065 *******************************************************************************/
3067 void codegen_emit_stub_builtin(jitdata *jd, builtintable_entry *bte)
3076 /* get required compiler data */
3080 /* set some variables */
3083 /* calculate stack frame size */
3084 cd->stackframesize =
3088 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3089 4; /* 4 arguments or return value */
3092 /* keep stack 16-byte aligned (ABI requirement) */
3094 if (cd->stackframesize & 1)
3095 cd->stackframesize++;
3097 /* create method header */
3098 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3099 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3100 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
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 */
3104 (void) dseg_addlinenumbertablesize(cd);
3105 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3108 /* generate stub code */
3109 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3111 #if defined(ENABLE_GC_CACAO)
3112 /* Save callee saved integer registers in stackframeinfo (GC may
3113 need to recover them during a collection). */
3115 disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
3116 OFFSET(stackframeinfo, intregs) + BIAS;
3118 for (i = 0; i < INT_SAV_CNT; i++)
3119 M_AST(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3122 for (i = 0; i < md->paramcount; i++) {
3123 s1 = md->params[i].regoff;
3125 switch (md->paramtypes[i].type) {
3132 M_DST(s1, REG_SP, JITSTACK + i * 8);
3137 /* create dynamic stack info */
3139 M_AADD_IMM(REG_SP, BIAS + cd->stackframesize * 8, REG_OUT0); /* data sp*/
3140 M_MOV(REG_PV_CALLEE, REG_OUT1); /* PV */
3141 M_MOV(REG_FP, REG_OUT2); /* java sp */
3142 M_MOV(REG_RA_CALLEE, REG_OUT3); /* ra */
3144 disp = dseg_add_functionptr(cd, codegen_stub_builtin_enter);
3145 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3146 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3147 M_NOP; /* XXX fill me! */
3150 /* builtins are allowed to have 5 arguments max */
3152 assert(md->paramcount <= 5);
3154 /* copy arguments into position */
3156 for (i = 0; i < md->paramcount; i++) {
3157 assert(!md->params[i].inmemory);
3159 s1 = md->params[i].regoff;
3161 switch (md->paramtypes[i].type) {
3165 M_MOV(REG_WINDOW_TRANSPOSE(abi_registers_integer_argument[i]), s1);
3169 M_DLD(s1, REG_SP, JITSTACK + i * 8);
3175 /* call the builtin function */
3177 disp = dseg_add_functionptr(cd, bte->fp);
3178 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp); /* load adress of builtin */
3179 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call builtin */
3180 M_NOP; /* delay slot */
3183 /* save return value */
3185 if (md->returntype.type != TYPE_VOID) {
3186 if (IS_INT_LNG_TYPE(md->returntype.type))
3187 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3189 M_DST(REG_FRESULT, REG_SP, CSTACK);
3193 /* remove native stackframe info */
3195 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3196 disp = dseg_add_functionptr(cd, codegen_stub_builtin_exit);
3197 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3198 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3201 /* restore float return value, int return value already in our return reg */
3203 if (md->returntype.type != TYPE_VOID) {
3204 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3205 if (IS_2_WORD_TYPE(md->returntype.type))
3206 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3208 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3213 #if defined(ENABLE_GC_CACAO)
3214 /* Restore callee saved integer registers from stackframeinfo (GC
3215 might have modified them during a collection). */
3217 disp = cd->stackframesize * 8 - sizeof(stackframeinfo) +
3218 OFFSET(stackframeinfo, intregs) + BIAS;
3220 for (i = 0; i < INT_SAV_CNT; i++)
3221 M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 8);
3225 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3232 /* codegen_emit_stub_native ****************************************************
3234 Emits a stub routine which calls a native method.
3236 *******************************************************************************/
3238 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3245 s4 i, j; /* count variables */
3248 s4 funcdisp; /* displacement of the function */
3249 s4 fltregarg_offset[FLT_ARG_CNT];
3251 /* get required compiler data */
3257 /* initialize variables */
3260 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3262 /* calculate stack frame size */
3264 cd->stackframesize =
3265 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3266 sizeof(localref_table) / SIZEOF_VOID_P +
3267 md->paramcount + /* for saving arguments over calls */
3268 nmd->memuse + /* nmd->memuse includes the (6) abi params */
3272 /* keep stack 16-byte aligned (ABI requirement) */
3274 if (cd->stackframesize & 1)
3275 cd->stackframesize++;
3277 /* create method header */
3279 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3280 (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
3281 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3282 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3283 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3284 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3285 (void) dseg_addlinenumbertablesize(cd);
3286 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3288 /* generate stub code */
3290 M_SAVE(REG_SP, -cd->stackframesize * 8, REG_SP); /* build up stackframe */
3292 #if !defined(NDEBUG)
3293 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3294 emit_verbosecall_enter(jd);
3297 /* get function address (this must happen before the stackframeinfo) */
3299 funcdisp = dseg_add_functionptr(cd, f);
3301 #if !defined(WITH_STATIC_CLASSPATH)
3303 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, funcdisp);
3307 /* save float argument registers */
3309 assert(ABIPARAMS_CNT >= FLT_ARG_CNT);
3311 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3312 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3313 s1 = WINSAVE_CNT + nmd->memuse + j;
3314 M_DST(abi_registers_float_argument[i], REG_SP, BIAS + (s1*8));
3315 fltregarg_offset[i] = s1; /* remember stack offset */
3320 /* prepare data structures for native function call */
3322 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp == top of the stack frame (absolute, ie. + BIAS) */
3323 M_MOV(REG_PV_CALLEE, REG_OUT1);
3324 M_MOV(REG_FP, REG_OUT2); /* java sp */
3325 M_MOV(REG_RA_CALLEE, REG_OUT3);
3326 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3327 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3328 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3329 M_NOP; /* XXX fill me! */
3331 /* keep float arguments on stack */
3333 for (i = 0, j = 0; i < md->paramcount && i < FLT_ARG_CNT; i++) {
3334 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3335 M_DLD(abi_registers_float_argument[i], REG_SP, CSTACK + (j * 8));
3341 /* copy or spill arguments to new locations */
3343 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3344 t = md->paramtypes[i].type;
3346 if (IS_INT_LNG_TYPE(t)) {
3348 /* integral types */
3350 if (!md->params[i].inmemory) {
3351 s1 = md->params[i].regoff;
3352 /* s1 refers to the old window, transpose */
3353 s1 = REG_WINDOW_TRANSPOSE(s1);
3355 if (!nmd->params[j].inmemory) {
3356 s2 = nmd->params[j].regoff;
3359 /* nmd's regoff is relative to the start of the param array */
3360 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3361 M_AST(s1, REG_SP, s2);
3365 if (!nmd->params[j].inmemory) {
3366 /* JIT stack arg -> NAT reg arg */
3368 /* Due to the Env pointer that is always passed, the 6th JIT arg */
3369 /* is the 7th (or 8th w/ class ptr) NAT arg, and goes to the stack */
3371 assert(false); /* path never taken */
3374 s1 = md->params[i].regoff + cd->stackframesize * 8;
3375 s2 = BIAS + WINSAVE_CNT * 8 + nmd->params[j].regoff;
3376 M_ALD(REG_ITMP1, REG_SP, CSTACK + s1);
3377 M_AST(REG_ITMP1, REG_SP, s2);
3382 /* floating point types */
3384 if (!md->params[i].inmemory) {
3385 s1 = md->params[i].regoff;
3387 if (!nmd->params[j].inmemory) {
3389 /* no mapping to regs needed, native flt args use regoff */
3390 s2 = nmd->params[j].regoff;
3392 /* JIT float regs are still on the stack */
3393 M_DLD(s2, REG_SP, BIAS + (fltregarg_offset[i] * 8));
3396 /* not supposed to happen with 16 NAT flt args */
3399 s2 = nmd->params[j].regoff;
3400 if (IS_2_WORD_TYPE(t))
3401 M_DST(s1, REG_SP, CSTACK + (s2 * 8));
3403 M_FST(s1, REG_SP, CSTACK + (s2 * 8));
3409 s1 = md->params[i].regoff;
3411 if (!nmd->params[j].inmemory) {
3413 /* JIT stack -> NAT reg */
3415 s2 = nmd->params[j].regoff;
3416 M_DLD(s2, REG_FP, JITSTACK + s1);
3420 /* JIT stack -> NAT stack */
3422 s2 = WINSAVE_CNT * 8 + nmd->params[j].regoff;
3424 /* The FTMP register may already be loaded with args */
3425 /* we know $f0 is unused because of the env pointer */
3426 M_DLD(REG_F0, REG_FP, JITSTACK + s1);
3427 M_DST(REG_F0, REG_SP, BIAS + s2);
3434 /* put class into second argument register */
3436 if (m->flags & ACC_STATIC) {
3437 disp = dseg_add_address(cd, m->class);
3438 M_ALD(REG_OUT1, REG_PV_CALLEE, disp);
3441 /* put env into first argument register */
3443 disp = dseg_add_address(cd, _Jv_env);
3444 M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
3446 /* do the native function call */
3448 M_ALD(REG_ITMP3, REG_PV_CALLEE, funcdisp); /* load adress of native method */
3449 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO); /* call native method */
3450 M_NOP; /* delay slot */
3452 /* save return value */
3454 if (md->returntype.type != TYPE_VOID) {
3455 if (IS_INT_LNG_TYPE(md->returntype.type))
3456 M_MOV(REG_RESULT_CALLER, REG_RESULT_CALLEE);
3458 M_DST(REG_FRESULT, REG_SP, CSTACK);
3461 /* Note: native functions return float values in %f0 (see ABI) */
3462 /* we handle this by doing M_FLD below. (which will load the lower word into %f1) */
3464 #if !defined(NDEBUG)
3465 /* But for the trace function we need to put a flt result into %f1 */
3466 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3467 if (!IS_2_WORD_TYPE(md->returntype.type))
3468 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3469 emit_verbosecall_exit(jd);
3473 /* remove native stackframe info */
3475 M_ADD_IMM(REG_FP, BIAS, REG_OUT0); /* datasp, like above */
3476 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3477 M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
3478 M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
3479 M_NOP; /* XXX fill me! */
3480 M_MOV(REG_RESULT_CALLER, REG_ITMP2_XPTR);
3482 /* restore float return value, int return value already in our return reg */
3484 if (md->returntype.type != TYPE_VOID) {
3485 if (IS_FLT_DBL_TYPE(md->returntype.type)) {
3486 if (IS_2_WORD_TYPE(md->returntype.type))
3487 M_DLD(REG_FRESULT, REG_SP, CSTACK);
3489 M_FLD(REG_FRESULT, REG_SP, CSTACK);
3493 /* check for exception */
3494 M_BNEZ(REG_ITMP2_XPTR, 4); /* if no exception then return */
3497 M_RETURN(REG_RA_CALLEE, 8); /* implicit window restore */
3500 /* handle exception */
3502 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3503 M_ALD(REG_ITMP1, REG_PV, disp); /* load asm exception handler address */
3504 M_MOV(REG_RA_CALLEE, REG_ITMP3_XPC); /* get exception address */
3505 M_JMP(REG_ZERO, REG_ITMP1, REG_ZERO);/* jump to asm exception handler */
3506 M_RESTORE(REG_ZERO, 0, REG_ZERO); /* restore callers window (DELAY) */
3508 /* generate patcher stubs */
3510 emit_patcher_stubs(jd);
3514 * These are local overrides for various environment variables in Emacs.
3515 * Please do not remove this and leave it at the end of the file, where
3516 * Emacs will automagically detect them.
3517 * ---------------------------------------------------------------------
3520 * indent-tabs-mode: t
3524 * vim:noexpandtab:sw=4:ts=4: