1 /* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Andreas Krall
30 Changes: Christian Thalinger
33 $Id: codegen.c 2841 2005-06-27 14:19:36Z christian $
48 #include "vm/jit/powerpc/arch.h"
49 #include "vm/jit/powerpc/codegen.h"
50 #include "vm/jit/powerpc/types.h"
52 #include "cacao/cacao.h"
53 #include "native/native.h"
54 #include "vm/builtin.h"
55 #include "vm/global.h"
56 #include "vm/loader.h"
57 #include "vm/stringlocal.h"
58 #include "vm/tables.h"
59 #include "vm/jit/asmpart.h"
60 #include "vm/jit/codegen.inc"
61 #include "vm/jit/jit.h"
64 # include "vm/jit/lsra.inc"
67 #include "vm/jit/parse.h"
68 #include "vm/jit/patcher.h"
69 #include "vm/jit/reg.h"
70 #include "vm/jit/reg.inc"
74 void asm_cacheflush(void *, long);
76 /* #include <architecture/ppc/cframe.h> */
78 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
79 void thread_restartcriticalsection(void *u)
81 /* XXX set pc to restart address */
86 /* codegen *********************************************************************
88 Generates machine code.
90 *******************************************************************************/
92 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
94 s4 len, s1, s2, s3, d, off;
103 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
104 builtintable_entry *bte;
113 /* space to save used callee saved registers */
115 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
116 savedregs_num += 2 * (FLT_SAV_CNT - rd->savfltreguse);
118 parentargs_base = rd->memuse + savedregs_num;
120 #if defined(USE_THREADS)
121 /* space to save argument of monitor_enter and Return Values to survive */
122 /* monitor_exit. The stack position for the argument can not be shared */
123 /* with place to save the return register on PPC, since both values */
125 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
126 /* reserve 2 slots for long/double return values for monitorexit */
128 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
129 parentargs_base += 3;
131 parentargs_nase += 2;
136 /* create method header */
138 parentargs_base = (parentargs_base + 3) & ~3;
140 #if SIZEOF_VOID_P == 4
141 (void) dseg_addaddress(cd, m); /* Filler */
143 (void) dseg_addaddress(cd, m); /* MethodPointer */
144 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
146 #if defined(USE_THREADS)
148 /* IsSync contains the offset relative to the stack pointer for the
149 argument of monitor_exit used in the exception handler. Since the
150 offset could be zero and give a wrong meaning of the flag it is
154 if (checksync && (m->flags & ACC_SYNCHRONIZED))
155 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
160 (void) dseg_adds4(cd, 0); /* IsSync */
162 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
163 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
164 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
165 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
167 /* create exception table */
169 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
170 dseg_addtarget(cd, ex->start);
171 dseg_addtarget(cd, ex->end);
172 dseg_addtarget(cd, ex->handler);
173 (void) dseg_addaddress(cd, ex->catchtype.cls);
176 /* initialize mcode variables */
178 mcodeptr = (s4 *) cd->mcodebase;
179 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
180 MCODECHECK(128 + m->paramcount);
182 /* create stack frame (if necessary) */
184 if (!m->isleafmethod) {
186 M_AST(REG_ITMP3, REG_SP, LA_LR_OFFSET);
189 if (parentargs_base) {
190 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
193 /* save return address and used callee saved registers */
196 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
197 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
199 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
200 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
203 /* take arguments out of register or stack frame */
207 for (p = 0, l = 0; p < md->paramcount; p++) {
208 t = md->paramtypes[p].type;
209 var = &(rd->locals[l][t]);
211 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
215 s1 = md->params[p].regoff;
216 if (IS_INT_LNG_TYPE(t)) { /* integer args */
217 if (IS_2_WORD_TYPE(t))
218 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
219 rd->argintregs[GET_HIGH_REG(s1)]);
221 s2 = rd->argintregs[s1];
222 if (!md->params[p].inmemory) { /* register arguments */
223 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
224 M_TINTMOVE(t, s2, var->regoff);
226 } else { /* reg arg -> spilled */
227 if (IS_2_WORD_TYPE(t)) {
228 M_IST(GET_HIGH_REG(s2), REG_SP, var->regoff * 4);
229 M_IST(GET_LOW_REG(s2), REG_SP, 4 * var->regoff + 4);
231 M_IST(s2, REG_SP, var->regoff * 4);
235 } else { /* stack arguments */
236 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
237 if (IS_2_WORD_TYPE(t)) {
238 M_ILD(GET_HIGH_REG(var->regoff), REG_SP,
239 (parentargs_base + s1) * 4);
240 M_ILD(GET_LOW_REG(var->regoff), REG_SP,
241 (parentargs_base + s1) * 4 + 4);
243 M_ILD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
246 } else { /* stack arg -> spilled */
248 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4);
249 M_IST(REG_ITMP1, REG_SP, var->regoff * 4);
250 if (IS_2_WORD_TYPE(t)) {
251 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4 +4);
252 M_IST(REG_ITMP1, REG_SP, var->regoff * 4 + 4);
255 /* Reuse Memory Position on Caller Stack */
256 var->regoff = parentargs_base + s1;
261 } else { /* floating args */
262 if (!md->params[p].inmemory) { /* register arguments */
263 s2 = rd->argfltregs[s1];
264 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
265 M_FLTMOVE(s2, var->regoff);
267 } else { /* reg arg -> spilled */
268 if (IS_2_WORD_TYPE(t))
269 M_DST(s2, REG_SP, var->regoff * 4);
271 M_FST(s2, REG_SP, var->regoff * 4);
274 } else { /* stack arguments */
275 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
276 if (IS_2_WORD_TYPE(t))
277 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
280 M_FLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
282 } else { /* stack-arg -> spilled */
284 if (IS_2_WORD_TYPE(t)) {
285 M_DLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
286 M_DST(REG_FTMP1, REG_SP, var->regoff * 4);
287 var->regoff = parentargs_base + s1;
290 M_FLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
291 M_FST(REG_FTMP1, REG_SP, var->regoff * 4);
294 /* Reuse Memory Position on Caller Stack */
295 var->regoff = parentargs_base + s1;
302 /* save monitorenter argument */
304 #if defined(USE_THREADS)
305 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
306 /* stack offset for monitor argument */
312 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT * 4 + FLT_ARG_CNT * 8));
314 for (p = 0; p < INT_ARG_CNT; p++)
315 M_IST(rd->argintregs[p], REG_SP, p * 4);
317 for (p = 0; p < FLT_ARG_CNT * 2; p += 2)
318 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
320 s1 += INT_ARG_CNT + FLT_ARG_CNT;
324 /* decide which monitor enter function to call */
326 if (m->flags & ACC_STATIC) {
327 p = dseg_addaddress(cd, m->class);
328 M_ALD(REG_ITMP1, REG_PV, p);
329 M_AST(REG_ITMP1, REG_SP, s1 * 4);
330 M_MOV(REG_ITMP1, rd->argintregs[0]);
331 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
332 M_ALD(REG_ITMP3, REG_PV, p);
337 M_TST(rd->argintregs[0]);
339 codegen_addxnullrefs(cd, mcodeptr);
340 M_AST(rd->argintregs[0], REG_SP, s1 * 4);
341 p = dseg_addaddress(cd, BUILTIN_monitorenter);
342 M_ALD(REG_ITMP3, REG_PV, p);
349 for (p = 0; p < INT_ARG_CNT; p++)
350 M_ILD(rd->argintregs[p], REG_SP, p * 4);
352 for (p = 0; p < FLT_ARG_CNT; p++)
353 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
356 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
362 /* call trace function */
370 /* XXX must be a multiple of 16 */
371 M_LDA(REG_SP, REG_SP, -(LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
373 M_IST(REG_ITMP3, REG_SP, LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
375 M_CLR(REG_ITMP1); /* clear help register */
377 /* save all arguments into the reserved stack space */
379 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
380 t = md->paramtypes[p].type;
382 if (IS_INT_LNG_TYPE(t)) {
383 /* overlapping u8's are on the stack */
384 if ((p + longargs + dblargs) <
385 (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
386 s1 = rd->argintregs[p + longargs + dblargs];
388 if (!IS_2_WORD_TYPE(t)) {
389 M_IST(REG_ITMP1, REG_SP, LA_SIZE + p * 8);
390 M_IST(s1, REG_SP, LA_SIZE + p * 8 + 4);
394 rd->argintregs[p + longargs + dblargs + 1]);
395 M_IST(GET_HIGH_REG(s1), REG_SP, LA_SIZE + p * 8);
396 M_IST(GET_LOW_REG(s1), REG_SP, LA_SIZE + p * 8 + 4);
401 a = dseg_adds4(cd, 0xdeadbeef);
402 M_ILD(REG_ITMP1, REG_PV, a);
403 M_IST(REG_ITMP1, REG_SP, LA_SIZE + p * 8);
404 M_IST(REG_ITMP1, REG_SP, LA_SIZE + p * 8 + 4);
408 if ((fltargs + dblargs) < FLT_ARG_CNT) {
409 s1 = rd->argfltregs[fltargs + dblargs];
411 if (!IS_2_WORD_TYPE(t)) {
412 M_IST(REG_ITMP1, REG_SP, LA_SIZE + p * 8);
413 M_FST(s1, REG_SP, LA_SIZE + p * 8 + 4);
417 M_DST(s1, REG_SP, LA_SIZE + p * 8);
422 /* this should not happen */
427 /* load first 4 arguments into integer argument registers */
429 for (p = 0; p < 8; p++) {
430 d = rd->argintregs[p];
431 M_ILD(d, REG_SP, LA_SIZE + p * 4);
434 p = dseg_addaddress(cd, m);
435 M_ALD(REG_ITMP1, REG_PV, p);
436 #if defined(__DARWIN__)
437 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 8 * 8); /* 24 (linkage area) + */
438 /* 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
440 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
442 p = dseg_addaddress(cd, (void *) builtin_trace_args);
443 M_ALD(REG_ITMP2, REG_PV, p);
451 /* restore arguments from the reserved stack space */
453 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
454 t = md->paramtypes[p].type;
456 if (IS_INT_LNG_TYPE(t)) {
457 if ((p + longargs + dblargs) < INT_ARG_CNT) {
458 s1 = rd->argintregs[p + longargs + dblargs];
460 if (!IS_2_WORD_TYPE(t)) {
461 M_ILD(s1, REG_SP, LA_SIZE + p * 8 + 4);
465 rd->argintregs[p + longargs + dblargs + 1]);
466 M_ILD(GET_HIGH_REG(s1), REG_SP, LA_SIZE + p * 8);
467 M_ILD(GET_LOW_REG(s1), REG_SP, LA_SIZE + p * 8 + 4);
473 if ((fltargs + dblargs) < FLT_ARG_CNT) {
474 s1 = rd->argfltregs[fltargs + dblargs];
476 if (!IS_2_WORD_TYPE(t)) {
477 M_FLD(s1, REG_SP, LA_SIZE + p * 8 + 4);
481 M_DLD(s1, REG_SP, LA_SIZE + p * 8);
488 M_ILD(REG_ITMP3, REG_SP, LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
490 M_LDA(REG_SP, REG_SP, LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
492 } /* if (runverbose) */
495 /* end of header generation */
497 /* walk through all basic blocks */
498 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
500 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
502 if (bptr->flags >= BBREACHED) {
504 /* branch resolving */
508 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
509 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
515 /* copy interface registers to their destination */
523 while (src != NULL) {
525 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
526 /* d = reg_of_var(m, src, REG_ITMP1); */
527 if (!(src->flags & INMEMORY))
531 M_INTMOVE(REG_ITMP1, d);
532 store_reg_to_var_int(src, d);
538 while (src != NULL) {
540 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
541 d = reg_of_var(rd, src, REG_ITMP1);
542 M_INTMOVE(REG_ITMP1, d);
543 store_reg_to_var_int(src, d);
545 if (src->type == TYPE_LNG)
546 d = reg_of_var(rd, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
548 d = reg_of_var(rd, src, REG_IFTMP);
549 if ((src->varkind != STACKVAR)) {
551 if (IS_FLT_DBL_TYPE(s2)) {
552 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
553 s1 = rd->interfaces[len][s2].regoff;
556 if (IS_2_WORD_TYPE(s2)) {
558 4 * rd->interfaces[len][s2].regoff);
561 4 * rd->interfaces[len][s2].regoff);
564 store_reg_to_var_flt(src, d);
566 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
567 s1 = rd->interfaces[len][s2].regoff;
570 if (IS_2_WORD_TYPE(s2)) {
571 M_ILD(GET_HIGH_REG(d), REG_SP,
572 4 * rd->interfaces[len][s2].regoff);
573 M_ILD(GET_LOW_REG(d), REG_SP,
574 4 * rd->interfaces[len][s2].regoff + 4);
577 4 * rd->interfaces[len][s2].regoff);
580 store_reg_to_var_int(src, d);
590 /* walk through all instructions */
594 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
596 MCODECHECK(64); /* an instruction usually needs < 64 words */
599 case ICMD_NOP: /* ... ==> ... */
600 case ICMD_INLINE_START:
601 case ICMD_INLINE_END:
604 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
606 var_to_reg_int(s1, src, REG_ITMP1);
609 codegen_addxnullrefs(cd, mcodeptr);
612 /* constant operations ************************************************/
614 case ICMD_ICONST: /* ... ==> ..., constant */
615 /* op1 = 0, val.i = constant */
617 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
618 ICONST(d, iptr->val.i);
619 store_reg_to_var_int(iptr->dst, d);
622 case ICMD_LCONST: /* ... ==> ..., constant */
623 /* op1 = 0, val.l = constant */
625 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
626 LCONST(d, iptr->val.l);
627 store_reg_to_var_int(iptr->dst, d);
630 case ICMD_FCONST: /* ... ==> ..., constant */
631 /* op1 = 0, val.f = constant */
633 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
634 a = dseg_addfloat(cd, iptr->val.f);
636 store_reg_to_var_flt(iptr->dst, d);
639 case ICMD_DCONST: /* ... ==> ..., constant */
640 /* op1 = 0, val.d = constant */
642 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
643 a = dseg_adddouble(cd, iptr->val.d);
645 store_reg_to_var_flt(iptr->dst, d);
648 case ICMD_ACONST: /* ... ==> ..., constant */
649 /* op1 = 0, val.a = constant */
651 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
652 ICONST(d, (u4) iptr->val.a);
653 store_reg_to_var_int(iptr->dst, d);
657 /* load/store operations **********************************************/
659 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
660 case ICMD_LLOAD: /* op1 = local variable */
663 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
664 if (IS_2_WORD_TYPE(var->type)) /* TYPE_LNG */
665 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
667 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
668 if ((iptr->dst->varkind == LOCALVAR) &&
669 (iptr->dst->varnum == iptr->op1))
672 if (var->flags & INMEMORY) {
673 if (IS_2_WORD_TYPE(var->type)) {
674 M_ILD(GET_HIGH_REG(d), REG_SP, 4 * var->regoff);
675 M_ILD(GET_LOW_REG(d), REG_SP, 4 * var->regoff + 4);
677 M_ILD(d, REG_SP, 4 * var->regoff);
680 M_TINTMOVE(var->type, var->regoff, d);
682 store_reg_to_var_int(iptr->dst, d);
685 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
686 case ICMD_DLOAD: /* op1 = local variable */
688 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
689 if ((iptr->dst->varkind == LOCALVAR) &&
690 (iptr->dst->varnum == iptr->op1))
692 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
693 if (var->flags & INMEMORY)
694 if (IS_2_WORD_TYPE(var->type))
695 M_DLD(d, REG_SP, 4 * var->regoff);
697 M_FLD(d, REG_SP, 4 * var->regoff);
699 M_FLTMOVE(var->regoff, d);
701 store_reg_to_var_flt(iptr->dst, d);
705 case ICMD_ISTORE: /* ..., value ==> ... */
706 case ICMD_LSTORE: /* op1 = local variable */
709 if ((src->varkind == LOCALVAR) &&
710 (src->varnum == iptr->op1))
712 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
713 if (var->flags & INMEMORY) {
714 if (IS_2_WORD_TYPE(var->type)) {
715 var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
716 M_IST(GET_HIGH_REG(s1), REG_SP, 4 * var->regoff);
717 M_IST(GET_LOW_REG(s1), REG_SP, 4 * var->regoff + 4);
719 var_to_reg_int(s1, src, REG_ITMP1);
720 M_IST(s1, REG_SP, 4 * var->regoff);
724 var_to_reg_int(s1, src, var->regoff);
725 M_TINTMOVE(var->type, s1, var->regoff);
729 case ICMD_FSTORE: /* ..., value ==> ... */
730 case ICMD_DSTORE: /* op1 = local variable */
732 if ((src->varkind == LOCALVAR) &&
733 (src->varnum == iptr->op1))
735 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
736 if (var->flags & INMEMORY) {
737 var_to_reg_flt(s1, src, REG_FTMP1);
738 if (var->type == TYPE_DBL)
739 M_DST(s1, REG_SP, 4 * var->regoff);
741 M_FST(s1, REG_SP, 4 * var->regoff);
743 var_to_reg_flt(s1, src, var->regoff);
744 M_FLTMOVE(s1, var->regoff);
749 /* pop/dup/swap operations ********************************************/
751 /* attention: double and longs are only one entry in CACAO ICMDs */
753 case ICMD_POP: /* ..., value ==> ... */
754 case ICMD_POP2: /* ..., value, value ==> ... */
757 case ICMD_DUP: /* ..., a ==> ..., a, a */
758 M_COPY(src, iptr->dst);
761 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
763 M_COPY(src, iptr->dst);
764 M_COPY(src->prev, iptr->dst->prev);
765 M_COPY(iptr->dst, iptr->dst->prev->prev);
768 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
770 M_COPY(src, iptr->dst);
771 M_COPY(src->prev, iptr->dst->prev);
772 M_COPY(src->prev->prev, iptr->dst->prev->prev);
773 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
776 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
778 M_COPY(src, iptr->dst);
779 M_COPY(src->prev, iptr->dst->prev);
782 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
784 M_COPY(src, iptr->dst);
785 M_COPY(src->prev, iptr->dst->prev);
786 M_COPY(src->prev->prev, iptr->dst->prev->prev);
787 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
788 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
791 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
793 M_COPY(src, iptr->dst);
794 M_COPY(src->prev, iptr->dst->prev);
795 M_COPY(src->prev->prev, iptr->dst->prev->prev);
796 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
797 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
798 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
801 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
803 M_COPY(src, iptr->dst->prev);
804 M_COPY(src->prev, iptr->dst);
808 /* integer operations *************************************************/
810 case ICMD_INEG: /* ..., value ==> ..., - value */
812 var_to_reg_int(s1, src, REG_ITMP1);
813 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
815 store_reg_to_var_int(iptr->dst, d);
818 case ICMD_LNEG: /* ..., value ==> ..., - value */
820 var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
821 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
822 M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
823 M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
824 store_reg_to_var_int(iptr->dst, d);
827 case ICMD_I2L: /* ..., value ==> ..., value */
829 var_to_reg_int(s1, src, REG_ITMP2);
830 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
831 M_INTMOVE(s1, GET_LOW_REG(d));
832 M_SRA_IMM(GET_LOW_REG(d), 31, GET_HIGH_REG(d));
833 store_reg_to_var_int(iptr->dst, d);
836 case ICMD_L2I: /* ..., value ==> ..., value */
838 var_to_reg_int_low(s1, src, REG_ITMP2);
839 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
841 store_reg_to_var_int(iptr->dst, d);
844 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
846 var_to_reg_int(s1, src, REG_ITMP1);
847 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
849 store_reg_to_var_int(iptr->dst, d);
852 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
854 var_to_reg_int(s1, src, REG_ITMP1);
855 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
857 store_reg_to_var_int(iptr->dst, d);
860 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
862 var_to_reg_int(s1, src, REG_ITMP1);
863 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
865 store_reg_to_var_int(iptr->dst, d);
869 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
871 var_to_reg_int(s1, src->prev, REG_ITMP1);
872 var_to_reg_int(s2, src, REG_ITMP2);
873 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
875 store_reg_to_var_int(iptr->dst, d);
878 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
879 /* val.i = constant */
881 var_to_reg_int(s1, src, REG_ITMP1);
882 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
883 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
884 M_IADD_IMM(s1, iptr->val.i, d);
886 ICONST(REG_ITMP2, iptr->val.i);
887 M_IADD(s1, REG_ITMP2, d);
889 store_reg_to_var_int(iptr->dst, d);
892 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
894 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
895 var_to_reg_int_low(s2, src, REG_ITMP2);
896 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
897 M_ADDC(s1, s2, GET_LOW_REG(d));
898 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
899 var_to_reg_int_high(s2, src, REG_ITMP3);
900 M_ADDE(s1, s2, GET_HIGH_REG(d));
901 store_reg_to_var_int(iptr->dst, d);
904 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
905 /* val.l = constant */
907 s3 = iptr->val.l & 0xffffffff;
908 var_to_reg_int_low(s1, src, REG_ITMP1);
909 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
910 if ((s3 >= -32768) && (s3 <= 32767)) {
911 M_ADDIC(s1, s3, GET_LOW_REG(d));
914 ICONST(REG_ITMP2, s3);
915 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
918 var_to_reg_int_high(s1, src, REG_ITMP1);
919 s3 = iptr->val.l >> 32;
921 M_ADDME(s1, GET_HIGH_REG(d));
923 M_ADDZE(s1, GET_HIGH_REG(d));
925 ICONST(REG_ITMP3, s3);
926 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
928 store_reg_to_var_int(iptr->dst, d);
931 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
933 var_to_reg_int(s1, src->prev, REG_ITMP1);
934 var_to_reg_int(s2, src, REG_ITMP2);
935 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
937 store_reg_to_var_int(iptr->dst, d);
940 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
941 /* val.i = constant */
943 var_to_reg_int(s1, src, REG_ITMP1);
944 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
945 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
946 M_IADD_IMM(s1, -iptr->val.i, d);
948 ICONST(REG_ITMP2, -iptr->val.i);
949 M_IADD(s1, REG_ITMP2, d);
951 store_reg_to_var_int(iptr->dst, d);
954 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
956 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
957 var_to_reg_int_low(s2, src, REG_ITMP2);
958 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
959 M_SUBC(s1, s2, GET_LOW_REG(d));
960 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
961 var_to_reg_int_high(s2, src, REG_ITMP3);
962 M_SUBE(s1, s2, GET_HIGH_REG(d));
963 store_reg_to_var_int(iptr->dst, d);
966 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
967 /* val.l = constant */
969 s3 = (-iptr->val.l) & 0xffffffff;
970 var_to_reg_int_low(s1, src, REG_ITMP1);
971 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
972 if ((s3 >= -32768) && (s3 <= 32767)) {
973 M_ADDIC(s1, s3, GET_LOW_REG(d));
975 ICONST(REG_ITMP2, s3);
976 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
978 var_to_reg_int_high(s1, src, REG_ITMP1);
979 s3 = (-iptr->val.l) >> 32;
981 M_ADDME(s1, GET_HIGH_REG(d));
983 M_ADDZE(s1, GET_HIGH_REG(d));
985 ICONST(REG_ITMP3, s3);
986 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
988 store_reg_to_var_int(iptr->dst, d);
991 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
993 var_to_reg_int(s1, src->prev, REG_ITMP1);
994 var_to_reg_int(s2, src, REG_ITMP2);
995 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
997 store_reg_to_var_int(iptr->dst, d);
1000 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1002 var_to_reg_int(s1, src->prev, REG_ITMP1);
1003 var_to_reg_int(s2, src, REG_ITMP2);
1004 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1008 store_reg_to_var_int(iptr->dst, d);
1011 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1013 var_to_reg_int(s1, src->prev, REG_ITMP1);
1014 var_to_reg_int(s2, src, REG_ITMP2);
1015 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1017 store_reg_to_var_int(iptr->dst, d);
1020 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1021 /* val.i = constant */
1023 var_to_reg_int(s1, src, REG_ITMP1);
1024 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1025 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1026 M_IMUL_IMM(s1, iptr->val.i, d);
1029 ICONST(REG_ITMP2, iptr->val.i);
1030 M_IMUL(s1, REG_ITMP2, d);
1032 store_reg_to_var_int(iptr->dst, d);
1035 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1037 var_to_reg_int(s1, src, REG_ITMP1);
1038 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1039 M_SRA_IMM(s1, iptr->val.i, d);
1041 store_reg_to_var_int(iptr->dst, d);
1044 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1046 var_to_reg_int(s1, src->prev, REG_ITMP1);
1047 var_to_reg_int(s2, src, REG_ITMP2);
1048 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1049 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1050 M_SLL(s1, REG_ITMP3, d);
1051 store_reg_to_var_int(iptr->dst, d);
1054 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1055 /* val.i = constant */
1057 var_to_reg_int(s1, src, REG_ITMP1);
1058 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1059 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1060 store_reg_to_var_int(iptr->dst, d);
1063 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1065 var_to_reg_int(s1, src->prev, REG_ITMP1);
1066 var_to_reg_int(s2, src, REG_ITMP2);
1067 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1068 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1069 M_SRA(s1, REG_ITMP3, d);
1070 store_reg_to_var_int(iptr->dst, d);
1073 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1074 /* val.i = constant */
1076 var_to_reg_int(s1, src, REG_ITMP1);
1077 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1078 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1079 store_reg_to_var_int(iptr->dst, d);
1082 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1084 var_to_reg_int(s1, src->prev, REG_ITMP1);
1085 var_to_reg_int(s2, src, REG_ITMP2);
1086 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1087 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1088 M_SRL(s1, REG_ITMP2, d);
1089 store_reg_to_var_int(iptr->dst, d);
1092 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1093 /* val.i = constant */
1095 var_to_reg_int(s1, src, REG_ITMP1);
1096 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1097 if (iptr->val.i & 0x1f)
1098 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1101 store_reg_to_var_int(iptr->dst, d);
1104 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1106 var_to_reg_int(s1, src->prev, REG_ITMP1);
1107 var_to_reg_int(s2, src, REG_ITMP2);
1108 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1110 store_reg_to_var_int(iptr->dst, d);
1113 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1114 /* val.i = constant */
1116 var_to_reg_int(s1, src, REG_ITMP1);
1117 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1118 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1119 M_AND_IMM(s1, iptr->val.i, d);
1122 else if (iptr->val.i == 0xffffff) {
1123 M_RLWINM(s1, 0, 8, 31, d);
1127 ICONST(REG_ITMP2, iptr->val.i);
1128 M_AND(s1, REG_ITMP2, d);
1130 store_reg_to_var_int(iptr->dst, d);
1133 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1135 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1136 var_to_reg_int_low(s2, src, REG_ITMP2);
1137 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1138 M_AND(s1, s2, GET_LOW_REG(d));
1139 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1140 var_to_reg_int_high(s2, src, REG_ITMP3);
1141 M_AND(s1, s2, GET_HIGH_REG(d));
1142 store_reg_to_var_int(iptr->dst, d);
1145 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1146 /* val.l = constant */
1148 s3 = iptr->val.l & 0xffffffff;
1149 var_to_reg_int_low(s1, src, REG_ITMP1);
1150 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1151 if ((s3 >= 0) && (s3 <= 65535)) {
1152 M_AND_IMM(s1, s3, GET_LOW_REG(d));
1154 ICONST(REG_ITMP2, s3);
1155 M_AND(s1, REG_ITMP2, GET_LOW_REG(d));
1157 var_to_reg_int_high(s1, src, REG_ITMP1);
1158 s3 = iptr->val.l >> 32;
1159 if ((s3 >= 0) && (s3 <= 65535)) {
1160 M_AND_IMM(s1, s3, GET_HIGH_REG(d));
1163 ICONST(REG_ITMP3, s3);
1164 M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
1166 store_reg_to_var_int(iptr->dst, d);
1169 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1170 /* val.i = constant */
1172 var_to_reg_int(s1, src, REG_ITMP1);
1173 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1174 M_MOV(s1, REG_ITMP2);
1176 M_BGE(1 + 2*(iptr->val.i >= 32768));
1177 if (iptr->val.i >= 32768) {
1178 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1179 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1180 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1182 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1184 int b=0, m = iptr->val.i;
1187 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1189 M_ISUB(s1, REG_ITMP2, d);
1190 store_reg_to_var_int(iptr->dst, d);
1193 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1195 var_to_reg_int(s1, src->prev, REG_ITMP1);
1196 var_to_reg_int(s2, src, REG_ITMP2);
1197 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1199 store_reg_to_var_int(iptr->dst, d);
1202 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1203 /* val.i = constant */
1205 var_to_reg_int(s1, src, REG_ITMP1);
1206 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1207 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1208 M_OR_IMM(s1, iptr->val.i, d);
1211 ICONST(REG_ITMP2, iptr->val.i);
1212 M_OR(s1, REG_ITMP2, d);
1214 store_reg_to_var_int(iptr->dst, d);
1217 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1219 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1220 var_to_reg_int_low(s2, src, REG_ITMP2);
1221 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1222 M_OR(s1, s2, GET_LOW_REG(d));
1223 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1224 var_to_reg_int_high(s2, src, REG_ITMP3);
1225 M_OR(s1, s2, GET_HIGH_REG(d));
1226 store_reg_to_var_int(iptr->dst, d);
1229 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1230 /* val.l = constant */
1232 s3 = iptr->val.l & 0xffffffff;
1233 var_to_reg_int_low(s1, src, REG_ITMP1);
1234 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1235 if ((s3 >= 0) && (s3 <= 65535)) {
1236 M_OR_IMM(s1, s3, GET_LOW_REG(d));
1238 ICONST(REG_ITMP2, s3);
1239 M_OR(s1, REG_ITMP2, GET_LOW_REG(d));
1241 var_to_reg_int_high(s1, src, REG_ITMP1);
1242 s3 = iptr->val.l >> 32;
1243 if ((s3 >= 0) && (s3 <= 65535)) {
1244 M_OR_IMM(s1, s3, GET_HIGH_REG(d));
1246 ICONST(REG_ITMP3, s3);
1247 M_OR(s1, REG_ITMP3, GET_HIGH_REG(d));
1249 store_reg_to_var_int(iptr->dst, d);
1252 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1254 var_to_reg_int(s1, src->prev, REG_ITMP1);
1255 var_to_reg_int(s2, src, REG_ITMP2);
1256 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1258 store_reg_to_var_int(iptr->dst, d);
1261 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1262 /* val.i = constant */
1264 var_to_reg_int(s1, src, REG_ITMP1);
1265 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1266 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1267 M_XOR_IMM(s1, iptr->val.i, d);
1270 ICONST(REG_ITMP2, iptr->val.i);
1271 M_XOR(s1, REG_ITMP2, d);
1273 store_reg_to_var_int(iptr->dst, d);
1276 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1278 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1279 var_to_reg_int_low(s2, src, REG_ITMP2);
1280 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1281 M_XOR(s1, s2, GET_LOW_REG(d));
1282 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1283 var_to_reg_int_high(s2, src, REG_ITMP3);
1284 M_XOR(s1, s2, GET_HIGH_REG(d));
1285 store_reg_to_var_int(iptr->dst, d);
1288 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1289 /* val.l = constant */
1291 s3 = iptr->val.l & 0xffffffff;
1292 var_to_reg_int_low(s1, src, REG_ITMP1);
1293 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1294 if ((s3 >= 0) && (s3 <= 65535)) {
1295 M_XOR_IMM(s1, s3, GET_LOW_REG(d));
1297 ICONST(REG_ITMP2, s3);
1298 M_XOR(s1, REG_ITMP2, GET_LOW_REG(d));
1300 var_to_reg_int_high(s1, src, REG_ITMP1);
1301 s3 = iptr->val.l >> 32;
1302 if ((s3 >= 0) && (s3 <= 65535)) {
1303 M_XOR_IMM(s1, s3, GET_HIGH_REG(d));
1305 ICONST(REG_ITMP3, s3);
1306 M_XOR(s1, REG_ITMP3, GET_HIGH_REG(d));
1308 store_reg_to_var_int(iptr->dst, d);
1311 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1312 /*******************************************************************
1313 TODO: CHANGE THIS TO A VERSION THAT WORKS !!!
1314 *******************************************************************/
1315 var_to_reg_int_high(s1, src->prev, REG_ITMP3);
1316 var_to_reg_int_high(s2, src, REG_ITMP2);
1317 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1319 int tempreg = false;
1323 if (src->prev->flags & INMEMORY) {
1324 tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1326 tempreg = tempreg || (d == GET_HIGH_REG(src->prev->regoff))
1327 || (d == GET_LOW_REG(src->prev->regoff));
1329 if (src->flags & INMEMORY) {
1330 tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1332 tempreg = tempreg || (d == GET_HIGH_REG(src->regoff))
1333 || (d == GET_LOW_REG(src->regoff));
1336 dreg = tempreg ? REG_ITMP1 : d;
1337 M_IADD_IMM(REG_ZERO, 1, dreg);
1342 var_to_reg_int_low(s1, src->prev, REG_ITMP3);
1343 var_to_reg_int_low(s2, src, REG_ITMP2);
1347 M_IADD_IMM(dreg, -1, dreg);
1348 M_IADD_IMM(dreg, -1, dreg);
1349 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1350 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1353 store_reg_to_var_int(iptr->dst, d);
1356 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1357 /* op1 = variable, val.i = constant */
1359 var = &(rd->locals[iptr->op1][TYPE_INT]);
1360 if (var->flags & INMEMORY) {
1362 M_ILD(s1, REG_SP, var->regoff * 4);
1370 M_ADDIS(s1, m>>16, s1);
1372 M_IADD_IMM(s1, m&0xffff, s1);
1374 if (var->flags & INMEMORY)
1375 M_IST(s1, REG_SP, var->regoff * 4);
1379 /* floating operations ************************************************/
1381 case ICMD_FNEG: /* ..., value ==> ..., - value */
1383 var_to_reg_flt(s1, src, REG_FTMP1);
1384 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1386 store_reg_to_var_flt(iptr->dst, d);
1389 case ICMD_DNEG: /* ..., value ==> ..., - value */
1391 var_to_reg_flt(s1, src, REG_FTMP1);
1392 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1394 store_reg_to_var_flt(iptr->dst, d);
1397 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1399 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1400 var_to_reg_flt(s2, src, REG_FTMP2);
1401 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1403 store_reg_to_var_flt(iptr->dst, d);
1406 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1408 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1409 var_to_reg_flt(s2, src, REG_FTMP2);
1410 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1412 store_reg_to_var_flt(iptr->dst, d);
1415 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1417 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1418 var_to_reg_flt(s2, src, REG_FTMP2);
1419 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1421 store_reg_to_var_flt(iptr->dst, d);
1424 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1426 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1427 var_to_reg_flt(s2, src, REG_FTMP2);
1428 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1430 store_reg_to_var_flt(iptr->dst, d);
1433 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1435 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1436 var_to_reg_flt(s2, src, REG_FTMP2);
1437 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1439 store_reg_to_var_flt(iptr->dst, d);
1442 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1444 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1445 var_to_reg_flt(s2, src, REG_FTMP2);
1446 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1448 store_reg_to_var_flt(iptr->dst, d);
1451 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1453 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1454 var_to_reg_flt(s2, src, REG_FTMP2);
1455 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1457 store_reg_to_var_flt(iptr->dst, d);
1460 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1462 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1463 var_to_reg_flt(s2, src, REG_FTMP2);
1464 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1466 store_reg_to_var_flt(iptr->dst, d);
1469 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1471 var_to_reg_flt(s1, src, REG_FTMP1);
1472 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1474 a = dseg_addfloat(cd, 0.0);
1475 M_FLD(REG_FTMP2, REG_PV, a);
1476 M_FCMPU(s1, REG_FTMP2);
1478 a = dseg_adds4(cd, 0);
1479 M_CVTDL_C(s1, REG_FTMP1);
1480 M_LDA (REG_ITMP1, REG_PV, a);
1481 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1482 M_ILD (d, REG_PV, a);
1483 store_reg_to_var_int(iptr->dst, d);
1486 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1488 var_to_reg_flt(s1, src, REG_FTMP1);
1489 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1491 store_reg_to_var_flt(iptr->dst, d);
1494 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1496 var_to_reg_flt(s1, src, REG_FTMP1);
1497 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1499 store_reg_to_var_flt(iptr->dst, d);
1502 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1504 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1505 var_to_reg_flt(s2, src, REG_FTMP2);
1506 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1508 M_IADD_IMM(0, -1, d);
1511 M_IADD_IMM(0, 0, d);
1513 M_IADD_IMM(0, 1, d);
1514 store_reg_to_var_int(iptr->dst, d);
1517 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1519 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1520 var_to_reg_flt(s2, src, REG_FTMP2);
1521 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1523 M_IADD_IMM(0, 1, d);
1526 M_IADD_IMM(0, 0, d);
1528 M_IADD_IMM(0, -1, d);
1529 store_reg_to_var_int(iptr->dst, d);
1533 /* memory operations **************************************************/
1535 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1537 var_to_reg_int(s1, src, REG_ITMP1);
1538 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1539 gen_nullptr_check(s1);
1540 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1541 store_reg_to_var_int(iptr->dst, d);
1544 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1546 var_to_reg_int(s1, src->prev, REG_ITMP1);
1547 var_to_reg_int(s2, src, REG_ITMP2);
1548 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1549 if (iptr->op1 == 0) {
1550 gen_nullptr_check(s1);
1553 M_SLL_IMM(s2, 2, REG_ITMP2);
1554 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1555 M_LWZX(d, s1, REG_ITMP2);
1556 store_reg_to_var_int(iptr->dst, d);
1559 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1561 var_to_reg_int(s1, src->prev, REG_ITMP1);
1562 var_to_reg_int(s2, src, REG_ITMP2);
1563 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1564 if (iptr->op1 == 0) {
1565 gen_nullptr_check(s1);
1568 M_SLL_IMM(s2, 3, REG_ITMP2);
1569 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1570 M_ILD(GET_HIGH_REG(d), REG_ITMP2, OFFSET(java_longarray, data[0]));
1571 M_ILD(GET_LOW_REG(d), REG_ITMP2, OFFSET(java_longarray,
1573 store_reg_to_var_int(iptr->dst, d);
1576 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1578 var_to_reg_int(s1, src->prev, REG_ITMP1);
1579 var_to_reg_int(s2, src, REG_ITMP2);
1580 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1581 if (iptr->op1 == 0) {
1582 gen_nullptr_check(s1);
1585 M_SLL_IMM(s2, 2, REG_ITMP2);
1586 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1587 M_LWZX(d, s1, REG_ITMP2);
1588 store_reg_to_var_int(iptr->dst, d);
1591 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1593 var_to_reg_int(s1, src->prev, REG_ITMP1);
1594 var_to_reg_int(s2, src, REG_ITMP2);
1595 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1596 if (iptr->op1 == 0) {
1597 gen_nullptr_check(s1);
1600 M_SLL_IMM(s2, 2, REG_ITMP2);
1601 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1602 M_LFSX(d, s1, REG_ITMP2);
1603 store_reg_to_var_flt(iptr->dst, d);
1606 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1608 var_to_reg_int(s1, src->prev, REG_ITMP1);
1609 var_to_reg_int(s2, src, REG_ITMP2);
1610 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1611 if (iptr->op1 == 0) {
1612 gen_nullptr_check(s1);
1615 M_SLL_IMM(s2, 3, REG_ITMP2);
1616 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1617 M_LFDX(d, s1, REG_ITMP2);
1618 store_reg_to_var_flt(iptr->dst, d);
1621 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1623 var_to_reg_int(s1, src->prev, REG_ITMP1);
1624 var_to_reg_int(s2, src, REG_ITMP2);
1625 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1626 if (iptr->op1 == 0) {
1627 gen_nullptr_check(s1);
1630 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1631 M_LBZX(d, s1, REG_ITMP2);
1633 store_reg_to_var_int(iptr->dst, d);
1636 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1638 var_to_reg_int(s1, src->prev, REG_ITMP1);
1639 var_to_reg_int(s2, src, REG_ITMP2);
1640 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1641 if (iptr->op1 == 0) {
1642 gen_nullptr_check(s1);
1645 M_SLL_IMM(s2, 1, REG_ITMP2);
1646 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1647 M_LHAX(d, s1, REG_ITMP2);
1648 store_reg_to_var_int(iptr->dst, d);
1651 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1653 var_to_reg_int(s1, src->prev, REG_ITMP1);
1654 var_to_reg_int(s2, src, REG_ITMP2);
1655 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1656 if (iptr->op1 == 0) {
1657 gen_nullptr_check(s1);
1660 M_SLL_IMM(s2, 1, REG_ITMP2);
1661 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1662 M_LHZX(d, s1, REG_ITMP2);
1663 store_reg_to_var_int(iptr->dst, d);
1666 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1668 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1669 var_to_reg_int(s2, src->prev, REG_ITMP2);
1670 if (iptr->op1 == 0) {
1671 gen_nullptr_check(s1);
1674 var_to_reg_int_high(s3, src, REG_ITMP3);
1675 M_SLL_IMM(s2, 3, REG_ITMP2);
1676 M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
1677 M_STWX(s3, s1, REG_ITMP2);
1678 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1679 var_to_reg_int_low(s3, src, REG_ITMP3);
1680 M_STWX(s3, s1, REG_ITMP2);
1683 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1685 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1686 var_to_reg_int(s2, src->prev, REG_ITMP2);
1687 if (iptr->op1 == 0) {
1688 gen_nullptr_check(s1);
1691 var_to_reg_int(s3, src, REG_ITMP3);
1692 M_SLL_IMM(s2, 2, REG_ITMP2);
1693 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1694 M_STWX(s3, s1, REG_ITMP2);
1697 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1699 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1700 var_to_reg_int(s2, src->prev, REG_ITMP2);
1701 if (iptr->op1 == 0) {
1702 gen_nullptr_check(s1);
1705 var_to_reg_flt(s3, src, REG_FTMP3);
1706 M_SLL_IMM(s2, 2, REG_ITMP2);
1707 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1708 M_STFSX(s3, s1, REG_ITMP2);
1711 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1713 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1714 var_to_reg_int(s2, src->prev, REG_ITMP2);
1715 if (iptr->op1 == 0) {
1716 gen_nullptr_check(s1);
1719 var_to_reg_flt(s3, src, REG_FTMP3);
1720 M_SLL_IMM(s2, 3, REG_ITMP2);
1721 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1722 M_STFDX(s3, s1, REG_ITMP2);
1725 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1727 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1728 var_to_reg_int(s2, src->prev, REG_ITMP2);
1729 if (iptr->op1 == 0) {
1730 gen_nullptr_check(s1);
1733 var_to_reg_int(s3, src, REG_ITMP3);
1734 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1735 M_STBX(s3, s1, REG_ITMP2);
1738 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1740 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1741 var_to_reg_int(s2, src->prev, REG_ITMP2);
1742 if (iptr->op1 == 0) {
1743 gen_nullptr_check(s1);
1746 var_to_reg_int(s3, src, REG_ITMP3);
1747 M_SLL_IMM(s2, 1, REG_ITMP2);
1748 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1749 M_STHX(s3, s1, REG_ITMP2);
1752 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1754 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1755 var_to_reg_int(s2, src->prev, REG_ITMP2);
1756 if (iptr->op1 == 0) {
1757 gen_nullptr_check(s1);
1760 var_to_reg_int(s3, src, REG_ITMP3);
1761 M_SLL_IMM(s2, 1, REG_ITMP2);
1762 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1763 M_STHX(s3, s1, REG_ITMP2);
1767 case ICMD_GETSTATIC: /* ... ==> ..., value */
1768 /* op1 = type, val.a = field address */
1771 codegen_addpatchref(cd, mcodeptr,
1772 PATCHER_get_putstatic,
1773 (unresolved_field *) iptr->target);
1775 if (showdisassemble)
1781 fieldinfo *fi = iptr->val.a;
1783 if (!fi->class->initialized) {
1784 codegen_addpatchref(cd, mcodeptr,
1785 PATCHER_clinit, fi->class);
1787 if (showdisassemble)
1791 a = (ptrint) &(fi->value);
1794 a = dseg_addaddress(cd, a);
1795 M_ALD(REG_ITMP1, REG_PV, a);
1796 switch (iptr->op1) {
1798 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1799 M_ILD(d, REG_ITMP1, 0);
1800 store_reg_to_var_int(iptr->dst, d);
1803 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1804 M_ILD(GET_HIGH_REG(d), REG_ITMP1, 0);
1805 M_ILD(GET_LOW_REG(d), REG_ITMP1, 4);
1806 store_reg_to_var_int(iptr->dst, d);
1809 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1810 M_ALD(d, REG_ITMP1, 0);
1811 store_reg_to_var_int(iptr->dst, d);
1814 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1815 M_FLD(d, REG_ITMP1, 0);
1816 store_reg_to_var_flt(iptr->dst, d);
1819 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1820 M_DLD(d, REG_ITMP1, 0);
1821 store_reg_to_var_flt(iptr->dst, d);
1826 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1827 /* op1 = type, val.a = field address */
1831 codegen_addpatchref(cd, mcodeptr,
1832 PATCHER_get_putstatic,
1833 (unresolved_field *) iptr->target);
1835 if (showdisassemble)
1841 fieldinfo *fi = iptr->val.a;
1843 if (!fi->class->initialized) {
1844 codegen_addpatchref(cd, mcodeptr,
1845 PATCHER_clinit, fi->class);
1847 if (showdisassemble)
1851 a = (ptrint) &(fi->value);
1854 a = dseg_addaddress(cd, a);
1855 M_ALD(REG_ITMP1, REG_PV, a);
1856 switch (iptr->op1) {
1858 var_to_reg_int(s2, src, REG_ITMP2);
1859 M_IST(s2, REG_ITMP1, 0);
1862 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1863 M_IST(GET_HIGH_REG(s2), REG_ITMP1, 0);
1864 M_IST(GET_LOW_REG(s2), REG_ITMP1, 4);
1867 var_to_reg_int(s2, src, REG_ITMP2);
1868 M_AST(s2, REG_ITMP1, 0);
1871 var_to_reg_flt(s2, src, REG_FTMP2);
1872 M_FST(s2, REG_ITMP1, 0);
1875 var_to_reg_flt(s2, src, REG_FTMP2);
1876 M_DST(s2, REG_ITMP1, 0);
1882 case ICMD_GETFIELD: /* ... ==> ..., value */
1883 /* op1 = type, val.i = field offset */
1885 var_to_reg_int(s1, src, REG_ITMP1);
1886 gen_nullptr_check(s1);
1889 codegen_addpatchref(cd, mcodeptr,
1890 PATCHER_get_putfield,
1891 (unresolved_field *) iptr->target);
1893 if (showdisassemble)
1899 a = ((fieldinfo *) (iptr->val.a))->offset;
1902 switch (iptr->op1) {
1904 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1906 store_reg_to_var_int(iptr->dst, d);
1909 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1910 M_ILD(GET_HIGH_REG(d), s1, a);
1911 M_ILD(GET_LOW_REG(d), s1, a + 4);
1912 store_reg_to_var_int(iptr->dst, d);
1915 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1917 store_reg_to_var_int(iptr->dst, d);
1920 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1922 store_reg_to_var_flt(iptr->dst, d);
1925 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1927 store_reg_to_var_flt(iptr->dst, d);
1932 case ICMD_PUTFIELD: /* ..., value ==> ... */
1933 /* op1 = type, val.i = field offset */
1935 var_to_reg_int(s1, src->prev, REG_ITMP1);
1936 gen_nullptr_check(s1);
1938 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
1939 if (IS_2_WORD_TYPE(iptr->op1)) {
1940 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP3, REG_ITMP2));
1942 var_to_reg_int(s2, src, REG_ITMP2);
1945 var_to_reg_flt(s2, src, REG_FTMP2);
1949 codegen_addpatchref(cd, mcodeptr,
1950 PATCHER_get_putfield,
1951 (unresolved_field *) iptr->target);
1953 if (showdisassemble)
1959 a = ((fieldinfo *) (iptr->val.a))->offset;
1962 switch (iptr->op1) {
1967 M_IST(GET_HIGH_REG(s2), s1, a);
1968 M_IST(GET_LOW_REG(s2), s1, a + 4);
1983 /* branch operations **************************************************/
1985 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1987 a = dseg_addaddress(cd, asm_handle_exception);
1988 M_ALD(REG_ITMP2, REG_PV, a);
1990 var_to_reg_int(s1, src, REG_ITMP1);
1991 M_INTMOVE(s1, REG_ITMP1_XPTR);
1993 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
1994 M_BL(0); /* get current PC */
1995 M_MFLR(REG_ITMP2_XPC);
1996 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
1997 M_RTS; /* jump to CTR */
2002 case ICMD_GOTO: /* ... ==> ... */
2003 /* op1 = target JavaVM pc */
2005 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2009 case ICMD_JSR: /* ... ==> ... */
2010 /* op1 = target JavaVM pc */
2012 if (m->isleafmethod) M_MFLR(REG_ITMP2);
2015 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
2016 if (m->isleafmethod) M_MTLR(REG_ITMP2);
2018 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2021 case ICMD_RET: /* ... ==> ... */
2022 /* op1 = local variable */
2024 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2025 if (var->flags & INMEMORY) {
2026 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2029 M_MTCTR(var->regoff);
2034 case ICMD_IFNULL: /* ..., value ==> ... */
2035 /* op1 = target JavaVM pc */
2037 var_to_reg_int(s1, src, REG_ITMP1);
2040 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2043 case ICMD_IFNONNULL: /* ..., value ==> ... */
2044 /* op1 = target JavaVM pc */
2046 var_to_reg_int(s1, src, REG_ITMP1);
2049 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2057 case ICMD_IFEQ: /* ..., value ==> ... */
2058 /* op1 = target JavaVM pc, val.i = constant */
2060 var_to_reg_int(s1, src, REG_ITMP1);
2061 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2062 M_CMPI(s1, iptr->val.i);
2065 ICONST(REG_ITMP2, iptr->val.i);
2066 M_CMP(s1, REG_ITMP2);
2089 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2093 case ICMD_IF_LEQ: /* ..., value ==> ... */
2094 /* op1 = target JavaVM pc, val.l = constant */
2096 var_to_reg_int_low(s1, src, REG_ITMP1);
2097 var_to_reg_int_high(s2, src, REG_ITMP2);
2098 if (iptr->val.l == 0) {
2099 M_OR(s1, s2, REG_ITMP3);
2100 M_CMPI(REG_ITMP3, 0);
2102 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2103 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2105 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2108 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2109 M_CMP(s2, REG_ITMP3);
2111 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2112 M_CMP(s1, REG_ITMP3)
2115 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2118 case ICMD_IF_LLT: /* ..., value ==> ... */
2119 /* op1 = target JavaVM pc, val.l = constant */
2120 var_to_reg_int_low(s1, src, REG_ITMP1);
2121 var_to_reg_int_high(s2, src, REG_ITMP2);
2122 /* if (iptr->val.l == 0) { */
2123 /* M_OR(s1, s2, REG_ITMP3); */
2124 /* M_CMPI(REG_ITMP3, 0); */
2127 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2128 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2130 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2132 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2135 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2136 M_CMP(s2, REG_ITMP3);
2138 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2140 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2141 M_CMP(s1, REG_ITMP3)
2144 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2147 case ICMD_IF_LLE: /* ..., value ==> ... */
2148 /* op1 = target JavaVM pc, val.l = constant */
2150 var_to_reg_int_low(s1, src, REG_ITMP1);
2151 var_to_reg_int_high(s2, src, REG_ITMP2);
2152 /* if (iptr->val.l == 0) { */
2153 /* M_OR(s1, s2, REG_ITMP3); */
2154 /* M_CMPI(REG_ITMP3, 0); */
2157 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2158 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2160 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2162 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2165 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2166 M_CMP(s2, REG_ITMP3);
2168 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2170 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2171 M_CMP(s1, REG_ITMP3)
2174 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2177 case ICMD_IF_LNE: /* ..., value ==> ... */
2178 /* op1 = target JavaVM pc, val.l = constant */
2180 var_to_reg_int_low(s1, src, REG_ITMP1);
2181 var_to_reg_int_high(s2, src, REG_ITMP2);
2182 if (iptr->val.l == 0) {
2183 M_OR(s1, s2, REG_ITMP3);
2184 M_CMPI(REG_ITMP3, 0);
2186 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2187 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2189 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2192 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2193 M_CMP(s2, REG_ITMP3);
2195 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2196 M_CMP(s1, REG_ITMP3)
2199 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2202 case ICMD_IF_LGT: /* ..., value ==> ... */
2203 /* op1 = target JavaVM pc, val.l = constant */
2205 var_to_reg_int_low(s1, src, REG_ITMP1);
2206 var_to_reg_int_high(s2, src, REG_ITMP2);
2207 /* if (iptr->val.l == 0) { */
2208 /* M_OR(s1, s2, REG_ITMP3); */
2209 /* M_CMPI(REG_ITMP3, 0); */
2212 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2213 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2215 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2217 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2220 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2221 M_CMP(s2, REG_ITMP3);
2223 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2225 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2226 M_CMP(s1, REG_ITMP3)
2229 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2232 case ICMD_IF_LGE: /* ..., value ==> ... */
2233 /* op1 = target JavaVM pc, val.l = constant */
2234 var_to_reg_int_low(s1, src, REG_ITMP1);
2235 var_to_reg_int_high(s2, src, REG_ITMP2);
2236 /* if (iptr->val.l == 0) { */
2237 /* M_OR(s1, s2, REG_ITMP3); */
2238 /* M_CMPI(REG_ITMP3, 0); */
2241 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2242 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2244 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2246 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2249 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2250 M_CMP(s2, REG_ITMP3);
2252 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2254 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2255 M_CMP(s1, REG_ITMP3)
2258 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2262 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2263 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2264 /******************************************************************
2265 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2266 *******************************************************************/
2267 case ICMD_IF_ACMPEQ:
2269 var_to_reg_int(s1, src->prev, REG_ITMP1);
2270 var_to_reg_int(s2, src, REG_ITMP2);
2273 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2276 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2277 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2278 /******************************************************************
2279 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2280 *******************************************************************/
2281 case ICMD_IF_ACMPNE:
2283 var_to_reg_int(s1, src->prev, REG_ITMP1);
2284 var_to_reg_int(s2, src, REG_ITMP2);
2287 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2290 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2291 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2292 /******************************************************************
2293 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2294 *******************************************************************/
2296 var_to_reg_int(s1, src->prev, REG_ITMP1);
2297 var_to_reg_int(s2, src, REG_ITMP2);
2300 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2303 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2304 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2305 /******************************************************************
2306 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2307 *******************************************************************/
2309 var_to_reg_int(s1, src->prev, REG_ITMP1);
2310 var_to_reg_int(s2, src, REG_ITMP2);
2313 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2316 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2317 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2318 /******************************************************************
2319 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2320 *******************************************************************/
2322 var_to_reg_int(s1, src->prev, REG_ITMP1);
2323 var_to_reg_int(s2, src, REG_ITMP2);
2326 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2329 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2330 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2331 /******************************************************************
2332 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2333 *******************************************************************/
2335 var_to_reg_int(s1, src->prev, REG_ITMP1);
2336 var_to_reg_int(s2, src, REG_ITMP2);
2339 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2342 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2344 var_to_reg_int(s1, src, REG_RESULT);
2345 M_TINTMOVE(src->type, s1, REG_RESULT);
2346 goto nowperformreturn;
2348 var_to_reg_int(s1, src, PACK_REGS(REG_RESULT2, REG_RESULT));
2349 M_TINTMOVE(src->type, s1, PACK_REGS(REG_RESULT2, REG_RESULT));
2350 goto nowperformreturn;
2352 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2354 var_to_reg_flt(s1, src, REG_FRESULT);
2355 M_FLTMOVE(s1, REG_FRESULT);
2356 goto nowperformreturn;
2358 case ICMD_RETURN: /* ... ==> ... */
2364 p = parentargs_base;
2366 /* call trace function */
2370 M_LDA(REG_SP, REG_SP, -10 * 8);
2371 M_DST(REG_FRESULT, REG_SP, 48+0);
2372 M_IST(REG_RESULT, REG_SP, 48+8);
2373 M_AST(REG_ITMP3, REG_SP, 48+12);
2374 M_IST(REG_RESULT2, REG_SP, 48+16);
2376 /* keep this order */
2377 switch (iptr->opc) {
2380 #if defined(__DARWIN__)
2381 M_MOV(REG_RESULT, rd->argintregs[2]);
2382 M_CLR(rd->argintregs[1]);
2384 M_MOV(REG_RESULT, rd->argintregs[3]);
2385 M_CLR(rd->argintregs[2]);
2390 #if defined(__DARWIN__)
2391 M_MOV(REG_RESULT2, rd->argintregs[2]);
2392 M_MOV(REG_RESULT, rd->argintregs[1]);
2394 M_MOV(REG_RESULT2, rd->argintregs[3]);
2395 M_MOV(REG_RESULT, rd->argintregs[2]);
2400 a = dseg_addaddress(cd, m);
2401 M_ALD(rd->argintregs[0], REG_PV, a);
2403 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2404 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2405 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2406 M_ALD(REG_ITMP2, REG_PV, a);
2409 M_DLD(REG_FRESULT, REG_SP, 48+0);
2410 M_ILD(REG_RESULT, REG_SP, 48+8);
2411 M_ALD(REG_ITMP3, REG_SP, 48+12);
2412 M_ILD(REG_RESULT2, REG_SP, 48+16);
2413 M_LDA(REG_SP, REG_SP, 10 * 8);
2417 #if defined(USE_THREADS)
2418 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2419 /* we need to save the proper return value */
2420 switch (iptr->opc) {
2422 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2426 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2429 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2432 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2436 a = dseg_addaddress(cd, BUILTIN_monitorexit);
2437 M_ALD(REG_ITMP3, REG_PV, a);
2439 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 4);
2442 /* and now restore the proper return value */
2443 switch (iptr->opc) {
2445 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2449 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2452 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2455 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2461 /* restore return address */
2463 if (!m->isleafmethod) {
2464 M_ALD(REG_ITMP3, REG_SP, p * 4 + LA_LR_OFFSET);
2468 /* restore saved registers */
2470 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2471 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2473 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2474 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2477 /* deallocate stack */
2479 if (parentargs_base)
2480 M_LDA(REG_SP, REG_SP, parentargs_base * 4);
2488 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2493 tptr = (void **) iptr->target;
2495 s4ptr = iptr->val.a;
2496 l = s4ptr[1]; /* low */
2497 i = s4ptr[2]; /* high */
2499 var_to_reg_int(s1, src, REG_ITMP1);
2501 M_INTMOVE(s1, REG_ITMP1);
2502 } else if (l <= 32768) {
2503 M_LDA(REG_ITMP1, s1, -l);
2505 ICONST(REG_ITMP2, l);
2506 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2512 M_CMPUI(REG_ITMP1, i - 1);
2515 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2516 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2518 /* build jump table top down and use address of lowest entry */
2520 /* s4ptr += 3 + i; */
2524 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2525 dseg_addtarget(cd, (basicblock *) tptr[0]);
2530 /* length of dataseg after last dseg_addtarget is used by load */
2532 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2533 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2534 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2541 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2543 s4 i, l, val, *s4ptr;
2546 tptr = (void **) iptr->target;
2548 s4ptr = iptr->val.a;
2549 l = s4ptr[0]; /* default */
2550 i = s4ptr[1]; /* count */
2552 MCODECHECK((i<<2)+8);
2553 var_to_reg_int(s1, src, REG_ITMP1);
2559 if ((val >= -32768) && (val <= 32767)) {
2563 a = dseg_adds4(cd, val);
2564 M_ILD(REG_ITMP2, REG_PV, a);
2565 M_CMP(s1, REG_ITMP2);
2568 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2569 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2573 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2575 tptr = (void **) iptr->target;
2576 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2583 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2584 /* op1 = arg count val.a = builtintable entry */
2590 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2591 /* op1 = arg count, val.a = method pointer */
2593 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2594 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2595 case ICMD_INVOKEINTERFACE:
2600 md = lm->parseddesc;
2602 unresolved_method *um = iptr->target;
2603 md = um->methodref->parseddesc.md;
2609 MCODECHECK((s3 << 1) + 64);
2611 /* copy arguments to registers or stack location */
2613 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2614 if (src->varkind == ARGVAR)
2616 if (IS_INT_LNG_TYPE(src->type)) {
2617 if (!md->params[s3].inmemory) {
2618 if (IS_2_WORD_TYPE(src->type))
2620 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2621 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]);
2623 s1 = rd->argintregs[md->params[s3].regoff];
2624 var_to_reg_int(d, src, s1);
2625 M_TINTMOVE(src->type, d, s1);
2627 var_to_reg_int(d, src, PACK_REGS(REG_ITMP3, REG_ITMP1));
2628 M_IST(GET_HIGH_REG(d), REG_SP,
2629 md->params[s3].regoff * 4);
2630 if (IS_2_WORD_TYPE(src->type))
2631 M_IST(GET_LOW_REG(d),
2632 REG_SP, md->params[s3].regoff * 4 + 4);
2636 if (!md->params[s3].inmemory) {
2637 s1 = rd->argfltregs[md->params[s3].regoff];
2638 var_to_reg_flt(d, src, s1);
2641 var_to_reg_flt(d, src, REG_FTMP1);
2642 if (IS_2_WORD_TYPE(src->type))
2643 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2645 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2650 switch (iptr->opc) {
2653 codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target);
2655 if (showdisassemble)
2661 a = (ptrint) bte->fp;
2664 a = dseg_addaddress(cd, a);
2665 d = md->returntype.type;
2667 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2670 case ICMD_INVOKESPECIAL:
2671 gen_nullptr_check(rd->argintregs[0]);
2672 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr */
2675 case ICMD_INVOKESTATIC:
2677 unresolved_method *um = iptr->target;
2679 codegen_addpatchref(cd, mcodeptr,
2680 PATCHER_invokestatic_special, um);
2682 if (showdisassemble)
2686 d = md->returntype.type;
2689 a = (ptrint) lm->stubroutine;
2690 d = md->returntype.type;
2693 a = dseg_addaddress(cd, a);
2694 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2697 case ICMD_INVOKEVIRTUAL:
2698 gen_nullptr_check(rd->argintregs[0]);
2701 unresolved_method *um = iptr->target;
2703 codegen_addpatchref(cd, mcodeptr,
2704 PATCHER_invokevirtual, um);
2706 if (showdisassemble)
2710 d = md->returntype.type;
2713 s1 = OFFSET(vftbl_t, table[0]) +
2714 sizeof(methodptr) * lm->vftblindex;
2715 d = md->returntype.type;
2718 M_ALD(REG_METHODPTR, rd->argintregs[0],
2719 OFFSET(java_objectheader, vftbl));
2720 M_ALD(REG_PV, REG_METHODPTR, s1);
2723 case ICMD_INVOKEINTERFACE:
2724 gen_nullptr_check(rd->argintregs[0]);
2727 unresolved_method *um = iptr->target;
2729 codegen_addpatchref(cd, mcodeptr,
2730 PATCHER_invokeinterface, um);
2732 if (showdisassemble)
2737 d = md->returntype.type;
2740 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2741 sizeof(methodptr*) * lm->class->index;
2743 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2745 d = md->returntype.type;
2748 M_ALD(REG_METHODPTR, rd->argintregs[0],
2749 OFFSET(java_objectheader, vftbl));
2750 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2751 M_ALD(REG_PV, REG_METHODPTR, s2);
2760 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2762 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2764 s4 ml = -s1, mh = 0;
2765 while (ml < -32768) { ml += 65536; mh--; }
2766 M_LDA(REG_PV, REG_ITMP1, ml);
2767 M_LDAH(REG_PV, REG_PV, mh);
2770 /* d contains return type */
2772 if (d != TYPE_VOID) {
2773 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2774 if (IS_2_WORD_TYPE(iptr->dst->type)) {
2775 s1 = reg_of_var(rd, iptr->dst,
2776 PACK_REGS(REG_RESULT2, REG_RESULT));
2777 M_TINTMOVE(iptr->dst->type,
2778 PACK_REGS(REG_RESULT2, REG_RESULT), s1);
2780 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2781 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2783 store_reg_to_var_int(iptr->dst, s1);
2786 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2787 M_FLTMOVE(REG_FRESULT, s1);
2788 store_reg_to_var_flt(iptr->dst, s1);
2794 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2796 /* op1: 0 == array, 1 == class */
2797 /* val.a: (classinfo*) superclass */
2799 /* superclass is an interface:
2801 * OK if ((sub == NULL) ||
2802 * (sub->vftbl->interfacetablelength > super->index) &&
2803 * (sub->vftbl->interfacetable[-super->index] != NULL));
2805 * superclass is a class:
2807 * OK if ((sub == NULL) || (0
2808 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2809 * super->vftbl->diffvall));
2814 vftbl_t *supervftbl;
2817 super = (classinfo *) iptr->val.a;
2824 superindex = super->index;
2825 supervftbl = super->vftbl;
2828 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2829 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2831 var_to_reg_int(s1, src, REG_ITMP1);
2833 /* calculate interface checkcast code size */
2837 s2 += (showdisassemble ? 1 : 0);
2839 /* calculate class checkcast code size */
2841 s3 = 8 + (s1 == REG_ITMP1);
2843 s3 += (showdisassemble ? 1 : 0);
2845 /* if class is not resolved, check which code to call */
2849 M_BEQ(3 + (showdisassemble ? 1 : 0) + s2 + 1 + s3);
2851 codegen_addpatchref(cd, mcodeptr,
2852 PATCHER_checkcast_instanceof_flags,
2853 (constant_classref *) iptr->target);
2855 if (showdisassemble)
2858 a = dseg_adds4(cd, 0); /* super->flags */
2859 M_ILD(REG_ITMP2, REG_PV, a);
2860 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2864 /* interface checkcast code */
2866 if (!super || (super->flags & ACC_INTERFACE)) {
2872 codegen_addpatchref(cd, mcodeptr,
2873 PATCHER_checkcast_instanceof_interface,
2874 (constant_classref *) iptr->target);
2876 if (showdisassemble)
2880 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2881 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2882 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2884 codegen_addxcastrefs(cd, mcodeptr);
2885 M_ALD(REG_ITMP3, REG_ITMP2,
2886 OFFSET(vftbl_t, interfacetable[0]) -
2887 superindex * sizeof(methodptr*));
2890 codegen_addxcastrefs(cd, mcodeptr);
2896 /* class checkcast code */
2898 if (!super || !(super->flags & ACC_INTERFACE)) {
2904 codegen_addpatchref(cd, mcodeptr,
2905 PATCHER_checkcast_class,
2906 (constant_classref *) iptr->target);
2908 if (showdisassemble)
2912 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2913 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2914 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
2916 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2917 a = dseg_addaddress(cd, supervftbl);
2918 M_ALD(REG_ITMP2, REG_PV, a);
2919 if (s1 != REG_ITMP1) {
2920 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2921 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2922 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2923 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2925 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2927 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2928 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2929 M_ALD(REG_ITMP2, REG_PV, a);
2930 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2931 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2932 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2935 M_CMPU(REG_ITMP3, REG_ITMP2);
2937 codegen_addxcastrefs(cd, mcodeptr);
2939 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2941 store_reg_to_var_int(iptr->dst, d);
2945 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2947 /* op1: 0 == array, 1 == class */
2948 /* val.a: (classinfo*) superclass */
2950 /* superclass is an interface:
2952 * return (sub != NULL) &&
2953 * (sub->vftbl->interfacetablelength > super->index) &&
2954 * (sub->vftbl->interfacetable[-super->index] != NULL);
2956 * superclass is a class:
2958 * return ((sub != NULL) && (0
2959 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2960 * super->vftbl->diffvall));
2965 vftbl_t *supervftbl;
2968 super = (classinfo *) iptr->val.a;
2975 superindex = super->index;
2976 supervftbl = super->vftbl;
2979 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2980 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2982 var_to_reg_int(s1, src, REG_ITMP1);
2983 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2985 M_MOV(s1, REG_ITMP1);
2989 /* calculate interface instanceof code size */
2993 s2 += (showdisassemble ? 1 : 0);
2995 /* calculate class instanceof code size */
2999 s3 += (showdisassemble ? 1 : 0);
3003 /* if class is not resolved, check which code to call */
3007 M_BEQ(3 + (showdisassemble ? 1 : 0) + s2 + 1 + s3);
3009 codegen_addpatchref(cd, mcodeptr,
3010 PATCHER_checkcast_instanceof_flags,
3011 (constant_classref *) iptr->target);
3013 if (showdisassemble)
3016 a = dseg_adds4(cd, 0); /* super->flags */
3017 M_ILD(REG_ITMP2, REG_PV, a);
3018 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
3022 /* interface instanceof code */
3024 if (!super || (super->flags & ACC_INTERFACE)) {
3030 codegen_addpatchref(cd, mcodeptr,
3031 PATCHER_checkcast_instanceof_interface,
3032 (constant_classref *) iptr->target);
3034 if (showdisassemble)
3038 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3039 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
3040 M_LDATST(REG_ITMP2, REG_ITMP2, -superindex);
3042 M_ALD(REG_ITMP1, REG_ITMP1,
3043 OFFSET(vftbl_t, interfacetable[0]) -
3044 superindex * sizeof(methodptr*));
3048 M_IADD_IMM(REG_ZERO, 1, d);
3054 /* class instanceof code */
3056 if (!super || !(super->flags & ACC_INTERFACE)) {
3062 codegen_addpatchref(cd, mcodeptr,
3063 PATCHER_instanceof_class,
3064 (constant_classref *) iptr->target);
3066 if (showdisassemble) {
3071 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
3072 a = dseg_addaddress(cd, supervftbl);
3073 M_ALD(REG_ITMP2, REG_PV, a);
3074 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3075 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
3077 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
3078 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
3079 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
3080 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3081 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
3083 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
3084 M_CMPU(REG_ITMP1, REG_ITMP2);
3087 M_IADD_IMM(REG_ZERO, 1, d);
3089 store_reg_to_var_int(iptr->dst, d);
3093 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
3095 var_to_reg_int(s1, src, REG_ITMP1);
3098 codegen_addxcheckarefs(cd, mcodeptr);
3101 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3103 M_CMPI(REG_RESULT, 0);
3105 codegen_addxexceptionrefs(cd, mcodeptr);
3108 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3109 /* op1 = dimension, val.a = array descriptor */
3111 /* check for negative sizes and copy sizes to stack if necessary */
3113 MCODECHECK((iptr->op1 << 1) + 64);
3115 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3116 var_to_reg_int(s2, src, REG_ITMP1);
3119 codegen_addxcheckarefs(cd, mcodeptr);
3121 /* copy SAVEDVAR sizes to stack */
3123 if (src->varkind != ARGVAR)
3124 #if defined(__DARWIN__)
3125 M_IST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 4);
3127 M_IST(s2, REG_SP, LA_SIZE + (s1 + 3) * 4);
3131 /* is patcher function set? */
3134 codegen_addpatchref(cd, mcodeptr,
3135 (functionptr) iptr->target, iptr->val.a);
3137 if (showdisassemble)
3143 a = (ptrint) iptr->val.a;
3146 /* a0 = dimension count */
3148 ICONST(rd->argintregs[0], iptr->op1);
3150 /* a1 = arraydescriptor */
3152 a = dseg_addaddress(cd, iptr->val.a);
3153 M_ALD(rd->argintregs[1], REG_PV, a);
3155 /* a2 = pointer to dimensions = stack pointer */
3157 #if defined(__DARWIN__)
3158 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 4);
3160 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 4);
3163 a = dseg_addaddress(cd, BUILTIN_multianewarray);
3164 M_ALD(REG_PV, REG_PV, a);
3167 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3170 M_LDA (REG_PV, REG_ITMP1, -s1);
3172 s4 ml = -s1, mh = 0;
3173 while (ml < -32768) {ml += 65536; mh--;}
3174 M_LDA(REG_PV, REG_ITMP1, ml);
3175 M_LDAH(REG_PV, REG_PV, mh);
3177 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3178 M_INTMOVE(REG_RESULT, s1);
3179 store_reg_to_var_int(iptr->dst, s1);
3184 throw_cacao_exception_exit(string_java_lang_InternalError,
3185 "Unknown ICMD %d", iptr->opc);
3188 } /* for instruction */
3190 /* copy values to interface registers */
3192 src = bptr->outstack;
3193 len = bptr->outdepth;
3194 MCODECHECK(64 + len);
3200 if ((src->varkind != STACKVAR)) {
3202 if (IS_FLT_DBL_TYPE(s2)) {
3203 var_to_reg_flt(s1, src, REG_FTMP1);
3204 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3205 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3208 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3212 var_to_reg_int(s1, src, REG_ITMP1);
3213 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3214 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3217 if (IS_2_WORD_TYPE(s2)) {
3218 M_IST(GET_HIGH_REG(s1),
3219 REG_SP, rd->interfaces[len][s2].regoff * 4);
3220 M_IST(GET_LOW_REG(s1), REG_SP,
3221 rd->interfaces[len][s2].regoff * 4 + 4);
3223 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3231 } /* if (bptr -> flags >= BBREACHED) */
3232 } /* for basic block */
3234 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3237 /* generate bound check stubs */
3239 s4 *xcodeptr = NULL;
3242 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3243 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3245 (u1 *) mcodeptr - cd->mcodebase);
3249 /* move index register into REG_ITMP1 */
3250 M_MOV(bref->reg, REG_ITMP1);
3251 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3253 if (xcodeptr != NULL) {
3254 off = xcodeptr - mcodeptr - 1;
3258 xcodeptr = mcodeptr;
3260 M_STWU(REG_SP, REG_SP, -(24 + 2 * 4));
3261 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3263 M_MOV(REG_ITMP1, rd->argintregs[0]);
3265 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3266 M_ALD(REG_ITMP2, REG_PV, a);
3269 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3271 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3272 M_IADD_IMM(REG_SP, 24 + 2 * 4, REG_SP);
3274 a = dseg_addaddress(cd, asm_handle_exception);
3275 M_ALD(REG_ITMP3, REG_PV, a);
3282 /* generate negative array size check stubs */
3286 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3287 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3288 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3290 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3294 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3296 (u1 *) mcodeptr - cd->mcodebase);
3300 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3302 if (xcodeptr != NULL) {
3303 off = xcodeptr - mcodeptr - 1;
3307 xcodeptr = mcodeptr;
3309 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3310 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3312 a = dseg_addaddress(cd, new_negativearraysizeexception);
3313 M_ALD(REG_ITMP2, REG_PV, a);
3316 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3318 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3319 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3321 a = dseg_addaddress(cd, asm_handle_exception);
3322 M_ALD(REG_ITMP3, REG_PV, a);
3329 /* generate cast check stubs */
3333 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3334 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3335 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3337 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3341 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3343 (u1 *) mcodeptr - cd->mcodebase);
3347 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3349 if (xcodeptr != NULL) {
3350 off = xcodeptr - mcodeptr - 1;
3354 xcodeptr = mcodeptr;
3356 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3357 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3359 a = dseg_addaddress(cd, new_classcastexception);
3360 M_ALD(REG_ITMP2, REG_PV, a);
3363 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3365 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3366 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3368 a = dseg_addaddress(cd, asm_handle_exception);
3369 M_ALD(REG_ITMP3, REG_PV, a);
3376 /* generate exception check stubs */
3380 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3381 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3382 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3384 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3388 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3390 (u1 *) mcodeptr - cd->mcodebase);
3394 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3396 if (xcodeptr != NULL) {
3397 off = xcodeptr - mcodeptr - 1;
3401 xcodeptr = mcodeptr;
3403 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3404 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3406 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3407 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3408 M_ALD(REG_ITMP2, REG_PV, a);
3412 /* get the exceptionptr from the ptrprt and clear it */
3413 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3415 M_AST(REG_ITMP3, REG_RESULT, 0);
3417 a = dseg_addaddress(cd, &_exceptionptr);
3418 M_ALD(REG_ITMP2, REG_PV, a);
3420 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3422 M_AST(REG_ITMP3, REG_ITMP2, 0);
3425 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3426 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3428 a = dseg_addaddress(cd, asm_handle_exception);
3429 M_ALD(REG_ITMP3, REG_PV, a);
3435 /* generate null pointer check stubs */
3439 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3440 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3441 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3443 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3447 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3449 (u1 *) mcodeptr - cd->mcodebase);
3453 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3455 if (xcodeptr != NULL) {
3456 off = xcodeptr - mcodeptr - 1;
3460 xcodeptr = mcodeptr;
3462 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3463 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3465 a = dseg_addaddress(cd, new_nullpointerexception);
3466 M_ALD(REG_ITMP2, REG_PV, a);
3469 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3471 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3472 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3474 a = dseg_addaddress(cd, asm_handle_exception);
3475 M_ALD(REG_ITMP3, REG_PV, a);
3481 /* generate patcher stub call code */
3488 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3489 /* check code segment size */
3493 /* Get machine code which is patched back in later. The call is */
3494 /* 1 instruction word long. */
3496 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3499 /* patch in the call to call the following code (done at compile */
3502 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3503 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3505 M_BL(tmpmcodeptr - (xcodeptr + 1));
3507 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3509 /* create stack frame - keep stack 16-byte aligned */
3511 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
3513 /* move return address onto stack */
3516 M_AST(REG_ITMP3, REG_SP, 4 * 4);
3518 /* move pointer to java_objectheader onto stack */
3520 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3521 /* order reversed because of data segment layout */
3523 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3524 off = dseg_addaddress(cd, NULL); /* vftbl */
3526 if (off >= -32768) {
3527 M_LDA(REG_ITMP3, REG_PV, off);
3529 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3530 M_LDA(REG_ITMP3, REG_ITMP3, off);
3532 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3535 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3538 /* move machine code onto stack */
3540 off = dseg_adds4(cd, mcode);
3541 if (off >= -32768) {
3542 M_ILD(REG_ITMP3, REG_PV, off);
3544 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3545 M_ILD(REG_ITMP3, REG_ITMP3, off);
3547 M_IST(REG_ITMP3, REG_SP, 2 * 4);
3549 /* move class/method/field reference onto stack */
3551 off = dseg_addaddress(cd, pref->ref);
3552 if (off >= -32768) {
3553 M_ALD(REG_ITMP3, REG_PV, off);
3555 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3556 M_ALD(REG_ITMP3, REG_ITMP3, off);
3558 M_AST(REG_ITMP3, REG_SP, 1 * 4);
3560 /* move patcher function pointer onto stack */
3562 off = dseg_addaddress(cd, pref->patcher);
3563 if (off >= -32768) {
3564 M_ALD(REG_ITMP3, REG_PV, off);
3566 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3567 M_ALD(REG_ITMP3, REG_ITMP3, off);
3569 M_AST(REG_ITMP3, REG_SP, 0 * 4);
3571 off = dseg_addaddress(cd, asm_wrapper_patcher);
3572 if (off >= -32768) {
3573 M_ALD(REG_ITMP3, REG_PV, off);
3575 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3576 M_ALD(REG_ITMP3, REG_ITMP3, off);
3585 codegen_finish(m, cd, (ptrint) ((u1 *) mcodeptr - cd->mcodebase));
3587 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3591 /* createcompilerstub **********************************************************
3593 Creates a stub routine which calls the compiler.
3595 *******************************************************************************/
3597 #define COMPSTUBSIZE 6
3599 functionptr createcompilerstub(methodinfo *m)
3601 s4 *s = CNEW(s4, COMPSTUBSIZE); /* memory to hold the stub */
3602 s4 *mcodeptr = s; /* code generation pointer */
3604 M_LDA(REG_ITMP1, REG_PV, 4*4);
3605 M_ALD(REG_PV, REG_PV, 5*4);
3609 s[4] = (s4) m; /* literals to be adressed */
3610 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3612 asm_cacheflush((void *) s, (u1 *) mcodeptr - (u1 *) s);
3614 #if defined(STATISTICS)
3616 count_cstub_len += COMPSTUBSIZE * 4;
3619 return (functionptr) (ptrint) s;
3623 /* createnativestub ************************************************************
3625 Creates a stub routine which calls a native method.
3627 *******************************************************************************/
3629 functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
3630 registerdata *rd, methoddesc *nmd)
3632 s4 *mcodeptr; /* code generation pointer */
3633 s4 stackframesize; /* size of stackframe if needed */
3637 s4 i, j; /* count variables */
3641 /* set some variables */
3644 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3646 /* calculate stackframe size */
3648 stackframesize = nmd->memuse;
3649 stackframesize = (stackframesize + 3) & ~3; /* keep stack 16-byte aligned */
3652 /* create method header */
3654 (void) dseg_addaddress(cd, m); /* MethodPointer */
3655 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
3656 (void) dseg_adds4(cd, 0); /* IsSync */
3657 (void) dseg_adds4(cd, 0); /* IsLeaf */
3658 (void) dseg_adds4(cd, 0); /* IntSave */
3659 (void) dseg_adds4(cd, 0); /* FltSave */
3660 (void) dseg_addlinenumbertablesize(cd);
3661 (void) dseg_adds4(cd, 0); /* ExTableSize */
3664 /* initialize mcode variables */
3666 mcodeptr = (s4 *) cd->mcodebase;
3667 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
3673 M_AST(REG_ITMP1, REG_SP, LA_LR_OFFSET);
3674 M_STWU(REG_SP, REG_SP, -(stackframesize * 4));
3677 /* if function is static, check for initialized */
3679 if ((m->flags & ACC_STATIC) && !m->class->initialized) {
3680 codegen_addpatchref(cd, mcodeptr, PATCHER_clinit, m->class);
3682 if (showdisassemble)
3691 /* XXX must be a multiple of 16 */
3692 M_LDA(REG_SP, REG_SP, -(LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3696 /* save all arguments into the reserved stack space */
3698 for (i = 0; i < md->paramcount && i < TRACE_ARGS_NUM; i++) {
3699 t = md->paramtypes[i].type;
3701 if (IS_INT_LNG_TYPE(t)) {
3702 /* overlapping u8's are on the stack */
3703 if ((i + longargs + dblargs) <
3704 (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3705 s1 = rd->argintregs[i + longargs + dblargs];
3707 if (!IS_2_WORD_TYPE(t)) {
3708 M_IST(REG_ITMP1, REG_SP, LA_SIZE + i * 8);
3709 M_IST(s1, REG_SP, LA_SIZE + i * 8 + 4);
3712 rd->argintregs[i + longargs + dblargs + 1]);
3713 M_IST(GET_HIGH_REG(s1), REG_SP, LA_SIZE + i * 8);
3714 M_IST(GET_LOW_REG(s1), REG_SP, LA_SIZE + i * 8 + 4);
3719 off = dseg_adds4(cd, 0xdeadbeef);
3720 M_ILD(REG_ITMP1, REG_PV, off);
3721 M_IST(REG_ITMP1, REG_SP, LA_SIZE + i * 8);
3722 M_IST(REG_ITMP1, REG_SP, LA_SIZE + i * 8 + 4);
3726 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3727 s1 = rd->argfltregs[fltargs + dblargs];
3729 if (!IS_2_WORD_TYPE(t)) {
3730 M_IST(REG_ITMP1, REG_SP, LA_SIZE + i * 8);
3731 M_FST(s1, REG_SP, LA_SIZE + i * 8 + 4);
3734 M_DST(s1, REG_SP, LA_SIZE + i * 8);
3739 /* this should not happen */
3744 /* TODO: save remaining integer and float argument registers */
3746 /* load first 4 arguments into integer argument registers */
3748 for (i = 0; i < INT_ARG_CNT; i++)
3749 M_ILD(rd->argintregs[i], REG_SP, LA_SIZE + i * 4);
3751 off = dseg_addaddress(cd, m);
3752 M_ALD(REG_ITMP1, REG_PV, off);
3753 #if defined(__DARWIN__)
3754 /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + */
3755 /* 32 (4 * s8 parameter area stack) = 88 */
3756 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 8 * 8);
3758 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
3760 off = dseg_addaddress(cd, builtin_trace_args);
3761 M_ALD(REG_ITMP2, REG_PV, off);
3769 /* restore arguments into the reserved stack space */
3771 for (i = 0; i < md->paramcount && i < TRACE_ARGS_NUM; i++) {
3772 t = md->paramtypes[i].type;
3774 if (IS_INT_LNG_TYPE(t)) {
3775 if ((i + longargs + dblargs) < INT_ARG_CNT) {
3776 s1 = rd->argintregs[i + longargs + dblargs];
3778 if (!IS_2_WORD_TYPE(t)) {
3779 M_ILD(s1, REG_SP, LA_SIZE + i * 8 + 4);
3782 rd->argintregs[i + longargs + dblargs + 1]);
3783 M_ILD(GET_HIGH_REG(s1), REG_SP, LA_SIZE + i * 8);
3784 M_ILD(GET_LOW_REG(s1), REG_SP, LA_SIZE + i * 8 + 4);
3790 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3791 s1 = rd->argfltregs[fltargs + dblargs];
3793 if (!IS_2_WORD_TYPE(t)) {
3794 M_FLD(s1, REG_SP, LA_SIZE + i * 8 + 4);
3797 M_DLD(s1, REG_SP, LA_SIZE + i * 8);
3804 M_LDA(REG_SP, REG_SP, LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3807 /* copy or spill arguments to new locations */
3809 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3810 t = md->paramtypes[i].type;
3812 if (IS_INT_LNG_TYPE(t)) {
3813 if (!md->params[i].inmemory) {
3814 if (IS_2_WORD_TYPE(t))
3816 rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
3817 rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
3819 s1 = rd->argintregs[md->params[i].regoff];
3820 if (!nmd->params[j].inmemory) {
3821 if (IS_2_WORD_TYPE(t))
3823 rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)],
3824 rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]);
3826 s2 = rd->argintregs[nmd->params[j].regoff];
3827 M_TINTMOVE(t, s1, s2);
3830 s2 = nmd->params[j].regoff;
3831 if (IS_2_WORD_TYPE(t)) {
3832 M_IST(GET_HIGH_REG(s1), REG_SP, s2 * 4);
3833 M_IST(GET_LOW_REG(s1), REG_SP, s2 * 4 + 4);
3835 M_IST(s1, REG_SP, s2 * 4);
3840 s1 = md->params[i].regoff + stackframesize;
3841 s2 = nmd->params[j].regoff;
3843 M_ILD(REG_ITMP1, REG_SP, s1 * 4);
3844 M_IST(REG_ITMP1, REG_SP, s2 * 4);
3845 if (IS_2_WORD_TYPE(t)) {
3846 M_ILD(REG_ITMP1, REG_SP, s1 * 4 + 4);
3847 M_IST(REG_ITMP1, REG_SP, s2 * 4 + 4);
3852 /* We only copy spilled float arguments, as the float argument */
3853 /* registers keep unchanged. */
3855 if (md->params[i].inmemory) {
3856 s1 = md->params[i].regoff + stackframesize;
3857 s2 = nmd->params[j].regoff;
3859 if (IS_2_WORD_TYPE(t)) {
3860 M_DLD(REG_FTMP1, REG_SP, s1 * 4);
3861 M_DST(REG_FTMP1, REG_SP, s2 * 4);
3864 M_FLD(REG_FTMP1, REG_SP, s1 * 4);
3865 M_FST(REG_FTMP1, REG_SP, s2 * 4);
3871 /* put class into second argument register */
3873 if (m->flags & ACC_STATIC) {
3874 off = dseg_addaddress(cd, m->class);
3875 M_ALD(rd->argintregs[1], REG_PV, off);
3878 /* put env into first argument register */
3880 off = dseg_addaddress(cd, &env);
3881 M_ALD(rd->argintregs[0], REG_PV, off);
3883 /* generate the actual native call */
3885 #if !defined(STATIC_CLASSPATH)
3887 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m);
3889 if (showdisassemble)
3894 off = dseg_addaddress(cd, f);
3895 M_ALD(REG_PV, REG_PV, off);
3898 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3900 M_LDA(REG_PV, REG_ITMP1, -disp); /* recompute pv from ra */
3902 /* 16 instructions */
3905 #if defined(__DARWIN__)
3906 M_LDA(REG_SP, REG_SP, -(LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4));
3907 M_IST(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
3908 M_IST(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
3909 M_DST(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
3911 M_LDA(REG_SP, REG_SP, -(LA_SIZE + (2 + 2) * 4));
3912 M_IST(REG_RESULT, REG_SP, LA_SIZE + 0 * 4);
3913 M_IST(REG_RESULT2, REG_SP, LA_SIZE + 1 * 4);
3914 M_DST(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4);
3917 /* keep this order */
3918 switch (m->returntype) {
3921 #if defined(__DARWIN__)
3922 M_MOV(REG_RESULT, rd->argintregs[2]);
3923 M_CLR(rd->argintregs[1]);
3925 M_MOV(REG_RESULT, rd->argintregs[3]);
3926 M_CLR(rd->argintregs[2]);
3931 #if defined(__DARWIN__)
3932 M_MOV(REG_RESULT2, rd->argintregs[2]);
3933 M_MOV(REG_RESULT, rd->argintregs[1]);
3935 M_MOV(REG_RESULT2, rd->argintregs[3]);
3936 M_MOV(REG_RESULT, rd->argintregs[2]);
3941 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3942 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3943 off = dseg_addaddress(cd, m);
3944 M_ALD(rd->argintregs[0], REG_PV, off);
3946 off = dseg_addaddress(cd, builtin_displaymethodstop);
3947 M_ALD(REG_ITMP2, REG_PV, off);
3951 #if defined(__DARWIN__)
3952 M_ILD(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
3953 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
3954 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
3955 M_LDA(REG_SP, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4);
3957 M_ILD(REG_RESULT, REG_SP, LA_SIZE + 0 * 4);
3958 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 1 * 4);
3959 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4);
3960 M_LDA(REG_SP, REG_SP, LA_SIZE + (2 + 2) * 4);
3964 /* check for exception */
3966 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3967 switch (md->returntype.type) {
3969 M_IST(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
3973 M_IST(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
3976 M_FST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
3979 M_DST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
3983 off = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3984 M_ALD(REG_ITMP2, REG_PV, off);
3987 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3989 M_LDA(REG_PV, REG_ITMP1, -disp);
3990 M_MOV(REG_RESULT, REG_ITMP2);
3992 switch (md->returntype.type) {
3994 M_ILD(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
3998 M_ILD(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
4001 M_FLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4004 M_DLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
4008 off = dseg_addaddress(cd, &_exceptionptr)
4009 M_ALD(REG_ITMP2, REG_PV, off);
4011 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1 */
4012 M_TST(REG_ITMP1_XPTR);
4013 M_BNE(4); /* if no exception then return */
4015 M_ALD(REG_ITMP1, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
4017 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
4021 /* handle exception */
4024 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
4026 M_ALD(REG_ITMP2, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
4029 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
4031 M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC); /* fault address */
4033 off = dseg_addaddress(cd, asm_handle_nat_exception);
4034 M_ALD(REG_ITMP3, REG_PV, off);
4038 /* generate patcher stub call code */
4046 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
4047 /* Get machine code which is patched back in later. The call is */
4048 /* 1 instruction word long. */
4050 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
4051 mcode = (u4) *xcodeptr;
4053 /* patch in the call to call the following code (done at compile */
4056 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
4057 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
4059 M_BL(tmpmcodeptr - (xcodeptr + 1));
4061 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
4063 /* create stack frame - keep stack 16-byte aligned */
4065 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
4067 /* move return address onto stack */
4070 M_AST(REG_ITMP3, REG_SP, 4 * 4);
4072 /* move pointer to java_objectheader onto stack */
4074 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
4075 /* order reversed because of data segment layout */
4077 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
4078 off = dseg_addaddress(cd, NULL); /* vftbl */
4080 M_LDA(REG_ITMP3, REG_PV, off);
4081 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4084 M_AST(REG_ITMP3, REG_SP, 3 * 4);
4087 /* move machine code onto stack */
4089 off = dseg_adds4(cd, mcode);
4090 M_ILD(REG_ITMP3, REG_PV, off);
4091 M_IST(REG_ITMP3, REG_SP, 2 * 4);
4093 /* move class/method/field reference onto stack */
4095 off = dseg_addaddress(cd, pref->ref);
4096 M_ALD(REG_ITMP3, REG_PV, off);
4097 M_AST(REG_ITMP3, REG_SP, 1 * 4);
4099 /* move patcher function pointer onto stack */
4101 off = dseg_addaddress(cd, pref->patcher);
4102 M_ALD(REG_ITMP3, REG_PV, off);
4103 M_AST(REG_ITMP3, REG_SP, 0 * 4);
4105 off = dseg_addaddress(cd, asm_wrapper_patcher);
4106 M_ALD(REG_ITMP3, REG_PV, off);
4112 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
4114 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
4116 return m->entrypoint;
4121 * These are local overrides for various environment variables in Emacs.
4122 * Please do not remove this and leave it at the end of the file, where
4123 * Emacs will automagically detect them.
4124 * ---------------------------------------------------------------------
4127 * indent-tabs-mode: t