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 2925 2005-07-07 09:41:59Z twisti $
47 #include "vm/jit/powerpc/arch.h"
48 #include "vm/jit/powerpc/codegen.h"
49 #include "vm/jit/powerpc/types.h"
51 #include "cacao/cacao.h"
52 #include "native/native.h"
53 #include "vm/builtin.h"
54 #include "vm/global.h"
55 #include "vm/loader.h"
56 #include "vm/stringlocal.h"
57 #include "vm/tables.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/codegen.inc"
60 #include "vm/jit/jit.h"
63 # include "vm/jit/lsra.inc"
66 #include "vm/jit/parse.h"
67 #include "vm/jit/patcher.h"
68 #include "vm/jit/reg.h"
69 #include "vm/jit/reg.inc"
73 void asm_cacheflush(void *, long);
75 /* #include <architecture/ppc/cframe.h> */
77 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
78 void thread_restartcriticalsection(void *u)
80 /* XXX set pc to restart address */
84 s4 *codegen_trace_args( methodinfo *m, codegendata *cd, registerdata *rd,
85 s4 *mcodeptr, s4 parentargs_base, bool nativestub);
87 /* codegen *********************************************************************
89 Generates machine code.
91 *******************************************************************************/
93 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
95 s4 len, s1, s2, s3, d, off;
104 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
105 builtintable_entry *bte;
114 /* space to save used callee saved registers */
116 savedregs_num += (INT_SAV_CNT - rd->savintreguse);
117 savedregs_num += 2 * (FLT_SAV_CNT - rd->savfltreguse);
119 parentargs_base = rd->memuse + savedregs_num;
121 #if defined(USE_THREADS)
122 /* space to save argument of monitor_enter and Return Values to survive */
123 /* monitor_exit. The stack position for the argument can not be shared */
124 /* with place to save the return register on PPC, since both values */
126 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
127 /* reserve 2 slots for long/double return values for monitorexit */
129 if (IS_2_WORD_TYPE(m->parseddesc->returntype.type))
130 parentargs_base += 3;
132 parentargs_base += 2;
137 /* create method header */
139 parentargs_base = (parentargs_base + 3) & ~3;
141 #if SIZEOF_VOID_P == 4
142 (void) dseg_addaddress(cd, m); /* Filler */
144 (void) dseg_addaddress(cd, m); /* MethodPointer */
145 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
147 #if defined(USE_THREADS)
149 /* IsSync contains the offset relative to the stack pointer for the
150 argument of monitor_exit used in the exception handler. Since the
151 offset could be zero and give a wrong meaning of the flag it is
155 if (checksync && (m->flags & ACC_SYNCHRONIZED))
156 (void) dseg_adds4(cd, (rd->memuse + 1) * 4); /* IsSync */
161 (void) dseg_adds4(cd, 0); /* IsSync */
163 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
164 (void) dseg_adds4(cd, INT_SAV_CNT - rd->savintreguse); /* IntSave */
165 (void) dseg_adds4(cd, FLT_SAV_CNT - rd->savfltreguse); /* FltSave */
166 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
168 /* create exception table */
170 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
171 dseg_addtarget(cd, ex->start);
172 dseg_addtarget(cd, ex->end);
173 dseg_addtarget(cd, ex->handler);
174 (void) dseg_addaddress(cd, ex->catchtype.cls);
177 /* initialize mcode variables */
179 mcodeptr = (s4 *) cd->mcodebase;
180 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
181 MCODECHECK(128 + m->paramcount);
183 /* create stack frame (if necessary) */
185 if (!m->isleafmethod) {
187 M_AST(REG_ITMP3, REG_SP, LA_LR_OFFSET);
190 if (parentargs_base) {
191 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
194 /* save return address and used callee saved registers */
197 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
198 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
200 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
201 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
204 /* take arguments out of register or stack frame */
208 for (p = 0, l = 0; p < md->paramcount; p++) {
209 t = md->paramtypes[p].type;
210 var = &(rd->locals[l][t]);
212 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
216 s1 = md->params[p].regoff;
217 if (IS_INT_LNG_TYPE(t)) { /* integer args */
218 if (IS_2_WORD_TYPE(t))
219 s2 = PACK_REGS(rd->argintregs[GET_LOW_REG(s1)],
220 rd->argintregs[GET_HIGH_REG(s1)]);
222 s2 = rd->argintregs[s1];
223 if (!md->params[p].inmemory) { /* register arguments */
224 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
225 M_TINTMOVE(t, s2, var->regoff);
227 } else { /* reg arg -> spilled */
228 if (IS_2_WORD_TYPE(t)) {
229 M_IST(GET_HIGH_REG(s2), REG_SP, var->regoff * 4);
230 M_IST(GET_LOW_REG(s2), REG_SP, 4 * var->regoff + 4);
232 M_IST(s2, REG_SP, var->regoff * 4);
236 } else { /* stack arguments */
237 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
238 if (IS_2_WORD_TYPE(t)) {
239 M_ILD(GET_HIGH_REG(var->regoff), REG_SP,
240 (parentargs_base + s1) * 4);
241 M_ILD(GET_LOW_REG(var->regoff), REG_SP,
242 (parentargs_base + s1) * 4 + 4);
244 M_ILD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
247 } else { /* stack arg -> spilled */
249 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4);
250 M_IST(REG_ITMP1, REG_SP, var->regoff * 4);
251 if (IS_2_WORD_TYPE(t)) {
252 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4 +4);
253 M_IST(REG_ITMP1, REG_SP, var->regoff * 4 + 4);
256 /* Reuse Memory Position on Caller Stack */
257 var->regoff = parentargs_base + s1;
262 } else { /* floating args */
263 if (!md->params[p].inmemory) { /* register arguments */
264 s2 = rd->argfltregs[s1];
265 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
266 M_FLTMOVE(s2, var->regoff);
268 } else { /* reg arg -> spilled */
269 if (IS_2_WORD_TYPE(t))
270 M_DST(s2, REG_SP, var->regoff * 4);
272 M_FST(s2, REG_SP, var->regoff * 4);
275 } else { /* stack arguments */
276 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
277 if (IS_2_WORD_TYPE(t))
278 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
281 M_FLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
283 } else { /* stack-arg -> spilled */
285 if (IS_2_WORD_TYPE(t)) {
286 M_DLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
287 M_DST(REG_FTMP1, REG_SP, var->regoff * 4);
288 var->regoff = parentargs_base + s1;
291 M_FLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
292 M_FST(REG_FTMP1, REG_SP, var->regoff * 4);
295 /* Reuse Memory Position on Caller Stack */
296 var->regoff = parentargs_base + s1;
303 /* save monitorenter argument */
305 #if defined(USE_THREADS)
306 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
307 /* stack offset for monitor argument */
313 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT * 4 + FLT_ARG_CNT * 8));
315 for (p = 0; p < INT_ARG_CNT; p++)
316 M_IST(rd->argintregs[p], REG_SP, p * 4);
318 for (p = 0; p < FLT_ARG_CNT * 2; p += 2)
319 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
321 s1 += INT_ARG_CNT + FLT_ARG_CNT;
325 /* decide which monitor enter function to call */
327 if (m->flags & ACC_STATIC) {
328 p = dseg_addaddress(cd, m->class);
329 M_ALD(REG_ITMP1, REG_PV, p);
330 M_AST(REG_ITMP1, REG_SP, s1 * 4);
331 M_MOV(REG_ITMP1, rd->argintregs[0]);
332 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
333 M_ALD(REG_ITMP3, REG_PV, p);
338 M_TST(rd->argintregs[0]);
340 codegen_addxnullrefs(cd, mcodeptr);
341 M_AST(rd->argintregs[0], REG_SP, s1 * 4);
342 p = dseg_addaddress(cd, BUILTIN_monitorenter);
343 M_ALD(REG_ITMP3, REG_PV, p);
350 for (p = 0; p < INT_ARG_CNT; p++)
351 M_ILD(rd->argintregs[p], REG_SP, p * 4);
353 for (p = 0; p < FLT_ARG_CNT; p++)
354 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
357 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
363 /* call trace function */
366 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, parentargs_base, false);
368 } /* if (runverbose) */
371 /* end of header generation */
373 /* walk through all basic blocks */
374 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
376 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
378 if (bptr->flags >= BBREACHED) {
380 /* branch resolving */
384 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
385 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
391 /* copy interface registers to their destination */
399 while (src != NULL) {
401 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
402 /* d = reg_of_var(m, src, REG_ITMP1); */
403 if (!(src->flags & INMEMORY))
407 M_INTMOVE(REG_ITMP1, d);
408 store_reg_to_var_int(src, d);
414 while (src != NULL) {
416 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
417 d = reg_of_var(rd, src, REG_ITMP1);
418 M_INTMOVE(REG_ITMP1, d);
419 store_reg_to_var_int(src, d);
421 if (src->type == TYPE_LNG)
422 d = reg_of_var(rd, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
424 d = reg_of_var(rd, src, REG_IFTMP);
425 if ((src->varkind != STACKVAR)) {
427 if (IS_FLT_DBL_TYPE(s2)) {
428 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
429 s1 = rd->interfaces[len][s2].regoff;
432 if (IS_2_WORD_TYPE(s2)) {
434 4 * rd->interfaces[len][s2].regoff);
437 4 * rd->interfaces[len][s2].regoff);
440 store_reg_to_var_flt(src, d);
442 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
443 s1 = rd->interfaces[len][s2].regoff;
446 if (IS_2_WORD_TYPE(s2)) {
447 M_ILD(GET_HIGH_REG(d), REG_SP,
448 4 * rd->interfaces[len][s2].regoff);
449 M_ILD(GET_LOW_REG(d), REG_SP,
450 4 * rd->interfaces[len][s2].regoff + 4);
453 4 * rd->interfaces[len][s2].regoff);
456 store_reg_to_var_int(src, d);
466 /* walk through all instructions */
470 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
472 MCODECHECK(64); /* an instruction usually needs < 64 words */
475 case ICMD_NOP: /* ... ==> ... */
476 case ICMD_INLINE_START:
477 case ICMD_INLINE_END:
480 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
482 var_to_reg_int(s1, src, REG_ITMP1);
485 codegen_addxnullrefs(cd, mcodeptr);
488 /* constant operations ************************************************/
490 case ICMD_ICONST: /* ... ==> ..., constant */
491 /* op1 = 0, val.i = constant */
493 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
494 ICONST(d, iptr->val.i);
495 store_reg_to_var_int(iptr->dst, d);
498 case ICMD_LCONST: /* ... ==> ..., constant */
499 /* op1 = 0, val.l = constant */
501 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
502 LCONST(d, iptr->val.l);
503 store_reg_to_var_int(iptr->dst, d);
506 case ICMD_FCONST: /* ... ==> ..., constant */
507 /* op1 = 0, val.f = constant */
509 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
510 a = dseg_addfloat(cd, iptr->val.f);
512 store_reg_to_var_flt(iptr->dst, d);
515 case ICMD_DCONST: /* ... ==> ..., constant */
516 /* op1 = 0, val.d = constant */
518 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
519 a = dseg_adddouble(cd, iptr->val.d);
521 store_reg_to_var_flt(iptr->dst, d);
524 case ICMD_ACONST: /* ... ==> ..., constant */
525 /* op1 = 0, val.a = constant */
527 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
528 ICONST(d, (u4) iptr->val.a);
529 store_reg_to_var_int(iptr->dst, d);
533 /* load/store operations **********************************************/
535 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
536 case ICMD_LLOAD: /* op1 = local variable */
539 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
540 if (IS_2_WORD_TYPE(var->type)) /* TYPE_LNG */
541 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
543 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
544 if ((iptr->dst->varkind == LOCALVAR) &&
545 (iptr->dst->varnum == iptr->op1))
548 if (var->flags & INMEMORY) {
549 if (IS_2_WORD_TYPE(var->type)) {
550 M_ILD(GET_HIGH_REG(d), REG_SP, 4 * var->regoff);
551 M_ILD(GET_LOW_REG(d), REG_SP, 4 * var->regoff + 4);
553 M_ILD(d, REG_SP, 4 * var->regoff);
556 M_TINTMOVE(var->type, var->regoff, d);
558 store_reg_to_var_int(iptr->dst, d);
561 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
562 case ICMD_DLOAD: /* op1 = local variable */
564 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
565 if ((iptr->dst->varkind == LOCALVAR) &&
566 (iptr->dst->varnum == iptr->op1))
568 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
569 if (var->flags & INMEMORY)
570 if (IS_2_WORD_TYPE(var->type))
571 M_DLD(d, REG_SP, 4 * var->regoff);
573 M_FLD(d, REG_SP, 4 * var->regoff);
575 M_FLTMOVE(var->regoff, d);
577 store_reg_to_var_flt(iptr->dst, d);
581 case ICMD_ISTORE: /* ..., value ==> ... */
582 case ICMD_LSTORE: /* op1 = local variable */
585 if ((src->varkind == LOCALVAR) &&
586 (src->varnum == iptr->op1))
588 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
589 if (var->flags & INMEMORY) {
590 if (IS_2_WORD_TYPE(var->type)) {
591 var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
592 M_IST(GET_HIGH_REG(s1), REG_SP, 4 * var->regoff);
593 M_IST(GET_LOW_REG(s1), REG_SP, 4 * var->regoff + 4);
595 var_to_reg_int(s1, src, REG_ITMP1);
596 M_IST(s1, REG_SP, 4 * var->regoff);
600 var_to_reg_int(s1, src, var->regoff);
601 M_TINTMOVE(var->type, s1, var->regoff);
605 case ICMD_FSTORE: /* ..., value ==> ... */
606 case ICMD_DSTORE: /* op1 = local variable */
608 if ((src->varkind == LOCALVAR) &&
609 (src->varnum == iptr->op1))
611 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
612 if (var->flags & INMEMORY) {
613 var_to_reg_flt(s1, src, REG_FTMP1);
614 if (var->type == TYPE_DBL)
615 M_DST(s1, REG_SP, 4 * var->regoff);
617 M_FST(s1, REG_SP, 4 * var->regoff);
619 var_to_reg_flt(s1, src, var->regoff);
620 M_FLTMOVE(s1, var->regoff);
625 /* pop/dup/swap operations ********************************************/
627 /* attention: double and longs are only one entry in CACAO ICMDs */
629 case ICMD_POP: /* ..., value ==> ... */
630 case ICMD_POP2: /* ..., value, value ==> ... */
633 case ICMD_DUP: /* ..., a ==> ..., a, a */
634 M_COPY(src, iptr->dst);
637 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
639 M_COPY(src, iptr->dst);
640 M_COPY(src->prev, iptr->dst->prev);
641 M_COPY(iptr->dst, iptr->dst->prev->prev);
644 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
646 M_COPY(src, iptr->dst);
647 M_COPY(src->prev, iptr->dst->prev);
648 M_COPY(src->prev->prev, iptr->dst->prev->prev);
649 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
652 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
654 M_COPY(src, iptr->dst);
655 M_COPY(src->prev, iptr->dst->prev);
658 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
660 M_COPY(src, iptr->dst);
661 M_COPY(src->prev, iptr->dst->prev);
662 M_COPY(src->prev->prev, iptr->dst->prev->prev);
663 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
664 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
667 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
669 M_COPY(src, iptr->dst);
670 M_COPY(src->prev, iptr->dst->prev);
671 M_COPY(src->prev->prev, iptr->dst->prev->prev);
672 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
673 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
674 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
677 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
679 M_COPY(src, iptr->dst->prev);
680 M_COPY(src->prev, iptr->dst);
684 /* integer operations *************************************************/
686 case ICMD_INEG: /* ..., value ==> ..., - value */
688 var_to_reg_int(s1, src, REG_ITMP1);
689 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
691 store_reg_to_var_int(iptr->dst, d);
694 case ICMD_LNEG: /* ..., value ==> ..., - value */
696 var_to_reg_int(s1, src, PACK_REGS(REG_ITMP2, REG_ITMP1));
697 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
698 M_SUBFIC(GET_LOW_REG(s1), 0, GET_LOW_REG(d));
699 M_SUBFZE(GET_HIGH_REG(s1), GET_HIGH_REG(d));
700 store_reg_to_var_int(iptr->dst, d);
703 case ICMD_I2L: /* ..., value ==> ..., value */
705 var_to_reg_int(s1, src, REG_ITMP2);
706 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
707 M_INTMOVE(s1, GET_LOW_REG(d));
708 M_SRA_IMM(GET_LOW_REG(d), 31, GET_HIGH_REG(d));
709 store_reg_to_var_int(iptr->dst, d);
712 case ICMD_L2I: /* ..., value ==> ..., value */
714 var_to_reg_int_low(s1, src, REG_ITMP2);
715 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
717 store_reg_to_var_int(iptr->dst, d);
720 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
722 var_to_reg_int(s1, src, REG_ITMP1);
723 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
725 store_reg_to_var_int(iptr->dst, d);
728 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
730 var_to_reg_int(s1, src, REG_ITMP1);
731 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
733 store_reg_to_var_int(iptr->dst, d);
736 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
738 var_to_reg_int(s1, src, REG_ITMP1);
739 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
741 store_reg_to_var_int(iptr->dst, d);
745 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
747 var_to_reg_int(s1, src->prev, REG_ITMP1);
748 var_to_reg_int(s2, src, REG_ITMP2);
749 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
751 store_reg_to_var_int(iptr->dst, d);
754 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
755 /* val.i = constant */
757 var_to_reg_int(s1, src, REG_ITMP1);
758 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
759 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
760 M_IADD_IMM(s1, iptr->val.i, d);
762 ICONST(REG_ITMP2, iptr->val.i);
763 M_IADD(s1, REG_ITMP2, d);
765 store_reg_to_var_int(iptr->dst, d);
768 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
770 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
771 var_to_reg_int_low(s2, src, REG_ITMP2);
772 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
773 M_ADDC(s1, s2, GET_LOW_REG(d));
774 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
775 var_to_reg_int_high(s2, src, REG_ITMP3);
776 M_ADDE(s1, s2, GET_HIGH_REG(d));
777 store_reg_to_var_int(iptr->dst, d);
780 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
781 /* val.l = constant */
783 s3 = iptr->val.l & 0xffffffff;
784 var_to_reg_int_low(s1, src, REG_ITMP1);
785 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
786 if ((s3 >= -32768) && (s3 <= 32767)) {
787 M_ADDIC(s1, s3, GET_LOW_REG(d));
790 ICONST(REG_ITMP2, s3);
791 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
794 var_to_reg_int_high(s1, src, REG_ITMP1);
795 s3 = iptr->val.l >> 32;
797 M_ADDME(s1, GET_HIGH_REG(d));
799 M_ADDZE(s1, GET_HIGH_REG(d));
801 ICONST(REG_ITMP3, s3);
802 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
804 store_reg_to_var_int(iptr->dst, d);
807 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
809 var_to_reg_int(s1, src->prev, REG_ITMP1);
810 var_to_reg_int(s2, src, REG_ITMP2);
811 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
813 store_reg_to_var_int(iptr->dst, d);
816 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
817 /* val.i = constant */
819 var_to_reg_int(s1, src, REG_ITMP1);
820 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
821 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
822 M_IADD_IMM(s1, -iptr->val.i, d);
824 ICONST(REG_ITMP2, -iptr->val.i);
825 M_IADD(s1, REG_ITMP2, d);
827 store_reg_to_var_int(iptr->dst, d);
830 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
832 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
833 var_to_reg_int_low(s2, src, REG_ITMP2);
834 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
835 M_SUBC(s1, s2, GET_LOW_REG(d));
836 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
837 var_to_reg_int_high(s2, src, REG_ITMP3);
838 M_SUBE(s1, s2, GET_HIGH_REG(d));
839 store_reg_to_var_int(iptr->dst, d);
842 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
843 /* val.l = constant */
845 s3 = (-iptr->val.l) & 0xffffffff;
846 var_to_reg_int_low(s1, src, REG_ITMP1);
847 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
848 if ((s3 >= -32768) && (s3 <= 32767)) {
849 M_ADDIC(s1, s3, GET_LOW_REG(d));
851 ICONST(REG_ITMP2, s3);
852 M_ADDC(s1, REG_ITMP2, GET_LOW_REG(d));
854 var_to_reg_int_high(s1, src, REG_ITMP1);
855 s3 = (-iptr->val.l) >> 32;
857 M_ADDME(s1, GET_HIGH_REG(d));
859 M_ADDZE(s1, GET_HIGH_REG(d));
861 ICONST(REG_ITMP3, s3);
862 M_ADDE(s1, REG_ITMP3, GET_HIGH_REG(d));
864 store_reg_to_var_int(iptr->dst, d);
867 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
869 var_to_reg_int(s1, src->prev, REG_ITMP1);
870 var_to_reg_int(s2, src, REG_ITMP2);
871 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
873 store_reg_to_var_int(iptr->dst, d);
876 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
878 var_to_reg_int(s1, src->prev, REG_ITMP1);
879 var_to_reg_int(s2, src, REG_ITMP2);
880 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
884 store_reg_to_var_int(iptr->dst, d);
887 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
889 var_to_reg_int(s1, src->prev, REG_ITMP1);
890 var_to_reg_int(s2, src, REG_ITMP2);
891 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
893 store_reg_to_var_int(iptr->dst, d);
896 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
897 /* val.i = constant */
899 var_to_reg_int(s1, src, REG_ITMP1);
900 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
901 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
902 M_IMUL_IMM(s1, iptr->val.i, d);
905 ICONST(REG_ITMP2, iptr->val.i);
906 M_IMUL(s1, REG_ITMP2, d);
908 store_reg_to_var_int(iptr->dst, d);
911 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
913 var_to_reg_int(s1, src, REG_ITMP1);
914 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
915 M_SRA_IMM(s1, iptr->val.i, d);
917 store_reg_to_var_int(iptr->dst, d);
920 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
922 var_to_reg_int(s1, src->prev, REG_ITMP1);
923 var_to_reg_int(s2, src, REG_ITMP2);
924 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
925 M_AND_IMM(s2, 0x1f, REG_ITMP3);
926 M_SLL(s1, REG_ITMP3, d);
927 store_reg_to_var_int(iptr->dst, d);
930 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
931 /* val.i = constant */
933 var_to_reg_int(s1, src, REG_ITMP1);
934 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
935 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
936 store_reg_to_var_int(iptr->dst, d);
939 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
941 var_to_reg_int(s1, src->prev, REG_ITMP1);
942 var_to_reg_int(s2, src, REG_ITMP2);
943 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
944 M_AND_IMM(s2, 0x1f, REG_ITMP3);
945 M_SRA(s1, REG_ITMP3, d);
946 store_reg_to_var_int(iptr->dst, d);
949 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
950 /* val.i = constant */
952 var_to_reg_int(s1, src, REG_ITMP1);
953 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
954 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
955 store_reg_to_var_int(iptr->dst, d);
958 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
960 var_to_reg_int(s1, src->prev, REG_ITMP1);
961 var_to_reg_int(s2, src, REG_ITMP2);
962 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
963 M_AND_IMM(s2, 0x1f, REG_ITMP2);
964 M_SRL(s1, REG_ITMP2, d);
965 store_reg_to_var_int(iptr->dst, d);
968 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
969 /* val.i = constant */
971 var_to_reg_int(s1, src, REG_ITMP1);
972 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
973 if (iptr->val.i & 0x1f)
974 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
977 store_reg_to_var_int(iptr->dst, d);
980 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
982 var_to_reg_int(s1, src->prev, REG_ITMP1);
983 var_to_reg_int(s2, src, REG_ITMP2);
984 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
986 store_reg_to_var_int(iptr->dst, d);
989 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
990 /* val.i = constant */
992 var_to_reg_int(s1, src, REG_ITMP1);
993 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
994 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
995 M_AND_IMM(s1, iptr->val.i, d);
998 else if (iptr->val.i == 0xffffff) {
999 M_RLWINM(s1, 0, 8, 31, d);
1003 ICONST(REG_ITMP2, iptr->val.i);
1004 M_AND(s1, REG_ITMP2, d);
1006 store_reg_to_var_int(iptr->dst, d);
1009 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1011 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1012 var_to_reg_int_low(s2, src, REG_ITMP2);
1013 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1014 M_AND(s1, s2, GET_LOW_REG(d));
1015 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1016 var_to_reg_int_high(s2, src, REG_ITMP3);
1017 M_AND(s1, s2, GET_HIGH_REG(d));
1018 store_reg_to_var_int(iptr->dst, d);
1021 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1022 /* val.l = constant */
1024 s3 = iptr->val.l & 0xffffffff;
1025 var_to_reg_int_low(s1, src, REG_ITMP1);
1026 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1027 if ((s3 >= 0) && (s3 <= 65535)) {
1028 M_AND_IMM(s1, s3, GET_LOW_REG(d));
1030 ICONST(REG_ITMP2, s3);
1031 M_AND(s1, REG_ITMP2, GET_LOW_REG(d));
1033 var_to_reg_int_high(s1, src, REG_ITMP1);
1034 s3 = iptr->val.l >> 32;
1035 if ((s3 >= 0) && (s3 <= 65535)) {
1036 M_AND_IMM(s1, s3, GET_HIGH_REG(d));
1039 ICONST(REG_ITMP3, s3);
1040 M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
1042 store_reg_to_var_int(iptr->dst, d);
1045 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1046 /* val.i = constant */
1048 var_to_reg_int(s1, src, REG_ITMP1);
1049 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1050 M_MOV(s1, REG_ITMP2);
1052 M_BGE(1 + 2*(iptr->val.i >= 32768));
1053 if (iptr->val.i >= 32768) {
1054 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1055 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1056 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1058 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1060 int b=0, m = iptr->val.i;
1063 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1065 M_ISUB(s1, REG_ITMP2, d);
1066 store_reg_to_var_int(iptr->dst, d);
1069 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1071 var_to_reg_int(s1, src->prev, REG_ITMP1);
1072 var_to_reg_int(s2, src, REG_ITMP2);
1073 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1075 store_reg_to_var_int(iptr->dst, d);
1078 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1079 /* val.i = constant */
1081 var_to_reg_int(s1, src, REG_ITMP1);
1082 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1083 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1084 M_OR_IMM(s1, iptr->val.i, d);
1087 ICONST(REG_ITMP2, iptr->val.i);
1088 M_OR(s1, REG_ITMP2, d);
1090 store_reg_to_var_int(iptr->dst, d);
1093 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1095 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1096 var_to_reg_int_low(s2, src, REG_ITMP2);
1097 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1098 M_OR(s1, s2, GET_LOW_REG(d));
1099 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1100 var_to_reg_int_high(s2, src, REG_ITMP3);
1101 M_OR(s1, s2, GET_HIGH_REG(d));
1102 store_reg_to_var_int(iptr->dst, d);
1105 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1106 /* val.l = constant */
1108 s3 = iptr->val.l & 0xffffffff;
1109 var_to_reg_int_low(s1, src, REG_ITMP1);
1110 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1111 if ((s3 >= 0) && (s3 <= 65535)) {
1112 M_OR_IMM(s1, s3, GET_LOW_REG(d));
1114 ICONST(REG_ITMP2, s3);
1115 M_OR(s1, REG_ITMP2, GET_LOW_REG(d));
1117 var_to_reg_int_high(s1, src, REG_ITMP1);
1118 s3 = iptr->val.l >> 32;
1119 if ((s3 >= 0) && (s3 <= 65535)) {
1120 M_OR_IMM(s1, s3, GET_HIGH_REG(d));
1122 ICONST(REG_ITMP3, s3);
1123 M_OR(s1, REG_ITMP3, GET_HIGH_REG(d));
1125 store_reg_to_var_int(iptr->dst, d);
1128 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1130 var_to_reg_int(s1, src->prev, REG_ITMP1);
1131 var_to_reg_int(s2, src, REG_ITMP2);
1132 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1134 store_reg_to_var_int(iptr->dst, d);
1137 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1138 /* val.i = constant */
1140 var_to_reg_int(s1, src, REG_ITMP1);
1141 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1142 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1143 M_XOR_IMM(s1, iptr->val.i, d);
1146 ICONST(REG_ITMP2, iptr->val.i);
1147 M_XOR(s1, REG_ITMP2, d);
1149 store_reg_to_var_int(iptr->dst, d);
1152 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1154 var_to_reg_int_low(s1, src->prev, REG_ITMP1);
1155 var_to_reg_int_low(s2, src, REG_ITMP2);
1156 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1157 M_XOR(s1, s2, GET_LOW_REG(d));
1158 var_to_reg_int_high(s1, src->prev, REG_ITMP1);
1159 var_to_reg_int_high(s2, src, REG_ITMP3);
1160 M_XOR(s1, s2, GET_HIGH_REG(d));
1161 store_reg_to_var_int(iptr->dst, d);
1164 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1165 /* val.l = constant */
1167 s3 = iptr->val.l & 0xffffffff;
1168 var_to_reg_int_low(s1, src, REG_ITMP1);
1169 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1170 if ((s3 >= 0) && (s3 <= 65535)) {
1171 M_XOR_IMM(s1, s3, GET_LOW_REG(d));
1173 ICONST(REG_ITMP2, s3);
1174 M_XOR(s1, REG_ITMP2, GET_LOW_REG(d));
1176 var_to_reg_int_high(s1, src, REG_ITMP1);
1177 s3 = iptr->val.l >> 32;
1178 if ((s3 >= 0) && (s3 <= 65535)) {
1179 M_XOR_IMM(s1, s3, GET_HIGH_REG(d));
1181 ICONST(REG_ITMP3, s3);
1182 M_XOR(s1, REG_ITMP3, GET_HIGH_REG(d));
1184 store_reg_to_var_int(iptr->dst, d);
1187 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1188 /*******************************************************************
1189 TODO: CHANGE THIS TO A VERSION THAT WORKS !!!
1190 *******************************************************************/
1191 var_to_reg_int_high(s1, src->prev, REG_ITMP3);
1192 var_to_reg_int_high(s2, src, REG_ITMP2);
1193 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1195 int tempreg = false;
1199 if (src->prev->flags & INMEMORY) {
1200 tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1202 tempreg = tempreg || (d == GET_HIGH_REG(src->prev->regoff))
1203 || (d == GET_LOW_REG(src->prev->regoff));
1205 if (src->flags & INMEMORY) {
1206 tempreg = tempreg || (d == REG_ITMP3) || (d == REG_ITMP2);
1208 tempreg = tempreg || (d == GET_HIGH_REG(src->regoff))
1209 || (d == GET_LOW_REG(src->regoff));
1212 dreg = tempreg ? REG_ITMP1 : d;
1213 M_IADD_IMM(REG_ZERO, 1, dreg);
1218 var_to_reg_int_low(s1, src->prev, REG_ITMP3);
1219 var_to_reg_int_low(s2, src, REG_ITMP2);
1223 M_IADD_IMM(dreg, -1, dreg);
1224 M_IADD_IMM(dreg, -1, dreg);
1225 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1226 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1229 store_reg_to_var_int(iptr->dst, d);
1232 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1233 /* op1 = variable, val.i = constant */
1235 var = &(rd->locals[iptr->op1][TYPE_INT]);
1236 if (var->flags & INMEMORY) {
1238 M_ILD(s1, REG_SP, var->regoff * 4);
1246 M_ADDIS(s1, m>>16, s1);
1248 M_IADD_IMM(s1, m&0xffff, s1);
1250 if (var->flags & INMEMORY)
1251 M_IST(s1, REG_SP, var->regoff * 4);
1255 /* floating operations ************************************************/
1257 case ICMD_FNEG: /* ..., value ==> ..., - value */
1259 var_to_reg_flt(s1, src, REG_FTMP1);
1260 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1262 store_reg_to_var_flt(iptr->dst, d);
1265 case ICMD_DNEG: /* ..., value ==> ..., - value */
1267 var_to_reg_flt(s1, src, REG_FTMP1);
1268 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1270 store_reg_to_var_flt(iptr->dst, d);
1273 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1275 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1276 var_to_reg_flt(s2, src, REG_FTMP2);
1277 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1279 store_reg_to_var_flt(iptr->dst, d);
1282 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1284 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1285 var_to_reg_flt(s2, src, REG_FTMP2);
1286 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1288 store_reg_to_var_flt(iptr->dst, d);
1291 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1293 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1294 var_to_reg_flt(s2, src, REG_FTMP2);
1295 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1297 store_reg_to_var_flt(iptr->dst, d);
1300 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1302 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1303 var_to_reg_flt(s2, src, REG_FTMP2);
1304 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1306 store_reg_to_var_flt(iptr->dst, d);
1309 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1311 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1312 var_to_reg_flt(s2, src, REG_FTMP2);
1313 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1315 store_reg_to_var_flt(iptr->dst, d);
1318 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1320 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1321 var_to_reg_flt(s2, src, REG_FTMP2);
1322 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1324 store_reg_to_var_flt(iptr->dst, d);
1327 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1329 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1330 var_to_reg_flt(s2, src, REG_FTMP2);
1331 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1333 store_reg_to_var_flt(iptr->dst, d);
1336 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1338 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1339 var_to_reg_flt(s2, src, REG_FTMP2);
1340 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1342 store_reg_to_var_flt(iptr->dst, d);
1345 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1347 var_to_reg_flt(s1, src, REG_FTMP1);
1348 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1350 a = dseg_addfloat(cd, 0.0);
1351 M_FLD(REG_FTMP2, REG_PV, a);
1352 M_FCMPU(s1, REG_FTMP2);
1354 a = dseg_adds4(cd, 0);
1355 M_CVTDL_C(s1, REG_FTMP1);
1356 M_LDA (REG_ITMP1, REG_PV, a);
1357 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1358 M_ILD (d, REG_PV, a);
1359 store_reg_to_var_int(iptr->dst, d);
1362 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1364 var_to_reg_flt(s1, src, REG_FTMP1);
1365 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1367 store_reg_to_var_flt(iptr->dst, d);
1370 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1372 var_to_reg_flt(s1, src, REG_FTMP1);
1373 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1375 store_reg_to_var_flt(iptr->dst, d);
1378 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1380 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1381 var_to_reg_flt(s2, src, REG_FTMP2);
1382 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1384 M_IADD_IMM(0, -1, d);
1387 M_IADD_IMM(0, 0, d);
1389 M_IADD_IMM(0, 1, d);
1390 store_reg_to_var_int(iptr->dst, d);
1393 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1395 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1396 var_to_reg_flt(s2, src, REG_FTMP2);
1397 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1399 M_IADD_IMM(0, 1, d);
1402 M_IADD_IMM(0, 0, d);
1404 M_IADD_IMM(0, -1, d);
1405 store_reg_to_var_int(iptr->dst, d);
1409 /* memory operations **************************************************/
1411 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1413 var_to_reg_int(s1, src, REG_ITMP1);
1414 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1415 gen_nullptr_check(s1);
1416 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1417 store_reg_to_var_int(iptr->dst, d);
1420 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1422 var_to_reg_int(s1, src->prev, REG_ITMP1);
1423 var_to_reg_int(s2, src, REG_ITMP2);
1424 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1425 if (iptr->op1 == 0) {
1426 gen_nullptr_check(s1);
1429 M_SLL_IMM(s2, 2, REG_ITMP2);
1430 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1431 M_LWZX(d, s1, REG_ITMP2);
1432 store_reg_to_var_int(iptr->dst, d);
1435 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1437 var_to_reg_int(s1, src->prev, REG_ITMP1);
1438 var_to_reg_int(s2, src, REG_ITMP2);
1439 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1440 if (iptr->op1 == 0) {
1441 gen_nullptr_check(s1);
1444 M_SLL_IMM(s2, 3, REG_ITMP2);
1445 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1446 M_ILD(GET_HIGH_REG(d), REG_ITMP2, OFFSET(java_longarray, data[0]));
1447 M_ILD(GET_LOW_REG(d), REG_ITMP2, OFFSET(java_longarray,
1449 store_reg_to_var_int(iptr->dst, d);
1452 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1454 var_to_reg_int(s1, src->prev, REG_ITMP1);
1455 var_to_reg_int(s2, src, REG_ITMP2);
1456 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1457 if (iptr->op1 == 0) {
1458 gen_nullptr_check(s1);
1461 M_SLL_IMM(s2, 2, REG_ITMP2);
1462 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1463 M_LWZX(d, s1, REG_ITMP2);
1464 store_reg_to_var_int(iptr->dst, d);
1467 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1469 var_to_reg_int(s1, src->prev, REG_ITMP1);
1470 var_to_reg_int(s2, src, REG_ITMP2);
1471 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1472 if (iptr->op1 == 0) {
1473 gen_nullptr_check(s1);
1476 M_SLL_IMM(s2, 2, REG_ITMP2);
1477 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1478 M_LFSX(d, s1, REG_ITMP2);
1479 store_reg_to_var_flt(iptr->dst, d);
1482 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1484 var_to_reg_int(s1, src->prev, REG_ITMP1);
1485 var_to_reg_int(s2, src, REG_ITMP2);
1486 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1487 if (iptr->op1 == 0) {
1488 gen_nullptr_check(s1);
1491 M_SLL_IMM(s2, 3, REG_ITMP2);
1492 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1493 M_LFDX(d, s1, REG_ITMP2);
1494 store_reg_to_var_flt(iptr->dst, d);
1497 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1499 var_to_reg_int(s1, src->prev, REG_ITMP1);
1500 var_to_reg_int(s2, src, REG_ITMP2);
1501 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1502 if (iptr->op1 == 0) {
1503 gen_nullptr_check(s1);
1506 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1507 M_LBZX(d, s1, REG_ITMP2);
1509 store_reg_to_var_int(iptr->dst, d);
1512 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1514 var_to_reg_int(s1, src->prev, REG_ITMP1);
1515 var_to_reg_int(s2, src, REG_ITMP2);
1516 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1517 if (iptr->op1 == 0) {
1518 gen_nullptr_check(s1);
1521 M_SLL_IMM(s2, 1, REG_ITMP2);
1522 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1523 M_LHAX(d, s1, REG_ITMP2);
1524 store_reg_to_var_int(iptr->dst, d);
1527 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1529 var_to_reg_int(s1, src->prev, REG_ITMP1);
1530 var_to_reg_int(s2, src, REG_ITMP2);
1531 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1532 if (iptr->op1 == 0) {
1533 gen_nullptr_check(s1);
1536 M_SLL_IMM(s2, 1, REG_ITMP2);
1537 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1538 M_LHZX(d, s1, REG_ITMP2);
1539 store_reg_to_var_int(iptr->dst, d);
1542 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1544 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1545 var_to_reg_int(s2, src->prev, REG_ITMP2);
1546 if (iptr->op1 == 0) {
1547 gen_nullptr_check(s1);
1550 var_to_reg_int_high(s3, src, REG_ITMP3);
1551 M_SLL_IMM(s2, 3, REG_ITMP2);
1552 M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
1553 M_STWX(s3, s1, REG_ITMP2);
1554 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1555 var_to_reg_int_low(s3, src, REG_ITMP3);
1556 M_STWX(s3, s1, REG_ITMP2);
1559 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1561 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1562 var_to_reg_int(s2, src->prev, REG_ITMP2);
1563 if (iptr->op1 == 0) {
1564 gen_nullptr_check(s1);
1567 var_to_reg_int(s3, src, REG_ITMP3);
1568 M_SLL_IMM(s2, 2, REG_ITMP2);
1569 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1570 M_STWX(s3, s1, REG_ITMP2);
1573 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1575 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1576 var_to_reg_int(s2, src->prev, REG_ITMP2);
1577 if (iptr->op1 == 0) {
1578 gen_nullptr_check(s1);
1581 var_to_reg_flt(s3, src, REG_FTMP3);
1582 M_SLL_IMM(s2, 2, REG_ITMP2);
1583 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1584 M_STFSX(s3, s1, REG_ITMP2);
1587 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1589 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1590 var_to_reg_int(s2, src->prev, REG_ITMP2);
1591 if (iptr->op1 == 0) {
1592 gen_nullptr_check(s1);
1595 var_to_reg_flt(s3, src, REG_FTMP3);
1596 M_SLL_IMM(s2, 3, REG_ITMP2);
1597 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1598 M_STFDX(s3, s1, REG_ITMP2);
1601 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1603 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1604 var_to_reg_int(s2, src->prev, REG_ITMP2);
1605 if (iptr->op1 == 0) {
1606 gen_nullptr_check(s1);
1609 var_to_reg_int(s3, src, REG_ITMP3);
1610 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1611 M_STBX(s3, s1, REG_ITMP2);
1614 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1616 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1617 var_to_reg_int(s2, src->prev, REG_ITMP2);
1618 if (iptr->op1 == 0) {
1619 gen_nullptr_check(s1);
1622 var_to_reg_int(s3, src, REG_ITMP3);
1623 M_SLL_IMM(s2, 1, REG_ITMP2);
1624 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1625 M_STHX(s3, s1, REG_ITMP2);
1628 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1630 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1631 var_to_reg_int(s2, src->prev, REG_ITMP2);
1632 if (iptr->op1 == 0) {
1633 gen_nullptr_check(s1);
1636 var_to_reg_int(s3, src, REG_ITMP3);
1637 M_SLL_IMM(s2, 1, REG_ITMP2);
1638 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1639 M_STHX(s3, s1, REG_ITMP2);
1643 case ICMD_GETSTATIC: /* ... ==> ..., value */
1644 /* op1 = type, val.a = field address */
1647 codegen_addpatchref(cd, mcodeptr,
1648 PATCHER_get_putstatic,
1649 (unresolved_field *) iptr->target);
1651 if (showdisassemble)
1657 fieldinfo *fi = iptr->val.a;
1659 if (!fi->class->initialized) {
1660 codegen_addpatchref(cd, mcodeptr,
1661 PATCHER_clinit, fi->class);
1663 if (showdisassemble)
1667 a = (ptrint) &(fi->value);
1670 a = dseg_addaddress(cd, a);
1671 M_ALD(REG_ITMP1, REG_PV, a);
1672 switch (iptr->op1) {
1674 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1675 M_ILD(d, REG_ITMP1, 0);
1676 store_reg_to_var_int(iptr->dst, d);
1679 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1680 M_ILD(GET_HIGH_REG(d), REG_ITMP1, 0);
1681 M_ILD(GET_LOW_REG(d), REG_ITMP1, 4);
1682 store_reg_to_var_int(iptr->dst, d);
1685 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1686 M_ALD(d, REG_ITMP1, 0);
1687 store_reg_to_var_int(iptr->dst, d);
1690 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1691 M_FLD(d, REG_ITMP1, 0);
1692 store_reg_to_var_flt(iptr->dst, d);
1695 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1696 M_DLD(d, REG_ITMP1, 0);
1697 store_reg_to_var_flt(iptr->dst, d);
1702 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1703 /* op1 = type, val.a = field address */
1707 codegen_addpatchref(cd, mcodeptr,
1708 PATCHER_get_putstatic,
1709 (unresolved_field *) iptr->target);
1711 if (showdisassemble)
1717 fieldinfo *fi = iptr->val.a;
1719 if (!fi->class->initialized) {
1720 codegen_addpatchref(cd, mcodeptr,
1721 PATCHER_clinit, fi->class);
1723 if (showdisassemble)
1727 a = (ptrint) &(fi->value);
1730 a = dseg_addaddress(cd, a);
1731 M_ALD(REG_ITMP1, REG_PV, a);
1732 switch (iptr->op1) {
1734 var_to_reg_int(s2, src, REG_ITMP2);
1735 M_IST(s2, REG_ITMP1, 0);
1738 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP2, REG_ITMP3));
1739 M_IST(GET_HIGH_REG(s2), REG_ITMP1, 0);
1740 M_IST(GET_LOW_REG(s2), REG_ITMP1, 4);
1743 var_to_reg_int(s2, src, REG_ITMP2);
1744 M_AST(s2, REG_ITMP1, 0);
1747 var_to_reg_flt(s2, src, REG_FTMP2);
1748 M_FST(s2, REG_ITMP1, 0);
1751 var_to_reg_flt(s2, src, REG_FTMP2);
1752 M_DST(s2, REG_ITMP1, 0);
1758 case ICMD_GETFIELD: /* ... ==> ..., value */
1759 /* op1 = type, val.i = field offset */
1761 var_to_reg_int(s1, src, REG_ITMP1);
1762 gen_nullptr_check(s1);
1765 codegen_addpatchref(cd, mcodeptr,
1766 PATCHER_get_putfield,
1767 (unresolved_field *) iptr->target);
1769 if (showdisassemble)
1775 a = ((fieldinfo *) (iptr->val.a))->offset;
1778 switch (iptr->op1) {
1780 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1782 store_reg_to_var_int(iptr->dst, d);
1785 d = reg_of_var(rd, iptr->dst, PACK_REGS(REG_ITMP2, REG_ITMP3));
1786 M_ILD(GET_HIGH_REG(d), s1, a);
1787 M_ILD(GET_LOW_REG(d), s1, a + 4);
1788 store_reg_to_var_int(iptr->dst, d);
1791 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1793 store_reg_to_var_int(iptr->dst, d);
1796 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1798 store_reg_to_var_flt(iptr->dst, d);
1801 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1803 store_reg_to_var_flt(iptr->dst, d);
1808 case ICMD_PUTFIELD: /* ..., value ==> ... */
1809 /* op1 = type, val.i = field offset */
1811 var_to_reg_int(s1, src->prev, REG_ITMP1);
1812 gen_nullptr_check(s1);
1814 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
1815 if (IS_2_WORD_TYPE(iptr->op1)) {
1816 var_to_reg_int(s2, src, PACK_REGS(REG_ITMP3, REG_ITMP2));
1818 var_to_reg_int(s2, src, REG_ITMP2);
1821 var_to_reg_flt(s2, src, REG_FTMP2);
1825 codegen_addpatchref(cd, mcodeptr,
1826 PATCHER_get_putfield,
1827 (unresolved_field *) iptr->target);
1829 if (showdisassemble)
1835 a = ((fieldinfo *) (iptr->val.a))->offset;
1838 switch (iptr->op1) {
1843 M_IST(GET_HIGH_REG(s2), s1, a);
1844 M_IST(GET_LOW_REG(s2), s1, a + 4);
1859 /* branch operations **************************************************/
1861 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1863 a = dseg_addaddress(cd, asm_handle_exception);
1864 M_ALD(REG_ITMP2, REG_PV, a);
1866 var_to_reg_int(s1, src, REG_ITMP1);
1867 M_INTMOVE(s1, REG_ITMP1_XPTR);
1869 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
1870 M_BL(0); /* get current PC */
1871 M_MFLR(REG_ITMP2_XPC);
1872 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
1873 M_RTS; /* jump to CTR */
1878 case ICMD_GOTO: /* ... ==> ... */
1879 /* op1 = target JavaVM pc */
1881 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1885 case ICMD_JSR: /* ... ==> ... */
1886 /* op1 = target JavaVM pc */
1888 if (m->isleafmethod) M_MFLR(REG_ITMP2);
1891 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
1892 if (m->isleafmethod) M_MTLR(REG_ITMP2);
1894 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1897 case ICMD_RET: /* ... ==> ... */
1898 /* op1 = local variable */
1900 var = &(rd->locals[iptr->op1][TYPE_ADR]);
1901 if (var->flags & INMEMORY) {
1902 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
1905 M_MTCTR(var->regoff);
1910 case ICMD_IFNULL: /* ..., value ==> ... */
1911 /* op1 = target JavaVM pc */
1913 var_to_reg_int(s1, src, REG_ITMP1);
1916 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1919 case ICMD_IFNONNULL: /* ..., value ==> ... */
1920 /* op1 = target JavaVM pc */
1922 var_to_reg_int(s1, src, REG_ITMP1);
1925 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1933 case ICMD_IFEQ: /* ..., value ==> ... */
1934 /* op1 = target JavaVM pc, val.i = constant */
1936 var_to_reg_int(s1, src, REG_ITMP1);
1937 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1938 M_CMPI(s1, iptr->val.i);
1941 ICONST(REG_ITMP2, iptr->val.i);
1942 M_CMP(s1, REG_ITMP2);
1965 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1969 case ICMD_IF_LEQ: /* ..., value ==> ... */
1970 /* op1 = target JavaVM pc, val.l = constant */
1972 var_to_reg_int_low(s1, src, REG_ITMP1);
1973 var_to_reg_int_high(s2, src, REG_ITMP2);
1974 if (iptr->val.l == 0) {
1975 M_OR(s1, s2, REG_ITMP3);
1976 M_CMPI(REG_ITMP3, 0);
1978 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
1979 M_CMPI(s2, (u4) (iptr->val.l >> 32));
1981 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
1984 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
1985 M_CMP(s2, REG_ITMP3);
1987 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
1988 M_CMP(s1, REG_ITMP3)
1991 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
1994 case ICMD_IF_LLT: /* ..., value ==> ... */
1995 /* op1 = target JavaVM pc, val.l = constant */
1996 var_to_reg_int_low(s1, src, REG_ITMP1);
1997 var_to_reg_int_high(s2, src, REG_ITMP2);
1998 /* if (iptr->val.l == 0) { */
1999 /* M_OR(s1, s2, REG_ITMP3); */
2000 /* M_CMPI(REG_ITMP3, 0); */
2003 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2004 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2006 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2008 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2011 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2012 M_CMP(s2, REG_ITMP3);
2014 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2016 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2017 M_CMP(s1, REG_ITMP3)
2020 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2023 case ICMD_IF_LLE: /* ..., value ==> ... */
2024 /* op1 = target JavaVM pc, val.l = constant */
2026 var_to_reg_int_low(s1, src, REG_ITMP1);
2027 var_to_reg_int_high(s2, src, REG_ITMP2);
2028 /* if (iptr->val.l == 0) { */
2029 /* M_OR(s1, s2, REG_ITMP3); */
2030 /* M_CMPI(REG_ITMP3, 0); */
2033 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2034 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2036 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2038 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2041 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2042 M_CMP(s2, REG_ITMP3);
2044 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2046 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2047 M_CMP(s1, REG_ITMP3)
2050 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2053 case ICMD_IF_LNE: /* ..., value ==> ... */
2054 /* op1 = target JavaVM pc, val.l = constant */
2056 var_to_reg_int_low(s1, src, REG_ITMP1);
2057 var_to_reg_int_high(s2, src, REG_ITMP2);
2058 if (iptr->val.l == 0) {
2059 M_OR(s1, s2, REG_ITMP3);
2060 M_CMPI(REG_ITMP3, 0);
2062 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2063 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2065 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2068 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2069 M_CMP(s2, REG_ITMP3);
2071 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2072 M_CMP(s1, REG_ITMP3)
2075 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2078 case ICMD_IF_LGT: /* ..., value ==> ... */
2079 /* op1 = target JavaVM pc, val.l = constant */
2081 var_to_reg_int_low(s1, src, REG_ITMP1);
2082 var_to_reg_int_high(s2, src, REG_ITMP2);
2083 /* if (iptr->val.l == 0) { */
2084 /* M_OR(s1, s2, REG_ITMP3); */
2085 /* M_CMPI(REG_ITMP3, 0); */
2088 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2089 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2091 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2093 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2096 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2097 M_CMP(s2, REG_ITMP3);
2099 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2101 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2102 M_CMP(s1, REG_ITMP3)
2105 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2108 case ICMD_IF_LGE: /* ..., value ==> ... */
2109 /* op1 = target JavaVM pc, val.l = constant */
2110 var_to_reg_int_low(s1, src, REG_ITMP1);
2111 var_to_reg_int_high(s2, src, REG_ITMP2);
2112 /* if (iptr->val.l == 0) { */
2113 /* M_OR(s1, s2, REG_ITMP3); */
2114 /* M_CMPI(REG_ITMP3, 0); */
2117 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2118 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2120 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2122 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2125 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2126 M_CMP(s2, REG_ITMP3);
2128 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2130 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2131 M_CMP(s1, REG_ITMP3)
2134 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2138 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2139 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2140 /******************************************************************
2141 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2142 *******************************************************************/
2143 case ICMD_IF_ACMPEQ:
2145 var_to_reg_int(s1, src->prev, REG_ITMP1);
2146 var_to_reg_int(s2, src, REG_ITMP2);
2149 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2152 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2153 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2154 /******************************************************************
2155 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2156 *******************************************************************/
2157 case ICMD_IF_ACMPNE:
2159 var_to_reg_int(s1, src->prev, REG_ITMP1);
2160 var_to_reg_int(s2, src, REG_ITMP2);
2163 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2166 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2167 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2168 /******************************************************************
2169 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2170 *******************************************************************/
2172 var_to_reg_int(s1, src->prev, REG_ITMP1);
2173 var_to_reg_int(s2, src, REG_ITMP2);
2176 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2179 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2180 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2181 /******************************************************************
2182 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2183 *******************************************************************/
2185 var_to_reg_int(s1, src->prev, REG_ITMP1);
2186 var_to_reg_int(s2, src, REG_ITMP2);
2189 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2192 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2193 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2194 /******************************************************************
2195 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2196 *******************************************************************/
2198 var_to_reg_int(s1, src->prev, REG_ITMP1);
2199 var_to_reg_int(s2, src, REG_ITMP2);
2202 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2205 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2206 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2207 /******************************************************************
2208 TODO: CMP UPPER 32 BIT OF LONGS, TOO!
2209 *******************************************************************/
2211 var_to_reg_int(s1, src->prev, REG_ITMP1);
2212 var_to_reg_int(s2, src, REG_ITMP2);
2215 codegen_addreference(cd, (basicblock *) iptr->target, mcodeptr);
2218 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2220 var_to_reg_int(s1, src, REG_RESULT);
2221 M_TINTMOVE(src->type, s1, REG_RESULT);
2222 goto nowperformreturn;
2224 var_to_reg_int(s1, src, PACK_REGS(REG_RESULT2, REG_RESULT));
2225 M_TINTMOVE(src->type, s1, PACK_REGS(REG_RESULT2, REG_RESULT));
2226 goto nowperformreturn;
2228 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2230 var_to_reg_flt(s1, src, REG_FRESULT);
2231 M_FLTMOVE(s1, REG_FRESULT);
2232 goto nowperformreturn;
2234 case ICMD_RETURN: /* ... ==> ... */
2240 p = parentargs_base;
2242 /* call trace function */
2246 M_LDA(REG_SP, REG_SP, -10 * 8);
2247 M_DST(REG_FRESULT, REG_SP, 48+0);
2248 M_IST(REG_RESULT, REG_SP, 48+8);
2249 M_AST(REG_ITMP3, REG_SP, 48+12);
2250 M_IST(REG_RESULT2, REG_SP, 48+16);
2252 /* keep this order */
2253 switch (iptr->opc) {
2256 #if defined(__DARWIN__)
2257 M_MOV(REG_RESULT, rd->argintregs[2]);
2258 M_CLR(rd->argintregs[1]);
2260 M_MOV(REG_RESULT, rd->argintregs[3]);
2261 M_CLR(rd->argintregs[2]);
2266 #if defined(__DARWIN__)
2267 M_MOV(REG_RESULT2, rd->argintregs[2]);
2268 M_MOV(REG_RESULT, rd->argintregs[1]);
2270 M_MOV(REG_RESULT2, rd->argintregs[3]);
2271 M_MOV(REG_RESULT, rd->argintregs[2]);
2276 a = dseg_addaddress(cd, m);
2277 M_ALD(rd->argintregs[0], REG_PV, a);
2279 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2280 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2281 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2282 M_ALD(REG_ITMP2, REG_PV, a);
2285 M_DLD(REG_FRESULT, REG_SP, 48+0);
2286 M_ILD(REG_RESULT, REG_SP, 48+8);
2287 M_ALD(REG_ITMP3, REG_SP, 48+12);
2288 M_ILD(REG_RESULT2, REG_SP, 48+16);
2289 M_LDA(REG_SP, REG_SP, 10 * 8);
2293 #if defined(USE_THREADS)
2294 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2295 /* we need to save the proper return value */
2296 switch (iptr->opc) {
2298 M_IST(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2302 M_IST(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2305 M_FST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2308 M_DST(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2312 a = dseg_addaddress(cd, BUILTIN_monitorexit);
2313 M_ALD(REG_ITMP3, REG_PV, a);
2315 M_ALD(rd->argintregs[0], REG_SP, rd->memuse * 4);
2318 /* and now restore the proper return value */
2319 switch (iptr->opc) {
2321 M_ILD(REG_RESULT2, REG_SP, rd->memuse * 4 + 8);
2325 M_ILD(REG_RESULT , REG_SP, rd->memuse * 4 + 4);
2328 M_FLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2331 M_DLD(REG_FRESULT, REG_SP, rd->memuse * 4 + 4);
2337 /* restore return address */
2339 if (!m->isleafmethod) {
2340 M_ALD(REG_ITMP3, REG_SP, p * 4 + LA_LR_OFFSET);
2344 /* restore saved registers */
2346 for (i = INT_SAV_CNT - 1; i >= rd->savintreguse; i--) {
2347 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2349 for (i = FLT_SAV_CNT - 1; i >= rd->savfltreguse; i--) {
2350 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2353 /* deallocate stack */
2355 if (parentargs_base)
2356 M_LDA(REG_SP, REG_SP, parentargs_base * 4);
2364 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2369 tptr = (void **) iptr->target;
2371 s4ptr = iptr->val.a;
2372 l = s4ptr[1]; /* low */
2373 i = s4ptr[2]; /* high */
2375 var_to_reg_int(s1, src, REG_ITMP1);
2377 M_INTMOVE(s1, REG_ITMP1);
2378 } else if (l <= 32768) {
2379 M_LDA(REG_ITMP1, s1, -l);
2381 ICONST(REG_ITMP2, l);
2382 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2388 M_CMPUI(REG_ITMP1, i - 1);
2391 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2392 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2394 /* build jump table top down and use address of lowest entry */
2396 /* s4ptr += 3 + i; */
2400 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2401 dseg_addtarget(cd, (basicblock *) tptr[0]);
2406 /* length of dataseg after last dseg_addtarget is used by load */
2408 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2409 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2410 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2417 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2419 s4 i, l, val, *s4ptr;
2422 tptr = (void **) iptr->target;
2424 s4ptr = iptr->val.a;
2425 l = s4ptr[0]; /* default */
2426 i = s4ptr[1]; /* count */
2428 MCODECHECK((i<<2)+8);
2429 var_to_reg_int(s1, src, REG_ITMP1);
2435 if ((val >= -32768) && (val <= 32767)) {
2439 a = dseg_adds4(cd, val);
2440 M_ILD(REG_ITMP2, REG_PV, a);
2441 M_CMP(s1, REG_ITMP2);
2444 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2445 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2449 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2451 tptr = (void **) iptr->target;
2452 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2459 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2460 /* op1 = arg count val.a = builtintable entry */
2466 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2467 /* op1 = arg count, val.a = method pointer */
2469 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2470 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2471 case ICMD_INVOKEINTERFACE:
2476 md = lm->parseddesc;
2478 unresolved_method *um = iptr->target;
2479 md = um->methodref->parseddesc.md;
2485 MCODECHECK((s3 << 1) + 64);
2487 /* copy arguments to registers or stack location */
2489 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2490 if (src->varkind == ARGVAR)
2492 if (IS_INT_LNG_TYPE(src->type)) {
2493 if (!md->params[s3].inmemory) {
2494 if (IS_2_WORD_TYPE(src->type))
2496 rd->argintregs[GET_LOW_REG(md->params[s3].regoff)],
2497 rd->argintregs[GET_HIGH_REG(md->params[s3].regoff)]);
2499 s1 = rd->argintregs[md->params[s3].regoff];
2500 var_to_reg_int(d, src, s1);
2501 M_TINTMOVE(src->type, d, s1);
2503 var_to_reg_int(d, src, PACK_REGS(REG_ITMP3, REG_ITMP1));
2504 M_IST(GET_HIGH_REG(d), REG_SP,
2505 md->params[s3].regoff * 4);
2506 if (IS_2_WORD_TYPE(src->type))
2507 M_IST(GET_LOW_REG(d),
2508 REG_SP, md->params[s3].regoff * 4 + 4);
2512 if (!md->params[s3].inmemory) {
2513 s1 = rd->argfltregs[md->params[s3].regoff];
2514 var_to_reg_flt(d, src, s1);
2517 var_to_reg_flt(d, src, REG_FTMP1);
2518 if (IS_2_WORD_TYPE(src->type))
2519 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2521 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2526 switch (iptr->opc) {
2529 codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target);
2531 if (showdisassemble)
2537 a = (ptrint) bte->fp;
2540 a = dseg_addaddress(cd, a);
2541 d = md->returntype.type;
2543 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2546 case ICMD_INVOKESPECIAL:
2547 gen_nullptr_check(rd->argintregs[0]);
2548 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr */
2551 case ICMD_INVOKESTATIC:
2553 unresolved_method *um = iptr->target;
2555 codegen_addpatchref(cd, mcodeptr,
2556 PATCHER_invokestatic_special, um);
2558 if (showdisassemble)
2562 d = md->returntype.type;
2565 a = (ptrint) lm->stubroutine;
2566 d = md->returntype.type;
2569 a = dseg_addaddress(cd, a);
2570 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2573 case ICMD_INVOKEVIRTUAL:
2574 gen_nullptr_check(rd->argintregs[0]);
2577 unresolved_method *um = iptr->target;
2579 codegen_addpatchref(cd, mcodeptr,
2580 PATCHER_invokevirtual, um);
2582 if (showdisassemble)
2586 d = md->returntype.type;
2589 s1 = OFFSET(vftbl_t, table[0]) +
2590 sizeof(methodptr) * lm->vftblindex;
2591 d = md->returntype.type;
2594 M_ALD(REG_METHODPTR, rd->argintregs[0],
2595 OFFSET(java_objectheader, vftbl));
2596 M_ALD(REG_PV, REG_METHODPTR, s1);
2599 case ICMD_INVOKEINTERFACE:
2600 gen_nullptr_check(rd->argintregs[0]);
2603 unresolved_method *um = iptr->target;
2605 codegen_addpatchref(cd, mcodeptr,
2606 PATCHER_invokeinterface, um);
2608 if (showdisassemble)
2613 d = md->returntype.type;
2616 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2617 sizeof(methodptr*) * lm->class->index;
2619 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2621 d = md->returntype.type;
2624 M_ALD(REG_METHODPTR, rd->argintregs[0],
2625 OFFSET(java_objectheader, vftbl));
2626 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2627 M_ALD(REG_PV, REG_METHODPTR, s2);
2636 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2638 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2640 s4 ml = -s1, mh = 0;
2641 while (ml < -32768) { ml += 65536; mh--; }
2642 M_LDA(REG_PV, REG_ITMP1, ml);
2643 M_LDAH(REG_PV, REG_PV, mh);
2646 /* d contains return type */
2648 if (d != TYPE_VOID) {
2649 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2650 if (IS_2_WORD_TYPE(iptr->dst->type)) {
2651 s1 = reg_of_var(rd, iptr->dst,
2652 PACK_REGS(REG_RESULT2, REG_RESULT));
2653 M_TINTMOVE(iptr->dst->type,
2654 PACK_REGS(REG_RESULT2, REG_RESULT), s1);
2656 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2657 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2659 store_reg_to_var_int(iptr->dst, s1);
2662 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2663 M_FLTMOVE(REG_FRESULT, s1);
2664 store_reg_to_var_flt(iptr->dst, s1);
2670 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2672 /* op1: 0 == array, 1 == class */
2673 /* val.a: (classinfo*) superclass */
2675 /* superclass is an interface:
2677 * OK if ((sub == NULL) ||
2678 * (sub->vftbl->interfacetablelength > super->index) &&
2679 * (sub->vftbl->interfacetable[-super->index] != NULL));
2681 * superclass is a class:
2683 * OK if ((sub == NULL) || (0
2684 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2685 * super->vftbl->diffvall));
2690 vftbl_t *supervftbl;
2693 super = (classinfo *) iptr->val.a;
2700 superindex = super->index;
2701 supervftbl = super->vftbl;
2704 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2705 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2707 var_to_reg_int(s1, src, REG_ITMP1);
2709 /* calculate interface checkcast code size */
2713 s2 += (showdisassemble ? 1 : 0);
2715 /* calculate class checkcast code size */
2717 s3 = 8 + (s1 == REG_ITMP1);
2719 s3 += (showdisassemble ? 1 : 0);
2721 /* if class is not resolved, check which code to call */
2725 M_BEQ(3 + (showdisassemble ? 1 : 0) + s2 + 1 + s3);
2727 codegen_addpatchref(cd, mcodeptr,
2728 PATCHER_checkcast_instanceof_flags,
2729 (constant_classref *) iptr->target);
2731 if (showdisassemble)
2734 a = dseg_adds4(cd, 0); /* super->flags */
2735 M_ILD(REG_ITMP2, REG_PV, a);
2736 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2740 /* interface checkcast code */
2742 if (!super || (super->flags & ACC_INTERFACE)) {
2748 codegen_addpatchref(cd, mcodeptr,
2749 PATCHER_checkcast_instanceof_interface,
2750 (constant_classref *) iptr->target);
2752 if (showdisassemble)
2756 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2757 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2758 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2760 codegen_addxcastrefs(cd, mcodeptr);
2761 M_ALD(REG_ITMP3, REG_ITMP2,
2762 OFFSET(vftbl_t, interfacetable[0]) -
2763 superindex * sizeof(methodptr*));
2766 codegen_addxcastrefs(cd, mcodeptr);
2772 /* class checkcast code */
2774 if (!super || !(super->flags & ACC_INTERFACE)) {
2780 codegen_addpatchref(cd, mcodeptr,
2781 PATCHER_checkcast_class,
2782 (constant_classref *) iptr->target);
2784 if (showdisassemble)
2788 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2789 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2790 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
2792 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2793 a = dseg_addaddress(cd, supervftbl);
2794 M_ALD(REG_ITMP2, REG_PV, a);
2795 if (s1 != REG_ITMP1) {
2796 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2797 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2798 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2799 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2801 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2803 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2804 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2805 M_ALD(REG_ITMP2, REG_PV, a);
2806 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2807 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2808 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2811 M_CMPU(REG_ITMP3, REG_ITMP2);
2813 codegen_addxcastrefs(cd, mcodeptr);
2815 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2817 store_reg_to_var_int(iptr->dst, d);
2821 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2823 /* op1: 0 == array, 1 == class */
2824 /* val.a: (classinfo*) superclass */
2826 /* superclass is an interface:
2828 * return (sub != NULL) &&
2829 * (sub->vftbl->interfacetablelength > super->index) &&
2830 * (sub->vftbl->interfacetable[-super->index] != NULL);
2832 * superclass is a class:
2834 * return ((sub != NULL) && (0
2835 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2836 * super->vftbl->diffvall));
2841 vftbl_t *supervftbl;
2844 super = (classinfo *) iptr->val.a;
2851 superindex = super->index;
2852 supervftbl = super->vftbl;
2855 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2856 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2858 var_to_reg_int(s1, src, REG_ITMP1);
2859 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2861 M_MOV(s1, REG_ITMP1);
2865 /* calculate interface instanceof code size */
2869 s2 += (showdisassemble ? 1 : 0);
2871 /* calculate class instanceof code size */
2875 s3 += (showdisassemble ? 1 : 0);
2879 /* if class is not resolved, check which code to call */
2883 M_BEQ(3 + (showdisassemble ? 1 : 0) + s2 + 1 + s3);
2885 codegen_addpatchref(cd, mcodeptr,
2886 PATCHER_checkcast_instanceof_flags,
2887 (constant_classref *) iptr->target);
2889 if (showdisassemble)
2892 a = dseg_adds4(cd, 0); /* super->flags */
2893 M_ILD(REG_ITMP2, REG_PV, a);
2894 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2898 /* interface instanceof code */
2900 if (!super || (super->flags & ACC_INTERFACE)) {
2906 codegen_addpatchref(cd, mcodeptr,
2907 PATCHER_checkcast_instanceof_interface,
2908 (constant_classref *) iptr->target);
2910 if (showdisassemble)
2914 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2915 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2916 M_LDATST(REG_ITMP2, REG_ITMP2, -superindex);
2918 M_ALD(REG_ITMP1, REG_ITMP1,
2919 OFFSET(vftbl_t, interfacetable[0]) -
2920 superindex * sizeof(methodptr*));
2924 M_IADD_IMM(REG_ZERO, 1, d);
2930 /* class instanceof code */
2932 if (!super || !(super->flags & ACC_INTERFACE)) {
2938 codegen_addpatchref(cd, mcodeptr,
2939 PATCHER_instanceof_class,
2940 (constant_classref *) iptr->target);
2942 if (showdisassemble) {
2947 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2948 a = dseg_addaddress(cd, supervftbl);
2949 M_ALD(REG_ITMP2, REG_PV, a);
2950 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2951 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
2953 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2954 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2955 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2956 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2957 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2959 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2960 M_CMPU(REG_ITMP1, REG_ITMP2);
2963 M_IADD_IMM(REG_ZERO, 1, d);
2965 store_reg_to_var_int(iptr->dst, d);
2969 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
2971 var_to_reg_int(s1, src, REG_ITMP1);
2974 codegen_addxcheckarefs(cd, mcodeptr);
2977 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
2979 M_CMPI(REG_RESULT, 0);
2981 codegen_addxexceptionrefs(cd, mcodeptr);
2984 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2985 /* op1 = dimension, val.a = array descriptor */
2987 /* check for negative sizes and copy sizes to stack if necessary */
2989 MCODECHECK((iptr->op1 << 1) + 64);
2991 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
2992 var_to_reg_int(s2, src, REG_ITMP1);
2995 codegen_addxcheckarefs(cd, mcodeptr);
2997 /* copy SAVEDVAR sizes to stack */
2999 if (src->varkind != ARGVAR)
3000 #if defined(__DARWIN__)
3001 M_IST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 4);
3003 M_IST(s2, REG_SP, LA_SIZE + (s1 + 3) * 4);
3007 /* is patcher function set? */
3010 codegen_addpatchref(cd, mcodeptr,
3011 (functionptr) iptr->target, iptr->val.a);
3013 if (showdisassemble)
3019 a = (ptrint) iptr->val.a;
3022 /* a0 = dimension count */
3024 ICONST(rd->argintregs[0], iptr->op1);
3026 /* a1 = arraydescriptor */
3028 a = dseg_addaddress(cd, iptr->val.a);
3029 M_ALD(rd->argintregs[1], REG_PV, a);
3031 /* a2 = pointer to dimensions = stack pointer */
3033 #if defined(__DARWIN__)
3034 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 4);
3036 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 4);
3039 a = dseg_addaddress(cd, BUILTIN_multianewarray);
3040 M_ALD(REG_PV, REG_PV, a);
3043 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3046 M_LDA (REG_PV, REG_ITMP1, -s1);
3048 s4 ml = -s1, mh = 0;
3049 while (ml < -32768) {ml += 65536; mh--;}
3050 M_LDA(REG_PV, REG_ITMP1, ml);
3051 M_LDAH(REG_PV, REG_PV, mh);
3053 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3054 M_INTMOVE(REG_RESULT, s1);
3055 store_reg_to_var_int(iptr->dst, s1);
3060 throw_cacao_exception_exit(string_java_lang_InternalError,
3061 "Unknown ICMD %d", iptr->opc);
3064 } /* for instruction */
3066 /* copy values to interface registers */
3068 src = bptr->outstack;
3069 len = bptr->outdepth;
3070 MCODECHECK(64 + len);
3076 if ((src->varkind != STACKVAR)) {
3078 if (IS_FLT_DBL_TYPE(s2)) {
3079 var_to_reg_flt(s1, src, REG_FTMP1);
3080 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3081 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3084 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3088 var_to_reg_int(s1, src, REG_ITMP1);
3089 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3090 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3093 if (IS_2_WORD_TYPE(s2)) {
3094 M_IST(GET_HIGH_REG(s1),
3095 REG_SP, rd->interfaces[len][s2].regoff * 4);
3096 M_IST(GET_LOW_REG(s1), REG_SP,
3097 rd->interfaces[len][s2].regoff * 4 + 4);
3099 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3107 } /* if (bptr -> flags >= BBREACHED) */
3108 } /* for basic block */
3110 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3113 /* generate bound check stubs */
3115 s4 *xcodeptr = NULL;
3118 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3119 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3121 (u1 *) mcodeptr - cd->mcodebase);
3125 /* move index register into REG_ITMP1 */
3126 M_MOV(bref->reg, REG_ITMP1);
3127 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3129 if (xcodeptr != NULL) {
3130 off = xcodeptr - mcodeptr - 1;
3134 xcodeptr = mcodeptr;
3136 M_STWU(REG_SP, REG_SP, -(24 + 2 * 4));
3137 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3139 M_MOV(REG_ITMP1, rd->argintregs[0]);
3141 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3142 M_ALD(REG_ITMP2, REG_PV, a);
3145 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3147 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3148 M_IADD_IMM(REG_SP, 24 + 2 * 4, REG_SP);
3150 a = dseg_addaddress(cd, asm_handle_exception);
3151 M_ALD(REG_ITMP3, REG_PV, a);
3158 /* generate negative array size check stubs */
3162 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3163 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3164 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3166 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3170 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3172 (u1 *) mcodeptr - cd->mcodebase);
3176 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3178 if (xcodeptr != NULL) {
3179 off = xcodeptr - mcodeptr - 1;
3183 xcodeptr = mcodeptr;
3185 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3186 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3188 a = dseg_addaddress(cd, new_negativearraysizeexception);
3189 M_ALD(REG_ITMP2, REG_PV, a);
3192 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3194 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3195 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3197 a = dseg_addaddress(cd, asm_handle_exception);
3198 M_ALD(REG_ITMP3, REG_PV, a);
3205 /* generate cast check stubs */
3209 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3210 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3211 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3213 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3217 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3219 (u1 *) mcodeptr - cd->mcodebase);
3223 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3225 if (xcodeptr != NULL) {
3226 off = xcodeptr - mcodeptr - 1;
3230 xcodeptr = mcodeptr;
3232 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3233 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3235 a = dseg_addaddress(cd, new_classcastexception);
3236 M_ALD(REG_ITMP2, REG_PV, a);
3239 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3241 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3242 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3244 a = dseg_addaddress(cd, asm_handle_exception);
3245 M_ALD(REG_ITMP3, REG_PV, a);
3252 /* generate exception check stubs */
3256 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3257 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3258 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3260 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3264 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3266 (u1 *) mcodeptr - cd->mcodebase);
3270 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3272 if (xcodeptr != NULL) {
3273 off = xcodeptr - mcodeptr - 1;
3277 xcodeptr = mcodeptr;
3279 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3280 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3282 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3283 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3284 M_ALD(REG_ITMP2, REG_PV, a);
3288 /* get the exceptionptr from the ptrprt and clear it */
3289 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3291 M_AST(REG_ITMP3, REG_RESULT, 0);
3293 a = dseg_addaddress(cd, &_exceptionptr);
3294 M_ALD(REG_ITMP2, REG_PV, a);
3296 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3298 M_AST(REG_ITMP3, REG_ITMP2, 0);
3301 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3302 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3304 a = dseg_addaddress(cd, asm_handle_exception);
3305 M_ALD(REG_ITMP3, REG_PV, a);
3311 /* generate null pointer check stubs */
3315 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3316 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3317 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3319 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3323 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3325 (u1 *) mcodeptr - cd->mcodebase);
3329 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3331 if (xcodeptr != NULL) {
3332 off = xcodeptr - mcodeptr - 1;
3336 xcodeptr = mcodeptr;
3338 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3339 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3341 a = dseg_addaddress(cd, new_nullpointerexception);
3342 M_ALD(REG_ITMP2, REG_PV, a);
3345 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3347 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3348 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3350 a = dseg_addaddress(cd, asm_handle_exception);
3351 M_ALD(REG_ITMP3, REG_PV, a);
3357 /* generate patcher stub call code */
3364 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3365 /* check code segment size */
3369 /* Get machine code which is patched back in later. The call is */
3370 /* 1 instruction word long. */
3372 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3375 /* patch in the call to call the following code (done at compile */
3378 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3379 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3381 M_BL(tmpmcodeptr - (xcodeptr + 1));
3383 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3385 /* create stack frame - keep stack 16-byte aligned */
3387 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
3389 /* move return address onto stack */
3392 M_AST(REG_ITMP3, REG_SP, 4 * 4);
3394 /* move pointer to java_objectheader onto stack */
3396 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3397 /* order reversed because of data segment layout */
3399 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3400 off = dseg_addaddress(cd, NULL); /* vftbl */
3402 if (off >= -32768) {
3403 M_LDA(REG_ITMP3, REG_PV, off);
3405 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3406 M_LDA(REG_ITMP3, REG_ITMP3, off);
3408 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3411 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3414 /* move machine code onto stack */
3416 off = dseg_adds4(cd, mcode);
3417 if (off >= -32768) {
3418 M_ILD(REG_ITMP3, REG_PV, off);
3420 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3421 M_ILD(REG_ITMP3, REG_ITMP3, off);
3423 M_IST(REG_ITMP3, REG_SP, 2 * 4);
3425 /* move class/method/field reference onto stack */
3427 off = dseg_addaddress(cd, pref->ref);
3428 if (off >= -32768) {
3429 M_ALD(REG_ITMP3, REG_PV, off);
3431 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3432 M_ALD(REG_ITMP3, REG_ITMP3, off);
3434 M_AST(REG_ITMP3, REG_SP, 1 * 4);
3436 /* move patcher function pointer onto stack */
3438 off = dseg_addaddress(cd, pref->patcher);
3439 if (off >= -32768) {
3440 M_ALD(REG_ITMP3, REG_PV, off);
3442 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3443 M_ALD(REG_ITMP3, REG_ITMP3, off);
3445 M_AST(REG_ITMP3, REG_SP, 0 * 4);
3447 off = dseg_addaddress(cd, asm_wrapper_patcher);
3448 if (off >= -32768) {
3449 M_ALD(REG_ITMP3, REG_PV, off);
3451 M_LDAH(REG_ITMP3, REG_PV, (off >> 16));
3452 M_ALD(REG_ITMP3, REG_ITMP3, off);
3461 codegen_finish(m, cd, (ptrint) ((u1 *) mcodeptr - cd->mcodebase));
3463 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3467 /* createcompilerstub **********************************************************
3469 Creates a stub routine which calls the compiler.
3471 *******************************************************************************/
3473 #define COMPSTUBSIZE 6
3475 functionptr createcompilerstub(methodinfo *m)
3477 s4 *s = CNEW(s4, COMPSTUBSIZE); /* memory to hold the stub */
3478 s4 *mcodeptr = s; /* code generation pointer */
3480 M_LDA(REG_ITMP1, REG_PV, 4*4);
3481 M_ALD(REG_PV, REG_PV, 5*4);
3485 s[4] = (s4) m; /* literals to be adressed */
3486 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3488 asm_cacheflush((void *) s, (u1 *) mcodeptr - (u1 *) s);
3490 #if defined(STATISTICS)
3492 count_cstub_len += COMPSTUBSIZE * 4;
3495 return (functionptr) (ptrint) s;
3499 /* createnativestub ************************************************************
3501 Creates a stub routine which calls a native method.
3503 *******************************************************************************/
3505 functionptr createnativestub(functionptr f, methodinfo *m, codegendata *cd,
3506 registerdata *rd, methoddesc *nmd)
3508 s4 *mcodeptr; /* code generation pointer */
3509 s4 stackframesize; /* size of stackframe if needed */
3513 s4 i, j; /* count variables */
3517 /* set some variables */
3520 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3522 /* calculate stackframe size */
3524 stackframesize = nmd->memuse;
3525 stackframesize = (stackframesize + 3) & ~3; /* keep stack 16-byte aligned */
3528 /* create method header */
3530 (void) dseg_addaddress(cd, m); /* MethodPointer */
3531 (void) dseg_adds4(cd, stackframesize * 4); /* FrameSize */
3532 (void) dseg_adds4(cd, 0); /* IsSync */
3533 (void) dseg_adds4(cd, 0); /* IsLeaf */
3534 (void) dseg_adds4(cd, 0); /* IntSave */
3535 (void) dseg_adds4(cd, 0); /* FltSave */
3536 (void) dseg_addlinenumbertablesize(cd);
3537 (void) dseg_adds4(cd, 0); /* ExTableSize */
3540 /* initialize mcode variables */
3542 mcodeptr = (s4 *) cd->mcodebase;
3543 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
3549 M_AST(REG_ITMP1, REG_SP, LA_LR_OFFSET);
3550 M_STWU(REG_SP, REG_SP, -(stackframesize * 4));
3553 /* if function is static, check for initialized */
3555 if ((m->flags & ACC_STATIC) && !m->class->initialized) {
3556 codegen_addpatchref(cd, mcodeptr, PATCHER_clinit, m->class);
3558 if (showdisassemble)
3563 /* parent_argbase == stackframesize * 4 */
3564 mcodeptr = codegen_trace_args(m, cd, rd, mcodeptr, stackframesize * 4 ,
3568 /* copy or spill arguments to new locations */
3570 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3571 t = md->paramtypes[i].type;
3573 if (IS_INT_LNG_TYPE(t)) {
3574 if (!md->params[i].inmemory) {
3575 if (IS_2_WORD_TYPE(t))
3577 rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
3578 rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
3580 s1 = rd->argintregs[md->params[i].regoff];
3581 if (!nmd->params[j].inmemory) {
3582 if (IS_2_WORD_TYPE(t))
3584 rd->argintregs[GET_LOW_REG(nmd->params[j].regoff)],
3585 rd->argintregs[GET_HIGH_REG(nmd->params[j].regoff)]);
3587 s2 = rd->argintregs[nmd->params[j].regoff];
3588 M_TINTMOVE(t, s1, s2);
3591 s2 = nmd->params[j].regoff;
3592 if (IS_2_WORD_TYPE(t)) {
3593 M_IST(GET_HIGH_REG(s1), REG_SP, s2 * 4);
3594 M_IST(GET_LOW_REG(s1), REG_SP, s2 * 4 + 4);
3596 M_IST(s1, REG_SP, s2 * 4);
3601 s1 = md->params[i].regoff + stackframesize;
3602 s2 = nmd->params[j].regoff;
3604 M_ILD(REG_ITMP1, REG_SP, s1 * 4);
3605 M_IST(REG_ITMP1, REG_SP, s2 * 4);
3606 if (IS_2_WORD_TYPE(t)) {
3607 M_ILD(REG_ITMP1, REG_SP, s1 * 4 + 4);
3608 M_IST(REG_ITMP1, REG_SP, s2 * 4 + 4);
3613 /* We only copy spilled float arguments, as the float argument */
3614 /* registers keep unchanged. */
3616 if (md->params[i].inmemory) {
3617 s1 = md->params[i].regoff + stackframesize;
3618 s2 = nmd->params[j].regoff;
3620 if (IS_2_WORD_TYPE(t)) {
3621 M_DLD(REG_FTMP1, REG_SP, s1 * 4);
3622 M_DST(REG_FTMP1, REG_SP, s2 * 4);
3625 M_FLD(REG_FTMP1, REG_SP, s1 * 4);
3626 M_FST(REG_FTMP1, REG_SP, s2 * 4);
3632 /* put class into second argument register */
3634 if (m->flags & ACC_STATIC) {
3635 off = dseg_addaddress(cd, m->class);
3636 M_ALD(rd->argintregs[1], REG_PV, off);
3639 /* put env into first argument register */
3641 off = dseg_addaddress(cd, &env);
3642 M_ALD(rd->argintregs[0], REG_PV, off);
3644 /* generate the actual native call */
3646 #if !defined(ENABLE_STATICVM)
3648 codegen_addpatchref(cd, mcodeptr, PATCHER_resolve_native, m);
3650 if (showdisassemble)
3655 off = dseg_addaddress(cd, f);
3656 M_ALD(REG_PV, REG_PV, off);
3659 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3661 M_LDA(REG_PV, REG_ITMP1, -disp); /* recompute pv from ra */
3663 /* 16 instructions */
3666 #if defined(__DARWIN__)
3667 M_LDA(REG_SP, REG_SP, -(LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4));
3668 M_IST(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
3669 M_IST(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
3670 M_DST(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
3672 M_LDA(REG_SP, REG_SP, -(LA_SIZE + (2 + 2) * 4));
3673 M_IST(REG_RESULT, REG_SP, LA_SIZE + 0 * 4);
3674 M_IST(REG_RESULT2, REG_SP, LA_SIZE + 1 * 4);
3675 M_DST(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4);
3678 /* keep this order */
3679 switch (m->returntype) {
3682 #if defined(__DARWIN__)
3683 M_MOV(REG_RESULT, rd->argintregs[2]);
3684 M_CLR(rd->argintregs[1]);
3686 M_MOV(REG_RESULT, rd->argintregs[3]);
3687 M_CLR(rd->argintregs[2]);
3692 #if defined(__DARWIN__)
3693 M_MOV(REG_RESULT2, rd->argintregs[2]);
3694 M_MOV(REG_RESULT, rd->argintregs[1]);
3696 M_MOV(REG_RESULT2, rd->argintregs[3]);
3697 M_MOV(REG_RESULT, rd->argintregs[2]);
3702 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3703 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3704 off = dseg_addaddress(cd, m);
3705 M_ALD(rd->argintregs[0], REG_PV, off);
3707 off = dseg_addaddress(cd, builtin_displaymethodstop);
3708 M_ALD(REG_ITMP2, REG_PV, off);
3712 #if defined(__DARWIN__)
3713 M_ILD(REG_RESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 0) * 4);
3714 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 1) * 4);
3715 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2) * 4);
3716 M_LDA(REG_SP, REG_SP, LA_SIZE + ((1 + 2 + 2 + 1) + 2 + 2) * 4);
3718 M_ILD(REG_RESULT, REG_SP, LA_SIZE + 0 * 4);
3719 M_ILD(REG_RESULT2, REG_SP, LA_SIZE + 1 * 4);
3720 M_DLD(REG_FRESULT, REG_SP, LA_SIZE + 2 * 4);
3721 M_LDA(REG_SP, REG_SP, LA_SIZE + (2 + 2) * 4);
3725 /* check for exception */
3727 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3728 switch (md->returntype.type) {
3730 M_IST(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
3734 M_IST(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
3737 M_FST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
3740 M_DST(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
3744 off = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3745 M_ALD(REG_ITMP2, REG_PV, off);
3748 disp = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3750 M_LDA(REG_PV, REG_ITMP1, -disp);
3751 M_MOV(REG_RESULT, REG_ITMP2);
3753 switch (md->returntype.type) {
3755 M_ILD(REG_RESULT2, REG_SP, (stackframesize - 1) * 4);
3759 M_ILD(REG_RESULT, REG_SP, (stackframesize - 2) * 4);
3762 M_FLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
3765 M_DLD(REG_FRESULT, REG_SP, (stackframesize - 2) * 4);
3769 off = dseg_addaddress(cd, &_exceptionptr)
3770 M_ALD(REG_ITMP2, REG_PV, off);
3772 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1 */
3773 M_TST(REG_ITMP1_XPTR);
3774 M_BNE(4); /* if no exception then return */
3776 M_ALD(REG_ITMP1, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
3778 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
3782 /* handle exception */
3785 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3787 M_ALD(REG_ITMP2, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
3790 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
3792 M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC); /* fault address */
3794 off = dseg_addaddress(cd, asm_handle_nat_exception);
3795 M_ALD(REG_ITMP3, REG_PV, off);
3799 /* generate patcher stub call code */
3807 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3808 /* Get machine code which is patched back in later. The call is */
3809 /* 1 instruction word long. */
3811 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3812 mcode = (u4) *xcodeptr;
3814 /* patch in the call to call the following code (done at compile */
3817 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3818 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3820 M_BL(tmpmcodeptr - (xcodeptr + 1));
3822 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3824 /* create stack frame - keep stack 16-byte aligned */
3826 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
3828 /* move return address onto stack */
3831 M_AST(REG_ITMP3, REG_SP, 4 * 4);
3833 /* move pointer to java_objectheader onto stack */
3835 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3836 /* order reversed because of data segment layout */
3838 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3839 off = dseg_addaddress(cd, NULL); /* vftbl */
3841 M_LDA(REG_ITMP3, REG_PV, off);
3842 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3845 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3848 /* move machine code onto stack */
3850 off = dseg_adds4(cd, mcode);
3851 M_ILD(REG_ITMP3, REG_PV, off);
3852 M_IST(REG_ITMP3, REG_SP, 2 * 4);
3854 /* move class/method/field reference onto stack */
3856 off = dseg_addaddress(cd, pref->ref);
3857 M_ALD(REG_ITMP3, REG_PV, off);
3858 M_AST(REG_ITMP3, REG_SP, 1 * 4);
3860 /* move patcher function pointer onto stack */
3862 off = dseg_addaddress(cd, pref->patcher);
3863 M_ALD(REG_ITMP3, REG_PV, off);
3864 M_AST(REG_ITMP3, REG_SP, 0 * 4);
3866 off = dseg_addaddress(cd, asm_wrapper_patcher);
3867 M_ALD(REG_ITMP3, REG_PV, off);
3873 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3875 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3877 return m->entrypoint;
3880 s4 *codegen_trace_args( methodinfo *m, codegendata *cd, registerdata *rd,
3881 s4 *mcodeptr, s4 parentargs_base, bool nativestub)
3892 /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
3894 /* LA + TRACE_ARGS_NUM u8 args + methodinfo + LR */
3895 /* LA_SIZE(=6*4) + 8*8 + 4 + 4 + 0(Padding) */
3896 /* 6 * 4 + 8 * 8 + 2 * 4 = 12 * 8 = 6 * 16 */
3898 /* LA + (TRACE_ARGS_NUM - INT_ARG_CNT/2) u8 args + methodinfo */
3899 /* + INT_ARG_CNT * 4 ( save integer registers) + LR + 8 + 8 (Padding) */
3900 /* LA_SIZE(=2*4) + 4 * 8 + 4 + 8 * 4 + 4 + 8 */
3901 /* 2 * 4 + 4 * 8 + 10 * 4 + 1 * 8 + 8= 12 * 8 = 6 * 16 */
3903 /* in nativestubs no Place to save the LR (Link Register) would be needed */
3904 /* but since the stack frame has to be aligned the 4 Bytes would have to */
3905 /* be padded again */
3907 #if defined(__DARWIN__)
3908 stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
3910 stack_size = 6 * 16;
3912 M_LDA(REG_SP, REG_SP, -stack_size);
3916 M_IST(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
3918 M_CLR(REG_ITMP1); /* clear help register */
3920 /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
3921 #if defined(__DARWIN__)
3922 /* Copy Params starting from first to Stack */
3923 /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs */
3927 /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in */
3928 /* integer argument regs */
3929 /* all integer argument registers have to be saved */
3930 for (p = 0; p < 8; p++) {
3931 d = rd->argintregs[p];
3932 /* save integer argument registers */
3933 M_IST(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
3937 stack_off = LA_SIZE;
3938 for (; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
3939 t = md->paramtypes[p].type;
3940 if (IS_INT_LNG_TYPE(t)) {
3941 if (!md->params[p].inmemory) { /* Param in Arg Reg */
3942 if (IS_2_WORD_TYPE(t)) {
3943 M_IST(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
3944 , REG_SP, stack_off);
3945 M_IST(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
3946 , REG_SP, stack_off + 4);
3948 M_IST(REG_ITMP1, REG_SP, stack_off);
3949 M_IST(rd->argintregs[md->params[p].regoff]
3950 , REG_SP, stack_off + 4);
3952 } else { /* Param on Stack */
3953 s1 = (md->params[p].regoff + parentargs_base) * 4
3955 if (IS_2_WORD_TYPE(t)) {
3956 M_ILD(REG_ITMP2, REG_SP, s1);
3957 M_IST(REG_ITMP2, REG_SP, stack_off);
3958 M_ILD(REG_ITMP2, REG_SP, s1 + 4);
3959 M_IST(REG_ITMP2, REG_SP, stack_off + 4);
3961 M_IST(REG_ITMP1, REG_SP, stack_off);
3962 M_ILD(REG_ITMP2, REG_SP, s1);
3963 M_IST(REG_ITMP2, REG_SP, stack_off + 4);
3966 } else { /* IS_FLT_DBL_TYPE(t) */
3967 if (!md->params[p].inmemory) { /* in Arg Reg */
3968 s1 = rd->argfltregs[md->params[p].regoff];
3969 if (!IS_2_WORD_TYPE(t)) {
3970 M_IST(REG_ITMP1, REG_SP, stack_off);
3971 M_FST(s1, REG_SP, stack_off + 4);
3973 M_DST(s1, REG_SP, stack_off);
3975 } else { /* on Stack */
3976 /* this should not happen */
3981 /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
3982 #if defined(__DARWIN__)
3983 for (p = 0; p < 8; p++) {
3984 d = rd->argintregs[p];
3985 M_ILD(d, REG_SP, LA_SIZE + p * 4);
3989 /* Set integer and float argument registers vor trace_args call */
3990 /* offset to saved integer argument registers */
3991 stack_off = LA_SIZE + 4 * 8 + 4;
3992 for (p = 0; (p < 4) && (p < md->paramcount); p++) {
3993 t = md->paramtypes[p].type;
3994 if (IS_INT_LNG_TYPE(t)) {
3995 /* "stretch" int types */
3996 if (!IS_2_WORD_TYPE(t)) {
3997 M_CLR(rd->argintregs[2 * p]);
3998 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off);
4001 M_ILD(rd->argintregs[2 * p + 1], REG_SP,stack_off + 4);
4002 M_ILD(rd->argintregs[2 * p], REG_SP,stack_off);
4005 } else { /* Float/Dbl */
4006 if (!md->params[p].inmemory) { /* Param in Arg Reg */
4007 /* use reserved Place on Stack (sp + 5 * 16) to copy */
4008 /* float/double arg reg to int reg */
4009 s1 = rd->argfltregs[md->params[p].regoff];
4010 if (!IS_2_WORD_TYPE(t)) {
4011 M_FST(s1, REG_SP, 5 * 16);
4012 M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16);
4013 M_CLR(rd->argintregs[2 * p]);
4015 M_DST(s1, REG_SP, 5 * 16);
4016 M_ILD(rd->argintregs[2 * p + 1], REG_SP, 5 * 16 + 4);
4017 M_ILD(rd->argintregs[2 * p], REG_SP, 5 * 16);
4024 /* put methodinfo pointer on Stackframe */
4025 p = dseg_addaddress(cd, m);
4026 M_ALD(REG_ITMP1, REG_PV, p);
4027 #if defined(__DARWIN__)
4028 M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8);
4030 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
4032 p = dseg_addaddress(cd, (void *) builtin_trace_args);
4033 M_ALD(REG_ITMP2, REG_PV, p);
4037 #if defined(__DARWIN__)
4038 /* restore integer argument registers from the reserved stack space */
4040 stack_off = LA_SIZE;
4041 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM;
4042 p++, stack_off += 8) {
4043 t = md->paramtypes[p].type;
4045 if (IS_INT_LNG_TYPE(t)) {
4046 if (!md->params[p].inmemory) {
4047 if (IS_2_WORD_TYPE(t)) {
4048 M_ILD(rd->argintregs[GET_HIGH_REG(md->params[p].regoff)]
4049 , REG_SP, stack_off);
4050 M_ILD(rd->argintregs[GET_LOW_REG(md->params[p].regoff)]
4051 , REG_SP, stack_off + 4);
4053 M_ILD(rd->argintregs[md->params[p].regoff]
4054 , REG_SP, stack_off + 4);
4061 for (p = 0; p < 8; p++) {
4062 d = rd->argintregs[p];
4063 /* save integer argument registers */
4064 M_ILD(d, REG_SP, LA_SIZE + 4 * 8 + 4 + p * 4);
4069 M_ILD(REG_ITMP3, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8 + 1 * 4);
4071 M_LDA(REG_SP, REG_SP, stack_size);
4078 * These are local overrides for various environment variables in Emacs.
4079 * Please do not remove this and leave it at the end of the file, where
4080 * Emacs will automagically detect them.
4081 * ---------------------------------------------------------------------
4084 * indent-tabs-mode: t