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
32 $Id: codegen.c 2578 2005-06-07 15:07:55Z 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"
72 void asm_cacheflush(void *, long);
74 /* #include <architecture/ppc/cframe.h> */
76 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
77 void thread_restartcriticalsection(void *u)
79 /* XXX set pc to restart address */
84 void init_exceptions(void)
88 #if !defined(__DARWIN__)
89 nregdescint[2] = REG_RES;
94 /* codegen *********************************************************************
96 Generates machine code.
98 *******************************************************************************/
100 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
102 s4 len, s1, s2, s3, d;
111 methodinfo *lm; /* local methodinfo for ICMD_INVOKE* */
112 builtintable_entry *bte;
121 /* space to save used callee saved registers */
123 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
124 savedregs_num += 2 * (rd->savfltregcnt - rd->maxsavfltreguse);
126 parentargs_base = rd->maxmemuse + savedregs_num;
128 #if defined(USE_THREADS) /* space to save argument of monitor_enter */
129 /* and Return Values to survive monitor_exit */
130 if (checksync && (m->flags & ACC_SYNCHRONIZED))
131 parentargs_base += 3;
135 /* create method header */
137 parentargs_base = (parentargs_base + 3) & ~3;
139 #if SIZEOF_VOID_P == 4
140 (void) dseg_addaddress(cd, m); /* Filler */
142 (void) dseg_addaddress(cd, m); /* MethodPointer */
143 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
145 #if defined(USE_THREADS)
147 /* IsSync contains the offset relative to the stack pointer for the
148 argument of monitor_exit used in the exception handler. Since the
149 offset could be zero and give a wrong meaning of the flag it is
153 if (checksync && (m->flags & ACC_SYNCHRONIZED))
154 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 4); /* IsSync */
159 (void) dseg_adds4(cd, 0); /* IsSync */
161 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
162 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
163 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
164 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
166 /* create exception table */
168 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
169 dseg_addtarget(cd, ex->start);
170 dseg_addtarget(cd, ex->end);
171 dseg_addtarget(cd, ex->handler);
172 (void) dseg_addaddress(cd, ex->catchtype.cls);
175 /* initialize mcode variables */
177 mcodeptr = (s4 *) cd->mcodebase;
178 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
179 MCODECHECK(128 + m->paramcount);
181 /* create stack frame (if necessary) */
183 if (!m->isleafmethod) {
185 M_AST(REG_ITMP3, REG_SP, LA_LR_OFFSET);
188 if (parentargs_base) {
189 M_STWU(REG_SP, REG_SP, -parentargs_base * 4);
192 /* save return address and used callee saved registers */
195 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
196 p--; M_IST(rd->savintregs[i], REG_SP, p * 4);
198 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
199 p -= 2; M_DST(rd->savfltregs[i], REG_SP, p * 4);
202 /* take arguments out of register or stack frame */
206 for (p = 0, l = 0; p < md->paramcount; p++) {
207 t = md->paramtypes[p].type;
208 var = &(rd->locals[l][t]);
210 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
214 s1 = md->params[p].regoff;
215 if (IS_INT_LNG_TYPE(t)) { /* integer args */
216 s2 = rd->argintregs[s1];
217 if (!md->params[p].inmemory) { /* register arguments */
218 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
219 M_TINTMOVE(t, s2, var->regoff);
221 } else { /* reg arg -> spilled */
222 M_IST(s2, REG_SP, var->regoff * 4);
223 if (IS_2_WORD_TYPE(t))
224 M_IST(rd->secondregs[s2], REG_SP, 4 * var->regoff + 4);
227 } else { /* stack arguments */
228 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
229 M_ILD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
230 if (IS_2_WORD_TYPE(t))
231 M_ILD(rd->secondregs[var->regoff], REG_SP, (parentargs_base + s1) * 4 + 4);
233 } else { /* stack arg -> spilled */
234 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4);
235 M_IST(REG_ITMP1, REG_SP, var->regoff * 4);
236 if (IS_2_WORD_TYPE(t)) {
237 M_ILD(REG_ITMP1, REG_SP, (parentargs_base + s1) * 4 + 4);
238 M_IST(REG_ITMP1, REG_SP, var->regoff * 4 + 4);
243 } else { /* floating args */
244 if (!md->params[p].inmemory) { /* register arguments */
245 s2 = rd->argfltregs[s1];
246 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
247 M_FLTMOVE(s2, var->regoff);
249 } else { /* reg arg -> spilled */
250 if (IS_2_WORD_TYPE(t))
251 M_DST(s2, REG_SP, var->regoff * 4);
253 M_FST(s2, REG_SP, var->regoff * 4);
256 } else { /* stack arguments */
257 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
258 if (IS_2_WORD_TYPE(t))
259 M_DLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
262 M_FLD(var->regoff, REG_SP, (parentargs_base + s1) * 4);
264 } else { /* stack-arg -> spilled */
265 if (IS_2_WORD_TYPE(t)) {
266 M_DLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
267 M_DST(REG_FTMP1, REG_SP, var->regoff * 4);
270 M_FLD(REG_FTMP1, REG_SP, (parentargs_base + s1) * 4);
271 M_FST(REG_FTMP1, REG_SP, var->regoff * 4);
278 /* save monitorenter argument */
280 #if defined(USE_THREADS)
281 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
282 /* stack offset for monitor argument */
288 M_LDA(REG_SP, REG_SP, -(INT_ARG_CNT * 4 + FLT_ARG_CNT * 8));
290 for (p = 0; p < INT_ARG_CNT; p++)
291 M_IST(rd->argintregs[p], REG_SP, p * 4);
293 for (p = 0; p < FLT_ARG_CNT * 2; p += 2)
294 M_DST(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
296 s1 += INT_ARG_CNT + FLT_ARG_CNT;
300 /* decide which monitor enter function to call */
302 if (m->flags & ACC_STATIC) {
303 p = dseg_addaddress(cd, m->class);
304 M_ALD(REG_ITMP1, REG_PV, p);
305 M_AST(REG_ITMP1, REG_SP, s1 * 4);
306 M_MOV(REG_ITMP1, rd->argintregs[0]);
307 p = dseg_addaddress(cd, BUILTIN_staticmonitorenter);
308 M_ALD(REG_ITMP3, REG_PV, p);
313 M_TST(rd->argintregs[0]);
315 codegen_addxnullrefs(cd, mcodeptr);
316 M_AST(rd->argintregs[0], REG_SP, s1 * 4);
317 p = dseg_addaddress(cd, BUILTIN_monitorenter);
318 M_ALD(REG_ITMP3, REG_PV, p);
325 for (p = 0; p < INT_ARG_CNT; p++)
326 M_ILD(rd->argintregs[p], REG_SP, p * 4);
328 for (p = 0; p < FLT_ARG_CNT; p++)
329 M_DLD(rd->argfltregs[p], REG_SP, (INT_ARG_CNT + p) * 4);
332 M_LDA(REG_SP, REG_SP, (INT_ARG_CNT + FLT_ARG_CNT) * 8);
338 /* call trace function */
346 /* XXX must be a multiple of 16 */
347 M_LDA(REG_SP, REG_SP, -(LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
349 M_IST(REG_ITMP3, REG_SP, LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
351 M_CLR(REG_ITMP1); /* clear help register */
353 /* save all arguments into the reserved stack space */
355 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
356 t = md->paramtypes[p].type;
358 if (IS_INT_LNG_TYPE(t)) {
359 /* overlapping u8's are on the stack */
360 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
361 s1 = rd->argintregs[p + longargs + dblargs];
363 if (!IS_2_WORD_TYPE(t)) {
364 M_IST(REG_ITMP1, REG_SP, LA_SIZE + p * 8);
365 M_IST(s1, REG_SP, LA_SIZE + p * 8 + 4);
368 M_IST(s1, REG_SP, LA_SIZE + p * 8);
369 M_IST(rd->secondregs[s1], REG_SP, LA_SIZE + p * 8 + 4);
374 a = dseg_adds4(cd, 0xdeadbeef);
375 M_ILD(REG_ITMP1, REG_PV, a);
376 M_IST(REG_ITMP1, REG_SP, LA_SIZE + p * 8);
377 M_IST(REG_ITMP1, REG_SP, LA_SIZE + p * 8 + 4);
381 if ((fltargs + dblargs) < FLT_ARG_CNT) {
382 s1 = rd->argfltregs[fltargs + dblargs];
384 if (!IS_2_WORD_TYPE(t)) {
385 M_IST(REG_ITMP1, REG_SP, LA_SIZE + p * 8);
386 M_FST(s1, REG_SP, LA_SIZE + p * 8 + 4);
390 M_DST(s1, REG_SP, LA_SIZE + p * 8);
395 /* this should not happen */
400 /* load first 4 arguments into integer argument registers */
402 for (p = 0; p < 8; p++) {
403 d = rd->argintregs[p];
404 M_ILD(d, REG_SP, LA_SIZE + p * 4);
407 p = dseg_addaddress(cd, m);
408 M_ALD(REG_ITMP1, REG_PV, p);
409 #if defined(__DARWIN__)
410 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 8 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
412 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
414 p = dseg_addaddress(cd, (void *) builtin_trace_args);
415 M_ALD(REG_ITMP2, REG_PV, p);
423 /* restore arguments from the reserved stack space */
425 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
426 t = md->paramtypes[p].type;
428 if (IS_INT_LNG_TYPE(t)) {
429 if ((p + longargs + dblargs) < INT_ARG_CNT) {
430 s1 = rd->argintregs[p + longargs + dblargs];
432 if (!IS_2_WORD_TYPE(t)) {
433 M_ILD(s1, REG_SP, LA_SIZE + p * 8 + 4);
436 M_ILD(s1, REG_SP, LA_SIZE + p * 8);
437 M_ILD(rd->secondregs[s1], REG_SP, LA_SIZE + p * 8 + 4);
443 if ((fltargs + dblargs) < FLT_ARG_CNT) {
444 s1 = rd->argfltregs[fltargs + dblargs];
446 if (!IS_2_WORD_TYPE(t)) {
447 M_FLD(s1, REG_SP, LA_SIZE + p * 8 + 4);
451 M_DLD(s1, REG_SP, LA_SIZE + p * 8);
458 M_ILD(REG_ITMP3, REG_SP, LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
460 M_LDA(REG_SP, REG_SP, LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
466 /* end of header generation */
468 /* walk through all basic blocks */
469 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
471 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
473 if (bptr->flags >= BBREACHED) {
475 /* branch resolving */
479 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
480 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
486 /* copy interface registers to their destination */
494 while (src != NULL) {
496 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
497 /* d = reg_of_var(m, src, REG_ITMP1); */
498 if (!(src->flags & INMEMORY))
502 M_INTMOVE(REG_ITMP1, d);
503 store_reg_to_var_int(src, d);
509 while (src != NULL) {
511 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
512 d = reg_of_var(rd, src, REG_ITMP1);
513 M_INTMOVE(REG_ITMP1, d);
514 store_reg_to_var_int(src, d);
517 d = reg_of_var(rd, src, REG_IFTMP);
518 if ((src->varkind != STACKVAR)) {
520 if (IS_FLT_DBL_TYPE(s2)) {
521 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
522 s1 = rd->interfaces[len][s2].regoff;
526 if (IS_2_WORD_TYPE(s2)) {
527 M_DLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
530 M_FLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
533 store_reg_to_var_flt(src, d);
536 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
537 s1 = rd->interfaces[len][s2].regoff;
541 M_ILD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
542 if (IS_2_WORD_TYPE(s2))
543 M_ILD(rd->secondregs[d], REG_SP, 4 * rd->interfaces[len][s2].regoff + 4);
545 store_reg_to_var_int(src, d);
555 /* walk through all instructions */
559 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
561 MCODECHECK(64); /* an instruction usually needs < 64 words */
564 case ICMD_NOP: /* ... ==> ... */
565 case ICMD_INLINE_START:
566 case ICMD_INLINE_END:
569 case ICMD_CHECKNULL: /* ..., objectref ==> ..., objectref */
571 var_to_reg_int(s1, src, REG_ITMP1);
574 codegen_addxnullrefs(cd, mcodeptr);
577 /* constant operations ************************************************/
579 case ICMD_ICONST: /* ... ==> ..., constant */
580 /* op1 = 0, val.i = constant */
582 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
583 ICONST(d, iptr->val.i);
584 store_reg_to_var_int(iptr->dst, d);
587 case ICMD_LCONST: /* ... ==> ..., constant */
588 /* op1 = 0, val.l = constant */
590 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
591 LCONST(d, iptr->val.l);
592 store_reg_to_var_int(iptr->dst, d);
595 case ICMD_FCONST: /* ... ==> ..., constant */
596 /* op1 = 0, val.f = constant */
598 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
599 a = dseg_addfloat(cd, iptr->val.f);
601 store_reg_to_var_flt(iptr->dst, d);
604 case ICMD_DCONST: /* ... ==> ..., constant */
605 /* op1 = 0, val.d = constant */
607 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
608 a = dseg_adddouble(cd, iptr->val.d);
610 store_reg_to_var_flt(iptr->dst, d);
613 case ICMD_ACONST: /* ... ==> ..., constant */
614 /* op1 = 0, val.a = constant */
616 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
617 ICONST(d, (u4) iptr->val.a);
618 store_reg_to_var_int(iptr->dst, d);
622 /* load/store operations **********************************************/
624 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
625 case ICMD_LLOAD: /* op1 = local variable */
628 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
629 if ((iptr->dst->varkind == LOCALVAR) &&
630 (iptr->dst->varnum == iptr->op1))
632 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
633 if (var->flags & INMEMORY) {
634 M_ILD(d, REG_SP, 4 * var->regoff);
635 if (IS_2_WORD_TYPE(var->type))
636 M_ILD(rd->secondregs[d], REG_SP, 4 * var->regoff + 4);
638 M_TINTMOVE(var->type, var->regoff, d);
640 store_reg_to_var_int(iptr->dst, d);
643 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
644 case ICMD_DLOAD: /* op1 = local variable */
646 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
647 if ((iptr->dst->varkind == LOCALVAR) &&
648 (iptr->dst->varnum == iptr->op1))
650 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
651 if (var->flags & INMEMORY)
652 if (IS_2_WORD_TYPE(var->type))
653 M_DLD(d, REG_SP, 4 * var->regoff);
655 M_FLD(d, REG_SP, 4 * var->regoff);
657 M_FLTMOVE(var->regoff, d);
659 store_reg_to_var_flt(iptr->dst, d);
663 case ICMD_ISTORE: /* ..., value ==> ... */
664 case ICMD_LSTORE: /* op1 = local variable */
667 if ((src->varkind == LOCALVAR) &&
668 (src->varnum == iptr->op1))
670 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
671 if (var->flags & INMEMORY) {
672 var_to_reg_int(s1, src, REG_ITMP1);
673 M_IST(s1, REG_SP, 4 * var->regoff);
674 if (IS_2_WORD_TYPE(var->type))
675 M_IST(rd->secondregs[s1], REG_SP, 4 * var->regoff + 4);
677 var_to_reg_int(s1, src, var->regoff);
678 M_TINTMOVE(var->type, s1, var->regoff);
682 case ICMD_FSTORE: /* ..., value ==> ... */
683 case ICMD_DSTORE: /* op1 = local variable */
685 if ((src->varkind == LOCALVAR) &&
686 (src->varnum == iptr->op1))
688 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
689 if (var->flags & INMEMORY) {
690 var_to_reg_flt(s1, src, REG_FTMP1);
691 if (var->type == TYPE_DBL)
692 M_DST(s1, REG_SP, 4 * var->regoff);
694 M_FST(s1, REG_SP, 4 * var->regoff);
696 var_to_reg_flt(s1, src, var->regoff);
697 M_FLTMOVE(s1, var->regoff);
702 /* pop/dup/swap operations ********************************************/
704 /* attention: double and longs are only one entry in CACAO ICMDs */
706 case ICMD_POP: /* ..., value ==> ... */
707 case ICMD_POP2: /* ..., value, value ==> ... */
710 case ICMD_DUP: /* ..., a ==> ..., a, a */
711 M_COPY(src, iptr->dst);
714 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
716 M_COPY(src, iptr->dst);
717 M_COPY(src->prev, iptr->dst->prev);
718 M_COPY(iptr->dst, iptr->dst->prev->prev);
721 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
723 M_COPY(src, iptr->dst);
724 M_COPY(src->prev, iptr->dst->prev);
725 M_COPY(src->prev->prev, iptr->dst->prev->prev);
726 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
729 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
731 M_COPY(src, iptr->dst);
732 M_COPY(src->prev, iptr->dst->prev);
735 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
737 M_COPY(src, iptr->dst);
738 M_COPY(src->prev, iptr->dst->prev);
739 M_COPY(src->prev->prev, iptr->dst->prev->prev);
740 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
741 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
744 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
746 M_COPY(src, iptr->dst);
747 M_COPY(src->prev, iptr->dst->prev);
748 M_COPY(src->prev->prev, iptr->dst->prev->prev);
749 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
750 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
751 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
754 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
756 M_COPY(src, iptr->dst->prev);
757 M_COPY(src->prev, iptr->dst);
761 /* integer operations *************************************************/
763 case ICMD_INEG: /* ..., value ==> ..., - value */
765 var_to_reg_int(s1, src, REG_ITMP1);
766 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
768 store_reg_to_var_int(iptr->dst, d);
771 case ICMD_LNEG: /* ..., value ==> ..., - value */
773 var_to_reg_int(s1, src, REG_ITMP1);
774 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
775 M_SUBFIC(rd->secondregs[s1], 0, rd->secondregs[d]);
777 store_reg_to_var_int(iptr->dst, d);
780 case ICMD_I2L: /* ..., value ==> ..., value */
782 var_to_reg_int(s1, src, REG_ITMP2);
783 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
784 M_INTMOVE(s1, rd->secondregs[d]);
785 M_SRA_IMM(rd->secondregs[d], 31, d);
786 store_reg_to_var_int(iptr->dst, d);
789 case ICMD_L2I: /* ..., value ==> ..., value */
791 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
792 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
794 store_reg_to_var_int(iptr->dst, d);
797 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
799 var_to_reg_int(s1, src, REG_ITMP1);
800 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
802 store_reg_to_var_int(iptr->dst, d);
805 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
807 var_to_reg_int(s1, src, REG_ITMP1);
808 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
810 store_reg_to_var_int(iptr->dst, d);
813 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
815 var_to_reg_int(s1, src, REG_ITMP1);
816 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
818 store_reg_to_var_int(iptr->dst, d);
822 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
824 var_to_reg_int(s1, src->prev, REG_ITMP1);
825 var_to_reg_int(s2, src, REG_ITMP2);
826 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
828 store_reg_to_var_int(iptr->dst, d);
831 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
832 /* val.i = constant */
834 var_to_reg_int(s1, src, REG_ITMP1);
835 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
836 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
837 M_IADD_IMM(s1, iptr->val.i, d);
839 ICONST(REG_ITMP2, iptr->val.i);
840 M_IADD(s1, REG_ITMP2, d);
842 store_reg_to_var_int(iptr->dst, d);
845 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
847 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
848 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
849 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
850 M_ADDC(s1, s2, rd->secondregs[d]);
851 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
852 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
854 store_reg_to_var_int(iptr->dst, d);
857 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
858 /* val.l = constant */
860 s3 = iptr->val.l & 0xffffffff;
861 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
862 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
863 if ((s3 >= -32768) && (s3 <= 32767)) {
864 M_ADDIC(s1, s3, rd->secondregs[d]);
866 ICONST(REG_ITMP2, s3);
867 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
869 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
870 s3 = iptr->val.l >> 32;
876 ICONST(REG_ITMP3, s3);
877 M_ADDE(s1, REG_ITMP3, d);
879 store_reg_to_var_int(iptr->dst, d);
882 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
884 var_to_reg_int(s1, src->prev, REG_ITMP1);
885 var_to_reg_int(s2, src, REG_ITMP2);
886 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
888 store_reg_to_var_int(iptr->dst, d);
891 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
892 /* val.i = constant */
894 var_to_reg_int(s1, src, REG_ITMP1);
895 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
896 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
897 M_IADD_IMM(s1, -iptr->val.i, d);
899 ICONST(REG_ITMP2, -iptr->val.i);
900 M_IADD(s1, REG_ITMP2, d);
902 store_reg_to_var_int(iptr->dst, d);
905 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
907 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
908 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
909 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
910 M_SUBC(s1, s2, rd->secondregs[d]);
911 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
912 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
914 store_reg_to_var_int(iptr->dst, d);
917 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
918 /* val.l = constant */
920 s3 = (-iptr->val.l) & 0xffffffff;
921 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
922 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
923 if ((s3 >= -32768) && (s3 <= 32767)) {
924 M_ADDIC(s1, s3, rd->secondregs[d]);
926 ICONST(REG_ITMP2, s3);
927 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
929 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
930 s3 = (-iptr->val.l) >> 32;
936 ICONST(REG_ITMP3, s3);
937 M_ADDE(s1, REG_ITMP3, d);
939 store_reg_to_var_int(iptr->dst, d);
942 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
944 var_to_reg_int(s1, src->prev, REG_ITMP1);
945 var_to_reg_int(s2, src, REG_ITMP2);
946 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
948 store_reg_to_var_int(iptr->dst, d);
951 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
953 var_to_reg_int(s1, src->prev, REG_ITMP1);
954 var_to_reg_int(s2, src, REG_ITMP2);
955 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
959 store_reg_to_var_int(iptr->dst, d);
962 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
964 var_to_reg_int(s1, src->prev, REG_ITMP1);
965 var_to_reg_int(s2, src, REG_ITMP2);
966 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
968 store_reg_to_var_int(iptr->dst, d);
971 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
972 /* val.i = constant */
974 var_to_reg_int(s1, src, REG_ITMP1);
975 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
976 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
977 M_IMUL_IMM(s1, iptr->val.i, d);
980 ICONST(REG_ITMP2, iptr->val.i);
981 M_IMUL(s1, REG_ITMP2, d);
983 store_reg_to_var_int(iptr->dst, d);
986 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
988 var_to_reg_int(s1, src, REG_ITMP1);
989 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
990 M_SRA_IMM(s1, iptr->val.i, d);
992 store_reg_to_var_int(iptr->dst, d);
995 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
997 var_to_reg_int(s1, src->prev, REG_ITMP1);
998 var_to_reg_int(s2, src, REG_ITMP2);
999 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1000 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1001 M_SLL(s1, REG_ITMP3, d);
1002 store_reg_to_var_int(iptr->dst, d);
1005 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1006 /* val.i = constant */
1008 var_to_reg_int(s1, src, REG_ITMP1);
1009 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1010 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1011 store_reg_to_var_int(iptr->dst, d);
1014 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1016 var_to_reg_int(s1, src->prev, REG_ITMP1);
1017 var_to_reg_int(s2, src, REG_ITMP2);
1018 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1019 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1020 M_SRA(s1, REG_ITMP3, d);
1021 store_reg_to_var_int(iptr->dst, d);
1024 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1025 /* val.i = constant */
1027 var_to_reg_int(s1, src, REG_ITMP1);
1028 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1029 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1030 store_reg_to_var_int(iptr->dst, d);
1033 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1035 var_to_reg_int(s1, src->prev, REG_ITMP1);
1036 var_to_reg_int(s2, src, REG_ITMP2);
1037 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1038 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1039 M_SRL(s1, REG_ITMP2, d);
1040 store_reg_to_var_int(iptr->dst, d);
1043 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1044 /* val.i = constant */
1046 var_to_reg_int(s1, src, REG_ITMP1);
1047 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1048 if (iptr->val.i & 0x1f)
1049 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1052 store_reg_to_var_int(iptr->dst, d);
1055 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1057 var_to_reg_int(s1, src->prev, REG_ITMP1);
1058 var_to_reg_int(s2, src, REG_ITMP2);
1059 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1061 store_reg_to_var_int(iptr->dst, d);
1064 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1065 /* val.i = constant */
1067 var_to_reg_int(s1, src, REG_ITMP1);
1068 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1069 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1070 M_AND_IMM(s1, iptr->val.i, d);
1073 else if (iptr->val.i == 0xffffff) {
1074 M_RLWINM(s1, 0, 8, 31, d);
1078 ICONST(REG_ITMP2, iptr->val.i);
1079 M_AND(s1, REG_ITMP2, d);
1081 store_reg_to_var_int(iptr->dst, d);
1084 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1086 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1087 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1088 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1089 M_AND(s1, s2, rd->secondregs[d]);
1090 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1091 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1093 store_reg_to_var_int(iptr->dst, d);
1096 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1097 /* val.l = constant */
1099 s3 = iptr->val.l & 0xffffffff;
1100 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1101 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1102 if ((s3 >= 0) && (s3 <= 65535)) {
1103 M_AND_IMM(s1, s3, rd->secondregs[d]);
1105 ICONST(REG_ITMP2, s3);
1106 M_AND(s1, REG_ITMP2, rd->secondregs[d]);
1108 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1109 s3 = iptr->val.l >> 32;
1110 if ((s3 >= 0) && (s3 <= 65535)) {
1111 M_AND_IMM(s1, s3, d);
1113 ICONST(REG_ITMP3, s3);
1114 M_AND(s1, REG_ITMP3, d);
1116 store_reg_to_var_int(iptr->dst, d);
1119 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1120 /* val.i = constant */
1122 var_to_reg_int(s1, src, REG_ITMP1);
1123 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1124 M_MOV(s1, REG_ITMP2);
1126 M_BGE(1 + 2*(iptr->val.i >= 32768));
1127 if (iptr->val.i >= 32768) {
1128 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1129 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1130 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1132 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1134 int b=0, m = iptr->val.i;
1137 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1139 M_ISUB(s1, REG_ITMP2, d);
1140 store_reg_to_var_int(iptr->dst, d);
1143 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1145 var_to_reg_int(s1, src->prev, REG_ITMP1);
1146 var_to_reg_int(s2, src, REG_ITMP2);
1147 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1149 store_reg_to_var_int(iptr->dst, d);
1152 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1153 /* val.i = constant */
1155 var_to_reg_int(s1, src, REG_ITMP1);
1156 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1157 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1158 M_OR_IMM(s1, iptr->val.i, d);
1161 ICONST(REG_ITMP2, iptr->val.i);
1162 M_OR(s1, REG_ITMP2, d);
1164 store_reg_to_var_int(iptr->dst, d);
1167 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1169 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1170 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1171 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1172 M_OR(s1, s2, rd->secondregs[d]);
1173 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1174 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1176 store_reg_to_var_int(iptr->dst, d);
1179 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1180 /* val.l = constant */
1182 s3 = iptr->val.l & 0xffffffff;
1183 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1184 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1185 if ((s3 >= 0) && (s3 <= 65535)) {
1186 M_OR_IMM(s1, s3, rd->secondregs[d]);
1189 ICONST(REG_ITMP2, s3);
1190 M_OR(s1, REG_ITMP2, rd->secondregs[d]);
1192 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1193 s3 = iptr->val.l >> 32;
1194 if ((s3 >= 0) && (s3 <= 65535)) {
1195 M_OR_IMM(s1, s3, d);
1198 ICONST(REG_ITMP3, s3);
1199 M_OR(s1, REG_ITMP3, d);
1201 store_reg_to_var_int(iptr->dst, d);
1204 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1206 var_to_reg_int(s1, src->prev, REG_ITMP1);
1207 var_to_reg_int(s2, src, REG_ITMP2);
1208 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1210 store_reg_to_var_int(iptr->dst, d);
1213 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1214 /* val.i = constant */
1216 var_to_reg_int(s1, src, REG_ITMP1);
1217 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1218 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1219 M_XOR_IMM(s1, iptr->val.i, d);
1222 ICONST(REG_ITMP2, iptr->val.i);
1223 M_XOR(s1, REG_ITMP2, d);
1225 store_reg_to_var_int(iptr->dst, d);
1228 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1230 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1231 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1232 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1233 M_XOR(s1, s2, rd->secondregs[d]);
1234 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1235 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1237 store_reg_to_var_int(iptr->dst, d);
1240 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1241 /* val.l = constant */
1243 s3 = iptr->val.l & 0xffffffff;
1244 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1245 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1246 if ((s3 >= 0) && (s3 <= 65535)) {
1247 M_XOR_IMM(s1, s3, rd->secondregs[d]);
1250 ICONST(REG_ITMP2, s3);
1251 M_XOR(s1, REG_ITMP2, rd->secondregs[d]);
1253 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1254 s3 = iptr->val.l >> 32;
1255 if ((s3 >= 0) && (s3 <= 65535)) {
1256 M_XOR_IMM(s1, s3, d);
1259 ICONST(REG_ITMP3, s3);
1260 M_XOR(s1, REG_ITMP3, d);
1262 store_reg_to_var_int(iptr->dst, d);
1265 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1267 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1268 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1269 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1272 (d==s1 || d==s2 || d==rd->secondregs[s1] || d==rd->secondregs[s2]);
1273 int dreg = tempreg ? REG_ITMP1 : d;
1275 M_IADD_IMM(REG_ZERO, 1, dreg);
1280 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1281 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1285 M_IADD_IMM(dreg, -1, dreg);
1286 M_IADD_IMM(dreg, -1, dreg);
1287 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1288 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1291 store_reg_to_var_int(iptr->dst, d);
1294 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1295 /* op1 = variable, val.i = constant */
1297 var = &(rd->locals[iptr->op1][TYPE_INT]);
1298 if (var->flags & INMEMORY) {
1300 M_ILD(s1, REG_SP, var->regoff * 4);
1308 M_ADDIS(s1, m>>16, s1);
1310 M_IADD_IMM(s1, m&0xffff, s1);
1312 if (var->flags & INMEMORY)
1313 M_IST(s1, REG_SP, var->regoff * 4);
1317 /* floating operations ************************************************/
1319 case ICMD_FNEG: /* ..., value ==> ..., - value */
1321 var_to_reg_flt(s1, src, REG_FTMP1);
1322 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1324 store_reg_to_var_flt(iptr->dst, d);
1327 case ICMD_DNEG: /* ..., value ==> ..., - value */
1329 var_to_reg_flt(s1, src, REG_FTMP1);
1330 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1332 store_reg_to_var_flt(iptr->dst, d);
1335 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1337 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1338 var_to_reg_flt(s2, src, REG_FTMP2);
1339 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1341 store_reg_to_var_flt(iptr->dst, d);
1344 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1346 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1347 var_to_reg_flt(s2, src, REG_FTMP2);
1348 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1350 store_reg_to_var_flt(iptr->dst, d);
1353 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1355 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1356 var_to_reg_flt(s2, src, REG_FTMP2);
1357 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1359 store_reg_to_var_flt(iptr->dst, d);
1362 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1364 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1365 var_to_reg_flt(s2, src, REG_FTMP2);
1366 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1368 store_reg_to_var_flt(iptr->dst, d);
1371 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1373 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1374 var_to_reg_flt(s2, src, REG_FTMP2);
1375 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1377 store_reg_to_var_flt(iptr->dst, d);
1380 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1382 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1383 var_to_reg_flt(s2, src, REG_FTMP2);
1384 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1386 store_reg_to_var_flt(iptr->dst, d);
1389 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1391 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1392 var_to_reg_flt(s2, src, REG_FTMP2);
1393 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1395 store_reg_to_var_flt(iptr->dst, d);
1398 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1400 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1401 var_to_reg_flt(s2, src, REG_FTMP2);
1402 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1404 store_reg_to_var_flt(iptr->dst, d);
1407 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1409 var_to_reg_flt(s1, src, REG_FTMP1);
1410 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1412 a = dseg_addfloat(cd, 0.0);
1413 M_FLD(REG_FTMP2, REG_PV, a);
1414 M_FCMPU(s1, REG_FTMP2);
1416 a = dseg_adds4(cd, 0);
1417 M_CVTDL_C(s1, REG_FTMP1);
1418 M_LDA (REG_ITMP1, REG_PV, a);
1419 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1420 M_ILD (d, REG_PV, a);
1421 store_reg_to_var_int(iptr->dst, d);
1424 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1426 var_to_reg_flt(s1, src, REG_FTMP1);
1427 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1429 store_reg_to_var_flt(iptr->dst, d);
1432 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1434 var_to_reg_flt(s1, src, REG_FTMP1);
1435 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1437 store_reg_to_var_flt(iptr->dst, d);
1440 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1442 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1443 var_to_reg_flt(s2, src, REG_FTMP2);
1444 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1446 M_IADD_IMM(0, -1, d);
1449 M_IADD_IMM(0, 0, d);
1451 M_IADD_IMM(0, 1, d);
1452 store_reg_to_var_int(iptr->dst, d);
1455 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1457 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1458 var_to_reg_flt(s2, src, REG_FTMP2);
1459 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1461 M_IADD_IMM(0, 1, d);
1464 M_IADD_IMM(0, 0, d);
1466 M_IADD_IMM(0, -1, d);
1467 store_reg_to_var_int(iptr->dst, d);
1471 /* memory operations **************************************************/
1473 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1475 var_to_reg_int(s1, src, REG_ITMP1);
1476 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1477 gen_nullptr_check(s1);
1478 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1479 store_reg_to_var_int(iptr->dst, d);
1482 case ICMD_AALOAD: /* ..., 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_ITMP3);
1487 if (iptr->op1 == 0) {
1488 gen_nullptr_check(s1);
1491 M_SLL_IMM(s2, 2, REG_ITMP2);
1492 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1493 M_LWZX(d, s1, REG_ITMP2);
1494 store_reg_to_var_int(iptr->dst, d);
1497 case ICMD_LALOAD: /* ..., 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_SLL_IMM(s2, 3, REG_ITMP2);
1507 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1508 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1509 M_ILD(rd->secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0]) + 4);
1510 store_reg_to_var_int(iptr->dst, d);
1513 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1515 var_to_reg_int(s1, src->prev, REG_ITMP1);
1516 var_to_reg_int(s2, src, REG_ITMP2);
1517 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1518 if (iptr->op1 == 0) {
1519 gen_nullptr_check(s1);
1522 M_SLL_IMM(s2, 2, REG_ITMP2);
1523 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1524 M_LWZX(d, s1, REG_ITMP2);
1525 store_reg_to_var_int(iptr->dst, d);
1528 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1530 var_to_reg_int(s1, src->prev, REG_ITMP1);
1531 var_to_reg_int(s2, src, REG_ITMP2);
1532 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1533 if (iptr->op1 == 0) {
1534 gen_nullptr_check(s1);
1537 M_SLL_IMM(s2, 2, REG_ITMP2);
1538 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1539 M_LFSX(d, s1, REG_ITMP2);
1540 store_reg_to_var_flt(iptr->dst, d);
1543 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1545 var_to_reg_int(s1, src->prev, REG_ITMP1);
1546 var_to_reg_int(s2, src, REG_ITMP2);
1547 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1548 if (iptr->op1 == 0) {
1549 gen_nullptr_check(s1);
1552 M_SLL_IMM(s2, 3, REG_ITMP2);
1553 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1554 M_LFDX(d, s1, REG_ITMP2);
1555 store_reg_to_var_flt(iptr->dst, d);
1558 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1560 var_to_reg_int(s1, src->prev, REG_ITMP1);
1561 var_to_reg_int(s2, src, REG_ITMP2);
1562 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1563 if (iptr->op1 == 0) {
1564 gen_nullptr_check(s1);
1567 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1568 M_LBZX(d, s1, REG_ITMP2);
1570 store_reg_to_var_int(iptr->dst, d);
1573 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1575 var_to_reg_int(s1, src->prev, REG_ITMP1);
1576 var_to_reg_int(s2, src, REG_ITMP2);
1577 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1578 if (iptr->op1 == 0) {
1579 gen_nullptr_check(s1);
1582 M_SLL_IMM(s2, 1, REG_ITMP2);
1583 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1584 M_LHAX(d, s1, REG_ITMP2);
1585 store_reg_to_var_int(iptr->dst, d);
1588 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1590 var_to_reg_int(s1, src->prev, REG_ITMP1);
1591 var_to_reg_int(s2, src, REG_ITMP2);
1592 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1593 if (iptr->op1 == 0) {
1594 gen_nullptr_check(s1);
1597 M_SLL_IMM(s2, 1, REG_ITMP2);
1598 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1599 M_LHZX(d, s1, REG_ITMP2);
1600 store_reg_to_var_int(iptr->dst, d);
1603 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1605 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1606 var_to_reg_int(s2, src->prev, REG_ITMP2);
1607 if (iptr->op1 == 0) {
1608 gen_nullptr_check(s1);
1611 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1612 M_SLL_IMM(s2, 3, REG_ITMP2);
1613 M_IADD_IMM(REG_ITMP2, OFFSET(java_longarray, data[0]), REG_ITMP2);
1614 M_STWX(s3, s1, REG_ITMP2);
1615 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1616 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1617 M_STWX(s3, s1, REG_ITMP2);
1620 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1622 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1623 var_to_reg_int(s2, src->prev, REG_ITMP2);
1624 if (iptr->op1 == 0) {
1625 gen_nullptr_check(s1);
1628 var_to_reg_int(s3, src, REG_ITMP3);
1629 M_SLL_IMM(s2, 2, REG_ITMP2);
1630 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1631 M_STWX(s3, s1, REG_ITMP2);
1634 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1636 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1637 var_to_reg_int(s2, src->prev, REG_ITMP2);
1638 if (iptr->op1 == 0) {
1639 gen_nullptr_check(s1);
1642 var_to_reg_flt(s3, src, REG_FTMP3);
1643 M_SLL_IMM(s2, 2, REG_ITMP2);
1644 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1645 M_STFSX(s3, s1, REG_ITMP2);
1648 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1650 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1651 var_to_reg_int(s2, src->prev, REG_ITMP2);
1652 if (iptr->op1 == 0) {
1653 gen_nullptr_check(s1);
1656 var_to_reg_flt(s3, src, REG_FTMP3);
1657 M_SLL_IMM(s2, 3, REG_ITMP2);
1658 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1659 M_STFDX(s3, s1, REG_ITMP2);
1662 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1664 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1665 var_to_reg_int(s2, src->prev, REG_ITMP2);
1666 if (iptr->op1 == 0) {
1667 gen_nullptr_check(s1);
1670 var_to_reg_int(s3, src, REG_ITMP3);
1671 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1672 M_STBX(s3, s1, REG_ITMP2);
1675 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1677 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1678 var_to_reg_int(s2, src->prev, REG_ITMP2);
1679 if (iptr->op1 == 0) {
1680 gen_nullptr_check(s1);
1683 var_to_reg_int(s3, src, REG_ITMP3);
1684 M_SLL_IMM(s2, 1, REG_ITMP2);
1685 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1686 M_STHX(s3, s1, REG_ITMP2);
1689 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1691 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1692 var_to_reg_int(s2, src->prev, REG_ITMP2);
1693 if (iptr->op1 == 0) {
1694 gen_nullptr_check(s1);
1697 var_to_reg_int(s3, src, REG_ITMP3);
1698 M_SLL_IMM(s2, 1, REG_ITMP2);
1699 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1700 M_STHX(s3, s1, REG_ITMP2);
1704 case ICMD_GETSTATIC: /* ... ==> ..., value */
1705 /* op1 = type, val.a = field address */
1708 codegen_addpatchref(cd, mcodeptr,
1709 PATCHER_get_putstatic,
1710 (unresolved_field *) iptr->target);
1712 if (showdisassemble)
1718 fieldinfo *fi = iptr->val.a;
1720 if (!fi->class->initialized) {
1721 codegen_addpatchref(cd, mcodeptr,
1722 PATCHER_clinit, fi->class);
1724 if (showdisassemble)
1728 a = (ptrint) &(fi->value);
1731 a = dseg_addaddress(cd, a);
1732 M_ALD(REG_ITMP1, REG_PV, a);
1733 switch (iptr->op1) {
1735 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1736 M_ILD(d, REG_ITMP1, 0);
1737 store_reg_to_var_int(iptr->dst, d);
1740 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1741 M_ILD(d, REG_ITMP1, 0);
1742 M_ILD(rd->secondregs[d], REG_ITMP1, 4);
1743 store_reg_to_var_int(iptr->dst, d);
1746 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1747 M_ALD(d, REG_ITMP1, 0);
1748 store_reg_to_var_int(iptr->dst, d);
1751 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1752 M_FLD(d, REG_ITMP1, 0);
1753 store_reg_to_var_flt(iptr->dst, d);
1756 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1757 M_DLD(d, REG_ITMP1, 0);
1758 store_reg_to_var_flt(iptr->dst, d);
1763 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1764 /* op1 = type, val.a = field address */
1768 codegen_addpatchref(cd, mcodeptr,
1769 PATCHER_get_putstatic,
1770 (unresolved_field *) iptr->target);
1772 if (showdisassemble)
1778 fieldinfo *fi = iptr->val.a;
1780 if (!fi->class->initialized) {
1781 codegen_addpatchref(cd, mcodeptr,
1782 PATCHER_clinit, fi->class);
1784 if (showdisassemble)
1788 a = (ptrint) &(fi->value);
1791 a = dseg_addaddress(cd, a);
1792 M_ALD(REG_ITMP1, REG_PV, a);
1793 switch (iptr->op1) {
1795 var_to_reg_int(s2, src, REG_ITMP2);
1796 M_IST(s2, REG_ITMP1, 0);
1799 var_to_reg_int(s2, src, REG_ITMP3);
1800 M_IST(s2, REG_ITMP1, 0);
1801 M_IST(rd->secondregs[s2], REG_ITMP1, 4);
1804 var_to_reg_int(s2, src, REG_ITMP2);
1805 M_AST(s2, REG_ITMP1, 0);
1808 var_to_reg_flt(s2, src, REG_FTMP2);
1809 M_FST(s2, REG_ITMP1, 0);
1812 var_to_reg_flt(s2, src, REG_FTMP2);
1813 M_DST(s2, REG_ITMP1, 0);
1819 case ICMD_GETFIELD: /* ... ==> ..., value */
1820 /* op1 = type, val.i = field offset */
1822 var_to_reg_int(s1, src, REG_ITMP1);
1823 gen_nullptr_check(s1);
1826 codegen_addpatchref(cd, mcodeptr,
1827 PATCHER_get_putfield,
1828 (unresolved_field *) iptr->target);
1830 if (showdisassemble)
1836 a = ((fieldinfo *) (iptr->val.a))->offset;
1839 switch (iptr->op1) {
1841 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1843 store_reg_to_var_int(iptr->dst, d);
1846 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1848 M_ILD(rd->secondregs[d], s1, a + 4);
1849 store_reg_to_var_int(iptr->dst, d);
1852 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1854 store_reg_to_var_int(iptr->dst, d);
1857 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1859 store_reg_to_var_flt(iptr->dst, d);
1862 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1864 store_reg_to_var_flt(iptr->dst, d);
1869 case ICMD_PUTFIELD: /* ..., value ==> ... */
1870 /* op1 = type, val.i = field offset */
1872 var_to_reg_int(s1, src->prev, REG_ITMP1);
1873 gen_nullptr_check(s1);
1875 if (!IS_FLT_DBL_TYPE(iptr->op1)) {
1876 var_to_reg_int(s2, src, REG_ITMP2);
1878 var_to_reg_flt(s2, src, REG_FTMP2);
1882 codegen_addpatchref(cd, mcodeptr,
1883 PATCHER_get_putfield,
1884 (unresolved_field *) iptr->target);
1886 if (showdisassemble)
1892 a = ((fieldinfo *) (iptr->val.a))->offset;
1895 switch (iptr->op1) {
1901 M_IST(rd->secondregs[s2], s1, a + 4);
1916 /* branch operations **************************************************/
1918 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1920 a = dseg_addaddress(cd, asm_handle_exception);
1921 M_ALD(REG_ITMP2, REG_PV, a);
1923 var_to_reg_int(s1, src, REG_ITMP1);
1924 M_INTMOVE(s1, REG_ITMP1_XPTR);
1926 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
1927 M_BL(0); /* get current PC */
1928 M_MFLR(REG_ITMP2_XPC);
1929 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
1930 M_RTS; /* jump to CTR */
1935 case ICMD_GOTO: /* ... ==> ... */
1936 /* op1 = target JavaVM pc */
1938 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
1942 case ICMD_JSR: /* ... ==> ... */
1943 /* op1 = target JavaVM pc */
1945 if (m->isleafmethod) M_MFLR(REG_ITMP2);
1948 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
1949 if (m->isleafmethod) M_MTLR(REG_ITMP2);
1951 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
1954 case ICMD_RET: /* ... ==> ... */
1955 /* op1 = local variable */
1957 var = &(rd->locals[iptr->op1][TYPE_ADR]);
1958 if (var->flags & INMEMORY) {
1959 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
1962 M_MTCTR(var->regoff);
1967 case ICMD_IFNULL: /* ..., value ==> ... */
1968 /* op1 = target JavaVM pc */
1970 var_to_reg_int(s1, src, REG_ITMP1);
1973 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
1976 case ICMD_IFNONNULL: /* ..., value ==> ... */
1977 /* op1 = target JavaVM pc */
1979 var_to_reg_int(s1, src, REG_ITMP1);
1982 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
1990 case ICMD_IFEQ: /* ..., value ==> ... */
1991 /* op1 = target JavaVM pc, val.i = constant */
1993 var_to_reg_int(s1, src, REG_ITMP1);
1994 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1995 M_CMPI(s1, iptr->val.i);
1998 ICONST(REG_ITMP2, iptr->val.i);
1999 M_CMP(s1, REG_ITMP2);
2022 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2026 case ICMD_IF_LEQ: /* ..., value ==> ... */
2027 /* op1 = target JavaVM pc, val.l = constant */
2029 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2030 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2031 if (iptr->val.l == 0) {
2032 M_OR(s1, s2, REG_ITMP3);
2033 M_CMPI(REG_ITMP3, 0);
2035 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2036 M_CMPI(s2, (u4) (iptr->val.l >> 32));
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 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2045 M_CMP(s1, REG_ITMP3)
2048 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2051 case ICMD_IF_LLT: /* ..., value ==> ... */
2052 /* op1 = target JavaVM pc, val.l = constant */
2053 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2054 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2055 /* if (iptr->val.l == 0) { */
2056 /* M_OR(s1, s2, REG_ITMP3); */
2057 /* M_CMPI(REG_ITMP3, 0); */
2060 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2061 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2063 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
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 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2073 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2074 M_CMP(s1, REG_ITMP3)
2077 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2080 case ICMD_IF_LLE: /* ..., value ==> ... */
2081 /* op1 = target JavaVM pc, val.l = constant */
2083 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2084 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2085 /* if (iptr->val.l == 0) { */
2086 /* M_OR(s1, s2, REG_ITMP3); */
2087 /* M_CMPI(REG_ITMP3, 0); */
2090 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2091 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2093 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2095 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2098 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2099 M_CMP(s2, REG_ITMP3);
2101 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2103 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2104 M_CMP(s1, REG_ITMP3)
2107 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2110 case ICMD_IF_LNE: /* ..., value ==> ... */
2111 /* op1 = target JavaVM pc, val.l = constant */
2113 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2114 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2115 if (iptr->val.l == 0) {
2116 M_OR(s1, s2, REG_ITMP3);
2117 M_CMPI(REG_ITMP3, 0);
2119 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2120 M_CMPI(s2, (u4) (iptr->val.l >> 32));
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 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2129 M_CMP(s1, REG_ITMP3)
2132 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2135 case ICMD_IF_LGT: /* ..., value ==> ... */
2136 /* op1 = target JavaVM pc, val.l = constant */
2138 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2139 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2140 /* if (iptr->val.l == 0) { */
2141 /* M_OR(s1, s2, REG_ITMP3); */
2142 /* M_CMPI(REG_ITMP3, 0); */
2145 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2146 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2148 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2150 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2153 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2154 M_CMP(s2, REG_ITMP3);
2156 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2158 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2159 M_CMP(s1, REG_ITMP3)
2162 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2165 case ICMD_IF_LGE: /* ..., value ==> ... */
2166 /* op1 = target JavaVM pc, val.l = constant */
2167 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2168 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2169 /* if (iptr->val.l == 0) { */
2170 /* M_OR(s1, s2, REG_ITMP3); */
2171 /* M_CMPI(REG_ITMP3, 0); */
2174 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2175 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2177 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2179 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2182 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2183 M_CMP(s2, REG_ITMP3);
2185 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2187 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2188 M_CMP(s1, REG_ITMP3)
2191 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2195 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2196 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2197 case ICMD_IF_ACMPEQ:
2199 var_to_reg_int(s1, src->prev, REG_ITMP1);
2200 var_to_reg_int(s2, src, REG_ITMP2);
2203 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2206 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2207 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2208 case ICMD_IF_ACMPNE:
2210 var_to_reg_int(s1, src->prev, REG_ITMP1);
2211 var_to_reg_int(s2, src, REG_ITMP2);
2214 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2217 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2218 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2220 var_to_reg_int(s1, src->prev, REG_ITMP1);
2221 var_to_reg_int(s2, src, REG_ITMP2);
2224 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2227 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2228 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2230 var_to_reg_int(s1, src->prev, REG_ITMP1);
2231 var_to_reg_int(s2, src, REG_ITMP2);
2234 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2237 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2238 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2240 var_to_reg_int(s1, src->prev, REG_ITMP1);
2241 var_to_reg_int(s2, src, REG_ITMP2);
2244 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2247 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2248 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2250 var_to_reg_int(s1, src->prev, REG_ITMP1);
2251 var_to_reg_int(s2, src, REG_ITMP2);
2254 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2257 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2260 var_to_reg_int(s1, src, REG_RESULT);
2261 M_TINTMOVE(src->type, s1, REG_RESULT);
2262 goto nowperformreturn;
2264 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2266 var_to_reg_flt(s1, src, REG_FRESULT);
2267 M_FLTMOVE(s1, REG_FRESULT);
2268 goto nowperformreturn;
2270 case ICMD_RETURN: /* ... ==> ... */
2276 p = parentargs_base;
2278 /* call trace function */
2282 M_LDA(REG_SP, REG_SP, -10 * 8);
2283 M_DST(REG_FRESULT, REG_SP, 48+0);
2284 M_IST(REG_RESULT, REG_SP, 48+8);
2285 M_AST(REG_ITMP3, REG_SP, 48+12);
2286 M_IST(REG_RESULT2, REG_SP, 48+16);
2288 /* keep this order */
2289 switch (iptr->opc) {
2292 #if defined(__DARWIN__)
2293 M_MOV(REG_RESULT, rd->argintregs[2]);
2294 M_CLR(rd->argintregs[1]);
2296 M_MOV(REG_RESULT, rd->argintregs[3]);
2297 M_CLR(rd->argintregs[2]);
2302 #if defined(__DARWIN__)
2303 M_MOV(REG_RESULT2, rd->argintregs[2]);
2304 M_MOV(REG_RESULT, rd->argintregs[1]);
2306 M_MOV(REG_RESULT2, rd->argintregs[3]);
2307 M_MOV(REG_RESULT, rd->argintregs[2]);
2312 a = dseg_addaddress(cd, m);
2313 M_ALD(rd->argintregs[0], REG_PV, a);
2315 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2316 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2317 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2318 M_ALD(REG_ITMP2, REG_PV, a);
2321 M_DLD(REG_FRESULT, REG_SP, 48+0);
2322 M_ILD(REG_RESULT, REG_SP, 48+8);
2323 M_ALD(REG_ITMP3, REG_SP, 48+12);
2324 M_ILD(REG_RESULT2, REG_SP, 48+16);
2325 M_LDA(REG_SP, REG_SP, 10 * 8);
2329 #if defined(USE_THREADS)
2330 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2331 /* we need to save the proper return value */
2332 switch (iptr->opc) {
2335 M_IST(REG_RESULT , REG_SP, rd->maxmemuse * 4 + 4);
2337 M_IST(REG_RESULT2, REG_SP, rd->maxmemuse * 4 + 8);
2340 M_FST(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2343 M_DST(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2347 a = dseg_addaddress(cd, BUILTIN_monitorexit);
2348 M_ALD(REG_ITMP3, REG_PV, a);
2350 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
2353 /* and now restore the proper return value */
2354 switch (iptr->opc) {
2357 M_ILD(REG_RESULT , REG_SP, rd->maxmemuse * 4 + 4);
2359 M_ILD(REG_RESULT2, REG_SP, rd->maxmemuse * 4 + 8);
2362 M_FLD(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2365 M_DLD(REG_FRESULT, REG_SP, rd->maxmemuse * 4 + 4);
2371 /* restore return address */
2373 if (!m->isleafmethod) {
2374 M_ALD(REG_ITMP3, REG_SP, p * 4 + LA_LR_OFFSET);
2378 /* restore saved registers */
2380 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2381 p--; M_ILD(rd->savintregs[i], REG_SP, p * 4);
2383 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2384 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, p * 4);
2387 /* deallocate stack */
2389 if (parentargs_base)
2390 M_LDA(REG_SP, REG_SP, parentargs_base * 4);
2398 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2403 tptr = (void **) iptr->target;
2405 s4ptr = iptr->val.a;
2406 l = s4ptr[1]; /* low */
2407 i = s4ptr[2]; /* high */
2409 var_to_reg_int(s1, src, REG_ITMP1);
2411 M_INTMOVE(s1, REG_ITMP1);
2412 } else if (l <= 32768) {
2413 M_LDA(REG_ITMP1, s1, -l);
2415 ICONST(REG_ITMP2, l);
2416 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2422 M_CMPUI(REG_ITMP1, i - 1);
2425 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2426 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2428 /* build jump table top down and use address of lowest entry */
2430 /* s4ptr += 3 + i; */
2434 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2435 dseg_addtarget(cd, (basicblock *) tptr[0]);
2440 /* length of dataseg after last dseg_addtarget is used by load */
2442 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2443 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2444 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2451 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2453 s4 i, l, val, *s4ptr;
2456 tptr = (void **) iptr->target;
2458 s4ptr = iptr->val.a;
2459 l = s4ptr[0]; /* default */
2460 i = s4ptr[1]; /* count */
2462 MCODECHECK((i<<2)+8);
2463 var_to_reg_int(s1, src, REG_ITMP1);
2469 if ((val >= -32768) && (val <= 32767)) {
2473 a = dseg_adds4(cd, val);
2474 M_ILD(REG_ITMP2, REG_PV, a);
2475 M_CMP(s1, REG_ITMP2);
2478 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2479 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2483 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2485 tptr = (void **) iptr->target;
2486 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2493 case ICMD_BUILTIN: /* ..., [arg1, [arg2 ...]] ==> ... */
2494 /* op1 = arg count val.a = builtintable entry */
2500 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2501 /* op1 = arg count, val.a = method pointer */
2503 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2504 case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer */
2505 case ICMD_INVOKEINTERFACE:
2510 md = lm->parseddesc;
2512 unresolved_method *um = iptr->target;
2513 md = um->methodref->parseddesc.md;
2519 MCODECHECK((s3 << 1) + 64);
2521 /* copy arguments to registers or stack location */
2523 for (s3 = s3 - 1; s3 >= 0; s3--, src = src->prev) {
2524 if (src->varkind == ARGVAR)
2526 if (IS_INT_LNG_TYPE(src->type)) {
2527 if (!md->params[s3].inmemory) {
2528 s1 = rd->argintregs[md->params[s3].regoff];
2529 var_to_reg_int(d, src, s1);
2530 M_TINTMOVE(src->type, d, s1);
2532 var_to_reg_int(d, src, REG_ITMP1);
2533 M_IST(d, REG_SP, md->params[s3].regoff * 4);
2534 if (IS_2_WORD_TYPE(src->type))
2535 M_IST(rd->secondregs[d],
2536 REG_SP, md->params[s3].regoff * 4 + 4);
2540 if (!md->params[s3].inmemory) {
2541 s1 = rd->argfltregs[md->params[s3].regoff];
2542 var_to_reg_flt(d, src, s1);
2545 var_to_reg_flt(d, src, REG_FTMP1);
2546 if (IS_2_WORD_TYPE(src->type))
2547 M_DST(d, REG_SP, md->params[s3].regoff * 4);
2549 M_FST(d, REG_SP, md->params[s3].regoff * 4);
2554 switch (iptr->opc) {
2557 codegen_addpatchref(cd, mcodeptr, bte->fp, iptr->target);
2559 if (showdisassemble)
2565 a = (ptrint) bte->fp;
2568 a = dseg_addaddress(cd, a);
2569 d = md->returntype.type;
2571 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2574 case ICMD_INVOKESPECIAL:
2575 gen_nullptr_check(rd->argintregs[0]);
2576 M_ILD(REG_ITMP1, rd->argintregs[0], 0); /* hardware nullptr */
2579 case ICMD_INVOKESTATIC:
2581 unresolved_method *um = iptr->target;
2583 codegen_addpatchref(cd, mcodeptr,
2584 PATCHER_invokestatic_special, um);
2586 if (showdisassemble)
2590 d = md->returntype.type;
2593 a = (ptrint) lm->stubroutine;
2594 d = md->returntype.type;
2597 a = dseg_addaddress(cd, a);
2598 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2601 case ICMD_INVOKEVIRTUAL:
2602 gen_nullptr_check(rd->argintregs[0]);
2605 unresolved_method *um = iptr->target;
2607 codegen_addpatchref(cd, mcodeptr,
2608 PATCHER_invokevirtual, um);
2610 if (showdisassemble)
2614 d = md->returntype.type;
2617 s1 = OFFSET(vftbl_t, table[0]) +
2618 sizeof(methodptr) * lm->vftblindex;
2619 d = md->returntype.type;
2622 M_ALD(REG_METHODPTR, rd->argintregs[0],
2623 OFFSET(java_objectheader, vftbl));
2624 M_ALD(REG_PV, REG_METHODPTR, s1);
2627 case ICMD_INVOKEINTERFACE:
2628 gen_nullptr_check(rd->argintregs[0]);
2631 unresolved_method *um = iptr->target;
2633 codegen_addpatchref(cd, mcodeptr,
2634 PATCHER_invokeinterface, um);
2636 if (showdisassemble)
2641 d = md->returntype.type;
2644 s1 = OFFSET(vftbl_t, interfacetable[0]) -
2645 sizeof(methodptr*) * lm->class->index;
2647 s2 = sizeof(methodptr) * (lm - lm->class->methods);
2649 d = md->returntype.type;
2652 M_ALD(REG_METHODPTR, rd->argintregs[0],
2653 OFFSET(java_objectheader, vftbl));
2654 M_ALD(REG_METHODPTR, REG_METHODPTR, s1);
2655 M_ALD(REG_PV, REG_METHODPTR, s2);
2664 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2666 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2668 s4 ml = -s1, mh = 0;
2669 while (ml < -32768) { ml += 65536; mh--; }
2670 M_LDA(REG_PV, REG_ITMP1, ml);
2671 M_LDAH(REG_PV, REG_PV, mh);
2674 /* d contains return type */
2676 if (d != TYPE_VOID) {
2677 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2678 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2679 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2680 store_reg_to_var_int(iptr->dst, s1);
2683 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2684 M_FLTMOVE(REG_FRESULT, s1);
2685 store_reg_to_var_flt(iptr->dst, s1);
2691 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2693 /* op1: 0 == array, 1 == class */
2694 /* val.a: (classinfo*) superclass */
2696 /* superclass is an interface:
2698 * OK if ((sub == NULL) ||
2699 * (sub->vftbl->interfacetablelength > super->index) &&
2700 * (sub->vftbl->interfacetable[-super->index] != NULL));
2702 * superclass is a class:
2704 * OK if ((sub == NULL) || (0
2705 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2706 * super->vftbl->diffvall));
2711 vftbl_t *supervftbl;
2714 super = (classinfo *) iptr->val.a;
2721 superindex = super->index;
2722 supervftbl = super->vftbl;
2725 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2726 codegen_threadcritrestart(cd, (u1 *) mcodeptr - cd->mcodebase);
2728 var_to_reg_int(s1, src, REG_ITMP1);
2730 /* calculate interface checkcast code size */
2734 s2 += (showdisassemble ? 1 : 0);
2736 /* calculate class checkcast code size */
2738 s3 = 8 + (s1 == REG_ITMP1);
2740 s3 += (showdisassemble ? 1 : 0);
2742 /* if class is not resolved, check which code to call */
2746 M_BEQ(3 + (showdisassemble ? 1 : 0) + s2 + 1 + s3);
2748 codegen_addpatchref(cd, mcodeptr,
2749 PATCHER_checkcast_instanceof_flags,
2750 (constant_classref *) iptr->target);
2752 if (showdisassemble)
2755 a = dseg_adds4(cd, 0); /* super->flags */
2756 M_ILD(REG_ITMP2, REG_PV, a);
2757 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2761 /* interface checkcast code */
2763 if (!super || (super->flags & ACC_INTERFACE)) {
2769 codegen_addpatchref(cd, mcodeptr,
2770 PATCHER_checkcast_instanceof_interface,
2771 (constant_classref *) iptr->target);
2773 if (showdisassemble)
2777 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2778 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2779 M_LDATST(REG_ITMP3, REG_ITMP3, -superindex);
2781 codegen_addxcastrefs(cd, mcodeptr);
2782 M_ALD(REG_ITMP3, REG_ITMP2,
2783 OFFSET(vftbl_t, interfacetable[0]) -
2784 superindex * sizeof(methodptr*));
2787 codegen_addxcastrefs(cd, mcodeptr);
2793 /* class checkcast code */
2795 if (!super || !(super->flags & ACC_INTERFACE)) {
2801 codegen_addpatchref(cd, mcodeptr,
2802 PATCHER_checkcast_class,
2803 (constant_classref *) iptr->target);
2805 if (showdisassemble)
2809 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2810 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2811 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
2813 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2814 a = dseg_addaddress(cd, supervftbl);
2815 M_ALD(REG_ITMP2, REG_PV, a);
2816 if (s1 != REG_ITMP1) {
2817 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2818 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2819 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2820 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2822 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2824 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2825 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2826 M_ALD(REG_ITMP2, REG_PV, a);
2827 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2828 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2829 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2832 M_CMPU(REG_ITMP3, REG_ITMP2);
2834 codegen_addxcastrefs(cd, mcodeptr);
2836 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2838 store_reg_to_var_int(iptr->dst, d);
2842 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2844 /* op1: 0 == array, 1 == class */
2845 /* val.a: (classinfo*) superclass */
2847 /* superclass is an interface:
2849 * return (sub != NULL) &&
2850 * (sub->vftbl->interfacetablelength > super->index) &&
2851 * (sub->vftbl->interfacetable[-super->index] != NULL);
2853 * superclass is a class:
2855 * return ((sub != NULL) && (0
2856 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2857 * super->vftbl->diffvall));
2862 vftbl_t *supervftbl;
2865 super = (classinfo *) iptr->val.a;
2872 superindex = super->index;
2873 supervftbl = super->vftbl;
2876 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2877 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2879 var_to_reg_int(s1, src, REG_ITMP1);
2880 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2882 M_MOV(s1, REG_ITMP1);
2886 /* calculate interface instanceof code size */
2890 s2 += (showdisassemble ? 1 : 0);
2892 /* calculate class instanceof code size */
2896 s3 += (showdisassemble ? 1 : 0);
2900 /* if class is not resolved, check which code to call */
2904 M_BEQ(3 + (showdisassemble ? 1 : 0) + s2 + 1 + s3);
2906 codegen_addpatchref(cd, mcodeptr,
2907 PATCHER_checkcast_instanceof_flags,
2908 (constant_classref *) iptr->target);
2910 if (showdisassemble)
2913 a = dseg_adds4(cd, 0); /* super->flags */
2914 M_ILD(REG_ITMP2, REG_PV, a);
2915 M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
2919 /* interface instanceof code */
2921 if (!super || (super->flags & ACC_INTERFACE)) {
2927 codegen_addpatchref(cd, mcodeptr,
2928 PATCHER_checkcast_instanceof_interface,
2929 (constant_classref *) iptr->target);
2931 if (showdisassemble)
2935 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2936 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2937 M_LDATST(REG_ITMP2, REG_ITMP2, -superindex);
2939 M_ALD(REG_ITMP1, REG_ITMP1,
2940 OFFSET(vftbl_t, interfacetable[0]) -
2941 superindex * sizeof(methodptr*));
2945 M_IADD_IMM(REG_ZERO, 1, d);
2951 /* class instanceof code */
2953 if (!super || !(super->flags & ACC_INTERFACE)) {
2959 codegen_addpatchref(cd, mcodeptr,
2960 PATCHER_instanceof_class,
2961 (constant_classref *) iptr->target);
2963 if (showdisassemble) {
2968 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2969 a = dseg_addaddress(cd, supervftbl);
2970 M_ALD(REG_ITMP2, REG_PV, a);
2971 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2972 codegen_threadcritstart(cd, (u1 *) mcodeptr - cd->mcodebase);
2974 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2975 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2976 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2977 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2978 codegen_threadcritstop(cd, (u1 *) mcodeptr - cd->mcodebase);
2980 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2981 M_CMPU(REG_ITMP1, REG_ITMP2);
2984 M_IADD_IMM(REG_ZERO, 1, d);
2986 store_reg_to_var_int(iptr->dst, d);
2990 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
2992 var_to_reg_int(s1, src, REG_ITMP1);
2995 codegen_addxcheckarefs(cd, mcodeptr);
2998 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
3000 M_CMPI(REG_RESULT, 0);
3002 codegen_addxexceptionrefs(cd, mcodeptr);
3005 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
3006 /* op1 = dimension, val.a = array descriptor */
3008 /* check for negative sizes and copy sizes to stack if necessary */
3010 MCODECHECK((iptr->op1 << 1) + 64);
3012 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
3013 var_to_reg_int(s2, src, REG_ITMP1);
3016 codegen_addxcheckarefs(cd, mcodeptr);
3018 /* copy SAVEDVAR sizes to stack */
3020 if (src->varkind != ARGVAR)
3021 #if defined(__DARWIN__)
3022 M_IST(s2, REG_SP, LA_SIZE + (s1 + INT_ARG_CNT) * 4);
3024 M_IST(s2, REG_SP, LA_SIZE + (s1 + 3) * 4);
3028 /* is patcher function set? */
3031 codegen_addpatchref(cd, mcodeptr,
3032 (functionptr) iptr->target, iptr->val.a);
3034 if (showdisassemble)
3040 a = (ptrint) iptr->val.a;
3043 /* a0 = dimension count */
3045 ICONST(rd->argintregs[0], iptr->op1);
3047 /* a1 = arraydescriptor */
3049 a = dseg_addaddress(cd, iptr->val.a);
3050 M_ALD(rd->argintregs[1], REG_PV, a);
3052 /* a2 = pointer to dimensions = stack pointer */
3054 #if defined(__DARWIN__)
3055 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + INT_ARG_CNT * 4);
3057 M_LDA(rd->argintregs[2], REG_SP, LA_SIZE + 3 * 4);
3060 a = dseg_addaddress(cd, BUILTIN_multianewarray);
3061 M_ALD(REG_PV, REG_PV, a);
3064 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
3067 M_LDA (REG_PV, REG_ITMP1, -s1);
3069 s4 ml = -s1, mh = 0;
3070 while (ml < -32768) {ml += 65536; mh--;}
3071 M_LDA(REG_PV, REG_ITMP1, ml);
3072 M_LDAH(REG_PV, REG_PV, mh);
3074 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
3075 M_INTMOVE(REG_RESULT, s1);
3076 store_reg_to_var_int(iptr->dst, s1);
3081 throw_cacao_exception_exit(string_java_lang_InternalError,
3082 "Unknown ICMD %d", iptr->opc);
3085 } /* for instruction */
3087 /* copy values to interface registers */
3089 src = bptr->outstack;
3090 len = bptr->outdepth;
3091 MCODECHECK(64 + len);
3097 if ((src->varkind != STACKVAR)) {
3099 if (IS_FLT_DBL_TYPE(s2)) {
3100 var_to_reg_flt(s1, src, REG_FTMP1);
3101 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3102 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
3105 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3109 var_to_reg_int(s1, src, REG_ITMP1);
3110 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
3111 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
3114 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
3115 if (IS_2_WORD_TYPE(s2))
3116 M_IST(rd->secondregs[s1], REG_SP, rd->interfaces[len][s2].regoff * 4 + 4);
3122 } /* if (bptr -> flags >= BBREACHED) */
3123 } /* for basic block */
3125 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
3128 /* generate bound check stubs */
3130 s4 *xcodeptr = NULL;
3133 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
3134 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3136 (u1 *) mcodeptr - cd->mcodebase);
3140 /* move index register into REG_ITMP1 */
3141 M_MOV(bref->reg, REG_ITMP1);
3142 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3144 if (xcodeptr != NULL) {
3145 M_BR(xcodeptr - mcodeptr - 1);
3148 xcodeptr = mcodeptr;
3150 M_STWU(REG_SP, REG_SP, -(24 + 2 * 4));
3151 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3153 M_MOV(REG_ITMP1, rd->argintregs[0]);
3155 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3156 M_ALD(REG_ITMP2, REG_PV, a);
3159 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3161 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 1 * 4);
3162 M_IADD_IMM(REG_SP, 24 + 2 * 4, REG_SP);
3164 a = dseg_addaddress(cd, asm_handle_exception);
3165 M_ALD(REG_ITMP3, REG_PV, a);
3172 /* generate negative array size check stubs */
3176 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3177 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3178 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3180 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3184 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3186 (u1 *) mcodeptr - cd->mcodebase);
3190 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3192 if (xcodeptr != NULL) {
3193 M_BR(xcodeptr - mcodeptr - 1);
3196 xcodeptr = mcodeptr;
3198 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3199 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3201 a = dseg_addaddress(cd, new_negativearraysizeexception);
3202 M_ALD(REG_ITMP2, REG_PV, a);
3205 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3207 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3208 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3210 a = dseg_addaddress(cd, asm_handle_exception);
3211 M_ALD(REG_ITMP3, REG_PV, a);
3218 /* generate cast check stubs */
3222 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3223 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3224 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3226 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3230 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3232 (u1 *) mcodeptr - cd->mcodebase);
3236 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3238 if (xcodeptr != NULL) {
3239 M_BR(xcodeptr - mcodeptr - 1);
3242 xcodeptr = mcodeptr;
3244 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3245 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3247 a = dseg_addaddress(cd, new_classcastexception);
3248 M_ALD(REG_ITMP2, REG_PV, a);
3251 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3253 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3254 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3256 a = dseg_addaddress(cd, asm_handle_exception);
3257 M_ALD(REG_ITMP3, REG_PV, a);
3264 /* generate exception check stubs */
3268 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3269 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3270 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3272 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3276 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3278 (u1 *) mcodeptr - cd->mcodebase);
3282 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3284 if (xcodeptr != NULL) {
3285 M_BR(xcodeptr - mcodeptr - 1);
3288 xcodeptr = mcodeptr;
3290 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3291 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3293 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3294 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3295 M_ALD(REG_ITMP2, REG_PV, a);
3299 /* get the exceptionptr from the ptrprt and clear it */
3300 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3302 M_AST(REG_ITMP3, REG_RESULT, 0);
3304 a = dseg_addaddress(cd, &_exceptionptr);
3305 M_ALD(REG_ITMP2, REG_PV, a);
3307 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3309 M_AST(REG_ITMP3, REG_ITMP2, 0);
3312 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3313 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3315 a = dseg_addaddress(cd, asm_handle_exception);
3316 M_ALD(REG_ITMP3, REG_PV, a);
3322 /* generate null pointer check stubs */
3326 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3327 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3328 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3330 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3334 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3336 (u1 *) mcodeptr - cd->mcodebase);
3340 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3342 if (xcodeptr != NULL) {
3343 M_BR(xcodeptr - mcodeptr - 1);
3346 xcodeptr = mcodeptr;
3348 M_STWU(REG_SP, REG_SP, -(24 + 1 * 4));
3349 M_IST(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3351 a = dseg_addaddress(cd, new_nullpointerexception);
3352 M_ALD(REG_ITMP2, REG_PV, a);
3355 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3357 M_ILD(REG_ITMP2_XPC, REG_SP, 24 + 0 * 4);
3358 M_IADD_IMM(REG_SP, 24 + 1 * 4, REG_SP);
3360 a = dseg_addaddress(cd, asm_handle_exception);
3361 M_ALD(REG_ITMP3, REG_PV, a);
3367 /* generate patcher stub call code */
3374 for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
3375 /* check code segment size */
3379 /* Get machine code which is patched back in later. The call is */
3380 /* 1 instruction word long. */
3382 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3385 /* patch in the call to call the following code (done at compile */
3388 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3389 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3391 M_BL(tmpmcodeptr - (xcodeptr + 1));
3393 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3395 /* create stack frame - keep stack 16-byte aligned */
3397 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
3399 /* move return address onto stack */
3402 M_AST(REG_ITMP3, REG_SP, 4 * 4);
3404 /* move pointer to java_objectheader onto stack */
3406 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3407 /* order reversed because of data segment layout */
3409 (void) dseg_addaddress(cd, get_dummyLR()); /* monitorPtr */
3410 a = dseg_addaddress(cd, NULL); /* vftbl */
3412 M_LDA(REG_ITMP3, REG_PV, a);
3413 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3416 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3419 /* move machine code onto stack */
3421 a = dseg_adds4(cd, mcode);
3422 M_ILD(REG_ITMP3, REG_PV, a);
3423 M_IST(REG_ITMP3, REG_SP, 2 * 4);
3425 /* move class/method/field reference onto stack */
3427 a = dseg_addaddress(cd, pref->ref);
3428 M_ALD(REG_ITMP3, REG_PV, a);
3429 M_AST(REG_ITMP3, REG_SP, 1 * 4);
3431 /* move patcher function pointer onto stack */
3433 a = dseg_addaddress(cd, pref->patcher);
3434 M_ALD(REG_ITMP3, REG_PV, a);
3435 M_AST(REG_ITMP3, REG_SP, 0 * 4);
3437 a = dseg_addaddress(cd, asm_wrapper_patcher);
3438 M_ALD(REG_ITMP3, REG_PV, a);
3446 codegen_finish(m, cd, (ptrint) ((u1 *) mcodeptr - cd->mcodebase));
3448 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3452 /* createcompilerstub **********************************************************
3454 Creates a stub routine which calls the compiler.
3456 *******************************************************************************/
3458 #define COMPSTUBSIZE 6
3460 u1 *createcompilerstub(methodinfo *m)
3462 s4 *s = CNEW(s4, COMPSTUBSIZE); /* memory to hold the stub */
3463 s4 *mcodeptr = s; /* code generation pointer */
3465 M_LDA(REG_ITMP1, REG_PV, 4*4);
3466 M_ALD(REG_PV, REG_PV, 5*4);
3470 s[4] = (s4) m; /* literals to be adressed */
3471 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3473 asm_cacheflush((void *) s, (u1 *) mcodeptr - (u1 *) s);
3475 #if defined(STATISTICS)
3477 count_cstub_len += COMPSTUBSIZE * 4;
3484 /* removecompilerstub **********************************************************
3486 Deletes a compilerstub from memory (simply by freeing it).
3488 *******************************************************************************/
3490 void removecompilerstub(u1 *stub)
3492 CFREE(stub, COMPSTUBSIZE * 4);
3496 /* createnativestub ************************************************************
3498 Creates a stub routine which calls a native method.
3500 *******************************************************************************/
3502 #define NATIVESTUB_SIZE 200
3503 #define NATIVESTUB_OFFSET 14
3506 u1 *createnativestub(functionptr f, methodinfo *m)
3508 s4 *s; /* memory to hold the stub */
3511 s4 *mcodeptr; /* code generation pointer */
3512 s4 stackframesize; /* size of stackframe if needed */
3517 t_inlining_globals *id;
3521 s4 i, j; /* count variables */
3525 /* set some variables */
3527 nativeparams = (m->flags & ACC_STATIC) ? 2 : 1;
3529 /* mark start of dump memory area */
3531 dumpsize = dump_size();
3533 /* setup registers before using it */
3535 cd = DNEW(codegendata);
3536 rd = DNEW(registerdata);
3537 id = DNEW(t_inlining_globals);
3539 inlining_setup(m, id);
3540 reg_setup(m, rd, id);
3542 /* create new method descriptor with additional native parameters */
3546 nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
3547 md->paramcount * sizeof(typedesc) +
3548 nativeparams * sizeof(typedesc));
3550 nmd->paramcount = md->paramcount + nativeparams;
3552 nmd->params = DMNEW(paramdesc, nmd->paramcount);
3554 nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
3556 if (m->flags & ACC_STATIC)
3557 nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
3559 MCOPY(nmd->paramtypes + nativeparams, md->paramtypes, typedesc,
3562 md_param_alloc(nmd);
3564 /* calculate native stub size */
3566 stubsize = NATIVESTUB_SIZE;
3568 s = CNEW(s4, stubsize);
3569 cs = s + NATIVESTUB_OFFSET;
3572 /* set some required varibles which are normally set by codegen_setup */
3574 cd->mcodebase = (u1 *) mcodeptr;
3575 cd->patchrefs = NULL;
3577 *(cs-1) = (u4) f; /* address of native method */
3578 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3579 *(cs-2) = (u4) builtin_get_exceptionptrptr;
3581 *(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
3583 *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler*/
3584 *(cs-4) = (u4) (&env); /* addr of jni_environement */
3585 *(cs-5) = (u4) builtin_trace_args;
3587 *(cs-7) = (u4) builtin_displaymethodstop;
3588 *(cs-8) = (u4) m->class;
3589 *(cs-9) = (u4) asm_wrapper_patcher;
3590 *(cs-10) = (u4) &builtin_asm_get_stackframeinfo;
3591 *(cs-11) = (u4) NULL; /* filled with machine code */
3592 *(cs-12) = (ptrint) PATCHER_clinit;
3593 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3594 *(cs-13) = (ptrint) get_dummyLR(); /* monitorPtr */
3596 *(cs-13) = (ptrint) NULL; /* monitorPtr */
3598 *(cs-14) = (ptrint) NULL; /* vftbl */
3602 M_AST(REG_ITMP1, REG_SP, LA_LR_OFFSET); /* store return address */
3604 /* Build up new Stackframe for native call */
3606 stackframesize = nmd->memuse;
3608 stackframesize = (stackframesize + 3) & ~3; /* Keep Stack 16 Byte aligned */
3609 M_STWU(REG_SP, REG_SP, -(stackframesize * 4)); /* build up stackframe */
3611 /* if function is static, check for initialized */
3613 if ((m->flags & ACC_STATIC) && !m->class->initialized)
3614 codegen_addpatchref(cd, mcodeptr, NULL, NULL);
3621 /* XXX must be a multiple of 16 */
3622 M_LDA(REG_SP, REG_SP, -(LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3626 /* save all arguments into the reserved stack space */
3628 for (i = 0; i < md->paramcount && i < TRACE_ARGS_NUM; i++) {
3629 t = md->paramtypes[i].type;
3631 if (IS_INT_LNG_TYPE(t)) {
3632 /* overlapping u8's are on the stack */
3633 if ((i + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3634 s1 = rd->argintregs[i + longargs + dblargs];
3636 if (!IS_2_WORD_TYPE(t)) {
3637 M_IST(REG_ITMP1, REG_SP, LA_SIZE + i * 8);
3638 M_IST(s1, REG_SP, LA_SIZE + i * 8 + 4);
3641 M_IST(s1, REG_SP, LA_SIZE + i * 8);
3642 M_IST(rd->secondregs[s1], REG_SP, LA_SIZE + i * 8 + 4);
3647 /* we do not have a data segment here */
3648 /* a = dseg_adds4(cd, 0xdeadbeef);
3649 M_ILD(REG_ITMP1, REG_PV, a); */
3650 M_LDA(REG_ITMP1, REG_ZERO, -1);
3651 M_IST(REG_ITMP1, REG_SP, LA_SIZE + i * 8);
3652 M_IST(REG_ITMP1, REG_SP, LA_SIZE + i * 8 + 4);
3656 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3657 s1 = rd->argfltregs[fltargs + dblargs];
3659 if (!IS_2_WORD_TYPE(t)) {
3660 M_IST(REG_ITMP1, REG_SP, LA_SIZE + i * 8);
3661 M_FST(s1, REG_SP, LA_SIZE + i * 8 + 4);
3665 M_DST(s1, REG_SP, LA_SIZE + i * 8);
3670 /* this should not happen */
3675 /* TODO: save remaining integer and float argument registers */
3677 /* load first 4 arguments into integer argument registers */
3679 for (i = 0; i < INT_ARG_CNT; i++)
3680 M_ILD(rd->argintregs[i], REG_SP, LA_SIZE + i * 4);
3682 M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3683 #if defined(__DARWIN__)
3684 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 8 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3686 M_AST(REG_ITMP1, REG_SP, LA_SIZE + 4 * 8);
3688 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3696 /* restore arguments into the reserved stack space */
3698 for (i = 0; i < md->paramcount && i < TRACE_ARGS_NUM; i++) {
3699 t = md->paramtypes[i].type;
3701 if (IS_INT_LNG_TYPE(t)) {
3702 if ((i + longargs + dblargs) < INT_ARG_CNT) {
3703 s1 = rd->argintregs[i + longargs + dblargs];
3705 if (!IS_2_WORD_TYPE(t)) {
3706 M_ILD(s1, REG_SP, LA_SIZE + i * 8 + 4);
3709 M_ILD(s1, REG_SP, LA_SIZE + i * 8);
3710 M_ILD(rd->secondregs[s1], REG_SP, LA_SIZE + i * 8 + 4);
3716 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3717 s1 = rd->argfltregs[fltargs + dblargs];
3719 if (!IS_2_WORD_TYPE(t)) {
3720 M_FLD(s1, REG_SP, LA_SIZE + i * 8 + 4);
3724 M_DLD(s1, REG_SP, LA_SIZE + i * 8);
3731 M_LDA(REG_SP, REG_SP, LA_SIZE + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3734 /* copy or spill arguments to new locations */
3736 for (i = md->paramcount - 1, j = i + nativeparams; i >= 0; i--, j--) {
3737 t = md->paramtypes[i].type;
3739 if (IS_INT_LNG_TYPE(t)) {
3740 if (!md->params[i].inmemory) {
3741 s1 = rd->argintregs[md->params[i].regoff];
3743 if (!nmd->params[j].inmemory) {
3744 s2 = rd->argintregs[nmd->params[j].regoff];
3745 M_TINTMOVE(t, s1, s2);
3748 s2 = nmd->params[j].regoff;
3750 M_IST(s1, REG_SP, s2 * 4);
3751 if (IS_2_WORD_TYPE(t))
3752 M_IST(rd->secondregs[s1], REG_SP, s2 * 4 + 4);
3756 s1 = md->params[i].regoff + stackframesize;
3757 s2 = nmd->params[j].regoff;
3759 M_ILD(REG_ITMP1, REG_SP, s1 * 4);
3760 M_IST(REG_ITMP1, REG_SP, s2 * 4);
3761 if (IS_2_WORD_TYPE(t)) {
3762 M_ILD(REG_ITMP1, REG_SP, s1 * 4 + 4);
3763 M_IST(REG_ITMP1, REG_SP, s2 * 4 + 4);
3768 /* We only copy spilled float arguments, as the float argument */
3769 /* registers keep unchanged. */
3771 if (md->params[i].inmemory) {
3772 s1 = md->params[i].regoff + stackframesize;
3773 s2 = nmd->params[j].regoff;
3775 if (IS_2_WORD_TYPE(t)) {
3776 M_DLD(REG_FTMP1, REG_SP, s1 * 4);
3777 M_DST(REG_FTMP1, REG_SP, s2 * 4);
3780 M_FLD(REG_FTMP1, REG_SP, s1 * 4 + 4);
3781 M_FST(REG_FTMP1, REG_SP, s2 * 4 + 4);
3787 /* put class into second argument register */
3789 if (m->flags & ACC_STATIC)
3790 M_ALD(rd->argintregs[1], REG_PV, -8 * 4);
3792 /* put env into first argument register */
3794 M_ALD(rd->argintregs[0], REG_PV, -4 * 4);
3796 /* generate the actual native call */
3798 M_ALD(REG_PV, REG_PV, -1 * 4); /* load adress of native method */
3801 disp = -(s4) (mcodeptr - cs) * 4;
3803 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3805 /* 20 instructions */
3809 M_LDA(REG_SP, REG_SP, -10 * 8);
3810 M_DST(REG_FRESULT, REG_SP, 48+0);
3811 M_IST(REG_RESULT, REG_SP, 48+8);
3812 M_AST(REG_ITMP3, REG_SP, 48+12);
3813 M_IST(REG_RESULT2, REG_SP, 48+16);
3815 /* keep this order */
3816 switch (m->returntype) {
3819 #if defined(__DARWIN__)
3820 M_MOV(REG_RESULT, rd->argintregs[2]);
3821 M_CLR(rd->argintregs[1]);
3823 M_MOV(REG_RESULT, rd->argintregs[3]);
3824 M_CLR(rd->argintregs[2]);
3829 #if defined(__DARWIN__)
3830 M_MOV(REG_RESULT2, rd->argintregs[2]);
3831 M_MOV(REG_RESULT, rd->argintregs[1]);
3833 M_MOV(REG_RESULT2, rd->argintregs[3]);
3834 M_MOV(REG_RESULT, rd->argintregs[2]);
3838 M_ALD(rd->argintregs[0], REG_PV, -6 * 4);
3840 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3841 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3842 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop */
3845 M_DLD(REG_FRESULT, REG_SP, 48+0);
3846 M_ILD(REG_RESULT, REG_SP, 48+8);
3847 M_ALD(REG_ITMP3, REG_SP, 48+12);
3848 M_ILD(REG_RESULT2, REG_SP, 48+16);
3849 M_LDA(REG_SP, REG_SP, 10 * 8);
3853 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3854 switch (md->returntype.type) {
3856 M_IST(REG_RESULT2, REG_SP, stackframesize * 4 - 4 /* 60*/);
3860 M_IST(REG_RESULT, REG_SP, stackframesize * 4 - 8 /*56*/);
3863 M_FST(REG_FRESULT, REG_SP, stackframesize * 4 - 8 /*56*/);
3866 M_DST(REG_FRESULT, REG_SP, stackframesize * 4 - 8 /*56*/);
3870 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
3873 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3875 M_LDA(REG_PV, REG_ITMP1, disp);
3876 M_MOV(REG_RESULT, REG_ITMP2);
3878 switch (md->returntype.type) {
3880 M_ILD(REG_RESULT2, REG_SP, stackframesize * 4 - 4 /*60*/);
3884 M_ILD(REG_RESULT, REG_SP, stackframesize * 4 - 8 /*56*/);
3887 M_FLD(REG_FRESULT, REG_SP, stackframesize * 4 - 8 /*56*/);
3890 M_DLD(REG_FRESULT, REG_SP, stackframesize * 4 - 8 /*56*/);
3894 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
3896 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);/* load exception into reg. itmp1 */
3897 M_TST(REG_ITMP1_XPTR);
3898 M_BNE(4); /* if no exception then return */
3900 M_ALD(REG_ITMP1, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
3902 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
3907 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3909 M_ALD(REG_ITMP2, REG_SP, stackframesize * 4 + LA_LR_OFFSET); /* load ra */
3912 M_LDA(REG_SP, REG_SP, stackframesize * 4); /* remove stackframe */
3914 M_IADD_IMM(REG_ITMP2, -4, REG_ITMP2_XPC); /* fault address */
3916 M_ALD(REG_ITMP3, REG_PV, -3 * 4); /* load asm exception handler address */
3920 /* generate patcher stub call code */
3927 /* there can only be one <clinit> ref entry */
3929 pref = cd->patchrefs;
3932 /* Get machine code which is patched back in later. The call is */
3933 /* 1 instruction word long. */
3935 xcodeptr = (s4 *) (cd->mcodebase + pref->branchpos);
3936 *(cs-11) = (u4) *xcodeptr;
3938 /* patch in the call to call the following code (done at compile */
3941 tmpmcodeptr = mcodeptr; /* save current mcodeptr */
3942 mcodeptr = xcodeptr; /* set mcodeptr to patch position */
3944 M_BL(tmpmcodeptr - (xcodeptr + 1));
3946 mcodeptr = tmpmcodeptr; /* restore the current mcodeptr */
3948 /* create stack frame - keep stack 16-byte aligned */
3950 M_AADD_IMM(REG_SP, -8 * 4, REG_SP);
3952 /* move return address onto stack */
3955 M_AST(REG_ITMP3, REG_SP, 4 * 4);
3957 /* move pointer to java_objectheader onto stack */
3959 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3960 M_LDA(REG_ITMP3, REG_PV, -14 * 4);
3961 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3964 M_AST(REG_ITMP3, REG_SP, 3 * 4);
3967 /* move machine code onto stack */
3969 M_ILD(REG_ITMP3, REG_PV, -11 * 4); /* machine code */
3970 M_IST(REG_ITMP3, REG_SP, 2 * 4);
3972 /* move class reference onto stack */
3974 M_ALD(REG_ITMP3, REG_PV, -8 * 4); /* class */
3975 M_AST(REG_ITMP3, REG_SP, 1 * 4);
3977 /* move patcher function pointer onto stack */
3979 M_ALD(REG_ITMP3, REG_PV, -12 * 4); /* patcher function */
3980 M_AST(REG_ITMP3, REG_SP, 0 * 4);
3982 M_ALD(REG_ITMP3, REG_PV, -9 * 4); /* asm_wrapper_patcher */
3988 /* Check if the stub size is big enough to hold the whole stub generated. */
3989 /* If not, this can lead into unpredictable crashes, because of heap */
3992 if ((s4) (mcodeptr - s) > stubsize) {
3993 throw_cacao_exception_exit(string_java_lang_InternalError,
3994 "Native stub size %d is to small for current stub size %d",
3995 stubsize, (s4) (mcodeptr - s));
3998 asm_cacheflush((void *) s, (u1 *) mcodeptr - (u1 *) s);
4000 #if defined(STATISTICS)
4002 count_nstub_len += NATIVESTUB_SIZE * 4;
4005 /* release dump area */
4007 dump_release(dumpsize);
4009 return (u1*) (s + NATIVESTUB_OFFSET);
4013 /* function: removenativestub **************************************************
4015 removes a previously created native-stub from memory
4017 *******************************************************************************/
4019 void removenativestub(u1 *stub)
4021 CFREE((s4 *) stub - NATIVESTUB_OFFSET, NATIVESTUB_SIZE * 4);
4026 * These are local overrides for various environment variables in Emacs.
4027 * Please do not remove this and leave it at the end of the file, where
4028 * Emacs will automagically detect them.
4029 * ---------------------------------------------------------------------
4032 * indent-tabs-mode: t