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 1501 2004-11-12 16:36:13Z twisti $
48 #include "jit/parse.h"
50 #include "jit/powerpc/codegen.h"
53 /* register descripton - array ************************************************/
55 /* #define REG_RES 0 reserved register for OS or code generator */
56 /* #define REG_RET 1 return value register */
57 /* #define REG_EXC 2 exception value register (only old jit) */
58 /* #define REG_SAV 3 (callee) saved register */
59 /* #define REG_TMP 4 scratch temporary register (caller saved) */
60 /* #define REG_ARG 5 argument register (caller saved) */
62 /* #define REG_END -1 last entry in tables */
65 REG_RES, REG_RES, REG_TMP, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
66 REG_ARG, REG_ARG, REG_ARG, REG_RES, REG_RES, REG_RES, REG_SAV, REG_SAV,
67 REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
68 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
71 /* for use of reserved registers, see comment above */
73 int nregdescfloat[] = {
74 REG_RES, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG,
75 REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_ARG, REG_SAV, REG_SAV,
76 REG_RES, REG_RES, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP, REG_TMP,
77 REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV, REG_SAV,
80 /* for use of reserved registers, see comment above */
83 /*******************************************************************************
85 include independent code generation stuff -- include after register
86 descriptions to avoid extern definitions
88 *******************************************************************************/
90 #include "jit/codegen.inc"
91 #include "jit/reg.inc"
94 void asm_cacheflush(void *, long);
96 /* #include <architecture/ppc/cframe.h> */
98 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
99 void thread_restartcriticalsection(void *u)
101 /* XXX set pc to restart address */
105 #include <mach/message.h>
107 int cacao_catch_Handler(mach_port_t thread)
110 unsigned int crashpc;
112 java_objectheader *xptr;
115 thread_state_flavor_t flavor = PPC_THREAD_STATE;
116 mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
117 ppc_thread_state_t thread_state;
123 r = thread_get_state(thread, flavor,
124 (natural_t*)&thread_state, &thread_state_count);
125 if (r != KERN_SUCCESS)
126 panic("thread_get_state failed");
128 regs = &thread_state.r0;
129 crashpc = thread_state.srr0;
131 instr = *(s4*) crashpc;
132 reg = (instr >> 16) & 31;
135 xptr = new_nullpointerexception();
137 regs[REG_ITMP2_XPC] = crashpc;
138 regs[REG_ITMP1_XPTR] = (u4) xptr;
139 thread_state.srr0 = (u4) asm_handle_exception;
141 r = thread_set_state(thread, flavor,
142 (natural_t*)&thread_state, thread_state_count);
143 if (r != KERN_SUCCESS)
144 panic("thread_set_state failed");
149 throw_cacao_exception_exit(string_java_lang_InternalError, "Segmentation fault at %p", regs[reg]);
154 void init_exceptions(void)
159 void adjust_argvars(stackptr s, int d, int *fa, int *ia)
165 adjust_argvars(s->prev, d-1, fa, ia);
166 if (s->varkind == ARGVAR)
167 s->varnum = (IS_FLT_DBL_TYPE(s->type)) ? *fa : *ia;
168 *fa += (IS_FLT_DBL_TYPE(s->type) != 0);
169 *ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
173 #define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
175 void preregpass(methodinfo *m, registerdata *rd)
185 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
187 for (iptr = bptr->iinstr, src = bptr->instack;
189 src = iptr->dst, len--, iptr++)
191 if (bptr->flags < BBREACHED)
204 case ICMD_INVOKEVIRTUAL:
205 case ICMD_INVOKESPECIAL:
206 case ICMD_INVOKESTATIC:
207 case ICMD_INVOKEINTERFACE:
212 adjust_argvars(src, s3, &fa, &ia);
215 for (; --s3 >= 0; src = src->prev) {
216 paramsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
218 rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
221 case ICMD_MULTIANEWARRAY:
223 paramsize = rd->intreg_argnum + s3;
224 rd->ifmemuse = intmaxf(rd->ifmemuse, paramsize);
231 rd->maxmemuse = rd->ifmemuse;
235 /* function gen_mcode **********************************************************
237 generates machine code
239 *******************************************************************************/
241 void codegen(methodinfo *m, codegendata *cd, registerdata *rd)
243 s4 len, s1, s2, s3, d;
259 /* space to save used callee saved registers */
261 savedregs_num += (rd->savintregcnt - rd->maxsavintreguse);
262 savedregs_num += 2 * (rd->savfltregcnt - rd->maxsavfltreguse);
264 parentargs_base = rd->maxmemuse + savedregs_num;
266 #ifdef USE_THREADS /* space to save argument of monitor_enter */
268 if (checksync && (m->flags & ACC_SYNCHRONIZED))
273 /* create method header */
275 parentargs_base = (parentargs_base + 3) & ~3;
278 (void) dseg_addaddress(cd, m); /* Filler */
280 (void) dseg_addaddress(cd, m); /* MethodPointer */
281 (void) dseg_adds4(cd, parentargs_base * 4); /* FrameSize */
285 /* IsSync contains the offset relative to the stack pointer for the
286 argument of monitor_exit used in the exception handler. Since the
287 offset could be zero and give a wrong meaning of the flag it is
291 if (checksync && (m->flags & ACC_SYNCHRONIZED))
292 (void) dseg_adds4(cd, (rd->maxmemuse + 1) * 4); /* IsSync */
297 (void) dseg_adds4(cd, 0); /* IsSync */
299 (void) dseg_adds4(cd, m->isleafmethod); /* IsLeaf */
300 (void) dseg_adds4(cd, rd->savintregcnt - rd->maxsavintreguse); /* IntSave */
301 (void) dseg_adds4(cd, rd->savfltregcnt - rd->maxsavfltreguse); /* FltSave */
302 (void) dseg_adds4(cd, cd->exceptiontablelength); /* ExTableSize */
304 /* create exception table */
306 for (ex = cd->exceptiontable; ex != NULL; ex = ex->down) {
307 dseg_addtarget(cd, ex->start);
308 dseg_addtarget(cd, ex->end);
309 dseg_addtarget(cd, ex->handler);
310 (void) dseg_addaddress(cd, ex->catchtype);
313 /* initialize mcode variables */
315 mcodeptr = (s4 *) cd->mcodebase;
316 cd->mcodeend = (s4 *) (cd->mcodebase + cd->mcodesize);
317 MCODECHECK(128 + m->paramcount);
319 /* create stack frame (if necessary) */
321 if (!m->isleafmethod) {
323 M_AST(REG_ITMP3, REG_SP, 8);
326 if (parentargs_base) {
327 M_LDA(REG_SP, REG_SP, -parentargs_base * 4);
330 /* save return address and used callee saved registers */
333 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
334 p--; M_IST(rd->savintregs[i], REG_SP, 4 * p);
336 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
337 p-=2; M_DST(rd->savfltregs[i], REG_SP, 4 * p);
340 /* save monitorenter argument */
342 #if defined(USE_THREADS)
343 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
344 if (m->flags & ACC_STATIC) {
345 p = dseg_addaddress(cd, m->class);
346 M_ALD(REG_ITMP1, REG_PV, p);
347 M_AST(REG_ITMP1, REG_SP, 4 * rd->maxmemuse);
350 M_AST(rd->argintregs[0], REG_SP, 4 * rd->maxmemuse);
355 /* copy argument registers to stack and call trace function with pointer
356 to arguments on stack.
365 /* XXX must be a multiple of 16 */
366 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
368 M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
370 M_CLR(REG_ITMP1); /* clear help register */
372 /* save all arguments into the reserved stack space */
373 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
374 t = m->paramtypes[p];
376 if (IS_INT_LNG_TYPE(t)) {
377 /* overlapping u8's are on the stack */
378 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
379 s1 = rd->argintregs[p + longargs + dblargs];
381 if (!IS_2_WORD_TYPE(t)) {
382 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
383 M_IST(s1, REG_SP, 24 + p * 8 + 4);
386 M_IST(s1, REG_SP, 24 + p * 8);
387 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
392 a = dseg_adds4(cd, 0xdeadbeef);
393 M_ILD(REG_ITMP1, REG_PV, a);
394 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
395 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
399 if ((fltargs + dblargs) < FLT_ARG_CNT) {
400 s1 = rd->argfltregs[fltargs + dblargs];
402 if (!IS_2_WORD_TYPE(t)) {
403 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
404 M_FST(s1, REG_SP, 24 + p * 8 + 4);
408 M_DST(s1, REG_SP, 24 + p * 8);
413 /* this should not happen */
418 /* TODO: save remaining integer and flaot argument registers */
420 /* load first 4 arguments into integer argument registers */
421 for (p = 0; p < 8; p++) {
422 d = rd->argintregs[p];
423 M_ILD(d, REG_SP, 24 + p * 4);
426 p = dseg_addaddress(cd, m);
427 M_ALD(REG_ITMP1, REG_PV, p);
428 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
429 p = dseg_addaddress(cd, (void *) builtin_trace_args);
430 M_ALD(REG_ITMP2, REG_PV, p);
438 /* restore arguments into the reserved stack space */
439 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
440 t = m->paramtypes[p];
442 if (IS_INT_LNG_TYPE(t)) {
443 if ((p + longargs + dblargs) < INT_ARG_CNT) {
444 s1 = rd->argintregs[p + longargs + dblargs];
446 if (!IS_2_WORD_TYPE(t)) {
447 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
450 M_ILD(s1, REG_SP, 24 + p * 8);
451 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
457 if ((fltargs + dblargs) < FLT_ARG_CNT) {
458 s1 = rd->argfltregs[fltargs + dblargs];
460 if (!IS_2_WORD_TYPE(t)) {
461 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
465 M_DLD(s1, REG_SP, 24 + p * 8);
472 M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
474 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
478 /* take arguments out of register or stack frame */
484 for (p = 0, l = 0; p < m->paramcount; p++) {
485 arg = narg; iarg = niarg;
486 t = m->paramtypes[p];
487 var = &(rd->locals[l][t]);
489 if (IS_2_WORD_TYPE(t)) /* increment local counter for 2 word types */
493 if (IS_INT_LNG_TYPE(t)) { /* integer args */
494 if (iarg < INT_ARG_CNT -
495 (IS_2_WORD_TYPE(t)!=0)) { /* register arguments */
496 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
497 M_TINTMOVE(t, rd->argintregs[iarg], var->regoff);
499 } else { /* reg arg -> spilled */
500 M_IST(rd->argintregs[iarg], REG_SP, 4 * var->regoff);
501 if (IS_2_WORD_TYPE(t))
502 M_IST(rd->secondregs[rd->argintregs[iarg]], REG_SP, 4 * var->regoff + 4);
505 } else { /* stack arguments */
507 if (!(var->flags & INMEMORY)) { /* stack arg -> register */
508 M_ILD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
509 if (IS_2_WORD_TYPE(t))
510 M_ILD(rd->secondregs[var->regoff], REG_SP, 4 * (parentargs_base + pa) + 4);
512 } else { /* stack arg -> spilled */
513 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa));
514 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff);
515 if (IS_2_WORD_TYPE(t)) {
516 M_ILD(REG_ITMP1, REG_SP, 4 * (parentargs_base + pa) + 4);
517 M_IST(REG_ITMP1, REG_SP, 4 * var->regoff + 4);
522 } else { /* floating args */
524 if (arg < FLT_ARG_CNT) { /* register arguments */
525 if (!(var->flags & INMEMORY)) { /* reg arg -> register */
526 M_FLTMOVE(rd->argfltregs[arg], var->regoff);
528 } else { /* reg arg -> spilled */
529 M_DST(rd->argfltregs[arg], REG_SP, 4 * var->regoff);
532 } else { /* stack arguments */
534 if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
535 if (IS_2_WORD_TYPE(t)) {
536 M_DLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
539 M_FLD(var->regoff, REG_SP, 4 * (parentargs_base + pa));
542 } else { /* stack-arg -> spilled */
543 if (IS_2_WORD_TYPE(t)) {
544 M_DLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
547 M_FLD(REG_FTMP1, REG_SP, 4 * (parentargs_base + pa));
549 M_DST(REG_FTMP1, REG_SP, 4 * var->regoff);
556 /* call monitorenter function */
558 #if defined(USE_THREADS)
559 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
560 s4 func_enter = (m->flags & ACC_STATIC) ?
561 (s4) builtin_staticmonitorenter : (s4) builtin_monitorenter;
562 p = dseg_addaddress(cd, (void *) func_enter);
563 M_ALD(REG_ITMP3, REG_PV, p);
565 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
571 /* end of header generation */
573 /* walk through all basic blocks */
574 for (bptr = m->basicblocks; bptr != NULL; bptr = bptr->next) {
576 bptr->mpc = (s4) ((u1 *) mcodeptr - cd->mcodebase);
578 if (bptr->flags >= BBREACHED) {
580 /* branch resolving */
584 for (brefs = bptr->branchrefs; brefs != NULL; brefs = brefs->next) {
585 gen_resolvebranch((u1*) cd->mcodebase + brefs->branchpos,
591 /* copy interface registers to their destination */
596 while (src != NULL) {
598 if ((len == 0) && (bptr->type != BBTYPE_STD)) {
599 d = reg_of_var(rd, src, REG_ITMP1);
600 M_INTMOVE(REG_ITMP1, d);
601 store_reg_to_var_int(src, d);
604 d = reg_of_var(rd, src, REG_IFTMP);
605 if ((src->varkind != STACKVAR)) {
607 if (IS_FLT_DBL_TYPE(s2)) {
608 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
609 s1 = rd->interfaces[len][s2].regoff;
613 if (IS_2_WORD_TYPE(s2)) {
614 M_DLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
617 M_FLD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
620 store_reg_to_var_flt(src, d);
623 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
624 s1 = rd->interfaces[len][s2].regoff;
628 M_ILD(d, REG_SP, 4 * rd->interfaces[len][s2].regoff);
629 if (IS_2_WORD_TYPE(s2))
630 M_ILD(rd->secondregs[d], REG_SP, 4 * rd->interfaces[len][s2].regoff + 4);
632 store_reg_to_var_int(src, d);
639 /* walk through all instructions */
643 for (iptr = bptr->iinstr; len > 0; src = iptr->dst, len--, iptr++) {
645 MCODECHECK(64); /* an instruction usually needs < 64 words */
648 case ICMD_NOP: /* ... ==> ... */
651 case ICMD_NULLCHECKPOP: /* ..., objectref ==> ... */
653 var_to_reg_int(s1, src, REG_ITMP1);
656 codegen_addxnullrefs(cd, mcodeptr);
659 /* constant operations ************************************************/
661 case ICMD_ICONST: /* ... ==> ..., constant */
662 /* op1 = 0, val.i = constant */
664 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
665 ICONST(d, iptr->val.i);
666 store_reg_to_var_int(iptr->dst, d);
669 case ICMD_LCONST: /* ... ==> ..., constant */
670 /* op1 = 0, val.l = constant */
672 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
673 LCONST(d, iptr->val.l);
674 store_reg_to_var_int(iptr->dst, d);
677 case ICMD_FCONST: /* ... ==> ..., constant */
678 /* op1 = 0, val.f = constant */
680 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
681 a = dseg_addfloat(cd, iptr->val.f);
683 store_reg_to_var_flt(iptr->dst, d);
686 case ICMD_DCONST: /* ... ==> ..., constant */
687 /* op1 = 0, val.d = constant */
689 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
690 a = dseg_adddouble(cd, iptr->val.d);
692 store_reg_to_var_flt(iptr->dst, d);
695 case ICMD_ACONST: /* ... ==> ..., constant */
696 /* op1 = 0, val.a = constant */
698 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
699 ICONST(d, (u4) iptr->val.a);
700 store_reg_to_var_int(iptr->dst, d);
704 /* load/store operations **********************************************/
706 case ICMD_ILOAD: /* ... ==> ..., content of local variable */
707 case ICMD_LLOAD: /* op1 = local variable */
710 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
711 if ((iptr->dst->varkind == LOCALVAR) &&
712 (iptr->dst->varnum == iptr->op1))
714 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
715 if (var->flags & INMEMORY) {
716 M_ILD(d, REG_SP, 4 * var->regoff);
717 if (IS_2_WORD_TYPE(var->type))
718 M_ILD(rd->secondregs[d], REG_SP, 4 * var->regoff + 4);
720 M_TINTMOVE(var->type, var->regoff, d);
722 store_reg_to_var_int(iptr->dst, d);
725 case ICMD_FLOAD: /* ... ==> ..., content of local variable */
726 case ICMD_DLOAD: /* op1 = local variable */
728 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
729 if ((iptr->dst->varkind == LOCALVAR) &&
730 (iptr->dst->varnum == iptr->op1))
732 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ILOAD]);
733 if (var->flags & INMEMORY)
734 if (IS_2_WORD_TYPE(var->type))
735 M_DLD(d, REG_SP, 4 * var->regoff);
737 M_FLD(d, REG_SP, 4 * var->regoff);
739 M_FLTMOVE(var->regoff, d);
741 store_reg_to_var_flt(iptr->dst, d);
745 case ICMD_ISTORE: /* ..., value ==> ... */
746 case ICMD_LSTORE: /* op1 = local variable */
749 if ((src->varkind == LOCALVAR) &&
750 (src->varnum == iptr->op1))
752 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
753 if (var->flags & INMEMORY) {
754 var_to_reg_int(s1, src, REG_ITMP1);
755 M_IST(s1, REG_SP, 4 * var->regoff);
756 if (IS_2_WORD_TYPE(var->type))
757 M_IST(rd->secondregs[s1], REG_SP, 4 * var->regoff + 4);
759 var_to_reg_int(s1, src, var->regoff);
760 M_TINTMOVE(var->type, s1, var->regoff);
764 case ICMD_FSTORE: /* ..., value ==> ... */
765 case ICMD_DSTORE: /* op1 = local variable */
767 if ((src->varkind == LOCALVAR) &&
768 (src->varnum == iptr->op1))
770 var = &(rd->locals[iptr->op1][iptr->opc - ICMD_ISTORE]);
771 if (var->flags & INMEMORY) {
772 var_to_reg_flt(s1, src, REG_FTMP1);
773 if (var->type == TYPE_DBL)
774 M_DST(s1, REG_SP, 4 * var->regoff);
776 M_FST(s1, REG_SP, 4 * var->regoff);
778 var_to_reg_flt(s1, src, var->regoff);
779 M_FLTMOVE(s1, var->regoff);
784 /* pop/dup/swap operations ********************************************/
786 /* attention: double and longs are only one entry in CACAO ICMDs */
788 case ICMD_POP: /* ..., value ==> ... */
789 case ICMD_POP2: /* ..., value, value ==> ... */
792 case ICMD_DUP: /* ..., a ==> ..., a, a */
793 M_COPY(src, iptr->dst);
796 case ICMD_DUP_X1: /* ..., a, b ==> ..., b, a, b */
798 M_COPY(src, iptr->dst);
799 M_COPY(src->prev, iptr->dst->prev);
800 M_COPY(iptr->dst, iptr->dst->prev->prev);
803 case ICMD_DUP_X2: /* ..., a, b, c ==> ..., c, a, b, c */
805 M_COPY(src, iptr->dst);
806 M_COPY(src->prev, iptr->dst->prev);
807 M_COPY(src->prev->prev, iptr->dst->prev->prev);
808 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
811 case ICMD_DUP2: /* ..., a, b ==> ..., a, b, a, b */
813 M_COPY(src, iptr->dst);
814 M_COPY(src->prev, iptr->dst->prev);
817 case ICMD_DUP2_X1: /* ..., a, b, c ==> ..., b, c, a, b, c */
819 M_COPY(src, iptr->dst);
820 M_COPY(src->prev, iptr->dst->prev);
821 M_COPY(src->prev->prev, iptr->dst->prev->prev);
822 M_COPY(iptr->dst, iptr->dst->prev->prev->prev);
823 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev);
826 case ICMD_DUP2_X2: /* ..., a, b, c, d ==> ..., c, d, a, b, c, d */
828 M_COPY(src, iptr->dst);
829 M_COPY(src->prev, iptr->dst->prev);
830 M_COPY(src->prev->prev, iptr->dst->prev->prev);
831 M_COPY(src->prev->prev->prev, iptr->dst->prev->prev->prev);
832 M_COPY(iptr->dst, iptr->dst->prev->prev->prev->prev);
833 M_COPY(iptr->dst->prev, iptr->dst->prev->prev->prev->prev->prev);
836 case ICMD_SWAP: /* ..., a, b ==> ..., b, a */
838 M_COPY(src, iptr->dst->prev);
839 M_COPY(src->prev, iptr->dst);
843 /* integer operations *************************************************/
845 case ICMD_INEG: /* ..., value ==> ..., - value */
847 var_to_reg_int(s1, src, REG_ITMP1);
848 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
850 store_reg_to_var_int(iptr->dst, d);
853 case ICMD_LNEG: /* ..., value ==> ..., - value */
855 var_to_reg_int(s1, src, REG_ITMP1);
856 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
857 M_SUBFIC(rd->secondregs[s1], 0, rd->secondregs[d]);
859 store_reg_to_var_int(iptr->dst, d);
862 case ICMD_I2L: /* ..., value ==> ..., value */
864 var_to_reg_int(s1, src, REG_ITMP2);
865 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
866 M_INTMOVE(s1, rd->secondregs[d]);
867 M_SRA_IMM(rd->secondregs[d], 31, d);
868 store_reg_to_var_int(iptr->dst, d);
871 case ICMD_L2I: /* ..., value ==> ..., value */
873 var_to_reg_int0(s1, src, REG_ITMP2, 0, 1);
874 d = reg_of_var(rd, iptr->dst, REG_ITMP2);
876 store_reg_to_var_int(iptr->dst, d);
879 case ICMD_INT2BYTE: /* ..., value ==> ..., value */
881 var_to_reg_int(s1, src, REG_ITMP1);
882 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
884 store_reg_to_var_int(iptr->dst, d);
887 case ICMD_INT2CHAR: /* ..., value ==> ..., value */
889 var_to_reg_int(s1, src, REG_ITMP1);
890 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
892 store_reg_to_var_int(iptr->dst, d);
895 case ICMD_INT2SHORT: /* ..., value ==> ..., value */
897 var_to_reg_int(s1, src, REG_ITMP1);
898 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
900 store_reg_to_var_int(iptr->dst, d);
904 case ICMD_IADD: /* ..., val1, val2 ==> ..., val1 + val2 */
906 var_to_reg_int(s1, src->prev, REG_ITMP1);
907 var_to_reg_int(s2, src, REG_ITMP2);
908 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
910 store_reg_to_var_int(iptr->dst, d);
913 case ICMD_IADDCONST: /* ..., value ==> ..., value + constant */
914 /* val.i = constant */
916 var_to_reg_int(s1, src, REG_ITMP1);
917 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
918 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
919 M_IADD_IMM(s1, iptr->val.i, d);
922 ICONST(REG_ITMP2, iptr->val.i);
923 M_IADD(s1, REG_ITMP2, d);
925 store_reg_to_var_int(iptr->dst, d);
928 case ICMD_LADD: /* ..., val1, val2 ==> ..., val1 + val2 */
930 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
931 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
932 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
933 M_ADDC(s1, s2, rd->secondregs[d]);
934 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
935 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
937 store_reg_to_var_int(iptr->dst, d);
940 case ICMD_LADDCONST: /* ..., value ==> ..., value + constant */
941 /* val.l = constant */
943 s3 = iptr->val.l & 0xffffffff;
944 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
945 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
946 if ((s3 >= -32768) && (s3 <= 32767)) {
947 M_ADDIC(s1, s3, rd->secondregs[d]);
950 ICONST(REG_ITMP2, s3);
951 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
953 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
954 s3 = iptr->val.l >> 32;
960 ICONST(REG_ITMP3, s3);
961 M_ADDE(s1, REG_ITMP3, d);
963 store_reg_to_var_int(iptr->dst, d);
966 case ICMD_ISUB: /* ..., val1, val2 ==> ..., val1 - val2 */
968 var_to_reg_int(s1, src->prev, REG_ITMP1);
969 var_to_reg_int(s2, src, REG_ITMP2);
970 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
972 store_reg_to_var_int(iptr->dst, d);
975 case ICMD_ISUBCONST: /* ..., value ==> ..., value + constant */
976 /* val.i = constant */
978 var_to_reg_int(s1, src, REG_ITMP1);
979 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
980 if ((iptr->val.i >= -32767) && (iptr->val.i <= 32768)) {
981 M_IADD_IMM(s1, -iptr->val.i, d);
984 ICONST(REG_ITMP2, -iptr->val.i);
985 M_IADD(s1, REG_ITMP2, d);
987 store_reg_to_var_int(iptr->dst, d);
990 case ICMD_LSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
992 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
993 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
994 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
995 M_SUBC(s1, s2, rd->secondregs[d]);
996 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
997 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
999 store_reg_to_var_int(iptr->dst, d);
1002 case ICMD_LSUBCONST: /* ..., value ==> ..., value - constant */
1003 /* val.l = constant */
1005 s3 = (-iptr->val.l) & 0xffffffff;
1006 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1007 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1008 if ((s3 >= -32768) && (s3 <= 32767)) {
1009 M_ADDIC(s1, s3, rd->secondregs[d]);
1012 ICONST(REG_ITMP2, s3);
1013 M_ADDC(s1, REG_ITMP2, rd->secondregs[d]);
1015 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1016 s3 = (-iptr->val.l) >> 32;
1022 ICONST(REG_ITMP3, s3);
1023 M_ADDE(s1, REG_ITMP3, d);
1025 store_reg_to_var_int(iptr->dst, d);
1028 case ICMD_IDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1029 var_to_reg_int(s1, src->prev, REG_ITMP1);
1030 var_to_reg_int(s2, src, REG_ITMP2);
1031 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1033 store_reg_to_var_int(iptr->dst, d);
1036 case ICMD_IREM: /* ..., val1, val2 ==> ..., val1 % val2 */
1037 var_to_reg_int(s1, src->prev, REG_ITMP1);
1038 var_to_reg_int(s2, src, REG_ITMP2);
1039 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1043 store_reg_to_var_int(iptr->dst, d);
1046 case ICMD_IMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1048 var_to_reg_int(s1, src->prev, REG_ITMP1);
1049 var_to_reg_int(s2, src, REG_ITMP2);
1050 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1052 store_reg_to_var_int(iptr->dst, d);
1055 case ICMD_IMULCONST: /* ..., value ==> ..., value * constant */
1056 /* val.i = constant */
1058 var_to_reg_int(s1, src, REG_ITMP1);
1059 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1060 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
1061 M_IMUL_IMM(s1, iptr->val.i, d);
1064 ICONST(REG_ITMP2, iptr->val.i);
1065 M_IMUL(s1, REG_ITMP2, d);
1067 store_reg_to_var_int(iptr->dst, d);
1070 case ICMD_IDIVPOW2: /* ..., value ==> ..., value << constant */
1072 var_to_reg_int(s1, src, REG_ITMP1);
1073 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1074 M_SRA_IMM(s1, iptr->val.i, d);
1076 store_reg_to_var_int(iptr->dst, d);
1079 case ICMD_ISHL: /* ..., val1, val2 ==> ..., val1 << val2 */
1081 var_to_reg_int(s1, src->prev, REG_ITMP1);
1082 var_to_reg_int(s2, src, REG_ITMP2);
1083 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1084 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1085 M_SLL(s1, REG_ITMP3, d);
1086 store_reg_to_var_int(iptr->dst, d);
1089 case ICMD_ISHLCONST: /* ..., value ==> ..., value << constant */
1090 /* val.i = constant */
1092 var_to_reg_int(s1, src, REG_ITMP1);
1093 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1094 M_SLL_IMM(s1, iptr->val.i & 0x1f, d);
1095 store_reg_to_var_int(iptr->dst, d);
1098 case ICMD_ISHR: /* ..., val1, val2 ==> ..., val1 >> val2 */
1100 var_to_reg_int(s1, src->prev, REG_ITMP1);
1101 var_to_reg_int(s2, src, REG_ITMP2);
1102 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1103 M_AND_IMM(s2, 0x1f, REG_ITMP3);
1104 M_SRA(s1, REG_ITMP3, d);
1105 store_reg_to_var_int(iptr->dst, d);
1108 case ICMD_ISHRCONST: /* ..., value ==> ..., value >> constant */
1109 /* val.i = constant */
1111 var_to_reg_int(s1, src, REG_ITMP1);
1112 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1113 M_SRA_IMM(s1, iptr->val.i & 0x1f, d);
1114 store_reg_to_var_int(iptr->dst, d);
1117 case ICMD_IUSHR: /* ..., val1, val2 ==> ..., val1 >>> val2 */
1119 var_to_reg_int(s1, src->prev, REG_ITMP1);
1120 var_to_reg_int(s2, src, REG_ITMP2);
1121 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1122 M_AND_IMM(s2, 0x1f, REG_ITMP2);
1123 M_SRL(s1, REG_ITMP2, d);
1124 store_reg_to_var_int(iptr->dst, d);
1127 case ICMD_IUSHRCONST: /* ..., value ==> ..., value >>> constant */
1128 /* val.i = constant */
1130 var_to_reg_int(s1, src, REG_ITMP1);
1131 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1132 if (iptr->val.i & 0x1f)
1133 M_SRL_IMM(s1, iptr->val.i & 0x1f, d);
1136 store_reg_to_var_int(iptr->dst, d);
1139 case ICMD_IAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1141 var_to_reg_int(s1, src->prev, REG_ITMP1);
1142 var_to_reg_int(s2, src, REG_ITMP2);
1143 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1145 store_reg_to_var_int(iptr->dst, d);
1148 case ICMD_IANDCONST: /* ..., value ==> ..., value & constant */
1149 /* val.i = constant */
1151 var_to_reg_int(s1, src, REG_ITMP1);
1152 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1153 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1154 M_AND_IMM(s1, iptr->val.i, d);
1157 else if (iptr->val.i == 0xffffff) {
1158 M_RLWINM(s1, 0, 8, 31, d);
1162 ICONST(REG_ITMP2, iptr->val.i);
1163 M_AND(s1, REG_ITMP2, d);
1165 store_reg_to_var_int(iptr->dst, d);
1168 case ICMD_LAND: /* ..., val1, val2 ==> ..., val1 & val2 */
1170 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1171 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1172 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1173 M_AND(s1, s2, rd->secondregs[d]);
1174 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1175 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1177 store_reg_to_var_int(iptr->dst, d);
1180 case ICMD_LANDCONST: /* ..., value ==> ..., value & constant */
1181 /* val.l = constant */
1183 s3 = iptr->val.l & 0xffffffff;
1184 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1185 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1186 if ((s3 >= 0) && (s3 <= 65535)) {
1187 M_AND_IMM(s1, s3, rd->secondregs[d]);
1190 ICONST(REG_ITMP2, s3);
1191 M_AND(s1, REG_ITMP2, rd->secondregs[d]);
1193 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1194 s3 = iptr->val.l >> 32;
1195 if ((s3 >= 0) && (s3 <= 65535)) {
1196 M_AND_IMM(s1, s3, d);
1199 ICONST(REG_ITMP3, s3);
1200 M_AND(s1, REG_ITMP3, d);
1202 store_reg_to_var_int(iptr->dst, d);
1205 case ICMD_IREMPOW2: /* ..., value ==> ..., value % constant */
1206 /* val.i = constant */
1208 var_to_reg_int(s1, src, REG_ITMP1);
1209 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1210 M_MOV(s1, REG_ITMP2);
1212 M_BGE(1 + 2*(iptr->val.i >= 32768));
1213 if (iptr->val.i >= 32768) {
1214 M_ADDIS(REG_ZERO, iptr->val.i>>16, REG_ITMP2);
1215 M_OR_IMM(REG_ITMP2, iptr->val.i, REG_ITMP2);
1216 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1219 M_IADD_IMM(s1, iptr->val.i, REG_ITMP2);
1221 int b=0, m = iptr->val.i;
1224 M_RLWINM(REG_ITMP2, 0, 0, 30-b, REG_ITMP2);
1226 M_ISUB(s1, REG_ITMP2, d);
1227 store_reg_to_var_int(iptr->dst, d);
1230 case ICMD_IOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1232 var_to_reg_int(s1, src->prev, REG_ITMP1);
1233 var_to_reg_int(s2, src, REG_ITMP2);
1234 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1236 store_reg_to_var_int(iptr->dst, d);
1239 case ICMD_IORCONST: /* ..., value ==> ..., value | constant */
1240 /* val.i = constant */
1242 var_to_reg_int(s1, src, REG_ITMP1);
1243 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1244 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1245 M_OR_IMM(s1, iptr->val.i, d);
1248 ICONST(REG_ITMP2, iptr->val.i);
1249 M_OR(s1, REG_ITMP2, d);
1251 store_reg_to_var_int(iptr->dst, d);
1254 case ICMD_LOR: /* ..., val1, val2 ==> ..., val1 | val2 */
1256 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1257 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1258 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1259 M_OR(s1, s2, rd->secondregs[d]);
1260 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1261 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1263 store_reg_to_var_int(iptr->dst, d);
1266 case ICMD_LORCONST: /* ..., value ==> ..., value | constant */
1267 /* val.l = constant */
1269 s3 = iptr->val.l & 0xffffffff;
1270 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1271 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1272 if ((s3 >= 0) && (s3 <= 65535)) {
1273 M_OR_IMM(s1, s3, rd->secondregs[d]);
1276 ICONST(REG_ITMP2, s3);
1277 M_OR(s1, REG_ITMP2, rd->secondregs[d]);
1279 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1280 s3 = iptr->val.l >> 32;
1281 if ((s3 >= 0) && (s3 <= 65535)) {
1282 M_OR_IMM(s1, s3, d);
1285 ICONST(REG_ITMP3, s3);
1286 M_OR(s1, REG_ITMP3, d);
1288 store_reg_to_var_int(iptr->dst, d);
1291 case ICMD_IXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1293 var_to_reg_int(s1, src->prev, REG_ITMP1);
1294 var_to_reg_int(s2, src, REG_ITMP2);
1295 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1297 store_reg_to_var_int(iptr->dst, d);
1300 case ICMD_IXORCONST: /* ..., value ==> ..., value ^ constant */
1301 /* val.i = constant */
1303 var_to_reg_int(s1, src, REG_ITMP1);
1304 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1305 if ((iptr->val.i >= 0) && (iptr->val.i <= 65535)) {
1306 M_XOR_IMM(s1, iptr->val.i, d);
1309 ICONST(REG_ITMP2, iptr->val.i);
1310 M_XOR(s1, REG_ITMP2, d);
1312 store_reg_to_var_int(iptr->dst, d);
1315 case ICMD_LXOR: /* ..., val1, val2 ==> ..., val1 ^ val2 */
1317 var_to_reg_int0(s1, src->prev, REG_ITMP1, 0, 1);
1318 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1319 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1320 M_XOR(s1, s2, rd->secondregs[d]);
1321 var_to_reg_int0(s1, src->prev, REG_ITMP1, 1, 0);
1322 var_to_reg_int0(s2, src, REG_ITMP3, 1, 0);
1324 store_reg_to_var_int(iptr->dst, d);
1327 case ICMD_LXORCONST: /* ..., value ==> ..., value ^ constant */
1328 /* val.l = constant */
1330 s3 = iptr->val.l & 0xffffffff;
1331 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
1332 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1333 if ((s3 >= 0) && (s3 <= 65535)) {
1334 M_XOR_IMM(s1, s3, rd->secondregs[d]);
1337 ICONST(REG_ITMP2, s3);
1338 M_XOR(s1, REG_ITMP2, rd->secondregs[d]);
1340 var_to_reg_int0(s1, src, REG_ITMP1, 1, 0);
1341 s3 = iptr->val.l >> 32;
1342 if ((s3 >= 0) && (s3 <= 65535)) {
1343 M_XOR_IMM(s1, s3, d);
1346 ICONST(REG_ITMP3, s3);
1347 M_XOR(s1, REG_ITMP3, d);
1349 store_reg_to_var_int(iptr->dst, d);
1352 case ICMD_LCMP: /* ..., val1, val2 ==> ..., val1 cmp val2 */
1354 var_to_reg_int0(s1, src->prev, REG_ITMP3, 1, 0);
1355 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
1356 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
1359 (d==s1 || d==s2 || d==rd->secondregs[s1] || d==rd->secondregs[s2]);
1360 int dreg = tempreg ? REG_ITMP1 : d;
1362 M_IADD_IMM(REG_ZERO, 1, dreg);
1367 var_to_reg_int0(s1, src->prev, REG_ITMP3, 0, 1);
1368 var_to_reg_int0(s2, src, REG_ITMP2, 0, 1);
1372 M_IADD_IMM(dreg, -1, dreg);
1373 M_IADD_IMM(dreg, -1, dreg);
1374 gen_resolvebranch(br1, (u1*) br1, (u1*) mcodeptr);
1375 gen_resolvebranch(br1+1, (u1*) (br1+1), (u1*) (mcodeptr-2));
1378 store_reg_to_var_int(iptr->dst, d);
1381 case ICMD_IINC: /* ..., value ==> ..., value + constant */
1382 /* op1 = variable, val.i = constant */
1384 var = &(rd->locals[iptr->op1][TYPE_INT]);
1385 if (var->flags & INMEMORY) {
1387 M_ILD(s1, REG_SP, 4 * var->regoff);
1396 M_ADDIS(s1, m>>16, s1);
1398 M_IADD_IMM(s1, m&0xffff, s1);
1400 if (var->flags & INMEMORY)
1401 M_IST(s1, REG_SP, 4 * var->regoff);
1405 /* floating operations ************************************************/
1407 case ICMD_FNEG: /* ..., value ==> ..., - value */
1409 var_to_reg_flt(s1, src, REG_FTMP1);
1410 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1412 store_reg_to_var_flt(iptr->dst, d);
1415 case ICMD_DNEG: /* ..., value ==> ..., - value */
1417 var_to_reg_flt(s1, src, REG_FTMP1);
1418 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1420 store_reg_to_var_flt(iptr->dst, d);
1423 case ICMD_FADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1425 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1426 var_to_reg_flt(s2, src, REG_FTMP2);
1427 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1429 store_reg_to_var_flt(iptr->dst, d);
1432 case ICMD_DADD: /* ..., val1, val2 ==> ..., val1 + val2 */
1434 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1435 var_to_reg_flt(s2, src, REG_FTMP2);
1436 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1438 store_reg_to_var_flt(iptr->dst, d);
1441 case ICMD_FSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1443 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1444 var_to_reg_flt(s2, src, REG_FTMP2);
1445 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1447 store_reg_to_var_flt(iptr->dst, d);
1450 case ICMD_DSUB: /* ..., val1, val2 ==> ..., val1 - val2 */
1452 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1453 var_to_reg_flt(s2, src, REG_FTMP2);
1454 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1456 store_reg_to_var_flt(iptr->dst, d);
1459 case ICMD_FMUL: /* ..., val1, val2 ==> ..., val1 * val2 */
1461 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1462 var_to_reg_flt(s2, src, REG_FTMP2);
1463 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1465 store_reg_to_var_flt(iptr->dst, d);
1468 case ICMD_DMUL: /* ..., val1, val2 ==> ..., val1 *** val2 */
1470 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1471 var_to_reg_flt(s2, src, REG_FTMP2);
1472 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1474 store_reg_to_var_flt(iptr->dst, d);
1477 case ICMD_FDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1479 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1480 var_to_reg_flt(s2, src, REG_FTMP2);
1481 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1483 store_reg_to_var_flt(iptr->dst, d);
1486 case ICMD_DDIV: /* ..., val1, val2 ==> ..., val1 / val2 */
1488 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1489 var_to_reg_flt(s2, src, REG_FTMP2);
1490 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1492 store_reg_to_var_flt(iptr->dst, d);
1495 case ICMD_F2I: /* ..., value ==> ..., (int) value */
1497 var_to_reg_flt(s1, src, REG_FTMP1);
1498 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1500 a = dseg_addfloat(cd, 0.0);
1501 M_FLD(REG_FTMP2, REG_PV, a);
1502 M_FCMPU(s1, REG_FTMP2);
1504 a = dseg_adds4(cd, 0);
1505 M_CVTDL_C(s1, REG_FTMP1);
1506 M_LDA (REG_ITMP1, REG_PV, a);
1507 M_STFIWX(REG_FTMP1, 0, REG_ITMP1);
1508 M_ILD (d, REG_PV, a);
1509 store_reg_to_var_int(iptr->dst, d);
1512 case ICMD_F2D: /* ..., value ==> ..., (double) value */
1514 var_to_reg_flt(s1, src, REG_FTMP1);
1515 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1517 store_reg_to_var_flt(iptr->dst, d);
1520 case ICMD_D2F: /* ..., value ==> ..., (double) value */
1522 var_to_reg_flt(s1, src, REG_FTMP1);
1523 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1525 store_reg_to_var_flt(iptr->dst, d);
1528 case ICMD_FCMPL: /* ..., val1, val2 ==> ..., val1 fcmpg val2 */
1530 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1531 var_to_reg_flt(s2, src, REG_FTMP2);
1532 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1534 M_IADD_IMM(0, -1, d);
1537 M_IADD_IMM(0, 0, d);
1539 M_IADD_IMM(0, 1, d);
1540 store_reg_to_var_int(iptr->dst, d);
1543 case ICMD_FCMPG: /* ..., val1, val2 ==> ..., val1 fcmpl val2 */
1545 var_to_reg_flt(s1, src->prev, REG_FTMP1);
1546 var_to_reg_flt(s2, src, REG_FTMP2);
1547 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1549 M_IADD_IMM(0, 1, d);
1552 M_IADD_IMM(0, 0, d);
1554 M_IADD_IMM(0, -1, d);
1555 store_reg_to_var_int(iptr->dst, d);
1559 /* memory operations **************************************************/
1561 case ICMD_ARRAYLENGTH: /* ..., arrayref ==> ..., length */
1563 var_to_reg_int(s1, src, REG_ITMP1);
1564 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1565 gen_nullptr_check(s1);
1566 M_ILD(d, s1, OFFSET(java_arrayheader, size));
1567 store_reg_to_var_int(iptr->dst, d);
1570 case ICMD_AALOAD: /* ..., arrayref, index ==> ..., value */
1572 var_to_reg_int(s1, src->prev, REG_ITMP1);
1573 var_to_reg_int(s2, src, REG_ITMP2);
1574 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1575 if (iptr->op1 == 0) {
1576 gen_nullptr_check(s1);
1579 M_SLL_IMM(s2, 2, REG_ITMP2);
1580 M_IADD_IMM(REG_ITMP2, OFFSET(java_objectarray, data[0]), REG_ITMP2);
1581 M_LWZX(d, s1, REG_ITMP2);
1582 store_reg_to_var_int(iptr->dst, d);
1585 case ICMD_LALOAD: /* ..., arrayref, index ==> ..., value */
1587 var_to_reg_int(s1, src->prev, REG_ITMP1);
1588 var_to_reg_int(s2, src, REG_ITMP2);
1589 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1590 if (iptr->op1 == 0) {
1591 gen_nullptr_check(s1);
1594 M_SLL_IMM(s2, 3, REG_ITMP2);
1595 M_IADD(s1, REG_ITMP2, REG_ITMP2);
1596 M_ILD(d, REG_ITMP2, OFFSET(java_longarray, data[0]));
1597 M_ILD(rd->secondregs[d], REG_ITMP2, OFFSET(java_longarray, data[0])+4);
1598 store_reg_to_var_int(iptr->dst, d);
1601 case ICMD_IALOAD: /* ..., arrayref, index ==> ..., value */
1603 var_to_reg_int(s1, src->prev, REG_ITMP1);
1604 var_to_reg_int(s2, src, REG_ITMP2);
1605 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1606 if (iptr->op1 == 0) {
1607 gen_nullptr_check(s1);
1610 M_SLL_IMM(s2, 2, REG_ITMP2);
1611 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1612 M_LWZX(d, s1, REG_ITMP2);
1613 store_reg_to_var_int(iptr->dst, d);
1616 case ICMD_FALOAD: /* ..., arrayref, index ==> ..., value */
1618 var_to_reg_int(s1, src->prev, REG_ITMP1);
1619 var_to_reg_int(s2, src, REG_ITMP2);
1620 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1621 if (iptr->op1 == 0) {
1622 gen_nullptr_check(s1);
1625 M_SLL_IMM(s2, 2, REG_ITMP2);
1626 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1627 M_LFSX(d, s1, REG_ITMP2);
1628 store_reg_to_var_flt(iptr->dst, d);
1631 case ICMD_DALOAD: /* ..., arrayref, index ==> ..., value */
1633 var_to_reg_int(s1, src->prev, REG_ITMP1);
1634 var_to_reg_int(s2, src, REG_ITMP2);
1635 d = reg_of_var(rd, iptr->dst, REG_FTMP3);
1636 if (iptr->op1 == 0) {
1637 gen_nullptr_check(s1);
1640 M_SLL_IMM(s2, 3, REG_ITMP2);
1641 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1642 M_LFDX(d, s1, REG_ITMP2);
1643 store_reg_to_var_flt(iptr->dst, d);
1646 case ICMD_BALOAD: /* ..., arrayref, index ==> ..., value */
1648 var_to_reg_int(s1, src->prev, REG_ITMP1);
1649 var_to_reg_int(s2, src, REG_ITMP2);
1650 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1651 if (iptr->op1 == 0) {
1652 gen_nullptr_check(s1);
1655 M_IADD_IMM(s2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1656 M_LBZX(d, s1, REG_ITMP2);
1658 store_reg_to_var_int(iptr->dst, d);
1661 case ICMD_SALOAD: /* ..., arrayref, index ==> ..., value */
1663 var_to_reg_int(s1, src->prev, REG_ITMP1);
1664 var_to_reg_int(s2, src, REG_ITMP2);
1665 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1666 if (iptr->op1 == 0) {
1667 gen_nullptr_check(s1);
1670 M_SLL_IMM(s2, 1, REG_ITMP2);
1671 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1672 M_LHAX(d, s1, REG_ITMP2);
1673 store_reg_to_var_int(iptr->dst, d);
1676 case ICMD_CALOAD: /* ..., arrayref, index ==> ..., value */
1678 var_to_reg_int(s1, src->prev, REG_ITMP1);
1679 var_to_reg_int(s2, src, REG_ITMP2);
1680 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1681 if (iptr->op1 == 0) {
1682 gen_nullptr_check(s1);
1685 M_SLL_IMM(s2, 1, REG_ITMP2);
1686 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1687 M_LHZX(d, s1, REG_ITMP2);
1688 store_reg_to_var_int(iptr->dst, d);
1691 case ICMD_LASTORE: /* ..., arrayref, index, value ==> ... */
1693 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1694 var_to_reg_int(s2, src->prev, REG_ITMP2);
1695 if (iptr->op1 == 0) {
1696 gen_nullptr_check(s1);
1699 var_to_reg_int0(s3, src, REG_ITMP3, 1, 0);
1700 M_SLL_IMM(s2, 3, REG_ITMP2);
1701 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1702 M_STWX(s3, s1, REG_ITMP2);
1703 M_IADD_IMM(REG_ITMP2, 4, REG_ITMP2);
1704 var_to_reg_int0(s3, src, REG_ITMP3, 0, 1);
1705 M_STWX(s3, s1, REG_ITMP2);
1708 case ICMD_IASTORE: /* ..., arrayref, index, value ==> ... */
1710 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1711 var_to_reg_int(s2, src->prev, REG_ITMP2);
1712 if (iptr->op1 == 0) {
1713 gen_nullptr_check(s1);
1716 var_to_reg_int(s3, src, REG_ITMP3);
1717 M_SLL_IMM(s2, 2, REG_ITMP2);
1718 M_IADD_IMM(REG_ITMP2, OFFSET(java_intarray, data[0]), REG_ITMP2);
1719 M_STWX(s3, s1, REG_ITMP2);
1722 case ICMD_FASTORE: /* ..., arrayref, index, value ==> ... */
1724 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1725 var_to_reg_int(s2, src->prev, REG_ITMP2);
1726 if (iptr->op1 == 0) {
1727 gen_nullptr_check(s1);
1730 var_to_reg_flt(s3, src, REG_FTMP3);
1731 M_SLL_IMM(s2, 2, REG_ITMP2);
1732 M_IADD_IMM(REG_ITMP2, OFFSET(java_floatarray, data[0]), REG_ITMP2);
1733 M_STFSX(s3, s1, REG_ITMP2);
1736 case ICMD_DASTORE: /* ..., arrayref, index, value ==> ... */
1738 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1739 var_to_reg_int(s2, src->prev, REG_ITMP2);
1740 if (iptr->op1 == 0) {
1741 gen_nullptr_check(s1);
1744 var_to_reg_flt(s3, src, REG_FTMP3);
1745 M_SLL_IMM(s2, 3, REG_ITMP2);
1746 M_IADD_IMM(REG_ITMP2, OFFSET(java_doublearray, data[0]), REG_ITMP2);
1747 M_STFDX(s3, s1, REG_ITMP2);
1750 case ICMD_BASTORE: /* ..., arrayref, index, value ==> ... */
1752 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1753 var_to_reg_int(s2, src->prev, REG_ITMP2);
1754 if (iptr->op1 == 0) {
1755 gen_nullptr_check(s1);
1758 var_to_reg_int(s3, src, REG_ITMP3);
1759 M_IADD_IMM(s2, OFFSET(java_bytearray, data[0]), REG_ITMP2);
1760 M_STBX(s3, s1, REG_ITMP2);
1763 case ICMD_SASTORE: /* ..., arrayref, index, value ==> ... */
1765 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1766 var_to_reg_int(s2, src->prev, REG_ITMP2);
1767 if (iptr->op1 == 0) {
1768 gen_nullptr_check(s1);
1771 var_to_reg_int(s3, src, REG_ITMP3);
1772 M_SLL_IMM(s2, 1, REG_ITMP2);
1773 M_IADD_IMM(REG_ITMP2, OFFSET(java_shortarray, data[0]), REG_ITMP2);
1774 M_STHX(s3, s1, REG_ITMP2);
1777 case ICMD_CASTORE: /* ..., arrayref, index, value ==> ... */
1779 var_to_reg_int(s1, src->prev->prev, REG_ITMP1);
1780 var_to_reg_int(s2, src->prev, REG_ITMP2);
1781 if (iptr->op1 == 0) {
1782 gen_nullptr_check(s1);
1785 var_to_reg_int(s3, src, REG_ITMP3);
1786 M_SLL_IMM(s2, 1, REG_ITMP2);
1787 M_IADD_IMM(REG_ITMP2, OFFSET(java_chararray, data[0]), REG_ITMP2);
1788 M_STHX(s3, s1, REG_ITMP2);
1791 case ICMD_PUTSTATIC: /* ..., value ==> ... */
1792 /* op1 = type, val.a = field address */
1794 /* if class isn't yet initialized, do it */
1795 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1796 /* call helper function which patches this code */
1797 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1798 M_ALD(REG_ITMP1, REG_PV, a);
1799 a = dseg_addaddress(cd, asm_check_clinit);
1800 M_ALD(REG_PV, REG_PV, a);
1805 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1807 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1809 s4 ml = -s1, mh = 0;
1810 while (ml < -32768) { ml += 65536; mh--; }
1811 M_LDA(REG_PV, REG_ITMP1, ml);
1812 M_LDAH(REG_PV, REG_PV, mh);
1816 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1817 M_ALD(REG_ITMP1, REG_PV, a);
1818 switch (iptr->op1) {
1820 var_to_reg_int(s2, src, REG_ITMP2);
1821 M_IST(s2, REG_ITMP1, 0);
1824 var_to_reg_int(s2, src, REG_ITMP3);
1825 M_IST(s2, REG_ITMP1, 0);
1826 M_IST(rd->secondregs[s2], REG_ITMP1, 4);
1829 var_to_reg_int(s2, src, REG_ITMP2);
1830 M_AST(s2, REG_ITMP1, 0);
1833 var_to_reg_flt(s2, src, REG_FTMP2);
1834 M_FST(s2, REG_ITMP1, 0);
1837 var_to_reg_flt(s2, src, REG_FTMP2);
1838 M_DST(s2, REG_ITMP1, 0);
1840 default: panic ("internal error");
1844 case ICMD_GETSTATIC: /* ... ==> ..., value */
1845 /* op1 = type, val.a = field address */
1847 /* if class isn't yet initialized, do it */
1848 if (!((fieldinfo *) iptr->val.a)->class->initialized) {
1849 /* call helper function which patches this code */
1850 a = dseg_addaddress(cd, ((fieldinfo *) iptr->val.a)->class);
1851 M_ALD(REG_ITMP1, REG_PV, a);
1852 a = dseg_addaddress(cd, asm_check_clinit);
1853 M_ALD(REG_PV, REG_PV, a);
1858 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
1860 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
1862 s4 ml = -s1, mh = 0;
1863 while (ml < -32768) { ml += 65536; mh--; }
1864 M_LDA(REG_PV, REG_ITMP1, ml);
1865 M_LDAH(REG_PV, REG_PV, mh);
1869 a = dseg_addaddress(cd, &(((fieldinfo *) iptr->val.a)->value));
1870 M_ALD(REG_ITMP1, REG_PV, a);
1871 switch (iptr->op1) {
1873 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1874 M_ILD(d, REG_ITMP1, 0);
1875 store_reg_to_var_int(iptr->dst, d);
1878 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1879 M_ILD(d, REG_ITMP1, 0);
1880 M_ILD(rd->secondregs[d], REG_ITMP1, 4);
1881 store_reg_to_var_int(iptr->dst, d);
1884 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1885 M_ALD(d, REG_ITMP1, 0);
1886 store_reg_to_var_int(iptr->dst, d);
1889 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1890 M_FLD(d, REG_ITMP1, 0);
1891 store_reg_to_var_flt(iptr->dst, d);
1894 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1895 M_DLD(d, REG_ITMP1, 0);
1896 store_reg_to_var_flt(iptr->dst, d);
1898 default: panic ("internal error");
1903 case ICMD_PUTFIELD: /* ..., value ==> ... */
1904 /* op1 = type, val.i = field offset */
1906 a = ((fieldinfo *)(iptr->val.a))->offset;
1907 switch (iptr->op1) {
1909 var_to_reg_int(s1, src->prev, REG_ITMP1);
1910 var_to_reg_int(s2, src, REG_ITMP2);
1911 gen_nullptr_check(s1);
1915 var_to_reg_int(s1, src->prev, REG_ITMP1);
1916 var_to_reg_int(s2, src, REG_ITMP3);
1917 gen_nullptr_check(s1);
1919 M_IST(rd->secondregs[s2], s1, a+4);
1922 var_to_reg_int(s1, src->prev, REG_ITMP1);
1923 var_to_reg_int(s2, src, REG_ITMP2);
1924 gen_nullptr_check(s1);
1928 var_to_reg_int(s1, src->prev, REG_ITMP1);
1929 var_to_reg_flt(s2, src, REG_FTMP2);
1930 gen_nullptr_check(s1);
1934 var_to_reg_int(s1, src->prev, REG_ITMP1);
1935 var_to_reg_flt(s2, src, REG_FTMP2);
1936 gen_nullptr_check(s1);
1939 default: panic ("internal error");
1943 case ICMD_GETFIELD: /* ... ==> ..., value */
1944 /* op1 = type, val.i = field offset */
1946 a = ((fieldinfo *)(iptr->val.a))->offset;
1947 switch (iptr->op1) {
1949 var_to_reg_int(s1, src, REG_ITMP1);
1950 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1951 gen_nullptr_check(s1);
1953 store_reg_to_var_int(iptr->dst, d);
1956 var_to_reg_int(s1, src, REG_ITMP1);
1957 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1958 gen_nullptr_check(s1);
1960 M_ILD(rd->secondregs[d], s1, a+4);
1961 store_reg_to_var_int(iptr->dst, d);
1964 var_to_reg_int(s1, src, REG_ITMP1);
1965 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
1966 gen_nullptr_check(s1);
1968 store_reg_to_var_int(iptr->dst, d);
1971 var_to_reg_int(s1, src, REG_ITMP1);
1972 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1973 gen_nullptr_check(s1);
1975 store_reg_to_var_flt(iptr->dst, d);
1978 var_to_reg_int(s1, src, REG_ITMP1);
1979 d = reg_of_var(rd, iptr->dst, REG_FTMP1);
1980 gen_nullptr_check(s1);
1982 store_reg_to_var_flt(iptr->dst, d);
1984 default: panic ("internal error");
1989 /* branch operations **************************************************/
1991 case ICMD_ATHROW: /* ..., objectref ==> ... (, objectref) */
1993 a = dseg_addaddress(cd, asm_handle_exception);
1994 M_ALD(REG_ITMP2, REG_PV, a);
1996 var_to_reg_int(s1, src, REG_ITMP1);
1997 M_INTMOVE(s1, REG_ITMP1_XPTR);
1999 if (m->isleafmethod) M_MFLR(REG_ITMP3); /* save LR */
2000 M_BL(0); /* get current PC */
2001 M_MFLR(REG_ITMP2_XPC);
2002 if (m->isleafmethod) M_MTLR(REG_ITMP3); /* restore LR */
2003 M_RTS; /* jump to CTR */
2008 case ICMD_GOTO: /* ... ==> ... */
2009 /* op1 = target JavaVM pc */
2011 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2015 case ICMD_JSR: /* ... ==> ... */
2016 /* op1 = target JavaVM pc */
2018 if (m->isleafmethod) M_MFLR(REG_ITMP2);
2021 M_IADD_IMM(REG_ITMP1, m->isleafmethod ? 16 : 12, REG_ITMP1);
2022 if (m->isleafmethod) M_MTLR(REG_ITMP2);
2024 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2027 case ICMD_RET: /* ... ==> ... */
2028 /* op1 = local variable */
2030 var = &(rd->locals[iptr->op1][TYPE_ADR]);
2031 if (var->flags & INMEMORY) {
2032 M_ALD(REG_ITMP1, REG_SP, 4 * var->regoff);
2036 M_MTCTR(var->regoff);
2041 case ICMD_IFNULL: /* ..., value ==> ... */
2042 /* op1 = target JavaVM pc */
2044 var_to_reg_int(s1, src, REG_ITMP1);
2047 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2050 case ICMD_IFNONNULL: /* ..., value ==> ... */
2051 /* op1 = target JavaVM pc */
2053 var_to_reg_int(s1, src, REG_ITMP1);
2056 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2064 case ICMD_IFEQ: /* ..., value ==> ... */
2065 /* op1 = target JavaVM pc, val.i = constant */
2067 var_to_reg_int(s1, src, REG_ITMP1);
2068 if ((iptr->val.i >= -32768) && (iptr->val.i <= 32767)) {
2069 M_CMPI(s1, iptr->val.i);
2072 ICONST(REG_ITMP2, iptr->val.i);
2073 M_CMP(s1, REG_ITMP2);
2096 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2100 case ICMD_IF_LEQ: /* ..., value ==> ... */
2101 /* op1 = target JavaVM pc, val.l = constant */
2103 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2104 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2105 if (iptr->val.l == 0) {
2106 M_OR(s1, s2, REG_ITMP3);
2107 M_CMPI(REG_ITMP3, 0);
2109 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2110 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2112 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2115 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2116 M_CMP(s2, REG_ITMP3);
2118 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2119 M_CMP(s1, REG_ITMP3)
2122 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2125 case ICMD_IF_LLT: /* ..., value ==> ... */
2126 /* op1 = target JavaVM pc, val.l = constant */
2127 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2128 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2129 /* if (iptr->val.l == 0) { */
2130 /* M_OR(s1, s2, REG_ITMP3); */
2131 /* M_CMPI(REG_ITMP3, 0); */
2134 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2135 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2137 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2139 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2142 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2143 M_CMP(s2, REG_ITMP3);
2145 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2147 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2148 M_CMP(s1, REG_ITMP3)
2151 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2154 case ICMD_IF_LLE: /* ..., value ==> ... */
2155 /* op1 = target JavaVM pc, val.l = constant */
2157 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2158 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2159 /* if (iptr->val.l == 0) { */
2160 /* M_OR(s1, s2, REG_ITMP3); */
2161 /* M_CMPI(REG_ITMP3, 0); */
2164 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2165 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2167 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2169 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2172 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2173 M_CMP(s2, REG_ITMP3);
2175 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2177 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2178 M_CMP(s1, REG_ITMP3)
2181 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2184 case ICMD_IF_LNE: /* ..., value ==> ... */
2185 /* op1 = target JavaVM pc, val.l = constant */
2187 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2188 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2189 if (iptr->val.l == 0) {
2190 M_OR(s1, s2, REG_ITMP3);
2191 M_CMPI(REG_ITMP3, 0);
2193 } else if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2194 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2196 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2199 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2200 M_CMP(s2, REG_ITMP3);
2202 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2203 M_CMP(s1, REG_ITMP3)
2206 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2209 case ICMD_IF_LGT: /* ..., value ==> ... */
2210 /* op1 = target JavaVM pc, val.l = constant */
2212 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2213 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2214 /* if (iptr->val.l == 0) { */
2215 /* M_OR(s1, s2, REG_ITMP3); */
2216 /* M_CMPI(REG_ITMP3, 0); */
2219 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2220 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2222 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2224 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2227 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2228 M_CMP(s2, REG_ITMP3);
2230 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2232 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2233 M_CMP(s1, REG_ITMP3)
2236 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2239 case ICMD_IF_LGE: /* ..., value ==> ... */
2240 /* op1 = target JavaVM pc, val.l = constant */
2241 var_to_reg_int0(s1, src, REG_ITMP1, 0, 1);
2242 var_to_reg_int0(s2, src, REG_ITMP2, 1, 0);
2243 /* if (iptr->val.l == 0) { */
2244 /* M_OR(s1, s2, REG_ITMP3); */
2245 /* M_CMPI(REG_ITMP3, 0); */
2248 if ((iptr->val.l >= -32768) && (iptr->val.l <= 32767)) {
2249 M_CMPI(s2, (u4) (iptr->val.l >> 32));
2251 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2253 M_CMPI(s1, (u4) (iptr->val.l & 0xffffffff));
2256 ICONST(REG_ITMP3, (u4) (iptr->val.l >> 32));
2257 M_CMP(s2, REG_ITMP3);
2259 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2261 ICONST(REG_ITMP3, (u4) (iptr->val.l & 0xffffffff));
2262 M_CMP(s1, REG_ITMP3)
2265 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2269 case ICMD_IF_ICMPEQ: /* ..., value, value ==> ... */
2270 case ICMD_IF_LCMPEQ: /* op1 = target JavaVM pc */
2271 case ICMD_IF_ACMPEQ:
2273 var_to_reg_int(s1, src->prev, REG_ITMP1);
2274 var_to_reg_int(s2, src, REG_ITMP2);
2277 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2280 case ICMD_IF_ICMPNE: /* ..., value, value ==> ... */
2281 case ICMD_IF_LCMPNE: /* op1 = target JavaVM pc */
2282 case ICMD_IF_ACMPNE:
2284 var_to_reg_int(s1, src->prev, REG_ITMP1);
2285 var_to_reg_int(s2, src, REG_ITMP2);
2288 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2291 case ICMD_IF_ICMPLT: /* ..., value, value ==> ... */
2292 case ICMD_IF_LCMPLT: /* op1 = target JavaVM pc */
2294 var_to_reg_int(s1, src->prev, REG_ITMP1);
2295 var_to_reg_int(s2, src, REG_ITMP2);
2298 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2301 case ICMD_IF_ICMPGT: /* ..., value, value ==> ... */
2302 case ICMD_IF_LCMPGT: /* op1 = target JavaVM pc */
2304 var_to_reg_int(s1, src->prev, REG_ITMP1);
2305 var_to_reg_int(s2, src, REG_ITMP2);
2308 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2311 case ICMD_IF_ICMPLE: /* ..., value, value ==> ... */
2312 case ICMD_IF_LCMPLE: /* op1 = target JavaVM pc */
2314 var_to_reg_int(s1, src->prev, REG_ITMP1);
2315 var_to_reg_int(s2, src, REG_ITMP2);
2318 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2321 case ICMD_IF_ICMPGE: /* ..., value, value ==> ... */
2322 case ICMD_IF_LCMPGE: /* op1 = target JavaVM pc */
2324 var_to_reg_int(s1, src->prev, REG_ITMP1);
2325 var_to_reg_int(s2, src, REG_ITMP2);
2328 codegen_addreference(cd, BlockPtrOfPC(iptr->op1), mcodeptr);
2331 case ICMD_IRETURN: /* ..., retvalue ==> ... */
2335 case ICMD_FRETURN: /* ..., retvalue ==> ... */
2338 case ICMD_RETURN: /* ... ==> ... */
2340 #if defined(USE_THREADS)
2341 if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
2342 a = dseg_addaddress(cd, (void *) (builtin_monitorexit));
2343 M_ALD(REG_ITMP3, REG_PV, a);
2345 M_ALD(rd->argintregs[0], REG_SP, rd->maxmemuse * 4);
2349 switch (iptr->opc) {
2353 var_to_reg_int(s1, src, REG_RESULT);
2354 M_TINTMOVE(src->type, s1, REG_RESULT);
2355 goto nowperformreturn;
2359 var_to_reg_flt(s1, src, REG_FRESULT);
2360 M_FLTMOVE(s1, REG_FRESULT);
2361 goto nowperformreturn;
2368 p = parentargs_base;
2370 /* restore return address */
2372 if (!m->isleafmethod) {
2373 M_ALD(REG_ITMP3, REG_SP, 4 * p + 8);
2377 /* restore saved registers */
2379 for (i = rd->savintregcnt - 1; i >= rd->maxsavintreguse; i--) {
2380 p--; M_ILD(rd->savintregs[i], REG_SP, 4 * p);
2382 for (i = rd->savfltregcnt - 1; i >= rd->maxsavfltreguse; i--) {
2383 p -= 2; M_DLD(rd->savfltregs[i], REG_SP, 4 * p);
2386 /* deallocate stack */
2388 if (parentargs_base) {
2389 M_LDA(REG_SP, REG_SP, parentargs_base*4);
2392 /* call trace function */
2396 M_LDA(REG_SP, REG_SP, -10 * 8);
2397 M_DST(REG_FRESULT, REG_SP, 48+0);
2398 M_IST(REG_RESULT, REG_SP, 48+8);
2399 M_AST(REG_ITMP3, REG_SP, 48+12);
2400 M_IST(REG_RESULT2, REG_SP, 48+16);
2401 a = dseg_addaddress(cd, m);
2403 /* keep this order */
2404 switch (iptr->opc) {
2407 M_MOV(REG_RESULT, rd->argintregs[2]);
2408 M_CLR(rd->argintregs[1]);
2412 M_MOV(REG_RESULT2, rd->argintregs[2]);
2413 M_MOV(REG_RESULT, rd->argintregs[1]);
2416 M_ALD(rd->argintregs[0], REG_PV, a);
2418 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
2419 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
2420 a = dseg_addaddress(cd, (void *) builtin_displaymethodstop);
2421 M_ALD(REG_ITMP2, REG_PV, a);
2424 M_DLD(REG_FRESULT, REG_SP, 48+0);
2425 M_ILD(REG_RESULT, REG_SP, 48+8);
2426 M_ALD(REG_ITMP3, REG_SP, 48+12);
2427 M_ILD(REG_RESULT2, REG_SP, 48+16);
2428 M_LDA(REG_SP, REG_SP, 10 * 8);
2438 case ICMD_TABLESWITCH: /* ..., index ==> ... */
2443 tptr = (void **) iptr->target;
2445 s4ptr = iptr->val.a;
2446 l = s4ptr[1]; /* low */
2447 i = s4ptr[2]; /* high */
2449 var_to_reg_int(s1, src, REG_ITMP1);
2451 M_INTMOVE(s1, REG_ITMP1);
2452 } else if (l <= 32768) {
2453 M_LDA(REG_ITMP1, s1, -l);
2455 ICONST(REG_ITMP2, l);
2456 M_ISUB(s1, REG_ITMP2, REG_ITMP1);
2462 M_CMPUI(REG_ITMP1, i - 1);
2465 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[0]), mcodeptr); */
2466 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2468 /* build jump table top down and use address of lowest entry */
2470 /* s4ptr += 3 + i; */
2474 /* dseg_addtarget(cd, BlockPtrOfPC(*--s4ptr)); */
2475 dseg_addtarget(cd, (basicblock *) tptr[0]);
2480 /* length of dataseg after last dseg_addtarget is used by load */
2482 M_SLL_IMM(REG_ITMP1, 2, REG_ITMP1);
2483 M_IADD(REG_ITMP1, REG_PV, REG_ITMP2);
2484 M_ALD(REG_ITMP2, REG_ITMP2, -(cd->dseglen));
2491 case ICMD_LOOKUPSWITCH: /* ..., key ==> ... */
2493 s4 i, l, val, *s4ptr;
2496 tptr = (void **) iptr->target;
2498 s4ptr = iptr->val.a;
2499 l = s4ptr[0]; /* default */
2500 i = s4ptr[1]; /* count */
2502 MCODECHECK((i<<2)+8);
2503 var_to_reg_int(s1, src, REG_ITMP1);
2509 if ((val >= -32768) && (val <= 32767)) {
2513 a = dseg_adds4(cd, val);
2514 M_ILD(REG_ITMP2, REG_PV, a);
2515 M_CMP(s1, REG_ITMP2);
2518 /* codegen_addreference(cd, BlockPtrOfPC(s4ptr[1]), mcodeptr); */
2519 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2523 /* codegen_addreference(cd, BlockPtrOfPC(l), mcodeptr); */
2525 tptr = (void **) iptr->target;
2526 codegen_addreference(cd, (basicblock *) tptr[0], mcodeptr);
2533 case ICMD_BUILTIN3: /* ..., arg1, arg2, arg3 ==> ... */
2534 /* op1 = return type, val.a = function pointer*/
2538 case ICMD_BUILTIN2: /* ..., arg1, arg2 ==> ... */
2539 /* op1 = return type, val.a = function pointer*/
2543 case ICMD_BUILTIN1: /* ..., arg1 ==> ... */
2544 /* op1 = return type, val.a = function pointer*/
2548 case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ... */
2549 /* op1 = arg count, val.a = method pointer */
2551 case ICMD_INVOKESPECIAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2552 /* op1 = arg count, val.a = method pointer */
2554 case ICMD_INVOKEVIRTUAL:/* ..., objectref, [arg1, [arg2 ...]] ==> ... */
2555 /* op1 = arg count, val.a = method pointer */
2557 case ICMD_INVOKEINTERFACE:/*.., objectref, [arg1, [arg2 ...]] ==> ... */
2558 /* op1 = arg count, val.a = method pointer */
2566 MCODECHECK((s3 << 1) + 64);
2569 /* copy arguments to registers or stack location */
2571 stackptr srcsave = src;
2575 for (; --s3 >= 0; src = src->prev) {
2576 argsize += IS_2_WORD_TYPE(src->type) ? 2 : 1;
2577 if (IS_FLT_DBL_TYPE(src->type))
2581 for (s3 = s3save, src = srcsave; --s3 >= 0; src = src->prev) {
2582 argsize -= IS_2_WORD_TYPE(src->type) ? 2 : 1;
2583 if (IS_FLT_DBL_TYPE(src->type))
2585 if (src->varkind == ARGVAR)
2587 if (IS_INT_LNG_TYPE(src->type)) {
2588 if (argsize < INT_ARG_CNT) {
2589 s1 = rd->argintregs[argsize];
2590 var_to_reg_int(d, src, s1);
2591 if (argsize < INT_ARG_CNT-1) {
2592 M_TINTMOVE(src->type, d, s1);
2596 if (IS_2_WORD_TYPE(src->type))
2597 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2601 var_to_reg_int(d, src, REG_ITMP1);
2602 M_IST(d, REG_SP, 4 * (argsize + 6));
2603 if (IS_2_WORD_TYPE(src->type))
2604 M_IST(rd->secondregs[d], REG_SP, 4 * (argsize + 6) + 4);
2608 if (fltcnt < FLT_ARG_CNT) {
2609 s1 = rd->argfltregs[fltcnt];
2610 var_to_reg_flt(d, src, s1);
2614 var_to_reg_flt(d, src, REG_FTMP1);
2615 if (IS_2_WORD_TYPE(src->type))
2616 M_DST(d, REG_SP, 4 * (argsize + 6));
2618 M_FST(d, REG_SP, 4 * (argsize + 6));
2625 switch (iptr->opc) {
2629 a = dseg_addaddress(cd, (void *) lm);
2631 M_ALD(REG_PV, REG_PV, a); /* Pointer to built-in-function */
2633 goto makeactualcall;
2635 case ICMD_INVOKESTATIC:
2636 case ICMD_INVOKESPECIAL:
2637 a = dseg_addaddress(cd, lm->stubroutine);
2639 M_ALD(REG_PV, REG_PV, a); /* method pointer in r27 */
2642 goto makeactualcall;
2644 case ICMD_INVOKEVIRTUAL:
2646 gen_nullptr_check(rd->argintregs[0]);
2647 M_ALD(REG_METHODPTR, rd->argintregs[0],
2648 OFFSET(java_objectheader, vftbl));
2649 M_ALD(REG_PV, REG_METHODPTR, OFFSET(vftbl_t, table[0]) +
2650 sizeof(methodptr) * lm->vftblindex);
2653 goto makeactualcall;
2655 case ICMD_INVOKEINTERFACE:
2658 gen_nullptr_check(rd->argintregs[0]);
2659 M_ALD(REG_METHODPTR, rd->argintregs[0],
2660 OFFSET(java_objectheader, vftbl));
2661 M_ALD(REG_METHODPTR, REG_METHODPTR,
2662 OFFSET(vftbl_t, interfacetable[0]) -
2663 sizeof(methodptr*) * ci->index);
2664 M_ALD(REG_PV, REG_METHODPTR,
2665 sizeof(methodptr) * (lm - ci->methods));
2668 goto makeactualcall;
2672 error ("Unkown ICMD-Command: %d", iptr->opc);
2681 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2683 if (s1 <= 32768) M_LDA(REG_PV, REG_ITMP1, -s1);
2685 s4 ml = -s1, mh = 0;
2686 while (ml < -32768) { ml += 65536; mh--; }
2687 M_LDA(REG_PV, REG_ITMP1, ml);
2688 M_LDAH(REG_PV, REG_PV, mh);
2691 /* d contains return type */
2693 if (d != TYPE_VOID) {
2694 if (IS_INT_LNG_TYPE(iptr->dst->type)) {
2695 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2696 M_TINTMOVE(iptr->dst->type, REG_RESULT, s1);
2697 store_reg_to_var_int(iptr->dst, s1);
2700 s1 = reg_of_var(rd, iptr->dst, REG_FRESULT);
2701 M_FLTMOVE(REG_FRESULT, s1);
2702 store_reg_to_var_flt(iptr->dst, s1);
2709 case ICMD_INSTANCEOF: /* ..., objectref ==> ..., intresult */
2711 /* op1: 0 == array, 1 == class */
2712 /* val.a: (classinfo*) superclass */
2714 /* superclass is an interface:
2716 * return (sub != NULL) &&
2717 * (sub->vftbl->interfacetablelength > super->index) &&
2718 * (sub->vftbl->interfacetable[-super->index] != NULL);
2720 * superclass is a class:
2722 * return ((sub != NULL) && (0
2723 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2724 * super->vftbl->diffvall));
2728 classinfo *super = (classinfo*) iptr->val.a;
2730 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2731 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2733 var_to_reg_int(s1, src, REG_ITMP1);
2734 d = reg_of_var(rd, iptr->dst, REG_ITMP3);
2736 M_MOV(s1, REG_ITMP1);
2740 if (iptr->op1) { /* class/interface */
2742 if (super->flags & ACC_INTERFACE) { /* interface */
2744 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2745 M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, interfacetablelength));
2746 M_LDATST(REG_ITMP2, REG_ITMP2, - super->index);
2748 M_ALD(REG_ITMP1, REG_ITMP1,
2749 OFFSET(vftbl_t, interfacetable[0]) -
2750 super->index * sizeof(methodptr*));
2754 M_IADD_IMM(REG_ZERO, 1, d);
2758 M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
2759 a = dseg_addaddress(cd, (void*) super->vftbl);
2760 M_ALD(REG_ITMP2, REG_PV, a);
2761 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2762 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2764 M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
2765 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2766 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2767 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2768 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2770 M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
2771 M_CMPU(REG_ITMP1, REG_ITMP2);
2774 M_IADD_IMM(REG_ZERO, 1, d);
2778 panic ("internal error: no inlined array instanceof");
2780 store_reg_to_var_int(iptr->dst, d);
2783 case ICMD_CHECKCAST: /* ..., objectref ==> ..., objectref */
2785 /* op1: 0 == array, 1 == class */
2786 /* val.a: (classinfo*) superclass */
2788 /* superclass is an interface:
2790 * OK if ((sub == NULL) ||
2791 * (sub->vftbl->interfacetablelength > super->index) &&
2792 * (sub->vftbl->interfacetable[-super->index] != NULL));
2794 * superclass is a class:
2796 * OK if ((sub == NULL) || (0
2797 * <= (sub->vftbl->baseval - super->vftbl->baseval) <=
2798 * super->vftbl->diffvall));
2802 classinfo *super = (classinfo*) iptr->val.a;
2804 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2805 codegen_threadcritrestart(cd, (u1*) mcodeptr - cd->mcodebase);
2807 d = reg_of_var(rd, iptr->dst, REG_ITMP1);
2808 var_to_reg_int(s1, src, d);
2809 if (iptr->op1) { /* class/interface */
2811 if (super->flags & ACC_INTERFACE) { /* interface */
2813 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2814 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, interfacetablelength));
2815 M_LDATST(REG_ITMP3, REG_ITMP3, - super->index);
2817 codegen_addxcastrefs(cd, mcodeptr);
2818 M_ALD(REG_ITMP3, REG_ITMP2,
2819 OFFSET(vftbl_t, interfacetable[0]) -
2820 super->index * sizeof(methodptr*));
2823 codegen_addxcastrefs(cd, mcodeptr);
2826 M_BEQ(8 + (s1 == REG_ITMP1));
2827 M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
2828 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2829 codegen_threadcritstart(cd, (u1*) mcodeptr - cd->mcodebase);
2831 M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
2832 a = dseg_addaddress(cd, (void*) super->vftbl);
2833 M_ALD(REG_ITMP2, REG_PV, a);
2834 if (d != REG_ITMP1) {
2835 M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
2836 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2837 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2838 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2840 M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
2843 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
2844 M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
2845 M_ALD(REG_ITMP2, REG_PV, a);
2846 M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
2847 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
2848 codegen_threadcritstop(cd, (u1*) mcodeptr - cd->mcodebase);
2851 M_CMPU(REG_ITMP3, REG_ITMP2);
2853 codegen_addxcastrefs(cd, mcodeptr);
2857 panic ("internal error: no inlined array checkcast");
2860 store_reg_to_var_int(iptr->dst, d);
2863 case ICMD_CHECKASIZE: /* ..., size ==> ..., size */
2865 var_to_reg_int(s1, src, REG_ITMP1);
2868 codegen_addxcheckarefs(cd, mcodeptr);
2871 case ICMD_CHECKEXCEPTION: /* ... ==> ... */
2873 M_CMPI(REG_RESULT, 0);
2875 codegen_addxexceptionrefs(cd, mcodeptr);
2878 case ICMD_MULTIANEWARRAY:/* ..., cnt1, [cnt2, ...] ==> ..., arrayref */
2879 /* op1 = dimension, val.a = array descriptor */
2881 /* check for negative sizes and copy sizes to stack if necessary */
2883 MCODECHECK((iptr->op1 << 1) + 64);
2885 for (s1 = iptr->op1; --s1 >= 0; src = src->prev) {
2886 var_to_reg_int(s2, src, REG_ITMP1);
2889 codegen_addxcheckarefs(cd, mcodeptr);
2891 /* copy sizes to stack (argument numbers >= INT_ARG_CNT) */
2893 if (src->varkind != ARGVAR) {
2894 M_IST(s2, REG_SP, 4 * (s1 + INT_ARG_CNT + 6));
2898 /* a0 = dimension count */
2900 ICONST(rd->argintregs[0], iptr->op1);
2902 /* a1 = arraydescriptor */
2904 a = dseg_addaddress(cd, iptr->val.a);
2905 M_ALD(rd->argintregs[1], REG_PV, a);
2907 /* a2 = pointer to dimensions = stack pointer */
2909 M_LDA(rd->argintregs[2], REG_SP, (INT_ARG_CNT + 6)*4);
2911 a = dseg_addaddress(cd, (void *) builtin_nmultianewarray);
2912 M_ALD(REG_PV, REG_PV, a);
2915 s1 = (s4) ((u1 *) mcodeptr - cd->mcodebase);
2918 M_LDA (REG_PV, REG_ITMP1, -s1);
2920 s4 ml = -s1, mh = 0;
2921 while (ml < -32768) {ml += 65536; mh--;}
2922 M_LDA(REG_PV, REG_ITMP1, ml);
2923 M_LDAH(REG_PV, REG_PV, mh);
2925 s1 = reg_of_var(rd, iptr->dst, REG_RESULT);
2926 M_INTMOVE(REG_RESULT, s1);
2927 store_reg_to_var_int(iptr->dst, s1);
2931 default: error ("Unknown pseudo command: %d", iptr->opc);
2935 } /* for instruction */
2937 /* copy values to interface registers */
2939 src = bptr->outstack;
2940 len = bptr->outdepth;
2941 MCODECHECK(64 + len);
2944 if ((src->varkind != STACKVAR)) {
2946 if (IS_FLT_DBL_TYPE(s2)) {
2947 var_to_reg_flt(s1, src, REG_FTMP1);
2948 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
2949 M_FLTMOVE(s1, rd->interfaces[len][s2].regoff);
2952 M_DST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
2956 var_to_reg_int(s1, src, REG_ITMP1);
2957 if (!(rd->interfaces[len][s2].flags & INMEMORY)) {
2958 M_TINTMOVE(s2, s1, rd->interfaces[len][s2].regoff);
2961 M_IST(s1, REG_SP, rd->interfaces[len][s2].regoff * 4);
2962 if (IS_2_WORD_TYPE(s2))
2963 M_IST(rd->secondregs[s1], REG_SP, rd->interfaces[len][s2].regoff * 4 + 4);
2969 } /* if (bptr -> flags >= BBREACHED) */
2970 } /* for basic block */
2972 /* bptr -> mpc = (int)((u1*) mcodeptr - mcodebase); */
2975 /* generate bound check stubs */
2977 s4 *xcodeptr = NULL;
2980 for (bref = cd->xboundrefs; bref != NULL; bref = bref->next) {
2981 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
2983 (u1 *) mcodeptr - cd->mcodebase);
2987 /* move index register into REG_ITMP1 */
2988 M_MOV(bref->reg, REG_ITMP1);
2989 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
2991 if (xcodeptr != NULL) {
2992 M_BR(xcodeptr - mcodeptr - 1);
2995 xcodeptr = mcodeptr;
2997 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
2998 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3000 M_MOV(REG_ITMP1, rd->argintregs[0]);
3002 a = dseg_addaddress(cd, new_arrayindexoutofboundsexception);
3003 M_ALD(REG_ITMP2, REG_PV, a);
3006 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3008 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3009 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3011 a = dseg_addaddress(cd, asm_handle_exception);
3012 M_ALD(REG_ITMP3, REG_PV, a);
3019 /* generate negative array size check stubs */
3023 for (bref = cd->xcheckarefs; bref != NULL; bref = bref->next) {
3024 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3025 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3027 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3031 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3033 (u1 *) mcodeptr - cd->mcodebase);
3037 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3039 if (xcodeptr != NULL) {
3040 M_BR(xcodeptr - mcodeptr - 1);
3043 xcodeptr = mcodeptr;
3045 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3046 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3048 a = dseg_addaddress(cd, new_negativearraysizeexception);
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, new_classcastexception);
3095 M_ALD(REG_ITMP2, REG_PV, a);
3098 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3100 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3101 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3103 a = dseg_addaddress(cd, asm_handle_exception);
3104 M_ALD(REG_ITMP3, REG_PV, a);
3111 /* generate exception check stubs */
3115 for (bref = cd->xexceptionrefs; bref != NULL; bref = bref->next) {
3116 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3117 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3119 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3123 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3125 (u1 *) mcodeptr - cd->mcodebase);
3129 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3131 if (xcodeptr != NULL) {
3132 M_BR(xcodeptr - mcodeptr - 1);
3135 xcodeptr = mcodeptr;
3137 /* XXX this cannot work - there is no link area */
3138 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3139 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3141 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3142 a = dseg_addaddress(cd, builtin_get_exceptionptrptr);
3143 M_ALD(REG_ITMP2, REG_PV, a);
3147 /* get the exceptionptr from the ptrprt and clear it */
3148 M_ALD(REG_ITMP1_XPTR, REG_RESULT, 0);
3150 M_AST(REG_ITMP3, REG_RESULT, 0);
3152 a = dseg_addaddress(cd, &_exceptionptr);
3153 M_ALD(REG_ITMP2, REG_PV, a);
3155 M_ALD(REG_ITMP1_XPTR, REG_ITMP2, 0);
3157 M_AST(REG_ITMP3, REG_ITMP2, 0);
3160 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3161 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3163 a = dseg_addaddress(cd, asm_handle_exception);
3164 M_ALD(REG_ITMP3, REG_PV, a);
3170 /* generate null pointer check stubs */
3174 for (bref = cd->xnullrefs; bref != NULL; bref = bref->next) {
3175 if ((m->exceptiontablelength == 0) && (xcodeptr != NULL)) {
3176 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3178 (u1 *) xcodeptr - (u1 *) cd->mcodebase - 4);
3182 gen_resolvebranch((u1 *) cd->mcodebase + bref->branchpos,
3184 (u1 *) mcodeptr - cd->mcodebase);
3188 M_LDA(REG_ITMP2_XPC, REG_PV, bref->branchpos - 4);
3190 if (xcodeptr != NULL) {
3191 M_BR(xcodeptr - mcodeptr - 1);
3194 xcodeptr = mcodeptr;
3196 M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
3197 M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
3199 a = dseg_addaddress(cd, new_nullpointerexception);
3200 M_ALD(REG_ITMP2, REG_PV, a);
3203 M_MOV(REG_RESULT, REG_ITMP1_XPTR);
3205 M_ILD(REG_ITMP2_XPC, REG_SP, 0 * 8);
3206 M_IADD_IMM(REG_SP, 1 * 8, REG_SP);
3208 a = dseg_addaddress(cd, asm_handle_exception);
3209 M_ALD(REG_ITMP3, REG_PV, a);
3216 codegen_finish(m, cd, (s4) ((u1 *) mcodeptr - cd->mcodebase));
3218 asm_cacheflush((void *) m->entrypoint, ((u1 *) mcodeptr - cd->mcodebase));
3222 /* function createcompilerstub *************************************************
3224 creates a stub routine which calls the compiler
3226 *******************************************************************************/
3228 #define COMPSTUBSIZE 6
3230 u1 *createcompilerstub(methodinfo *m)
3232 s4 *s = CNEW (s4, COMPSTUBSIZE); /* memory to hold the stub */
3233 s4 *mcodeptr = s; /* code generation pointer */
3235 M_LDA(2, REG_PV, 4*4);
3236 M_ALD(REG_PV, REG_PV, 5*4);
3240 s[4] = (s4) m; /* literals to be adressed */
3241 s[5] = (s4) asm_call_jit_compiler; /* jump directly via PV from above */
3243 asm_cacheflush((void*) s, (u1*) mcodeptr - (u1*) s);
3245 #if defined(STATISTICS)
3247 count_cstub_len += COMPSTUBSIZE * 4;
3254 /* function removecompilerstub *************************************************
3256 deletes a compilerstub from memory (simply by freeing it)
3258 *******************************************************************************/
3260 void removecompilerstub(u1 *stub)
3262 CFREE(stub, COMPSTUBSIZE * 4);
3266 /* function: createnativestub **************************************************
3268 creates a stub routine which calls a native method
3270 *******************************************************************************/
3272 #define NATIVESTUBSIZE 200
3273 #define NATIVESTUBOFFSET 9
3275 u1 *createnativestub(functionptr f, methodinfo *m)
3277 s4 *s; /* memory to hold the stub */
3279 s4 *mcodeptr; /* code generation pointer */
3280 s4 stackframesize = 0; /* size of stackframe if needed */
3283 t_inlining_globals *id;
3286 /* mark start of dump memory area */
3288 dumpsize = dump_size();
3290 /* setup registers before using it */
3292 rd = DNEW(registerdata);
3293 id = DNEW(t_inlining_globals);
3295 inlining_setup(m, id);
3296 reg_setup(m, rd, id);
3298 descriptor2types(m); /* set paramcount and paramtypes */
3300 s = CNEW(s4, NATIVESTUBSIZE);
3301 cs = s + NATIVESTUBOFFSET;
3304 *(cs-1) = (u4) f; /* address of native method */
3305 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3306 *(cs-2) = (u4) builtin_get_exceptionptrptr;
3308 *(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
3310 *(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
3311 *(cs-4) = (u4) (&env); /* addr of jni_environement */
3312 *(cs-5) = (u4) builtin_trace_args;
3314 *(cs-7) = (u4) builtin_displaymethodstop;
3315 *(cs-8) = (u4) m->class;
3316 *(cs-9) = (u4) asm_check_clinit;
3319 M_AST(REG_ITMP1, REG_SP, 8); /* store return address */
3320 M_LDA(REG_SP, REG_SP, -64); /* build up stackframe */
3322 /* if function is static, check for initialized */
3324 if (m->flags & ACC_STATIC) {
3325 /* if class isn't yet initialized, do it */
3326 if (!m->class->initialized) {
3327 /* call helper function which patches this code */
3328 M_ALD(REG_ITMP1, REG_PV, -8 * 4); /* class */
3329 M_ALD(REG_PV, REG_PV, -9 * 4); /* asm_check_clinit */
3332 disp = -(s4) (mcodeptr - cs) * 4;
3334 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3344 /* M_MFLR(REG_ITMP3); */
3345 /* XXX must be a multiple of 16 */
3346 M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
3348 /* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3352 /* save all arguments into the reserved stack space */
3353 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3354 t = m->paramtypes[p];
3356 if (IS_INT_LNG_TYPE(t)) {
3357 /* overlapping u8's are on the stack */
3358 if ((p + longargs + dblargs) < (INT_ARG_CNT - IS_2_WORD_TYPE(t))) {
3359 s1 = rd->argintregs[p + longargs + dblargs];
3361 if (!IS_2_WORD_TYPE(t)) {
3362 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3363 M_IST(s1, REG_SP, 24 + p * 8 + 4);
3366 M_IST(s1, REG_SP, 24 + p * 8);
3367 M_IST(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3372 /* we do not have a data segment here */
3373 /* a = dseg_adds4(cd, 0xdeadbeef);
3374 M_ILD(REG_ITMP1, REG_PV, a); */
3375 M_LDA(REG_ITMP1, REG_ZERO, -1);
3376 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3377 M_IST(REG_ITMP1, REG_SP, 24 + p * 8 + 4);
3381 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3382 s1 = rd->argfltregs[fltargs + dblargs];
3384 if (!IS_2_WORD_TYPE(t)) {
3385 M_IST(REG_ITMP1, REG_SP, 24 + p * 8);
3386 M_FST(s1, REG_SP, 24 + p * 8 + 4);
3390 M_DST(s1, REG_SP, 24 + p * 8);
3395 /* this should not happen */
3400 /* TODO: save remaining integer and flaot argument registers */
3402 /* load first 4 arguments into integer argument registers */
3403 for (p = 0; p < 8; p++) {
3404 d = rd->argintregs[p];
3405 M_ILD(d, REG_SP, 24 + p * 4);
3408 M_ALD(REG_ITMP1, REG_PV, -6 * 4);
3409 M_AST(REG_ITMP1, REG_SP, 11 * 8); /* 24 (linkage area) + 32 (4 * s8 parameter area regs) + 32 (4 * s8 parameter area stack) = 88 */
3410 M_ALD(REG_ITMP2, REG_PV, -5 * 4);
3418 /* restore arguments into the reserved stack space */
3419 for (p = 0; p < m->paramcount && p < TRACE_ARGS_NUM; p++) {
3420 t = m->paramtypes[p];
3422 if (IS_INT_LNG_TYPE(t)) {
3423 if ((p + longargs + dblargs) < INT_ARG_CNT) {
3424 s1 = rd->argintregs[p + longargs + dblargs];
3426 if (!IS_2_WORD_TYPE(t)) {
3427 M_ILD(s1, REG_SP, 24 + p * 8 + 4);
3430 M_ILD(s1, REG_SP, 24 + p * 8);
3431 M_ILD(rd->secondregs[s1], REG_SP, 24 + p * 8 + 4);
3437 if ((fltargs + dblargs) < FLT_ARG_CNT) {
3438 s1 = rd->argfltregs[fltargs + dblargs];
3440 if (!IS_2_WORD_TYPE(t)) {
3441 M_FLD(s1, REG_SP, 24 + p * 8 + 4);
3445 M_DLD(s1, REG_SP, 24 + p * 8);
3452 /* M_ILD(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
3454 M_LDA(REG_SP, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8);
3455 /* M_MTLR(REG_ITMP3); */
3458 /* save argument registers on stack -- if we have to */
3459 if ((m->flags & ACC_STATIC && m->paramcount > (INT_ARG_CNT - 2)) ||
3460 m->paramcount > (INT_ARG_CNT - 1)) {
3462 s4 paramshiftcnt = (m->flags & ACC_STATIC) ? 2 : 1;
3463 s4 stackparamcnt = (m->paramcount > INT_ARG_CNT) ? m->paramcount - INT_ARG_CNT : 0;
3465 stackframesize = stackparamcnt + paramshiftcnt;
3467 M_LDA(REG_SP, REG_SP, -stackframesize * 8);
3469 panic("nativestub");
3472 if (m->flags & ACC_STATIC) {
3473 M_MOV(rd->argintregs[5], rd->argintregs[7]);
3474 M_MOV(rd->argintregs[4], rd->argintregs[6]);
3475 M_MOV(rd->argintregs[3], rd->argintregs[5]);
3476 M_MOV(rd->argintregs[2], rd->argintregs[4]);
3477 M_MOV(rd->argintregs[1], rd->argintregs[3]);
3478 M_MOV(rd->argintregs[0], rd->argintregs[2]);
3480 /* put class into second argument register */
3481 M_ALD(rd->argintregs[1], REG_PV, -8 * 4);
3484 M_MOV(rd->argintregs[6], rd->argintregs[7]);
3485 M_MOV(rd->argintregs[5], rd->argintregs[6]);
3486 M_MOV(rd->argintregs[4], rd->argintregs[5]);
3487 M_MOV(rd->argintregs[3], rd->argintregs[4]);
3488 M_MOV(rd->argintregs[2], rd->argintregs[3]);
3489 M_MOV(rd->argintregs[1], rd->argintregs[2]);
3490 M_MOV(rd->argintregs[0], rd->argintregs[1]);
3493 /* put env into first argument register */
3494 M_ALD(rd->argintregs[0], REG_PV, -4 * 4);
3496 M_ALD(REG_PV, REG_PV, -1 * 4); /* load adress of native method */
3499 disp = -(s4) (mcodeptr - cs) * 4;
3501 M_LDA(REG_PV, REG_ITMP1, disp); /* recompute pv from ra */
3503 /* remove stackframe if there is one */
3504 if (stackframesize) {
3505 M_LDA(REG_SP, REG_SP, stackframesize * 8);
3508 /* 20 instructions */
3511 M_LDA(REG_SP, REG_SP, -10 * 8);
3512 M_DST(REG_FRESULT, REG_SP, 48+0);
3513 M_IST(REG_RESULT, REG_SP, 48+8);
3514 M_AST(REG_ITMP3, REG_SP, 48+12);
3515 M_IST(REG_RESULT2, REG_SP, 48+16);
3517 /* keep this order */
3518 switch (m->returntype) {
3521 M_MOV(REG_RESULT, rd->argintregs[2]);
3522 M_CLR(rd->argintregs[1]);
3526 M_MOV(REG_RESULT2, rd->argintregs[2]);
3527 M_MOV(REG_RESULT, rd->argintregs[1]);
3530 M_ALD(rd->argintregs[0], REG_PV, -6 * 4);
3532 M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
3533 M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
3534 M_ALD(REG_ITMP2, REG_PV, -7 * 4);/* builtin_displaymethodstop */
3537 M_DLD(REG_FRESULT, REG_SP, 48+0);
3538 M_ILD(REG_RESULT, REG_SP, 48+8);
3539 M_ALD(REG_ITMP3, REG_SP, 48+12);
3540 M_ILD(REG_RESULT2, REG_SP, 48+16);
3541 M_LDA(REG_SP, REG_SP, 10 * 8);
3545 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
3546 if (IS_FLT_DBL_TYPE(m->returntype))
3547 if (IS_2_WORD_TYPE(m->returntype))
3548 M_DST(REG_FRESULT, REG_SP, 56);
3550 M_FST(REG_FRESULT, REG_SP, 56);
3552 M_IST(REG_RESULT, REG_SP, 56);
3553 if (IS_2_WORD_TYPE(m->returntype))
3554 M_IST(REG_RESULT2, REG_SP, 60);
3557 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
3560 disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
3562 M_LDA(REG_PV, REG_ITMP1, disp);
3563 M_MOV(REG_RESULT, REG_ITMP2);
3565 if (IS_FLT_DBL_TYPE(m->returntype))
3566 if (IS_2_WORD_TYPE(m->returntype))
3567 M_DLD(REG_FRESULT, REG_SP, 56);
3569 M_FLD(REG_FRESULT, REG_SP, 56);
3571 M_ILD(REG_RESULT, REG_SP, 56);
3572 if (IS_2_WORD_TYPE(m->returntype))
3573 M_ILD(REG_RESULT2, REG_SP, 60);
3576 M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
3578 M_ALD(REG_ITMP1, REG_ITMP2, 0); /* load exception into reg. itmp1 */
3580 M_BNE(4); /* if no exception then return */
3582 M_ALD(REG_ITMP1, REG_SP, 64 + 8); /* load return address */
3584 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3589 M_AST(REG_ITMP3, REG_ITMP2, 0); /* store NULL into exceptionptr */
3591 M_ALD(REG_ITMP3, REG_SP, 64 + 8); /* load return address */
3593 M_LDA(REG_SP, REG_SP, 64); /* remove stackframe */
3595 M_LDA(REG_ITMP2, REG_ITMP1, -4); /* move fault address into reg. itmp2 */
3597 M_ALD(REG_ITMP3, REG_PV, -3 * 4); /* load asm exception handler address */
3602 dolog_plain("stubsize: %d (for %d params)\n", (int) (mcodeptr - (s4 *) s), m->paramcount);
3605 asm_cacheflush((void *) s, (u1*) mcodeptr - (u1*) s);
3607 #if defined(STATISTICS)
3609 count_nstub_len += NATIVESTUBSIZE * 4;
3612 /* release dump area */
3614 dump_release(dumpsize);
3616 return (u1*) (s + NATIVESTUBOFFSET);
3620 /* function: removenativestub **************************************************
3622 removes a previously created native-stub from memory
3624 *******************************************************************************/
3626 void removenativestub(u1 *stub)
3628 CFREE((s4 *) stub - NATIVESTUBOFFSET, NATIVESTUBSIZE * 4);
3633 * These are local overrides for various environment variables in Emacs.
3634 * Please do not remove this and leave it at the end of the file, where
3635 * Emacs will automagically detect them.
3636 * ---------------------------------------------------------------------
3639 * indent-tabs-mode: t