1 /* src/vm/jit/s390/codegen.c - machine code generator for s390
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 7691 2007-04-12 12:45:10Z twisti $
39 #include "vm/jit/s390/arch.h"
40 #include "vm/jit/s390/codegen.h"
41 #include "vm/jit/s390/emit.h"
43 #include "mm/memory.h"
44 #include "native/jni.h"
45 #include "native/native.h"
47 #if defined(ENABLE_THREADS)
48 # include "threads/native/lock.h"
51 #include "vm/builtin.h"
52 #include "vm/exceptions.h"
53 #include "vm/global.h"
54 #include "vmcore/loader.h"
55 #include "vmcore/options.h"
56 #include "vmcore/statistics.h"
57 #include "vm/stringlocal.h"
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/codegen-common.h"
61 #include "vm/jit/dseg.h"
62 #include "vm/jit/emit-common.h"
63 #include "vm/jit/jit.h"
64 #include "vm/jit/methodheader.h"
65 #include "vm/jit/parse.h"
66 #include "vm/jit/patcher.h"
67 #include "vm/jit/reg.h"
68 #include "vm/jit/replace.h"
69 #include "vm/jit/stacktrace.h"
71 #if defined(ENABLE_LSRA)
72 # include "vm/jit/allocator/lsra.h"
75 #define OOPS() assert(0);
79 /* codegen *********************************************************************
81 Generates machine code.
83 *******************************************************************************/
86 bool codegen(jitdata *jd)
92 s4 len, s1, s2, s3, d, dd, disp;
95 varinfo *var, *var1, *var2, *dst;
99 constant_classref *cr;
100 unresolved_class *uc;
101 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
102 unresolved_method *um;
103 builtintable_entry *bte;
106 unresolved_field *uf;
109 rplpoint *replacementpoint;
113 /* get required compiler data */
120 /* prevent compiler warnings */
133 /* space to save used callee saved registers */
135 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
136 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse) * 2;
138 cd->stackframesize = rd->memuse + savedregs_num + 1 /* space to save RA */;
141 * As REG_ITMP3 == REG_RA, do not touch REG_ITMP3, until it has been saved.
144 #if defined(ENABLE_THREADS)
145 /* space to save argument of monitor_enter */
146 OOPS(); /* see powerpc */
148 if (checksync && (m->flags & ACC_SYNCHRONIZED))
149 cd->stackframesize++;
153 /* Keep stack of non-leaf functions 16-byte aligned for calls into
154 native code e.g. libc or jni (alignment problems with
157 if (!jd->isleafmethod || opt_verbosecall )
158 /* TODO really 16 bytes ? */
159 cd->stackframesize = (cd->stackframesize + 3) & ~3;
161 /* create method header */
163 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
164 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
166 #if defined(ENABLE_THREADS)
167 /* IsSync contains the offset relative to the stack pointer for the
168 argument of monitor_exit used in the exception handler. Since the
169 offset could be zero and give a wrong meaning of the flag it is
173 if (checksync && (m->flags & ACC_SYNCHRONIZED))
174 (void) dseg_add_unique_s4(cd, (rd->memuse + 1) * 4); /* IsSync */
178 (void) dseg_add_unique_s4(cd, 0);*/ /* IsSync */
180 disp = dseg_add_unique_address(cd, 0);
182 (void) dseg_add_unique_s4(cd, jd->isleafmethod); /* IsLeaf */
183 (void) dseg_add_unique_s4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
184 (void) dseg_add_unique_s4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
186 (void) dseg_addlinenumbertablesize(cd);
188 (void) dseg_add_unique_s4(cd, jd->exceptiontablelength); /* ExTableSize */
190 /* create exception table */
192 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
193 dseg_add_target(cd, ex->start);
194 dseg_add_target(cd, ex->end);
195 dseg_add_target(cd, ex->handler);
196 (void) dseg_add_unique_address(cd, ex->catchtype.any);
199 /* generate method profiling code */
201 #if defined(ENABLE_PROFILING)
202 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
203 /* count frequency */
205 M_ALD(REG_ITMP1, REG_PV, CodeinfoPointer);
206 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
207 M_IADD_IMM(1, REG_ITMP2);
208 M_IST(REG_ITMP2, REG_ITMP1, OFFSET(codeinfo, frequency));
210 /* PROFILE_CYCLE_START; */
214 /* create stack frame (if necessary) */
216 if (cd->stackframesize)
217 M_ASUB_IMM(cd->stackframesize * 4, REG_SP);
219 N_LHI(REG_ITMP2, disp);
220 N_ST(REG_SP, 0, REG_ITMP2, REG_PV);
222 /* save used callee saved registers and return address */
224 p = cd->stackframesize;
225 p--; M_AST(REG_RA, REG_SP, p * 4);
227 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
228 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
230 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
231 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
234 /* take arguments out of register or stack frame */
238 for (p = 0, l = 0; p < md->paramcount; p++) {
239 t = md->paramtypes[p].type;
240 varindex = jd->local_map[l * 5 + t];
243 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
246 if (varindex == UNUSED)
251 s1 = md->params[p].regoff;
252 if (IS_INT_LNG_TYPE(t)) { /* integer args */
253 if (IS_2_WORD_TYPE(t))
254 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
255 rd->argintregs[GET_HIGH_REG(s1)]);
257 s2 = rd->argintregs[s1];
258 if (!md->params[p].inmemory) { /* register arguments */
259 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
260 if (IS_2_WORD_TYPE(t))
261 M_LNGMOVE(s2, var->vv.regoff);
263 M_INTMOVE(s2, var->vv.regoff);
265 } else { /* reg arg -> spilled */
266 if (IS_2_WORD_TYPE(t))
267 M_LST(s2, REG_SP, var->vv.regoff * 4);
269 M_IST(s2, REG_SP, var->vv.regoff * 4);
272 } else { /* stack arguments */
273 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
274 if (IS_2_WORD_TYPE(t))
275 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
277 M_ILD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
279 } else { /* stack arg -> spilled */
280 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4);
281 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4);
282 if (IS_2_WORD_TYPE(t)) {
283 M_ILD(REG_ITMP1, REG_SP, (cd->stackframesize + s1) * 4 +4);
284 M_IST(REG_ITMP1, REG_SP, var->vv.regoff * 4 + 4);
289 } else { /* floating args */
290 if (!md->params[p].inmemory) { /* register arguments */
291 s2 = rd->argfltregs[s1];
292 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
293 M_FLTMOVE(s2, var->vv.regoff);
295 } else { /* reg arg -> spilled */
296 if (IS_2_WORD_TYPE(t))
297 M_DST(s2, REG_SP, var->vv.regoff * 4);
299 M_FST(s2, REG_SP, var->vv.regoff * 4);
302 } else { /* stack arguments */
303 if (!IS_INMEMORY(var->flags)) { /* stack-arg -> register */
304 if (IS_2_WORD_TYPE(t))
305 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
308 M_FLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 4);
310 } else { /* stack-arg -> spilled */
311 if (IS_2_WORD_TYPE(t)) {
312 M_DLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
313 M_DST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
314 var->vv.regoff = cd->stackframesize + s1;
317 M_FLD(REG_FTMP1, REG_SP, (cd->stackframesize + s1) * 4);
318 M_FST(REG_FTMP1, REG_SP, var->vv.regoff * 4);
325 /* save monitorenter argument */
327 #if defined(ENABLE_THREADS)
328 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
329 /* stack offset for monitor argument */
333 if (opt_verbosecall) {
334 M_LSUB_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
336 for (p = 0; p < INT_ARG_CNT; p++)
337 M_LST(rd->argintregs[p], REG_SP, p * 8);
339 for (p = 0; p < FLT_ARG_CNT; p++)
340 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
342 s1 += INT_ARG_CNT + FLT_ARG_CNT;
345 /* decide which monitor enter function to call */
347 if (m->flags & ACC_STATIC) {
348 M_MOV_IMM(&m->class->object.header, REG_A0);
353 codegen_add_nullpointerexception_ref(cd);
356 M_AST(REG_A0, REG_SP, s1 * 8);
357 M_MOV_IMM(LOCK_monitor_enter, REG_ITMP1);
360 if (opt_verbosecall) {
361 for (p = 0; p < INT_ARG_CNT; p++)
362 M_LLD(rd->argintregs[p], REG_SP, p * 8);
364 for (p = 0; p < FLT_ARG_CNT; p++)
365 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 8);
367 M_LADD_IMM((INT_ARG_CNT + FLT_ARG_CNT) * 8, REG_SP);
373 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
374 emit_verbosecall_enter(jd);
375 #endif /* !defined(NDEBUG) */
379 /* end of header generation */
381 replacementpoint = jd->code->rplpoints;
384 /* walk through all basic blocks */
386 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
388 bptr->mpc = (u4) ((u1 *) cd->mcodeptr - cd->mcodebase);
390 if (bptr->flags >= BBREACHED) {
392 /* branch resolving */
394 codegen_resolve_branchrefs(cd, bptr);
396 /* handle replacement points */
399 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
400 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
404 assert(cd->lastmcodeptr <= cd->mcodeptr);
405 cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
409 /* copy interface registers to their destination */
414 /* generate basicblock profiling code */
416 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
417 /* count frequency */
419 M_MOV_IMM(code->bbfrequency, REG_ITMP3);
420 M_IINC_MEMBASE(REG_ITMP3, bptr->nr * 4);
422 /* if this is an exception handler, start profiling again */
424 if (bptr->type == BBTYPE_EXH)
428 #if defined(ENABLE_LSRA)
432 src = bptr->invars[len];
433 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
434 if (bptr->type == BBTYPE_EXH) {
435 /* d = reg_of_var(rd, src, REG_ITMP1); */
436 if (!IS_INMEMORY(src->flags))
440 M_INTMOVE(REG_ITMP1, d);
441 emit_store(jd, NULL, src, d);
451 var = VAR(bptr->invars[len]);
452 if ((len == bptr->indepth-1) && (bptr->type != BBTYPE_STD)) {
453 if (bptr->type == BBTYPE_EXH) {
454 d = codegen_reg_of_var(0, var, REG_ITMP1);
455 M_INTMOVE(REG_ITMP1, d);
456 emit_store(jd, NULL, var, d);
460 assert((var->flags & INOUT));
463 #if defined(ENABLE_LSRA)
466 /* walk through all instructions */
471 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
472 if (iptr->line != currentline) {
473 dseg_addlinenumber(cd, iptr->line);
474 currentline = iptr->line;
477 MCODECHECK(1024); /* 1KB should be enough */
480 case ICMD_NOP: /* ... ==> ... */
481 case ICMD_POP: /* ..., value ==> ... */
482 case ICMD_POP2: /* ..., value, value ==> ... */
483 case ICMD_INLINE_START: /* internal ICMDs */
484 case ICMD_INLINE_END:
487 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
488 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
491 codegen_add_nullpointerexception_ref(cd);
494 /* constant operations ************************************************/
496 case ICMD_ICONST: /* ... ==> ..., constant */
497 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
498 ICONST(d, iptr->sx.val.i);
499 emit_store_dst(jd, iptr, d);
502 case ICMD_LCONST: /* ... ==> ..., constant */
504 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
505 LCONST(d, iptr->sx.val.l);
506 emit_store_dst(jd, iptr, d);
509 case ICMD_FCONST: /* ... ==> ..., constant */
510 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
511 disp = dseg_add_float(cd, iptr->sx.val.f);
512 M_FLDN(d, REG_PV, disp, REG_ITMP1);
513 emit_store_dst(jd, iptr, d);
516 case ICMD_DCONST: /* ... ==> ..., constant */
517 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
518 disp = dseg_add_double(cd, iptr->sx.val.d);
519 M_DLDN(d, REG_PV, disp, REG_ITMP1);
520 emit_store_dst(jd, iptr, d);
523 case ICMD_ACONST: /* ... ==> ..., constant */
524 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
526 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
527 cr = iptr->sx.val.c.ref;
528 disp = dseg_add_unique_address(cd, cr);
530 /* PROFILE_CYCLE_STOP; */
532 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
535 /* PROFILE_CYCLE_START; */
537 M_ALD(d, REG_PV, disp);
539 if (iptr->sx.val.anyptr == 0) {
542 disp = dseg_add_unique_address(cd, iptr->sx.val.anyptr);
543 M_ALD(d, REG_PV, disp);
546 emit_store_dst(jd, iptr, d);
550 /* load/store/copy/move operations ************************************/
552 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
553 case ICMD_ALOAD: /* s1 = local variable */
557 case ICMD_ISTORE: /* ..., value ==> ... */
563 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
567 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
568 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
571 /* integer operations *************************************************/
573 case ICMD_INEG: /* ..., value ==> ..., - value */
575 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
576 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
578 emit_store_dst(jd, iptr, d);
582 case ICMD_LNEG: /* ..., value ==> ..., - value */
584 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
585 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
586 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
587 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
588 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
589 N_AHI(GET_HIGH_REG(d), -1);
590 emit_store_dst(jd, iptr, d);
593 case ICMD_I2L: /* ..., value ==> ..., value */
595 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
596 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
598 M_INTMOVE(s1, GET_HIGH_REG(d));
599 ICONST(GET_LOW_REG(d), 0);
600 M_SRDA_IMM(32, GET_HIGH_REG(d));
602 emit_copy_dst(jd, iptr, d);
603 emit_store_dst(jd, iptr, d);
604 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
608 case ICMD_L2I: /* ..., value ==> ..., value */
609 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
610 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
611 M_INTMOVE(GET_LOW_REG(s1), d);
612 emit_store_dst(jd, iptr, d);
615 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
616 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
617 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
621 emit_store_dst(jd, iptr, d);
624 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
625 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
626 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
630 emit_store_dst(jd, iptr, d);
633 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
635 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
636 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
640 emit_store_dst(jd, iptr, d);
643 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
645 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
646 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
647 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
654 emit_store_dst(jd, iptr, d);
659 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
660 /* sx.val.i = constant */
661 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
662 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
665 if (N_VALID_IMM(iptr->sx.val.i)) {
666 M_IADD_IMM(iptr->sx.val.i, d);
668 disp = dseg_add_s4(cd, iptr->sx.val.i);
669 M_ILD(REG_ITMP2, REG_PV, disp);
670 M_IADD(REG_ITMP2, d);
672 emit_store_dst(jd, iptr, d);
675 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
677 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
679 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
680 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
681 dd = GET_HIGH_REG(d);
690 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
691 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
701 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
702 N_AHI(GET_HIGH_REG(d), 1);
704 emit_store_dst(jd, iptr, d);
707 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
708 /* sx.val.l = constant */
710 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
712 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
713 s3 = iptr->sx.val.l >> 32;
715 M_INTMOVE(s1, GET_HIGH_REG(d));
717 if (N_VALID_IMM(s3)) {
720 ICONST(REG_ITMP3, s3);
721 M_IADD(REG_ITMP3, s1);
724 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
725 s3 = iptr->sx.val.l & 0xffffffff;
726 ICONST(REG_ITMP3, s3);
728 M_INTMOVE(s1, GET_LOW_REG(d));
729 N_ALR(GET_LOW_REG(d), REG_ITMP3);
731 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
732 N_AHI(GET_HIGH_REG(d), 1);
734 emit_store_dst(jd, iptr, d);
737 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
739 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
740 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
741 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
743 M_INTMOVE(s1, REG_ITMP1);
744 M_ISUB(s2, REG_ITMP1);
745 M_INTMOVE(REG_ITMP1, d);
750 emit_store_dst(jd, iptr, d);
754 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
755 /* sx.val.i = constant */
757 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
758 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
761 if (N_VALID_IMM(iptr->sx.val.i)) {
762 M_ISUB_IMM(iptr->sx.val.i, d);
764 disp = dseg_add_s4(cd, iptr->sx.val.i);
765 M_ILD(REG_ITMP2, REG_PV, disp);
766 M_ISUB(REG_ITMP2, d);
768 emit_store_dst(jd, iptr, d);
772 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
774 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
776 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
777 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
778 dd = GET_HIGH_REG(d);
781 M_INTMOVE(s2, REG_ITMP3);
788 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
789 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
793 M_INTMOVE(s2, REG_ITMP3);
800 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
801 N_AHI(GET_HIGH_REG(d), -1);
803 emit_store_dst(jd, iptr, d);
806 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
807 /* sx.val.l = constant */
809 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
811 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
812 s3 = iptr->sx.val.l >> 32;
814 M_INTMOVE(s1, GET_HIGH_REG(d));
816 if (N_VALID_IMM(-s3)) {
819 ICONST(REG_ITMP3, s3);
820 M_ISUB(REG_ITMP3, s1);
823 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
824 s3 = iptr->sx.val.l & 0xffffffff;
825 ICONST(REG_ITMP3, s3);
827 N_SLR(GET_LOW_REG(d), REG_ITMP3);
829 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
830 N_AHI(GET_HIGH_REG(d), -1);
832 emit_store_dst(jd, iptr, d);
835 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
837 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
838 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
839 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
846 emit_store_dst(jd, iptr, d);
850 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
851 /* sx.val.i = constant */
852 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
853 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
855 if (iptr->sx.val.i == 2) {
857 } else if (N_VALID_IMM(iptr->sx.val.i)) {
858 M_IMUL_IMM(iptr->sx.val.i, d);
860 disp = dseg_add_s4(cd, iptr->sx.val.i);
861 M_ILD(REG_ITMP2, REG_PV, disp);
862 M_IMUL(REG_ITMP2, d);
864 emit_store_dst(jd, iptr, d);
867 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
868 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
870 /* For this operation we need a register pair.
871 * We will use r0 and itmp1 and will backup r0.
874 M_INTMOVE(R0, REG_ITMP3);
876 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
880 codegen_add_arithmeticexception_ref(cd);
882 s1 = emit_load_s1(jd, iptr, R0);
891 d = codegen_reg_of_dst(jd, iptr, R0);
895 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
896 M_INTMOVE(REG_ITMP1, d);
900 emit_store_dst(jd, iptr, d);
902 M_INTMOVE(REG_ITMP3, R0);
906 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
907 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
909 bte = iptr->sx.s23.s3.bte;
912 /* test s2 for zero */
914 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
915 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
916 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
918 codegen_add_arithmeticexception_ref(cd);
920 disp = dseg_add_functionptr(cd, bte->fp);
924 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
926 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
927 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
931 M_ASUB_IMM(96, REG_SP);
932 M_ALD(REG_ITMP3, REG_PV, disp);
933 M_JSR(REG_RA, REG_ITMP3);
934 M_AADD_IMM(96, REG_SP);
938 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
939 M_LNGMOVE(REG_RESULT_PACKED, d);
940 emit_store_dst(jd, iptr, d);
944 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
945 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
946 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
948 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
949 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
950 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
953 M_INTMOVE(s2, REG_ITMP2);
972 emit_store_dst(jd, iptr, d);
975 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
976 /* sx.val.i = constant */
980 assert(iptr->sx.val.i <= 32);
982 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
983 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
990 s3 = (1 << iptr->sx.val.i) - 1;
992 if (N_VALID_IMM(s3)) {
995 ICONST(REG_ITMP1, -1);
996 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
997 M_IADD(REG_ITMP1, d);
1000 *(u4 *)ref |= (u4)(cd->mcodeptr - ref) / 2;
1002 M_SRA_IMM(iptr->sx.val.i, d);
1004 emit_store_dst(jd, iptr, d);
1009 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1010 /* sx.val.i = constant */
1012 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1013 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1016 M_MOV(s1, REG_ITMP1);
1020 ICONST(REG_ITMP3, iptr->sx.val.i);
1023 M_IAND(REG_ITMP3, d);
1026 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1032 emit_store_dst(jd, iptr, d);
1036 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1037 /* sx.val.i = constant */
1038 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1039 /* sx.val.i = constant */
1040 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1041 /* sx.val.i = constant */
1042 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1043 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1047 if (N_VALID_DISP(iptr->sx.val.i)) {
1048 disp = iptr->sx.val.i;
1051 ICONST(REG_ITMP3, iptr->sx.val.i);
1056 switch (iptr->opc) {
1057 case ICMD_ISHLCONST:
1060 case ICMD_ISHRCONST:
1063 case ICMD_IUSHRCONST:
1070 emit_store_dst(jd, iptr, d);
1073 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1075 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1077 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1079 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1080 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1082 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1083 M_INTMOVE(s2, REG_ITMP3);
1087 s1 = emit_load_s1(jd, iptr, d);
1091 switch (iptr->opc) {
1093 M_SLDA(s2, GET_HIGH_REG(d));
1096 M_SRDA(s2, GET_HIGH_REG(d));
1099 M_SRDL(s2, GET_HIGH_REG(d));
1105 emit_copy_dst(jd, iptr, d);
1106 emit_store_dst(jd, iptr, d);
1107 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1111 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1112 /* sx.val.i = constant */
1113 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1114 /* sx.val.i = constant */
1115 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1116 /* sx.val.l = constant */
1119 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1120 s1 = emit_load_s1(jd, iptr, d);
1124 if (N_VALID_DISP(iptr->sx.val.i)) {
1125 disp = iptr->sx.val.i;
1128 ICONST(REG_ITMP3, iptr->sx.val.i);
1133 switch (iptr->opc) {
1134 case ICMD_LSHLCONST:
1135 N_SLDA(GET_HIGH_REG(d), disp, s3);
1137 case ICMD_LSHRCONST:
1138 N_SRDA(GET_HIGH_REG(d), disp, s3);
1140 case ICMD_LUSHRCONST:
1141 N_SRDL(GET_HIGH_REG(d), disp, s3);
1144 N_SLDL(GET_HIGH_REG(d), disp, s3);
1150 emit_copy_dst(jd, iptr, d);
1151 emit_store_dst(jd, iptr, d);
1152 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1156 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1158 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1159 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1160 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1167 emit_store_dst(jd, iptr, d);
1171 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1173 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1174 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1175 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1182 emit_store_dst(jd, iptr, d);
1186 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1188 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1189 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1190 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1197 emit_store_dst(jd, iptr, d);
1203 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1204 /* sx.val.i = constant */
1205 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1206 /* sx.val.i = constant */
1207 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1208 /* sx.val.i = constant */
1210 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1211 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1214 ICONST(REG_ITMP2, iptr->sx.val.i);
1216 switch (iptr->opc) {
1217 case ICMD_IANDCONST:
1218 M_IAND(REG_ITMP2, d);
1220 case ICMD_IXORCONST:
1221 M_IXOR(REG_ITMP2, d);
1224 M_IOR(REG_ITMP2, d);
1230 emit_store_dst(jd, iptr, d);
1234 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1235 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1236 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1238 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1240 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1241 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1242 dd = GET_LOW_REG(d);
1244 switch (iptr->opc) {
1273 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1274 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1275 dd = GET_HIGH_REG(d);
1277 switch (iptr->opc) {
1306 emit_store_dst(jd, iptr, d);
1309 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1310 /* sx.val.l = constant */
1311 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1312 /* sx.val.l = constant */
1313 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1314 /* sx.val.l = constant */
1316 /* TODO should use memory operand to access data segment, not load */
1318 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1320 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1321 s3 = iptr->sx.val.l & 0xffffffff;
1323 M_INTMOVE(s1, GET_LOW_REG(d));
1325 ICONST(REG_ITMP3, s3);
1327 switch (iptr->opc) {
1328 case ICMD_LANDCONST:
1329 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1331 case ICMD_LXORCONST:
1332 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1335 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1341 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1342 s3 = iptr->sx.val.l >> 32;
1344 M_INTMOVE(s1, GET_HIGH_REG(d));
1346 ICONST(REG_ITMP3, s3);
1348 switch (iptr->opc) {
1349 case ICMD_LANDCONST:
1350 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1352 case ICMD_LXORCONST:
1353 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1356 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1362 emit_store_dst(jd, iptr, d);
1366 /* floating operations ************************************************/
1368 case ICMD_FNEG: /* ..., value ==> ..., - value */
1369 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1370 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1372 emit_store_dst(jd, iptr, d);
1375 case ICMD_DNEG: /* ..., value ==> ..., - value */
1376 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1377 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1379 emit_store_dst(jd, iptr, d);
1382 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1383 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1384 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1385 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1392 emit_store_dst(jd, iptr, d);
1395 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1396 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1397 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1398 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1405 emit_store_dst(jd, iptr, d);
1408 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1409 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1410 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1411 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1415 emit_store_dst(jd, iptr, d);
1418 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1419 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1420 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1421 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1425 emit_store_dst(jd, iptr, d);
1428 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1429 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1430 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1431 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1438 emit_store_dst(jd, iptr, d);
1441 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1442 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1443 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1444 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1451 emit_store_dst(jd, iptr, d);
1454 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1455 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1456 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1457 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1461 emit_store_dst(jd, iptr, d);
1464 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1465 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1466 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1467 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1471 emit_store_dst(jd, iptr, d);
1474 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1475 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1476 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1478 emit_store_dst(jd, iptr, d);
1481 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1482 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1483 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1485 emit_store_dst(jd, iptr, d);
1488 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1489 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1490 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1492 emit_store_dst(jd, iptr, d);
1493 /* TODO: corner cases ? */
1496 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1497 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1498 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1500 emit_store_dst(jd, iptr, d);
1501 /* TODO: corner cases ? */
1506 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1507 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1508 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1510 emit_store_dst(jd, iptr, d);
1513 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1514 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1515 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1517 emit_store_dst(jd, iptr, d);
1520 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1521 /* == => 0, < => 1, > => -1 */
1525 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1526 /* == => 0, < => 1, > => -1 */
1529 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1530 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1531 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1533 switch (iptr->opc) {
1545 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1546 SZ_BRC + SZ_BRC + SZ_BRC
1549 N_BRC( /* load -1 */
1550 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1551 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1556 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1559 N_LHI(d, 1); /* GT */
1560 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1561 N_LHI(d, -1); /* LT */
1562 M_BR(SZ_BRC + SZ_LHI);
1563 N_LHI(d, 0); /* EQ */
1565 emit_store_dst(jd, iptr, d);
1570 /* memory operations **************************************************/
1572 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1574 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1575 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1576 gen_nullptr_check(s1);
1577 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1578 emit_store_dst(jd, iptr, d);
1582 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1583 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1584 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1585 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1587 emit_array_checks(cd, iptr, s1, s2);
1589 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1590 /* TODO improove this */
1593 emit_store_dst(jd, iptr, d);
1596 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1598 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1599 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1600 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1602 emit_array_checks(cd, iptr, s1, s2);
1604 M_INTMOVE(s2, REG_ITMP2);
1605 M_SLL_IMM(1, REG_ITMP2);
1607 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1608 emit_store_dst(jd, iptr, d);
1611 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1612 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1613 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1614 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1616 emit_array_checks(cd, iptr, s1, s2);
1618 M_INTMOVE(s2, REG_ITMP2);
1619 M_SLL_IMM(1, REG_ITMP2);
1621 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1622 emit_store_dst(jd, iptr, d);
1625 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1626 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1627 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1628 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1629 emit_array_checks(cd, iptr, s1, s2);
1631 M_INTMOVE(s2, REG_ITMP2);
1632 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1633 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1634 emit_store_dst(jd, iptr, d);
1637 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1639 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1640 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1642 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1643 emit_array_checks(cd, iptr, s1, s2);
1645 M_INTMOVE(s2, REG_ITMP2);
1646 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1648 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1649 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1650 emit_store_dst(jd, iptr, d);
1654 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1656 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1657 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1658 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1659 emit_array_checks(cd, iptr, s1, s2);
1661 M_INTMOVE(s2, REG_ITMP2);
1662 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1664 N_LE(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1666 emit_store_dst(jd, iptr, d);
1669 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1670 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1671 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1672 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1673 emit_array_checks(cd, iptr, s1, s2);
1675 M_INTMOVE(s2, REG_ITMP2);
1676 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1678 N_LD(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1680 emit_store_dst(jd, iptr, d);
1683 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1684 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1685 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1686 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1687 emit_array_checks(cd, iptr, s1, s2);
1689 M_INTMOVE(s2, REG_ITMP2);
1690 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1691 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1692 emit_store_dst(jd, iptr, d);
1695 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1696 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1697 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1698 emit_array_checks(cd, iptr, s1, s2);
1699 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1701 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1704 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1706 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1707 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1708 emit_array_checks(cd, iptr, s1, s2);
1709 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1711 M_INTMOVE(s2, REG_ITMP2);
1712 M_SLL_IMM(1, REG_ITMP2);
1714 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1718 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1719 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1720 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1721 emit_array_checks(cd, iptr, s1, s2);
1722 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1724 M_INTMOVE(s2, REG_ITMP2);
1725 M_SLL_IMM(1, REG_ITMP2);
1727 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1730 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1732 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1733 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1734 emit_array_checks(cd, iptr, s1, s2);
1736 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1738 M_INTMOVE(s2, REG_ITMP2);
1739 M_SLL_IMM(2, REG_ITMP2);
1741 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1744 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1746 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1747 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1748 emit_array_checks(cd, iptr, s1, s2);
1750 M_INTMOVE(s2, REG_ITMP2);
1751 M_SLL_IMM(3, REG_ITMP2);
1753 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1754 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1755 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1756 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1759 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1760 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1761 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1762 emit_array_checks(cd, iptr, s1, s2);
1763 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1765 M_INTMOVE(s2, REG_ITMP2);
1766 M_SLL_IMM(2, REG_ITMP2);
1768 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1771 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1772 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1773 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1774 emit_array_checks(cd, iptr, s1, s2);
1775 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1777 M_INTMOVE(s2, REG_ITMP2);
1778 M_SLL_IMM(3, REG_ITMP2);
1780 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1783 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1785 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1786 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1787 emit_array_checks(cd, iptr, s1, s2);
1788 s3 = emit_load_s3(jd, iptr, REG_A1);
1790 M_INTMOVE(s1, REG_A0);
1791 M_INTMOVE(s3, REG_A1);
1793 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1794 M_ALD(REG_ITMP3, REG_PV, disp);
1795 M_ASUB_IMM(96, REG_SP);
1796 M_JSR(REG_RA, REG_ITMP3);
1797 M_AADD_IMM(96, REG_SP);
1801 codegen_add_arraystoreexception_ref(cd);
1803 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1804 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1805 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1807 M_INTMOVE(s2, REG_ITMP2);
1808 M_SLL_IMM(2, REG_ITMP2);
1809 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1812 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1813 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1818 case ICMD_GETSTATIC: /* ... ==> ..., value */
1820 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1821 uf = iptr->sx.s23.s3.uf;
1822 fieldtype = uf->fieldref->parseddesc.fd->type;
1823 disp = dseg_add_unique_address(cd, NULL);
1825 /* PROFILE_CYCLE_STOP; */
1827 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1829 /* PROFILE_CYCLE_START; */
1832 fi = iptr->sx.s23.s3.fmiref->p.field;
1833 fieldtype = fi->type;
1834 disp = dseg_add_address(cd, &(fi->value));
1836 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1839 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
1841 PROFILE_CYCLE_START;
1845 M_ALD(REG_ITMP1, REG_PV, disp);
1847 switch (fieldtype) {
1849 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1850 M_ILD(d, REG_ITMP1, 0);
1853 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1854 M_LLD(d, REG_ITMP1, 0);
1857 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1858 M_ALD(d, REG_ITMP1, 0);
1861 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1862 M_FLD(d, REG_ITMP1, 0);
1865 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1866 M_DLD(d, REG_ITMP1, 0);
1870 emit_store_dst(jd, iptr, d);
1874 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1876 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1877 uf = iptr->sx.s23.s3.uf;
1878 fieldtype = uf->fieldref->parseddesc.fd->type;
1879 disp = dseg_add_unique_address(cd, uf);
1881 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
1884 fi = iptr->sx.s23.s3.fmiref->p.field;
1885 fieldtype = fi->type;
1886 disp = dseg_add_address(cd, &(fi->value));
1888 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1889 codegen_addpatchref(cd, PATCHER_clinit,
1893 M_ALD(REG_ITMP1, REG_PV, disp);
1894 switch (fieldtype) {
1896 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1897 M_IST(s1, REG_ITMP1, 0);
1900 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
1901 M_LST(s1, REG_ITMP1, 0);
1904 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1905 M_AST(s1, REG_ITMP1, 0);
1908 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1909 M_FST(s1, REG_ITMP1, 0);
1912 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1913 M_DST(s1, REG_ITMP1, 0);
1918 case ICMD_GETFIELD: /* ... ==> ..., value */
1920 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1921 gen_nullptr_check(s1);
1923 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1924 uf = iptr->sx.s23.s3.uf;
1925 fieldtype = uf->fieldref->parseddesc.fd->type;
1928 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1931 fi = iptr->sx.s23.s3.fmiref->p.field;
1932 fieldtype = fi->type;
1936 switch (fieldtype) {
1938 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1942 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1943 if (GET_HIGH_REG(d) == s1) {
1944 M_ILD(GET_LOW_REG(d), s1, disp + 4);
1945 M_ILD(GET_HIGH_REG(d), s1, disp);
1948 M_ILD(GET_LOW_REG(d), s1, disp + 4);
1949 M_ILD(GET_HIGH_REG(d), s1, disp);
1953 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1957 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1961 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1965 emit_store_dst(jd, iptr, d);
1968 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1970 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1971 gen_nullptr_check(s1);
1973 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1974 uf = iptr->sx.s23.s3.uf;
1975 fieldtype = uf->fieldref->parseddesc.fd->type;
1979 fi = iptr->sx.s23.s3.fmiref->p.field;
1980 fieldtype = fi->type;
1984 if (IS_INT_LNG_TYPE(fieldtype)) {
1985 if (IS_2_WORD_TYPE(fieldtype))
1986 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1988 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1991 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1993 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1994 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1996 switch (fieldtype) {
1998 M_IST(s2, s1, disp);
2001 /* TODO really order */
2002 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2003 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2006 M_AST(s2, s1, disp);
2009 M_FST(s2, s1, disp);
2012 M_DST(s2, s1, disp);
2017 /* branch operations **************************************************/
2019 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2021 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2022 M_INTMOVE(s1, REG_ITMP1_XPTR);
2026 #ifdef ENABLE_VERIFIER
2027 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2028 uc = iptr->sx.s23.s2.uc;
2030 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2032 #endif /* ENABLE_VERIFIER */
2034 disp = dseg_add_functionptr(cd, asm_handle_exception);
2035 M_ALD(REG_ITMP2, REG_PV, disp);
2036 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2041 case ICMD_GOTO: /* ... ==> ... */
2042 case ICMD_RET: /* ... ==> ... */
2045 codegen_add_branch_ref(cd, iptr->dst.block);
2049 case ICMD_JSR: /* ... ==> ... */
2052 codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2056 case ICMD_IFNULL: /* ..., value ==> ... */
2057 case ICMD_IFNONNULL: /* ..., value ==> ... */
2058 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2060 switch (iptr->opc) {
2064 case ICMD_IFNONNULL:
2068 codegen_add_branch_ref(cd, iptr->dst.block);
2071 case ICMD_IFEQ: /* ..., value ==> ... */
2072 case ICMD_IFLT: /* ..., value ==> ... */
2073 case ICMD_IFLE: /* ..., value ==> ... */
2074 case ICMD_IFNE: /* ..., value ==> ... */
2075 case ICMD_IFGT: /* ..., value ==> ... */
2076 case ICMD_IFGE: /* ..., value ==> ... */
2078 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2080 if (N_VALID_IMM(iptr->sx.val.i))
2081 M_ICMP_IMM(s1, iptr->sx.val.i);
2083 disp = dseg_add_s4(cd, iptr->sx.val.i);
2084 ICONST(REG_ITMP2, disp);
2085 N_C(s1, 0, REG_ITMP2, REG_PV);
2088 switch (iptr->opc) {
2108 codegen_add_branch_ref(cd, iptr->dst.block);
2112 case ICMD_IF_LLT: /* ..., value ==> ... */
2113 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2122 /* ATTENTION: compare high words signed and low words unsigned */
2124 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2126 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2127 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2129 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2130 ICONST(REG_ITMP2, disp);
2131 N_C(s1, 0, REG_ITMP2, REG_PV);
2138 codegen_addreference(cd, iptr->dst.block);
2139 /* EQ ... fall through */
2140 out_ref = cd->mcodeptr;
2146 codegen_addreference(cd, iptr->dst.block);
2147 /* EQ ... fall through */
2148 out_ref = cd->mcodeptr;
2152 /* EQ ... fall through */
2153 out_ref = cd->mcodeptr;
2157 /* EQ ... fall through */
2159 codegen_addreference(cd, iptr->dst.block);
2165 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2167 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2168 ICONST(REG_ITMP2, disp);
2169 N_CL(s1, 0, REG_ITMP2, REG_PV);
2193 codegen_addreference(cd, iptr->dst.block);
2195 if (out_ref != NULL) {
2196 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2202 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2203 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2205 /* Compare addresses as 31 bit unsigned integers */
2207 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2208 M_LDA(REG_ITMP1, s1, 0);
2210 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2211 M_LDA(REG_ITMP2, s2, 0);
2213 M_CMP(REG_ITMP1, REG_ITMP2);
2215 switch (iptr->opc) {
2216 case ICMD_IF_ACMPEQ:
2219 case ICMD_IF_ACMPNE:
2224 codegen_add_branch_ref(cd, iptr->dst.block);
2228 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2229 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2230 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2231 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2232 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2233 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2235 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2236 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2238 switch (iptr->opc) {
2239 case ICMD_IF_ICMPEQ:
2242 case ICMD_IF_ICMPNE:
2245 case ICMD_IF_ICMPLT:
2248 case ICMD_IF_ICMPGT:
2251 case ICMD_IF_ICMPLE:
2254 case ICMD_IF_ICMPGE:
2258 codegen_add_branch_ref(cd, iptr->dst.block);
2262 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2263 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2264 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2265 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2266 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2267 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2272 /* ATTENTION: compare high words signed and low words unsigned */
2274 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2275 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2280 case ICMD_IF_LCMPLT:
2281 case ICMD_IF_LCMPLE:
2283 codegen_addreference(cd, iptr->dst.block);
2284 /* EQ ... fall through */
2285 out_ref = cd->mcodeptr;
2288 case ICMD_IF_LCMPGT:
2289 case ICMD_IF_LCMPGE:
2291 codegen_addreference(cd, iptr->dst.block);
2292 /* EQ ... fall through */
2293 out_ref = cd->mcodeptr;
2296 case ICMD_IF_LCMPEQ:
2297 /* EQ ... fall through */
2298 out_ref = cd->mcodeptr;
2301 case ICMD_IF_LCMPNE:
2302 /* EQ ... fall through */
2304 codegen_addreference(cd, iptr->dst.block);
2310 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2311 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2316 case ICMD_IF_LCMPLT:
2319 case ICMD_IF_LCMPLE:
2322 case ICMD_IF_LCMPGT:
2325 case ICMD_IF_LCMPGE:
2328 case ICMD_IF_LCMPEQ:
2331 case ICMD_IF_LCMPNE:
2338 codegen_addreference(cd, iptr->dst.block);
2340 if (out_ref != NULL) {
2341 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2347 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2349 REPLACEMENT_POINT_RETURN(cd, iptr);
2350 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2351 M_INTMOVE(s1, REG_RESULT);
2352 goto nowperformreturn;
2354 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2356 REPLACEMENT_POINT_RETURN(cd, iptr);
2357 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2358 M_INTMOVE(s1, REG_RESULT);
2360 #ifdef ENABLE_VERIFIER
2361 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2362 unresolved_class *uc = iptr->sx.s23.s2.uc;
2364 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2366 #endif /* ENABLE_VERIFIER */
2367 goto nowperformreturn;
2369 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2371 REPLACEMENT_POINT_RETURN(cd, iptr);
2372 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2373 M_LNGMOVE(s1, REG_RESULT_PACKED);
2374 goto nowperformreturn;
2376 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2379 REPLACEMENT_POINT_RETURN(cd, iptr);
2380 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2381 M_FLTMOVE(s1, REG_FRESULT);
2382 goto nowperformreturn;
2384 case ICMD_RETURN: /* ... ==> ... */
2386 REPLACEMENT_POINT_RETURN(cd, iptr);
2392 p = cd->stackframesize;
2394 /* call trace function */
2396 #if !defined(NDEBUG)
2397 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2398 emit_verbosecall_exit(jd);
2399 #endif /* !defined(NDEBUG) */
2401 #if defined(ENABLE_THREADS)
2402 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2403 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2404 M_ALD(REG_ITMP3, REG_PV, disp);
2407 /* we need to save the proper return value */
2409 switch (iptr->opc) {
2411 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2415 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2418 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2421 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2425 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2428 /* and now restore the proper return value */
2430 switch (iptr->opc) {
2432 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2436 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2439 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2442 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2448 /* restore return address */
2450 p--; M_ALD(REG_RA, REG_SP, p * 4);
2452 /* restore saved registers */
2454 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2455 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2457 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2458 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2461 /* deallocate stack */
2463 if (cd->stackframesize)
2464 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2471 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2474 branch_target_t *table;
2476 table = iptr->dst.table;
2478 l = iptr->sx.s23.s2.tablelow;
2479 i = iptr->sx.s23.s3.tablehigh;
2481 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2482 M_INTMOVE(s1, REG_ITMP1);
2486 } else if (N_VALID_IMM(-l)) {
2487 M_ISUB_IMM(l, REG_ITMP1);
2489 ICONST(REG_ITMP2, l);
2490 M_ISUB(REG_ITMP2, REG_ITMP1);
2493 /* number of targets */
2499 ICONST(REG_ITMP2, i);
2500 M_ICMPU(REG_ITMP1, REG_ITMP2);
2502 codegen_add_branch_ref(cd, table[0].block);
2504 /* build jump table top down and use address of lowest entry */
2509 dseg_add_target(cd, table->block);
2514 /* length of dataseg after last dseg_add_target is used by load */
2516 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2517 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2518 N_L(REG_ITMP1, 0, REG_ITMP1, REG_PV);
2519 M_JMP(RN, REG_ITMP1);
2524 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2527 lookup_target_t *lookup;
2529 lookup = iptr->dst.lookup;
2531 i = iptr->sx.s23.s2.lookupcount;
2533 MCODECHECK(8 + ((7 + 6) * i) + 5);
2534 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2537 if (N_VALID_IMM(lookup->value)) {
2538 M_ICMP_IMM(s1, lookup->value);
2540 ICONST(REG_ITMP2, lookup->value);
2541 M_ICMP(REG_ITMP2, s1);
2544 codegen_add_branch_ref(cd, lookup->target.block);
2550 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2555 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2557 bte = iptr->sx.s23.s3.bte;
2561 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2562 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2563 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2564 case ICMD_INVOKEINTERFACE:
2566 REPLACEMENT_POINT_INVOKE(cd, iptr);
2568 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2570 um = iptr->sx.s23.s3.um;
2571 md = um->methodref->parseddesc.md;
2574 lm = iptr->sx.s23.s3.fmiref->p.method;
2576 md = lm->parseddesc;
2580 s3 = md->paramcount;
2582 MCODECHECK((s3 << 1) + 64);
2584 /* copy arguments to registers or stack location */
2586 for (s3 = s3 - 1; s3 >= 0; s3--) {
2587 var = VAR(iptr->sx.s23.s2.args[s3]);
2589 /* Already Preallocated? */
2590 if (var->flags & PREALLOC)
2593 if (IS_INT_LNG_TYPE(var->type)) {
2594 if (!md->params[s3].inmemory) {
2595 if (IS_2_WORD_TYPE(var->type)) {
2597 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2598 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2600 d = emit_load(jd, iptr, var, s1);
2604 s1 = rd->argintregs[md->params[s3].regoff];
2605 d = emit_load(jd, iptr, var, s1);
2610 if (IS_2_WORD_TYPE(var->type)) {
2611 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2612 M_LST(d, REG_SP, md->params[s3].regoff * 4);
2615 d = emit_load(jd, iptr, var, REG_ITMP1);
2616 M_IST(d, REG_SP, md->params[s3].regoff * 4);
2621 if (!md->params[s3].inmemory) {
2622 s1 = rd->argfltregs[md->params[s3].regoff];
2623 d = emit_load(jd, iptr, var, s1);
2627 d = emit_load(jd, iptr, var, REG_FTMP1);
2628 if (IS_2_WORD_TYPE(var->type))
2629 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2631 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2636 switch (iptr->opc) {
2638 disp = dseg_add_functionptr(cd, bte->fp);
2640 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2641 N_LHI(REG_ITMP1, disp);
2642 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2645 case ICMD_INVOKESPECIAL:
2647 gen_nullptr_check_intern(REG_A0);
2649 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
2653 case ICMD_INVOKESTATIC:
2655 disp = dseg_add_unique_address(cd, um);
2657 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2661 disp = dseg_add_address(cd, lm->stubroutine);
2663 N_LHI(REG_ITMP1, disp);
2664 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2667 case ICMD_INVOKEVIRTUAL:
2668 gen_nullptr_check(REG_A0);
2671 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2676 s1 = OFFSET(vftbl_t, table[0]) +
2677 sizeof(methodptr) * lm->vftblindex;
2680 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2681 M_ALD(REG_PV, REG_METHODPTR, s1);
2684 case ICMD_INVOKEINTERFACE:
2685 gen_nullptr_check(REG_A0);
2687 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2688 * and -0xFFF in index register (itmp1)
2691 N_LHI(REG_ITMP1, -N_DISP_MAX);
2694 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2700 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2701 sizeof(methodptr*) * lm->class->index +
2704 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2707 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2708 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
2709 M_ALD(REG_PV, REG_METHODPTR, s2);
2713 /* generate the actual call */
2716 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2718 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2719 M_ASUB_IMM(disp, REG_PV);
2721 /* post call finalization */
2723 if (iptr->opc == ICMD_BUILTIN) {
2724 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2727 /* actually only used for ICMD_BUILTIN */
2729 if (INSTRUCTION_MUST_CHECK(iptr)) {
2732 codegen_add_fillinstacktrace_ref(cd);
2735 /* store return value */
2737 d = md->returntype.type;
2739 if (d != TYPE_VOID) {
2740 if (IS_INT_LNG_TYPE(d)) {
2741 if (IS_2_WORD_TYPE(d)) {
2742 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2743 M_LNGMOVE(REG_RESULT_PACKED, s1);
2746 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2747 M_INTMOVE(REG_RESULT, s1);
2751 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2752 M_FLTMOVE(REG_FRESULT, s1);
2754 emit_store_dst(jd, iptr, s1);
2760 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2762 /* val.a: (classinfo*) superclass */
2764 /* superclass is an interface:
2766 * OK if ((sub == NULL) ||
2767 * (sub->vftbl->interfacetablelength > super->index) &&
2768 * (sub->vftbl->interfacetable[-super->index] != NULL));
2770 * superclass is a class:
2772 * OK if ((sub == NULL) || (0
2773 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2774 * super->vftbl->diffval));
2777 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2778 /* object type cast-check */
2781 vftbl_t *supervftbl;
2784 u1 *class_label_refs[] = { 0 }, *class_label;
2785 u1 *exit_label_refs[] = { 0, 0, 0, 0 };
2787 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2793 super = iptr->sx.s23.s3.c.cls;
2794 superindex = super->index;
2795 supervftbl = super->vftbl;
2798 #if defined(ENABLE_THREADS)
2799 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2801 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2803 /* if class is not resolved, check which code to call */
2805 if (super == NULL) {
2807 exit_label_refs[0] = cd->mcodeptr;
2810 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2812 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
2813 iptr->sx.s23.s3.c.ref,
2816 ICONST(REG_ITMP2, ACC_INTERFACE);
2817 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
2818 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
2819 class_label_refs[0] = cd->mcodeptr;
2823 /* interface checkcast code */
2825 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2826 if (super == NULL) {
2827 codegen_add_patch_ref(cd,
2828 PATCHER_checkcast_instanceof_interface,
2829 iptr->sx.s23.s3.c.ref,
2833 exit_label_refs[1] = cd->mcodeptr;
2837 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2838 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2839 M_ISUB_IMM(superindex, REG_ITMP3);
2841 codegen_add_classcastexception_ref(cd, s1);
2844 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2845 superindex * sizeof(methodptr*))
2847 M_ALD(REG_ITMP2, REG_ITMP2, 0);
2850 codegen_add_classcastexception_ref(cd, s1);
2852 if (super == NULL) {
2853 exit_label_refs[2] = cd->mcodeptr;
2858 /* class checkcast code */
2860 class_label = cd->mcodeptr;
2862 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2863 if (super == NULL) {
2864 disp = dseg_add_unique_address(cd, NULL);
2866 codegen_add_patch_ref(cd,
2867 PATCHER_resolve_classref_to_vftbl,
2868 iptr->sx.s23.s3.c.ref,
2872 disp = dseg_add_address(cd, supervftbl);
2874 exit_label_refs[3] = cd->mcodeptr;
2878 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2879 M_ALD(REG_ITMP3, REG_PV, disp);
2880 #if defined(ENABLE_THREADS)
2881 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
2883 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2884 /* if (s1 != REG_ITMP1) { */
2885 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
2886 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
2887 /* #if defined(ENABLE_THREADS) */
2888 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
2890 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
2893 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2894 M_ISUB(REG_ITMP3, REG_ITMP2);
2895 M_ALD(REG_ITMP3, REG_PV, disp);
2896 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2897 #if defined(ENABLE_THREADS)
2898 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
2901 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
2902 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
2903 M_BGT(0); /* Branch if greater then */
2904 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
2905 codegen_add_classcastexception_ref(cd, s1);
2908 /* resolve labels by adding the correct displacement */
2910 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
2911 if (exit_label_refs[s2])
2912 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
2915 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
2916 if (class_label_refs[s2])
2917 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
2920 d = codegen_reg_of_dst(jd, iptr, s1);
2923 /* array type cast-check */
2925 s1 = emit_load_s1(jd, iptr, REG_A0);
2926 M_INTMOVE(s1, REG_A0);
2928 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2929 disp = dseg_add_unique_address(cd, NULL);
2931 codegen_add_patch_ref(cd,
2932 PATCHER_resolve_classref_to_classinfo,
2933 iptr->sx.s23.s3.c.ref,
2937 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2939 M_ALD(REG_A1, REG_PV, disp);
2940 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2941 M_ALD(REG_ITMP1, REG_PV, disp);
2942 M_ASUB_IMM(96, REG_SP);
2943 M_JSR(REG_RA, REG_ITMP1);
2944 M_AADD_IMM(96, REG_SP);
2946 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2949 codegen_add_classcastexception_ref(cd, s1);
2951 d = codegen_reg_of_dst(jd, iptr, s1);
2955 emit_store_dst(jd, iptr, d);
2958 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2959 /* val.a: (classinfo*) superclass */
2961 /* superclass is an interface:
2963 * return (sub != NULL) &&
2964 * (sub->vftbl->interfacetablelength > super->index) &&
2965 * (sub->vftbl->interfacetable[-super->index] != NULL);
2967 * superclass is a class:
2969 * return ((sub != NULL) && (0
2970 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2971 * super->vftbl->diffvall));
2976 vftbl_t *supervftbl;
2979 u1 *class_label, *class_label_refs[1] = { 0 };
2980 u1 *exit_label_refs[4] = { 0, 0, 0, 0 };
2981 u1 *label1, *label1_refs[1] = { 0 };
2983 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2989 super = iptr->sx.s23.s3.c.cls;
2990 superindex = super->index;
2991 supervftbl = super->vftbl;
2994 #if defined(ENABLE_THREADS)
2995 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2997 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2998 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3000 M_MOV(s1, REG_ITMP1);
3004 /* if class is not resolved, check which code to call */
3006 if (super == NULL) {
3010 exit_label_refs[0] = cd->mcodeptr;
3013 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3015 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3016 iptr->sx.s23.s3.c.ref, disp);
3018 ICONST(REG_ITMP2, ACC_INTERFACE);
3019 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3020 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3021 class_label_refs[0] = cd->mcodeptr;
3025 /* interface instanceof code */
3027 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3028 if (super == NULL) {
3029 /* If d == REG_ITMP2, then it's destroyed in check
3034 codegen_add_patch_ref(cd,
3035 PATCHER_checkcast_instanceof_interface,
3036 iptr->sx.s23.s3.c.ref, 0);
3041 exit_label_refs[1] = cd->mcodeptr;
3045 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3046 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3047 M_ISUB_IMM(superindex, REG_ITMP3);
3048 label1_refs[0] = cd->mcodeptr;
3052 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3053 superindex * sizeof(methodptr*))
3055 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3057 /* d := (REG_ITMP1 != 0) */
3059 N_LTR(d, REG_ITMP1);
3060 M_BEQ(SZ_BRC + SZ_LHI);
3063 label1 = cd->mcodeptr;
3065 if (super == NULL) {
3066 exit_label_refs[2] = cd->mcodeptr;
3071 /* class instanceof code */
3073 class_label = cd->mcodeptr;
3075 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3076 if (super == NULL) {
3077 disp = dseg_add_unique_address(cd, NULL);
3079 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3080 iptr->sx.s23.s3.c.ref,
3084 disp = dseg_add_address(cd, supervftbl);
3089 exit_label_refs[3] = cd->mcodeptr;
3093 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3094 M_ALD(REG_ITMP2, REG_PV, disp);
3095 #if defined(ENABLE_THREADS)
3096 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3098 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3099 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3100 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3101 #if defined(ENABLE_THREADS)
3102 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3104 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3106 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3108 M_BGT(SZ_BRC + SZ_LHI);
3112 /* resolve labels by adding the correct displacement */
3114 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3115 if (exit_label_refs[s2])
3116 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3119 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3120 if (class_label_refs[s2])
3121 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3124 for (s2 = 0; s2 < sizeof(label1_refs) / sizeof(label1_refs[0]); ++s2) {
3125 if (label1_refs[s2])
3126 *(u4 *)label1_refs[s2] |= (u4)(label1 - label1_refs[s2]) / 2;
3129 emit_store_dst(jd, iptr, d);
3135 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3137 /* check for negative sizes and copy sizes to stack if necessary */
3139 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3142 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3144 /* copy SAVEDVAR sizes to stack */
3145 var = VAR(iptr->sx.s23.s2.args[s1]);
3147 /* Already Preallocated? */
3148 if (!(var->flags & PREALLOC)) {
3149 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3150 M_IST(s2, REG_SP, s1 * 4);
3154 /* is a patcher function set? */
3156 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3157 disp = dseg_add_unique_address(cd, 0);
3159 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
3160 iptr->sx.s23.s3.c.ref,
3164 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3166 /* a0 = dimension count */
3168 ICONST(REG_A0, iptr->s1.argcount);
3170 /* a1 = classinfo */
3172 M_ALD(REG_A1, REG_PV, disp);
3174 /* a2 = pointer to dimensions = stack pointer */
3176 M_MOV(REG_SP, REG_A2);
3178 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3179 M_ALD(REG_ITMP1, REG_PV, disp);
3180 M_ASUB_IMM(96, REG_SP);
3181 M_JSR(REG_RA, REG_ITMP1);
3182 M_AADD_IMM(96, REG_SP);
3184 /* check for exception before result assignment */
3188 codegen_add_fillinstacktrace_ref(cd);
3190 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3191 M_INTMOVE(REG_RESULT, s1);
3192 emit_store_dst(jd, iptr, s1);
3197 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3201 } /* for instruction */
3203 MCODECHECK(512); /* XXX require a lower number? */
3205 /* At the end of a basic block we may have to append some nops,
3206 because the patcher stub calling code might be longer than the
3207 actual instruction. So codepatching does not change the
3208 following block unintentionally. */
3210 if (cd->mcodeptr < cd->lastmcodeptr) {
3211 while (cd->mcodeptr < cd->lastmcodeptr) {
3216 } /* if (bptr -> flags >= BBREACHED) */
3217 } /* for basic block */
3219 dseg_createlinenumbertable(cd);
3221 /* generate stubs */
3223 emit_exception_stubs(jd);
3224 emit_patcher_stubs(jd);
3226 emit_replacement_stubs(jd);
3231 /* everything's ok */
3237 /* codegen_emit_stub_compiler **************************************************
3239 Emits a stub routine which calls the compiler.
3241 *******************************************************************************/
3243 void codegen_emit_stub_compiler(jitdata *jd)
3248 /* get required compiler data */
3253 /* code for the stub */
3255 /* don't touch ITMP3 as it cointains the return address */
3257 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3259 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3260 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3261 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3266 /* createnativestub ************************************************************
3268 Creates a stub routine which calls a native method.
3270 *******************************************************************************/
3273 arguments on stack \
3274 -------------------------------------------------| <- SP on nativestub entry
3276 callee saved int regs (none) |
3277 callee saved float regs (none) | stack frame like in cacao
3278 local variable slots (none) |
3279 arguments for calling methods (none) /
3280 ------------------------------------------------------------------ <- datasp
3285 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3286 0 - 96 register save area for callee /
3287 -------------------------------------------------------- <- SP native method
3289 SP after method entry
3292 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3300 s4 i, j; /* count variables */
3305 /* get required compiler data */
3312 /* initialize variables */
3315 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3317 /* calculate stack frame size */
3319 cd->stackframesize =
3320 1 + /* r14 - return address */ +
3321 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3322 sizeof(localref_table) / SIZEOF_VOID_P +
3324 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3325 nmd->memuse + /* parameter passing */
3326 96 / SIZEOF_VOID_P /* required by ABI */;
3328 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3331 /* create method header */
3333 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3334 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3335 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3336 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3337 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3338 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3339 (void) dseg_addlinenumbertablesize(cd);
3340 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3342 /* generate native method profiling code */
3344 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3345 /* count frequency */
3347 M_MOV_IMM(code, REG_ITMP3);
3348 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3352 /* generate stub code */
3354 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3356 /* save return address */
3358 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3360 #if !defined(NDEBUG)
3361 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3362 emit_verbosecall_enter(jd);
3365 /* get function address (this must happen before the stackframeinfo) */
3367 disp = dseg_add_functionptr(cd, f);
3369 #if !defined(WITH_STATIC_CLASSPATH)
3371 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3374 M_ILD(REG_ITMP1, REG_PV, disp);
3376 j = 96 + (nmd->memuse * 4);
3378 /* todo some arg registers are not volatile in C-abi terms */
3380 /* save integer and float argument registers */
3382 for (i = 0; i < md->paramcount; i++) {
3383 if (! md->params[i].inmemory) {
3384 s1 = md->params[i].regoff;
3386 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3387 if (IS_2_WORD_TYPE(t)) {
3388 /* todo store multiple */
3389 N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3390 N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3392 N_ST(rd->argintregs[s1], j, RN, REG_SP);
3395 if (IS_2_WORD_TYPE(t)) {
3396 N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3398 N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3406 N_ST(REG_ITMP1, j, RN, REG_SP);
3408 /* create dynamic stack info */
3410 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3411 N_LR(REG_A1, REG_PV); /* pv */
3412 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3413 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3415 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3416 M_ILD(REG_ITMP1, REG_PV, disp);
3418 M_CALL(REG_ITMP1); /* call */
3420 /* restore integer and float argument registers */
3422 j = 96 + (nmd->memuse * 4);
3424 for (i = 0; i < md->paramcount; i++) {
3425 if (! md->params[i].inmemory) {
3426 s1 = md->params[i].regoff;
3428 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3429 if (IS_2_WORD_TYPE(t)) {
3430 /* todo load multiple ! */
3431 N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3432 N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3434 N_L(rd->argintregs[s1], j, RN, REG_SP);
3437 if (IS_2_WORD_TYPE(t)) {
3438 N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3440 N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3448 N_L(REG_ITMP1, j, RN, REG_SP);
3450 /* copy or spill arguments to new locations */
3452 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3453 t = md->paramtypes[i].type;
3455 if (IS_INT_LNG_TYPE(t)) {
3457 if (!md->params[i].inmemory) {
3459 s1 = rd->argintregs[md->params[i].regoff];
3461 if (!nmd->params[j].inmemory) {
3462 s2 = rd->argintregs[nmd->params[j].regoff];
3463 if (IS_2_WORD_TYPE(t)) {
3464 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3465 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3470 s2 = nmd->params[j].regoff;
3471 if (IS_2_WORD_TYPE(t)) {
3472 N_STM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3474 N_ST(s1, 96 + (s2 * 4), RN, REG_SP);
3479 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3480 s2 = nmd->params[j].regoff;
3482 if (IS_2_WORD_TYPE(t)) {
3483 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3485 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3490 /* We only copy spilled float arguments, as the float argument */
3491 /* registers keep unchanged. */
3493 if (md->params[i].inmemory) {
3494 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3495 s2 = nmd->params[j].regoff;
3497 if (IS_2_WORD_TYPE(t)) {
3498 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3500 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3506 /* put class into second argument register */
3508 if (m->flags & ACC_STATIC) {
3509 disp = dseg_add_address(cd, m->class);
3510 M_ILD(REG_A1, REG_PV, disp);
3513 /* put env into first argument register */
3515 disp = dseg_add_address(cd, _Jv_env);
3516 M_ILD(REG_A0, REG_PV, disp);
3518 /* do the native function call */
3520 M_CALL(REG_ITMP1); /* call */
3522 /* save return value */
3524 t = md->returntype.type;
3526 if (t != TYPE_VOID) {
3527 if (IS_INT_LNG_TYPE(t)) {
3528 if (IS_2_WORD_TYPE(t)) {
3529 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3531 N_ST(REG_RESULT, 96, RN, REG_SP);
3534 if (IS_2_WORD_TYPE(t)) {
3535 N_STD(REG_FRESULT, 96, RN, REG_SP);
3537 N_STE(REG_FRESULT, 96, RN, REG_SP);
3542 #if !defined(NDEBUG)
3543 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3544 emit_verbosecall_exit(jd);
3547 /* remove native stackframe info */
3549 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3550 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3551 M_ILD(REG_ITMP1, REG_PV, disp);
3553 N_LR(REG_ITMP3, REG_RESULT);
3555 /* restore return value */
3557 if (t != TYPE_VOID) {
3558 if (IS_INT_LNG_TYPE(t)) {
3559 if (IS_2_WORD_TYPE(t)) {
3560 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3562 N_L(REG_RESULT, 96, RN, REG_SP);
3565 if (IS_2_WORD_TYPE(t)) {
3566 N_LD(REG_FRESULT, 96, RN, REG_SP);
3568 N_LE(REG_FRESULT, 96, RN, REG_SP);
3573 /* load return address */
3575 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3577 /* remove stackframe */
3579 N_AHI(REG_SP, cd->stackframesize * 4);
3581 /* test for exception */
3583 N_LTR(REG_ITMP3, REG_ITMP3);
3584 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3588 N_BCR(DD_ANY, REG_ITMP2);
3590 /* handle exception */
3592 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3593 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3597 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3600 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3601 M_ALD(REG_ITMP3, REG_PV, disp);
3602 M_JMP(RN, REG_ITMP3);
3604 /* generate patcher stubs */
3606 emit_patcher_stubs(jd);
3610 return code->entrypoint;
3614 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3615 codegendata *cd = jd->cd;
3616 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3618 M_MOV(reg, tempregnum);
3626 * These are local overrides for various environment variables in Emacs.
3627 * Please do not remove this and leave it at the end of the file, where
3628 * Emacs will automagically detect them.
3629 * ---------------------------------------------------------------------
3632 * indent-tabs-mode: t
3636 * vim:noexpandtab:sw=4:ts=4: