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 7766 2007-04-19 13:24:48Z michi $
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 ==> ... */
568 if (!(iptr->flags.bits & INS_FLAG_RETADDR))
572 /* integer operations *************************************************/
574 case ICMD_INEG: /* ..., value ==> ..., - value */
576 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
577 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
579 emit_store_dst(jd, iptr, d);
583 case ICMD_LNEG: /* ..., value ==> ..., - value */
585 s1 = emit_load_s1(jd, iptr, REG_ITMP12_PACKED);
586 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
587 M_INEG(GET_HIGH_REG(s1), GET_HIGH_REG(d));
588 M_INEG(GET_LOW_REG(s1), GET_LOW_REG(d));
589 N_BRC(8 /* result zero, no overflow */, SZ_BRC + SZ_AHI);
590 N_AHI(GET_HIGH_REG(d), -1);
591 emit_store_dst(jd, iptr, d);
594 case ICMD_I2L: /* ..., value ==> ..., value */
596 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
597 s1 = emit_load_s1(jd, iptr, GET_HIGH_REG(d));
599 M_INTMOVE(s1, GET_HIGH_REG(d));
600 ICONST(GET_LOW_REG(d), 0);
601 M_SRDA_IMM(32, GET_HIGH_REG(d));
603 emit_copy_dst(jd, iptr, d);
604 emit_store_dst(jd, iptr, d);
605 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
609 case ICMD_L2I: /* ..., value ==> ..., value */
610 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
611 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
612 M_INTMOVE(GET_LOW_REG(s1), d);
613 emit_store_dst(jd, iptr, d);
616 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
617 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
618 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
622 emit_store_dst(jd, iptr, d);
625 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
626 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
627 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
631 emit_store_dst(jd, iptr, d);
634 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
636 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
637 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
641 emit_store_dst(jd, iptr, d);
644 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
646 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
647 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
648 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
655 emit_store_dst(jd, iptr, d);
660 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
661 /* sx.val.i = constant */
662 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
663 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
666 if (N_VALID_IMM(iptr->sx.val.i)) {
667 M_IADD_IMM(iptr->sx.val.i, d);
669 disp = dseg_add_s4(cd, iptr->sx.val.i);
670 M_ILD(REG_ITMP2, REG_PV, disp);
671 M_IADD(REG_ITMP2, d);
673 emit_store_dst(jd, iptr, d);
676 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
678 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
680 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
681 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
682 dd = GET_HIGH_REG(d);
691 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
692 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
702 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
703 N_AHI(GET_HIGH_REG(d), 1);
705 emit_store_dst(jd, iptr, d);
708 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
709 /* sx.val.l = constant */
711 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
713 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
714 s3 = iptr->sx.val.l >> 32;
716 M_INTMOVE(s1, GET_HIGH_REG(d));
718 if (N_VALID_IMM(s3)) {
721 ICONST(REG_ITMP3, s3);
722 M_IADD(REG_ITMP3, s1);
725 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
726 s3 = iptr->sx.val.l & 0xffffffff;
727 ICONST(REG_ITMP3, s3);
729 M_INTMOVE(s1, GET_LOW_REG(d));
730 N_ALR(GET_LOW_REG(d), REG_ITMP3);
732 N_BRC(8 | 4, SZ_BRC + SZ_AHI);
733 N_AHI(GET_HIGH_REG(d), 1);
735 emit_store_dst(jd, iptr, d);
738 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
740 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
741 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
742 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
744 M_INTMOVE(s1, REG_ITMP1);
745 M_ISUB(s2, REG_ITMP1);
746 M_INTMOVE(REG_ITMP1, d);
751 emit_store_dst(jd, iptr, d);
755 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
756 /* sx.val.i = constant */
758 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
759 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
762 if (N_VALID_IMM(iptr->sx.val.i)) {
763 M_ISUB_IMM(iptr->sx.val.i, d);
765 disp = dseg_add_s4(cd, iptr->sx.val.i);
766 M_ILD(REG_ITMP2, REG_PV, disp);
767 M_ISUB(REG_ITMP2, d);
769 emit_store_dst(jd, iptr, d);
773 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
775 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
777 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
778 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
779 dd = GET_HIGH_REG(d);
782 M_INTMOVE(s2, REG_ITMP3);
789 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
790 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
794 M_INTMOVE(s2, REG_ITMP3);
801 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
802 N_AHI(GET_HIGH_REG(d), -1);
804 emit_store_dst(jd, iptr, d);
807 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
808 /* sx.val.l = constant */
810 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
812 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
813 s3 = iptr->sx.val.l >> 32;
815 M_INTMOVE(s1, GET_HIGH_REG(d));
817 if (N_VALID_IMM(-s3)) {
820 ICONST(REG_ITMP3, s3);
821 M_ISUB(REG_ITMP3, s1);
824 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
825 s3 = iptr->sx.val.l & 0xffffffff;
826 ICONST(REG_ITMP3, s3);
828 N_SLR(GET_LOW_REG(d), REG_ITMP3);
830 N_BRC(1 | 2, SZ_BRC + SZ_AHI);
831 N_AHI(GET_HIGH_REG(d), -1);
833 emit_store_dst(jd, iptr, d);
836 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
838 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
839 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
840 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
847 emit_store_dst(jd, iptr, d);
851 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
852 /* sx.val.i = constant */
853 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
854 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
856 if (iptr->sx.val.i == 2) {
858 } else if (N_VALID_IMM(iptr->sx.val.i)) {
859 M_IMUL_IMM(iptr->sx.val.i, d);
861 disp = dseg_add_s4(cd, iptr->sx.val.i);
862 M_ILD(REG_ITMP2, REG_PV, disp);
863 M_IMUL(REG_ITMP2, d);
865 emit_store_dst(jd, iptr, d);
868 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
869 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
871 /* For this operation we need a register pair.
872 * We will use r0 and itmp1 and will backup r0.
875 M_INTMOVE(R0, REG_ITMP3);
877 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
881 codegen_add_arithmeticexception_ref(cd);
883 s1 = emit_load_s1(jd, iptr, R0);
892 d = codegen_reg_of_dst(jd, iptr, R0);
896 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
897 M_INTMOVE(REG_ITMP1, d);
901 emit_store_dst(jd, iptr, d);
903 M_INTMOVE(REG_ITMP3, R0);
907 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
908 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
910 bte = iptr->sx.s23.s3.bte;
913 /* test s2 for zero */
915 s2 = emit_load_s2(jd, iptr, REG_ITMP12_PACKED);
916 M_INTMOVE(GET_LOW_REG(s2), REG_ITMP3);
917 M_IOR(GET_HIGH_REG(s2), REG_ITMP3);
919 codegen_add_arithmeticexception_ref(cd);
921 disp = dseg_add_functionptr(cd, bte->fp);
925 M_LNGMOVE(s2, PACK_REGS(REG_A3, REG_A2));
927 s1 = emit_load_s1(jd, iptr, PACK_REGS(REG_A1, REG_A0));
928 M_LNGMOVE(s1, PACK_REGS(REG_A1, REG_A0));
932 M_ASUB_IMM(96, REG_SP);
933 M_ALD(REG_ITMP3, REG_PV, disp);
934 M_JSR(REG_RA, REG_ITMP3);
935 M_AADD_IMM(96, REG_SP);
939 d = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
940 M_LNGMOVE(REG_RESULT_PACKED, d);
941 emit_store_dst(jd, iptr, d);
945 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
946 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
947 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
949 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
950 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
951 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
954 M_INTMOVE(s2, REG_ITMP2);
973 emit_store_dst(jd, iptr, d);
976 case ICMD_IDIVPOW2: /* ..., value ==> ..., value >> constant */
977 /* sx.val.i = constant */
981 assert(iptr->sx.val.i <= 32);
983 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
984 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
991 s3 = (1 << iptr->sx.val.i) - 1;
993 if (N_VALID_IMM(s3)) {
996 ICONST(REG_ITMP1, -1);
997 M_SRL_IMM(32 - iptr->sx.val.i, REG_ITMP1);
998 M_IADD(REG_ITMP1, d);
1001 *(u4 *)ref |= (u4)(cd->mcodeptr - ref) / 2;
1003 M_SRA_IMM(iptr->sx.val.i, d);
1005 emit_store_dst(jd, iptr, d);
1010 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1011 /* sx.val.i = constant */
1013 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1014 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1017 M_MOV(s1, REG_ITMP1);
1021 ICONST(REG_ITMP3, iptr->sx.val.i);
1024 M_IAND(REG_ITMP3, d);
1027 M_BGE(SZ_BRC + SZ_LCR + SZ_NR + SZ_LCR);
1033 emit_store_dst(jd, iptr, d);
1037 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1038 /* sx.val.i = constant */
1039 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1040 /* sx.val.i = constant */
1041 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1042 /* sx.val.i = constant */
1043 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1044 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1048 if (N_VALID_DISP(iptr->sx.val.i)) {
1049 disp = iptr->sx.val.i;
1052 ICONST(REG_ITMP3, iptr->sx.val.i);
1057 switch (iptr->opc) {
1058 case ICMD_ISHLCONST:
1061 case ICMD_ISHRCONST:
1064 case ICMD_IUSHRCONST:
1071 emit_store_dst(jd, iptr, d);
1074 case ICMD_LSHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1076 case ICMD_LSHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1078 case ICMD_LUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1080 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1081 s2 = emit_load_s2(jd, iptr, REG_ITMP3); /* d wont contain REG_ITMP3 */
1083 if ((s2 == GET_LOW_REG(d)) || (s2 == GET_HIGH_REG(d))) {
1084 M_INTMOVE(s2, REG_ITMP3);
1088 s1 = emit_load_s1(jd, iptr, d);
1092 switch (iptr->opc) {
1094 M_SLDA(s2, GET_HIGH_REG(d));
1097 M_SRDA(s2, GET_HIGH_REG(d));
1100 M_SRDL(s2, GET_HIGH_REG(d));
1106 emit_copy_dst(jd, iptr, d);
1107 emit_store_dst(jd, iptr, d);
1108 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1112 case ICMD_LSHLCONST: /* ..., value ==> ..., value << constant */
1113 /* sx.val.i = constant */
1114 case ICMD_LSHRCONST: /* ..., value ==> ..., value >> constant */
1115 /* sx.val.i = constant */
1116 case ICMD_LUSHRCONST: /* ..., value ==> ..., value >>> constant */
1117 /* sx.val.l = constant */
1120 d = emit_alloc_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2); /* won't contain itmp3 */
1121 s1 = emit_load_s1(jd, iptr, d);
1125 if (N_VALID_DISP(iptr->sx.val.i)) {
1126 disp = iptr->sx.val.i;
1129 ICONST(REG_ITMP3, iptr->sx.val.i);
1134 switch (iptr->opc) {
1135 case ICMD_LSHLCONST:
1136 N_SLDA(GET_HIGH_REG(d), disp, s3);
1138 case ICMD_LSHRCONST:
1139 N_SRDA(GET_HIGH_REG(d), disp, s3);
1141 case ICMD_LUSHRCONST:
1142 N_SRDL(GET_HIGH_REG(d), disp, s3);
1145 N_SLDL(GET_HIGH_REG(d), disp, s3);
1151 emit_copy_dst(jd, iptr, d);
1152 emit_store_dst(jd, iptr, d);
1153 emit_restore_dst_even_odd(jd, iptr, R0, REG_ITMP1, REG_ITMP2);
1157 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1159 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1160 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1161 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1168 emit_store_dst(jd, iptr, d);
1172 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1174 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1175 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1176 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1183 emit_store_dst(jd, iptr, d);
1187 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1189 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1190 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1191 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1198 emit_store_dst(jd, iptr, d);
1204 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1205 /* sx.val.i = constant */
1206 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1207 /* sx.val.i = constant */
1208 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1209 /* sx.val.i = constant */
1211 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1212 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1215 ICONST(REG_ITMP2, iptr->sx.val.i);
1217 switch (iptr->opc) {
1218 case ICMD_IANDCONST:
1219 M_IAND(REG_ITMP2, d);
1221 case ICMD_IXORCONST:
1222 M_IXOR(REG_ITMP2, d);
1225 M_IOR(REG_ITMP2, d);
1231 emit_store_dst(jd, iptr, d);
1235 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1236 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1237 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1239 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1241 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1242 s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
1243 dd = GET_LOW_REG(d);
1245 switch (iptr->opc) {
1274 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1275 s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
1276 dd = GET_HIGH_REG(d);
1278 switch (iptr->opc) {
1307 emit_store_dst(jd, iptr, d);
1310 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1311 /* sx.val.l = constant */
1312 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1313 /* sx.val.l = constant */
1314 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1315 /* sx.val.l = constant */
1317 /* TODO should use memory operand to access data segment, not load */
1319 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1321 s1 = emit_load_s1_low(jd, iptr, GET_LOW_REG(d));
1322 s3 = iptr->sx.val.l & 0xffffffff;
1324 M_INTMOVE(s1, GET_LOW_REG(d));
1326 ICONST(REG_ITMP3, s3);
1328 switch (iptr->opc) {
1329 case ICMD_LANDCONST:
1330 M_IAND(REG_ITMP3, GET_LOW_REG(d));
1332 case ICMD_LXORCONST:
1333 M_IXOR(REG_ITMP3, GET_LOW_REG(d));
1336 M_IOR(REG_ITMP3, GET_LOW_REG(d));
1342 s1 = emit_load_s1_high(jd, iptr, GET_HIGH_REG(d));
1343 s3 = iptr->sx.val.l >> 32;
1345 M_INTMOVE(s1, GET_HIGH_REG(d));
1347 ICONST(REG_ITMP3, s3);
1349 switch (iptr->opc) {
1350 case ICMD_LANDCONST:
1351 M_IAND(REG_ITMP3, GET_HIGH_REG(d));
1353 case ICMD_LXORCONST:
1354 M_IXOR(REG_ITMP3, GET_HIGH_REG(d));
1357 M_IOR(REG_ITMP3, GET_HIGH_REG(d));
1363 emit_store_dst(jd, iptr, d);
1367 /* floating operations ************************************************/
1369 case ICMD_FNEG: /* ..., value ==> ..., - value */
1370 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1371 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1373 emit_store_dst(jd, iptr, d);
1376 case ICMD_DNEG: /* ..., value ==> ..., - value */
1377 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1378 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1380 emit_store_dst(jd, iptr, d);
1383 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1384 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1385 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1386 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1393 emit_store_dst(jd, iptr, d);
1396 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1397 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1398 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1399 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1406 emit_store_dst(jd, iptr, d);
1409 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1410 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1411 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1412 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1416 emit_store_dst(jd, iptr, d);
1419 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1420 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1421 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1422 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1426 emit_store_dst(jd, iptr, d);
1429 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1430 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1431 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1432 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1439 emit_store_dst(jd, iptr, d);
1442 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1443 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1444 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1445 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1452 emit_store_dst(jd, iptr, d);
1455 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1456 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1457 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1458 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1462 emit_store_dst(jd, iptr, d);
1465 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1466 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1467 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1468 s2 = emit_load_s2_but(jd, iptr, REG_FTMP2, d);
1472 emit_store_dst(jd, iptr, d);
1475 case ICMD_I2F: /* ..., value ==> ..., (float) value */
1476 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1477 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1479 emit_store_dst(jd, iptr, d);
1482 case ICMD_I2D: /* ..., value ==> ..., (double) value */
1483 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1484 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1486 emit_store_dst(jd, iptr, d);
1489 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1490 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1491 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1493 emit_store_dst(jd, iptr, d);
1494 /* TODO: corner cases ? */
1497 case ICMD_D2I: /* ..., value ==> ..., (int) value */
1498 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1499 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1501 emit_store_dst(jd, iptr, d);
1502 /* TODO: corner cases ? */
1507 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1508 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1509 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1511 emit_store_dst(jd, iptr, d);
1514 case ICMD_D2F: /* ..., value ==> ..., (float) value */
1515 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1516 d = codegen_reg_of_dst(jd, iptr, REG_FTMP2);
1518 emit_store_dst(jd, iptr, d);
1521 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1522 /* == => 0, < => 1, > => -1 */
1526 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1527 /* == => 0, < => 1, > => -1 */
1530 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1531 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1532 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1534 switch (iptr->opc) {
1546 DD_H | (iptr->opc == ICMD_FCMPG || iptr->opc == ICMD_DCMPG ? DD_O : 0),
1547 SZ_BRC + SZ_BRC + SZ_BRC
1550 N_BRC( /* load -1 */
1551 DD_L | (iptr->opc == ICMD_FCMPL || iptr->opc == ICMD_DCMPL ? DD_O : 0),
1552 SZ_BRC + SZ_BRC + SZ_LHI + SZ_BRC
1557 SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI + SZ_BRC
1560 N_LHI(d, 1); /* GT */
1561 M_BR(SZ_BRC + SZ_LHI + SZ_BRC + SZ_LHI);
1562 N_LHI(d, -1); /* LT */
1563 M_BR(SZ_BRC + SZ_LHI);
1564 N_LHI(d, 0); /* EQ */
1566 emit_store_dst(jd, iptr, d);
1571 /* memory operations **************************************************/
1573 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., (int) length */
1575 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1576 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
1577 gen_nullptr_check(s1);
1578 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1579 emit_store_dst(jd, iptr, d);
1583 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1584 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1585 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1586 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1588 emit_array_checks(cd, iptr, s1, s2);
1590 N_IC(d, OFFSET(java_bytearray, data[0]), s2, s1);
1591 /* TODO improove this */
1594 emit_store_dst(jd, iptr, d);
1597 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1599 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1600 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1601 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1603 emit_array_checks(cd, iptr, s1, s2);
1605 M_INTMOVE(s2, REG_ITMP2);
1606 M_SLL_IMM(1, REG_ITMP2);
1608 N_LH(d, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1609 emit_store_dst(jd, iptr, d);
1612 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1613 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1614 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1615 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1617 emit_array_checks(cd, iptr, s1, s2);
1619 M_INTMOVE(s2, REG_ITMP2);
1620 M_SLL_IMM(1, REG_ITMP2);
1622 N_LH(d, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1623 emit_store_dst(jd, iptr, d);
1626 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1627 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1628 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1629 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1630 emit_array_checks(cd, iptr, s1, s2);
1632 M_INTMOVE(s2, REG_ITMP2);
1633 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1634 N_L(d, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1635 emit_store_dst(jd, iptr, d);
1638 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1640 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP3);
1641 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1643 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1644 emit_array_checks(cd, iptr, s1, s2);
1646 M_INTMOVE(s2, REG_ITMP2);
1647 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1649 N_L(GET_HIGH_REG(d) /* evntl. itmp1 */, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1650 N_L(GET_LOW_REG(d) /* evntl. itmp2 */, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1651 emit_store_dst(jd, iptr, d);
1655 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1657 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1658 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1659 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1660 emit_array_checks(cd, iptr, s1, s2);
1662 M_INTMOVE(s2, REG_ITMP2);
1663 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1665 N_LE(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1667 emit_store_dst(jd, iptr, d);
1670 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1671 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1672 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1673 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1674 emit_array_checks(cd, iptr, s1, s2);
1676 M_INTMOVE(s2, REG_ITMP2);
1677 M_SLL_IMM(3, REG_ITMP2); /* scale index by 8 */
1679 N_LD(d, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1681 emit_store_dst(jd, iptr, d);
1684 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1685 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1686 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1687 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1688 emit_array_checks(cd, iptr, s1, s2);
1690 M_INTMOVE(s2, REG_ITMP2);
1691 M_SLL_IMM(2, REG_ITMP2); /* scale index by 4 */
1692 N_L(d, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1693 emit_store_dst(jd, iptr, d);
1696 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1697 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1698 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
1699 emit_array_checks(cd, iptr, s1, s2);
1700 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1702 N_STC(s3, OFFSET(java_bytearray, data[0]), s2, s1);
1705 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1707 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1708 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1709 emit_array_checks(cd, iptr, s1, s2);
1710 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1712 M_INTMOVE(s2, REG_ITMP2);
1713 M_SLL_IMM(1, REG_ITMP2);
1715 N_STH(s3, OFFSET(java_chararray, data[0]), REG_ITMP2, s1);
1719 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1720 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1721 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1722 emit_array_checks(cd, iptr, s1, s2);
1723 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1725 M_INTMOVE(s2, REG_ITMP2);
1726 M_SLL_IMM(1, REG_ITMP2);
1728 N_STH(s3, OFFSET(java_shortarray, data[0]), REG_ITMP2, s1);
1731 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1733 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1734 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1735 emit_array_checks(cd, iptr, s1, s2);
1737 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1739 M_INTMOVE(s2, REG_ITMP2);
1740 M_SLL_IMM(2, REG_ITMP2);
1742 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1745 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1747 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1748 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1749 emit_array_checks(cd, iptr, s1, s2);
1751 M_INTMOVE(s2, REG_ITMP2);
1752 M_SLL_IMM(3, REG_ITMP2);
1754 s3 = emit_load_s3_high(jd, iptr, REG_ITMP3);
1755 N_ST(s3, OFFSET(java_intarray, data[0]), REG_ITMP2, s1);
1756 s3 = emit_load_s3_low(jd, iptr, REG_ITMP3);
1757 N_ST(s3, OFFSET(java_intarray, data[0]) + 4, REG_ITMP2, s1);
1760 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1761 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1762 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1763 emit_array_checks(cd, iptr, s1, s2);
1764 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1766 M_INTMOVE(s2, REG_ITMP2);
1767 M_SLL_IMM(2, REG_ITMP2);
1769 N_STE(s3, OFFSET(java_floatarray, data[0]), REG_ITMP2, s1);
1772 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1773 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1774 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1775 emit_array_checks(cd, iptr, s1, s2);
1776 s3 = emit_load_s3(jd, iptr, REG_FTMP1);
1778 M_INTMOVE(s2, REG_ITMP2);
1779 M_SLL_IMM(3, REG_ITMP2);
1781 N_STD(s3, OFFSET(java_doublearray, data[0]), REG_ITMP2, s1);
1784 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1786 s1 = emit_load_s1_notzero(jd, iptr, REG_A0);
1787 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1788 emit_array_checks(cd, iptr, s1, s2);
1789 s3 = emit_load_s3(jd, iptr, REG_A1);
1791 M_INTMOVE(s1, REG_A0);
1792 M_INTMOVE(s3, REG_A1);
1794 disp = dseg_add_functionptr(cd, BUILTIN_canstore);
1795 M_ALD(REG_ITMP3, REG_PV, disp);
1796 M_ASUB_IMM(96, REG_SP);
1797 M_JSR(REG_RA, REG_ITMP3);
1798 M_AADD_IMM(96, REG_SP);
1802 codegen_add_arraystoreexception_ref(cd);
1804 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1805 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1806 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1808 M_INTMOVE(s2, REG_ITMP2);
1809 M_SLL_IMM(2, REG_ITMP2);
1810 N_ST(s3, OFFSET(java_objectarray, data[0]), REG_ITMP2, s1);
1813 M_SAADDQ(s2, s1, REG_ITMP1); itmp1 := 4 * s2 + s1
1814 M_AST(s3, REG_ITMP1, OFFSET(java_objectarray, data[0]));
1819 case ICMD_GETSTATIC: /* ... ==> ..., value */
1821 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1822 uf = iptr->sx.s23.s3.uf;
1823 fieldtype = uf->fieldref->parseddesc.fd->type;
1824 disp = dseg_add_unique_address(cd, NULL);
1826 /* PROFILE_CYCLE_STOP; */
1828 codegen_add_patch_ref(cd, PATCHER_get_putstatic, uf, disp);
1830 /* PROFILE_CYCLE_START; */
1833 fi = iptr->sx.s23.s3.fmiref->p.field;
1834 fieldtype = fi->type;
1835 disp = dseg_add_address(cd, &(fi->value));
1837 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1840 codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, 0);
1842 PROFILE_CYCLE_START;
1846 M_ALD(REG_ITMP1, REG_PV, disp);
1848 switch (fieldtype) {
1850 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1851 M_ILD(d, REG_ITMP1, 0);
1854 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1855 M_LLD(d, REG_ITMP1, 0);
1858 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1859 M_ALD(d, REG_ITMP1, 0);
1862 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1863 M_FLD(d, REG_ITMP1, 0);
1866 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1867 M_DLD(d, REG_ITMP1, 0);
1871 emit_store_dst(jd, iptr, d);
1875 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1877 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1878 uf = iptr->sx.s23.s3.uf;
1879 fieldtype = uf->fieldref->parseddesc.fd->type;
1880 disp = dseg_add_unique_address(cd, uf);
1882 codegen_addpatchref(cd, PATCHER_get_putstatic, uf, disp);
1885 fi = iptr->sx.s23.s3.fmiref->p.field;
1886 fieldtype = fi->type;
1887 disp = dseg_add_address(cd, &(fi->value));
1889 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
1890 codegen_addpatchref(cd, PATCHER_clinit,
1894 M_ALD(REG_ITMP1, REG_PV, disp);
1895 switch (fieldtype) {
1897 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1898 M_IST(s1, REG_ITMP1, 0);
1901 s1 = emit_load_s1(jd, iptr, REG_ITMP23_PACKED);
1902 M_LST(s1, REG_ITMP1, 0);
1905 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1906 M_AST(s1, REG_ITMP1, 0);
1909 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1910 M_FST(s1, REG_ITMP1, 0);
1913 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1914 M_DST(s1, REG_ITMP1, 0);
1919 case ICMD_GETFIELD: /* ... ==> ..., value */
1921 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1922 gen_nullptr_check(s1);
1924 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1925 uf = iptr->sx.s23.s3.uf;
1926 fieldtype = uf->fieldref->parseddesc.fd->type;
1929 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1932 fi = iptr->sx.s23.s3.fmiref->p.field;
1933 fieldtype = fi->type;
1937 switch (fieldtype) {
1939 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1943 d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
1944 if (GET_HIGH_REG(d) == s1) {
1945 M_ILD(GET_LOW_REG(d), s1, disp + 4);
1946 M_ILD(GET_HIGH_REG(d), s1, disp);
1949 M_ILD(GET_LOW_REG(d), s1, disp + 4);
1950 M_ILD(GET_HIGH_REG(d), s1, disp);
1954 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1958 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1962 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1966 emit_store_dst(jd, iptr, d);
1969 case ICMD_PUTFIELD: /* ..., objectref, value ==> ... */
1971 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
1972 gen_nullptr_check(s1);
1974 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1975 uf = iptr->sx.s23.s3.uf;
1976 fieldtype = uf->fieldref->parseddesc.fd->type;
1980 fi = iptr->sx.s23.s3.fmiref->p.field;
1981 fieldtype = fi->type;
1985 if (IS_INT_LNG_TYPE(fieldtype)) {
1986 if (IS_2_WORD_TYPE(fieldtype))
1987 s2 = emit_load_s2(jd, iptr, REG_ITMP23_PACKED);
1989 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1992 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1994 if (INSTRUCTION_IS_UNRESOLVED(iptr))
1995 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1997 switch (fieldtype) {
1999 M_IST(s2, s1, disp);
2002 /* TODO really order */
2003 M_IST(GET_LOW_REG(s2), s1, disp + 4); /* keep this order */
2004 M_IST(GET_HIGH_REG(s2), s1, disp); /* keep this order */
2007 M_AST(s2, s1, disp);
2010 M_FST(s2, s1, disp);
2013 M_DST(s2, s1, disp);
2018 /* branch operations **************************************************/
2020 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
2022 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2023 M_INTMOVE(s1, REG_ITMP1_XPTR);
2027 #ifdef ENABLE_VERIFIER
2028 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2029 uc = iptr->sx.s23.s2.uc;
2031 codegen_add_patch_ref(cd, PATCHER_athrow_areturn, uc, 0);
2033 #endif /* ENABLE_VERIFIER */
2035 disp = dseg_add_functionptr(cd, asm_handle_exception);
2036 M_ALD(REG_ITMP2, REG_PV, disp);
2037 M_JMP(REG_ITMP2_XPC, REG_ITMP2);
2042 case ICMD_GOTO: /* ... ==> ... */
2043 case ICMD_RET: /* ... ==> ... */
2046 codegen_add_branch_ref(cd, iptr->dst.block);
2050 case ICMD_JSR: /* ... ==> ... */
2053 codegen_add_branch_ref(cd, iptr->sx.s23.s3.jsrtarget.block);
2057 case ICMD_IFNULL: /* ..., value ==> ... */
2058 case ICMD_IFNONNULL: /* ..., value ==> ... */
2059 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2061 switch (iptr->opc) {
2065 case ICMD_IFNONNULL:
2069 codegen_add_branch_ref(cd, iptr->dst.block);
2072 case ICMD_IFEQ: /* ..., value ==> ... */
2073 case ICMD_IFLT: /* ..., value ==> ... */
2074 case ICMD_IFLE: /* ..., value ==> ... */
2075 case ICMD_IFNE: /* ..., value ==> ... */
2076 case ICMD_IFGT: /* ..., value ==> ... */
2077 case ICMD_IFGE: /* ..., value ==> ... */
2079 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2081 if (N_VALID_IMM(iptr->sx.val.i))
2082 M_ICMP_IMM(s1, iptr->sx.val.i);
2084 disp = dseg_add_s4(cd, iptr->sx.val.i);
2085 ICONST(REG_ITMP2, disp);
2086 N_C(s1, 0, REG_ITMP2, REG_PV);
2089 switch (iptr->opc) {
2109 codegen_add_branch_ref(cd, iptr->dst.block);
2113 case ICMD_IF_LLT: /* ..., value ==> ... */
2114 case ICMD_IF_LLE: /* op1 = target JavaVM pc, val.l = constant */
2123 /* ATTENTION: compare high words signed and low words unsigned */
2125 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2127 if (N_VALID_IMM(iptr->sx.val.l >> 32))
2128 M_ICMP_IMM(s1, iptr->sx.val.l >> 32);
2130 disp = dseg_add_s4(cd, iptr->sx.val.l >> 32);
2131 ICONST(REG_ITMP2, disp);
2132 N_C(s1, 0, REG_ITMP2, REG_PV);
2139 codegen_addreference(cd, iptr->dst.block);
2140 /* EQ ... fall through */
2141 out_ref = cd->mcodeptr;
2147 codegen_addreference(cd, iptr->dst.block);
2148 /* EQ ... fall through */
2149 out_ref = cd->mcodeptr;
2153 /* EQ ... fall through */
2154 out_ref = cd->mcodeptr;
2158 /* EQ ... fall through */
2160 codegen_addreference(cd, iptr->dst.block);
2166 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2168 disp = dseg_add_s4(cd, (s4)(iptr->sx.val.l & 0xffffffff));
2169 ICONST(REG_ITMP2, disp);
2170 N_CL(s1, 0, REG_ITMP2, REG_PV);
2194 codegen_addreference(cd, iptr->dst.block);
2196 if (out_ref != NULL) {
2197 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2203 case ICMD_IF_ACMPEQ: /* ..., value, value ==> ... */
2204 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
2206 /* Compare addresses as 31 bit unsigned integers */
2208 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2209 M_LDA(REG_ITMP1, s1, 0);
2211 s2 = emit_load_s2_notzero(jd, iptr, REG_ITMP2);
2212 M_LDA(REG_ITMP2, s2, 0);
2214 M_CMP(REG_ITMP1, REG_ITMP2);
2216 switch (iptr->opc) {
2217 case ICMD_IF_ACMPEQ:
2220 case ICMD_IF_ACMPNE:
2225 codegen_add_branch_ref(cd, iptr->dst.block);
2229 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2230 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2231 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2232 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2233 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2234 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2236 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2237 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
2239 switch (iptr->opc) {
2240 case ICMD_IF_ICMPEQ:
2243 case ICMD_IF_ICMPNE:
2246 case ICMD_IF_ICMPLT:
2249 case ICMD_IF_ICMPGT:
2252 case ICMD_IF_ICMPLE:
2255 case ICMD_IF_ICMPGE:
2259 codegen_add_branch_ref(cd, iptr->dst.block);
2263 case ICMD_IF_LCMPLE: /* ..., value, value ==> ... */
2264 case ICMD_IF_LCMPLT: /* ..., value, value ==> ... */
2265 case ICMD_IF_LCMPGT: /* ..., value, value ==> ... */
2266 case ICMD_IF_LCMPGE: /* ..., value, value ==> ... */
2267 case ICMD_IF_LCMPNE: /* ..., value, value ==> ... */
2268 case ICMD_IF_LCMPEQ: /* ..., value, value ==> ... */
2273 /* ATTENTION: compare high words signed and low words unsigned */
2275 s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
2276 s2 = emit_load_s2_high(jd, iptr, REG_ITMP2);
2281 case ICMD_IF_LCMPLT:
2282 case ICMD_IF_LCMPLE:
2284 codegen_addreference(cd, iptr->dst.block);
2285 /* EQ ... fall through */
2286 out_ref = cd->mcodeptr;
2289 case ICMD_IF_LCMPGT:
2290 case ICMD_IF_LCMPGE:
2292 codegen_addreference(cd, iptr->dst.block);
2293 /* EQ ... fall through */
2294 out_ref = cd->mcodeptr;
2297 case ICMD_IF_LCMPEQ:
2298 /* EQ ... fall through */
2299 out_ref = cd->mcodeptr;
2302 case ICMD_IF_LCMPNE:
2303 /* EQ ... fall through */
2305 codegen_addreference(cd, iptr->dst.block);
2311 s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
2312 s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
2317 case ICMD_IF_LCMPLT:
2320 case ICMD_IF_LCMPLE:
2323 case ICMD_IF_LCMPGT:
2326 case ICMD_IF_LCMPGE:
2329 case ICMD_IF_LCMPEQ:
2332 case ICMD_IF_LCMPNE:
2339 codegen_addreference(cd, iptr->dst.block);
2341 if (out_ref != NULL) {
2342 *(u4 *)out_ref |= (u4)(cd->mcodeptr - out_ref) / 2;
2348 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2350 REPLACEMENT_POINT_RETURN(cd, iptr);
2351 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2352 M_INTMOVE(s1, REG_RESULT);
2353 goto nowperformreturn;
2355 case ICMD_ARETURN: /* ..., retvalue ==> ... */
2357 REPLACEMENT_POINT_RETURN(cd, iptr);
2358 s1 = emit_load_s1(jd, iptr, REG_RESULT);
2359 M_INTMOVE(s1, REG_RESULT);
2361 #ifdef ENABLE_VERIFIER
2362 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2363 unresolved_class *uc = iptr->sx.s23.s2.uc;
2365 codegen_addpatchref(cd, PATCHER_athrow_areturn, uc, 0);
2367 #endif /* ENABLE_VERIFIER */
2368 goto nowperformreturn;
2370 case ICMD_LRETURN: /* ..., retvalue ==> ... */
2372 REPLACEMENT_POINT_RETURN(cd, iptr);
2373 s1 = emit_load_s1(jd, iptr, REG_RESULT_PACKED);
2374 M_LNGMOVE(s1, REG_RESULT_PACKED);
2375 goto nowperformreturn;
2377 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2380 REPLACEMENT_POINT_RETURN(cd, iptr);
2381 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
2382 M_FLTMOVE(s1, REG_FRESULT);
2383 goto nowperformreturn;
2385 case ICMD_RETURN: /* ... ==> ... */
2387 REPLACEMENT_POINT_RETURN(cd, iptr);
2393 p = cd->stackframesize;
2395 /* call trace function */
2397 #if !defined(NDEBUG)
2398 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
2399 emit_verbosecall_exit(jd);
2400 #endif /* !defined(NDEBUG) */
2402 #if defined(ENABLE_THREADS)
2403 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2404 disp = dseg_add_functionptr(cd, LOCK_monitor_exit);
2405 M_ALD(REG_ITMP3, REG_PV, disp);
2408 /* we need to save the proper return value */
2410 switch (iptr->opc) {
2412 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2416 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2419 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2422 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2426 M_ALD(REG_A0, REG_SP, rd->memuse * 4);
2429 /* and now restore the proper return value */
2431 switch (iptr->opc) {
2433 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2437 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2440 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2443 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2449 /* restore return address */
2451 p--; M_ALD(REG_RA, REG_SP, p * 4);
2453 /* restore saved registers */
2455 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2456 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2458 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2459 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2462 /* deallocate stack */
2464 if (cd->stackframesize)
2465 M_AADD_IMM(cd->stackframesize * 4, REG_SP);
2472 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2475 branch_target_t *table;
2477 table = iptr->dst.table;
2479 l = iptr->sx.s23.s2.tablelow;
2480 i = iptr->sx.s23.s3.tablehigh;
2482 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2483 M_INTMOVE(s1, REG_ITMP1);
2487 } else if (N_VALID_IMM(-l)) {
2488 M_ISUB_IMM(l, REG_ITMP1);
2490 ICONST(REG_ITMP2, l);
2491 M_ISUB(REG_ITMP2, REG_ITMP1);
2494 /* number of targets */
2500 ICONST(REG_ITMP2, i);
2501 M_ICMPU(REG_ITMP1, REG_ITMP2);
2503 codegen_add_branch_ref(cd, table[0].block);
2505 /* build jump table top down and use address of lowest entry */
2510 dseg_add_target(cd, table->block);
2515 /* length of dataseg after last dseg_add_target is used by load */
2517 M_SLL_IMM(2, REG_ITMP1); /* scale by 4 */
2518 M_ASUB_IMM(cd->dseglen, REG_ITMP1);
2519 N_L(REG_ITMP1, 0, REG_ITMP1, REG_PV);
2520 M_JMP(RN, REG_ITMP1);
2525 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2528 lookup_target_t *lookup;
2530 lookup = iptr->dst.lookup;
2532 i = iptr->sx.s23.s2.lookupcount;
2534 MCODECHECK(8 + ((7 + 6) * i) + 5);
2535 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2538 if (N_VALID_IMM(lookup->value)) {
2539 M_ICMP_IMM(s1, lookup->value);
2541 ICONST(REG_ITMP2, lookup->value);
2542 M_ICMP(REG_ITMP2, s1);
2545 codegen_add_branch_ref(cd, lookup->target.block);
2551 codegen_add_branch_ref(cd, iptr->sx.s23.s3.lookupdefault.block);
2556 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2558 bte = iptr->sx.s23.s3.bte;
2562 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2563 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2564 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2565 case ICMD_INVOKEINTERFACE:
2567 REPLACEMENT_POINT_INVOKE(cd, iptr);
2569 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2571 um = iptr->sx.s23.s3.um;
2572 md = um->methodref->parseddesc.md;
2575 lm = iptr->sx.s23.s3.fmiref->p.method;
2577 md = lm->parseddesc;
2581 s3 = md->paramcount;
2583 MCODECHECK((s3 << 1) + 64);
2585 /* copy arguments to registers or stack location */
2587 for (s3 = s3 - 1; s3 >= 0; s3--) {
2588 var = VAR(iptr->sx.s23.s2.args[s3]);
2590 /* Already Preallocated? */
2591 if (var->flags & PREALLOC)
2594 if (IS_INT_LNG_TYPE(var->type)) {
2595 if (!md->params[s3].inmemory) {
2596 if (IS_2_WORD_TYPE(var->type)) {
2598 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2599 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]
2601 d = emit_load(jd, iptr, var, s1);
2605 s1 = rd->argintregs[md->params[s3].regoff];
2606 d = emit_load(jd, iptr, var, s1);
2611 if (IS_2_WORD_TYPE(var->type)) {
2612 d = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
2613 M_LST(d, REG_SP, md->params[s3].regoff * 4);
2616 d = emit_load(jd, iptr, var, REG_ITMP1);
2617 M_IST(d, REG_SP, md->params[s3].regoff * 4);
2622 if (!md->params[s3].inmemory) {
2623 s1 = rd->argfltregs[md->params[s3].regoff];
2624 d = emit_load(jd, iptr, var, s1);
2628 d = emit_load(jd, iptr, var, REG_FTMP1);
2629 if (IS_2_WORD_TYPE(var->type))
2630 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2632 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2637 switch (iptr->opc) {
2639 disp = dseg_add_functionptr(cd, bte->fp);
2641 M_ASUB_IMM(96, REG_SP); /* register save area as required by C abi */
2642 N_LHI(REG_ITMP1, disp);
2643 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2646 case ICMD_INVOKESPECIAL:
2648 gen_nullptr_check_intern(REG_A0);
2650 M_ILD(REG_ITMP1, REG_A0, 0); /* hardware nullptr */
2654 case ICMD_INVOKESTATIC:
2656 disp = dseg_add_unique_address(cd, um);
2658 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2662 disp = dseg_add_address(cd, lm->stubroutine);
2664 N_LHI(REG_ITMP1, disp);
2665 N_L(REG_PV, 0, REG_ITMP1, REG_PV);
2668 case ICMD_INVOKEVIRTUAL:
2669 gen_nullptr_check(REG_A0);
2672 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2677 s1 = OFFSET(vftbl_t, table[0]) +
2678 sizeof(methodptr) * lm->vftblindex;
2681 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2682 M_ALD(REG_PV, REG_METHODPTR, s1);
2685 case ICMD_INVOKEINTERFACE:
2686 gen_nullptr_check(REG_A0);
2688 /* s1 will be negative here, so use (0xFFF + s1) as displacement
2689 * and -0xFFF in index register (itmp1)
2692 N_LHI(REG_ITMP1, -N_DISP_MAX);
2695 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2701 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2702 sizeof(methodptr*) * lm->class->index +
2705 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2708 M_ALD(REG_METHODPTR, REG_A0, OFFSET(java_objectheader, vftbl));
2709 N_L(REG_METHODPTR, s1, REG_ITMP1, REG_METHODPTR);
2710 M_ALD(REG_PV, REG_METHODPTR, s2);
2714 /* generate the actual call */
2717 REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr);
2719 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2720 M_ASUB_IMM(disp, REG_PV);
2722 /* post call finalization */
2724 if (iptr->opc == ICMD_BUILTIN) {
2725 M_AADD_IMM(96, REG_SP); /* remove C abi register save area */
2728 /* actually only used for ICMD_BUILTIN */
2730 if (INSTRUCTION_MUST_CHECK(iptr)) {
2733 codegen_add_fillinstacktrace_ref(cd);
2736 /* store return value */
2738 d = md->returntype.type;
2740 if (d != TYPE_VOID) {
2741 if (IS_INT_LNG_TYPE(d)) {
2742 if (IS_2_WORD_TYPE(d)) {
2743 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
2744 M_LNGMOVE(REG_RESULT_PACKED, s1);
2747 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2748 M_INTMOVE(REG_RESULT, s1);
2752 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2753 M_FLTMOVE(REG_FRESULT, s1);
2755 emit_store_dst(jd, iptr, s1);
2761 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2763 /* val.a: (classinfo*) superclass */
2765 /* superclass is an interface:
2767 * OK if ((sub == NULL) ||
2768 * (sub->vftbl->interfacetablelength > super->index) &&
2769 * (sub->vftbl->interfacetable[-super->index] != NULL));
2771 * superclass is a class:
2773 * OK if ((sub == NULL) || (0
2774 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2775 * super->vftbl->diffval));
2778 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2779 /* object type cast-check */
2782 vftbl_t *supervftbl;
2785 u1 *class_label_refs[] = { 0 }, *class_label;
2786 u1 *exit_label_refs[] = { 0, 0, 0, 0 };
2788 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2794 super = iptr->sx.s23.s3.c.cls;
2795 superindex = super->index;
2796 supervftbl = super->vftbl;
2799 #if defined(ENABLE_THREADS)
2800 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2802 s1 = emit_load_s1_notzero(jd, iptr, REG_ITMP1);
2804 /* if class is not resolved, check which code to call */
2806 if (super == NULL) {
2808 exit_label_refs[0] = cd->mcodeptr;
2811 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
2813 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
2814 iptr->sx.s23.s3.c.ref,
2817 ICONST(REG_ITMP2, ACC_INTERFACE);
2818 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
2819 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
2820 class_label_refs[0] = cd->mcodeptr;
2824 /* interface checkcast code */
2826 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2827 if (super == NULL) {
2828 codegen_add_patch_ref(cd,
2829 PATCHER_checkcast_instanceof_interface,
2830 iptr->sx.s23.s3.c.ref,
2834 exit_label_refs[1] = cd->mcodeptr;
2838 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2839 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2840 M_ISUB_IMM(superindex, REG_ITMP3);
2842 codegen_add_classcastexception_ref(cd, s1);
2845 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
2846 superindex * sizeof(methodptr*))
2848 M_ALD(REG_ITMP2, REG_ITMP2, 0);
2851 codegen_add_classcastexception_ref(cd, s1);
2853 if (super == NULL) {
2854 exit_label_refs[2] = cd->mcodeptr;
2859 /* class checkcast code */
2861 class_label = cd->mcodeptr;
2863 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2864 if (super == NULL) {
2865 disp = dseg_add_unique_address(cd, NULL);
2867 codegen_add_patch_ref(cd,
2868 PATCHER_resolve_classref_to_vftbl,
2869 iptr->sx.s23.s3.c.ref,
2873 disp = dseg_add_address(cd, supervftbl);
2875 exit_label_refs[3] = cd->mcodeptr;
2879 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2880 M_ALD(REG_ITMP3, REG_PV, disp);
2881 #if defined(ENABLE_THREADS)
2882 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
2884 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2885 /* if (s1 != REG_ITMP1) { */
2886 /* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
2887 /* M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
2888 /* #if defined(ENABLE_THREADS) */
2889 /* codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase); */
2891 /* M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
2894 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
2895 M_ISUB(REG_ITMP3, REG_ITMP2);
2896 M_ALD(REG_ITMP3, REG_PV, disp);
2897 M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
2898 #if defined(ENABLE_THREADS)
2899 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
2902 M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
2903 /* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
2904 M_BGT(0); /* Branch if greater then */
2905 /* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
2906 codegen_add_classcastexception_ref(cd, s1);
2909 /* resolve labels by adding the correct displacement */
2911 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
2912 if (exit_label_refs[s2])
2913 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
2916 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
2917 if (class_label_refs[s2])
2918 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
2921 d = codegen_reg_of_dst(jd, iptr, s1);
2924 /* array type cast-check */
2926 s1 = emit_load_s1(jd, iptr, REG_A0);
2927 M_INTMOVE(s1, REG_A0);
2929 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2930 disp = dseg_add_unique_address(cd, NULL);
2932 codegen_add_patch_ref(cd,
2933 PATCHER_resolve_classref_to_classinfo,
2934 iptr->sx.s23.s3.c.ref,
2938 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
2940 M_ALD(REG_A1, REG_PV, disp);
2941 disp = dseg_add_functionptr(cd, BUILTIN_arraycheckcast);
2942 M_ALD(REG_ITMP1, REG_PV, disp);
2943 M_ASUB_IMM(96, REG_SP);
2944 M_JSR(REG_RA, REG_ITMP1);
2945 M_AADD_IMM(96, REG_SP);
2947 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2950 codegen_add_classcastexception_ref(cd, s1);
2952 d = codegen_reg_of_dst(jd, iptr, s1);
2956 emit_store_dst(jd, iptr, d);
2959 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2960 /* val.a: (classinfo*) superclass */
2962 /* superclass is an interface:
2964 * return (sub != NULL) &&
2965 * (sub->vftbl->interfacetablelength > super->index) &&
2966 * (sub->vftbl->interfacetable[-super->index] != NULL);
2968 * superclass is a class:
2970 * return ((sub != NULL) && (0
2971 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2972 * super->vftbl->diffvall));
2977 vftbl_t *supervftbl;
2980 u1 *class_label, *class_label_refs[1] = { 0 };
2981 u1 *exit_label_refs[4] = { 0, 0, 0, 0 };
2982 u1 *label1, *label1_refs[1] = { 0 };
2984 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2990 super = iptr->sx.s23.s3.c.cls;
2991 superindex = super->index;
2992 supervftbl = super->vftbl;
2995 #if defined(ENABLE_THREADS)
2996 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2998 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2999 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
3001 M_MOV(s1, REG_ITMP1);
3005 /* if class is not resolved, check which code to call */
3007 if (super == NULL) {
3011 exit_label_refs[0] = cd->mcodeptr;
3014 disp = dseg_add_unique_s4(cd, 0); /* super->flags */
3016 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_flags,
3017 iptr->sx.s23.s3.c.ref, disp);
3019 ICONST(REG_ITMP2, ACC_INTERFACE);
3020 ICONST(REG_ITMP3, disp); /* TODO negative displacement */
3021 N_N(REG_ITMP2, 0, REG_ITMP3, REG_PV);
3022 class_label_refs[0] = cd->mcodeptr;
3026 /* interface instanceof code */
3028 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
3029 if (super == NULL) {
3030 /* If d == REG_ITMP2, then it's destroyed in check
3035 codegen_add_patch_ref(cd,
3036 PATCHER_checkcast_instanceof_interface,
3037 iptr->sx.s23.s3.c.ref, 0);
3042 exit_label_refs[1] = cd->mcodeptr;
3046 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3047 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3048 M_ISUB_IMM(superindex, REG_ITMP3);
3049 label1_refs[0] = cd->mcodeptr;
3053 (s4) (OFFSET(vftbl_t, interfacetable[0]) -
3054 superindex * sizeof(methodptr*))
3056 M_ALD(REG_ITMP1, REG_ITMP1, 0);
3058 /* d := (REG_ITMP1 != 0) */
3060 N_LTR(d, REG_ITMP1);
3061 M_BEQ(SZ_BRC + SZ_LHI);
3064 label1 = cd->mcodeptr;
3066 if (super == NULL) {
3067 exit_label_refs[2] = cd->mcodeptr;
3072 /* class instanceof code */
3074 class_label = cd->mcodeptr;
3076 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
3077 if (super == NULL) {
3078 disp = dseg_add_unique_address(cd, NULL);
3080 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_vftbl,
3081 iptr->sx.s23.s3.c.ref,
3085 disp = dseg_add_address(cd, supervftbl);
3090 exit_label_refs[3] = cd->mcodeptr;
3094 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3095 M_ALD(REG_ITMP2, REG_PV, disp);
3096 #if defined(ENABLE_THREADS)
3097 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
3099 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3100 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3101 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3102 #if defined(ENABLE_THREADS)
3103 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
3105 M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
3107 M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
3109 M_BGT(SZ_BRC + SZ_LHI);
3113 /* resolve labels by adding the correct displacement */
3115 for (s2 = 0; s2 < sizeof(exit_label_refs) / sizeof(exit_label_refs[0]); ++s2) {
3116 if (exit_label_refs[s2])
3117 *(u4 *)exit_label_refs[s2] |= (u4)(cd->mcodeptr - exit_label_refs[s2]) / 2;
3120 for (s2 = 0; s2 < sizeof(class_label_refs) / sizeof(class_label_refs[0]); ++s2) {
3121 if (class_label_refs[s2])
3122 *(u4 *)class_label_refs[s2] |= (u4)(class_label - class_label_refs[s2]) / 2;
3125 for (s2 = 0; s2 < sizeof(label1_refs) / sizeof(label1_refs[0]); ++s2) {
3126 if (label1_refs[s2])
3127 *(u4 *)label1_refs[s2] |= (u4)(label1 - label1_refs[s2]) / 2;
3130 emit_store_dst(jd, iptr, d);
3136 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3138 /* check for negative sizes and copy sizes to stack if necessary */
3140 /*MCODECHECK((10 * 4 * iptr->s1.argcount) + 5 + 10 * 8);*/
3143 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
3145 /* copy SAVEDVAR sizes to stack */
3146 var = VAR(iptr->sx.s23.s2.args[s1]);
3148 /* Already Preallocated? */
3149 if (!(var->flags & PREALLOC)) {
3150 s2 = emit_load(jd, iptr, var, REG_ITMP1);
3151 M_IST(s2, REG_SP, s1 * 4);
3155 /* is a patcher function set? */
3157 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
3158 disp = dseg_add_unique_address(cd, 0);
3160 codegen_add_patch_ref(cd, PATCHER_resolve_classref_to_classinfo,
3161 iptr->sx.s23.s3.c.ref,
3165 disp = dseg_add_address(cd, iptr->sx.s23.s3.c.cls);
3167 /* a0 = dimension count */
3169 ICONST(REG_A0, iptr->s1.argcount);
3171 /* a1 = classinfo */
3173 M_ALD(REG_A1, REG_PV, disp);
3175 /* a2 = pointer to dimensions = stack pointer */
3177 M_MOV(REG_SP, REG_A2);
3179 disp = dseg_add_functionptr(cd, BUILTIN_multianewarray);
3180 M_ALD(REG_ITMP1, REG_PV, disp);
3181 M_ASUB_IMM(96, REG_SP);
3182 M_JSR(REG_RA, REG_ITMP1);
3183 M_AADD_IMM(96, REG_SP);
3185 /* check for exception before result assignment */
3189 codegen_add_fillinstacktrace_ref(cd);
3191 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
3192 M_INTMOVE(REG_RESULT, s1);
3193 emit_store_dst(jd, iptr, s1);
3198 exceptions_throw_internalerror("Unknown ICMD %d", iptr->opc);
3202 } /* for instruction */
3204 MCODECHECK(512); /* XXX require a lower number? */
3206 /* At the end of a basic block we may have to append some nops,
3207 because the patcher stub calling code might be longer than the
3208 actual instruction. So codepatching does not change the
3209 following block unintentionally. */
3211 if (cd->mcodeptr < cd->lastmcodeptr) {
3212 while (cd->mcodeptr < cd->lastmcodeptr) {
3217 } /* if (bptr -> flags >= BBREACHED) */
3218 } /* for basic block */
3220 dseg_createlinenumbertable(cd);
3222 /* generate stubs */
3224 emit_exception_stubs(jd);
3225 emit_patcher_stubs(jd);
3227 emit_replacement_stubs(jd);
3232 /* everything's ok */
3238 /* codegen_emit_stub_compiler **************************************************
3240 Emits a stub routine which calls the compiler.
3242 *******************************************************************************/
3244 void codegen_emit_stub_compiler(jitdata *jd)
3249 /* get required compiler data */
3254 /* code for the stub */
3256 /* don't touch ITMP3 as it cointains the return address */
3258 M_ISUB_IMM((3 * 4), REG_PV); /* suppress negative displacements */
3260 M_ILD(REG_ITMP1, REG_PV, 1 * 4); /* methodinfo */
3261 /* TODO where is methodpointer loaded into itmp2? is it already inside? */
3262 M_ILD(REG_PV, REG_PV, 0 * 4); /* compiler pointer */
3267 /* codegen_emit_stub_native ****************************************************
3269 Emits a stub routine which calls a native method.
3271 *******************************************************************************/
3274 arguments on stack \
3275 -------------------------------------------------| <- SP on nativestub entry
3277 callee saved int regs (none) |
3278 callee saved float regs (none) | stack frame like in cacao
3279 local variable slots (none) |
3280 arguments for calling methods (none) /
3281 ------------------------------------------------------------------ <- datasp
3286 96 - ... on stack parameters (nmd->memuse slots) \ stack frame like in ABI
3287 0 - 96 register save area for callee /
3288 -------------------------------------------------------- <- SP native method
3290 SP after method entry
3293 void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f)
3301 s4 i, j; /* count variables */
3306 /* get required compiler data */
3313 /* initialize variables */
3316 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3318 /* calculate stack frame size */
3320 cd->stackframesize =
3321 1 + /* r14 - return address */ +
3322 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3323 sizeof(localref_table) / SIZEOF_VOID_P +
3325 (INT_ARG_CNT + FLT_ARG_CNT) * 2 +
3326 nmd->memuse + /* parameter passing */
3327 96 / SIZEOF_VOID_P /* required by ABI */;
3329 cd->stackframesize |= 0x1; /* keep stack 8-byte aligned */
3332 /* create method header */
3334 (void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
3335 (void) dseg_add_unique_s4(cd, cd->stackframesize * 4); /* FrameSize */
3336 (void) dseg_add_unique_s4(cd, 0); /* IsSync */
3337 (void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
3338 (void) dseg_add_unique_s4(cd, 0); /* IntSave */
3339 (void) dseg_add_unique_s4(cd, 0); /* FltSave */
3340 (void) dseg_addlinenumbertablesize(cd);
3341 (void) dseg_add_unique_s4(cd, 0); /* ExTableSize */
3343 /* generate native method profiling code */
3345 if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) {
3346 /* count frequency */
3348 M_MOV_IMM(code, REG_ITMP3);
3349 M_IINC_MEMBASE(REG_ITMP3, OFFSET(codeinfo, frequency));
3353 /* generate stub code */
3355 N_AHI(REG_SP, -(cd->stackframesize * SIZEOF_VOID_P));
3357 /* save return address */
3359 N_ST(R14, (cd->stackframesize - 1) * SIZEOF_VOID_P, RN, REG_SP);
3361 #if !defined(NDEBUG)
3362 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3363 emit_verbosecall_enter(jd);
3366 /* get function address (this must happen before the stackframeinfo) */
3368 disp = dseg_add_functionptr(cd, f);
3370 #if !defined(WITH_STATIC_CLASSPATH)
3372 codegen_add_patch_ref(cd, PATCHER_resolve_native, m, disp);
3375 M_ILD(REG_ITMP1, REG_PV, disp);
3377 j = 96 + (nmd->memuse * 4);
3379 /* todo some arg registers are not volatile in C-abi terms */
3381 /* save integer and float argument registers */
3383 for (i = 0; i < md->paramcount; i++) {
3384 if (! md->params[i].inmemory) {
3385 s1 = md->params[i].regoff;
3387 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3388 if (IS_2_WORD_TYPE(t)) {
3389 /* todo store multiple */
3390 N_ST(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3391 N_ST(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3393 N_ST(rd->argintregs[s1], j, RN, REG_SP);
3396 if (IS_2_WORD_TYPE(t)) {
3397 N_STD(rd->argfltregs[s1], j, RN, REG_SP);
3399 N_STE(rd->argfltregs[s1], j, RN, REG_SP);
3407 N_ST(REG_ITMP1, j, RN, REG_SP);
3409 /* create dynamic stack info */
3411 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3412 N_LR(REG_A1, REG_PV); /* pv */
3413 N_LAE(REG_A2, cd->stackframesize * 4, RN, REG_SP); /* old SP */
3414 N_L(REG_A3, (cd->stackframesize - 1) * 4, RN, REG_SP); /* return address */
3416 disp = dseg_add_functionptr(cd, codegen_start_native_call);
3417 M_ILD(REG_ITMP1, REG_PV, disp);
3419 M_CALL(REG_ITMP1); /* call */
3421 /* restore integer and float argument registers */
3423 j = 96 + (nmd->memuse * 4);
3425 for (i = 0; i < md->paramcount; i++) {
3426 if (! md->params[i].inmemory) {
3427 s1 = md->params[i].regoff;
3429 if (IS_INT_LNG_TYPE(md->paramtypes[i].type)) {
3430 if (IS_2_WORD_TYPE(t)) {
3431 /* todo load multiple ! */
3432 N_L(rd->argintregs[GET_HIGH_REG(s1)], j, RN, REG_SP);
3433 N_L(rd->argintregs[GET_LOW_REG(s1)], j + 4, RN, REG_SP);
3435 N_L(rd->argintregs[s1], j, RN, REG_SP);
3438 if (IS_2_WORD_TYPE(t)) {
3439 N_LD(rd->argfltregs[s1], j, RN, REG_SP);
3441 N_LE(rd->argfltregs[s1], j, RN, REG_SP);
3449 N_L(REG_ITMP1, j, RN, REG_SP);
3451 /* copy or spill arguments to new locations */
3453 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3454 t = md->paramtypes[i].type;
3456 if (IS_INT_LNG_TYPE(t)) {
3458 if (!md->params[i].inmemory) {
3460 s1 = rd->argintregs[md->params[i].regoff];
3462 if (!nmd->params[j].inmemory) {
3463 s2 = rd->argintregs[nmd->params[j].regoff];
3464 if (IS_2_WORD_TYPE(t)) {
3465 N_LR(GET_HIGH_REG(s2), GET_HIGH_REG(s1));
3466 N_LR(GET_LOW_REG(s2), GET_LOW_REG(s1));
3471 s2 = nmd->params[j].regoff;
3472 if (IS_2_WORD_TYPE(t)) {
3473 N_STM(GET_LOW_REG(s1), GET_HIGH_REG(s1), 96 + (s2 * 4), REG_SP);
3475 N_ST(s1, 96 + (s2 * 4), RN, REG_SP);
3480 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3481 s2 = nmd->params[j].regoff;
3483 if (IS_2_WORD_TYPE(t)) {
3484 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3486 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3491 /* We only copy spilled float arguments, as the float argument */
3492 /* registers keep unchanged. */
3494 if (md->params[i].inmemory) {
3495 s1 = md->params[i].regoff + cd->stackframesize + 1; /* + 1 (RA) */
3496 s2 = nmd->params[j].regoff;
3498 if (IS_2_WORD_TYPE(t)) {
3499 N_MVC(96 + (s2 * 4), 8, REG_SP, s1, REG_SP);
3501 N_MVC(96 + (s2 * 4), 4, REG_SP, s1, REG_SP);
3507 /* put class into second argument register */
3509 if (m->flags & ACC_STATIC) {
3510 disp = dseg_add_address(cd, m->class);
3511 M_ILD(REG_A1, REG_PV, disp);
3514 /* put env into first argument register */
3516 disp = dseg_add_address(cd, _Jv_env);
3517 M_ILD(REG_A0, REG_PV, disp);
3519 /* do the native function call */
3521 M_CALL(REG_ITMP1); /* call */
3523 /* save return value */
3525 t = md->returntype.type;
3527 if (t != TYPE_VOID) {
3528 if (IS_INT_LNG_TYPE(t)) {
3529 if (IS_2_WORD_TYPE(t)) {
3530 N_STM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3532 N_ST(REG_RESULT, 96, RN, REG_SP);
3535 if (IS_2_WORD_TYPE(t)) {
3536 N_STD(REG_FRESULT, 96, RN, REG_SP);
3538 N_STE(REG_FRESULT, 96, RN, REG_SP);
3543 #if !defined(NDEBUG)
3544 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
3545 emit_verbosecall_exit(jd);
3548 /* remove native stackframe info */
3550 N_LAE(REG_A0, (cd->stackframesize - 1) * 4, RN, REG_SP); /* datasp */
3551 disp = dseg_add_functionptr(cd, codegen_finish_native_call);
3552 M_ILD(REG_ITMP1, REG_PV, disp);
3554 N_LR(REG_ITMP3, REG_RESULT);
3556 /* restore return value */
3558 if (t != TYPE_VOID) {
3559 if (IS_INT_LNG_TYPE(t)) {
3560 if (IS_2_WORD_TYPE(t)) {
3561 N_LM(REG_RESULT, REG_RESULT2, 96, REG_SP);
3563 N_L(REG_RESULT, 96, RN, REG_SP);
3566 if (IS_2_WORD_TYPE(t)) {
3567 N_LD(REG_FRESULT, 96, RN, REG_SP);
3569 N_LE(REG_FRESULT, 96, RN, REG_SP);
3574 /* load return address */
3576 N_L(REG_ITMP2, (cd->stackframesize - 1) * 4, RN, REG_SP);
3578 /* remove stackframe */
3580 N_AHI(REG_SP, cd->stackframesize * 4);
3582 /* test for exception */
3584 N_LTR(REG_ITMP3, REG_ITMP3);
3585 N_BRC(DD_NE, SZ_BRC + SZ_BCR);
3589 N_BCR(DD_ANY, REG_ITMP2);
3591 /* handle exception */
3593 M_MOV(REG_ITMP3, REG_ITMP1_XPTR);
3594 M_MOV(REG_ITMP2, REG_ITMP2_XPC); /* get return address from stack */
3598 M_ASUB_IMM(3, REG_ITMP2_XPC); /* callq */
3601 disp = dseg_add_functionptr(cd, asm_handle_nat_exception);
3602 M_ALD(REG_ITMP3, REG_PV, disp);
3603 M_JMP(RN, REG_ITMP3);
3605 /* generate patcher stubs */
3607 emit_patcher_stubs(jd);
3610 s4 codegen_reg_of_dst_notzero(jitdata *jd, instruction *iptr, s4 tempregnum) {
3611 codegendata *cd = jd->cd;
3612 s4 reg = codegen_reg_of_dst(jd, iptr, tempregnum);
3614 M_MOV(reg, tempregnum);
3622 * These are local overrides for various environment variables in Emacs.
3623 * Please do not remove this and leave it at the end of the file, where
3624 * Emacs will automagically detect them.
3625 * ---------------------------------------------------------------------
3628 * indent-tabs-mode: t
3632 * vim:noexpandtab:sw=4:ts=4: