1 /* src/vm/jit/powerpc64/codegen.c - machine code generator for 32-bit PowerPC
3 Copyright (C) 1996-2005, 2006 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 Contact: cacao@cacaojvm.org
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
35 $Id: codegen.c 5957 2006-11-12 12:57:59Z twisti $
49 #include "vm/jit/abi-asm.h"
51 #include "vm/jit/powerpc64/arch.h"
52 #include "vm/jit/powerpc64/codegen.h"
54 #include "mm/memory.h"
55 #include "native/native.h"
56 #include "vm/builtin.h"
57 #include "vm/exceptions.h"
58 #include "vm/global.h"
59 #include "vm/loader.h"
60 #include "vm/options.h"
61 #include "vm/stringlocal.h"
63 #include "vm/jit/asmpart.h"
64 #include "vm/jit/codegen-common.h"
65 #include "vm/jit/dseg.h"
66 #include "vm/jit/emit-common.h"
67 #include "vm/jit/jit.h"
68 #include "vm/jit/parse.h"
69 #include "vm/jit/patcher.h"
70 #include "vm/jit/reg.h"
71 #include "vm/jit/replace.h"
73 #if defined(ENABLE_LSRA)
74 # include "vm/jit/allocator/lsra.h"
78 /* codegen *********************************************************************
80 Generates machine code.
82 *******************************************************************************/
84 bool codegen(jitdata *jd)
90 s4 len, s1, s2, s3, d, disp;
97 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
98 builtintable_entry *bte;
100 rplpoint *replacementpoint;
103 unresolved_field *uf;
106 /* get required compiler data */
113 /* prevent compiler warnings */
125 /* space to save used callee saved registers */
127 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
128 savedregs_num += (FLT_SAV_CNT - rd->savfltreguse);
130 cd->stackframesize = rd->memuse + savedregs_num;
132 #if defined(ENABLE_THREADS)
133 /* space to save argument of monitor_enter and Return Values to survive */
134 /* monitor_exit. The stack position for the argument can not be shared */
135 /* with place to save the return register on PPC64, since both values */
137 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
138 /* reserve 2 slots for long/double return values for monitorexit */
139 cd->stackframesize += 2;
144 /* create method header */
146 /* align stack to 16-bytes */
149 /* if (!m->isleafmethod || opt_verbosecall) */
150 /* stackframesize = (stackframesize + 3) & ~3;
152 /* else if (m->isleafmethod && (stackframesize == LA_WORD_SIZE)) */
153 /* stackframesize = 0; */
155 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
156 (void) dseg_adds4(cd, cd->stackframesize * 8); /* FrameSize */
158 #if defined(ENABLE_THREADS)
159 /* IsSync contains the offset relative to the stack pointer for the
160 argument of monitor_exit used in the exception handler. Since the
161 offset could be zero and give a wrong meaning of the flag it is
165 if (checksync && (m->flags & ACC_SYNCHRONIZED))
166 (void) dseg_adds4(cd, (rd->memuse + 1) * 8); /* IsSync */
169 (void) dseg_adds4(cd, 0); /* IsSync */
171 (void) dseg_adds4(cd, jd->isleafmethod); /* IsLeaf */
172 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
173 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
175 dseg_addlinenumbertablesize(cd);
177 (void) dseg_adds4(cd, jd->exceptiontablelength); /* ExTableSize */
179 /* create exception table */
181 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
182 dseg_addtarget(cd, ex->start);
183 dseg_addtarget(cd, ex->end);
184 dseg_addtarget(cd, ex->handler);
185 (void) dseg_addaddress(cd, ex->catchtype.any);
188 /* create stack frame (if necessary) */
190 if (!jd->isleafmethod) {
192 M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
195 if (cd->stackframesize)
196 M_STDU(REG_SP, REG_SP, -cd->stackframesize * 8);
198 /* save return address and used callee saved registers */
200 p = cd->stackframesize;
201 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
202 p--; M_LST(rd->savintregs[i], REG_SP, p * 8);
204 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
205 p --; M_DST(rd->savfltregs[i], REG_SP, p * 8);
208 /* take arguments out of register or stack frame */
212 for (p = 0, l = 0; p < md->paramcount; p++) {
213 t = md->paramtypes[p].type;
214 varindex = jd->local_map[l*5 + t];
216 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
218 if (varindex == UNUSED)
221 s1 = md->params[p].regoff;
222 if (IS_INT_LNG_TYPE(t)) { /* integer args */
223 if (!md->params[p].inmemory) { /* register arguments */
224 s2 = rd->argintregs[s1];
225 if (!IS_INMEMORY(var->flags)) {
226 M_INTMOVE(s2, var->vv.regoff);
227 } else { /* reg arg -> spilled */
228 M_LST(s2, REG_SP, var->vv.regoff * 8);
230 } else { /* stack arguments */
231 if (!IS_INMEMORY(var->flags)) { /* stack arg -> register */
232 M_LLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 8);
234 } else { /* stack arg -> spilled */
235 var->vv.regoff = cd->stackframesize + s1;
239 } else { /* floating args */
240 if (!md->params[p].inmemory) { /* register arguments */
241 s2 = rd->argfltregs[s1];
242 if (!IS_INMEMORY(var->flags)) { /* reg arg -> register */
243 M_FLTMOVE(s2, var->vv.regoff);
244 } else { /* reg arg -> spilled */
245 M_DST(s2, REG_SP, var->vv.regoff * 8);
248 } else { /* stack arguments */
249 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
250 M_DLD(var->vv.regoff, REG_SP, (cd->stackframesize + s1) * 8);
251 } else { /* stack-arg -> spilled */
252 var->vv.regoff = cd->stackframesize + s1;
258 /* save monitorenter argument */
260 #if defined(ENABLE_THREADS)
262 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
264 /* stackoffset for argument used for LOCK_monitor_exit */
266 #if !defined (NDEBUG)
267 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
268 M_AADD_IMM(REG_SP, -((LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8), REG_SP);
270 for (p = 0; p < INT_ARG_CNT; p++)
271 M_LST(rd->argintregs[p], REG_SP, LA_SIZE + PA_SIZE + p * 8);
273 for (p = 0; p < FLT_ARG_CNT; p++)
274 M_DST(rd->argfltregs[p], REG_SP, LA_SIZE + PA_SIZE + (INT_ARG_CNT + p) * 8);
276 /* used for LOCK_monitor_exit, adopt size because we created another stackframe */
277 s1 += (LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT);
280 p = dseg_addaddress(cd, LOCK_monitor_enter);
281 M_ALD(REG_ITMP3, REG_PV, p);
282 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
285 /* get or test the lock object */
287 if (m->flags & ACC_STATIC) {
288 p = dseg_addaddress(cd, &m->class->object.header);
289 M_ALD(rd->argintregs[0], REG_PV, p);
292 M_TST(rd->argintregs[0]);
294 codegen_add_nullpointerexception_ref(cd);
297 M_AST(rd->argintregs[0], REG_SP, s1 * 8); /* rd->memuse * 8 */
299 #if !defined (NDEBUG)
300 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
301 for (p = 0; p < INT_ARG_CNT; p++)
302 M_LLD(rd->argintregs[p], REG_SP, LA_SIZE + PA_SIZE + p * 8);
304 for (p = 0; p < FLT_ARG_CNT; p++)
305 M_DLD(rd->argfltregs[p], REG_SP, LA_SIZE + PA_SIZE + (INT_ARG_CNT + p) * 8);
307 M_AADD_IMM(REG_SP, (LA_SIZE_IN_POINTERS + PA_SIZE_IN_POINTERS + ARG_CNT) * 8, REG_SP);
313 /* call trace function */
314 #if !defined (NDEBUG)
315 if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
316 emit_verbosecall_enter(jd);
321 /* end of header generation */
323 replacementpoint = jd->code->rplpoints;
325 /* walk through all basic blocks */
326 for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
328 bptr->mpc = (s4) (cd->mcodeptr - cd->mcodebase);
330 if (bptr->flags >= BBREACHED) {
332 /* branch resolving */
336 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
337 md_codegen_patch_branch(cd, brefs->branchpos, bptr->mpc);
341 /* handle replacement points */
344 if (bptr->bitflags & BBFLAG_REPLACEMENT) {
345 replacementpoint->pc = (u1*)(ptrint)bptr->mpc; /* will be resolved later */
351 /* copy interface registers to their destination */
356 #if defined(ENABLE_LSRA)
360 var = VAR(bptr->invars[len]);
361 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
362 /* d = reg_of_var(m, var, REG_ITMP1); */
363 if (!(var->flags & INMEMORY))
367 M_INTMOVE(REG_ITMP1, d);
368 emit_store(jd, NULL, var, d);
375 var = VAR(bptr->invars[len]);
376 if ((len == bptr->indepth-1) && (bptr->type == BBTYPE_EXH)) {
377 d = codegen_reg_of_var(0, var, REG_ITMP1);
378 M_INTMOVE(REG_ITMP1, d);
379 emit_store(jd, NULL, var, d);
382 assert((var->flags & INOUT));
386 #if defined(ENABLE_LSRA)
389 /* walk through all instructions */
394 for (iptr = bptr->iinstr; len > 0; len--, iptr++) {
395 bool sign_ext = false;
396 if (iptr->line != currentline) {
397 dseg_addlinenumber(cd, iptr->line);
398 currentline = iptr->line;
401 MCODECHECK(64); /* an instruction usually needs < 64 words */
404 case ICMD_NOP: /* ... ==> ... */
405 case ICMD_INLINE_START:
406 case ICMD_INLINE_END:
409 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
411 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
414 codegen_add_nullpointerexception_ref(cd);
417 /* constant operations ************************************************/
419 case ICMD_ICONST: /* ... ==> ..., constant */
421 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
422 ICONST(d, iptr->sx.val.i);
423 emit_store_dst(jd, iptr, d);
426 case ICMD_LCONST: /* ... ==> ..., constant */
428 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
429 LCONST(d, iptr->sx.val.l);
430 emit_store_dst(jd, iptr, d);
433 case ICMD_FCONST: /* ... ==> ..., constant */
435 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
436 a = dseg_addfloat(cd, iptr->sx.val.f);
438 emit_store_dst(jd, iptr, d);
441 case ICMD_DCONST: /* ... ==> ..., constant */
443 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
444 a = dseg_adddouble(cd, iptr->sx.val.d);
446 emit_store_dst(jd, iptr, d);
449 case ICMD_ACONST: /* ... ==> ..., constant */
450 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
451 disp = dseg_addaddress(cd, iptr->sx.val.anyptr);
453 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
454 codegen_addpatchref(cd, PATCHER_aconst,
458 if (opt_showdisassemble)
462 M_ALD(d, REG_PV, disp);
463 emit_store_dst(jd, iptr, d);
467 /* load/store/copy/move operations ************************************/
469 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
470 case ICMD_ALOAD: /* s1.localindex = local variable */
472 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
473 case ICMD_DLOAD: /* ... ==> ..., content of local variable */
474 case ICMD_ISTORE: /* ..., value ==> ... */
475 case ICMD_ASTORE: /* dst.localindex = local variable */
477 case ICMD_FSTORE: /* ..., value ==> ... */
478 case ICMD_DSTORE: /* ..., value ==> ... */
482 emit_copy(jd, iptr, VAROP(iptr->s1), VAROP(iptr->dst));
486 /* pop operations *****************************************************/
488 /* attention: double and longs are only one entry in CACAO ICMDs */
490 case ICMD_POP: /* ..., value ==> ... */
491 case ICMD_POP2: /* ..., value, value ==> ... */
496 /* integer operations *************************************************/
498 case ICMD_INEG: /* ..., value ==> ..., - value */
501 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
502 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
504 if (sign_ext) M_EXTSW(d, d);
505 emit_store_dst(jd, iptr, d);
509 case ICMD_I2L: /* ..., value ==> ..., value */
511 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
512 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
514 emit_store_dst(jd, iptr, d);
517 case ICMD_L2I: /* ..., value ==> ..., value */
519 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
520 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
522 emit_store_dst(jd, iptr, d);
525 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
527 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
528 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
530 emit_store_dst(jd, iptr, d);
533 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
535 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
536 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
538 emit_store_dst(jd, iptr, d);
541 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
543 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
544 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
546 emit_store_dst(jd, iptr, d);
550 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
552 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
553 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
554 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
557 emit_store_dst(jd, iptr, d);
563 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
564 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
565 if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767)) {
566 M_IADD_IMM(s1, iptr->sx.val.i, d);
568 ICONST(REG_ITMP2, iptr->sx.val.i);
569 M_IADD(s1, REG_ITMP2, d);
572 emit_store_dst(jd, iptr, d);
575 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
577 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
578 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
579 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
581 emit_store_dst(jd, iptr, d);
584 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
585 /* sx.val.l = constant */
587 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
588 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
590 if ((iptr->sx.val.l >= -32768) && (iptr->sx.val.l <= 32767)) {
591 M_LADD_IMM(s1, iptr->sx.val.l, d);
593 LCONST(REG_ITMP2, iptr->sx.val.l);
594 M_LADD(s1, REG_ITMP2, d);
596 emit_store_dst(jd, iptr, d);
599 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
601 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
602 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
603 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
605 emit_store_dst(jd, iptr, d);
608 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
609 /* sx.val.i = constant */
611 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
612 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
613 if ((iptr->sx.val.i >= -32767) && (iptr->sx.val.i <= 32768)) {
614 M_IADD_IMM(s1, -iptr->sx.val.i, d);
616 ICONST(REG_ITMP2, iptr->sx.val.i);
617 M_SUB(s1, REG_ITMP2, d);
620 emit_store_dst(jd, iptr, d);
623 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
625 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
626 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
627 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
629 emit_store_dst(jd, iptr, d);
632 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
633 /* sx.val.l = constant */
635 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
636 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
638 if ((iptr->sx.val.l >= -32767) && (iptr->sx.val.l <= 32767)) {
639 M_LADD_IMM(s1, -iptr->sx.val.l, d);
641 LCONST(REG_ITMP2, iptr->sx.val.l);
642 M_SUB(s1, REG_ITMP2, d);
644 emit_store_dst(jd, iptr, d);
649 case ICMD_LDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
651 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
652 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
653 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
656 codegen_add_arithmeticexception_ref(cd);
659 /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
660 /* we only need to check this if we did a LDIV, not for IDIV */
663 M_ANDIS(REG_ITMP2, 0x4000, REG_ITMP2); /* test OV */
665 M_MOV(s1, d); /* java specs says result == dividend */
667 if (sign_ext) M_EXTSW(d, d);
668 emit_store_dst(jd, iptr, d);
673 case ICMD_LREM: /* ..., val1, val2 ==> ..., val1 % val2 */
674 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
675 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
678 codegen_add_arithmeticexception_ref(cd);
680 M_DIV(s1, s2, REG_ITMP3);
681 /* we need to test if divident was 0x8000000000000, bit OV is set in XER in this case */
682 /* we only need to check this if we did a LDIV, not for IDIV */
685 M_ANDIS(REG_ITMP2, 0x4000, REG_ITMP2); /* test OV */
687 LCONST(REG_ITMP3, 0); /* result == 0 in this case */
690 M_MUL(REG_ITMP3, s2, REG_ITMP2);
691 M_SUB(s1, REG_ITMP2, REG_ITMP3);
692 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
695 emit_store_dst(jd, iptr, REG_ITMP1);
699 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
702 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
703 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
704 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
706 if (sign_ext) M_EXTSW(d, d);
707 emit_store_dst(jd, iptr, d);
710 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
711 /* sx.val.i = constant */
713 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
714 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
715 if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
716 M_MUL_IMM(s1, iptr->sx.val.i, d);
718 ICONST(REG_ITMP3, iptr->sx.val.i);
719 M_MUL(s1, REG_ITMP3, d);
722 emit_store_dst(jd, iptr, d);
725 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
726 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
727 if ((iptr->sx.val.l >= -32767) && (iptr->sx.val.l <= 32767))
728 M_MUL_IMM(s1, iptr->sx.val.l, d);
730 LCONST(REG_ITMP3, iptr->sx.val.l);
731 M_MUL(s1, REG_ITMP3, d);
733 emit_store_dst(jd, iptr, d);
736 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
738 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
739 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
740 M_SRA_IMM(s1, iptr->sx.val.i, d);
742 emit_store_dst(jd, iptr, d);
745 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
747 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
748 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
749 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
750 M_AND_IMM(s2, 0x1f, REG_ITMP3);
751 M_SLL(s1, REG_ITMP3, d);
753 emit_store_dst(jd, iptr, d);
756 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
757 /* sx.val.i = constant */
759 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
760 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
761 M_SLL_IMM(s1, iptr->sx.val.i & 0x1f, d);
763 emit_store_dst(jd, iptr, d);
766 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
768 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
769 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
770 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
771 M_AND_IMM(s2, 0x1f, REG_ITMP3);
772 M_SRA(s1, REG_ITMP3, d);
773 emit_store_dst(jd, iptr, d);
776 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
777 /* sx.val.i = constant */
779 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
780 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
781 M_SRA_IMM(s1, iptr->sx.val.i & 0x1f, d);
782 emit_store_dst(jd, iptr, d);
785 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
787 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
788 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
789 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
790 M_AND_IMM(s2, 0x1f, REG_ITMP2);
791 M_SRL(s1, REG_ITMP2, d);
792 emit_store_dst(jd, iptr, d);
795 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
796 /* sx.val.i = constant */
798 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
799 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
800 if (iptr->sx.val.i & 0x1f) {
801 M_SRL_IMM(s1, iptr->sx.val.i & 0x1f, d);
805 emit_store_dst(jd, iptr, d);
808 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
811 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
812 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
813 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
815 emit_store_dst(jd, iptr, d);
818 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
819 /* sx.val.i = constant */
821 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
822 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
823 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535)) {
824 M_AND_IMM(s1, iptr->sx.val.i, d);
827 else if (iptr->sx.val.i == 0xffffff) {
828 M_RLWINM(s1, 0, 8, 31, d);
832 ICONST(REG_ITMP3, iptr->sx.val.i);
833 M_AND(s1, REG_ITMP3, d);
835 emit_store_dst(jd, iptr, d);
838 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
839 /* sx.val.l = constant */
841 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
842 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
843 if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 65535))
844 M_AND_IMM(s1, iptr->sx.val.l, d);
846 else if (iptr->sx.val.l == 0xffffff) {
847 M_RLWINM(s1, 0, 8, 31, d);
851 LCONST(REG_ITMP3, iptr->sx.val.l);
852 M_AND(s1, REG_ITMP3, d);
854 emit_store_dst(jd, iptr, d);
857 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
858 /* sx.val.i = constant */
859 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
860 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
861 M_MOV(s1, REG_ITMP2);
863 M_BGE(1 + 2*(iptr->sx.val.i >= 32768));
864 if (iptr->sx.val.i >= 32768) {
865 M_ADDIS(REG_ZERO, iptr->sx.val.i >> 16, REG_ITMP2);
866 M_OR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2);
867 M_IADD(s1, REG_ITMP2, REG_ITMP2);
869 M_IADD_IMM(s1, iptr->sx.val.i, REG_ITMP2);
872 int b=0, m = iptr->sx.val.i;
875 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
877 M_SUB(s1, REG_ITMP2, d);
879 emit_store_dst(jd, iptr, d);
882 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
885 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
886 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
887 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
889 emit_store_dst(jd, iptr, d);
892 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
893 /* sx.val.i = constant */
895 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
896 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
897 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
898 M_OR_IMM(s1, iptr->sx.val.i, d);
900 ICONST(REG_ITMP3, iptr->sx.val.i);
901 M_OR(s1, REG_ITMP3, d);
903 emit_store_dst(jd, iptr, d);
906 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
907 /* sx.val.l = constant */
909 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
910 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
911 if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 65535))
912 M_OR_IMM(s1, iptr->sx.val.l, d);
914 LCONST(REG_ITMP3, iptr->sx.val.l);
915 M_OR(s1, REG_ITMP3, d);
917 emit_store_dst(jd, iptr, d);
921 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
924 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
925 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
926 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
928 emit_store_dst(jd, iptr, d);
931 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
932 /* sx.val.i = constant */
934 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
935 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
936 if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
937 M_XOR_IMM(s1, iptr->sx.val.i, d);
939 ICONST(REG_ITMP3, iptr->sx.val.i);
940 M_XOR(s1, REG_ITMP3, d);
942 emit_store_dst(jd, iptr, d);
945 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
946 /* sx.val.l = constant */
948 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
949 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
950 if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 65535))
951 M_XOR_IMM(s1, iptr->sx.val.l, d);
953 LCONST(REG_ITMP3, iptr->sx.val.l);
954 M_XOR(s1, REG_ITMP3, d);
956 emit_store_dst(jd, iptr, d);
959 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
961 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
962 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
963 d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
964 /* XXX implement me!!! */
965 emit_store_dst(jd, iptr, d);
970 /* floating operations ************************************************/
972 case ICMD_FNEG: /* ..., value ==> ..., - value */
974 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
975 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
977 emit_store_dst(jd, iptr, d);
980 case ICMD_DNEG: /* ..., value ==> ..., - value */
982 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
983 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
985 emit_store_dst(jd, iptr, d);
988 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
990 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
991 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
992 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
994 emit_store_dst(jd, iptr, d);
997 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
999 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1000 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1001 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1003 emit_store_dst(jd, iptr, d);
1006 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1008 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1009 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1010 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1012 emit_store_dst(jd, iptr, d);
1015 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1017 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1018 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1019 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1021 emit_store_dst(jd, iptr, d);
1024 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1026 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1027 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1028 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1030 emit_store_dst(jd, iptr, d);
1033 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1035 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1036 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1037 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1039 emit_store_dst(jd, iptr, d);
1042 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1044 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1045 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1046 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1048 emit_store_dst(jd, iptr, d);
1051 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1053 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1054 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1055 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1057 emit_store_dst(jd, iptr, d);
1060 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1063 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1064 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1066 disp = dseg_addfloat(cd, 0.0);
1067 M_FLD(REG_FTMP2, REG_PV, disp);
1068 M_FCMPU(s1, REG_FTMP2);
1070 disp = dseg_adds4(cd, 0);
1071 M_CVTDL_C(s1, REG_FTMP1);
1072 M_LDA(REG_ITMP1, REG_PV, disp);
1073 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1074 M_ILD(d, REG_PV, disp);
1075 emit_store_dst(jd, iptr, d);
1078 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1080 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1081 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1083 emit_store_dst(jd, iptr, d);
1086 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1088 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1089 d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
1091 emit_store_dst(jd, iptr, d);
1094 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1095 case ICMD_DCMPL: /* == => 0, < => 1, > => -1 */
1098 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1099 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1100 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1102 M_IADD_IMM(REG_ZERO, -1, d);
1105 M_IADD_IMM(REG_ZERO, 0, d);
1107 M_IADD_IMM(REG_ZERO, 1, d);
1108 emit_store_dst(jd, iptr, d);
1111 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1112 case ICMD_DCMPG: /* == => 0, < => 1, > => -1 */
1114 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1115 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1116 d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
1118 M_IADD_IMM(REG_ZERO, 1, d);
1121 M_IADD_IMM(REG_ZERO, 0, d);
1123 M_IADD_IMM(REG_ZERO, -1, d);
1124 emit_store_dst(jd, iptr, d);
1127 case ICMD_IF_FCMPEQ: /* ..., value, value ==> ... */
1128 case ICMD_IF_DCMPEQ:
1130 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1131 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1135 codegen_addreference(cd, iptr->dst.block);
1138 case ICMD_IF_FCMPNE: /* ..., value, value ==> ... */
1139 case ICMD_IF_DCMPNE:
1141 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1142 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1145 codegen_addreference(cd, iptr->dst.block);
1147 codegen_addreference(cd, iptr->dst.block);
1151 case ICMD_IF_FCMPL_LT: /* ..., value, value ==> ... */
1152 case ICMD_IF_DCMPL_LT:
1154 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1155 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1158 codegen_addreference(cd, iptr->dst.block);
1160 codegen_addreference(cd, iptr->dst.block);
1163 case ICMD_IF_FCMPL_GT: /* ..., value, value ==> ... */
1164 case ICMD_IF_DCMPL_GT:
1166 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1167 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1171 codegen_addreference(cd, iptr->dst.block);
1174 case ICMD_IF_FCMPL_LE: /* ..., value, value ==> ... */
1175 case ICMD_IF_DCMPL_LE:
1177 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1178 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1181 codegen_addreference(cd, iptr->dst.block);
1183 codegen_addreference(cd, iptr->dst.block);
1186 case ICMD_IF_FCMPL_GE: /* ..., value, value ==> ... */
1187 case ICMD_IF_DCMPL_GE:
1189 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1190 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1194 codegen_addreference(cd, iptr->dst.block);
1197 case ICMD_IF_FCMPG_LT: /* ..., value, value ==> ... */
1198 case ICMD_IF_DCMPG_LT:
1200 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1201 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1205 codegen_addreference(cd, iptr->dst.block);
1208 case ICMD_IF_FCMPG_GT: /* ..., value, value ==> ... */
1209 case ICMD_IF_DCMPG_GT:
1211 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1212 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1215 codegen_addreference(cd, iptr->dst.block);
1217 codegen_addreference(cd, iptr->dst.block);
1220 case ICMD_IF_FCMPG_LE: /* ..., value, value ==> ... */
1221 case ICMD_IF_DCMPG_LE:
1223 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1224 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1228 codegen_addreference(cd, iptr->dst.block);
1231 case ICMD_IF_FCMPG_GE: /* ..., value, value ==> ... */
1232 case ICMD_IF_DCMPG_GE:
1234 s1 = emit_load_s1(jd, iptr, REG_FTMP1);
1235 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1238 codegen_addreference(cd, iptr->dst.block);
1240 codegen_addreference(cd, iptr->dst.block);
1244 /* memory operations **************************************************/
1246 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1248 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1249 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1250 gen_nullptr_check(s1);
1251 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1252 emit_store_dst(jd, iptr, d);
1255 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1257 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1258 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1259 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1260 if (INSTRUCTION_MUST_CHECK(iptr)) {
1261 gen_nullptr_check(s1);
1264 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1265 M_LBZX(d, s1, REG_ITMP2);
1267 emit_store_dst(jd, iptr, d);
1270 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1272 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1273 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1274 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1275 if (INSTRUCTION_MUST_CHECK(iptr)) {
1276 gen_nullptr_check(s1);
1279 M_SLL_IMM(s2, 1, REG_ITMP2);
1280 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1281 M_LHAX(d, s1, REG_ITMP2);
1282 emit_store_dst(jd, iptr, d);
1285 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1287 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1288 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1289 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1290 if (INSTRUCTION_MUST_CHECK(iptr)) {
1291 gen_nullptr_check(s1);
1294 M_SLL_IMM(s2, 1, REG_ITMP2);
1295 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1296 M_LHAX(d, s1, REG_ITMP2);
1297 emit_store_dst(jd, iptr, d);
1300 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1302 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1303 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1304 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1305 if (INSTRUCTION_MUST_CHECK(iptr)) {
1306 gen_nullptr_check(s1);
1309 M_SLL_IMM(s2, 2, REG_ITMP2);
1310 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1311 M_LWZX(d, s1, REG_ITMP2);
1312 emit_store_dst(jd, iptr, d);
1315 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1317 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1318 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1319 d = codegen_reg_of_dst(jd, iptr, PACK_REGS(REG_ITMP2, REG_ITMP1));
1320 if (INSTRUCTION_MUST_CHECK(iptr)) {
1321 gen_nullptr_check(s1);
1324 M_SLL_IMM(s2, 3, REG_ITMP2);
1325 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1326 M_LLD_INTERN(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1327 emit_store_dst(jd, iptr, d);
1330 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1332 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1333 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1334 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1335 if (INSTRUCTION_MUST_CHECK(iptr)) {
1336 gen_nullptr_check(s1);
1339 M_SLL_IMM(s2, 2, REG_ITMP2);
1340 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1341 M_LFSX(d, s1, REG_ITMP2);
1342 emit_store_dst(jd, iptr, d);
1345 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1347 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1348 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1349 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1350 if (INSTRUCTION_MUST_CHECK(iptr)) {
1351 gen_nullptr_check(s1);
1354 M_SLL_IMM(s2, 3, REG_ITMP2);
1355 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1356 M_LFDX(d, s1, REG_ITMP2);
1357 emit_store_dst(jd, iptr, d);
1360 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1362 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1363 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1364 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1365 if (INSTRUCTION_MUST_CHECK(iptr)) {
1366 gen_nullptr_check(s1);
1369 M_SLL_IMM(s2, 3, REG_ITMP2);
1370 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1371 M_ALDX(d, s1, REG_ITMP2);
1372 emit_store_dst(jd, iptr, d);
1376 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1378 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1379 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1380 if (INSTRUCTION_MUST_CHECK(iptr)) {
1381 gen_nullptr_check(s1);
1384 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1385 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1386 M_STBX(s3, s1, REG_ITMP2);
1389 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1391 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1392 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1393 if (INSTRUCTION_MUST_CHECK(iptr)) {
1394 gen_nullptr_check(s1);
1397 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1398 M_SLL_IMM(s2, 1, REG_ITMP2);
1399 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1400 M_STHX(s3, s1, REG_ITMP2);
1403 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1405 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1406 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1407 if (INSTRUCTION_MUST_CHECK(iptr)) {
1408 gen_nullptr_check(s1);
1411 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1412 M_SLL_IMM(s2, 1, REG_ITMP2);
1413 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1414 M_STHX(s3, s1, REG_ITMP2);
1417 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1419 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1420 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1421 if (INSTRUCTION_MUST_CHECK(iptr)) {
1422 gen_nullptr_check(s1);
1425 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1426 M_SLL_IMM(s2, 2, REG_ITMP2);
1427 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1428 M_STWX(s3, s1, REG_ITMP2);
1431 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1433 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1434 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1435 if (INSTRUCTION_MUST_CHECK(iptr)) {
1436 gen_nullptr_check(s1);
1439 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1440 M_SLL_IMM(s2, 3, REG_ITMP2);
1441 M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
1442 M_LSTX(s3, s1, REG_ITMP2);
1445 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1447 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1448 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1449 if (INSTRUCTION_MUST_CHECK(iptr)) {
1450 gen_nullptr_check(s1);
1453 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1454 M_SLL_IMM(s2, 2, REG_ITMP2);
1455 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1456 M_STFSX(s3, s1, REG_ITMP2);
1459 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1461 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1462 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1463 if (INSTRUCTION_MUST_CHECK(iptr)) {
1464 gen_nullptr_check(s1);
1467 s3 = emit_load_s3(jd, iptr, REG_FTMP3);
1468 M_SLL_IMM(s2, 3, REG_ITMP2);
1469 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1470 M_STFDX(s3, s1, REG_ITMP2);
1473 case ICMD_AASTORE: /* ..., arrayref, index, value ==> ... */
1475 s1 = emit_load_s1(jd, iptr, rd->argintregs[0]);
1476 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1477 if (INSTRUCTION_MUST_CHECK(iptr)) {
1478 gen_nullptr_check(s1);
1481 s3 = emit_load_s3(jd, iptr, rd->argintregs[1]);
1483 disp = dseg_addaddress(cd, BUILTIN_canstore);
1484 M_ALD(REG_ITMP3, REG_PV, disp);
1485 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
1488 M_INTMOVE(s1, rd->argintregs[0]);
1489 M_INTMOVE(s3, rd->argintregs[1]);
1494 codegen_add_arraystoreexception_ref(cd);
1496 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1497 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1498 s3 = emit_load_s3(jd, iptr, REG_ITMP3);
1499 M_SLL_IMM(s2, 3, REG_ITMP2);
1500 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1501 M_ASTX(s3, s1, REG_ITMP2);
1505 case ICMD_GETSTATIC: /* ... ==> ..., value */
1507 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1508 uf = iptr->sx.s23.s3.uf;
1510 fieldtype = uf->fieldref->parseddesc.fd->type;
1511 disp = dseg_addaddress(cd, NULL);
1513 codegen_addpatchref(cd, PATCHER_get_putstatic,
1514 iptr->sx.s23.s3.uf, disp);
1516 if (opt_showdisassemble)
1520 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1522 fieldtype = fi->type;
1523 disp = dseg_addaddress(cd, &(fi->value));
1525 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1526 codegen_addpatchref(cd, PATCHER_clinit, fi->class, disp);
1528 if (opt_showdisassemble)
1533 M_ALD(REG_ITMP1, REG_PV, disp);
1534 switch (fieldtype) {
1536 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1537 M_ILD_INTERN(d, REG_ITMP1, 0);
1540 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1541 M_LLD(d, REG_ITMP1, 0);
1544 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1545 M_ALD_INTERN(d, REG_ITMP1, 0);
1548 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1549 M_FLD_INTERN(d, REG_ITMP1, 0);
1552 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1553 M_DLD_INTERN(d, REG_ITMP1, 0);
1556 emit_store_dst(jd, iptr, d);
1559 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1562 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1563 uf = iptr->sx.s23.s3.uf;
1565 fieldtype = uf->fieldref->parseddesc.fd->type;
1566 disp = dseg_addaddress(cd, NULL);
1568 codegen_addpatchref(cd, PATCHER_get_putstatic,
1569 iptr->sx.s23.s3.uf, disp);
1571 if (opt_showdisassemble)
1575 fieldinfo *fi = iptr->sx.s23.s3.fmiref->p.field;
1577 fieldtype = fi->type;
1578 disp = dseg_addaddress(cd, &(fi->value));
1580 if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
1581 codegen_addpatchref(cd, PATCHER_clinit, fi->class, disp);
1583 if (opt_showdisassemble)
1588 M_ALD(REG_ITMP1, REG_PV, disp);
1589 switch (fieldtype) {
1591 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1592 M_IST_INTERN(s1, REG_ITMP1, 0);
1595 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1596 M_LST_INTERN(s1, REG_ITMP1, 0);
1599 s1 = emit_load_s1(jd, iptr, REG_ITMP2);
1600 M_AST_INTERN(s1, REG_ITMP1, 0);
1603 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1604 M_FST_INTERN(s1, REG_ITMP1, 0);
1607 s1 = emit_load_s1(jd, iptr, REG_FTMP2);
1608 M_DST_INTERN(s1, REG_ITMP1, 0);
1614 case ICMD_GETFIELD: /* ... ==> ..., value */
1616 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1617 gen_nullptr_check(s1);
1619 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1620 uf = iptr->sx.s23.s3.uf;
1621 fieldtype = uf->fieldref->parseddesc.fd->type;
1624 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1626 if (opt_showdisassemble)
1630 fi = iptr->sx.s23.s3.fmiref->p.field;
1631 fieldtype = fi->type;
1635 switch (fieldtype) {
1637 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1641 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1645 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
1649 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1653 d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
1657 emit_store_dst(jd, iptr, d);
1660 case ICMD_PUTFIELD: /* ..., value ==> ... */
1662 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1663 gen_nullptr_check(s1);
1665 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1666 uf = iptr->sx.s23.s3.uf;
1667 fieldtype = uf->fieldref->parseddesc.fd->type;
1671 fi = iptr->sx.s23.s3.fmiref->p.field;
1672 fieldtype = fi->type;
1676 if (IS_INT_LNG_TYPE(fieldtype)) {
1677 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1680 s2 = emit_load_s2(jd, iptr, REG_FTMP2);
1682 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1683 codegen_addpatchref(cd, PATCHER_get_putfield, uf, 0);
1685 if (opt_showdisassemble)
1690 switch (fieldtype) {
1692 M_IST(s2, s1, disp);
1695 M_LST(s2, s1, disp);
1698 M_AST(s2, s1, disp);
1701 M_FST(s2, s1, disp);
1704 M_DST(s2, s1, disp);
1710 /* branch operations **************************************************/
1712 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1714 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1715 M_LNGMOVE(s1, REG_ITMP1_XPTR);
1717 #ifdef ENABLE_VERIFIER
1718 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1719 codegen_addpatchref(cd, PATCHER_athrow_areturn,
1720 iptr->sx.s23.s2.uc, 0);
1722 if (opt_showdisassemble)
1725 #endif /* ENABLE_VERIFIER */
1727 disp = dseg_addaddress(cd, asm_handle_exception);
1728 M_ALD(REG_ITMP2, REG_PV, disp);
1731 if (jd->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
1732 M_BL(0); /* get current PC */
1733 M_MFLR(REG_ITMP2_XPC);
1734 if (jd->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
1735 M_RTS; /* jump to CTR */
1740 case ICMD_GOTO: /* ... ==> ... */
1741 case ICMD_RET: /* ... ==> ... */
1744 codegen_addreference(cd, iptr->dst.block);
1748 case ICMD_JSR: /* ... ==> ... */
1751 codegen_addreference(cd, iptr->sx.s23.s3.jsrtarget.block);
1755 case ICMD_IFNULL: /* ..., value ==> ... */
1757 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1760 codegen_addreference(cd, iptr->dst.block);
1763 case ICMD_IFNONNULL: /* ..., value ==> ... */
1765 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1768 codegen_addreference(cd, iptr->dst.block);
1776 case ICMD_IFEQ: /* ..., value ==> ... */
1778 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1779 if ((iptr->sx.val.i >= -32768) && (iptr->sx.val.i <= 32767))
1780 M_CMPI(s1, iptr->sx.val.i);
1782 ICONST(REG_ITMP2, iptr->sx.val.i);
1783 M_CMP(s1, REG_ITMP2);
1785 switch (iptr->opc) {
1805 codegen_addreference(cd, iptr->dst.block);
1808 case ICMD_IF_LEQ: /* ..., value ==> ... */
1809 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1810 LCONST(REG_ITMP2, iptr->sx.val.l);
1811 M_CMP(s1, REG_ITMP2);
1813 codegen_addreference(cd, iptr->dst.block);
1815 case ICMD_IF_LLT: /* ..., value ==> ... */
1816 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1817 LCONST(REG_ITMP2, iptr->sx.val.l);
1818 M_CMP(s1, REG_ITMP2);
1820 codegen_addreference(cd, iptr->dst.block);
1822 case ICMD_IF_LLE: /* ..., value ==> ... */
1823 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1824 LCONST(REG_ITMP2, iptr->sx.val.l);
1825 M_CMP(s1, REG_ITMP2);
1827 codegen_addreference(cd, iptr->dst.block);
1830 case ICMD_IF_LNE: /* ..., value ==> ... */
1831 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1832 LCONST(REG_ITMP2, iptr->sx.val.l);
1833 M_CMP(s1, REG_ITMP2);
1835 codegen_addreference(cd, iptr->dst.block);
1837 case ICMD_IF_LGE: /* ..., value ==> ... */
1838 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1839 LCONST(REG_ITMP2, iptr->sx.val.l);
1840 M_CMP(s1, REG_ITMP2);
1842 codegen_addreference(cd, iptr->dst.block);
1844 case ICMD_IF_LGT: /* ..., value ==> ... */
1845 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1846 LCONST(REG_ITMP2, iptr->sx.val.l);
1847 M_CMP(s1, REG_ITMP2);
1849 codegen_addreference(cd, iptr->dst.block);
1851 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
1852 case ICMD_IF_ACMPEQ: /* op1 = target JavaVM pc */
1853 case ICMD_IF_LCMPEQ:
1855 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1856 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1859 codegen_addreference(cd, iptr->dst.block);
1862 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
1863 case ICMD_IF_ACMPNE: /* op1 = target JavaVM pc */
1864 case ICMD_IF_LCMPNE:
1866 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1867 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1870 codegen_addreference(cd, iptr->dst.block);
1874 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
1875 case ICMD_IF_LCMPLT:
1877 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1878 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1881 codegen_addreference(cd, iptr->dst.block);
1884 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
1885 case ICMD_IF_LCMPGT:
1887 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1888 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1891 codegen_addreference(cd, iptr->dst.block);
1894 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
1895 case ICMD_IF_LCMPLE:
1897 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1898 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1901 codegen_addreference(cd, iptr->dst.block);
1904 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
1905 case ICMD_IF_LCMPGE:
1907 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
1908 s2 = emit_load_s2(jd, iptr, REG_ITMP2);
1911 codegen_addreference(cd, iptr->dst.block);
1915 case ICMD_LRETURN: /* ..., retvalue ==> ... */
1916 case ICMD_IRETURN: /* ..., retvalue ==> ... */
1918 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1919 M_LNGMOVE(s1, REG_RESULT);
1920 goto nowperformreturn;
1922 case ICMD_ARETURN: /* ..., retvalue ==> ... */
1924 s1 = emit_load_s1(jd, iptr, REG_RESULT);
1925 M_LNGMOVE(s1, REG_RESULT);
1927 #ifdef ENABLE_VERIFIER
1928 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1929 codegen_addpatchref(cd, PATCHER_athrow_areturn,
1930 iptr->sx.s23.s2.uc, 0);
1932 if (opt_showdisassemble)
1935 #endif /* ENABLE_VERIFIER */
1937 goto nowperformreturn;
1939 case ICMD_FRETURN: /* ..., retvalue ==> ... */
1942 s1 = emit_load_s1(jd, iptr, REG_FRESULT);
1943 M_FLTMOVE(s1, REG_FRESULT);
1944 goto nowperformreturn;
1946 case ICMD_RETURN: /* ... ==> ... */
1952 p = cd->stackframesize;
1954 /* call trace function */
1956 #if !defined(NDEBUG)
1957 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
1958 emit_verbosecall_exit(jd);
1962 #if defined(ENABLE_THREADS)
1963 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
1964 disp = dseg_addaddress(cd, LOCK_monitor_exit);
1965 M_ALD(REG_ITMP3, REG_PV, disp);
1966 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
1969 /* we need to save the proper return value */
1971 switch (iptr->opc) {
1976 M_LST(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1979 M_FST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1982 M_DST(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
1986 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 8);
1989 /* and now restore the proper return value */
1991 switch (iptr->opc) {
1996 M_LLD(REG_RESULT , REG_SP, rd->memuse * 8 + 8);
1999 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
2002 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 8 + 8);
2008 /* restore return address */
2010 if (!jd->isleafmethod) {
2011 /* ATTENTION: Don't use REG_ZERO (r0) here, as M_ALD
2012 may have a displacement overflow. */
2014 M_ALD(REG_ITMP1, REG_SP, p * 8 + LA_LR_OFFSET);
2018 /* restore saved registers */
2020 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2021 p--; M_LLD(rd->savintregs[i], REG_SP, p * 8);
2023 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2024 p--; M_DLD(rd->savfltregs[i], REG_SP, p * 8);
2027 /* deallocate stack */
2029 if (cd->stackframesize)
2030 M_LDA(REG_SP, REG_SP, cd->stackframesize * 8);
2038 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2041 branch_target_t *table;
2043 table = iptr->dst.table;
2045 l = iptr->sx.s23.s2.tablelow;
2046 i = iptr->sx.s23.s3.tablehigh;
2048 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2050 M_INTMOVE(s1, REG_ITMP1);
2051 } else if (l <= 32768) {
2052 M_LDA(REG_ITMP1, s1, -l);
2054 ICONST(REG_ITMP2, l);
2055 M_SUB(s1, REG_ITMP2, REG_ITMP1);
2058 /* number of targets */
2063 M_CMPUI(REG_ITMP1, i - 1);
2065 codegen_addreference(cd, table[0].block);
2067 /* build jump table top down and use address of lowest entry */
2072 dseg_addtarget(cd, table->block);
2077 /* length of dataseg after last dseg_addtarget is used by load */
2079 M_SLL_IMM(REG_ITMP1, 3, REG_ITMP1);
2080 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2081 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2088 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2091 lookup_target_t *lookup;
2093 lookup = iptr->dst.lookup;
2095 i = iptr->sx.s23.s2.lookupcount;
2097 MCODECHECK((i<<2)+8);
2098 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2100 val = lookup->value;
2101 if ((val >= -32768) && (val <= 32767)) {
2104 a = dseg_adds4(cd, val);
2105 M_ILD(REG_ITMP2, REG_PV, a);
2106 M_CMP(s1, REG_ITMP2);
2109 codegen_addreference(cd, lookup->target.block);
2114 codegen_addreference(cd, iptr->sx.s23.s3.lookupdefault.block);
2121 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2123 bte = iptr->sx.s23.s3.bte;
2127 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2129 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2130 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2131 case ICMD_INVOKEINTERFACE:
2133 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2134 md = iptr->sx.s23.s3.um->methodref->parseddesc.md;
2138 lm = iptr->sx.s23.s3.fmiref->p.method;
2139 md = lm->parseddesc;
2143 s3 = md->paramcount;
2145 MCODECHECK((s3 << 1) + 64);
2147 /* copy arguments to registers or stack location */
2149 for (s3 = s3 - 1; s3 >= 0; s3--) {
2150 var = VAR(iptr->sx.s23.s2.args[s3]);
2152 if (var->flags & PREALLOC)
2155 if (IS_INT_LNG_TYPE(var->type)) {
2156 if (!md->params[s3].inmemory) {
2157 s1 = rd->argintregs[md->params[s3].regoff];
2158 d = emit_load(jd, iptr, var, s1);
2161 d = emit_load(jd, iptr, var, REG_ITMP1);
2162 M_LST(d, REG_SP, md->params[s3].regoff * 8);
2165 if (!md->params[s3].inmemory) {
2166 s1 = rd->argfltregs[md->params[s3].regoff];
2167 d = emit_load(jd, iptr, var, s1);
2170 d = emit_load(jd, iptr, var, REG_FTMP1);
2171 if (IS_2_WORD_TYPE(var->type))
2172 M_DST(d, REG_SP, md->params[s3].regoff * 8);
2174 M_FST(d, REG_SP, md->params[s3].regoff * 8);
2179 switch (iptr->opc) {
2181 disp = dseg_addaddress(cd, bte->fp);
2182 d = md->returntype.type;
2184 M_ALD(REG_PV, REG_PV, disp); /* pointer to built-in-function descriptor */
2185 M_ALD(REG_ITMP1, REG_PV, 0); /* function entry point address, what about TOC */
2189 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2191 M_LDA(REG_PV, REG_ITMP1, -disp);
2194 if (INSTRUCTION_MUST_CHECK(iptr)) {
2195 M_CMPI(REG_RESULT, 0);
2197 codegen_add_fillinstacktrace_ref(cd);
2201 case ICMD_INVOKESPECIAL:
2202 gen_nullptr_check(rd->argintregs[0]);
2203 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr */
2206 case ICMD_INVOKESTATIC:
2208 unresolved_method *um = iptr->sx.s23.s3.um;
2210 disp = dseg_addaddress(cd, NULL);
2212 codegen_addpatchref(cd, PATCHER_invokestatic_special,
2215 if (opt_showdisassemble)
2218 d = md->returntype.type;
2221 disp = dseg_addaddress(cd, lm->stubroutine);
2222 d = md->returntype.type;
2226 M_ALD(REG_PV, REG_PV, disp);
2229 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2231 M_LDA(REG_PV, REG_ITMP1, -disp);
2234 case ICMD_INVOKEVIRTUAL:
2235 gen_nullptr_check(rd->argintregs[0]);
2238 unresolved_method *um = iptr->sx.s23.s3.um;
2240 codegen_addpatchref(cd, PATCHER_invokevirtual, um, 0);
2242 if (opt_showdisassemble)
2246 d = md->returntype.type;
2249 s1 = OFFSET(vftbl_t, table[0]) +
2250 sizeof(methodptr) * lm->vftblindex;
2251 d = md->returntype.type;
2254 M_ALD(REG_METHODPTR, rd->argintregs[0],
2255 OFFSET(java_objectheader, vftbl));
2256 M_ALD(REG_PV, REG_METHODPTR, s1);
2259 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2261 M_LDA(REG_PV, REG_ITMP1, -disp);
2264 case ICMD_INVOKEINTERFACE:
2265 gen_nullptr_check(rd->argintregs[0]);
2268 unresolved_method *um = iptr->sx.s23.s3.um;
2270 codegen_addpatchref(cd, PATCHER_invokeinterface, um, 0);
2272 if (opt_showdisassemble)
2277 d = md->returntype.type;
2280 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2281 sizeof(methodptr*) * lm->class->index;
2283 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2285 d = md->returntype.type;
2288 M_ALD(REG_METHODPTR, rd->argintregs[0],
2289 OFFSET(java_objectheader, vftbl));
2290 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2291 M_ALD(REG_PV, REG_METHODPTR, s2);
2294 disp = (s4) (cd->mcodeptr - cd->mcodebase);
2296 M_LDA(REG_PV, REG_ITMP1, -disp);
2300 /* d contains return type */
2302 if (d != TYPE_VOID) {
2303 if (IS_INT_LNG_TYPE(d)) {
2304 s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2305 M_MOV(REG_RESULT, s1);
2307 s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
2308 M_FLTMOVE(REG_FRESULT, s1);
2310 emit_store_dst(jd, iptr, s1);
2315 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2316 /* val.a: (classinfo*) superclass */
2318 /* superclass is an interface:
2320 * OK if ((sub == NULL) ||
2321 * (sub->vftbl->interfacetablelength > super->index) &&
2322 * (sub->vftbl->interfacetable[-super->index] != NULL));
2324 * superclass is a class:
2326 * OK if ((sub == NULL) || (0
2327 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2328 * super->vftbl->diffvall));
2331 if (!(iptr->flags.bits & INS_FLAG_ARRAY)) {
2332 /* object type cast-check */
2337 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2341 super = iptr->sx.s23.s3.c.cls;
2342 superindex = super->index;
2345 #if defined(ENABLE_THREADS)
2346 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2348 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2350 /* calculate interface checkcast code size */
2354 s2 += (opt_showdisassemble ? 1 : 0);
2356 /* calculate class checkcast code size */
2358 s3 = 9 + (s1 == REG_ITMP1);
2360 s3 += (opt_showdisassemble ? 1 : 0);
2362 /* if class is not resolved, check which code to call */
2364 if (super == NULL) {
2366 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
2368 disp = dseg_adds4(cd, 0); /* super->flags */
2370 codegen_addpatchref(cd,
2371 PATCHER_checkcast_instanceof_flags,
2372 iptr->sx.s23.s3.c.ref,
2375 if (opt_showdisassemble)
2378 M_ILD(REG_ITMP2, REG_PV, disp);
2379 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2383 /* interface checkcast code */
2385 if ((super == NULL) || (super->flags & ACC_INTERFACE)) {
2386 if (super == NULL) {
2387 codegen_addpatchref(cd,
2388 PATCHER_checkcast_instanceof_interface,
2389 iptr->sx.s23.s3.c.ref,
2391 if (opt_showdisassemble)
2399 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2400 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2401 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2403 codegen_add_classcastexception_ref(cd, s1); /*XXX s1?? */
2404 M_ALD(REG_ITMP3, REG_ITMP2,
2405 OFFSET(vftbl_t, interfacetable[0]) -
2406 superindex * sizeof(methodptr*));
2409 codegen_add_classcastexception_ref(cd, s1); /*XXX s1??*/
2415 /* class checkcast code */
2417 if ((super == NULL) || !(super->flags & ACC_INTERFACE)) {
2418 if (super == NULL) {
2419 disp = dseg_add_unique_address(cd, NULL);
2420 codegen_addpatchref(cd, PATCHER_checkcast_class,
2421 iptr->sx.s23.s3.c.ref,
2423 if (opt_showdisassemble)
2426 disp = dseg_addaddress(cd, super->vftbl);
2431 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2432 #if defined(ENABLE_THREADS)
2433 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
2435 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2436 M_ALD(REG_ITMP2, REG_PV, disp);
2437 if (s1 != REG_ITMP1) {
2438 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2439 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2440 #if defined(ENABLE_THREADS)
2441 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
2443 M_SUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2444 M_EXTSW(REG_ITMP3, REG_ITMP3);
2446 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2447 M_SUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2448 M_EXTSW(REG_ITMP3, REG_ITMP3);
2449 M_ALD(REG_ITMP2, REG_PV, disp);
2450 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2451 #if defined(ENABLE_THREADS)
2452 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
2455 M_CMPU(REG_ITMP3, REG_ITMP2);
2457 codegen_add_classcastexception_ref(cd, s1); /* XXX s1? */
2459 d = codegen_reg_of_dst(jd, iptr, s1);
2462 /* array type cast-check */
2464 s1 = emit_load_s1(jd, iptr, rd->argintregs[0]);
2465 M_INTMOVE(s1, rd->argintregs[0]);
2468 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2469 disp = dseg_addaddress(cd, NULL);
2470 codegen_addpatchref(cd, PATCHER_builtin_arraycheckcast,
2471 iptr->sx.s23.s3.c.ref,
2474 if (opt_showdisassemble)
2477 disp = dseg_addaddress(cd, iptr->sx.s23.s3.c.cls);
2480 M_ALD(rd->argintregs[1], REG_PV, disp);
2481 disp = dseg_addaddress(cd, BUILTIN_arraycheckcast);
2482 M_ALD(REG_ITMP2, REG_PV, disp);
2483 M_ALD(REG_ITMP2, REG_ITMP2, 0); /* TOC */
2488 codegen_add_classcastexception_ref(cd, s1); /* XXX s1? */
2490 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2491 d = codegen_reg_of_dst(jd, iptr, s1);
2494 emit_store_dst(jd, iptr, d);
2497 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2498 /* val.a: (classinfo*) superclass */
2500 /* superclass is an interface:
2502 * return (sub != NULL) &&
2503 * (sub->vftbl->interfacetablelength > super->index) &&
2504 * (sub->vftbl->interfacetable[-super->index] != NULL);
2506 * superclass is a class:
2508 * return ((sub != NULL) && (0
2509 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2510 * super->vftbl->diffvall));
2515 vftbl_t *supervftbl;
2518 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2524 super = iptr->sx.s23.s3.c.cls;
2525 superindex = super->index;
2526 supervftbl = super->vftbl;
2529 #if defined(ENABLE_THREADS)
2530 codegen_threadcritrestart(cd, cd->mcodeptr - cd->mcodebase);
2532 s1 = emit_load_s1(jd, iptr, REG_ITMP1);
2533 d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
2535 M_MOV(s1, REG_ITMP1);
2539 /* calculate interface instanceof code size */
2543 s2 += (opt_showdisassemble ? 1 : 0);
2545 /* calculate class instanceof code size */
2549 s3 += (opt_showdisassemble ? 1 : 0);
2553 /* if class is not resolved, check which code to call */
2557 M_BEQ(3 + (opt_showdisassemble ? 1 : 0) + s2 + 1 + s3);
2559 disp = dseg_adds4(cd, 0); /* super->flags */
2561 codegen_addpatchref(cd, PATCHER_checkcast_instanceof_flags,
2562 iptr->sx.s23.s3.c.ref, disp);
2564 if (opt_showdisassemble)
2567 M_ILD(REG_ITMP3, REG_PV, disp);
2568 M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
2572 /* interface instanceof code */
2574 if (!super || (super->flags & ACC_INTERFACE)) {
2580 codegen_addpatchref(cd,
2581 PATCHER_checkcast_instanceof_interface,
2582 iptr->sx.s23.s3.c.ref, 0);
2584 if (opt_showdisassemble)
2588 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2589 M_ILD(REG_ITMP3, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2590 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2592 M_ALD(REG_ITMP1, REG_ITMP1,
2593 OFFSET(vftbl_t, interfacetable[0]) -
2594 superindex * sizeof(methodptr*));
2597 M_IADD_IMM(REG_ZERO, 1, d);
2603 /* class instanceof code */
2605 if (!super || !(super->flags & ACC_INTERFACE)) {
2606 disp = dseg_addaddress(cd, supervftbl);
2613 codegen_addpatchref(cd, PATCHER_instanceof_class,
2614 iptr->sx.s23.s3.c.ref,
2617 if (opt_showdisassemble) {
2622 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2623 M_ALD(REG_ITMP2, REG_PV, disp);
2624 #if defined(ENABLE_THREADS)
2625 codegen_threadcritstart(cd, cd->mcodeptr - cd->mcodebase);
2627 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2628 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2629 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2630 #if defined(ENABLE_THREADS)
2631 codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase);
2633 M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2634 M_CMPU(REG_ITMP1, REG_ITMP2);
2637 M_IADD_IMM(REG_ZERO, 1, d);
2639 emit_store_dst(jd, iptr, d);
2643 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2645 /* check for negative sizes and copy sizes to stack if necessary */
2647 MCODECHECK((iptr->s1.argcount << 1) + 64);
2649 for (s1 = iptr->s1.argcount; --s1 >= 0; ) {
2651 var = VAR(iptr->sx.s23.s2.args[s1]);
2653 /* copy SAVEDVAR sizes to stack */
2655 if (!(var->flags & PREALLOC)) {
2656 s2 = emit_load(jd, iptr, var, REG_ITMP1);
2657 #if defined(__DARWIN__)
2658 M_LST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 8);
2660 M_LST(s2, REG_SP, LA_SIZE + (s1 + 3) * 8);
2665 /* a0 = dimension count */
2667 ICONST(rd->argintregs[0], iptr->s1.argcount);
2669 /* is patcher function set? */
2671 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
2672 disp = dseg_add_unique_address(cd, NULL);
2674 codegen_addpatchref(cd, PATCHER_builtin_multianewarray,
2675 iptr->sx.s23.s3.c.ref, disp);
2677 if (opt_showdisassemble)
2681 disp = dseg_addaddress(cd, iptr->sx.s23.s3.c.cls);
2684 /* a1 = arraydescriptor */
2686 M_ALD(rd->argintregs[1], REG_PV, disp);
2688 /* a2 = pointer to dimensions = stack pointer */
2690 #if defined(__DARWIN__)
2691 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 8);
2693 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 8);
2696 disp = dseg_addaddress(cd, BUILTIN_multianewarray);
2697 M_ALD(REG_ITMP3, REG_PV, disp);
2698 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
2702 /* check for exception before result assignment */
2704 M_CMPI(REG_RESULT, 0);
2706 codegen_add_fillinstacktrace_ref(cd);
2708 d = codegen_reg_of_dst(jd, iptr, REG_RESULT);
2709 M_INTMOVE(REG_RESULT, d);
2710 emit_store_dst(jd, iptr, d);
2715 new_internalerror("Unknown ICMD %d during code generation",
2720 } /* for instruction */
2722 } /* if (bptr -> flags >= BBREACHED) */
2723 } /* for basic block */
2725 dseg_createlinenumbertable(cd);
2728 /* generate exception and patcher stubs */
2737 savedmcodeptr = NULL;
2739 /* generate exception stubs */
2741 for (eref = cd->exceptionrefs; eref != NULL; eref = eref->next) {
2742 md_codegen_patch_branch(cd, eref->branchpos, cd->mcodeptr - cd->mcodebase);
2746 /* Check if the exception is an
2747 ArrayIndexOutOfBoundsException. If so, move index register
2750 if (eref->reg != -1)
2751 M_MOV(eref->reg, REG_ITMP1);
2753 /* calcuate exception address */
2755 M_LDA(REG_ITMP2_XPC, REG_PV, eref->branchpos - 4);
2757 /* move function to call into REG_ITMP3 */
2759 disp = dseg_addaddress(cd, eref->function);
2760 M_ALD(REG_ITMP3, REG_PV, disp);
2761 M_ALD(REG_ITMP3, REG_ITMP3, 0); /* TOC */
2763 if (savedmcodeptr != NULL) {
2764 disp = ((u4 *) savedmcodeptr) - (((u4 *) cd->mcodeptr) + 1);
2768 savedmcodeptr = cd->mcodeptr;
2770 if (jd->isleafmethod) {
2772 M_AST(REG_ZERO, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
2775 M_MOV(REG_PV, rd->argintregs[0]);
2776 M_MOV(REG_SP, rd->argintregs[1]);
2778 if (jd->isleafmethod)
2779 M_MOV(REG_ZERO, rd->argintregs[2]);
2781 M_ALD(rd->argintregs[2],
2782 REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
2784 M_MOV(REG_ITMP2_XPC, rd->argintregs[3]);
2785 M_MOV(REG_ITMP1, rd->argintregs[4]);
2787 M_STDU(REG_SP, REG_SP, -(LA_SIZE + 6 * 8));
2788 M_AST(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 8);
2792 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
2794 M_ALD(REG_ITMP2_XPC, REG_SP, LA_SIZE + 5 * 8);
2795 M_LADD_IMM(REG_SP, LA_SIZE + 6 * 8, REG_SP);
2797 if (jd->isleafmethod) {
2798 /* XXX FIXME: REG_ZERO can cause problems here! */
2799 assert(cd->stackframesize * 8 <= 32767);
2801 M_ALD(REG_ZERO, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
2805 disp = dseg_addaddress(cd, asm_handle_exception);
2806 M_ALD(REG_ITMP3, REG_PV, disp);
2813 /* generate code patching stub call code */
2815 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
2816 /* check code segment size */
2820 /* Get machine code which is patched back in later. The
2821 call is 1 instruction word long. */
2823 tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
2825 mcode = *((u4 *) tmpmcodeptr);
2827 /* Patch in the call to call the following code (done at
2830 savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
2831 cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
2833 disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
2836 cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
2838 /* create stack frame - keep stack 16-byte aligned */
2840 M_AADD_IMM(REG_SP, -8 * 8, REG_SP);
2842 /* calculate return address and move it onto the stack */
2844 M_LDA(REG_ITMP3, REG_PV, pref->branchpos);
2845 M_AST_INTERN(REG_ITMP3, REG_SP, 5 * 8);
2847 /* move pointer to java_objectheader onto stack */
2849 #if defined(ENABLE_THREADS)
2850 /* order reversed because of data segment layout */
2852 (void) dseg_addaddress(cd, NULL); /* flcword */
2853 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
2854 disp = dseg_addaddress(cd, NULL); /* vftbl */
2856 M_LDA(REG_ITMP3, REG_PV, disp);
2857 M_AST_INTERN(REG_ITMP3, REG_SP, 4 * 8);
2862 /* move machine code onto stack */
2864 disp = dseg_adds4(cd, mcode);
2865 M_ILD(REG_ITMP3, REG_PV, disp);
2866 M_IST_INTERN(REG_ITMP3, REG_SP, 3 * 8);
2868 /* move class/method/field reference onto stack */
2870 disp = dseg_addaddress(cd, pref->ref);
2871 M_ALD(REG_ITMP3, REG_PV, disp);
2872 M_AST_INTERN(REG_ITMP3, REG_SP, 2 * 8);
2874 /* move data segment displacement onto stack */
2876 disp = dseg_addaddress(cd, pref->disp);
2877 M_LLD(REG_ITMP3, REG_PV, disp);
2878 M_IST_INTERN(REG_ITMP3, REG_SP, 1 * 8);
2880 /* move patcher function pointer onto stack */
2882 disp = dseg_addaddress(cd, pref->patcher);
2883 M_ALD(REG_ITMP3, REG_PV, disp);
2884 M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 8);
2886 disp = dseg_addaddress(cd, asm_patcher_wrapper);
2887 M_ALD(REG_ITMP3, REG_PV, disp);
2892 /* generate replacement-out stubs */
2898 replacementpoint = jd->code->rplpoints;
2900 for (i = 0; i < jd->code->rplpointcount; ++i, ++replacementpoint) {
2901 /* check code segment size */
2905 /* note start of stub code */
2907 replacementpoint->outcode = (u1 *) (cd->mcodeptr - cd->mcodebase);
2909 /* make machine code for patching */
2911 tmpmcodeptr = cd->mcodeptr;
2912 cd->mcodeptr = (u1 *) &(replacementpoint->mcode) + 1 /* big-endian */;
2914 disp = (ptrint)((s4*)replacementpoint->outcode - (s4*)replacementpoint->pc) - 1;
2917 cd->mcodeptr = tmpmcodeptr;
2919 /* create stack frame - keep 16-byte aligned */
2921 M_AADD_IMM(REG_SP, -4 * 4, REG_SP);
2923 /* push address of `rplpoint` struct */
2925 disp = dseg_addaddress(cd, replacementpoint);
2926 M_ALD(REG_ITMP3, REG_PV, disp);
2927 M_AST_INTERN(REG_ITMP3, REG_SP, 0 * 4);
2929 /* jump to replacement function */
2931 disp = dseg_addaddress(cd, asm_replacement_out);
2932 M_ALD(REG_ITMP3, REG_PV, disp);
2942 /* everything's ok */
2948 /* createcompilerstub **********************************************************
2950 Creates a stub routine which calls the compiler.
2952 *******************************************************************************/
2954 #define COMPILERSTUB_DATASIZE 3 * SIZEOF_VOID_P
2955 #define COMPILERSTUB_CODESIZE 4 * 4
2957 #define COMPILERSTUB_SIZE COMPILERSTUB_DATASIZE + COMPILERSTUB_CODESIZE
2960 u1 *createcompilerstub(methodinfo *m)
2962 u1 *s; /* memory to hold the stub */
2968 s = CNEW(u1, COMPILERSTUB_SIZE);
2970 /* set data pointer and code pointer */
2973 s = s + COMPILERSTUB_DATASIZE;
2975 /* mark start of dump memory area */
2977 dumpsize = dump_size();
2979 cd = DNEW(codegendata);
2982 /* Store the codeinfo pointer in the same place as in the
2983 methodheader for compiled methods. */
2985 code = code_codeinfo_new(m);
2987 d[0] = (ptrint) asm_call_jit_compiler;
2989 d[2] = (ptrint) code;
2991 M_ALD_INTERN(REG_ITMP1, REG_PV, -2 * SIZEOF_VOID_P);
2992 M_ALD_INTERN(REG_PV, REG_PV, -3 * SIZEOF_VOID_P);
2996 md_cacheflush((u1 *) d, COMPILERSTUB_SIZE);
2998 #if defined(ENABLE_STATISTICS)
3000 count_cstub_len += COMPILERSTUB_SIZE;
3003 /* release dump area */
3005 dump_release(dumpsize);
3011 /* createnativestub ************************************************************
3013 Creates a stub routine which calls a native method.
3015 *******************************************************************************/
3017 u1 *createnativestub(functionptr f, jitdata *jd, methoddesc *nmd)
3025 s4 i, j; /* count variables */
3030 /* get required compiler data */
3037 /* set some variables */
3040 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3042 /* calculate stackframe size */
3044 cd->stackframesize =
3045 sizeof(stackframeinfo) / SIZEOF_VOID_P +
3046 sizeof(localref_table) / SIZEOF_VOID_P +
3047 4 + /* 4 stackframeinfo arguments (darwin)*/
3051 cd->stackframesize = (cd->stackframesize + 3) & ~3; /* keep stack 16-byte aligned */
3053 /* create method header */
3055 (void) dseg_addaddress(cd, code); /* CodeinfoPointer */
3056 (void) dseg_adds4(cd, cd->stackframesize * 8); /* FrameSize */
3057 (void) dseg_adds4(cd, 0); /* IsSync */
3058 (void) dseg_adds4(cd, 0); /* IsLeaf */
3059 (void) dseg_adds4(cd, 0); /* IntSave */
3060 (void) dseg_adds4(cd, 0); /* FltSave */
3061 (void) dseg_addlinenumbertablesize(cd);
3062 (void) dseg_adds4(cd, 0); /* ExTableSize */
3067 M_AST_INTERN(REG_ZERO, REG_SP, LA_LR_OFFSET);
3068 M_STDU(REG_SP, REG_SP, -(cd->stackframesize * 8));
3070 #if !defined(NDEBUG)
3071 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3072 emit_verbosecall_enter(jd);
3075 /* get function address (this must happen before the stackframeinfo) */
3077 funcdisp = dseg_addaddress(cd, f);
3079 #if !defined(WITH_STATIC_CLASSPATH)
3081 codegen_addpatchref(cd, PATCHER_resolve_native, m, funcdisp);
3083 if (opt_showdisassemble)
3088 /* save integer and float argument registers */
3092 for (i = 0; i < md->paramcount; i++) {
3093 t = md->paramtypes[i].type;
3095 if (IS_INT_LNG_TYPE(t)) {
3096 if (!md->params[i].inmemory) {
3097 s1 = md->params[i].regoff;
3098 M_LST(rd->argintregs[s1], REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + j * 8);
3104 for (i = 0; i < md->paramcount; i++) {
3105 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3106 if (!md->params[i].inmemory) {
3107 s1 = md->params[i].regoff;
3108 M_DST(rd->argfltregs[s1], REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + j * 8);
3114 /* create native stack info */
3116 M_AADD_IMM(REG_SP, cd->stackframesize * 8, rd->argintregs[0]);
3117 M_MOV(REG_PV, rd->argintregs[1]);
3118 M_AADD_IMM(REG_SP, cd->stackframesize * 8, rd->argintregs[2]);
3119 M_ALD(rd->argintregs[3], REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
3120 disp = dseg_addaddress(cd, codegen_start_native_call);
3122 M_ALD(REG_ITMP1, REG_PV, disp);
3123 M_ALD(REG_ITMP1, REG_ITMP1, 0); /* TOC */
3127 /* restore integer and float argument registers */
3131 for (i = 0; i < md->paramcount; i++) {
3132 t = md->paramtypes[i].type;
3134 if (IS_INT_LNG_TYPE(t)) {
3135 if (!md->params[i].inmemory) {
3136 s1 = md->params[i].regoff;
3137 M_LLD(rd->argintregs[s1], REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + j * 8);
3143 for (i = 0; i < md->paramcount; i++) {
3144 if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
3145 if (!md->params[i].inmemory) {
3146 s1 = md->params[i].regoff;
3147 M_DLD(rd->argfltregs[s1], REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + j * 8);
3153 /* copy or spill arguments to new locations */
3155 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3156 t = md->paramtypes[i].type;
3158 if (IS_INT_LNG_TYPE(t)) {
3159 if (!md->params[i].inmemory) {
3160 s1 = rd->argintregs[md->params[i].regoff];
3162 if (!nmd->params[j].inmemory) {
3163 s2 = rd->argintregs[nmd->params[j].regoff];
3166 s2 = nmd->params[j].regoff;
3167 M_LST(s1, REG_SP, s2 * 8);
3171 s1 = md->params[i].regoff + cd->stackframesize;
3172 s2 = nmd->params[j].regoff;
3174 M_LLD(REG_ITMP1, REG_SP, s1 * 8);
3175 M_LST(REG_ITMP1, REG_SP, s2 * 8);
3179 /* We only copy spilled float arguments, as the float
3180 argument registers keep unchanged. */
3182 if (md->params[i].inmemory) {
3183 s1 = md->params[i].regoff + cd->stackframesize;
3184 s2 = nmd->params[j].regoff;
3186 if (IS_2_WORD_TYPE(t)) {
3187 M_DLD(REG_FTMP1, REG_SP, s1 * 8);
3188 M_DST(REG_FTMP1, REG_SP, s2 * 8);
3191 M_FLD(REG_FTMP1, REG_SP, s1 * 8);
3192 M_FST(REG_FTMP1, REG_SP, s2 * 8);
3198 /* put class into second argument register */
3200 if (m->flags & ACC_STATIC) {
3201 disp = dseg_addaddress(cd, m->class);
3202 M_ALD(rd->argintregs[1], REG_PV, disp);
3205 /* put env into first argument register */
3207 disp = dseg_addaddress(cd, _Jv_env);
3208 M_ALD(rd->argintregs[0], REG_PV, disp);
3210 /* generate the actual native call */
3211 /* native functions have a different TOC for sure */
3213 M_AST(REG_TOC, REG_SP, 40); /* save old TOC */
3214 M_ALD(REG_ITMP3, REG_PV, funcdisp);
3215 M_ALD(REG_TOC, REG_ITMP3, 8); /* load TOC from func. descriptor */
3216 M_ALD(REG_ITMP3, REG_ITMP3, 0);
3219 M_ALD(REG_TOC, REG_SP, 40); /* restore TOC */
3221 /* save return value */
3223 if (md->returntype.type != TYPE_VOID) {
3224 if (IS_INT_LNG_TYPE(md->returntype.type)) {
3225 M_LST(REG_RESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
3228 if (IS_2_WORD_TYPE(md->returntype.type))
3229 M_DST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
3231 M_FST(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8); /* FIXME, needed ?*/
3235 /* print call trace */
3236 #if ! defined(NDEBGUU)
3237 if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
3238 emit_verbosecall_exit(jd);
3241 /* remove native stackframe info */
3243 M_AADD_IMM(REG_SP, cd->stackframesize * 8, rd->argintregs[0]);
3244 disp = dseg_addaddress(cd, codegen_finish_native_call);
3245 M_ALD(REG_ITMP1, REG_PV, disp);
3246 M_ALD(REG_ITMP1, REG_ITMP1, 0); /* XXX what about TOC? */
3249 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3251 /* restore return value */
3253 if (md->returntype.type != TYPE_VOID) {
3254 if (IS_INT_LNG_TYPE(md->returntype.type)) {
3255 M_LLD(REG_RESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
3258 if (IS_2_WORD_TYPE(md->returntype.type))
3259 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
3261 M_FLD(REG_FRESULT, REG_SP, LA_SIZE + PA_SIZE + 1 * 8);
3265 M_ALD(REG_ITMP2_XPC, REG_SP, cd->stackframesize * 8 + LA_LR_OFFSET);
3266 M_MTLR(REG_ITMP2_XPC);
3267 M_LDA(REG_SP, REG_SP, cd->stackframesize * 8); /* remove stackframe */
3269 /* check for exception */
3271 M_TST(REG_ITMP1_XPTR);
3272 M_BNE(1); /* if no exception then return */
3276 /* handle exception */
3278 M_LADD_IMM(REG_ITMP2_XPC, -4, REG_ITMP2_XPC); /* exception address */
3280 disp = dseg_addaddress(cd, asm_handle_nat_exception);
3281 M_ALD(REG_ITMP3, REG_PV, disp);
3285 /* generate patcher stub call code */
3293 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3294 /* Get machine code which is patched back in later. The
3295 call is 1 instruction word long. */
3297 tmpmcodeptr = cd->mcodebase + pref->branchpos;
3299 mcode = *((u4 *) tmpmcodeptr);
3301 /* Patch in the call to call the following code (done at
3304 savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
3305 cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
3307 disp = ((u4 *) savedmcodeptr) - (((u4 *) tmpmcodeptr) + 1);
3310 cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
3312 /* create stack frame - keep stack 16-byte aligned */
3314 M_AADD_IMM(REG_SP, -8 * 8, REG_SP);
3316 /* move return address onto stack */
3319 M_AST(REG_ZERO, REG_SP, 5 * 8);
3321 /* move pointer to java_objectheader onto stack */
3323 #if defined(ENABLE_THREADS)
3324 /* order reversed because of data segment layout */
3326 (void) dseg_addaddress(cd, NULL); /* flcword */
3327 (void) dseg_addaddress(cd, lock_get_initial_lock_word()); /* monitorPtr */
3328 disp = dseg_addaddress(cd, NULL); /* vftbl */
3330 M_LDA(REG_ITMP3, REG_PV, disp);
3331 M_AST(REG_ITMP3, REG_SP, 4 * 8);
3336 /* move machine code onto stack */
3338 disp = dseg_adds4(cd, mcode);
3339 M_ILD(REG_ITMP3, REG_PV, disp);
3340 M_IST(REG_ITMP3, REG_SP, 3 * 8);
3342 /* move class/method/field reference onto stack */
3344 disp = dseg_addaddress(cd, pref->ref);
3345 M_ALD(REG_ITMP3, REG_PV, disp);
3346 M_AST(REG_ITMP3, REG_SP, 2 * 8);
3348 /* move data segment displacement onto stack */
3350 disp = dseg_adds4(cd, pref->disp);
3351 M_ILD(REG_ITMP3, REG_PV, disp);
3352 M_IST(REG_ITMP3, REG_SP, 1 * 8);
3354 /* move patcher function pointer onto stack */
3356 disp = dseg_addaddress(cd, pref->patcher);
3357 M_ALD(REG_ITMP3, REG_PV, disp);
3358 M_AST(REG_ITMP3, REG_SP, 0 * 8);
3360 disp = dseg_addaddress(cd, asm_patcher_wrapper);
3361 M_ALD(REG_ITMP3, REG_PV, disp);
3369 return code->entrypoint;
3376 * These are local overrides for various environment variables in Emacs.
3377 * Please do not remove this and leave it at the end of the file, where
3378 * Emacs will automagically detect them.
3379 * ---------------------------------------------------------------------
3382 * indent-tabs-mode: t
3386 * vim:noexpandtab:sw=4:ts=4: