1 /* jit/powerpc/codegen.c - machine code generator for 32-bit powerpc
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 Institut f. Computersprachen, TU Wien
5 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, M. Probst,
6 S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich,
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Andreas Krall
31 $Id: codegen.c 1477 2004-11-11 10:47:04Z twisti $
48 #include "jit/parse.h"
50 #include "jit/powerpc/codegen.h"
52 /* include independent code generation stuff */
53 #include "jit/codegen.inc"
54 #include "jit/reg.inc"
57 /* register descripton - array ************************************************/
59 /* #define REG_RES 0 reserved register for OS or code generator */
60 /* #define REG_RET 1 return value register */
61 /* #define REG_EXC 2 exception value register (only old jit) */
62 /* #define REG_SAV 3 (callee) saved register */
63 /* #define REG_TMP 4 scratch temporary register (caller saved) */
64 /* #define REG_ARG 5 argument register (caller saved) */
66 /* #define REG_END -1 last entry in tables */
69 REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
70 REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
71 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
72 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
75 /* for use of reserved registers, see comment above */
77 int nregdescfloat[] = {
78 REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
79 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV,
80 REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
81 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
84 /* for use of reserved registers, see comment above */
87 void asm_cacheflush(void *, long);
89 //#include <architecture/ppc/cframe.h>
91 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
92 void thread_restartcriticalsection(void *u)
94 /* XXX set pc to restart address */
98 #include <mach/message.h>
100 int cacao_catch_Handler(mach_port_t thread)
103 unsigned int crashpc;
105 java_objectheader *xptr;
108 thread_state_flavor_t flavor = PPC_THREAD_STATE;
109 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
110 ppc_thread_state_t thread_state;
116 r = thread_get_state(thread, flavor,
117 (natural_t*)&thread_state, &thread_state_count);
118 if (r != KERN_SUCCESS)
119 panic("thread_get_state failed");
121 regs = &thread_state.r0;
122 crashpc = thread_state.srr0;
124 instr = *(s4*) crashpc;
125 reg = (instr >> 16) & 31;
128 xptr = new_exception(string_java_lang_NullPointerException);
130 regs[REG_ITMP2_XPC] = crashpc;
131 regs[REG_ITMP1_XPTR] = (u4) xptr;
132 thread_state.srr0 = (u4) asm_handle_exception;
134 r = thread_set_state(thread, flavor,
135 (natural_t*)&thread_state, thread_state_count);
136 if (r != KERN_SUCCESS)
137 panic("thread_set_state failed");
146 void init_exceptions(void)
151 void adjust_argvars(stackptr s, int d, int *fa, int *ia)
157 adjust_argvars(s->prev, d-1, fa, ia);
158 if (s->varkind == ARGVAR)
159 s->varnum = (IS_FLT_DBL_TYPE(s->type)) ? *fa : *ia;
160 *fa += (IS_FLT_DBL_TYPE(s->type) != 0);
161 *ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
165 #define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
167 void preregpass(methodinfo *m)
176 /* keep code size smaller */
180 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
182 for (iptr = bptr->iinstr, src = bptr->instack;
184 src = iptr->dst, len--, iptr++)
186 if (bptr->flags < BBREACHED)
199 case ICMD_INVOKEVIRTUAL:
200 case ICMD_INVOKESPECIAL:
201 case ICMD_INVOKESTATIC:
202 case ICMD_INVOKEINTERFACE:
207 adjust_argvars(src, s3, &fa, &ia);
210 for (; --s3 >= 0; src = src->prev) {
211 paramsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
213 r->ifmemuse = intmaxf(r->ifmemuse, paramsize);
216 case ICMD_MULTIANEWARRAY:
218 paramsize = r->intreg_argnum + s3;
219 r->ifmemuse = intmaxf(r->ifmemuse, paramsize);
226 r->maxmemuse = r->ifmemuse;
230 /* function gen_mcode **********************************************************
232 generates machine code
234 *******************************************************************************/
236 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
238 s4 len, s1, s2, s3, d;
254 /* space to save used callee saved registers */
256 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
257 savedregs_num += 2 * (rd->savfltregcnt - rd->maxsavfltreguse);
259 parentargs_base = rd->maxmemuse + savedregs_num;
261 #ifdef USE_THREADS /* space to save argument of monitor_enter */
263 if (checksync && (m->flags & ACC_SYNCHRONIZED))
268 /* create method header */
270 parentargs_base = (parentargs_base + 3) & ~3;
273 (void) dseg_addaddress(cd, m); /* Filler */
275 (void) dseg_addaddress(cd, m); /* MethodPointer */
276 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
280 /* IsSync contains the offset relative to the stack pointer for the
281 argument of monitor_exit used in the exception handler. Since the
282 offset could be zero and give a wrong meaning of the flag it is
286 if (checksync && (m->flags & ACC_SYNCHRONIZED))
287 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 4); /* IsSync */
292 (void) dseg_adds4(cd, 0); /* IsSync */
294 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
295 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
296 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
297 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
299 /* create exception table */
301 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
302 dseg_addtarget(cd, ex->start);
303 dseg_addtarget(cd, ex->end);
304 dseg_addtarget(cd, ex->handler);
305 (void) dseg_addaddress(cd, ex->catchtype);
308 /* initialize mcode variables */
310 mcodeptr = (s4 *) cd->mcodebase;
311 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
312 MCODECHECK(128 + m->paramcount);
314 /* create stack frame (if necessary) */
316 if (!m->isleafmethod) {
318 M_AST(REG_ITMP3, REG_SP, 8);
321 if (parentargs_base) {
322 M_LDA(REG_SP, REG_SP, -parentargs_base * 4);
325 /* save return address and used callee saved registers */
328 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
329 p--; M_IST(rd->savintregs[i], REG_SP, 4 * p);
331 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
332 p-=2; M_DST(rd->savfltregs[i], REG_SP, 4 * p);
335 /* save monitorenter argument */
337 #if defined(USE_THREADS)
338 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
339 if (m->flags & ACC_STATIC) {
340 p = dseg_addaddress(cd, m->class);
341 M_ALD(REG_ITMP1, REG_PV, p);
342 M_AST(REG_ITMP1, REG_SP, 4 * rd->maxmemuse);
345 M_AST(rd->argintregs[0], REG_SP, 4 * rd->maxmemuse);
350 /* copy argument registers to stack and call trace function with pointer
351 to arguments on stack.
360 /* XXX must be a multiple of 16 */
361 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
363 M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
365 M_CLR(REG_ITMP1); /* clear help register */
367 /* save all arguments into the reserved stack space */
368 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
369 t = m->paramtypes[p];
371 if (IS_INT_LNG_TYPE(t)) {
372 /* overlapping u8's are on the stack */
373 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
374 s1 = rd->argintregs[p + longargs + dblargs];
376 if (!IS_2_WORD_TYPE(t)) {
377 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
378 M_IST(s1, REG_SP, 24 + p * 8 + 4);
381 M_IST(s1, REG_SP, 24 + p * 8);
382 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
387 a = dseg_adds4(cd, 0xdeadbeef);
388 M_ILD(REG_ITMP1, REG_PV, a);
389 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
390 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
394 if ((fltargs + dblargs) < FLT_ARG_CNT) {
395 s1 = rd->argfltregs[fltargs + dblargs];
397 if (!IS_2_WORD_TYPE(t)) {
398 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
399 M_FST(s1, REG_SP, 24 + p * 8 + 4);
403 M_DST(s1, REG_SP, 24 + p * 8);
408 /* this should not happen */
413 /* TODO: save remaining integer and flaot argument registers */
415 /* load first 4 arguments into integer argument registers */
416 for (p = 0; p < 8; p++) {
417 d = rd->argintregs[p];
418 M_ILD(d, REG_SP, 24 + p * 4);
421 p = dseg_addaddress(cd, m);
422 M_ALD(REG_ITMP1, REG_PV, p);
423 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
424 p = dseg_addaddress(cd, (void *) builtin_trace_args);
425 M_ALD(REG_ITMP2, REG_PV, p);
433 /* restore arguments into the reserved stack space */
434 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
435 t = m->paramtypes[p];
437 if (IS_INT_LNG_TYPE(t)) {
438 if ((p + longargs + dblargs) < INT_ARG_CNT) {
439 s1 = rd->argintregs[p + longargs + dblargs];
441 if (!IS_2_WORD_TYPE(t)) {
442 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
445 M_ILD(s1, REG_SP, 24 + p * 8);
446 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
452 if ((fltargs + dblargs) < FLT_ARG_CNT) {
453 s1 = rd->argfltregs[fltargs + dblargs];
455 if (!IS_2_WORD_TYPE(t)) {
456 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
460 M_DLD(s1, REG_SP, 24 + p * 8);
467 M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
469 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
473 /* take arguments out of register or stack frame */
479 for (p = 0, l = 0; p < m->paramcount; p++) {
480 arg = narg; iarg = niarg;
481 t = m->paramtypes[p];
482 var = &(rd->locals[l][t]);
484 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
488 if (IS_INT_LNG_TYPE(t)) { /* integer args */
489 if (iarg < INT_ARG_CNT -
490 (IS_2_WORD_TYPE(t)!=0)) { /* register arguments */
491 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
492 M_TINTMOVE(t, rd->argintregs[iarg], var->regoff);
494 } else { /* reg arg -> spilled */
495 M_IST(rd->argintregs[iarg], REG_SP, 4 * var->regoff);
496 if (IS_2_WORD_TYPE(t))
497 M_IST(rd->secondregs[rd->argintregs[iarg]], REG_SP, 4 * var->regoff + 4);
500 } else { /* stack arguments */
502 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
503 M_ILD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
504 if (IS_2_WORD_TYPE(t))
505 M_ILD(rd->secondregs[var->regoff], REG_SP, 4 * (parentargs_base + pa) + 4);
507 } else { /* stack arg -> spilled */
508 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
509 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff);
510 if (IS_2_WORD_TYPE(t)) {
511 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
512 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff + 4);
517 } else { /* floating args */
519 if (arg < FLT_ARG_CNT) { /* register arguments */
520 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
521 M_FLTMOVE(rd->argfltregs[arg], var->regoff);
523 } else { /* reg arg -> spilled */
524 M_DST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
527 } else { /* stack arguments */
529 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
530 if (IS_2_WORD_TYPE(t)) {
531 M_DLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
534 M_FLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
537 } else { /* stack-arg -> spilled */
538 if (IS_2_WORD_TYPE(t)) {
539 M_DLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
542 M_FLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
544 M_DST(REG_FTMP1, REG_SP, 4 * var->regoff);
551 /* call monitorenter function */
553 #if defined(USE_THREADS)
554 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
555 s4 func_enter = (m->flags & ACC_STATIC) ?
556 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
557 p = dseg_addaddress(cd, (void *) func_enter);
558 M_ALD(REG_ITMP3, REG_PV, p);
560 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
566 /* end of header generation */
568 /* walk through all basic blocks */
569 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
571 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
573 if (bptr->flags >= BBREACHED) {
575 /* branch resolving */
579 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
580 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
586 /* copy interface registers to their destination */
591 while (src != NULL) {
593 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
594 d = reg_of_var(rd, src, REG_ITMP1);
595 M_INTMOVE(REG_ITMP1, d);
596 store_reg_to_var_int(src, d);
599 d = reg_of_var(rd, src, REG_IFTMP);
600 if ((src->varkind != STACKVAR)) {
602 if (IS_FLT_DBL_TYPE(s2)) {
603 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
604 s1 = rd->interfaces[len][s2].regoff;
608 if (IS_2_WORD_TYPE(s2)) {
609 M_DLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
612 M_FLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
615 store_reg_to_var_flt(src, d);
618 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
619 s1 = rd->interfaces[len][s2].regoff;
623 M_ILD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
624 if (IS_2_WORD_TYPE(s2))
625 M_ILD(rd->secondregs[d], REG_SP, 4 * rd->interfaces[len][s2].regoff + 4);
627 store_reg_to_var_int(src, d);
634 /* walk through all instructions */
638 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
640 MCODECHECK(64); /* an instruction usually needs < 64 words */
643 case ICMD_NOP: /* ... ==> ... */
646 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
648 var_to_reg_int(s1, src, REG_ITMP1);
651 codegen_addxnullrefs(cd, mcodeptr);
654 /* constant operations ************************************************/
656 case ICMD_ICONST: /* ... ==> ..., constant */
657 /* op1 = 0, val.i = constant */
659 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
660 ICONST(d, iptr->val.i);
661 store_reg_to_var_int(iptr->dst, d);
664 case ICMD_LCONST: /* ... ==> ..., constant */
665 /* op1 = 0, val.l = constant */
667 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
668 LCONST(d, iptr->val.l);
669 store_reg_to_var_int(iptr->dst, d);
672 case ICMD_FCONST: /* ... ==> ..., constant */
673 /* op1 = 0, val.f = constant */
675 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
676 a = dseg_addfloat(cd, iptr->val.f);
678 store_reg_to_var_flt(iptr->dst, d);
681 case ICMD_DCONST: /* ... ==> ..., constant */
682 /* op1 = 0, val.d = constant */
684 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
685 a = dseg_adddouble(cd, iptr->val.d);
687 store_reg_to_var_flt(iptr->dst, d);
690 case ICMD_ACONST: /* ... ==> ..., constant */
691 /* op1 = 0, val.a = constant */
693 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
694 ICONST(d, (u4) iptr->val.a);
695 store_reg_to_var_int(iptr->dst, d);
699 /* load/store operations **********************************************/
701 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
702 case ICMD_LLOAD: /* op1 = local variable */
705 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
706 if ((iptr->dst->varkind == LOCALVAR) &&
707 (iptr->dst->varnum == iptr->op1))
709 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
710 if (var->flags & INMEMORY) {
711 M_ILD(d, REG_SP, 4 * var->regoff);
712 if (IS_2_WORD_TYPE(var->type))
713 M_ILD(rd->secondregs[d], REG_SP, 4 * var->regoff + 4);
715 M_TINTMOVE(var->type, var->regoff, d);
717 store_reg_to_var_int(iptr->dst, d);
720 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
721 case ICMD_DLOAD: /* op1 = local variable */
723 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
724 if ((iptr->dst->varkind == LOCALVAR) &&
725 (iptr->dst->varnum == iptr->op1))
727 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
728 if (var->flags & INMEMORY)
729 if (IS_2_WORD_TYPE(var->type))
730 M_DLD(d, REG_SP, 4 * var->regoff);
732 M_FLD(d, REG_SP, 4 * var->regoff);
734 M_FLTMOVE(var->regoff, d);
736 store_reg_to_var_flt(iptr->dst, d);
740 case ICMD_ISTORE: /* ..., value ==> ... */
741 case ICMD_LSTORE: /* op1 = local variable */
744 if ((src->varkind == LOCALVAR) &&
745 (src->varnum == iptr->op1))
747 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
748 if (var->flags & INMEMORY) {
749 var_to_reg_int(s1, src, REG_ITMP1);
750 M_IST(s1, REG_SP, 4 * var->regoff);
751 if (IS_2_WORD_TYPE(var->type))
752 M_IST(rd->secondregs[s1], REG_SP, 4 * var->regoff + 4);
754 var_to_reg_int(s1, src, var->regoff);
755 M_TINTMOVE(var->type, s1, var->regoff);
759 case ICMD_FSTORE: /* ..., value ==> ... */
760 case ICMD_DSTORE: /* op1 = local variable */
762 if ((src->varkind == LOCALVAR) &&
763 (src->varnum == iptr->op1))
765 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
766 if (var->flags & INMEMORY) {
767 var_to_reg_flt(s1, src, REG_FTMP1);
768 if (var->type == TYPE_DBL)
769 M_DST(s1, REG_SP, 4 * var->regoff);
771 M_FST(s1, REG_SP, 4 * var->regoff);
773 var_to_reg_flt(s1, src, var->regoff);
774 M_FLTMOVE(s1, var->regoff);
779 /* pop/dup/swap operations ********************************************/
781 /* attention: double and longs are only one entry in CACAO ICMDs */
783 case ICMD_POP: /* ..., value ==> ... */
784 case ICMD_POP2: /* ..., value, value ==> ... */
787 case ICMD_DUP: /* ..., a ==> ..., a, a */
788 M_COPY(src, iptr->dst);
791 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
793 M_COPY(src, iptr->dst);
794 M_COPY(src->prev, iptr->dst->prev);
795 M_COPY(iptr->dst, iptr->dst->prev->prev);
798 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
800 M_COPY(src, iptr->dst);
801 M_COPY(src->prev, iptr->dst->prev);
802 M_COPY(src->prev->prev, iptr->dst->prev->prev);
803 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
806 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
808 M_COPY(src, iptr->dst);
809 M_COPY(src->prev, iptr->dst->prev);
812 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
814 M_COPY(src, iptr->dst);
815 M_COPY(src->prev, iptr->dst->prev);
816 M_COPY(src->prev->prev, iptr->dst->prev->prev);
817 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
818 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
821 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
823 M_COPY(src, iptr->dst);
824 M_COPY(src->prev, iptr->dst->prev);
825 M_COPY(src->prev->prev, iptr->dst->prev->prev);
826 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
827 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
828 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
831 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
833 M_COPY(src, iptr->dst->prev);
834 M_COPY(src->prev, iptr->dst);
838 /* integer operations *************************************************/
840 case ICMD_INEG: /* ..., value ==> ..., - value */
842 var_to_reg_int(s1, src, REG_ITMP1);
843 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
845 store_reg_to_var_int(iptr->dst, d);
848 case ICMD_LNEG: /* ..., value ==> ..., - value */
850 var_to_reg_int(s1, src, REG_ITMP1);
851 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
852 M_SUBFIC(rd->secondregs[s1], 0, rd->secondregs[d]);
854 store_reg_to_var_int(iptr->dst, d);
857 case ICMD_I2L: /* ..., value ==> ..., value */
859 var_to_reg_int(s1, src, REG_ITMP2);
860 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
861 M_INTMOVE(s1, rd->secondregs[d]);
862 M_SRA_IMM(rd->secondregs[d], 31, d);
863 store_reg_to_var_int(iptr->dst, d);
866 case ICMD_L2I: /* ..., value ==> ..., value */
868 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
869 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
871 store_reg_to_var_int(iptr->dst, d);
874 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
876 var_to_reg_int(s1, src, REG_ITMP1);
877 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
879 store_reg_to_var_int(iptr->dst, d);
882 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
884 var_to_reg_int(s1, src, REG_ITMP1);
885 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
887 store_reg_to_var_int(iptr->dst, d);
890 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
892 var_to_reg_int(s1, src, REG_ITMP1);
893 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
895 store_reg_to_var_int(iptr->dst, d);
899 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
901 var_to_reg_int(s1, src->prev, REG_ITMP1);
902 var_to_reg_int(s2, src, REG_ITMP2);
903 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
905 store_reg_to_var_int(iptr->dst, d);
908 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
909 /* val.i = constant */
911 var_to_reg_int(s1, src, REG_ITMP1);
912 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
913 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
914 M_IADD_IMM(s1, iptr->val.i, d);
917 ICONST(REG_ITMP2, iptr->val.i);
918 M_IADD(s1, REG_ITMP2, d);
920 store_reg_to_var_int(iptr->dst, d);
923 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
925 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
926 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
927 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
928 M_ADDC(s1, s2, rd->secondregs[d]);
929 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
930 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
932 store_reg_to_var_int(iptr->dst, d);
935 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
936 /* val.l = constant */
938 s3 = iptr->val.l & 0xffffffff;
939 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
940 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
941 if ((s3 >= -32768) && (s3 <= 32767)) {
942 M_ADDIC(s1, s3, rd->secondregs[d]);
945 ICONST(REG_ITMP2, s3);
946 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
948 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
949 s3 = iptr->val.l >> 32;
955 ICONST(REG_ITMP3, s3);
956 M_ADDE(s1, REG_ITMP3, d);
958 store_reg_to_var_int(iptr->dst, d);
961 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
963 var_to_reg_int(s1, src->prev, REG_ITMP1);
964 var_to_reg_int(s2, src, REG_ITMP2);
965 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
967 store_reg_to_var_int(iptr->dst, d);
970 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
971 /* val.i = constant */
973 var_to_reg_int(s1, src, REG_ITMP1);
974 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
975 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
976 M_IADD_IMM(s1, -iptr->val.i, d);
979 ICONST(REG_ITMP2, -iptr->val.i);
980 M_IADD(s1, REG_ITMP2, d);
982 store_reg_to_var_int(iptr->dst, d);
985 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
987 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
988 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
989 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
990 M_SUBC(s1, s2, rd->secondregs[d]);
991 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
992 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
994 store_reg_to_var_int(iptr->dst, d);
997 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
998 /* val.l = constant */
1000 s3 = (-iptr->val.l) & 0xffffffff;
1001 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1002 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1003 if ((s3 >= -32768) && (s3 <= 32767)) {
1004 M_ADDIC(s1, s3, rd->secondregs[d]);
1007 ICONST(REG_ITMP2, s3);
1008 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
1010 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1011 s3 = (-iptr->val.l) >> 32;
1017 ICONST(REG_ITMP3, s3);
1018 M_ADDE(s1, REG_ITMP3, d);
1020 store_reg_to_var_int(iptr->dst, d);
1023 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1024 var_to_reg_int(s1, src->prev, REG_ITMP1);
1025 var_to_reg_int(s2, src, REG_ITMP2);
1026 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1028 store_reg_to_var_int(iptr->dst, d);
1031 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1032 var_to_reg_int(s1, src->prev, REG_ITMP1);
1033 var_to_reg_int(s2, src, REG_ITMP2);
1034 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1038 store_reg_to_var_int(iptr->dst, d);
1041 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1043 var_to_reg_int(s1, src->prev, REG_ITMP1);
1044 var_to_reg_int(s2, src, REG_ITMP2);
1045 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1047 store_reg_to_var_int(iptr->dst, d);
1050 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1051 /* val.i = constant */
1053 var_to_reg_int(s1, src, REG_ITMP1);
1054 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1055 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1056 M_IMUL_IMM(s1, iptr->val.i, d);
1059 ICONST(REG_ITMP2, iptr->val.i);
1060 M_IMUL(s1, REG_ITMP2, d);
1062 store_reg_to_var_int(iptr->dst, d);
1065 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1067 var_to_reg_int(s1, src, REG_ITMP1);
1068 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1069 M_SRA_IMM(s1, iptr->val.i, d);
1071 store_reg_to_var_int(iptr->dst, d);
1074 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1076 var_to_reg_int(s1, src->prev, REG_ITMP1);
1077 var_to_reg_int(s2, src, REG_ITMP2);
1078 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1079 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1080 M_SLL(s1, REG_ITMP3, d);
1081 store_reg_to_var_int(iptr->dst, d);
1084 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1085 /* val.i = constant */
1087 var_to_reg_int(s1, src, REG_ITMP1);
1088 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1089 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1090 store_reg_to_var_int(iptr->dst, d);
1093 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1095 var_to_reg_int(s1, src->prev, REG_ITMP1);
1096 var_to_reg_int(s2, src, REG_ITMP2);
1097 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1098 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1099 M_SRA(s1, REG_ITMP3, d);
1100 store_reg_to_var_int(iptr->dst, d);
1103 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1104 /* val.i = constant */
1106 var_to_reg_int(s1, src, REG_ITMP1);
1107 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1108 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1109 store_reg_to_var_int(iptr->dst, d);
1112 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1114 var_to_reg_int(s1, src->prev, REG_ITMP1);
1115 var_to_reg_int(s2, src, REG_ITMP2);
1116 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1117 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1118 M_SRL(s1, REG_ITMP2, d);
1119 store_reg_to_var_int(iptr->dst, d);
1122 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1123 /* val.i = constant */
1125 var_to_reg_int(s1, src, REG_ITMP1);
1126 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1127 if (iptr->val.i & 0x1f)
1128 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1131 store_reg_to_var_int(iptr->dst, d);
1134 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1136 var_to_reg_int(s1, src->prev, REG_ITMP1);
1137 var_to_reg_int(s2, src, REG_ITMP2);
1138 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1140 store_reg_to_var_int(iptr->dst, d);
1143 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1144 /* val.i = constant */
1146 var_to_reg_int(s1, src, REG_ITMP1);
1147 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1148 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1149 M_AND_IMM(s1, iptr->val.i, d);
1152 else if (iptr->val.i == 0xffffff) {
1153 M_RLWINM(s1, 0, 8, 31, d);
1157 ICONST(REG_ITMP2, iptr->val.i);
1158 M_AND(s1, REG_ITMP2, d);
1160 store_reg_to_var_int(iptr->dst, d);
1163 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1165 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1166 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1167 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1168 M_AND(s1, s2, rd->secondregs[d]);
1169 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1170 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1172 store_reg_to_var_int(iptr->dst, d);
1175 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1176 /* val.l = constant */
1178 s3 = iptr->val.l & 0xffffffff;
1179 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1180 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1181 if ((s3 >= 0) && (s3 <= 65535)) {
1182 M_AND_IMM(s1, s3, rd->secondregs[d]);
1185 ICONST(REG_ITMP2, s3);
1186 M_AND(s1, REG_ITMP2, rd->secondregs[d]);
1188 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1189 s3 = iptr->val.l >> 32;
1190 if ((s3 >= 0) && (s3 <= 65535)) {
1191 M_AND_IMM(s1, s3, d);
1194 ICONST(REG_ITMP3, s3);
1195 M_AND(s1, REG_ITMP3, d);
1197 store_reg_to_var_int(iptr->dst, d);
1200 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1201 /* val.i = constant */
1203 var_to_reg_int(s1, src, REG_ITMP1);
1204 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1205 M_MOV(s1, REG_ITMP2);
1207 M_BGE(1 + 2*(iptr->val.i >= 32768));
1208 if (iptr->val.i >= 32768) {
1209 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1210 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1211 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1214 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1216 int b=0, m = iptr->val.i;
1219 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1221 M_ISUB(s1, REG_ITMP2, d);
1222 store_reg_to_var_int(iptr->dst, d);
1225 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1227 var_to_reg_int(s1, src->prev, REG_ITMP1);
1228 var_to_reg_int(s2, src, REG_ITMP2);
1229 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1231 store_reg_to_var_int(iptr->dst, d);
1234 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1235 /* val.i = constant */
1237 var_to_reg_int(s1, src, REG_ITMP1);
1238 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1239 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1240 M_OR_IMM(s1, iptr->val.i, d);
1243 ICONST(REG_ITMP2, iptr->val.i);
1244 M_OR(s1, REG_ITMP2, d);
1246 store_reg_to_var_int(iptr->dst, d);
1249 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1251 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1252 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1253 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1254 M_OR(s1, s2, rd->secondregs[d]);
1255 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1256 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1258 store_reg_to_var_int(iptr->dst, d);
1261 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1262 /* val.l = constant */
1264 s3 = iptr->val.l & 0xffffffff;
1265 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1266 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1267 if ((s3 >= 0) && (s3 <= 65535)) {
1268 M_OR_IMM(s1, s3, rd->secondregs[d]);
1271 ICONST(REG_ITMP2, s3);
1272 M_OR(s1, REG_ITMP2, rd->secondregs[d]);
1274 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1275 s3 = iptr->val.l >> 32;
1276 if ((s3 >= 0) && (s3 <= 65535)) {
1277 M_OR_IMM(s1, s3, d);
1280 ICONST(REG_ITMP3, s3);
1281 M_OR(s1, REG_ITMP3, d);
1283 store_reg_to_var_int(iptr->dst, d);
1286 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1288 var_to_reg_int(s1, src->prev, REG_ITMP1);
1289 var_to_reg_int(s2, src, REG_ITMP2);
1290 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1292 store_reg_to_var_int(iptr->dst, d);
1295 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1296 /* val.i = constant */
1298 var_to_reg_int(s1, src, REG_ITMP1);
1299 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1300 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1301 M_XOR_IMM(s1, iptr->val.i, d);
1304 ICONST(REG_ITMP2, iptr->val.i);
1305 M_XOR(s1, REG_ITMP2, d);
1307 store_reg_to_var_int(iptr->dst, d);
1310 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1312 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1313 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1314 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1315 M_XOR(s1, s2, rd->secondregs[d]);
1316 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1317 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1319 store_reg_to_var_int(iptr->dst, d);
1322 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1323 /* val.l = constant */
1325 s3 = iptr->val.l & 0xffffffff;
1326 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1327 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1328 if ((s3 >= 0) && (s3 <= 65535)) {
1329 M_XOR_IMM(s1, s3, rd->secondregs[d]);
1332 ICONST(REG_ITMP2, s3);
1333 M_XOR(s1, REG_ITMP2, rd->secondregs[d]);
1335 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1336 s3 = iptr->val.l >> 32;
1337 if ((s3 >= 0) && (s3 <= 65535)) {
1338 M_XOR_IMM(s1, s3, d);
1341 ICONST(REG_ITMP3, s3);
1342 M_XOR(s1, REG_ITMP3, d);
1344 store_reg_to_var_int(iptr->dst, d);
1347 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1349 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1350 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1351 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1354 (d==s1 || d==s2 || d==rd->secondregs[s1] || d==rd->secondregs[s2]);
1355 int dreg = tempreg ? REG_ITMP1 : d;
1357 M_IADD_IMM(REG_ZERO, 1, dreg);
1362 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1363 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1367 M_IADD_IMM(dreg, -1, dreg);
1368 M_IADD_IMM(dreg, -1, dreg);
1369 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1370 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1373 store_reg_to_var_int(iptr->dst, d);
1376 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1377 /* op1 = variable, val.i = constant */
1379 var = &(rd->locals[iptr->op1][TYPE_INT]);
1380 if (var->flags & INMEMORY) {
1382 M_ILD(s1, REG_SP, 4 * var->regoff);
1391 M_ADDIS(s1, m>>16, s1);
1393 M_IADD_IMM(s1, m&0xffff, s1);
1395 if (var->flags & INMEMORY)
1396 M_IST(s1, REG_SP, 4 * var->regoff);
1400 /* floating operations ************************************************/
1402 case ICMD_FNEG: /* ..., value ==> ..., - value */
1404 var_to_reg_flt(s1, src, REG_FTMP1);
1405 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1407 store_reg_to_var_flt(iptr->dst, d);
1410 case ICMD_DNEG: /* ..., value ==> ..., - value */
1412 var_to_reg_flt(s1, src, REG_FTMP1);
1413 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1415 store_reg_to_var_flt(iptr->dst, d);
1418 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1420 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1421 var_to_reg_flt(s2, src, REG_FTMP2);
1422 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1424 store_reg_to_var_flt(iptr->dst, d);
1427 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1429 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1430 var_to_reg_flt(s2, src, REG_FTMP2);
1431 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1433 store_reg_to_var_flt(iptr->dst, d);
1436 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1438 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1439 var_to_reg_flt(s2, src, REG_FTMP2);
1440 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1442 store_reg_to_var_flt(iptr->dst, d);
1445 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1447 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1448 var_to_reg_flt(s2, src, REG_FTMP2);
1449 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1451 store_reg_to_var_flt(iptr->dst, d);
1454 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1456 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1457 var_to_reg_flt(s2, src, REG_FTMP2);
1458 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1460 store_reg_to_var_flt(iptr->dst, d);
1463 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1465 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1466 var_to_reg_flt(s2, src, REG_FTMP2);
1467 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1469 store_reg_to_var_flt(iptr->dst, d);
1472 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1474 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1475 var_to_reg_flt(s2, src, REG_FTMP2);
1476 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1478 store_reg_to_var_flt(iptr->dst, d);
1481 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1483 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1484 var_to_reg_flt(s2, src, REG_FTMP2);
1485 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1487 store_reg_to_var_flt(iptr->dst, d);
1490 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1492 var_to_reg_flt(s1, src, REG_FTMP1);
1493 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1495 a = dseg_addfloat(cd, 0.0);
1496 M_FLD(REG_FTMP2, REG_PV, a);
1497 M_FCMPU(s1, REG_FTMP2);
1499 a = dseg_adds4(cd, 0);
1500 M_CVTDL_C(s1, REG_FTMP1);
1501 M_LDA (REG_ITMP1, REG_PV, a);
1502 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1503 M_ILD (d, REG_PV, a);
1504 store_reg_to_var_int(iptr->dst, d);
1507 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1509 var_to_reg_flt(s1, src, REG_FTMP1);
1510 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1512 store_reg_to_var_flt(iptr->dst, d);
1515 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1517 var_to_reg_flt(s1, src, REG_FTMP1);
1518 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1520 store_reg_to_var_flt(iptr->dst, d);
1523 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1525 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1526 var_to_reg_flt(s2, src, REG_FTMP2);
1527 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1529 M_IADD_IMM(0, -1, d);
1532 M_IADD_IMM(0, 0, d);
1534 M_IADD_IMM(0, 1, d);
1535 store_reg_to_var_int(iptr->dst, d);
1538 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1540 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1541 var_to_reg_flt(s2, src, REG_FTMP2);
1542 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1544 M_IADD_IMM(0, 1, d);
1547 M_IADD_IMM(0, 0, d);
1549 M_IADD_IMM(0, -1, d);
1550 store_reg_to_var_int(iptr->dst, d);
1554 /* memory operations **************************************************/
1556 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1558 var_to_reg_int(s1, src, REG_ITMP1);
1559 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1560 gen_nullptr_check(s1);
1561 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1562 store_reg_to_var_int(iptr->dst, d);
1565 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1567 var_to_reg_int(s1, src->prev, REG_ITMP1);
1568 var_to_reg_int(s2, src, REG_ITMP2);
1569 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1570 if (iptr->op1 == 0) {
1571 gen_nullptr_check(s1);
1574 M_SLL_IMM(s2, 2, REG_ITMP2);
1575 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1576 M_LWZX(d, s1, REG_ITMP2);
1577 store_reg_to_var_int(iptr->dst, d);
1580 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1582 var_to_reg_int(s1, src->prev, REG_ITMP1);
1583 var_to_reg_int(s2, src, REG_ITMP2);
1584 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1585 if (iptr->op1 == 0) {
1586 gen_nullptr_check(s1);
1589 M_SLL_IMM(s2, 3, REG_ITMP2);
1590 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1591 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1592 M_ILD(rd->secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1593 store_reg_to_var_int(iptr->dst, d);
1596 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1598 var_to_reg_int(s1, src->prev, REG_ITMP1);
1599 var_to_reg_int(s2, src, REG_ITMP2);
1600 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1601 if (iptr->op1 == 0) {
1602 gen_nullptr_check(s1);
1605 M_SLL_IMM(s2, 2, REG_ITMP2);
1606 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1607 M_LWZX(d, s1, REG_ITMP2);
1608 store_reg_to_var_int(iptr->dst, d);
1611 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1613 var_to_reg_int(s1, src->prev, REG_ITMP1);
1614 var_to_reg_int(s2, src, REG_ITMP2);
1615 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1616 if (iptr->op1 == 0) {
1617 gen_nullptr_check(s1);
1620 M_SLL_IMM(s2, 2, REG_ITMP2);
1621 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1622 M_LFSX(d, s1, REG_ITMP2);
1623 store_reg_to_var_flt(iptr->dst, d);
1626 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1628 var_to_reg_int(s1, src->prev, REG_ITMP1);
1629 var_to_reg_int(s2, src, REG_ITMP2);
1630 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1631 if (iptr->op1 == 0) {
1632 gen_nullptr_check(s1);
1635 M_SLL_IMM(s2, 3, REG_ITMP2);
1636 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1637 M_LFDX(d, s1, REG_ITMP2);
1638 store_reg_to_var_flt(iptr->dst, d);
1641 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1643 var_to_reg_int(s1, src->prev, REG_ITMP1);
1644 var_to_reg_int(s2, src, REG_ITMP2);
1645 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1646 if (iptr->op1 == 0) {
1647 gen_nullptr_check(s1);
1650 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1651 M_LBZX(d, s1, REG_ITMP2);
1653 store_reg_to_var_int(iptr->dst, d);
1656 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1658 var_to_reg_int(s1, src->prev, REG_ITMP1);
1659 var_to_reg_int(s2, src, REG_ITMP2);
1660 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1661 if (iptr->op1 == 0) {
1662 gen_nullptr_check(s1);
1665 M_SLL_IMM(s2, 1, REG_ITMP2);
1666 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1667 M_LHAX(d, s1, REG_ITMP2);
1668 store_reg_to_var_int(iptr->dst, d);
1671 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1673 var_to_reg_int(s1, src->prev, REG_ITMP1);
1674 var_to_reg_int(s2, src, REG_ITMP2);
1675 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1676 if (iptr->op1 == 0) {
1677 gen_nullptr_check(s1);
1680 M_SLL_IMM(s2, 1, REG_ITMP2);
1681 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1682 M_LHZX(d, s1, REG_ITMP2);
1683 store_reg_to_var_int(iptr->dst, d);
1686 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1688 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1689 var_to_reg_int(s2, src->prev, REG_ITMP2);
1690 if (iptr->op1 == 0) {
1691 gen_nullptr_check(s1);
1694 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1695 M_SLL_IMM(s2, 3, REG_ITMP2);
1696 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1697 M_STWX(s3, s1, REG_ITMP2);
1698 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1699 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1700 M_STWX(s3, s1, REG_ITMP2);
1703 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1705 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1706 var_to_reg_int(s2, src->prev, REG_ITMP2);
1707 if (iptr->op1 == 0) {
1708 gen_nullptr_check(s1);
1711 var_to_reg_int(s3, src, REG_ITMP3);
1712 M_SLL_IMM(s2, 2, REG_ITMP2);
1713 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1714 M_STWX(s3, s1, REG_ITMP2);
1717 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1719 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1720 var_to_reg_int(s2, src->prev, REG_ITMP2);
1721 if (iptr->op1 == 0) {
1722 gen_nullptr_check(s1);
1725 var_to_reg_flt(s3, src, REG_FTMP3);
1726 M_SLL_IMM(s2, 2, REG_ITMP2);
1727 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1728 M_STFSX(s3, s1, REG_ITMP2);
1731 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1733 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1734 var_to_reg_int(s2, src->prev, REG_ITMP2);
1735 if (iptr->op1 == 0) {
1736 gen_nullptr_check(s1);
1739 var_to_reg_flt(s3, src, REG_FTMP3);
1740 M_SLL_IMM(s2, 3, REG_ITMP2);
1741 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1742 M_STFDX(s3, s1, REG_ITMP2);
1745 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1747 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1748 var_to_reg_int(s2, src->prev, REG_ITMP2);
1749 if (iptr->op1 == 0) {
1750 gen_nullptr_check(s1);
1753 var_to_reg_int(s3, src, REG_ITMP3);
1754 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1755 M_STBX(s3, s1, REG_ITMP2);
1758 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1760 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1761 var_to_reg_int(s2, src->prev, REG_ITMP2);
1762 if (iptr->op1 == 0) {
1763 gen_nullptr_check(s1);
1766 var_to_reg_int(s3, src, REG_ITMP3);
1767 M_SLL_IMM(s2, 1, REG_ITMP2);
1768 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1769 M_STHX(s3, s1, REG_ITMP2);
1772 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1774 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1775 var_to_reg_int(s2, src->prev, REG_ITMP2);
1776 if (iptr->op1 == 0) {
1777 gen_nullptr_check(s1);
1780 var_to_reg_int(s3, src, REG_ITMP3);
1781 M_SLL_IMM(s2, 1, REG_ITMP2);
1782 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1783 M_STHX(s3, s1, REG_ITMP2);
1786 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1787 /* op1 = type, val.a = field address */
1789 /* if class isn't yet initialized, do it */
1790 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1791 /* call helper function which patches this code */
1792 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1793 M_ALD(REG_ITMP1, REG_PV, a);
1794 a = dseg_addaddress(cd, asm_check_clinit);
1795 M_ALD(REG_PV, REG_PV, a);
1800 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1802 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1804 s4 ml = -s1, mh = 0;
1805 while (ml < -32768) { ml += 65536; mh--; }
1806 M_LDA(REG_PV, REG_ITMP1, ml);
1807 M_LDAH(REG_PV, REG_PV, mh);
1811 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1812 M_ALD(REG_ITMP1, REG_PV, a);
1813 switch (iptr->op1) {
1815 var_to_reg_int(s2, src, REG_ITMP2);
1816 M_IST(s2, REG_ITMP1, 0);
1819 var_to_reg_int(s2, src, REG_ITMP3);
1820 M_IST(s2, REG_ITMP1, 0);
1821 M_IST(rd->secondregs[s2], REG_ITMP1, 4);
1824 var_to_reg_int(s2, src, REG_ITMP2);
1825 M_AST(s2, REG_ITMP1, 0);
1828 var_to_reg_flt(s2, src, REG_FTMP2);
1829 M_FST(s2, REG_ITMP1, 0);
1832 var_to_reg_flt(s2, src, REG_FTMP2);
1833 M_DST(s2, REG_ITMP1, 0);
1835 default: panic ("internal error");
1839 case ICMD_GETSTATIC: /* ... ==> ..., value */
1840 /* op1 = type, val.a = field address */
1842 /* if class isn't yet initialized, do it */
1843 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1844 /* call helper function which patches this code */
1845 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1846 M_ALD(REG_ITMP1, REG_PV, a);
1847 a = dseg_addaddress(cd, asm_check_clinit);
1848 M_ALD(REG_PV, REG_PV, a);
1853 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1855 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1857 s4 ml = -s1, mh = 0;
1858 while (ml < -32768) { ml += 65536; mh--; }
1859 M_LDA(REG_PV, REG_ITMP1, ml);
1860 M_LDAH(REG_PV, REG_PV, mh);
1864 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1865 M_ALD(REG_ITMP1, REG_PV, a);
1866 switch (iptr->op1) {
1868 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1869 M_ILD(d, REG_ITMP1, 0);
1870 store_reg_to_var_int(iptr->dst, d);
1873 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1874 M_ILD(d, REG_ITMP1, 0);
1875 M_ILD(rd->secondregs[d], REG_ITMP1, 4);
1876 store_reg_to_var_int(iptr->dst, d);
1879 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1880 M_ALD(d, REG_ITMP1, 0);
1881 store_reg_to_var_int(iptr->dst, d);
1884 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1885 M_FLD(d, REG_ITMP1, 0);
1886 store_reg_to_var_flt(iptr->dst, d);
1889 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1890 M_DLD(d, REG_ITMP1, 0);
1891 store_reg_to_var_flt(iptr->dst, d);
1893 default: panic ("internal error");
1898 case ICMD_PUTFIELD: /* ..., value ==> ... */
1899 /* op1 = type, val.i = field offset */
1901 a = ((fieldinfo *)(iptr->val.a))->offset;
1902 switch (iptr->op1) {
1904 var_to_reg_int(s1, src->prev, REG_ITMP1);
1905 var_to_reg_int(s2, src, REG_ITMP2);
1906 gen_nullptr_check(s1);
1910 var_to_reg_int(s1, src->prev, REG_ITMP1);
1911 var_to_reg_int(s2, src, REG_ITMP3);
1912 gen_nullptr_check(s1);
1914 M_IST(rd->secondregs[s2], s1, a+4);
1917 var_to_reg_int(s1, src->prev, REG_ITMP1);
1918 var_to_reg_int(s2, src, REG_ITMP2);
1919 gen_nullptr_check(s1);
1923 var_to_reg_int(s1, src->prev, REG_ITMP1);
1924 var_to_reg_flt(s2, src, REG_FTMP2);
1925 gen_nullptr_check(s1);
1929 var_to_reg_int(s1, src->prev, REG_ITMP1);
1930 var_to_reg_flt(s2, src, REG_FTMP2);
1931 gen_nullptr_check(s1);
1934 default: panic ("internal error");
1938 case ICMD_GETFIELD: /* ... ==> ..., value */
1939 /* op1 = type, val.i = field offset */
1941 a = ((fieldinfo *)(iptr->val.a))->offset;
1942 switch (iptr->op1) {
1944 var_to_reg_int(s1, src, REG_ITMP1);
1945 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1946 gen_nullptr_check(s1);
1948 store_reg_to_var_int(iptr->dst, d);
1951 var_to_reg_int(s1, src, REG_ITMP1);
1952 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1953 gen_nullptr_check(s1);
1955 M_ILD(rd->secondregs[d], s1, a+4);
1956 store_reg_to_var_int(iptr->dst, d);
1959 var_to_reg_int(s1, src, REG_ITMP1);
1960 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1961 gen_nullptr_check(s1);
1963 store_reg_to_var_int(iptr->dst, d);
1966 var_to_reg_int(s1, src, REG_ITMP1);
1967 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1968 gen_nullptr_check(s1);
1970 store_reg_to_var_flt(iptr->dst, d);
1973 var_to_reg_int(s1, src, REG_ITMP1);
1974 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1975 gen_nullptr_check(s1);
1977 store_reg_to_var_flt(iptr->dst, d);
1979 default: panic ("internal error");
1984 /* branch operations **************************************************/
1986 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1988 a = dseg_addaddress(cd, asm_handle_exception);
1989 M_ALD(REG_ITMP2, REG_PV, a);
1991 var_to_reg_int(s1, src, REG_ITMP1);
1992 M_INTMOVE(s1, REG_ITMP1_XPTR);
1994 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
1995 M_BL(0); /* get current PC */
1996 M_MFLR(REG_ITMP2_XPC);
1997 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
1998 M_RTS; /* jump to CTR */
2003 case ICMD_GOTO: /* ... ==> ... */
2004 /* op1 = target JavaVM pc */
2006 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2010 case ICMD_JSR: /* ... ==> ... */
2011 /* op1 = target JavaVM pc */
2013 if (m->isleafmethod) M_MFLR(REG_ITMP2);
2016 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
2017 if (m->isleafmethod) M_MTLR(REG_ITMP2);
2019 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2022 case ICMD_RET: /* ... ==> ... */
2023 /* op1 = local variable */
2025 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2026 if (var->flags & INMEMORY) {
2027 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2031 M_MTCTR(var->regoff);
2036 case ICMD_IFNULL: /* ..., value ==> ... */
2037 /* op1 = target JavaVM pc */
2039 var_to_reg_int(s1, src, REG_ITMP1);
2042 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2045 case ICMD_IFNONNULL: /* ..., value ==> ... */
2046 /* op1 = target JavaVM pc */
2048 var_to_reg_int(s1, src, REG_ITMP1);
2051 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2059 case ICMD_IFEQ: /* ..., value ==> ... */
2060 /* op1 = target JavaVM pc, val.i = constant */
2062 var_to_reg_int(s1, src, REG_ITMP1);
2063 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2064 M_CMPI(s1, iptr->val.i);
2067 ICONST(REG_ITMP2, iptr->val.i);
2068 M_CMP(s1, REG_ITMP2);
2091 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2095 case ICMD_IF_LEQ: /* ..., value ==> ... */
2096 /* op1 = target JavaVM pc, val.l = constant */
2098 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2099 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2100 if (iptr->val.l == 0) {
2101 M_OR(s1, s2, REG_ITMP3);
2102 M_CMPI(REG_ITMP3, 0);
2104 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2105 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2107 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2110 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2111 M_CMP(s2, REG_ITMP3);
2113 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2114 M_CMP(s1, REG_ITMP3)
2117 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2120 case ICMD_IF_LLT: /* ..., value ==> ... */
2121 /* op1 = target JavaVM pc, val.l = constant */
2122 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2123 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2124 /* if (iptr->val.l == 0) { */
2125 /* M_OR(s1, s2, REG_ITMP3); */
2126 /* M_CMPI(REG_ITMP3, 0); */
2129 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2130 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2132 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2134 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2137 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2138 M_CMP(s2, REG_ITMP3);
2140 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2142 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2143 M_CMP(s1, REG_ITMP3)
2146 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2149 case ICMD_IF_LLE: /* ..., value ==> ... */
2150 /* op1 = target JavaVM pc, val.l = constant */
2152 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2153 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2154 /* if (iptr->val.l == 0) { */
2155 /* M_OR(s1, s2, REG_ITMP3); */
2156 /* M_CMPI(REG_ITMP3, 0); */
2159 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2160 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2162 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2164 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2167 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2168 M_CMP(s2, REG_ITMP3);
2170 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2172 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2173 M_CMP(s1, REG_ITMP3)
2176 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2179 case ICMD_IF_LNE: /* ..., value ==> ... */
2180 /* op1 = target JavaVM pc, val.l = constant */
2182 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2183 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2184 if (iptr->val.l == 0) {
2185 M_OR(s1, s2, REG_ITMP3);
2186 M_CMPI(REG_ITMP3, 0);
2188 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2189 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2191 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2194 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2195 M_CMP(s2, REG_ITMP3);
2197 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2198 M_CMP(s1, REG_ITMP3)
2201 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2204 case ICMD_IF_LGT: /* ..., value ==> ... */
2205 /* op1 = target JavaVM pc, val.l = constant */
2207 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2208 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2209 /* if (iptr->val.l == 0) { */
2210 /* M_OR(s1, s2, REG_ITMP3); */
2211 /* M_CMPI(REG_ITMP3, 0); */
2214 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2215 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2217 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2219 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2222 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2223 M_CMP(s2, REG_ITMP3);
2225 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2227 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2228 M_CMP(s1, REG_ITMP3)
2231 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2234 case ICMD_IF_LGE: /* ..., value ==> ... */
2235 /* op1 = target JavaVM pc, val.l = constant */
2236 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2237 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2238 /* if (iptr->val.l == 0) { */
2239 /* M_OR(s1, s2, REG_ITMP3); */
2240 /* M_CMPI(REG_ITMP3, 0); */
2243 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2244 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2246 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2248 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2251 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2252 M_CMP(s2, REG_ITMP3);
2254 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2256 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2257 M_CMP(s1, REG_ITMP3)
2260 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2264 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2265 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2266 case ICMD_IF_ACMPEQ:
2268 var_to_reg_int(s1, src->prev, REG_ITMP1);
2269 var_to_reg_int(s2, src, REG_ITMP2);
2272 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2275 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2276 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2277 case ICMD_IF_ACMPNE:
2279 var_to_reg_int(s1, src->prev, REG_ITMP1);
2280 var_to_reg_int(s2, src, REG_ITMP2);
2283 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2286 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2287 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2289 var_to_reg_int(s1, src->prev, REG_ITMP1);
2290 var_to_reg_int(s2, src, REG_ITMP2);
2293 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2296 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2297 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2299 var_to_reg_int(s1, src->prev, REG_ITMP1);
2300 var_to_reg_int(s2, src, REG_ITMP2);
2303 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2306 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2307 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2309 var_to_reg_int(s1, src->prev, REG_ITMP1);
2310 var_to_reg_int(s2, src, REG_ITMP2);
2313 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2316 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2317 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2319 var_to_reg_int(s1, src->prev, REG_ITMP1);
2320 var_to_reg_int(s2, src, REG_ITMP2);
2323 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2326 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2330 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2333 case ICMD_RETURN: /* ... ==> ... */
2335 #if defined(USE_THREADS)
2336 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2337 a = dseg_addaddress(cd, (void *) (builtin_monitorexit));
2338 M_ALD(REG_ITMP3, REG_PV, a);
2340 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
2344 switch (iptr->opc) {
2348 var_to_reg_int(s1, src, REG_RESULT);
2349 M_TINTMOVE(src->type, s1, REG_RESULT);
2350 goto nowperformreturn;
2354 var_to_reg_flt(s1, src, REG_FRESULT);
2355 M_FLTMOVE(s1, REG_FRESULT);
2356 goto nowperformreturn;
2363 p = parentargs_base;
2365 /* restore return address */
2367 if (!m->isleafmethod) {
2368 M_ALD(REG_ITMP3, REG_SP, 4 * p + 8);
2372 /* restore saved registers */
2374 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2375 p--; M_ILD(rd->savintregs[i], REG_SP, 4 * p);
2377 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2378 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, 4 * p);
2381 /* deallocate stack */
2383 if (parentargs_base) {
2384 M_LDA(REG_SP, REG_SP, parentargs_base*4);
2387 /* call trace function */
2391 M_LDA(REG_SP, REG_SP, -10 * 8);
2392 M_DST(REG_FRESULT, REG_SP, 48+0);
2393 M_IST(REG_RESULT, REG_SP, 48+8);
2394 M_AST(REG_ITMP3, REG_SP, 48+12);
2395 M_IST(REG_RESULT2, REG_SP, 48+16);
2396 a = dseg_addaddress(cd, m);
2398 /* keep this order */
2399 switch (iptr->opc) {
2402 M_MOV(REG_RESULT, rd->argintregs[2]);
2403 M_CLR(rd->argintregs[1]);
2407 M_MOV(REG_RESULT2, rd->argintregs[2]);
2408 M_MOV(REG_RESULT, rd->argintregs[1]);
2411 M_ALD(rd->argintregs[0], REG_PV, a);
2413 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2414 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2415 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2416 M_ALD(REG_ITMP2, REG_PV, a);
2419 M_DLD(REG_FRESULT, REG_SP, 48+0);
2420 M_ILD(REG_RESULT, REG_SP, 48+8);
2421 M_ALD(REG_ITMP3, REG_SP, 48+12);
2422 M_ILD(REG_RESULT2, REG_SP, 48+16);
2423 M_LDA(REG_SP, REG_SP, 10 * 8);
2433 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2438 tptr = (void **) iptr->target;
2440 s4ptr = iptr->val.a;
2441 l = s4ptr[1]; /* low */
2442 i = s4ptr[2]; /* high */
2444 var_to_reg_int(s1, src, REG_ITMP1);
2446 M_INTMOVE(s1, REG_ITMP1);
2447 } else if (l <= 32768) {
2448 M_LDA(REG_ITMP1, s1, -l);
2450 ICONST(REG_ITMP2, l);
2451 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2457 M_CMPUI(REG_ITMP1, i - 1);
2460 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2461 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2463 /* build jump table top down and use address of lowest entry */
2465 /* s4ptr += 3 + i; */
2469 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2470 dseg_addtarget(cd, (basicblock *) tptr[0]);
2475 /* length of dataseg after last dseg_addtarget is used by load */
2477 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2478 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2479 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2486 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2488 s4 i, l, val, *s4ptr;
2491 tptr = (void **) iptr->target;
2493 s4ptr = iptr->val.a;
2494 l = s4ptr[0]; /* default */
2495 i = s4ptr[1]; /* count */
2497 MCODECHECK((i<<2)+8);
2498 var_to_reg_int(s1, src, REG_ITMP1);
2504 if ((val >= -32768) && (val <= 32767)) {
2508 a = dseg_adds4(cd, val);
2509 M_ILD(REG_ITMP2, REG_PV, a);
2510 M_CMP(s1, REG_ITMP2);
2513 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2514 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2518 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2520 tptr = (void **) iptr->target;
2521 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2528 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2529 /* op1 = return type, val.a = function pointer*/
2533 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2534 /* op1 = return type, val.a = function pointer*/
2538 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2539 /* op1 = return type, val.a = function pointer*/
2543 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2544 /* op1 = arg count, val.a = method pointer */
2546 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2547 /* op1 = arg count, val.a = method pointer */
2549 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2550 /* op1 = arg count, val.a = method pointer */
2552 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2553 /* op1 = arg count, val.a = method pointer */
2561 MCODECHECK((s3 << 1) + 64);
2564 /* copy arguments to registers or stack location */
2566 stackptr srcsave = src;
2570 for (; --s3 >= 0; src = src->prev) {
2571 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2572 if (IS_FLT_DBL_TYPE(src->type))
2576 for (s3 = s3save, src = srcsave; --s3 >= 0; src = src->prev) {
2577 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2578 if (IS_FLT_DBL_TYPE(src->type))
2580 if (src->varkind == ARGVAR)
2582 if (IS_INT_LNG_TYPE(src->type)) {
2583 if (argsize < INT_ARG_CNT) {
2584 s1 = rd->argintregs[argsize];
2585 var_to_reg_int(d, src, s1);
2586 if (argsize < INT_ARG_CNT-1) {
2587 M_TINTMOVE(src->type, d, s1);
2591 if (IS_2_WORD_TYPE(src->type))
2592 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2596 var_to_reg_int(d, src, REG_ITMP1);
2597 M_IST(d, REG_SP, 4 * (argsize + 6));
2598 if (IS_2_WORD_TYPE(src->type))
2599 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2603 if (fltcnt < FLT_ARG_CNT) {
2604 s1 = rd->argfltregs[fltcnt];
2605 var_to_reg_flt(d, src, s1);
2609 var_to_reg_flt(d, src, REG_FTMP1);
2610 if (IS_2_WORD_TYPE(src->type))
2611 M_DST(d, REG_SP, 4 * (argsize + 6));
2613 M_FST(d, REG_SP, 4 * (argsize + 6));
2620 switch (iptr->opc) {
2624 a = dseg_addaddress(cd, (void *) lm);
2626 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2628 goto makeactualcall;
2630 case ICMD_INVOKESTATIC:
2631 case ICMD_INVOKESPECIAL:
2632 a = dseg_addaddress(cd, lm->stubroutine);
2634 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2637 goto makeactualcall;
2639 case ICMD_INVOKEVIRTUAL:
2641 gen_nullptr_check(rd->argintregs[0]);
2642 M_ALD(REG_METHODPTR, rd->argintregs[0],
2643 OFFSET(java_objectheader, vftbl));
2644 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) +
2645 sizeof(methodptr) * lm->vftblindex);
2648 goto makeactualcall;
2650 case ICMD_INVOKEINTERFACE:
2653 gen_nullptr_check(rd->argintregs[0]);
2654 M_ALD(REG_METHODPTR, rd->argintregs[0],
2655 OFFSET(java_objectheader, vftbl));
2656 M_ALD(REG_METHODPTR, REG_METHODPTR,
2657 OFFSET(vftbl_t, interfacetable[0]) -
2658 sizeof(methodptr*) * ci->index);
2659 M_ALD(REG_PV, REG_METHODPTR,
2660 sizeof(methodptr) * (lm - ci->methods));
2663 goto makeactualcall;
2667 error ("Unkown ICMD-Command: %d", iptr->opc);
2676 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2678 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2680 s4 ml = -s1, mh = 0;
2681 while (ml < -32768) { ml += 65536; mh--; }
2682 M_LDA(REG_PV, REG_ITMP1, ml);
2683 M_LDAH(REG_PV, REG_PV, mh);
2686 /* d contains return type */
2688 if (d != TYPE_VOID) {
2689 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2690 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2691 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2692 store_reg_to_var_int(iptr->dst, s1);
2695 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2696 M_FLTMOVE(REG_FRESULT, s1);
2697 store_reg_to_var_flt(iptr->dst, s1);
2704 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2706 /* op1: 0 == array, 1 == class */
2707 /* val.a: (classinfo*) superclass */
2709 /* superclass is an interface:
2711 * return (sub != NULL) &&
2712 * (sub->vftbl->interfacetablelength > super->index) &&
2713 * (sub->vftbl->interfacetable[-super->index] != NULL);
2715 * superclass is a class:
2717 * return ((sub != NULL) && (0
2718 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2719 * super->vftbl->diffvall));
2723 classinfo *super = (classinfo*) iptr->val.a;
2725 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2726 codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
2728 var_to_reg_int(s1, src, REG_ITMP1);
2729 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2731 M_MOV(s1, REG_ITMP1);
2735 if (iptr->op1) { /* class/interface */
2737 if (super->flags & ACC_INTERFACE) { /* interface */
2739 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2740 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2741 M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2743 M_ALD(REG_ITMP1, REG_ITMP1,
2744 OFFSET(vftbl_t, interfacetable[0]) -
2745 super->index * sizeof(methodptr*));
2749 M_IADD_IMM(REG_ZERO, 1, d);
2753 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2754 a = dseg_addaddress(cd, (void*) super->vftbl);
2755 M_ALD(REG_ITMP2, REG_PV, a);
2756 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2757 codegen_threadcritstart((u1*) mcodeptr - mcodebase);
2759 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2760 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2761 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2762 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2763 codegen_threadcritstop((u1*) mcodeptr - mcodebase);
2765 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2766 M_CMPU(REG_ITMP1, REG_ITMP2);
2769 M_IADD_IMM(REG_ZERO, 1, d);
2773 panic ("internal error: no inlined array instanceof");
2775 store_reg_to_var_int(iptr->dst, d);
2778 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2780 /* op1: 0 == array, 1 == class */
2781 /* val.a: (classinfo*) superclass */
2783 /* superclass is an interface:
2785 * OK if ((sub == NULL) ||
2786 * (sub->vftbl->interfacetablelength > super->index) &&
2787 * (sub->vftbl->interfacetable[-super->index] != NULL));
2789 * superclass is a class:
2791 * OK if ((sub == NULL) || (0
2792 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2793 * super->vftbl->diffvall));
2797 classinfo *super = (classinfo*) iptr->val.a;
2799 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2800 codegen_threadcritrestart(cd, (u1*) mcodeptr - mcodebase);
2802 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2803 var_to_reg_int(s1, src, d);
2804 if (iptr->op1) { /* class/interface */
2806 if (super->flags & ACC_INTERFACE) { /* interface */
2808 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2809 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2810 M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
2812 codegen_addxcastrefs(cd, mcodeptr);
2813 M_ALD(REG_ITMP3, REG_ITMP2,
2814 OFFSET(vftbl_t, interfacetable[0]) -
2815 super->index * sizeof(methodptr*));
2818 codegen_addxcastrefs(cd, mcodeptr);
2821 M_BEQ(8 + (s1 == REG_ITMP1));
2822 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2823 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2824 codegen_threadcritstart(cd, (u1*) mcodeptr - mcodebase);
2826 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2827 a = dseg_addaddress(cd, (void*) super->vftbl);
2828 M_ALD(REG_ITMP2, REG_PV, a);
2829 if (d != REG_ITMP1) {
2830 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2831 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2832 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2833 codegen_threadcritstop(cd, (u1*) mcodeptr - mcodebase);
2835 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2838 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2839 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2840 M_ALD(REG_ITMP2, REG_PV, a);
2841 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2842 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2843 codegen_threadcritstop(cd, (u1*) mcodeptr - mcodebase);
2846 M_CMPU(REG_ITMP3, REG_ITMP2);
2848 codegen_addxcastrefs(cd, mcodeptr);
2852 panic ("internal error: no inlined array checkcast");
2855 store_reg_to_var_int(iptr->dst, d);
2858 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
2860 var_to_reg_int(s1, src, REG_ITMP1);
2863 codegen_addxcheckarefs(cd, mcodeptr);
2866 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
2868 M_CMPI(REG_RESULT, 0);
2870 codegen_addxexceptionrefs(cd, mcodeptr);
2873 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2874 /* op1 = dimension, val.a = array descriptor */
2876 /* check for negative sizes and copy sizes to stack if necessary */
2878 MCODECHECK((iptr->op1 << 1) + 64);
2880 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
2881 var_to_reg_int(s2, src, REG_ITMP1);
2884 codegen_addxcheckarefs(cd, mcodeptr);
2886 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
2888 if (src->varkind != ARGVAR) {
2889 M_IST(s2, REG_SP, 4 * (s1 + INT_ARG_CNT + 6));
2893 /* a0 = dimension count */
2895 ICONST(rd->argintregs[0], iptr->op1);
2897 /* a1 = arraydescriptor */
2899 a = dseg_addaddress(cd, iptr->val.a);
2900 M_ALD(rd->argintregs[1], REG_PV, a);
2902 /* a2 = pointer to dimensions = stack pointer */
2904 M_LDA(rd->argintregs[2], REG_SP, (INT_ARG_CNT + 6)*4);
2906 a = dseg_addaddress(cd, (void *) builtin_nmultianewarray);
2907 M_ALD(REG_PV, REG_PV, a);
2910 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2913 M_LDA (REG_PV, REG_ITMP1, -s1);
2915 s4 ml = -s1, mh = 0;
2916 while (ml < -32768) {ml += 65536; mh--;}
2917 M_LDA(REG_PV, REG_ITMP1, ml);
2918 M_LDAH(REG_PV, REG_PV, mh);
2920 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2921 M_INTMOVE(REG_RESULT, s1);
2922 store_reg_to_var_int(iptr->dst, s1);
2926 default: error ("Unknown pseudo command: %d", iptr->opc);
2930 } /* for instruction */
2932 /* copy values to interface registers */
2934 src = bptr->outstack;
2935 len = bptr->outdepth;
2936 MCODECHECK(64 + len);
2939 if ((src->varkind != STACKVAR)) {
2941 if (IS_FLT_DBL_TYPE(s2)) {
2942 var_to_reg_flt(s1, src, REG_FTMP1);
2943 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
2944 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
2947 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
2951 var_to_reg_int(s1, src, REG_ITMP1);
2952 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
2953 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
2956 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
2957 if (IS_2_WORD_TYPE(s2))
2958 M_IST(rd->secondregs[s1], REG_SP, rd->interfaces[len][s2].regoff * 4 + 4);
2964 } /* if (bptr -> flags >= BBREACHED) */
2965 } /* for basic block */
2967 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
2970 /* generate bound check stubs */
2972 s4 *xcodeptr = NULL;
2975 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
2976 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
2978 (u1 *) cd->mcodeptr - cd->mcodebase);
2982 /* move index register into REG_ITMP1 */
2983 M_MOV(bref->reg, REG_ITMP1);
2984 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
2986 if (xcodeptr != NULL) {
2987 M_BR(xcodeptr - mcodeptr - 1);
2990 xcodeptr = mcodeptr;
2992 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
2993 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
2995 a = dseg_addaddress(cd, string_java_lang_ArrayIndexOutOfBoundsException);
2996 M_ALD(rd->argintregs[0], REG_PV, a);
2997 M_MOV(REG_ITMP1, rd->argintregs[1]);
2999 a = dseg_addaddress(cd, new_exception_int);
3000 M_ALD(REG_ITMP2, REG_PV, a);
3003 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3005 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3006 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3008 a = dseg_addaddress(cd, asm_handle_exception);
3009 M_ALD(REG_ITMP3, REG_PV, a);
3016 /* generate negative array size check stubs */
3020 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3021 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3022 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3024 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3028 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3030 (u1 *) mcodeptr - cd->mcodebase);
3034 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3036 if (xcodeptr != NULL) {
3037 M_BR(xcodeptr - mcodeptr - 1);
3040 xcodeptr = mcodeptr;
3042 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3043 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3045 a = dseg_addaddress(cd, string_java_lang_NegativeArraySizeException);
3046 M_ALD(rd->argintregs[0], REG_PV, a);
3048 a = dseg_addaddress(cd, new_exception);
3049 M_ALD(REG_ITMP2, REG_PV, a);
3052 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3054 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3055 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3057 a = dseg_addaddress(cd, asm_handle_exception);
3058 M_ALD(REG_ITMP3, REG_PV, a);
3065 /* generate cast check stubs */
3069 for (bref = cd->xcastrefs; bref != NULL; bref = bref->next) {
3070 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3071 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3073 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3077 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3079 (u1 *) mcodeptr - cd->mcodebase);
3083 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3085 if (xcodeptr != NULL) {
3086 M_BR(xcodeptr - mcodeptr - 1);
3089 xcodeptr = mcodeptr;
3091 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3092 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3094 a = dseg_addaddress(cd, string_java_lang_ClassCastException);
3095 M_ALD(rd->argintregs[0], REG_PV, a);
3097 a = dseg_addaddress(cd, new_exception);
3098 M_ALD(REG_ITMP2, REG_PV, a);
3101 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3103 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3104 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3106 a = dseg_addaddress(cd, asm_handle_exception);
3107 M_ALD(REG_ITMP3, REG_PV, a);
3114 /* generate exception check stubs */
3118 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3119 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3120 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3122 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3126 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3128 (u1 *) mcodeptr - cd->mcodebase);
3132 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3134 if (xcodeptr != NULL) {
3135 M_BR(xcodeptr - mcodeptr - 1);
3138 xcodeptr = mcodeptr;
3140 /* XXX this cannot work - there is no link area */
3141 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3142 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3144 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3145 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3146 M_ALD(REG_ITMP2, REG_PV, a);
3149 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3151 a = dseg_addaddress(cd, &_exceptionptr);
3152 M_ALD(REG_ITMP2, REG_PV, a);
3154 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3156 M_AST(REG_ITMP3, REG_ITMP2, 0);
3159 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3160 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3162 a = dseg_addaddress(cd, asm_handle_exception);
3163 M_ALD(REG_ITMP3, REG_PV, a);
3169 /* generate null pointer check stubs */
3173 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3174 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3175 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3177 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3181 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3183 (u1 *) mcodeptr - cd->mcodebase);
3187 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3189 if (xcodeptr != NULL) {
3190 M_BR(xcodeptr - mcodeptr - 1);
3193 xcodeptr = mcodeptr;
3195 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3196 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3198 a = dseg_addaddress(cd, string_java_lang_NullPointerException);
3199 M_ALD(rd->argintregs[0], REG_PV, a);
3201 a = dseg_addaddress(cd, new_exception);
3202 M_ALD(REG_ITMP2, REG_PV, a);
3205 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3207 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3208 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3210 a = dseg_addaddress(cd, asm_handle_exception);
3211 M_ALD(REG_ITMP3, REG_PV, a);
3218 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3220 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3224 /* function createcompilerstub *************************************************
3226 creates a stub routine which calls the compiler
3228 *******************************************************************************/
3230 #define COMPSTUBSIZE 6
3232 u1 *createcompilerstub(methodinfo *m)
3234 s4 *s = CNEW (s4, COMPSTUBSIZE); /* memory to hold the stub */
3235 s4 *mcodeptr = s; /* code generation pointer */
3237 M_LDA(2, REG_PV, 4*4);
3238 M_ALD(REG_PV, REG_PV, 5*4);
3242 s[4] = (s4) m; /* literals to be adressed */
3243 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3245 asm_cacheflush((void*) s, (u1*) mcodeptr - (u1*) s);
3247 #if defined(STATISTICS)
3249 count_cstub_len += COMPSTUBSIZE * 4;
3256 /* function removecompilerstub *************************************************
3258 deletes a compilerstub from memory (simply by freeing it)
3260 *******************************************************************************/
3262 void removecompilerstub(u1 *stub)
3264 CFREE(stub, COMPSTUBSIZE * 4);
3268 /* function: createnativestub **************************************************
3270 creates a stub routine which calls a native method
3272 *******************************************************************************/
3274 #define NATIVESTUBSIZE 200
3275 #define NATIVESTUBOFFSET 9
3277 u1 *createnativestub(functionptr f, methodinfo *m)
3279 s4 *s; /* memory to hold the stub */
3281 s4 *mcodeptr; /* code generation pointer */
3282 s4 stackframesize = 0; /* size of stackframe if needed */
3285 t_inlining_globals *id;
3288 /* mark start of dump memory area */
3290 dumpsize = dump_size();
3292 /* setup registers before using it */
3294 rd = DNEW(registerdata);
3295 id = DNEW(t_inlining_globals);
3297 inlining_setup(m, id);
3298 reg_setup(m, rd, id);
3300 descriptor2types(m); /* set paramcount and paramtypes */
3302 s = CNEW(s4, NATIVESTUBSIZE);
3303 cs = s + NATIVESTUBOFFSET;
3306 *(cs-1) = (u4) f; /* address of native method */
3307 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3308 *(cs-2) = (u4) builtin_get_exceptionptrptr;
3310 *(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
3312 *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
3313 *(cs-4) = (u4) (&env); /* addr of jni_environement */
3314 *(cs-5) = (u4) builtin_trace_args;
3316 *(cs-7) = (u4) builtin_displaymethodstop;
3317 *(cs-8) = (u4) m->class;
3318 *(cs-9) = (u4) asm_check_clinit;
3321 M_AST(REG_ITMP1, REG_SP, 8); /* store return address */
3322 M_LDA(REG_SP, REG_SP, -64); /* build up stackframe */
3324 /* if function is static, check for initialized */
3326 if (m->flags & ACC_STATIC) {
3327 /* if class isn't yet initialized, do it */
3328 if (!m->class->initialized) {
3329 /* call helper function which patches this code */
3330 M_ALD(REG_ITMP1, REG_PV, -8 * 4); /* class */
3331 M_ALD(REG_PV, REG_PV, -9 * 4); /* asm_check_clinit */
3334 disp = -(s4) (mcodeptr - cs) * 4;
3336 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3346 /* M_MFLR(REG_ITMP3); */
3347 /* XXX must be a multiple of 16 */
3348 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3350 /* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3354 /* save all arguments into the reserved stack space */
3355 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3356 t = m->paramtypes[p];
3358 if (IS_INT_LNG_TYPE(t)) {
3359 /* overlapping u8's are on the stack */
3360 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3361 s1 = rd->argintregs[p + longargs + dblargs];
3363 if (!IS_2_WORD_TYPE(t)) {
3364 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3365 M_IST(s1, REG_SP, 24 + p * 8 + 4);
3368 M_IST(s1, REG_SP, 24 + p * 8);
3369 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3374 /* we do not have a data segment here */
3375 /* a = dseg_adds4(cd, 0xdeadbeef);
3376 M_ILD(REG_ITMP1, REG_PV, a); */
3377 M_LDA(REG_ITMP1, REG_ZERO, -1);
3378 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3379 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
3383 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3384 s1 = rd->argfltregs[fltargs + dblargs];
3386 if (!IS_2_WORD_TYPE(t)) {
3387 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3388 M_FST(s1, REG_SP, 24 + p * 8 + 4);
3392 M_DST(s1, REG_SP, 24 + p * 8);
3397 /* this should not happen */
3402 /* TODO: save remaining integer and flaot argument registers */
3404 /* load first 4 arguments into integer argument registers */
3405 for (p = 0; p < 8; p++) {
3406 d = rd->argintregs[p];
3407 M_ILD(d, REG_SP, 24 + p * 4);
3410 M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3411 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3412 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3420 /* restore arguments into the reserved stack space */
3421 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3422 t = m->paramtypes[p];
3424 if (IS_INT_LNG_TYPE(t)) {
3425 if ((p + longargs + dblargs) < INT_ARG_CNT) {
3426 s1 = rd->argintregs[p + longargs + dblargs];
3428 if (!IS_2_WORD_TYPE(t)) {
3429 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
3432 M_ILD(s1, REG_SP, 24 + p * 8);
3433 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3439 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3440 s1 = rd->argfltregs[fltargs + dblargs];
3442 if (!IS_2_WORD_TYPE(t)) {
3443 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
3447 M_DLD(s1, REG_SP, 24 + p * 8);
3454 /* M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3456 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3457 /* M_MTLR(REG_ITMP3); */
3460 /* save argument registers on stack -- if we have to */
3461 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) ||
3462 m->paramcount > (INT_ARG_CNT - 1)) {
3464 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3465 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3467 stackframesize = stackparamcnt + paramshiftcnt;
3469 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3471 panic("nativestub");
3474 if (m->flags & ACC_STATIC) {
3475 M_MOV(rd->argintregs[5], rd->argintregs[7]);
3476 M_MOV(rd->argintregs[4], rd->argintregs[6]);
3477 M_MOV(rd->argintregs[3], rd->argintregs[5]);
3478 M_MOV(rd->argintregs[2], rd->argintregs[4]);
3479 M_MOV(rd->argintregs[1], rd->argintregs[3]);
3480 M_MOV(rd->argintregs[0], rd->argintregs[2]);
3482 /* put class into second argument register */
3483 M_ALD(rd->argintregs[1], REG_PV, -8 * 4);
3486 M_MOV(rd->argintregs[6], rd->argintregs[7]);
3487 M_MOV(rd->argintregs[5], rd->argintregs[6]);
3488 M_MOV(rd->argintregs[4], rd->argintregs[5]);
3489 M_MOV(rd->argintregs[3], rd->argintregs[4]);
3490 M_MOV(rd->argintregs[2], rd->argintregs[3]);
3491 M_MOV(rd->argintregs[1], rd->argintregs[2]);
3492 M_MOV(rd->argintregs[0], rd->argintregs[1]);
3495 /* put env into first argument register */
3496 M_ALD(rd->argintregs[0], REG_PV, -4 * 4);
3498 M_ALD(REG_PV, REG_PV, -1 * 4); /* load adress of native method */
3501 disp = -(s4) (mcodeptr - cs) * 4;
3503 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3505 /* remove stackframe if there is one */
3506 if (stackframesize) {
3507 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3510 /* 20 instructions */
3513 M_LDA(REG_SP, REG_SP, -10 * 8);
3514 M_DST(REG_FRESULT, REG_SP, 48+0);
3515 M_IST(REG_RESULT, REG_SP, 48+8);
3516 M_AST(REG_ITMP3, REG_SP, 48+12);
3517 M_IST(REG_RESULT2, REG_SP, 48+16);
3519 /* keep this order */
3520 switch (m->returntype) {
3523 M_MOV(REG_RESULT, rd->argintregs[2]);
3524 M_CLR(rd->argintregs[1]);
3528 M_MOV(REG_RESULT2, rd->argintregs[2]);
3529 M_MOV(REG_RESULT, rd->argintregs[1]);
3532 M_ALD(rd->argintregs[0], REG_PV, -6 * 4);
3534 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3535 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3536 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop */
3539 M_DLD(REG_FRESULT, REG_SP, 48+0);
3540 M_ILD(REG_RESULT, REG_SP, 48+8);
3541 M_ALD(REG_ITMP3, REG_SP, 48+12);
3542 M_ILD(REG_RESULT2, REG_SP, 48+16);
3543 M_LDA(REG_SP, REG_SP, 10 * 8);
3547 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3548 if (IS_FLT_DBL_TYPE(m->returntype))
3549 if (IS_2_WORD_TYPE(m->returntype))
3550 M_DST(REG_FRESULT, REG_SP, 56);
3552 M_FST(REG_FRESULT, REG_SP, 56);
3554 M_IST(REG_RESULT, REG_SP, 56);
3555 if (IS_2_WORD_TYPE(m->returntype))
3556 M_IST(REG_RESULT2, REG_SP, 60);
3559 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
3562 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3564 M_LDA(REG_PV, REG_ITMP1, disp);
3565 M_MOV(REG_RESULT, REG_ITMP2);
3567 if (IS_FLT_DBL_TYPE(m->returntype))
3568 if (IS_2_WORD_TYPE(m->returntype))
3569 M_DLD(REG_FRESULT, REG_SP, 56);
3571 M_FLD(REG_FRESULT, REG_SP, 56);
3573 M_ILD(REG_RESULT, REG_SP, 56);
3574 if (IS_2_WORD_TYPE(m->returntype))
3575 M_ILD(REG_RESULT2, REG_SP, 60);
3578 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
3580 M_ALD(REG_ITMP1, REG_ITMP2, 0); /* load exception into reg. itmp1 */
3582 M_BNE(4); /* if no exception then return */
3584 M_ALD(REG_ITMP1, REG_SP, 64 + 8); /* load return address */
3586 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3591 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3593 M_ALD(REG_ITMP3, REG_SP, 64 + 8); /* load return address */
3595 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3597 M_LDA(REG_ITMP2, REG_ITMP1, -4); /* move fault address into reg. itmp2 */
3599 M_ALD(REG_ITMP3, REG_PV, -3 * 4); /* load asm exception handler address */
3604 dolog_plain("stubsize: %d (for %d params)\n", (int) (mcodeptr - (s4 *) s), m->paramcount);
3607 asm_cacheflush((void *) s, (u1*) mcodeptr - (u1*) s);
3609 #if defined(STATISTICS)
3611 count_nstub_len += NATIVESTUBSIZE * 4;
3614 /* release dump area */
3616 dump_release(dumpsize);
3618 return (u1*) (s + NATIVESTUBOFFSET);
3622 /* function: removenativestub **************************************************
3624 removes a previously created native-stub from memory
3626 *******************************************************************************/
3628 void removenativestub(u1 *stub)
3630 CFREE((s4 *) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 4);
3635 * These are local overrides for various environment variables in Emacs.
3636 * Please do not remove this and leave it at the end of the file, where
3637 * Emacs will automagically detect them.
3638 * ---------------------------------------------------------------------
3641 * indent-tabs-mode: t